From patchwork Tue Dec 5 10:16:27 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: 13479883 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=sony.com header.i=@sony.com header.b="nQHqZI1v" Received: from mx08-001d1705.pphosted.com (mx08-001d1705.pphosted.com [185.183.30.70]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A7C9F170B for ; Tue, 5 Dec 2023 02:16:49 -0800 (PST) Received: from pps.filterd (m0209319.ppops.net [127.0.0.1]) by mx08-001d1705.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 3B56Qawh013397; Tue, 5 Dec 2023 10:16:36 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sony.com; h=from : to : cc : subject : date : message-id : references : in-reply-to : mime-version : content-type : content-transfer-encoding; s=S1; bh=XYERbMOHgZgZDWwdeNt+LmB8iB+nd26oRVMFfd9kXvA=; b=nQHqZI1vN7f9AyQSPGtVAVto+Tbp4IGXF3DEi6E2cMA+qTE0EgaCRYlgY1oxBnvmm80y E2+9OTZOz+1yXJVojPDvw9TIaDlGZxmDvQ3a9sp9q6Yujnt+g75+N3E98FBKlWN7jEO2 twjL+mFiiTJ6KPj1kLVHEOsJdIq2ERzAmUHBh9V4lmkz4nSTmo9EEIyZrzKqGN+PBVoi wDYDnqo8DoVGisNRFJiXKoDKVOkcdUIHzmnR5w3BNVQUVEQZaoEZXWztiT/MW6ai13Sg zxwlQXEczotsGYqfnyiUdRqJL/61yzLAT/uZYj9H6P+Z4mM0ApiscSgHnKqggbKruKbZ ng== Received: from apc01-tyz-obe.outbound.protection.outlook.com (mail-tyzapc01lp2041.outbound.protection.outlook.com [104.47.110.41]) by mx08-001d1705.pphosted.com (PPS) with ESMTPS id 3uqvytjnux-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 05 Dec 2023 10:16:35 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=igPY/MXEacaDruh/L//kRitV7bSYOp3htc4hNlLwEFIGDNEvAQBfIHxFIKPjP8n4E3F57ZANuzz+GqaQcZ4eCXKkERYuOFRmixNbBrCRpgwARkSRHN99KJT7SzJc7IZw+Eacb21T3XzCzhk2uQzF/1uWv29UcTSB84No3hUbL1qFsA1uwRR3RjRkC41mAW8rmKjZRl9Ma3qox86IuSE3pHQrqvc59plfezsbH3/StqkcgNpGXCTLo4chctZraV0KAA5zsiZsl/1zyU6negX72Lx/vrq0CJ8HebKdyH7Q75bvVnTYvthQFf8ZR8JmZ4ZCk6ZussO0nRtrfon7ZH8o3g== 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=XYERbMOHgZgZDWwdeNt+LmB8iB+nd26oRVMFfd9kXvA=; b=BhfqWNIcPLC76j5WmlwLnMRD3J+4wFrwTgIwfnAJBY1m1ZbCLgcvQUH8dLw63FXKpWOzTQ1vJXB6ZsnyXh0lFmIEYM9rKs+46daScfCdQRfIihsnNGSrcj53CXCf/fnwVJC/f3BpldSMsFYups96299z2wt2oiGvsOc3D0xtbH6O/t0eHO8YLSap5aun3qqydKQYXboaN0lunCFYD6PWWK54g4BLlHSQLyFIDhYWzighiM2Pr3SN0OnREEAPE59HqzrZ26+f2XShIy7ZMKKFAujl8RkF8A8sun9Ma9KcF8M4BG2AFa7zmN9CrUcai6Hb7qzEs4LAtWeRBwNB5dZwYA== 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 TY0PR04MB5633.apcprd04.prod.outlook.com (2603:1096:400:1ae::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7046.34; Tue, 5 Dec 2023 10:16:28 +0000 Received: from PUZPR04MB6316.apcprd04.prod.outlook.com ([fe80::2fd0:f20f:14a9:a95a]) by PUZPR04MB6316.apcprd04.prod.outlook.com ([fe80::2fd0:f20f:14a9:a95a%4]) with mapi id 15.20.7046.034; Tue, 5 Dec 2023 10:16:27 +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" , "cpgs@samsung.com" , Dan Carpenter Subject: [PATCH v6 1/2] exfat: change to get file size from DataLength Thread-Topic: [PATCH v6 1/2] exfat: change to get file size from DataLength Thread-Index: AQHaJ2QbZwnpliBo30q9nKENpufiDg== Date: Tue, 5 Dec 2023 10:16:27 +0000 Message-ID: References: In-Reply-To: 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_|TY0PR04MB5633:EE_ x-ms-office365-filtering-correlation-id: 42b90f35-900d-4ba6-bbf0-08dbf57b3e54 x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: 0Ktn3LvRzVMZVX8FjtnjQ9AzME6aCogzaAlZSGe+EopjFJKlNqnRVvc/Yn303wfKaZRaJIFhxgom6KZCEwXTICIWKTEYYiS9GbQivS6bixbXq2z/68y54N5ZNCpoVbv5CGgpEXx5aW6ZdYi77UhbdqRIpW2W6rwwVcmlEOVTPhN1Q9w4MZg/eIkbRemNjTf3oBAmZK+GkwuXkto71k94sSsC+UWiX//WW3v0vcajzKnCGkSCqypjgnT7RVsEY6lMTLs7dAIZ6mPSqcLSwcoaYoA17u7xQx8X8STD7OLcMxHsWQSLe0n+evrarJnrM0U8UQ7D64HHsR55eDRyiZ/deov3pcs/Ef/TAFgxiueYsQtUxn0bgiadJFRO84a563NyUgY4ckkHZi67JDWQWYJJP86TV5lF3+REG4KkY/J525dr9K4TMddajl7kEpofGlRt6OK+lsPRaPAYOUolMJYWXKkDobchwNIHfitYIRZepC9jy7nadvxHNu+3GPHGrHyAyK+fOn7+yOzr+YSfCgRy9HC4sAcZP8qYYjrFzjvUFBpIumdm1tZpeCAiFqCAPrW0NnQZuu4SzWel29GkuRXQkh0GhrDLrSbWkbZrOILPRu66XBoBTabeyXCQeBGgmr95 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:(13230031)(376002)(39860400002)(346002)(396003)(366004)(136003)(230922051799003)(64100799003)(186009)(1800799012)(451199024)(76116006)(110136005)(122000001)(83380400001)(71200400001)(478600001)(6506007)(7696005)(82960400001)(66446008)(38100700002)(8936002)(8676002)(4326008)(66556008)(54906003)(66476007)(64756008)(316002)(9686003)(55016003)(26005)(66946007)(86362001)(52536014)(5660300002)(2906002)(30864003)(41300700001)(38070700009)(33656002);DIR:OUT;SFP:1102; x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?utf-8?q?s6eeytFRmY7plhbjPFOviZusbxzA?= =?utf-8?q?l4BJb778IAQw+ZkqDWRB1v6Y6ISj6tzrIxSsp2vIiF/LpklEV0QEMlWBqr9i7tTq8?= =?utf-8?q?oOM54Gk0YxoKeRPNaNrozqXiI0vhyw5LLBrueuwmBMTIwY784k5Wisd7dGGm5i6tO?= =?utf-8?q?Ww7TKR1xaEMGWYrn2JXkt5pEboDLqLCHYLO6q4JyJONLTzX6r2x2Hi51b3LAwhFJX?= =?utf-8?q?bZsBCg4tVTzhZjNREGf+VMysuFp2Y4Vt0fvHpskWS7xA42gfLdEO1De4/vqeF20S1?= =?utf-8?q?GnF8mflUqSrCLDJ8Yk+0/9rwsTA9tlq0cQz5hm3jhWOcuIgJOZsYPjjZVvm+QeTZ4?= =?utf-8?q?Ts+Yzg75yCMs7TnA7giocl39Y/tgs0eZnhD2/pet/AdjKZAo6VfD7Giup+ozqW9Ek?= =?utf-8?q?uyKxZ0GlNg+kF5sWJsvjMAR3k4IAEmn7QtRmsyHDuhOMaT0GmwImqxqAxWDM44+XN?= =?utf-8?q?QRFFVfAKW318jqvdX3W4lKKA9jvwqnVi/VtHwbYwH3RW3BIJxh78+y/OszWIVFpfL?= =?utf-8?q?W4qGa1S1tdvRg99VtvnyXnwZqbowB0VOEZHuxpVCvrPhvsUzLxZh/Cj/XlDkG3mF5?= =?utf-8?q?0oDZQqtuCO/fFHiUWBIR3dGlL964EIC+ownVSQbG8q21i0ileEE9xVP+Up49Ks3Ax?= =?utf-8?q?YHtWu65OQgu34Ttu0qumE2KeieMGCiG2eKz+WaEfMe/iqyOwRa+lGWfk/mFl/7ptf?= =?utf-8?q?KPBr7orS79XT8LBLUcLaiXx2UajJR9XEztfvHUX75UHb/XOpRIRfOBR9EwSFm26u7?= =?utf-8?q?45SQH+VisrpuZiH0EkgUFnO0ObqTFMZ9j8OeD4BmxZFVw1bT7s0HdWt1HFdvseo8X?= =?utf-8?q?mGmnwRNSD/X04MhWi3674mRGLekgeTTvlITanwuLH+Ep2YV4i5mPKnfemc7EE//gZ?= =?utf-8?q?7pMZ23FJdyMMtN7OemTGkni7MVjtZ8GulRlz8n2Udagw7PRew5xO12B74tM41bM25?= =?utf-8?q?G/hvaICDNTLR+60a6UP4EZm+BbPJq2y6a4ordXki9/O6KEgnOyX3oBJLAHZ4+S3mp?= =?utf-8?q?iZVEiHOINow0JXIPthiEF7nwAZsRK/ithZ5TJKIsqcukkSovCFi75EHGfODs26jWx?= =?utf-8?q?f6zXBSypNGmQRl/+tA9loPySpGHwbfDvmzL6SWSYSazc7llcikQ0ppahXARwYR1ua?= =?utf-8?q?Yk4F4Gy560mfc22fgCNO4rOWG9BTBwEsYDeSQbU+2C0AB9pq6OK4i9KyHUm1ugU/4?= =?utf-8?q?JJq65OK53e6zLpTaF4KK8MjSXrKOvC6KOYSlCDG1jbppN4+vYlsJerhpFXJXtc/pk?= =?utf-8?q?bgrAupqIgSwKWzLZAVtUVWk7xBPIKDCtM8y3jAYO7qUnm80LW1e9CCDyZ7eLYUkhO?= =?utf-8?q?onEqZFUfrv2CfGr+PvS+MycCr7+aeVYSWdbwz7MGFRSYMcVk1xDMEbh1yCaZ0H4qe?= =?utf-8?q?2mkXH+ngfHXNPvEzzTr4drZjRyAFowPCt+MBWHruibcjFbIdVht5fFad1BjKz6UjG?= =?utf-8?q?bHw+7r8M2G3iH02cBMHX4ZLsVYzrLfR2vzKql8+U8d0TRWyz2+uVM16TvNvbS3D5d?= =?utf-8?q?vxwthCDF1uxe?= Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-Exchange-AntiSpam-ExternalHop-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-ExternalHop-MessageData-0: m6kOEFj4pgGp6b/eZgrDo950gxxnkBR4N4QVNBn28aYWDVUSK05tLdSZPm65h7KdI+IWs8yz7Xw7uM8dVtT1qiggd38+RCRn9Sh4nCht4jUfeAnwk3AzpNTzql7AZhUYEsJVIqZB17+GgPpzUdTFKJKbasjSkmoMPSpv6STiQyMjpUhOGxU1RCDA3wp86tWKsHHhUaIfZL5StbTOCjwfNPp6Y/OTfF3SAYVH7WVwPH/gd9jfpezcvOlvaKBTlaf/4vfimTByygx/5pV5fWrWMoYfyxiIlhkt0RXxsL120YbLleaoaoLO/MA06FL7W6tf+AO0gIf86WR8lEJtmWn3fWnVgsY49R0l0iKFS+nkCzLJpI150hcDahkg3ZXcUmffgJbDVefJZkDoeMOVmNpKOfcjI8ibkA6B4u6pdDvYKDuBIYTDkQ9is5O1AdkHJO8fJfWQg8jUXTnMdWDCa/2uuyQfkkCN72brNYPLf58PH0GWrlmxIxwwPD394hYjMhdL9IHybJeONtysVNDRyW+PgBVN7SrP1A8hVSnaaL/++GVtYbir1ckJbJ+xsHWL6sAaH81WIlsR6GT3on1nIgYiq7AbA1qU52uqIv2ny614lETOLOwIBHtwsRri6l2cOF4UddPOoeReGSgu4+agGqHy1fXStwL2nDKgtdh/cIjQZJe651uNv4+Vf2zsYmXCUlsNxWSrKCxZ1/rFAuFem6o8V0XCM8Z74uv14kxflh94Pp5qOlall/xkfvCD0xQ3j83AryPksjkNcN9f5ZildUYOY9j1/m7uKa+P+BPkJB5FLnk7E+EDv9R6Noy2eSh2iTP4TVjqzI/dBUjPHb4//NEUf7JQ57x4n9RZxXZ76NGS2fKrPgBO1i2eYupG2Y+uq2eW 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: 42b90f35-900d-4ba6-bbf0-08dbf57b3e54 X-MS-Exchange-CrossTenant-originalarrivaltime: 05 Dec 2023 10:16:27.8494 (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: Ti77zojOCuin/W2UBlVPHFcxFdbE6Jt8TmIopGr+dTuTVkgh+GrR+koneJqnfK7os/FDXFjDOU7xznDGfe1ZRw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: TY0PR04MB5633 X-Proofpoint-GUID: EfsI7DZk9uD2akoj5FGVQYLTANQCQvmr X-Proofpoint-ORIG-GUID: EfsI7DZk9uD2akoj5FGVQYLTANQCQvmr X-Sony-Outbound-GUID: EfsI7DZk9uD2akoj5FGVQYLTANQCQvmr X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.997,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-12-05_04,2023-12-05_01,2023-05-22_02 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 | 118 ++++++++++++++++++++++++++++++++++++++++- fs/exfat/inode.c | 124 ++++++++++++++++++++++++++++++++++++++------ fs/exfat/namei.c | 6 +++ 4 files changed, 231 insertions(+), 19 deletions(-) diff --git a/fs/exfat/exfat_fs.h b/fs/exfat/exfat_fs.h index a7a2c35d74fb..e3b1f8e022df 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 bfdfafe00993..270e2f934124 100644 --- a/fs/exfat/file.c +++ b/fs/exfat/file.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "exfat_raw.h" #include "exfat_fs.h" @@ -26,6 +27,7 @@ static int exfat_cont_expand(struct inode *inode, loff_t size) return err; inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode)); + EXFAT_I(inode)->valid_size = size; mark_inode_dirty(inode); if (!IS_SYNC(inode)) @@ -146,6 +148,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 |= EXFAT_ATTR_ARCHIVE; @@ -474,15 +479,124 @@ 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 address_space *mapping = inode->i_mapping; + const struct address_space_operations *ops = mapping->a_ops; + + while (start < end) { + u32 zerofrom, len; + struct page *page = NULL; + + 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(); + } + +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; + + inode_lock(inode); + + valid_size = ei->valid_size; + + ret = generic_write_checks(iocb, iter); + if (ret < 0) + goto unlock; + + if (pos > valid_size) { + ret = exfat_file_zeroed_range(file, valid_size, pos); + if (ret < 0 && ret != -ENOSPC) { + exfat_err(inode->i_sb, + "write: fail to zero from %llu to %llu(%zd)", + valid_size, pos, ret); + } + if (ret < 0) + goto unlock; + } + + ret = __generic_file_write_iter(iocb, iter); + if (ret < 0) + goto unlock; + + inode_unlock(inode); + + if (pos > valid_size) + pos = valid_size; + + if (iocb_is_dsync(iocb) && iocb->ki_pos > pos) { + ssize_t err = vfs_fsync_range(file, pos, iocb->ki_pos - 1, + iocb->ki_flags & IOCB_SYNC); + if (err < 0) + return err; + } + + return 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 = filemap_splice_read, .splice_write = iter_file_splice_write, diff --git a/fs/exfat/inode.c b/fs/exfat/inode.c index e7ff58b8e68c..b02677c9fd45 100644 --- a/fs/exfat/inode.c +++ b/fs/exfat/inode.c @@ -75,8 +75,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); @@ -278,6 +278,7 @@ static int exfat_get_block(struct inode *inode, sector_t iblock, unsigned int cluster, sec_offset; sector_t last_block; sector_t phys = 0; + sector_t valid_blks; loff_t pos; mutex_lock(&sbi->s_lock); @@ -306,17 +307,32 @@ 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) { + valid_blks = EXFAT_B_TO_BLK_ROUND_UP(ei->valid_size, sb); + + if (iblock + max_blocks < valid_blks) { + /* The range has been written, map it */ + goto done; + } else if (iblock < valid_blks) { + /* + * The range has been partially written, + * map the written part. + */ + max_blocks = valid_blks - iblock; + goto done; + } + + /* The area has not been written, map and mark as new. */ err = exfat_map_new_buffer(ei, bh_result, pos); if (err) { exfat_fs_error(sb, @@ -324,11 +340,55 @@ static int exfat_get_block(struct inode *inode, sector_t iblock, pos, ei->i_size_aligned); goto unlock_ret; } + } else { + valid_blks = EXFAT_B_TO_BLK(ei->valid_size, sb); + + if (iblock + max_blocks < valid_blks) { + /* The range has been written, map it */ + goto done; + } else if (iblock < valid_blks) { + /* + * The area has been partially written, + * map the written part. + */ + max_blocks = valid_blks - iblock; + goto done; + } else if (iblock == valid_blks && + (ei->valid_size & (sb->s_blocksize - 1))) { + /* + * The block has been partially written, + * zero the unwritten part and map the block. + */ + loff_t size, off; + + max_blocks = 1; + + /* + * For direct read, the unwritten part will be zeroed in + * exfat_direct_IO() + */ + if (!bh_result->b_folio) + goto done; + + pos -= sb->s_blocksize; + size = ei->valid_size - pos; + off = pos & (PAGE_SIZE - 1); + + folio_set_bh(bh_result, bh_result->b_folio, off); + err = bh_read(bh_result, 0); + if (err < 0) + goto unlock_ret; + + folio_zero_segment(bh_result->b_folio, off + size, + off + sb->s_blocksize); + } else { + /* + * The range has not been written, clear the mapped flag + * to only zero the cache and do not read from disk. + */ + clear_buffer_mapped(bh_result); + } } - - if (buffer_delay(bh_result)) - clear_buffer_delay(bh_result); - map_bh(bh_result, sb, phys); done: bh_result->b_size = EXFAT_BLK_TO_B(max_blocks, sb); unlock_ret: @@ -343,6 +403,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); } @@ -370,9 +441,7 @@ static int exfat_write_begin(struct file *file, struct address_space *mapping, int ret; *pagep = NULL; - ret = cont_write_begin(file, mapping, pos, len, pagep, fsdata, - exfat_get_block, - &EXFAT_I(mapping->host)->i_size_ondisk); + ret = block_write_begin(mapping, pos, len, pagep, exfat_get_block); if (ret < 0) exfat_write_failed(mapping, pos+len); @@ -400,6 +469,11 @@ static int exfat_write_end(struct file *file, struct address_space *mapping, if (err < len) exfat_write_failed(mapping, pos+len); + if (!(err < 0) && pos + err > ei->valid_size) { + ei->valid_size = pos + err; + mark_inode_dirty(inode); + } + if (!(err < 0) && !(ei->attr & EXFAT_ATTR_ARCHIVE)) { inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode)); ei->attr |= EXFAT_ATTR_ARCHIVE; @@ -413,6 +487,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; @@ -436,8 +512,21 @@ 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; + + /* zero the unwritten part in the partially written block */ + 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; } @@ -537,6 +626,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 5d737e0b639a..9c549fd11fc8 100644 --- a/fs/exfat/namei.c +++ b/fs/exfat/namei.c @@ -406,6 +406,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; } @@ -558,6 +559,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)); @@ -660,6 +663,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->size == 0) { info->flags = ALLOC_NO_FAT_CHAIN; info->start_clu = EXFAT_EOF_CLUSTER; @@ -1288,6 +1293,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 Tue Dec 5 10:16:31 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: 13479882 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=sony.com header.i=@sony.com header.b="VQolO8gd" Received: from mx08-001d1705.pphosted.com (mx08-001d1705.pphosted.com [185.183.30.70]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3D07E1707 for ; Tue, 5 Dec 2023 02:16:49 -0800 (PST) Received: from pps.filterd (m0209319.ppops.net [127.0.0.1]) by mx08-001d1705.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 3B56Qawi013397; Tue, 5 Dec 2023 10:16:37 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sony.com; h=from : to : cc : subject : date : message-id : references : in-reply-to : mime-version : content-type : content-transfer-encoding; s=S1; bh=ITZgvUeR24PxtiCoVh5bk7z35mnk8a/6uDYKvWct7BY=; b=VQolO8gdPbQrRhKvYzamcQPKJbeDgHqxbnyisMFlvDJzFKh3RfnZ2xtqUkZVtZTZCuPW eXakaOYbBKGc31m/lXVK0P7MONwVh2aO73AnB/zDdNPBcALvDFXTwsgEcyyxFb8khj9S pjEXCqIBD8GjGWmo17UioUurMM9+CNvQONw+0sVTwQQJIPOwOBEc5yQX1fxVSUmJ+KXW PCK6Ah93KD4i2PS+H2QFibrx/G4hlariNEHnm/BdbLGogczyikpL3+Devoigniz/1Io+ BcBMo2gF98uEXFkrPTl3fGOp+PDhmVTVVGCGQni1IKZ0j20mQecpiZCM5fdpX28qMliS sA== Received: from apc01-tyz-obe.outbound.protection.outlook.com (mail-tyzapc01lp2041.outbound.protection.outlook.com [104.47.110.41]) by mx08-001d1705.pphosted.com (PPS) with ESMTPS id 3uqvytjnux-2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 05 Dec 2023 10:16:36 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=jdfDZjrjxgMR7i1r0fFitlb/QW5OwfoUb6u0SJm3dRm3jCDzytsgOGovq0Sf2KeBzvqRt37H9WMAxaT4SmHCYsB+ZYvjMR4R8ZlUGCzVfPDpQo7b6xpllJG1gZRKg5vCdMWtR0xI5g81QWPNe4OyNRiT6Gw6oGfpd6ipXOFAQx5iTNlC5ItFvS1s+Os6GeT7DNQz2Q68YDouHY5zgbCor+tDj0SrI5k5BvlxABv+1PHvxA+yASLcyyAnm0qmt6f+W+GvKHjmPT9USiQT9wORYcWW3p8jjZzXZfsh3VGxLlWfW/US3mOtr+7FfNXVmP9tBqMA+HEt3g8VS2BkLLMmJA== 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=ITZgvUeR24PxtiCoVh5bk7z35mnk8a/6uDYKvWct7BY=; b=RuL7Ezcomlr/x8aDi48D4CekmKIwneIMs8vNbJfERZ2B4qAvLnyRjJ80tepHpUUUToGaCUjTElzfcpsHgLWz4Iscq2Q106Q5EWFlHW+BejcznOh+knuRpRwOi1eB5K/FRAp5QkcW5J6dnVNSulcyXPW1YuoMEE8BqE7SxlZstCMqEI5LJ0OEltEXxC2w9gKC1cYwal1yvbb1BTd9zNIo9lbLqZizw8p8MVsWmdJAR/bfLAVRoNGyKjM1y5DiovWV9awS2gJM8us42Vf0SunPonPVPHV2R9V5nJEexDy1NACmI87zw+pkd63w6ULdBRSkzKnuvciq3LcByb2URB0czQ== 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 TY0PR04MB5633.apcprd04.prod.outlook.com (2603:1096:400:1ae::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7046.34; Tue, 5 Dec 2023 10:16:31 +0000 Received: from PUZPR04MB6316.apcprd04.prod.outlook.com ([fe80::2fd0:f20f:14a9:a95a]) by PUZPR04MB6316.apcprd04.prod.outlook.com ([fe80::2fd0:f20f:14a9:a95a%4]) with mapi id 15.20.7046.034; Tue, 5 Dec 2023 10:16:31 +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" , "cpgs@samsung.com" , Dan Carpenter Subject: [PATCH v6 2/2] exfat: do not zero the extended part Thread-Topic: [PATCH v6 2/2] exfat: do not zero the extended part Thread-Index: AQHaJ2Qdtym2rS1EE0O6pSv/WwmGAg== Date: Tue, 5 Dec 2023 10:16:31 +0000 Message-ID: References: In-Reply-To: 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_|TY0PR04MB5633:EE_ x-ms-office365-filtering-correlation-id: 80086963-2332-4d8e-20c9-08dbf57b404e x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: 26JXjnBoNVPuHz9ve9y2zZ/1r13c4q7Bo3C9VCQUc5VOS1TPaffR6pNcZn7TVgYnZOP9x1ixZR54xS+Ehc2S45EwosoZimjVyitTjaHRdwBeowHY2NQTxt8JPVPSjEsZJ589kMfDSf6q2Ma2jOeV16q/H85yC9ORkBK7bxWxH5352ToF9DDg4KI5XQXc3fU3Yhl1YfGAY9d3Sr7z9JqDrbeEVJeDUY3Sb/ByYecrGimfMayeHsqGSnuJ5uGNxuK+B00gWvu7KoUWMK75pynCXRZ8cV6cl8jOBIKooEQTjGZ1bpwqNNomrC3m1ta4rppWQpf8gsruXeJ1BG5bB0KKCdXTQ772ipnEyCwXsbyNSpv8fUc9Xt0Uad+7zySdbnQW+Uwt9xCdv/d08q9UaOADTkHDRhyjszEav0d/ckEWPfWCJNtVPYfj46D4pKqIPls3jo26Dnpyl8yk6kk4+Llo1kT6AcD6/bEVeVGCRUjhsvkZ885N6iOTssYdu2sP//6s1ddJb2k3gqH3kZwXoTZmDb0uUyhLhYnWcrHGSS6Xa1HvGWwmuR5TNTGwaVTOuLAW7VHt8uNJNKanSPzpBeTffAUlVRXXveCxeV7Kr6vSQM0FLPdoz/ZJ/teyVpuYzPqq 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:(13230031)(376002)(39860400002)(346002)(396003)(366004)(136003)(230922051799003)(64100799003)(186009)(1800799012)(451199024)(76116006)(110136005)(122000001)(83380400001)(71200400001)(478600001)(6506007)(7696005)(82960400001)(66446008)(38100700002)(8936002)(8676002)(4326008)(66556008)(54906003)(66476007)(64756008)(316002)(9686003)(55016003)(26005)(66946007)(86362001)(52536014)(5660300002)(2906002)(41300700001)(38070700009)(33656002);DIR:OUT;SFP:1102; x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?utf-8?q?eCDkSFWDg77CGkfN7gonJtjRC3qF?= =?utf-8?q?L7J0ZmD3wpXLLXKDrAndlu6bNTUAfaubYvZ2M3Uu5aseXSlVsG2j5vx912On+whl5?= =?utf-8?q?SZLtpQQ4o+dIrlWBRdVOeE290kFpSZI1CklGF1xLz11SN+hCJR2fiGkgpFrI4wJbV?= =?utf-8?q?T2yg064POqEzRlaNcU0et//C7caOVJbPDPOSWO9Usf43zLnWl1ZC3s17IA+kFxHcG?= =?utf-8?q?JDMraE54V+L3tbUesNCW/Un27r0xVqS4l1bKhZc7gEVOn28j/pXW4wQExG5bnxwl6?= =?utf-8?q?YK1KMAKjD6rVRpkxmXdZqoNTmyM8kamrRjZQQ8Qkd1Mh2HVB3nUFrZLUhpxGEhLZ/?= =?utf-8?q?95625g5/ktug1QLsRbAHbz6TeWAgVi9M3ZYXdBfkFOL67Ly0cihfOlHe7yRMEVkBz?= =?utf-8?q?8Kv33jm5oEWtoDfptMT7MYBTPDLS7TEJsAYabdlGcqcWJocq8BIq/YNbQFb8QtZSy?= =?utf-8?q?1GAHbRBB4PZUcHmuwxJvkjCZH6GJMeU/EjIl0OGoHMtBGGoudLIzLuUdGnZTqma6z?= =?utf-8?q?nTSDebZVUgQOvefywEOb1mmzPe2dHS0fEsQtYKQ7VOQ1KJ3SgO//NmyBykbu7m05U?= =?utf-8?q?BdiXgSRqqJhWLZPuqzVwM2Db6PBErFxubJALgX0IvQi+XYxLCprlfGKv9fURKeGnq?= =?utf-8?q?AaGiL/QwTPBoTlKe9PONnQsBJp4Y74rI6kKVfLNe/q8bSXC4gkmwh7MB5XY1M75Bv?= =?utf-8?q?nUhwWjgJ0vQLPnCrwSJzYkC2yoYLZfnXFgYBjPqDrXOg5okaICGSF5d/EhxE5x8sG?= =?utf-8?q?sY+7e+E45C++44luPaCve5xpksONBBeHCAmQx0xFTK0gWhYboXIDiaDTDjjbWnVbB?= =?utf-8?q?yPJGH9/Z85Z4htb+knQc1rWmMW6qYugYyX+DOkByZgo3nqlGxY7bQoBlN2o69jeLd?= =?utf-8?q?Gy8oUaPzFIPMnQxQU3UDuILhXdNh1Wb/jX/RPkPXfjeSWWC16xB9z9fdfnPSuLl8A?= =?utf-8?q?aByBBQCmsFfbnyz2JOdmh/BpBhT6mvi07whvDkfUte9kKdPoMgd9WtSVQOT/S8zg9?= =?utf-8?q?K0789bwcKc6oot0Xms/RKRuV6eFaNtPLN7+5lBnaPpij9Rc+Weu+zfdcy26PcLKRk?= =?utf-8?q?rUEtBapz3J5KSfSUZCEbyhEzvO4LkhRE3Gw/EYNHgqiSPCKnIfuCbCC5vQte3ia2d?= =?utf-8?q?5m8zJl39pvpFQKiDnmddSpO3X8TuNJnPFYnYiNOVwWNlzvcLm3CZx+bmUj303DWZd?= =?utf-8?q?i1JoiC86hBXw6MKf0QqBSm4Qs+9+cj3rSuUDe5JfVKOMN9iv2cam5vPeHxlQVTLv7?= =?utf-8?q?DF3IerkIhP9i6TKt/bYfYj0dsUhytZIS+7u4IasLDKN+aMRfjtNSZUXARJFR0twwD?= =?utf-8?q?X/+c001l3lkQwzYDb2U25LZipAjJY492Hj1OyrV6eLYeKOhbihJoe6LHyq1OkdfM3?= =?utf-8?q?XYk9bVcxrXNPAg88VSgHep11LdQn5GdalJ3b284gE0523bsbHmWw2tkc77dG1OWn4?= =?utf-8?q?od21bz8AuvgS+pGUbRjYyV4rirl131iqEUY3uGVoObNTN5ZxUo7b7jDq3CQQWb3uZ?= =?utf-8?q?h0nWyeT7B/09?= Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-Exchange-AntiSpam-ExternalHop-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-ExternalHop-MessageData-0: WTVcqTA4CJFSimLJA0dR5Spu7ugHkPXEpfMf82uXWqt4a6GQlRAfO9PaydH4CoTj5k8ZJaUW9zEGowxpglJXaBTTQ27iegRWLVl9SYYEudL7KFlxr0qj+QPlcMfdIOiHQTPSVtwmWSY1xq27Ik3jqWvJon7RZcSvv9PXCAezYIRRtNTpjUCUb8JSuZWLAO4BwfaXoNcXWFFCY+LJLGul7oKUBFI+XmRTQIOahU4v5qgcxjaXPpFmyeoDu3nrmgaqWMdkv/b35ktUY/f35V/gzGapGvK879ji9agK2FbryVvl2oA/yX8oSXFzYp+h0a20A1Z02Sp7Qc8l6C/Hl8ASiw5VBjWFYMhcIeEOMm86R0Ih7vhrgyTC+lWiZcNlOq+7HknsnDGHcgvCuvW58RQgXYZyLPWLX074HiQKuvp15+Iw0dXa+V7JTe4cOop6pEi15nnBSYC9K7fvUq9b8zQSt2AAnMYc/dh2hFJySOZDSVFS9LKbBGQ0ndb5zkcL9jnAeXmwWnFA24ekWacjRw4VqWiEirNL+00v4gf5ZaYTdCEa3+fdU5Q7eSlP7XIzLdJ6SOsvjdMP9/8p+Zvq+Aoq51ZvgneJIxGsCqE/USwuS1rWQwuI1hKp2RjpPShDeEbO6RgOm/B+ow6WoGa8Z8NW6UiCsJFIvFzygmRvGSKXpc/0tgRRj+pfBKm2O1Y4tBt4swGoPyEuiBw4QZiGMJ3I3yFu2eR29v9aBPoS6WaVdu9ond6ao/ZvB7/Dk54vL78nEuxKSWHtCT2tP095njMBuWh+eaFZwBG1tRR/wP2I3SwJrZoY9gEDNzake4D0hh1lrDtU3/LbRQtCs4em4V/Chlfwn37LQzA2SuHmXnJYtBPCEfIt/Ehp3klEmYpRwUSY 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: 80086963-2332-4d8e-20c9-08dbf57b404e X-MS-Exchange-CrossTenant-originalarrivaltime: 05 Dec 2023 10:16:31.1496 (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: ECkqXe2YBNOYlD4VoW9RX+70T8JTFjAwn8JP53CItWWjeh0xP4UOaXTFs9P6OUk7WjIQqiVkS48oNGiWKf+zxg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: TY0PR04MB5633 X-Proofpoint-GUID: cDzq66cGDkv8Z5DM9J4sxnnyT4V-sjai X-Proofpoint-ORIG-GUID: cDzq66cGDkv8Z5DM9J4sxnnyT4V-sjai X-Sony-Outbound-GUID: cDzq66cGDkv8Z5DM9J4sxnnyT4V-sjai X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.997,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-12-05_04,2023-12-05_01,2023-05-22_02 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 | 77 +++++++++++++++++++++++++++++++++++------------- fs/exfat/inode.c | 14 ++++++++- 2 files changed, 70 insertions(+), 21 deletions(-) diff --git a/fs/exfat/file.c b/fs/exfat/file.c index 270e2f934124..d25a96a148af 100644 --- a/fs/exfat/file.c +++ b/fs/exfat/file.c @@ -18,32 +18,69 @@ static int exfat_cont_expand(struct inode *inode, loff_t size) { - struct address_space *mapping = inode->i_mapping; - loff_t start = i_size_read(inode), count = size - i_size_read(inode); - int err, err2; + 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; - err = generic_cont_expand_simple(inode, size); - if (err) - return err; + ret = inode_newsize_ok(inode, size); + if (ret) + return ret; + + num_clusters = EXFAT_B_TO_CLU_ROUND_UP(ei->i_size_ondisk, 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_set_mtime_to_ts(inode, inode_set_ctime_current(inode)); - EXFAT_I(inode)->valid_size = size; - mark_inode_dirty(inode); + /* Expanded range not zeroed, do not update valid_size */ + i_size_write(inode, size); - if (!IS_SYNC(inode)) - return 0; + 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; - err = filemap_fdatawrite_range(mapping, start, start + count - 1); - err2 = sync_mapping_buffers(mapping); - if (!err) - err = err2; - err2 = write_inode_now(inode, 1); - if (!err) - err = err2; - if (err) - return err; + if (IS_DIRSYNC(inode)) + return write_inode_now(inode, 1); + + mark_inode_dirty(inode); + + return 0; - return filemap_fdatawait_range(mapping, start, start + count - 1); +free_clu: + exfat_free_cluster(inode, &clu); + return -EIO; } static bool exfat_allow_set_time(struct exfat_sb_info *sbi, struct inode *inode) diff --git a/fs/exfat/inode.c b/fs/exfat/inode.c index b02677c9fd45..522edcbb2ce4 100644 --- a/fs/exfat/inode.c +++ b/fs/exfat/inode.c @@ -75,8 +75,17 @@ 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(ei->valid_size); ep2->dentry.stream.size = cpu_to_le64(on_disk_size); + /* + * mmap write does not use exfat_write_end(), valid_size may be + * extended to the sector-aligned length in exfat_get_block(). + * So we need to fixup valid_size to the writren length. + */ + if (on_disk_size < ei->valid_size) + ep2->dentry.stream.valid_size = ep2->dentry.stream.size; + else + ep2->dentry.stream.valid_size = cpu_to_le64(ei->valid_size); + if (on_disk_size) { ep2->dentry.stream.flags = ei->flags; ep2->dentry.stream.start_clu = cpu_to_le32(ei->start_clu); @@ -340,6 +349,9 @@ static int exfat_get_block(struct inode *inode, sector_t iblock, pos, ei->i_size_aligned); goto unlock_ret; } + + ei->valid_size = EXFAT_BLK_TO_B(iblock + max_blocks, sb); + mark_inode_dirty(inode); } else { valid_blks = EXFAT_B_TO_BLK(ei->valid_size, sb);