From patchwork Thu Jun 15 03:29:11 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Yuezhang.Mo@sony.com" X-Patchwork-Id: 13280687 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 103F5EB64D9 for ; Thu, 15 Jun 2023 04:33:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243036AbjFOEdY (ORCPT ); Thu, 15 Jun 2023 00:33:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37104 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229944AbjFOEdW (ORCPT ); Thu, 15 Jun 2023 00:33:22 -0400 Received: from mx07-001d1705.pphosted.com (mx07-001d1705.pphosted.com [185.132.183.11]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C32D71BDB for ; Wed, 14 Jun 2023 21:33:20 -0700 (PDT) Received: from pps.filterd (m0209326.ppops.net [127.0.0.1]) by mx08-001d1705.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 35ENLK1U030487; Thu, 15 Jun 2023 03:29:18 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sony.com; h=from : to : cc : subject : date : message-id : mime-version : content-type : content-transfer-encoding; s=S1; bh=F4c8hw/QvO78bZtYo+SYTaR3BglNGnRcIp4w1WXNDXk=; b=m7BWKkeQXLNUqJYuCDS9XeRc3ZuanZOOhHp+qjfFNKPrhmvJru3zbdafyH12RPX86oEq KkSepq9fSgmhxbh/kv2Fe3YvCbn7vE81RkN+RZpfnFB2f0A6KW2w5TXRm8R8uEnto3r1 7sm5VW7HJ6b/49Hik8IYPzUS+2CpEMK2+59ls5dDM6Wol4b/uhamI076QJMQpdzf1sP4 VfjuIPqJ4jnfhrDNDb11ozc7d0xWiOpioLy0itKoQ1B/MjRsrPjmvmN3cV7PGDS/M8RV JM60jlDNyniuJ7KEDvejkQ4CuzTjhww2jQNPC3VjOS0BEre84RVvufO3uHYC0USjks0j Zg== Received: from apc01-sg2-obe.outbound.protection.outlook.com (mail-sgaapc01lp2106.outbound.protection.outlook.com [104.47.26.106]) by mx08-001d1705.pphosted.com (PPS) with ESMTPS id 3r6uunsna5-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Thu, 15 Jun 2023 03:29:17 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=eWASmDJKWZEbtR2rppbrr01J4KHdWOSqefklLzO1YBTu8LRrCrv4QB9/53x1OXFyBV/bC5vAgCndEd7Jh+U06RUPCIoXrEgF8yUYGQ4VmOKG/uFtb9k6znt+TvLSJJXqGKDe+HDsABZ2RC2fsOWTZic1oDfq4IRquODqLOjMEZivQ8y4UKgMdiftuvYuinglfqWyCLQ264pzUxEB94vuvrLwsegF1xlA7UMZf0lufGr0lp3ENcQ7B8GM5maGIUb9SE2JbGqsoZG/rLjsp5TwHLaAPi5rFyVzqzlTBiOiAhKwqsSm++vxYJE20QtBdfwRZRt9Wca0qIykLoF5H52M3g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=F4c8hw/QvO78bZtYo+SYTaR3BglNGnRcIp4w1WXNDXk=; b=ntFaaFyirapb23nOl6mztGY+igLgnzMWNyWCIOMnLLqUzvFbZyT4jXvcjG2qOusqRvzJGk46cptmazery6YLjBFtYWfn+bqJ2xIEpOom7U0ezUVJW2/G2uu5IKn26bvmwh3ilUKsbey3txUwVG/wRMl/eZnxoffblpUEjqbWcSaUetTgMLC7SUXlRWjAglSN7TyVQ4NYV8SW2TuxI//+MShFvw+06tkxOD6zoKS9H+5mLsgVre91LjNaiuOmvy/OlATocWuwdd+oUM969OTW5Jg5q1dZwzyJXirNKZ4TTrN7fh44XdJ/vsDCPJ85VtqVpgafDFCLQgFO/CnSLNE2sQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=sony.com; dmarc=pass action=none header.from=sony.com; dkim=pass header.d=sony.com; arc=none Received: from PUZPR04MB6316.apcprd04.prod.outlook.com (2603:1096:301:fc::7) by KL1PR0401MB4212.apcprd04.prod.outlook.com (2603:1096:820:27::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6500.25; Thu, 15 Jun 2023 03:29:11 +0000 Received: from PUZPR04MB6316.apcprd04.prod.outlook.com ([fe80::ce2d:a9dc:4955:5275]) by PUZPR04MB6316.apcprd04.prod.outlook.com ([fe80::ce2d:a9dc:4955:5275%5]) with mapi id 15.20.6455.037; Thu, 15 Jun 2023 03:29:11 +0000 From: "Yuezhang.Mo@sony.com" To: "linkinjeon@kernel.org" , "sj1557.seo@samsung.com" CC: "linux-fsdevel@vger.kernel.org" , "Andy.Wu@sony.com" , "Wataru.Aoyama@sony.com" Subject: [PATCH v1 1/2] exfat: change to get file size from DataLength Thread-Topic: [PATCH v1 1/2] exfat: change to get file size from DataLength Thread-Index: AdmfOM+RRg1waKiWT3mEw2cVv4oUyg== Date: Thu, 15 Jun 2023 03:29:11 +0000 Message-ID: Accept-Language: zh-CN, en-US Content-Language: zh-CN X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ms-publictraffictype: Email x-ms-traffictypediagnostic: PUZPR04MB6316:EE_|KL1PR0401MB4212:EE_ x-ms-office365-filtering-correlation-id: 433e14b8-3824-45b7-ba45-08db6d50afc2 x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: J5D59+4hBFbvHP80d2B0czS94fwSwKVdItKC2KDGmuPeSKMGGHps6Na+8uXm1qOtPFPhVWhkl/PQ6b1q0PyUXzwc7HpEL+rKsJ646SM3h0QlMSss9bUxDt4awBI7WDjuA/JBjHAjb88No9uIBoqjHKznsmNE8h1zX3Us1W/kN/MnEjVWJWHnpSHgOKGtN3iJ0YNtTwIyQeP/MvM9YgGu4oijUsdbHVaxexQe85GhU7TWG4rO7to4PHOPojX14a5XY4vayTw2xAru5po6c9Wt9hlagBpO9i5ZEODRZMJM/V39Cj2hSYQHBc96XrPNQXNY2/bGRll1N99s6ViFqF6NF9mUZZQsoPCdz4ndqVvWQSywPq/JA9lXEMXVMLL38LSQ++C9Q1b475nMbqnb2IB/aKNqu9iNmimC22YN+F6F7sbg27OtyhV/+OUk95RT8UnBmGCt6qdAEjLW/z4U4ZLK16ShGtl8U9dP3v3VT/qhIm+YLf0kqpSwYorye8AcHTCEj1O9IIEMqDIPnImwjhLviK9oloqChRGX7lwyx2IZRkUOl0gPhEFLDg23uvZ7UJicAAjCUQyY6tdAoXW/qEF4in6uS031CF1Cu7TpieJ0rcAxNr2YtU8v9BakkAQ5SzgS x-forefront-antispam-report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:PUZPR04MB6316.apcprd04.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230028)(4636009)(396003)(366004)(136003)(346002)(39860400002)(376002)(451199021)(76116006)(4326008)(30864003)(2906002)(86362001)(38070700005)(316002)(64756008)(66446008)(66476007)(66556008)(66946007)(41300700001)(110136005)(5660300002)(52536014)(8936002)(8676002)(54906003)(38100700002)(478600001)(122000001)(82960400001)(7696005)(71200400001)(83380400001)(107886003)(55016003)(9686003)(26005)(6506007)(186003)(33656002);DIR:OUT;SFP:1102; x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?utf-8?q?1UrexdE5i67oKU1p4u8gZ8SlNLof?= =?utf-8?q?pGbTv8rN2b7PuW5HTxw2eSzca2xiPshJt8cs0tpcXwedOm67YECAJqczOymKgPX3Y?= =?utf-8?q?ClGBDNnewnNQWZXo0A46yeyko538g5UGfWMkzk/1UGBfboXbpyAKXK2Tw/yAORrRN?= =?utf-8?q?Y+8G8Rq6CbRg9s7mKogiBc4kSBCbQo/R1rKE37xOCXbAXCqKW/+7jxy1L7v2k8EKM?= =?utf-8?q?/Qfkw1+NwfOxxOMeyejJxroClBCHfKuNnq+ynVajKbzMwRw2QcleY/TmltOXJyIuv?= =?utf-8?q?N26CV0UiE27+NkJ8bFGNU1+qMR6fYb4kDJfZIq20k42hAuyx2+eTLnfcFVPFeT89g?= =?utf-8?q?kjWi7nP2EjOTtMRW3wBw2R/EYi7R5uQf4vH3LPJce8k6wVYWqa9GZqta6VfGlG4wU?= =?utf-8?q?zn9tscCGDRzP0n+deFTl+AuFSxsfOJ0BxjlBQDfNUjBTgPyilHKiiJnDSQy1116+x?= =?utf-8?q?Ol1dNUprkxb/1KOUD1XgWiPt1LeQF4SJ3PSqbwYwRKT587p2UwCLMola1l9kR78/d?= =?utf-8?q?mXYLCGj3neyLyqpjv/rhPALp4T2lSaWz/mgTlBZRm3bxCDwtt13r/l1Tadb+BTcvj?= =?utf-8?q?R7pf8VRBdqh0fmUCRIkUsE1w6hww8hW5n7m5tRcQhEpnAfjVDacmsiovsZf6OKeIe?= =?utf-8?q?CQfGovwjmeKQpT0yG5DPaFjYf2LcdzMZKugejvL0zLkU9U/9Vv9xYG9VsqKTUxEXx?= =?utf-8?q?I/TLxTyQ39CC3KUInQ7GrpWbLKUBUakYwHbmygz8S7RgwOwa83OvBYmJlMdRxQNvt?= =?utf-8?q?NQ6YUlKHrWJvH4lYyEHaqN0FtC+IdrxhFowQtXeLQjo751gks3nkXKEubEgVdHYGL?= =?utf-8?q?bUP328gv9QlKmNqSAAZR5AQkagTAxR5Ak2Dys0UBRqg7YS3UyVOTYOgMQNFfCTH/5?= =?utf-8?q?eJbpM9dF8V77oeBw+5r2C+l2fp0Dw8dJ/enXQH3vGJe1HdnnCn71jSLL8qiZFhC/X?= =?utf-8?q?S4i2Ko4NcezmOSkejjXbyErBDPo/QDvJZXSx6G0ZXFLc/GPgTahPrthVIqFl473wb?= =?utf-8?q?NIR9gwTKubscxKawqWLZsUZLd1H7m5uzctBJo4CTYzgsNtD1PVRFS2VqkXcaCO7yY?= =?utf-8?q?buK/JQjHkyMimBk5Dd2hLFXSVND0L3bAvwSNr47upNJNORTDbfD5+hgdcGAR5bA26?= =?utf-8?q?dFGXZWvjVFVigAx+iK5Por8iQCKX1PBnduZBSE2ggRMDAjTT7OXnZi93s4t2fMWRV?= =?utf-8?q?TG02gal8VfssxM9LJWRP2czfXduQAqChDDOioIgfCvxx26Uuf5nzqqKVIAN+jTsi/?= =?utf-8?q?/A7QHO91EL+jjWfiMAHTU/anm0pylnslJueCpF48x7PHqH0y3XLJ9jCf0s5BXtkJr?= =?utf-8?q?nASCSz2Q1jkt9YZ5FPhkeg1Ighp5dM7986R9sU40nHa3a1AOd/xOQatNJA0PuUx/v?= =?utf-8?q?lIl4V2yHv2TpXsgL35rfH7XB8bIm40/gGit870rmwKyjbHS6yV8MfpOZXmfyB8HaF?= =?utf-8?q?AoYYeFHps3kDgJQmsEhbySNcqI4Q0twhPey4+sVTsyeTpK17FVmO0VfoDT3+dAvOk?= =?utf-8?q?gS7l5S6Ei/XR?= MIME-Version: 1.0 X-MS-Exchange-AntiSpam-ExternalHop-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-ExternalHop-MessageData-0: 44Mfj9jZ2ATBozhU67O/KQmoYn/1S85MBR71rr+zW8pWDi6TSE65vaTbL/GvzrHANPddLUccIJHBaI6leAO2adOlecSIumF622y8tRAzC+JfPsOgi1vMXYHLGpZZcRsp5cRLKdSK0DAaOroHuF+0Y4YV1cEFf1KZ340T3sGEXajhB1bFiWfaylXzgzRudVIlY6YpI91I4eNYq2tFd1nhAMU/vXEFqTTexVqX4CehSnItDiDz5iFKW87r0yzF7R2T644sbTQX3dJUc9PQS8b1owRaK6SPDx7PrnZqLruDmCkxFAFCSr6eJTzjFhZ0EmrWs2w5puh4Le3SAFkjfXNAWTuZuhwYSAytZP37uKaWIimpmaDPXOP5OpFu5Dx2V8iTYbv+j6u16+9k7wcR0L9vEckx21a3xtsnkd1Q4XWWUqJaG1Z5i8ojmvPRnkIt0Yo5d9JBMkvPZfVg2B7tUHVteZuDQZjrkUHIwGuYCk+FcjE0D0VTOdYtZnOL/CDw96G252xzAxCX6Tt88b8iqdTO7zoKvI8FgU7R/166LHl+z8PD3vhKWDW+B0qefz/Zc3uOxStYWEi45Tc1POYiYrkkY++YCUyD5VGaAN5aegiaESPw6zkUtmptnLAURboYamzIVk+P2EJ/9dBilpPRhcP3pzmFnkjIdAfJ2dF7Mgj00zoyFWNxXB0+rg7TtSzpq1DpKfutWlUPQ/gFZB+OL6yJya3lVb9tQM2+8u5djhbAsK44HIYH3jDhN8USVI8VY74l/gv4dqfxefu89JEMyWkDgqEdKfqq2cvnZaUJcQKkG0veObX2IKTb2hiwelczBvypKXj8R59OnorVTWTNh/hSXg== X-OriginatorOrg: sony.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: PUZPR04MB6316.apcprd04.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: 433e14b8-3824-45b7-ba45-08db6d50afc2 X-MS-Exchange-CrossTenant-originalarrivaltime: 15 Jun 2023 03:29:11.6571 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 66c65d8a-9158-4521-a2d8-664963db48e4 X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: XCV6neeJWGlsqVqJmPkMIwZpLp8P2ZSXml3BLEeilOc2NnJaovWfMqufEZCEN7khgHtQpdRGnizl3JS6zF1MxA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: KL1PR0401MB4212 X-Proofpoint-ORIG-GUID: FgG6EyIlyd715H7_7traVuy1BqMupbms X-Proofpoint-GUID: FgG6EyIlyd715H7_7traVuy1BqMupbms X-Sony-Outbound-GUID: FgG6EyIlyd715H7_7traVuy1BqMupbms X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.254,Aquarius:18.0.957,Hydra:6.0.573,FMLib:17.11.176.26 definitions=2023-06-14_14,2023-06-14_02,2023-05-22_02 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org In stream extension directory entry, the ValidDataLength field describes how far into the data stream user data has been written, and the DataLength field describes the file size. Signed-off-by: Yuezhang Mo Reviewed-by: Andy Wu Reviewed-by: Aoyama Wataru --- fs/exfat/exfat_fs.h | 2 + fs/exfat/file.c | 139 ++++++++++++++++++++++++++++++++++++++++++-- fs/exfat/inode.c | 108 +++++++++++++++++++++++++++++----- fs/exfat/namei.c | 7 ++- 4 files changed, 236 insertions(+), 20 deletions(-) diff --git a/fs/exfat/exfat_fs.h b/fs/exfat/exfat_fs.h index 729ada9e26e8..8d6248367433 100644 --- a/fs/exfat/exfat_fs.h +++ b/fs/exfat/exfat_fs.h @@ -208,6 +208,7 @@ struct exfat_dir_entry { unsigned char flags; unsigned short attr; loff_t size; + loff_t valid_size; unsigned int num_subdirs; struct timespec64 atime; struct timespec64 mtime; @@ -317,6 +318,7 @@ struct exfat_inode_info { loff_t i_size_aligned; /* on-disk position of directory entry or 0 */ loff_t i_pos; + loff_t valid_size; /* hash by i_location */ struct hlist_node i_hash_fat; /* protect bmap against truncate */ diff --git a/fs/exfat/file.c b/fs/exfat/file.c index e99183a74611..680597f3237d 100644 --- a/fs/exfat/file.c +++ b/fs/exfat/file.c @@ -8,11 +8,12 @@ #include #include #include +#include #include "exfat_raw.h" #include "exfat_fs.h" -static int exfat_cont_expand(struct inode *inode, loff_t size) +static int exfat_cont_expand(struct inode *inode, loff_t size, bool sync) { struct address_space *mapping = inode->i_mapping; loff_t start = i_size_read(inode), count = size - i_size_read(inode); @@ -23,9 +24,10 @@ static int exfat_cont_expand(struct inode *inode, loff_t size) return err; inode->i_ctime = inode->i_mtime = current_time(inode); + EXFAT_I(inode)->valid_size = size; mark_inode_dirty(inode); - if (!IS_SYNC(inode)) + if (!sync) return 0; err = filemap_fdatawrite_range(mapping, start, start + count - 1); @@ -143,6 +145,9 @@ int __exfat_truncate(struct inode *inode) ei->start_clu = EXFAT_EOF_CLUSTER; } + if (i_size_read(inode) < ei->valid_size) + ei->valid_size = i_size_read(inode); + if (ei->type == TYPE_FILE) ei->attr |= ATTR_ARCHIVE; @@ -251,7 +256,7 @@ int exfat_setattr(struct mnt_idmap *idmap, struct dentry *dentry, if ((attr->ia_valid & ATTR_SIZE) && attr->ia_size > i_size_read(inode)) { - error = exfat_cont_expand(inode, attr->ia_size); + error = exfat_cont_expand(inode, attr->ia_size, IS_SYNC(inode)); if (error || attr->ia_valid == ATTR_SIZE) return error; attr->ia_valid &= ~ATTR_SIZE; @@ -379,15 +384,139 @@ int exfat_file_fsync(struct file *filp, loff_t start, loff_t end, int datasync) return blkdev_issue_flush(inode->i_sb->s_bdev); } +static int exfat_file_zeroed_range(struct file *file, loff_t start, loff_t end) +{ + int err; + struct inode *inode = file_inode(file); + struct exfat_inode_info *ei = EXFAT_I(inode); + struct address_space *mapping = inode->i_mapping; + const struct address_space_operations *ops = mapping->a_ops; + + while (start < end) { + u32 zerofrom, len; + struct page *page; + + zerofrom = start & (PAGE_SIZE - 1); + len = PAGE_SIZE - zerofrom; + if (start + len > end) + len = end - start; + + err = ops->write_begin(file, mapping, start, len, &page, NULL); + if (err) + goto out; + + zero_user_segment(page, zerofrom, zerofrom + len); + + err = ops->write_end(file, mapping, start, len, len, page, NULL); + if (err < 0) + goto out; + start += len; + + balance_dirty_pages_ratelimited(mapping); + cond_resched(); + } + + ei->valid_size = end; + mark_inode_dirty(inode); + +out: + return err; +} + +static ssize_t exfat_file_write_iter(struct kiocb *iocb, struct iov_iter *iter) +{ + ssize_t ret; + struct file *file = iocb->ki_filp; + struct inode *inode = file_inode(file); + struct exfat_inode_info *ei = EXFAT_I(inode); + loff_t pos = iocb->ki_pos; + loff_t valid_size; + loff_t size; + size_t count = iov_iter_count(iter); + + inode_lock(inode); + + size = i_size_read(inode); + valid_size = ei->valid_size; + + ret = generic_write_checks(iocb, iter); + if (ret < 0) + goto unlock; + + if (pos + count > size) { + ret = exfat_cont_expand(inode, pos + count, false); + if (ret < 0) + goto unlock; + } + + if (pos > valid_size) { + ret = exfat_file_zeroed_range(file, valid_size, pos); + if (ret < 0) { + exfat_err(inode->i_sb, + "write: fail to zero from %llu to %llu(%ld)", + valid_size, pos, ret); + + goto unlock; + } + } + + ret = __generic_file_write_iter(iocb, iter); + if (ret <= 0) + goto unlock; + + if ((iocb->ki_flags & IOCB_DIRECT) && pos + ret > ei->valid_size) { + ei->valid_size = pos + ret; + mark_inode_dirty(inode); + } + + inode_unlock(inode); + + if (pos > valid_size && iocb_is_dsync(iocb)) { + ssize_t err = vfs_fsync_range(file, valid_size, pos - 1, + iocb->ki_flags & IOCB_SYNC); + if (err < 0) + return err; + } + + return generic_write_sync(iocb, ret); + +unlock: + inode_unlock(inode); + + return ret; +} + +static int exfat_file_mmap(struct file *file, struct vm_area_struct *vma) +{ + int ret; + struct inode *inode = file_inode(file); + struct exfat_inode_info *ei = EXFAT_I(inode); + loff_t start = ((loff_t)vma->vm_pgoff << PAGE_SHIFT); + loff_t end = min_t(loff_t, i_size_read(inode), + start + vma->vm_end - vma->vm_start); + + if ((vma->vm_flags & VM_WRITE) && ei->valid_size < end) { + ret = exfat_file_zeroed_range(file, ei->valid_size, end); + if (ret < 0) { + exfat_err(inode->i_sb, + "mmap: fail to zero from %llu to %llu(%d)", + start, end, ret); + return ret; + } + } + + return generic_file_mmap(file, vma); +} + const struct file_operations exfat_file_operations = { .llseek = generic_file_llseek, .read_iter = generic_file_read_iter, - .write_iter = generic_file_write_iter, + .write_iter = exfat_file_write_iter, .unlocked_ioctl = exfat_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = exfat_compat_ioctl, #endif - .mmap = generic_file_mmap, + .mmap = exfat_file_mmap, .fsync = exfat_file_fsync, .splice_read = generic_file_splice_read, .splice_write = iter_file_splice_write, diff --git a/fs/exfat/inode.c b/fs/exfat/inode.c index 481dd338f2b8..b85a8030b866 100644 --- a/fs/exfat/inode.c +++ b/fs/exfat/inode.c @@ -72,8 +72,8 @@ int __exfat_write_inode(struct inode *inode, int sync) if (ei->start_clu == EXFAT_EOF_CLUSTER) on_disk_size = 0; - ep2->dentry.stream.valid_size = cpu_to_le64(on_disk_size); - ep2->dentry.stream.size = ep2->dentry.stream.valid_size; + ep2->dentry.stream.valid_size = cpu_to_le64(ei->valid_size); + ep2->dentry.stream.size = cpu_to_le64(on_disk_size); if (on_disk_size) { ep2->dentry.stream.flags = ei->flags; ep2->dentry.stream.start_clu = cpu_to_le32(ei->start_clu); @@ -276,6 +276,7 @@ static int exfat_get_block(struct inode *inode, sector_t iblock, sector_t last_block; sector_t phys = 0; loff_t pos; + size_t b_size = bh_result->b_size; mutex_lock(&sbi->s_lock); last_block = EXFAT_B_TO_BLK_ROUND_UP(i_size_read(inode), sb); @@ -303,17 +304,25 @@ static int exfat_get_block(struct inode *inode, sector_t iblock, mapped_blocks = sbi->sect_per_clus - sec_offset; max_blocks = min(mapped_blocks, max_blocks); - /* Treat newly added block / cluster */ - if (iblock < last_block) - create = 0; - - if (create || buffer_delay(bh_result)) { - pos = EXFAT_BLK_TO_B((iblock + 1), sb); + pos = EXFAT_BLK_TO_B((iblock + 1), sb); + if ((create && iblock >= last_block) || buffer_delay(bh_result)) { if (ei->i_size_ondisk < pos) ei->i_size_ondisk = pos; } + map_bh(bh_result, sb, phys); + if (buffer_delay(bh_result)) + clear_buffer_delay(bh_result); + if (create) { + sector_t valid_blks; + + valid_blks = EXFAT_B_TO_BLK_ROUND_UP(ei->valid_size, sb); + if (iblock < valid_blks && iblock + max_blocks >= valid_blks) { + max_blocks = valid_blks - iblock; + goto done; + } + err = exfat_map_new_buffer(ei, bh_result, pos); if (err) { exfat_fs_error(sb, @@ -321,11 +330,40 @@ static int exfat_get_block(struct inode *inode, sector_t iblock, pos, ei->i_size_aligned); goto unlock_ret; } - } - if (buffer_delay(bh_result)) - clear_buffer_delay(bh_result); - map_bh(bh_result, sb, phys); + if (pos - sb->s_blocksize + b_size > ei->valid_size) { + ei->valid_size = pos - sb->s_blocksize + b_size; + mark_inode_dirty(inode); + } + } else { + size_t b_size = EXFAT_BLK_TO_B(max_blocks, sb); + + pos = EXFAT_BLK_TO_B(iblock, sb); + if (pos >= ei->valid_size) { + /* Read out of valid data */ + clear_buffer_mapped(bh_result); + } else if (pos + b_size <= ei->valid_size) { + /* Normal read */ + } else if (pos + sb->s_blocksize <= ei->valid_size) { + /* Normal short read */ + max_blocks = 1; + } else { + /* Read across valid size */ + if (bh_result->b_page) { + loff_t size = ei->valid_size - pos; + loff_t off = pos & (PAGE_SIZE - 1); + + set_bh_page(bh_result, bh_result->b_page, off); + err = bh_read(bh_result, 0); + if (err < 0) + goto unlock_ret; + + zero_user_segment(bh_result->b_page, off + size, + off + sb->s_blocksize); + } + max_blocks = 1; + } + } done: bh_result->b_size = EXFAT_BLK_TO_B(max_blocks, sb); unlock_ret: @@ -340,6 +378,17 @@ static int exfat_read_folio(struct file *file, struct folio *folio) static void exfat_readahead(struct readahead_control *rac) { + struct address_space *mapping = rac->mapping; + struct inode *inode = mapping->host; + struct exfat_inode_info *ei = EXFAT_I(inode); + loff_t pos = readahead_pos(rac); + + /* Range cross valid_size, read it page by page. */ + if (ei->valid_size < i_size_read(inode) && + pos <= ei->valid_size && + ei->valid_size < pos + readahead_length(rac)) + return; + mpage_readahead(rac, exfat_get_block); } @@ -403,6 +452,22 @@ static int exfat_write_end(struct file *file, struct address_space *mapping, mark_inode_dirty(inode); } + if (err >= 0) { + if (pos + err > ei->valid_size) { + ei->valid_size = pos + err; + mark_inode_dirty(inode); + } + + /* + * valid_size is extended with sector-aligned length in + * exfat_get_block(), set to the writren length. + */ + if (ei->valid_size > i_size_read(inode)) { + ei->valid_size = i_size_read(inode); + mark_inode_dirty(inode); + } + } + return err; } @@ -410,6 +475,8 @@ static ssize_t exfat_direct_IO(struct kiocb *iocb, struct iov_iter *iter) { struct address_space *mapping = iocb->ki_filp->f_mapping; struct inode *inode = mapping->host; + struct exfat_inode_info *ei = EXFAT_I(inode); + loff_t pos = iocb->ki_pos; loff_t size = iocb->ki_pos + iov_iter_count(iter); int rw = iov_iter_rw(iter); ssize_t ret; @@ -433,8 +500,20 @@ static ssize_t exfat_direct_IO(struct kiocb *iocb, struct iov_iter *iter) * condition of exfat_get_block() and ->truncate(). */ ret = blockdev_direct_IO(iocb, inode, iter, exfat_get_block); - if (ret < 0 && (rw & WRITE)) - exfat_write_failed(mapping, size); + if (ret < 0) { + if (rw & WRITE) + exfat_write_failed(mapping, size); + + if (ret != -EIOCBQUEUED) + return ret; + } else + size = pos + ret; + + if ((rw & READ) && pos < ei->valid_size && ei->valid_size < size) { + iov_iter_revert(iter, size - ei->valid_size); + iov_iter_zero(size - ei->valid_size, iter); + } + return ret; } @@ -534,6 +613,7 @@ static int exfat_fill_inode(struct inode *inode, struct exfat_dir_entry *info) ei->start_clu = info->start_clu; ei->flags = info->flags; ei->type = info->type; + ei->valid_size = info->valid_size; ei->version = 0; ei->hint_stat.eidx = 0; diff --git a/fs/exfat/namei.c b/fs/exfat/namei.c index e0ff9d156f6f..ceaa720804b9 100644 --- a/fs/exfat/namei.c +++ b/fs/exfat/namei.c @@ -395,6 +395,7 @@ static int exfat_find_empty_entry(struct inode *inode, i_size_write(inode, size); ei->i_size_ondisk += sbi->cluster_size; ei->i_size_aligned += sbi->cluster_size; + ei->valid_size += sbi->cluster_size; ei->flags = p_dir->flags; inode->i_blocks += sbi->cluster_size >> 9; } @@ -544,6 +545,8 @@ static int exfat_add_entry(struct inode *inode, const char *path, info->size = clu_size; info->num_subdirs = EXFAT_MIN_SUBDIR; } + info->valid_size = info->size; + memset(&info->crtime, 0, sizeof(info->crtime)); memset(&info->mtime, 0, sizeof(info->mtime)); memset(&info->atime, 0, sizeof(info->atime)); @@ -645,7 +648,8 @@ static int exfat_find(struct inode *dir, struct qstr *qname, info->type = exfat_get_entry_type(ep); info->attr = le16_to_cpu(ep->dentry.file.attr); - info->size = le64_to_cpu(ep2->dentry.stream.valid_size); + info->valid_size = le64_to_cpu(ep2->dentry.stream.valid_size); + info->size = le64_to_cpu(ep2->dentry.stream.size); if ((info->type == TYPE_FILE) && (info->size == 0)) { info->flags = ALLOC_NO_FAT_CHAIN; info->start_clu = EXFAT_EOF_CLUSTER; @@ -1271,6 +1275,7 @@ static int __exfat_rename(struct inode *old_parent_inode, } i_size_write(new_inode, 0); + new_ei->valid_size = 0; new_ei->start_clu = EXFAT_EOF_CLUSTER; new_ei->flags = ALLOC_NO_FAT_CHAIN; } From patchwork Thu Jun 15 03:29:13 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Yuezhang.Mo@sony.com" X-Patchwork-Id: 13280686 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 097C6EB64D9 for ; Thu, 15 Jun 2023 04:29:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243036AbjFOE3a (ORCPT ); Thu, 15 Jun 2023 00:29:30 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36386 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237726AbjFOE32 (ORCPT ); Thu, 15 Jun 2023 00:29:28 -0400 X-Greylist: delayed 3590 seconds by postgrey-1.37 at lindbergh.monkeyblade.net; Wed, 14 Jun 2023 21:29:26 PDT Received: from mx07-001d1705.pphosted.com (mx07-001d1705.pphosted.com [185.132.183.11]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CD6CA212B for ; Wed, 14 Jun 2023 21:29:26 -0700 (PDT) Received: from pps.filterd (m0209326.ppops.net [127.0.0.1]) by mx08-001d1705.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 35ENLK1V030487; Thu, 15 Jun 2023 03:29:19 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sony.com; h=from : to : cc : subject : date : message-id : mime-version : content-type : content-transfer-encoding; s=S1; bh=AOL5ot312TBpsYB2SJLfmwQiP99A4RF1n5uHkWVx2KA=; b=NiaJj88L5iijPY932/mIjEI+o+hTfW4KnReOz8ozgBoEa6oxNMRFbe4L63bQ5ZTsHLoM jbOoV+wrTWFByIDai4AOkujSPpElYmtXEiUjIVDpHdyRyN/7GdaqHcENMh8YGpqQ9mqJ 3MgSTyUw07kqsUTmrVBgEfZAivIR6wGRoOuOsRkqGh+QCCSb5gSSXlsCapybOQtBdKDl r1cZNTOFfyh4Cwp4uswzqIJ7LtbFE5kzqS0pqgljYnMwug0/7f84VGmKkLAn5/XvqnKh yDk6xvGnCi9712V80O2B955NiMHUyaq0cYWEB7Nda+tYg2+NhZ+8PWJjTDnF0ekVKSlY QQ== Received: from apc01-sg2-obe.outbound.protection.outlook.com (mail-sgaapc01lp2106.outbound.protection.outlook.com [104.47.26.106]) by mx08-001d1705.pphosted.com (PPS) with ESMTPS id 3r6uunsna5-2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Thu, 15 Jun 2023 03:29:18 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=W18jtP/s/UGvmVRfcDvtDv4NtzwsbD71vDdXvLnk3TgbNOIaIbVUg+jcE7nR8tZgCcKwbC+DmU++6IJ36l9O1TyAWeQTzbDqb7dpAa3WYR8cymRdeS7R0s0vby/ULxg6dBlBB6H0uryoLdJCz/egLQtgTOf+R3mStFeQPIyFohJsmmycvLLM9oYLuk6kj9FJmoGcl549OecQaaKRqygAj6VkBwkP6ypPgLkDFsUIjUX5+XdluLFXDTOfMeHWJYHXCWdVNT7SuT1+szLladmWsL7x/o2rBXQ+nuXjme3qW2TpNI79IMwB9934ehcGLX2L9CeP9g0vh39ZuL/BgjNWNg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=AOL5ot312TBpsYB2SJLfmwQiP99A4RF1n5uHkWVx2KA=; b=ir0w/Czi42P2db3ahsXMpIgRs+4TTkI/N6Q2ED/tYxCGafIt1PuEaW/3/BPO93kVdU49jyKzAPjCuMFVL3jReXByl2pZ4MB15EBr7ZegGwHAhcMxQiKJxeEzEsA0xZQoaOe7GRbKUjhVkT8rt7E/Tbh1vvensEOAonT6atMrCMn42t7YPR4rS/oPCa5F9qATPeOY20IqSJXU3awg0r+uTPTTgwoGnrLSyEBUCKziMZO3zADF2AtI4xJrNtrorxg8XUJWAh66QNhRwM52ElGHESy5dqQyEb7O8M1ZlEpClhwIB1dDQKxrrTwivaPy2kh2YAAqPMDtTnu+L/4zgPGe0Q== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=sony.com; dmarc=pass action=none header.from=sony.com; dkim=pass header.d=sony.com; arc=none Received: from PUZPR04MB6316.apcprd04.prod.outlook.com (2603:1096:301:fc::7) by KL1PR0401MB4212.apcprd04.prod.outlook.com (2603:1096:820:27::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6500.25; Thu, 15 Jun 2023 03:29:13 +0000 Received: from PUZPR04MB6316.apcprd04.prod.outlook.com ([fe80::ce2d:a9dc:4955:5275]) by PUZPR04MB6316.apcprd04.prod.outlook.com ([fe80::ce2d:a9dc:4955:5275%5]) with mapi id 15.20.6455.037; Thu, 15 Jun 2023 03:29:13 +0000 From: "Yuezhang.Mo@sony.com" To: "linkinjeon@kernel.org" , "sj1557.seo@samsung.com" CC: "linux-fsdevel@vger.kernel.org" , "Andy.Wu@sony.com" , "Wataru.Aoyama@sony.com" Subject: [PATCH v1 2/2] exfat: do not zeroed the extended part Thread-Topic: [PATCH v1 2/2] exfat: do not zeroed the extended part Thread-Index: AdmfORbaqcRl7y32Sz2Kb5mg+c6LvA== Date: Thu, 15 Jun 2023 03:29:13 +0000 Message-ID: Accept-Language: zh-CN, en-US Content-Language: zh-CN X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ms-publictraffictype: Email x-ms-traffictypediagnostic: PUZPR04MB6316:EE_|KL1PR0401MB4212:EE_ x-ms-office365-filtering-correlation-id: c760dad0-9624-47eb-9125-08db6d50b0a7 x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: Hz2C5hY+kWLEUJOkdry82CeWWVDRaJoy0No3XHrYEi7FqnroBxdaXQytwe/IEpeemV1SITK6MDiHjupxp+LvDSh8gAe+AO2wf09QebWtZaliWcW8H8ha6t5zXkgihU8uN9k06xEZYeXs7X5ORVOY9tKC9FvJ/IrCKqkFwbBMigdopvI9d5x3HK2tvKlp/qEKCZbWPdTFEHEOg2wxCYJefDflYp9GLiVaqkDGA40BrM8H62KqqK4r4wJeKM9TwABWIdfgi4JZ2fMn6wGpX+qqbN5uqSsifvHN5m/kq+Ccr66nWw+wQsa8Vz1dF6TGcc/DGOYuSj0SS+9BLDGnxXFem5GPG/nVKTKHcppNXaUjs0+heOS4UhxdwIqVOZ/yAknVEIDn/ThOVgb7TKLtOJHBeBmwFCUl0kQnhqody3gDimbUpTSbhuqR7xmYtxyYkJXKUapl2ec6QT0IR8cO8YGGusoYPjYWRCeE+oYMEPTIQwO50y1G8waT1xHfbAypNeiP9wNqBjAxXSAyLuMD54lU91pwpziCLQ+syrKGELexoCbBRCkZeAikraKSt5Ou+8bsoARirzzxT2iFbrTKDGwqvimMVZmTtjeQYrXpTcsrOWTeWE1kX5aJZOBiSBlHVV+U x-forefront-antispam-report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:PUZPR04MB6316.apcprd04.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230028)(4636009)(396003)(366004)(136003)(346002)(39860400002)(376002)(451199021)(76116006)(4326008)(2906002)(86362001)(38070700005)(316002)(64756008)(66446008)(66476007)(66556008)(66946007)(41300700001)(110136005)(5660300002)(52536014)(8936002)(8676002)(54906003)(38100700002)(478600001)(122000001)(82960400001)(7696005)(71200400001)(83380400001)(107886003)(55016003)(9686003)(26005)(6506007)(186003)(33656002);DIR:OUT;SFP:1102; x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?utf-8?q?l5Bm1Fic2cmsmm85lI/5vkd5pB6x?= =?utf-8?q?+f8aC5IcfoILckAI6bGRfSYRCaOeWG3tR/zybjW5yBJHuGKEeQdc34AeIrm0Br3r9?= =?utf-8?q?5zHoBmjKRrl2TOKU1eOrn3cn545looYDRqYUuCRvUhHBvfS59+slZumN88QaTD4Km?= =?utf-8?q?gD06BSzAuCSYqHrhXEq+CEp2rqC3GytoofNUnXu/uouSh7fB5UbJQ4lpyP1dwaFDP?= =?utf-8?q?+i6dYQV4egHjBhOVEvQf1USMAj3WLTzNczcRlTXt2mUb4loeIGGfsRAFp5tEuh5aA?= =?utf-8?q?4ZIx4Z5h/VdPKU8ehoKGXg8PG22nufFGcnfqX+APw7YGzcosQt0eLSSn3ASJOY1Rn?= =?utf-8?q?D3S4THL1JfFTFPhi+k07EtgACSgxEpczrXQ1nFTZ9D72VQCW++jymnRnsv2loMy85?= =?utf-8?q?oruyeEmz4y/kGmcYKDfasRg5fsDb+Lmo4AhqE2z+/BN9UcJd7vxJ5JNDVhmxgDOTA?= =?utf-8?q?4QvgUF1yjJuKJConE/09iMwl2CswOwm1C8Nh0cxLQUt2wGsc92m8++JuKCQocBN75?= =?utf-8?q?NkZS3JgHIJVxHxhbP1lekN/Uh0gaQlgmgji1V2Po6l14VXVbfsZbK73wnQxbVLAGA?= =?utf-8?q?OLyCAKkULAhLXAULrhAo5XjT0mY3ca/98Oo5si8+qyjK/qMxjqx/Zw9oPnjH+kPVj?= =?utf-8?q?ZSqhPSF/k6b3Nknco9YEunaPvvVCNXpbM/pZ/vsKiTEoKF5M9jN7bt2g0Fxj4PLsf?= =?utf-8?q?r1cYTVhz4CWkkoszgXdF+sGDTuWUHYFakqkDlFJrjjmm0rAT1ud0ISdrLWjdOcm86?= =?utf-8?q?rOgDJPQ6f9/PL7M30p6srXRxjti4HRjZDiMpffJx0V+Lv9Nl/4dWOxXkb4TGypN7W?= =?utf-8?q?ERKqDYlOBrn6uqbgy9SxrM08mImBTBR5BTUW4tmeTJOci9kKeLtFUi8GHPHEGoSrR?= =?utf-8?q?yKlwOc3HrhEFh1F7v7uBs77Yrqy3XeC1Vwzz/uMrUykFNII44/ZOOpcagzwOQCplW?= =?utf-8?q?+Ti7dzBCAGjQlEhd/9pEiuAjGSPARfLVf152Zk+M2P1M5DM8J//0RU4e18knplSco?= =?utf-8?q?R2X58i9NQRDFqg/VMG/9x7X2LveVgnl+rI9zW8xiJ2xHstloX2rwiWiePvtoaUNcA?= =?utf-8?q?TINcEF9tyf41NDqzZBk91c4R4IdvvC2etXizQAMzJt1KgFPEYN8pUrVAFtWV30M+N?= =?utf-8?q?tBSrwllB3rt1Kn6wzku3Zor0AHamuD2FS9xSesUThnY7S0ZlmZmhzH0mdGKHcBW/v?= =?utf-8?q?Ax8udegx0XjIYEojfrJBh548KH3p2EkUOAbQtDeKvOk0EQ11v8bZoRKJ/nuHyD3KG?= =?utf-8?q?UhEvKFG6S9O5P5mMU/1FyztJRv6shUunlHEaDBjxMUR6j+Y2SUpEX0NQwM5Y/hL7K?= =?utf-8?q?KwPH99j/gFeUyCCQVP0lkhhGBUIj+SnpLIvSKyQjWBsisIMB+SqicXB2QI/mrdjxK?= =?utf-8?q?mTZF5vqDAQvoea8PnfoiqZ3XB8TIt0Dzm4OOoIIlNshZyvzEYdXzO/YuGUgaq48gY?= =?utf-8?q?Z5Y7xxzqzvbfUHZp5iXD89du8V4OhMzM3uic1xKu1hIS680zzQdmkjAfr+Wt3E581?= =?utf-8?q?CKZ5mza+7D2c?= MIME-Version: 1.0 X-MS-Exchange-AntiSpam-ExternalHop-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-ExternalHop-MessageData-0: CF4jTwv5+PENww1h7VutkIuvrXXBX/Ipt0uLH63/9ZIMnetanbwbw/IRyAN07mhi57TDQcZM8562brtIBiMbIhBv/QekmrDcrgRQmPUeY7vmI1mScV+7iLCIIUt1Ih8Vk5zGdTsZxt5utcIGy46JP/rGi8lfjk9SAbVKiiHCvPc7IGZ6eAZvV6HdJNiv8PCRmPsImVNKo8b2rKX+Z4WvGtHxTAjeFSMia69MzvCVLs6BZ+d+02YVtvhobvVbRVsn497JWSvEj176AVNSSUzUJNhce1e3YbJelN0VYezrLobRQC6DTqdKXgJHMk2/0+vuZLM8VJhwW17MLPkOR6kaYEP0iJPB64TaDDT2BZmMhMOIIawo/KplRrRGw2sousQ0pesGTaTgH6BpMPXoipSKskQ96NbGc7yb+u/NZYTeNclS1rLCSOCKiHOxNVgeDIH/R3u6oT21RORFfOcDYVlHmVRssJV0vYDFq+Gs038bCjM+hZDAfV8xMGoLl49JCiYT3JgPzr65H68BrKJa5dZTE034ner/oznPE7MH3C5KRwtNd0Ql8gyYITtJWctkOhMBrjOYybzrpgsyzXsaDhPCq6EWv3K2UbeUrLBtfIygnqfKs1sWNqLzVjKFevB1/bqo5PY15b/qAOLwv7fYKj4VFhCRvZH8D7Cyi9wAhQGAX0MjMimr6PODNbpMJkW4z502kl+PA5LDkIr1/z+s8F2tnVrLOIVInblfLEVjANjTJmyglwC9PnaWq0V7K2rGaD8VZT8D5alCJieDF9d1syCoM/i2q9PBTlxpEo7EcI/QBG8M+bvkUZ2V3P4yZSsJzDmhhMCNChTg1hLpvIZu3Vi7ow== X-OriginatorOrg: sony.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: PUZPR04MB6316.apcprd04.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: c760dad0-9624-47eb-9125-08db6d50b0a7 X-MS-Exchange-CrossTenant-originalarrivaltime: 15 Jun 2023 03:29:13.1447 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 66c65d8a-9158-4521-a2d8-664963db48e4 X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: eLR+tEfUBwh8BwWV25YXFmEsYv3ZgEmn3ANvGjgRz5dowVVE2yrkG4tAgikiGQcG0jFj6Lxr2vMcFzm77NV2eA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: KL1PR0401MB4212 X-Proofpoint-ORIG-GUID: kqguvwZoEGSWlj_8xLfsZKbPQX2LoqHS X-Proofpoint-GUID: kqguvwZoEGSWlj_8xLfsZKbPQX2LoqHS X-Sony-Outbound-GUID: kqguvwZoEGSWlj_8xLfsZKbPQX2LoqHS X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.254,Aquarius:18.0.957,Hydra:6.0.573,FMLib:17.11.176.26 definitions=2023-06-14_14,2023-06-14_02,2023-05-22_02 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Since the read operation beyond the ValidDataLength returns zero, if we just extend the size of the file, we don't need to zero the extended part, but only change the DataLength without changing the ValidDataLength. Signed-off-by: Yuezhang Mo Reviewed-by: Andy Wu Reviewed-by: Aoyama Wataru --- fs/exfat/file.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 78 insertions(+), 3 deletions(-) diff --git a/fs/exfat/file.c b/fs/exfat/file.c index 680597f3237d..3daf31a4b0ab 100644 --- a/fs/exfat/file.c +++ b/fs/exfat/file.c @@ -13,7 +13,7 @@ #include "exfat_raw.h" #include "exfat_fs.h" -static int exfat_cont_expand(struct inode *inode, loff_t size, bool sync) +static int exfat_expand_and_zero(struct inode *inode, loff_t size, bool sync) { struct address_space *mapping = inode->i_mapping; loff_t start = i_size_read(inode), count = size - i_size_read(inode); @@ -43,6 +43,81 @@ static int exfat_cont_expand(struct inode *inode, loff_t size, bool sync) return filemap_fdatawait_range(mapping, start, start + count - 1); } +static int exfat_expand(struct inode *inode, loff_t size) +{ + int ret; + unsigned int num_clusters, new_num_clusters, last_clu; + struct exfat_inode_info *ei = EXFAT_I(inode); + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct exfat_chain clu; + + ret = inode_newsize_ok(inode, size); + if (ret) + return ret; + + num_clusters = EXFAT_B_TO_CLU_ROUND_UP(i_size_read(inode), sbi); + new_num_clusters = EXFAT_B_TO_CLU_ROUND_UP(size, sbi); + + if (new_num_clusters == num_clusters) + goto out; + + exfat_chain_set(&clu, ei->start_clu, num_clusters, ei->flags); + ret = exfat_find_last_cluster(sb, &clu, &last_clu); + if (ret) + return ret; + + clu.dir = (last_clu == EXFAT_EOF_CLUSTER) ? + EXFAT_EOF_CLUSTER : last_clu + 1; + clu.size = 0; + clu.flags = ei->flags; + + ret = exfat_alloc_cluster(inode, new_num_clusters - num_clusters, + &clu, IS_DIRSYNC(inode)); + if (ret) + return ret; + + /* Append new clusters to chain */ + if (clu.flags != ei->flags) { + exfat_chain_cont_cluster(sb, ei->start_clu, num_clusters); + ei->flags = ALLOC_FAT_CHAIN; + } + if (clu.flags == ALLOC_FAT_CHAIN) + if (exfat_ent_set(sb, last_clu, clu.dir)) + goto free_clu; + + if (num_clusters == 0) + ei->start_clu = clu.dir; + +out: + inode->i_ctime = inode->i_mtime = current_time(inode); + /* Expanded range not zeroed, do not update valid_size */ + i_size_write(inode, size); + + ei->i_size_aligned = round_up(size, sb->s_blocksize); + ei->i_size_ondisk = ei->i_size_aligned; + inode->i_blocks = round_up(size, sbi->cluster_size) >> 9; + + if (IS_DIRSYNC(inode)) + return write_inode_now(inode, 1); + + mark_inode_dirty(inode); + + return 0; + +free_clu: + exfat_free_cluster(inode, &clu); + return -EIO; +} + +static int exfat_cont_expand(struct inode *inode, loff_t size) +{ + if (mapping_writably_mapped(inode->i_mapping)) + return exfat_expand_and_zero(inode, size, IS_SYNC(inode)); + + return exfat_expand(inode, size); +} + static bool exfat_allow_set_time(struct exfat_sb_info *sbi, struct inode *inode) { mode_t allow_utime = sbi->options.allow_utime; @@ -256,7 +331,7 @@ int exfat_setattr(struct mnt_idmap *idmap, struct dentry *dentry, if ((attr->ia_valid & ATTR_SIZE) && attr->ia_size > i_size_read(inode)) { - error = exfat_cont_expand(inode, attr->ia_size, IS_SYNC(inode)); + error = exfat_cont_expand(inode, attr->ia_size); if (error || attr->ia_valid == ATTR_SIZE) return error; attr->ia_valid &= ~ATTR_SIZE; @@ -444,7 +519,7 @@ static ssize_t exfat_file_write_iter(struct kiocb *iocb, struct iov_iter *iter) goto unlock; if (pos + count > size) { - ret = exfat_cont_expand(inode, pos + count, false); + ret = exfat_expand_and_zero(inode, pos + count, false); if (ret < 0) goto unlock; }