From: "Sungjong Seo" <sj1557.seo@samsung.com>
To: <Yuezhang.Mo@sony.com>, <linkinjeon@kernel.org>
Cc: <linux-fsdevel@vger.kernel.org>, <Andy.Wu@sony.com>,
<Wataru.Aoyama@sony.com>, <cpgs@samsung.com>,
<sj1557.seo@samsung.com>
Subject: RE: [PATCH v4 1/2] exfat: change to get file size from DataLength
Date: Tue, 28 Nov 2023 18:21:03 +0900 [thread overview]
Message-ID: <1296674576.21701163681829.JavaMail.epsvc@epcpadp4> (raw)
In-Reply-To: <PUZPR04MB631680D4803CEE2B1A7F42F381A6A@PUZPR04MB6316.apcprd04.prod.outlook.com>
> 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 <Yuezhang.Mo@sony.com>
> Reviewed-by: Andy Wu <Andy.Wu@sony.com>
> Reviewed-by: Aoyama Wataru <wataru.aoyama@sony.com>
> ---
> fs/exfat/exfat_fs.h | 2 +
> fs/exfat/file.c | 122 +++++++++++++++++++++++++++++++++++++++++++-
> fs/exfat/inode.c | 96 ++++++++++++++++++++++++++++------
> fs/exfat/namei.c | 6 +++
> 4 files changed, 207 insertions(+), 19 deletions(-)
[snip]
> +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(%ld)",
> + 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 && iocb_is_dsync(iocb)) {
> + ssize_t err = vfs_fsync_range(file, valid_size, pos - 1,
> + iocb->ki_flags & IOCB_SYNC);
If there is a hole between valid_size and pos, it seems to call sync twice.
Is there any reason to call separately?
Why don't you call the vfs_fsync_range only once for the merged scope [valid_size:end]?
> + if (err < 0)
> + return err;
> + }
> +
> + if (ret)
> + ret = generic_write_sync(iocb, ret);
> +
> + return ret;
> +
> +unlock:
> + inode_unlock(inode);
> +
> + return ret;
> +}
> +
[snip]
> @@ -75,8 +75,7 @@ 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.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);
> @@ -85,6 +84,8 @@ int __exfat_write_inode(struct inode *inode, int sync)
> ep2->dentry.stream.start_clu = EXFAT_FREE_CLUSTER;
> }
>
> + ep2->dentry.stream.valid_size = cpu_to_le64(ei->valid_size);
Is there any reason to not only change the value but also move the line down?
> +
> exfat_update_dir_chksum_with_entry_set(&es);
> return exfat_put_dentry_set(&es, sync); } @@ -306,17 +307,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;
> + }
> +
You removed the code for handling the case for (iblock < last_block).
So, under all write call-flows, it could be buffer_new abnormally.
It seems wrong. right?
> err = exfat_map_new_buffer(ei, bh_result, pos);
> if (err) {
> exfat_fs_error(sb,
[snip]
> @@ -436,8 +485,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);
> + }
This approach causes unnecessary reads to the range after valid_size, right?
But it looks very simple and clear.
Hum...
Do you have any plan to handle the before and after of valid_size separately?
next prev parent reply other threads:[~2023-11-28 9:28 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <CGME20231102095908epcas1p12f13d65d91f093b3541c7c568a7a256b@epcas1p1.samsung.com>
2023-11-02 9:58 ` [PATCH v4 1/2] exfat: change to get file size from DataLength Yuezhang.Mo
2023-11-27 0:11 ` Namjae Jeon
2023-11-28 6:55 ` Yuezhang.Mo
2023-11-28 9:21 ` Sungjong Seo [this message]
[not found] ` <PUZPR04MB6316FB0EDA2C6B92617CD4538183A@PUZPR04MB6316.apcprd04.prod.outlook.com>
2023-11-29 7:24 ` Yuezhang.Mo
2023-11-29 8:50 ` Sungjong Seo
2023-11-30 2:45 ` Yuezhang.Mo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1296674576.21701163681829.JavaMail.epsvc@epcpadp4 \
--to=sj1557.seo@samsung.com \
--cc=Andy.Wu@sony.com \
--cc=Wataru.Aoyama@sony.com \
--cc=Yuezhang.Mo@sony.com \
--cc=cpgs@samsung.com \
--cc=linkinjeon@kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.