mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: liubaolin <liubaolin12138@163.com>
To: xkeyC <xkeyc@qq.com>, Namjae Jeon <linkinjeon@kernel.org>,
	Hyunchul Lee <hyc.lee@gmail.com>
Cc: ntfs@lists.linux.dev, linux-kernel@vger.kernel.org,
	stable@vger.kernel.org
Subject: Re: [PATCH v3] ntfs: don't let a fatal signal interrupt metadata reads
Date: Fri, 13 Nov 2026 13:30:27 +0800	[thread overview]
Message-ID: <aa52e1af-d019-4eeb-ab55-628c2f25fb2c@163.com> (raw)
In-Reply-To: <tencent_BED06C76C024128D13E6854C2FC31BF48A06@qq.com>



在 2026/11/13 11:26, xkeyC 写道:
> read_mapping_folio() returns -EINTR when the caller has a fatal signal
> pending while it waits for the read it submitted. ntfs reads its metadata
> through it and treats the failure as a volume error, so killing a task
> that waits on a metadata read turns the volume read-only with
> errors=remount-ro. A read that is part of an update also stops the update
> half way: killing an rm can leave clusters allocated in $Bitmap, an MFT
> record in use without a directory entry, or a directory index with
> entries that point to freed records. Killing a mount makes it fail with
> bogus $AttrDef and $UpCase errors, or leaves the volume mounted read-only
> with a bogus $MFTMirr or $BadClus error.
> 
> Add ntfs_read_metadata_folio(), which waits for the read uninterruptibly,
> and use it for metadata reads. Named stream contents, compressed data and
> the read-only bitmap scans through ntfs_get_locked_folio(), whose callers
> do not report a volume error, keep using read_mapping_folio(). A named
> stream write that is interrupted that way no longer reports a volume
> error either. A killed task now waits for its metadata read to complete,
> as it does on filesystems that use the buffer cache.
> 
> Closes: https://github.com/namjaejeon/linux-ntfs/issues/98
> Fixes: 11ccc9107dc4 ("ntfs: update runlist handling and cluster allocator")
> Fixes: 115380f9a2f9 ("ntfs: update mft operations")
> Fixes: af0db57d4293 ("ntfs: update inode operations")
> Fixes: 495e90fa3348 ("ntfs: update attrib operations")
> Fixes: 0a8ac0c1fa0b ("ntfs: update directory operations")
> Fixes: 5218cd102aec ("ntfs: update misc operations")
> Fixes: 6251f0b0de7d ("ntfs: update super block operations")
> Fixes: 8506a8031ebf ("ntfs: validate and reserve bad clusters at mount")
> Cc: stable@vger.kernel.org
> Signed-off-by: xkeyC <xkeyc@qq.com>
> ---
> v3:
> - Keep the folio reference after the read and recheck uptodate under
>    the folio lock, instead of dropping it and looking the folio up again
>    (Baolin)
> 
> v2:
> - Keep reads of named stream contents killable in writes too, and don't
>    report -EINTR from them as a volume error (Hyunchul)
> - Also convert the mount-time reads of $LogFile, $MFTMirr, hiberfil.sys,
>    $AttrDef, $UpCase and $BadClus (Hyunchul)
> - Add the missing Fixes tags (Hyunchul)
> 
> v2: https://lore.kernel.org/ntfs/tencent_AF42E4D94D935F34EB985032150C6AD0DF08@qq.com/
> v1: https://lore.kernel.org/ntfs/tencent_2859327A0C68D0D0429ED90F931234059808@qq.com/
> 
> Reproducers and logs: https://github.com/xkeyC/linux-ntfs/tree/eintr-repro
> 
> In QEMU (KASAN, lockdep, reads throttled), killing rm, ls -l, fallocate,
> dd, a named stream write or mount partway through turned the volume
> read-only or failed the mount within a few runs without this patch, and
> ntfsck found damage after rm. With it, 20 runs of each kept the volume
> read-write and ntfsck clean. The reporter of the GitHub issue confirmed
> that v1 fixes the cases there.
> 
> Developed with an AI coding assistant (Claude Code), which wrote the
> change and the reproducers and ran the tests.
> 
>   fs/ntfs/aops.c     | 60 ++++++++++++++++++++++++++++++++++++++++++++++
>   fs/ntfs/attrib.c   |  2 +-
>   fs/ntfs/bdev-io.c  |  2 +-
>   fs/ntfs/bitmap.c   |  7 +++---
>   fs/ntfs/dir.c      |  4 ++--
>   fs/ntfs/inode.c    | 21 +++++++++++++---
>   fs/ntfs/lcnalloc.c |  2 +-
>   fs/ntfs/logfile.c  |  4 ++--
>   fs/ntfs/mft.c      | 20 ++++++++--------
>   fs/ntfs/ntfs.h     |  4 ++++
>   fs/ntfs/super.c    | 14 +++++------
>   11 files changed, 109 insertions(+), 31 deletions(-)
> 
> diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c
> index ad781674fe..f7b5c9c457 100644
> --- a/fs/ntfs/aops.c
> +++ b/fs/ntfs/aops.c
> @@ -7,6 +7,7 @@
>    * Copyright (c) 2025 LG Electronics Co., Ltd.
>    */
>   
> +#include <linux/swap.h>
>   #include <linux/writeback.h>
>   
>   #include "attrib.h"
> @@ -304,6 +305,65 @@ static int ntfs_swap_activate(struct swap_info_struct *sis,
>   			&ntfs_read_iomap_ops);
>   }
>   
> +/**
> + * ntfs_read_metadata_folio - read a metadata folio, ignoring fatal signals
> + * @mapping:	address space of the metadata inode or block device
> + * @index:	page cache index to read
> + *
> + * Like read_mapping_folio(), but the wait for the read cannot be interrupted,
> + * so a fatal signal cannot fail a metadata read in the middle of an update.
> + * The caller must not hold the lock of the folio at @index.
> + *
> + * Return: the uptodate folio with a reference held, or an ERR_PTR().
> + */
> +struct folio *ntfs_read_metadata_folio(struct address_space *mapping,
> +				       pgoff_t index)
> +{
> +	struct folio *folio;
> +	int err;
> +
> +	folio = filemap_get_folio(mapping, index);
> +	if (!IS_ERR(folio)) {
> +		if (folio_test_uptodate(folio))
> +			goto out;
> +		folio_put(folio);
> +	}
> +repeat:
> +	folio = __filemap_get_folio(mapping, index, FGP_LOCK | FGP_CREAT,
> +				    mapping_gfp_mask(mapping));
> +	if (IS_ERR(folio))
> +		return folio;
> +	/* $MFT updates clear uptodate under the folio lock, so check it locked. */
> +	if (folio_test_uptodate(folio))
> +		goto unlock;
> +
> +	/* ->read_folio() unlocks the folio when the read completes. */
> +	err = mapping->a_ops->read_folio(NULL, folio);
> +	if (err) {
> +		folio_put(folio);
> +		if (err == AOP_TRUNCATED_PAGE)
> +			goto repeat;
> +		return ERR_PTR(err);
> +	}
> +	folio_lock(folio);
> +	if (folio->mapping != mapping) {
> +		/* Truncated while the read was in flight. */
> +		folio_unlock(folio);
> +		folio_put(folio);
> +		goto repeat;
> +	}
> +	if (!folio_test_uptodate(folio)) {
> +		folio_unlock(folio);
> +		folio_put(folio);
> +		return ERR_PTR(-EIO);
> +	}
> +unlock:
> +	folio_unlock(folio);
> +out:
> +	folio_mark_accessed(folio);
> +	return folio;
> +}
> +
>   const struct address_space_operations ntfs_aops = {
>   	.read_folio		= ntfs_read_folio,
>   	.readahead		= ntfs_readahead,
> diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c
> index 800e53df57..cf73fa4c33 100644
> --- a/fs/ntfs/attrib.c
> +++ b/fs/ntfs/attrib.c
> @@ -2323,7 +2323,7 @@ int ntfs_attr_set(struct ntfs_inode *ni, s64 ofs, s64 cnt, const u8 val)
>   
>   	index = ofs >> PAGE_SHIFT;
>   	while (cnt) {
> -		folio = read_mapping_folio(mapping, index, NULL);
> +		folio = ntfs_read_metadata_folio(mapping, index);
>   		if (IS_ERR(folio)) {
>   			ret = PTR_ERR(folio);
>   			ntfs_error(VFS_I(ni)->i_sb, "Failed to read a page %lu for attr %#x: %ld",
> diff --git a/fs/ntfs/bdev-io.c b/fs/ntfs/bdev-io.c
> index 4f27eed3b0..afb1d1df37 100644
> --- a/fs/ntfs/bdev-io.c
> +++ b/fs/ntfs/bdev-io.c
> @@ -99,7 +99,7 @@ int ntfs_bdev_write(struct super_block *sb, void *buf, loff_t start, size_t size
>   	for (; idx < idx_end; idx++, from = 0) {
>   		u32 len;
>   
> -		folio = read_mapping_folio(sb->s_bdev->bd_mapping, idx, NULL);
> +		folio = ntfs_read_metadata_folio(sb->s_bdev->bd_mapping, idx);
>   		if (IS_ERR(folio)) {
>   			ntfs_error(sb, "Unable to read %ld page", idx);
>   			return PTR_ERR(folio);
> diff --git a/fs/ntfs/bitmap.c b/fs/ntfs/bitmap.c
> index af86fb1c19..0ad80255d6 100644
> --- a/fs/ntfs/bitmap.c
> +++ b/fs/ntfs/bitmap.c
> @@ -36,8 +36,7 @@ int ntfs_bitmap_check_used(struct ntfs_volume *vol, s64 start, s64 count,
>   		return -EROFS;
>   
>   	while (count) {
> -		folio = read_mapping_folio(mapping,
> -					   start >> (PAGE_SHIFT + 3), NULL);
> +		folio = ntfs_read_metadata_folio(mapping, start >> (PAGE_SHIFT + 3));
>   		if (IS_ERR(folio))
>   			return PTR_ERR(folio);
>   
> @@ -203,7 +202,7 @@ int __ntfs_bitmap_set_bits_in_run(struct inode *vi, const s64 start_bit,
>   
>   	/* Get the page containing the first bit (@start_bit). */
>   	mapping = vi->i_mapping;
> -	folio = read_mapping_folio(mapping, index, NULL);
> +	folio = ntfs_read_metadata_folio(mapping, index);
>   	if (IS_ERR(folio)) {
>   		if (!is_rollback)
>   			ntfs_error(vi->i_sb,
> @@ -267,7 +266,7 @@ int __ntfs_bitmap_set_bits_in_run(struct inode *vi, const s64 start_bit,
>   		folio_unlock(folio);
>   		kunmap_local(kaddr);
>   		folio_put(folio);
> -		folio = read_mapping_folio(mapping, ++index, NULL);
> +		folio = ntfs_read_metadata_folio(mapping, ++index);
>   		if (IS_ERR(folio)) {
>   			ntfs_error(vi->i_sb,
>   				   "Failed to map subsequent page (error %li), aborting.",
> diff --git a/fs/ntfs/dir.c b/fs/ntfs/dir.c
> index 9fb5bb3d35..ce87799a28 100644
> --- a/fs/ntfs/dir.c
> +++ b/fs/ntfs/dir.c
> @@ -327,8 +327,8 @@ u64 ntfs_lookup_inode_by_name(struct ntfs_inode *dir_ni, const __le16 *uname,
>   	 * of PAGE_SIZE and map the page cache page, reading it from
>   	 * disk if necessary.
>   	 */
> -	folio = read_mapping_folio(ia_mapping, vcn <<
> -			dir_ni->itype.index.vcn_size_bits >> PAGE_SHIFT, NULL);
> +	folio = ntfs_read_metadata_folio(ia_mapping, vcn <<
> +			dir_ni->itype.index.vcn_size_bits >> PAGE_SHIFT);
>   	if (IS_ERR(folio)) {
>   		ntfs_error(sb, "Failed to map directory index page, error %ld.",
>   				-PTR_ERR(folio));
> diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
> index 62dd5bd5bb..b7fb57d084 100644
> --- a/fs/ntfs/inode.c
> +++ b/fs/ntfs/inode.c
> @@ -3773,8 +3773,14 @@ s64 ntfs_inode_attr_pread(struct inode *vi, s64 pos, s64 count, u8 *buf)
>   
>   	index = pos >> PAGE_SHIFT;
>   	do {
> -		/* Update @index and get the next folio. */
> -		folio = read_mapping_folio(mapping, index, NULL);
> +		/*
> +		 * Update @index and get the next folio.  The contents of a named
> +		 * stream are user data, so a fatal signal may still stop that read.
> +		 */
> +		if (ntfs_inode_is_named_stream(ni))
> +			folio = read_mapping_folio(mapping, index, NULL);
> +		else
> +			folio = ntfs_read_metadata_folio(mapping, index);
>   		if (IS_ERR(folio)) {
>   			err = PTR_ERR(folio);
>   			break;
> @@ -3926,9 +3932,18 @@ static s64 __ntfs_inode_non_resident_attr_pwrite(struct inode *vi,
>   				break;
>   			}
>   		} else {
> -			folio = read_mapping_folio(mapping, index, NULL);
> +			/*
> +			 * Named stream contents are user data; keep that read
> +			 * killable, as in ntfs_inode_attr_pread().
> +			 */
> +			if (ntfs_inode_is_named_stream(ni))
> +				folio = read_mapping_folio(mapping, index, NULL);
> +			else
> +				folio = ntfs_read_metadata_folio(mapping, index);
>   			if (IS_ERR(folio)) {
>   				ret = PTR_ERR(folio);
> +				if (ret == -EINTR)
> +					break;
>   				ntfs_error(vi->i_sb, "Failed to read a page %lu for attr %#x: %ld",
>   						index, ni->type, PTR_ERR(folio));
>   				break;
> diff --git a/fs/ntfs/lcnalloc.c b/fs/ntfs/lcnalloc.c
> index 3ebcac4c28..7e00016f42 100644
> --- a/fs/ntfs/lcnalloc.c
> +++ b/fs/ntfs/lcnalloc.c
> @@ -340,7 +340,7 @@ struct runlist_element *ntfs_cluster_alloc(struct ntfs_volume *vol, const s64 st
>   		if (vol->lcn_empty_bits_per_page[index] == 0)
>   			goto next_bmp_pos;
>   
> -		folio = read_mapping_folio(mapping, index, NULL);
> +		folio = ntfs_read_metadata_folio(mapping, index);
>   		if (IS_ERR(folio)) {
>   			err = PTR_ERR(folio);
>   			ntfs_error(vol->sb, "Failed to map page.");
> diff --git a/fs/ntfs/logfile.c b/fs/ntfs/logfile.c
> index 2f27ae7a39..cdc951309d 100644
> --- a/fs/ntfs/logfile.c
> +++ b/fs/ntfs/logfile.c
> @@ -367,7 +367,7 @@ static int ntfs_check_and_load_restart_page(struct inode *vi,
>   		to_read = le32_to_cpu(rp->system_page_size) - size;
>   		idx = (pos + size) >> PAGE_SHIFT;
>   		do {
> -			folio = read_mapping_folio(vi->i_mapping, idx, NULL);
> +			folio = ntfs_read_metadata_folio(vi->i_mapping, idx);
>   			if (IS_ERR(folio)) {
>   				ntfs_error(vi->i_sb, "Error mapping LogFile page (index %lu).",
>   						idx);
> @@ -514,7 +514,7 @@ bool ntfs_check_logfile(struct inode *log_vi, struct restart_page_header **rp)
>   				kunmap_local(kbase);
>   				folio_put(folio);
>   			}
> -			folio = read_mapping_folio(mapping, idx, NULL);
> +			folio = ntfs_read_metadata_folio(mapping, idx);
>   			if (IS_ERR(folio)) {
>   				ntfs_error(vol->sb, "Error mapping LogFile page (index %lu).",
>   						idx);
> diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c
> index 89288b7943..3601f77eee 100644
> --- a/fs/ntfs/mft.c
> +++ b/fs/ntfs/mft.c
> @@ -143,7 +143,7 @@ static inline struct mft_record *map_mft_record_folio(struct ntfs_inode *ni)
>   	}
>   
>   	/* Read, map, and pin the folio. */
> -	folio = read_mapping_folio(mft_vi->i_mapping, index, NULL);
> +	folio = ntfs_read_metadata_folio(mft_vi->i_mapping, index);
>   	if (!IS_ERR(folio)) {
>   		u8 *addr;
>   
> @@ -549,8 +549,8 @@ static int ntfs_sync_mft_mirror_unit(struct ntfs_volume *vol,
>   	if (unit->folio_ofs + unit->len > folio_size(source))
>   		return -EIO;
>   
> -	mirror = read_mapping_folio(vol->mftmirr_ino->i_mapping,
> -				    mirror_file_ofs >> PAGE_SHIFT, NULL);
> +	mirror = ntfs_read_metadata_folio(vol->mftmirr_ino->i_mapping,
> +					  mirror_file_ofs >> PAGE_SHIFT);
>   	if (IS_ERR(mirror))
>   		return PTR_ERR(mirror);
>   
> @@ -1023,7 +1023,7 @@ static bool mft_reserved_is_free(struct ntfs_volume *vol,
>   	if (!m)
>   		return false;
>   
> -	folio = read_mapping_folio(vol->mft_ino->i_mapping, index, NULL);
> +	folio = ntfs_read_metadata_folio(vol->mft_ino->i_mapping, index);
>   	if (IS_ERR(folio))
>   		goto free_m;
>   
> @@ -1199,8 +1199,8 @@ static s64 mft_bitmap_alloc_free_rec(struct ntfs_volume *vol,
>   		 * for a zero bit.
>   		 */
>   		if (size) {
> -			folio = read_mapping_folio(mftbmp_mapping,
> -					ofs >> PAGE_SHIFT, NULL);
> +			folio = ntfs_read_metadata_folio(mftbmp_mapping,
> +							 ofs >> PAGE_SHIFT);
>   			if (IS_ERR(folio)) {
>   				ntfs_error(vol->sb, "Failed to read mft bitmap, aborting.");
>   				return PTR_ERR(folio);
> @@ -1392,8 +1392,8 @@ static int ntfs_mft_bitmap_extend_allocation_nolock(struct ntfs_volume *vol)
>   	 * to us.
>   	 */
>   	ll = lcn >> 3;
> -	folio = read_mapping_folio(vol->lcnbmp_ino->i_mapping,
> -			ll >> PAGE_SHIFT, NULL);
> +	folio = ntfs_read_metadata_folio(vol->lcnbmp_ino->i_mapping,
> +					 ll >> PAGE_SHIFT);
>   	if (IS_ERR(folio)) {
>   		up_write(&mftbmp_ni->runlist.lock);
>   		ntfs_error(vol->sb, "Failed to read from lcn bitmap.");
> @@ -2207,7 +2207,7 @@ static int ntfs_mft_record_format(const struct ntfs_volume *vol, const s64 mft_n
>   	}
>   
>   	/* Read, map, and pin the folio containing the mft record. */
> -	folio = read_mapping_folio(mft_vi->i_mapping, index, NULL);
> +	folio = ntfs_read_metadata_folio(mft_vi->i_mapping, index);
>   	if (IS_ERR(folio)) {
>   		ntfs_error(vol->sb, "Failed to map page containing mft record to format 0x%llx.",
>   				(long long)mft_no);
> @@ -2725,7 +2725,7 @@ int ntfs_mft_record_alloc(struct ntfs_volume *vol, const int mode,
>   	index = NTFS_MFT_NR_TO_PIDX(vol, bit);
>   	ofs = NTFS_MFT_NR_TO_POFS(vol, bit);
>   	/* Read, map, and pin the folio containing the mft record. */
> -	folio = read_mapping_folio(vol->mft_ino->i_mapping, index, NULL);
> +	folio = ntfs_read_metadata_folio(vol->mft_ino->i_mapping, index);
>   	if (IS_ERR(folio)) {
>   		ntfs_error(vol->sb, "Failed to map page containing allocated mft record 0x%llx.",
>   				bit);
> diff --git a/fs/ntfs/ntfs.h b/fs/ntfs/ntfs.h
> index fac72d40f5..f33df986f5 100644
> --- a/fs/ntfs/ntfs.h
> +++ b/fs/ntfs/ntfs.h
> @@ -294,6 +294,10 @@ static inline int ntfs_ffs(int x)
>   	return r;
>   }
>   
> +/* From fs/ntfs/aops.c */
> +struct folio *ntfs_read_metadata_folio(struct address_space *mapping,
> +				       pgoff_t index);
> +
>   /* From fs/ntfs/bdev-io.c */
>   int ntfs_bdev_read(struct block_device *bdev, char *data, loff_t start, size_t size);
>   int ntfs_bdev_write(struct super_block *sb, void *buf, loff_t start, size_t size);
> diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c
> index 71f0aea46b..af97afe6a7 100644
> --- a/fs/ntfs/super.c
> +++ b/fs/ntfs/super.c
> @@ -1187,8 +1187,8 @@ static bool check_mft_mirror(struct ntfs_volume *vol)
>   				folio_put(mft_folio);
>   			}
>   			/* Get the $MFT page. */
> -			mft_folio = read_mapping_folio(vol->mft_ino->i_mapping,
> -					index, NULL);
> +			mft_folio = ntfs_read_metadata_folio(vol->mft_ino->i_mapping,
> +							     index);
>   			if (IS_ERR(mft_folio)) {
>   				ntfs_error(sb, "Failed to read $MFT.");
>   				return false;
> @@ -1196,8 +1196,8 @@ static bool check_mft_mirror(struct ntfs_volume *vol)
>   			kmft_base = kmap_local_folio(mft_folio, 0);
>   			kmft = kmft_base;
>   			/* Get the $MFTMirr page. */
> -			mirr_folio = read_mapping_folio(vol->mftmirr_ino->i_mapping,
> -					index, NULL);
> +			mirr_folio = ntfs_read_metadata_folio(vol->mftmirr_ino->i_mapping,
> +							      index);
>   			if (IS_ERR(mirr_folio)) {
>   				ntfs_error(sb, "Failed to read $MFTMirr.");
>   				goto mft_unmap_out;
> @@ -1395,7 +1395,7 @@ static int check_windows_hibernation_status(struct ntfs_volume *vol)
>   		goto iput_out;
>   	}
>   
> -	folio = read_mapping_folio(vi->i_mapping, 0, NULL);
> +	folio = ntfs_read_metadata_folio(vi->i_mapping, 0);
>   	if (IS_ERR(folio)) {
>   		ntfs_error(vol->sb, "Failed to read from hiberfil.sys.");
>   		ret = PTR_ERR(folio);
> @@ -1460,7 +1460,7 @@ static bool load_and_init_attrdef(struct ntfs_volume *vol)
>   	while (index < max_index) {
>   		/* Read the attrdef table and copy it into the linear buffer. */
>   read_partial_attrdef_page:
> -		folio = read_mapping_folio(ino->i_mapping, index, NULL);
> +		folio = ntfs_read_metadata_folio(ino->i_mapping, index);
>   		if (IS_ERR(folio))
>   			goto free_iput_failed;
>   		addr = kmap_local_folio(folio, 0);
> @@ -1526,7 +1526,7 @@ static bool load_and_init_upcase(struct ntfs_volume *vol)
>   	while (index < max_index) {
>   		/* Read the upcase table and copy it into the linear buffer. */
>   read_partial_upcase_page:
> -		folio = read_mapping_folio(ino->i_mapping, index, NULL);
> +		folio = ntfs_read_metadata_folio(ino->i_mapping, index);
>   		if (IS_ERR(folio))
>   			goto iput_upcase_failed;
>   		addr = kmap_local_folio(folio, 0);
> 
> base-commit: 2b4bb6d6d8fe8315a655cb63f186013bfb45dd21

Looks good to me.

Reviewed-by: Baolin Liu <liubaolin@kylinos.cn>


      reply	other threads:[~2026-11-13  5:30 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-13  3:26 xkeyC
2026-11-13  5:30 ` liubaolin [this message]

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=aa52e1af-d019-4eeb-ab55-628c2f25fb2c@163.com \
    --to=liubaolin12138@163.com \
    --cc=hyc.lee@gmail.com \
    --cc=linkinjeon@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=ntfs@lists.linux.dev \
    --cc=stable@vger.kernel.org \
    --cc=xkeyc@qq.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®