From patchwork Tue Aug 9 19:08:27 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 9272087 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id DD29F6075A for ; Tue, 9 Aug 2016 19:09:07 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C79972833A for ; Tue, 9 Aug 2016 19:09:07 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BC2A2283DF; Tue, 9 Aug 2016 19:09:07 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D53882833A for ; Tue, 9 Aug 2016 19:09:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752625AbcHITJC (ORCPT ); Tue, 9 Aug 2016 15:09:02 -0400 Received: from mx0b-00082601.pphosted.com ([67.231.153.30]:36002 "EHLO mx0a-00082601.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752611AbcHITI6 (ORCPT ); Tue, 9 Aug 2016 15:08:58 -0400 Received: from pps.filterd (m0001255.ppops.net [127.0.0.1]) by mx0b-00082601.pphosted.com (8.16.0.11/8.16.0.11) with SMTP id u79J4she003306; Tue, 9 Aug 2016 12:08:49 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=fb.com; h=from : to : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=facebook; bh=a8c68Q9aLULhSPHs4nWPqo8dl6sWmjy+7QjV1C7x4jQ=; b=LWILlyWTXzcwFbXSel4wB4QaapM0xHbtmMXcxg7xS7klRN3AraGnfLnnZkJeDGt3Pr5T SFp85Ommt6k5VjzISVCoaQeqGB3Kf3s+hNkcSnnn6pNJaTPl3lCNMHananPlfvYnP/sL LUhNRx0Nvdo4pfrxwGYBaRT7/cjxospko6w= Received: from maileast.thefacebook.com ([199.201.65.23]) by mx0b-00082601.pphosted.com with ESMTP id 24qebeadge-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT); Tue, 09 Aug 2016 12:08:49 -0700 Received: from NAM01-BN3-obe.outbound.protection.outlook.com (192.168.183.28) by o365-in.thefacebook.com (192.168.177.23) with Microsoft SMTP Server (TLS) id 14.3.294.0; Tue, 9 Aug 2016 15:08:47 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=fb.onmicrosoft.com; s=selector1-fb-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=iZmAxnclWCqaiQPOD6pLfOiHEE1WUKWtEH3HY1eLkfc=; b=ddfOwPVfX+pthrRixRyyZGQb99Oh3voyuLc+e20Ctgfux2xHURiJ038Zy3DjcZjVZIh54M+i2C2QKKu9e3bbdOx5RCubl3GyQjSXGJrA6g518Fes//61V+QvLITdj8SziPu6w4CaPe2VnVzZJ2412sKWWoSm00vsZuOHYc4w+Tc= Received: from localhost (107.15.72.49) by MWHPR15MB1328.namprd15.prod.outlook.com (10.175.3.142) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.549.15; Tue, 9 Aug 2016 19:08:44 +0000 From: Josef Bacik To: , , , , , , Subject: [PATCH 2/2] writeback: allow for dirty metadata accounting Date: Tue, 9 Aug 2016 15:08:27 -0400 Message-ID: <1470769707-26079-3-git-send-email-jbacik@fb.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1470769707-26079-1-git-send-email-jbacik@fb.com> References: <1470769707-26079-1-git-send-email-jbacik@fb.com> MIME-Version: 1.0 X-Originating-IP: [107.15.72.49] X-ClientProxiedBy: BN6PR01CA0069.prod.exchangelabs.com (10.172.194.159) To MWHPR15MB1328.namprd15.prod.outlook.com (10.175.3.142) X-MS-Office365-Filtering-Correlation-Id: 752c14c4-a248-4c4f-4e50-08d3c0889573 X-Microsoft-Exchange-Diagnostics: 1; MWHPR15MB1328; 2:cX0bIh7kHJZcDZrVJTLjUQFFjST+OOhW3Jp89g0HZJ9OIdBCdiwauAq6lMDFp1bUe3BaLTva7Soi3WGwNCZ7X+fWnxhWcXaKbwggLq6eo0Ere5fN3fedOVEy0sMz6Rj7f58wkrXy9l4afB1xQV6p9dO0oD2UKAk53O3ACbE4lZWtcSTik/J/3J6g/70HS2Ff; 3:oOj4ZtRU3taMW80TkJiFQp4a0bYlagTm8H/NzokAH0iWmdJHjOxMPPj+mLwYaFs+H1G0pbHkRBvFuLWaUmyWOO0jedDJIRbQ23sEUsDHKz1A4ebywtt/G1oxoz9hlhEa X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:MWHPR15MB1328; X-Microsoft-Exchange-Diagnostics: 1; MWHPR15MB1328; 25:wKa5xpMWJtmEYIubVWq9kVal1rfPzVZXbVGQYVye2H3G1auQR1gSwrNACCZZ0gh5iYZSasmwHSAVx32hANTvMcQ6uooHGM9PCciOim8vTPnoToP55wRXwoXJZJW13PPClCH/nppiEpMhvza9F5AuzkH5p2bF2tYnpF9HcE7W01vUD9fFzpwa92w7IE0/cdd9ZCmHpbpP2fHdaYKnJHTl5koWNdNMUsm0F4Io7LPBkF5Mny9JsHH2M0YajA9PpGlwYkMa8CMzmuaqF8flhJC2tXqUYNrm0wjOhBokGNxsZ14cgsV05/+deqvytHoPGqF2q9LeoPbfs39d2QqPvab7mI9oKBt94+GkYUF4JqTrc7ftMXfvjefcLenbJIaANvI2UdEHOjKCTDDkQ/w3r/croq9kBOUjEY3v6iSLWtUQRYk0Ihs0q0e9u56NhjdI3gTSWBcabtGxZnBMgU1zdXWdlVRwzCB0E/4O76tgFXxcG0Cr3uok6pyfKO2zoaCM67A4XlqzoZPcTZBL6Dr1/+j1FPBxPfP5NekrxVyKspHWYRfA9IXQ+T0Yh6unG2sK8rowXzp4yxZiThswCHW9nH0pV/v87JAci2qGrhz0QZ1qK9v/xirWUHrzHie9f/vCvkoHziDdL5kYe/v6aHU0+DWNBJTCFmlvNbvdog11YEX4XpLdTGgR9hwvmsg/Mb268f59D9JuHDVqfTZ+uqG/YO4D+tMPV5J8SoSb4pa0PKRZyGxjfpQvvGfnK2Jwhkk25XjI X-LD-Processed: 8ae927fe-1255-47a7-a2af-5f3a069daaa2,ExtAddr X-Microsoft-Exchange-Diagnostics: 1; MWHPR15MB1328; 31:jQsu4kjaR8Cla0cbZYGuURGPddsKNVVcIjImrin0fRsiB0wdWIKNHKgSYVUQVo/S+u0rT9UhSQ4GqHRvDv9WbuWUB7yUk0aPETQ8VL/i4BLI/fJbVLHVu6Q3N8Y6EP/JvJ3Gbv4oV520EjW3Vk+KOa62+0dRPhq5WSLguSPIa8Z1Im9EqezpTJoStX7UIcpYFSsjRuJE2ZLlTuezerwAkeYbDysHW9U3BCIjenQ2USo=; 20:u+POf1TtqGJIPrcrAiuMYjl8SHBzgXkfqO1A/8Lhc/6dw/UarrCi5NxD0bzQ0YHFAtas5kpLzI3ao570LY3Jo5GhyklN/skkPy7539zYt1YmB1U5rWg6vsIvyMDXsR0pzqmGeiEfKllF1BKq1A7Un0Uzs7oAmmRj89rjwBjepM0=; 4:Z4d587tV5kGmoLk/SIUmrmXMc+Q3jZ15aB4fRSUQDdm0iBPXG6jxf8s2T0pmCaEUbibJWxenrqtrqwqxuk659qr7xUzcjNcKn7QN2hlLxBifFviE+hP0HkiFpaXr4nMHYirv1rI9jzMly0IXEQ9qOri8paFVWbSn4G5J1OByctE0W9z2hDYnzNDDhsYgGm3DJGf5dwscO6lo0vVN4s+47+mR3pTlCAS30UWJ7Exv8E4iTmNqWUgkNTvNMyC/Ouq/4nJbvLVEiz6Q7dMQMQwn3rzWsyvGmdL/hbFewICfbL9UuuNFbJkk0ezOPjm4mW9L/rYf0u16d6iM42D68xVPxFDfBl+tpWUHYquLdePEXISvv+VplV/wIwS9EyjOpZoujDUgVXuYBfx9Mdtf2CYkkDySipWsjlfMb4o+i1J5W4o= X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(67672495146484); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(601004)(2401047)(8121501046)(5005006)(3002001)(10201501046); SRVR:MWHPR15MB1328; BCL:0; PCL:0; RULEID:; SRVR:MWHPR15MB1328; X-Forefront-PRVS: 0029F17A3F X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10019020)(4630300001)(6009001)(6069001)(7916002)(189002)(199003)(42186005)(101416001)(19580395003)(19580405001)(50226002)(48376002)(105586002)(50466002)(7736002)(305945005)(68736007)(7846002)(33646002)(229853001)(3846002)(66066001)(81166006)(586003)(77096005)(8676002)(5003940100001)(81156014)(15650500001)(86362001)(36756003)(575784001)(189998001)(5001770100001)(97736004)(107886002)(106356001)(2201001)(76506005)(6116002)(92566002)(76176999)(2950100001)(2906002)(50986999)(47776003)(14143004)(4720700001); DIR:OUT; SFP:1102; SCL:1; SRVR:MWHPR15MB1328; H:localhost; FPR:; SPF:None; PTR:InfoNoRecords; MX:1; A:1; LANG:en; Received-SPF: None (protection.outlook.com: fb.com does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; MWHPR15MB1328; 23:cGiZZOfE3Llku0U27xcmMLeplPmpjTuOH4dwUWagg?= =?us-ascii?Q?fHfZ8Tq2fB8HHXi+Uk6suMmGzVVTVEAUBNzv5+d22C030YKLDT9zghCiJpg2?= =?us-ascii?Q?Vvm57CooVBjGNFPbyXgDbZoHGjGhS3pHCnSU38oeMXFuW1/bKl61R2CstvI6?= =?us-ascii?Q?EuXsbbkdfWNtEs+x4fRlVHlXrwh1GAJfpfv8GLO5VEr87bkkjbamoq8YR0Tk?= =?us-ascii?Q?bz1acxtxf81thDfNJzC1uIIE9FXeN6XD878ovFA2VOdCRLzN94cBm5kSys1j?= =?us-ascii?Q?zW+8Cwo9zXCPAtbcs2J28kvNy1CRE2RkERb/oz/rU6bBJNbCyrxmV+ZJvo68?= =?us-ascii?Q?c8lRqgJ2ZlyJZFtuJWtWFUQNwU3/vr+XtCwO1SbfpJ4U/MApCM+JoayUBPPv?= =?us-ascii?Q?GjX8Nu3N4bjx5tt+gfH+ozU0Dk66Ecm28NFE5W7l+KMYyyFrvuKsIJ2il3MQ?= =?us-ascii?Q?0wfeRMC/N3szd//7BR6C+gN7X0TNdH4UU4Ymq8qFYRkytFw7i049Rle0/L74?= =?us-ascii?Q?5He1C/b55e0NV2eU9lLR1mQCH13UF3ZqZmSY/IDqBAXfwse/we8uLM11F/M/?= =?us-ascii?Q?7s/f70U8ofnPoloydunhfGBCkqjGYt+tt7CRPtNtpAQ1KF8reu6CVe3iZmTC?= =?us-ascii?Q?6a5eRwq7elfw1xh4wTf1a1ovmU3oXnHt518yNdWtoiM7XnT+eGbSowURGDhc?= =?us-ascii?Q?d1lNiudqjhdz9CNOX6+G/2Dns0xvQz7MRY0XmsEi8SyKBTpxi9CGBmyW+oC5?= =?us-ascii?Q?Am47ynQBbSxfz3BkjZ4YiHrSJPQ5YAk6T3WvZUqkB/DPvFBc7fV7D3R7/66r?= =?us-ascii?Q?vQVQ2UqKd9yiR/MALD9z2ksRf4IxYOdk4p3BV9d5yEuBr8k2D9hoO23ySj78?= =?us-ascii?Q?auNuY3KN5mzWljj8PIKq8s+pBtRE7olNAT2JDQwW2XPh8BW4aA5apmSL3uP8?= =?us-ascii?Q?I3Ro0NXfw1eAnYkgE6/bUqVEZZ0mC50ZhTXj9bhix6/9bglC2/UK886iFU95?= =?us-ascii?Q?7/eje73I964LrPuYTV400aXvB9r5vopqCRnsFNFBw290iB5B6qpniWeIysbM?= =?us-ascii?Q?CdoJcVkpKyPg+rtwmNesOKpwFZh3UC0ikzy6C1dUd+zlDYakva56vCu3XYnm?= =?us-ascii?Q?nYxZyJCY0Rtf+vex5UUgb+bK+P/zsw+7+v9zPkTJ6o0fuOf1TnZgeL8wjaxt?= =?us-ascii?Q?jWc9yHHTCrQCHYrneRbVnaq9IC+7R6uLVrpyojdqyAbBSIO9JoRxKmzmQ=3D?= =?us-ascii?Q?=3D?= X-Microsoft-Exchange-Diagnostics: 1; MWHPR15MB1328; 6:KBzGGcqcoBF7xltO8fhmH2JNBileYuIoaKwFp7AgfcAPxhH008wo7/Y/QseiWZlHdntNeJEBVLlUngHNOKTcOEnjGSEdJSoMKFA+0sS69rJ+e/GtWUrODf1+H60OZxlwbv10HJiCXxHaUwFsnyY2FdClgdWDn1j03Fzgq0Omz701vQL9f4skJ9EssyqktB232w/udlaMBOnKQMhq+su+OfFanu1W1P+u99STzt483dO9jY5joYHekJlS6LUGrjwem9QwJy4RTgB17hXzcJtDVD4m+z1nLNql3KAnsMsq4N8=; 5:hroFyRyIj0ms27pfDCzzzxOvlrh2QNchCuvYeb8VKrWpLbZOKiJgVqeSMRYCvh0HYZ+xWdFxBtvOaoFoKeDu5nNuCrOCrmRUvZ6vh9iab3304NjDlIpQ4Mg5d/0oOVJwv8ovD4W0Yg/F05pzt334QQ==; 24:bm1O/0LuZdVLDENxLaDV32fbK06siV+tGfSp3GKi2WAlyO2HXaTq3i7z9iC/btCQ1scaK/WW6iMI+pdWn4wA8q5ugU/ZISt5jNCpgXXIweE=; 7:w9mgMIKbSwyWh3v+Lx+vDY/1WKFzNCX9JqkEorFBr5XZYvmqKBjj3NcOdvFJgfBPeVKGYVZiBPGIr7znHKHT0Mup+628KWHi5nJvCZJ3FhYMBGrxS1SjlKDahNu2f43iTethey5KiwlEdxffBmCJjtysPu4PULDc9rYUyniKYnK4ClBBZuyJsWml7fh3Pb5RQtI/YdoRmiu3S+R9IQEoQ1CCz6DJRNT5c2/t3Cw2pc9Dt5fuYteTX/gix1hUz+gJ SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; MWHPR15MB1328; 20:ed82v0gNvo+eLbYCm7XgLvc/SNZWpMlsUubjPP0ynVEHLFhinwNRJebNzhAYRhxkehyRLXjC6hGKpyI095Y/1QRj3X1EtV6eBO30TICqNcuAB4gVP+jNd9Rs03liTEaoTEH0dIuz1uMMIo+TifOESvzLyB/C5mxZ28wdiQJcb6s= X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Aug 2016 19:08:44.2637 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: MWHPR15MB1328 X-OriginatorOrg: fb.com X-Proofpoint-Spam-Reason: safe X-FB-Internal: Safe X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2016-08-09_07:, , signatures=0 Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Provide a mechanism for file systems to indicate how much dirty metadata they are holding. This introduces a few things 1) Zone stats for dirty metadata, which is the same as the NR_FILE_DIRTY. 2) WB stat for dirty metadata. This way we know if we need to try and call into the file system to write out metadata. This could potentially be used in the future to make balancing of dirty pages smarter. 3) A super callback to handle writing back dirty metadata. A future patch will take advantage of this work in btrfs. Thanks, Signed-off-by: Josef Bacik --- fs/fs-writeback.c | 57 +++++++++++++++++++++++++++-- fs/super.c | 1 + include/linux/backing-dev-defs.h | 3 ++ include/linux/fs.h | 4 +++ include/linux/mm.h | 4 +++ include/linux/mmzone.h | 1 + mm/backing-dev.c | 3 ++ mm/page-writeback.c | 78 ++++++++++++++++++++++++++++++++++++++-- 8 files changed, 145 insertions(+), 6 deletions(-) diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 56c8fda..c670d45 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -1615,11 +1615,36 @@ static long writeback_sb_inodes(struct super_block *sb, return wrote; } +static long writeback_sb_metadata(struct super_block *sb, + struct bdi_writeback *wb, + struct wb_writeback_work *work) +{ + struct writeback_control wbc = { + .sync_mode = work->sync_mode, + .tagged_writepages = work->tagged_writepages, + .for_kupdate = work->for_kupdate, + .for_background = work->for_background, + .for_sync = work->for_sync, + .range_cyclic = work->range_cyclic, + .range_start = 0, + .range_end = LLONG_MAX, + }; + long write_chunk; + + write_chunk = writeback_chunk_size(wb, work); + wbc.nr_to_write = write_chunk; + sb->s_op->write_metadata(sb, &wbc); + work->nr_pages -= write_chunk - wbc.nr_to_write; + + return write_chunk - wbc.nr_to_write; +} + static long __writeback_inodes_wb(struct bdi_writeback *wb, struct wb_writeback_work *work) { unsigned long start_time = jiffies; long wrote = 0; + bool done = false; while (!list_empty(&wb->b_io)) { struct inode *inode = wb_inode(wb->b_io.prev); @@ -1639,11 +1664,37 @@ static long __writeback_inodes_wb(struct bdi_writeback *wb, /* refer to the same tests at the end of writeback_sb_inodes */ if (wrote) { - if (time_is_before_jiffies(start_time + HZ / 10UL)) - break; - if (work->nr_pages <= 0) + if (time_is_before_jiffies(start_time + HZ / 10UL) || + work->nr_pages <= 0) { + done = true; break; + } + } + } + + if (!done && wb_stat(wb, WB_METADATA_DIRTY)) { + struct list_head list; + + spin_unlock(&wb->list_lock); + spin_lock(&wb->bdi->sb_list_lock); + list_splice_init(&wb->bdi->sb_list, &list); + while (!list_empty(&list)) { + struct super_block *sb; + + sb = list_first_entry(&list, struct super_block, + s_bdi_list); + list_move_tail(&wb->bdi->sb_list, &sb->s_bdi_list); + if (!sb->s_op->write_metadata) + continue; + if (!trylock_super(sb)) + continue; + spin_unlock(&wb->bdi->sb_list_lock); + wrote += writeback_sb_metadata(sb, wb, work); + spin_lock(&wb->bdi->sb_list_lock); + up_read(&sb->s_umount); } + spin_unlock(&wb->bdi->sb_list_lock); + spin_lock(&wb->list_lock); } /* Leave any unwritten inodes on b_io */ return wrote; diff --git a/fs/super.c b/fs/super.c index c2ff475..940696d 100644 --- a/fs/super.c +++ b/fs/super.c @@ -215,6 +215,7 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags, spin_lock_init(&s->s_inode_list_lock); INIT_LIST_HEAD(&s->s_inodes_wb); spin_lock_init(&s->s_inode_wblist_lock); + INIT_LIST_HEAD(&s->s_bdi_list); if (list_lru_init_memcg(&s->s_dentry_lru)) goto fail; diff --git a/include/linux/backing-dev-defs.h b/include/linux/backing-dev-defs.h index 3f10307..0e731a3 100644 --- a/include/linux/backing-dev-defs.h +++ b/include/linux/backing-dev-defs.h @@ -34,6 +34,7 @@ typedef int (congested_fn)(void *, int); enum wb_stat_item { WB_RECLAIMABLE, WB_WRITEBACK, + WB_METADATA_DIRTY, WB_DIRTIED, WB_WRITTEN, NR_WB_STAT_ITEMS @@ -166,6 +167,8 @@ struct backing_dev_info { struct timer_list laptop_mode_wb_timer; + spinlock_t sb_list_lock; + struct list_head sb_list; #ifdef CONFIG_DEBUG_FS struct dentry *debug_dir; struct dentry *debug_stats; diff --git a/include/linux/fs.h b/include/linux/fs.h index f3f0b4c8..015b06d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1430,6 +1430,8 @@ struct super_block { spinlock_t s_inode_wblist_lock; struct list_head s_inodes_wb; /* writeback inodes */ + + struct list_head s_bdi_list; }; /* Helper functions so that in most cases filesystems will @@ -1805,6 +1807,8 @@ struct super_operations { struct shrink_control *); long (*free_cached_objects)(struct super_block *, struct shrink_control *); + long (*write_metadata)(struct super_block *sb, + struct writeback_control *wbc); }; /* diff --git a/include/linux/mm.h b/include/linux/mm.h index 08ed53e..0e90fde 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -31,6 +31,7 @@ struct file_ra_state; struct user_struct; struct writeback_control; struct bdi_writeback; +struct backing_dev_info; #ifndef CONFIG_NEED_MULTIPLE_NODES /* Don't use mapnrs, do it properly */ extern unsigned long max_mapnr; @@ -1363,6 +1364,9 @@ int redirty_page_for_writepage(struct writeback_control *wbc, void account_page_dirtied(struct page *page, struct address_space *mapping); void account_page_cleaned(struct page *page, struct address_space *mapping, struct bdi_writeback *wb); +void account_metadata_dirtied(struct page *page, struct backing_dev_info *bdi); +void account_metadata_cleaned(struct page *page, struct backing_dev_info *bdi); +void account_metadata_writeback(struct page *page, struct backing_dev_info *bdi); int set_page_dirty(struct page *page); int set_page_dirty_lock(struct page *page); void cancel_dirty_page(struct page *page); diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index f2e4e90..c4177ef 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -167,6 +167,7 @@ enum node_stat_item { NR_VMSCAN_IMMEDIATE, /* Prioritise for reclaim when writeback ends */ NR_DIRTIED, /* page dirtyings since bootup */ NR_WRITTEN, /* page writings since bootup */ + NR_METADATA_DIRTY, /* Metadata dirty pages */ NR_VM_NODE_STAT_ITEMS }; diff --git a/mm/backing-dev.c b/mm/backing-dev.c index efe2377..0f1692c 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c @@ -78,6 +78,7 @@ static int bdi_debug_stats_show(struct seq_file *m, void *v) "BackgroundThresh: %10lu kB\n" "BdiDirtied: %10lu kB\n" "BdiWritten: %10lu kB\n" + "BdiMetadataDirty: %10lu kB\n" "BdiWriteBandwidth: %10lu kBps\n" "b_dirty: %10lu\n" "b_io: %10lu\n" @@ -92,6 +93,7 @@ static int bdi_debug_stats_show(struct seq_file *m, void *v) K(background_thresh), (unsigned long) K(wb_stat(wb, WB_DIRTIED)), (unsigned long) K(wb_stat(wb, WB_WRITTEN)), + (unsigned long) K(wb_stat(wb, WB_METADATA_DIRTY)), (unsigned long) K(wb->write_bandwidth), nr_dirty, nr_io, @@ -780,6 +782,7 @@ int bdi_init(struct backing_dev_info *bdi) bdi->max_prop_frac = FPROP_FRAC_BASE; INIT_LIST_HEAD(&bdi->bdi_list); INIT_LIST_HEAD(&bdi->wb_list); + INIT_LIST_HEAD(&bdi->sb_list); init_waitqueue_head(&bdi->wb_waitq); ret = cgwb_bdi_init(bdi); diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 121a6e3..c6492de1a 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -506,6 +506,7 @@ bool node_dirty_ok(struct pglist_data *pgdat) nr_pages += node_page_state(pgdat, NR_FILE_DIRTY); nr_pages += node_page_state(pgdat, NR_UNSTABLE_NFS); nr_pages += node_page_state(pgdat, NR_WRITEBACK); + nr_pages += node_page_state(pgdat, NR_METADATA_DIRTY); return nr_pages <= limit; } @@ -1595,7 +1596,8 @@ static void balance_dirty_pages(struct bdi_writeback *wb, * been flushed to permanent storage. */ nr_reclaimable = global_node_page_state(NR_FILE_DIRTY) + - global_node_page_state(NR_UNSTABLE_NFS); + global_node_page_state(NR_UNSTABLE_NFS) + + global_node_page_state(NR_METADATA_DIRTY); gdtc->avail = global_dirtyable_memory(); gdtc->dirty = nr_reclaimable + global_node_page_state(NR_WRITEBACK); @@ -1935,7 +1937,8 @@ bool wb_over_bg_thresh(struct bdi_writeback *wb) */ gdtc->avail = global_dirtyable_memory(); gdtc->dirty = global_node_page_state(NR_FILE_DIRTY) + - global_node_page_state(NR_UNSTABLE_NFS); + global_node_page_state(NR_UNSTABLE_NFS) + + global_node_page_state(NR_METADATA_DIRTY); domain_dirty_limits(gdtc); if (gdtc->dirty > gdtc->bg_thresh) @@ -2009,7 +2012,8 @@ void laptop_mode_timer_fn(unsigned long data) { struct request_queue *q = (struct request_queue *)data; int nr_pages = global_node_page_state(NR_FILE_DIRTY) + - global_node_page_state(NR_UNSTABLE_NFS); + global_node_page_state(NR_UNSTABLE_NFS) + + global_node_page_state(NR_METADATA_DIRTY); struct bdi_writeback *wb; /* @@ -2473,6 +2477,74 @@ void account_page_dirtied(struct page *page, struct address_space *mapping) EXPORT_SYMBOL(account_page_dirtied); /* + * account_metadata_dirtied + * @page - the page being dirited + * @bdi - the bdi that owns this page + * + * Do the dirty page accounting for metadata pages that aren't backed by an + * address_space. + */ +void account_metadata_dirtied(struct page *page, struct backing_dev_info *bdi) +{ + unsigned long flags; + + local_irq_save(flags); + __inc_node_page_state(page, NR_METADATA_DIRTY); + __inc_node_page_state(page, NR_FILE_DIRTY); + __inc_zone_page_state(page, NR_ZONE_WRITE_PENDING); + __inc_node_page_state(page, NR_DIRTIED); + __inc_wb_stat(&bdi->wb, WB_RECLAIMABLE); + __inc_wb_stat(&bdi->wb, WB_DIRTIED); + __inc_wb_stat(&bdi->wb, WB_METADATA_DIRTY); + current->nr_dirtied++; + task_io_account_write(PAGE_SIZE); + this_cpu_inc(bdp_ratelimits); + local_irq_restore(flags); +} +EXPORT_SYMBOL(account_metadata_dirtied); + +/* + * account_metadata_cleaned + * @page - the page being cleaned + * @bdi - the bdi that owns this page + * + * Called on a no longer dirty metadata page. + */ +void account_metadata_cleaned(struct page *page, struct backing_dev_info *bdi) +{ + unsigned long flags; + + local_irq_save(flags); + __dec_node_page_state(page, NR_METADATA_DIRTY); + __dec_zone_page_state(page, NR_ZONE_WRITE_PENDING); + __dec_wb_stat(&bdi->wb, WB_RECLAIMABLE); + __dec_wb_stat(&bdi->wb, WB_METADATA_DIRTY); + task_io_account_cancelled_write(PAGE_SIZE); + local_irq_restore(flags); +} +EXPORT_SYMBOL(account_metadata_cleaned); + +/* + * account_metadata_writeback + * @page - the page being marked as writeback + * @bdi - the bdi that owns this page + * + * Called on a metadata page that has been marked writeback. + */ +void account_metadata_writeback(struct page *page, struct backing_dev_info *bdi) +{ + unsigned long flags; + + local_irq_save(flags); + __inc_wb_stat(&bdi->wb, WB_WRITEBACK); + __dec_wb_stat(&bdi->wb, WB_METADATA_DIRTY); + __inc_node_page_state(page, NR_WRITEBACK); + __dec_node_page_state(page, NR_METADATA_DIRTY); + local_irq_restore(flags); +} +EXPORT_SYMBOL(account_metadata_writeback); + +/* * Helper function for deaccounting dirty page without writeback. * * Caller must hold lock_page_memcg().