linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	stable@vger.kernel.org, Jaegeuk Kim <jaegeuk@kernel.org>,
	Ben Hutchings <ben.hutchings@codethink.co.uk>
Subject: [PATCH 4.4 004/104] f2fs: cover more area with nat_tree_lock
Date: Thu, 24 Jan 2019 20:18:53 +0100	[thread overview]
Message-ID: <20190124190155.361874013@linuxfoundation.org> (raw)
In-Reply-To: <20190124190154.968308875@linuxfoundation.org>

4.4-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Jaegeuk Kim <jaegeuk@kernel.org>

commit a51311938e14c17f5a94d30baac9d7bec71f5858 upstream.

There was a subtle bug on nat cache management which incurs wrong nid allocation
or wrong block addresses when try_to_free_nats is triggered heavily.
This patch enlarges the previous coverage of nat_tree_lock to avoid data race.

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 fs/f2fs/node.c |   29 ++++++++++++-----------------
 1 file changed, 12 insertions(+), 17 deletions(-)

--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -261,13 +261,11 @@ static void cache_nat_entry(struct f2fs_
 {
 	struct nat_entry *e;
 
-	down_write(&nm_i->nat_tree_lock);
 	e = __lookup_nat_cache(nm_i, nid);
 	if (!e) {
 		e = grab_nat_entry(nm_i, nid);
 		node_info_from_raw_nat(&e->ni, ne);
 	}
-	up_write(&nm_i->nat_tree_lock);
 }
 
 static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni,
@@ -379,6 +377,8 @@ void get_node_info(struct f2fs_sb_info *
 
 	memset(&ne, 0, sizeof(struct f2fs_nat_entry));
 
+	down_write(&nm_i->nat_tree_lock);
+
 	/* Check current segment summary */
 	mutex_lock(&curseg->curseg_mutex);
 	i = lookup_journal_in_cursum(sum, NAT_JOURNAL, nid, 0);
@@ -399,6 +399,7 @@ void get_node_info(struct f2fs_sb_info *
 cache:
 	/* cache nat entry */
 	cache_nat_entry(NM_I(sbi), nid, &ne);
+	up_write(&nm_i->nat_tree_lock);
 }
 
 /*
@@ -1440,13 +1441,10 @@ static int add_free_nid(struct f2fs_sb_i
 
 	if (build) {
 		/* do not add allocated nids */
-		down_read(&nm_i->nat_tree_lock);
 		ne = __lookup_nat_cache(nm_i, nid);
-		if (ne &&
-			(!get_nat_flag(ne, IS_CHECKPOINTED) ||
+		if (ne && (!get_nat_flag(ne, IS_CHECKPOINTED) ||
 				nat_get_blkaddr(ne) != NULL_ADDR))
 			allocated = true;
-		up_read(&nm_i->nat_tree_lock);
 		if (allocated)
 			return 0;
 	}
@@ -1532,6 +1530,8 @@ static void build_free_nids(struct f2fs_
 	ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nid), FREE_NID_PAGES,
 							META_NAT, true);
 
+	down_read(&nm_i->nat_tree_lock);
+
 	while (1) {
 		struct page *page = get_current_nat_page(sbi, nid);
 
@@ -1560,6 +1560,7 @@ static void build_free_nids(struct f2fs_
 			remove_free_nid(nm_i, nid);
 	}
 	mutex_unlock(&curseg->curseg_mutex);
+	up_read(&nm_i->nat_tree_lock);
 
 	ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nm_i->next_scan_nid),
 					nm_i->ra_nid_pages, META_NAT, false);
@@ -1842,14 +1843,12 @@ static void remove_nats_in_journal(struc
 
 		raw_ne = nat_in_journal(sum, i);
 
-		down_write(&nm_i->nat_tree_lock);
 		ne = __lookup_nat_cache(nm_i, nid);
 		if (!ne) {
 			ne = grab_nat_entry(nm_i, nid);
 			node_info_from_raw_nat(&ne->ni, &raw_ne);
 		}
 		__set_nat_cache_dirty(nm_i, ne);
-		up_write(&nm_i->nat_tree_lock);
 	}
 	update_nats_in_cursum(sum, -i);
 	mutex_unlock(&curseg->curseg_mutex);
@@ -1883,7 +1882,6 @@ static void __flush_nat_entry_set(struct
 	struct f2fs_nat_block *nat_blk;
 	struct nat_entry *ne, *cur;
 	struct page *page = NULL;
-	struct f2fs_nm_info *nm_i = NM_I(sbi);
 
 	/*
 	 * there are two steps to flush nat entries:
@@ -1920,12 +1918,8 @@ static void __flush_nat_entry_set(struct
 			raw_ne = &nat_blk->entries[nid - start_nid];
 		}
 		raw_nat_from_node_info(raw_ne, &ne->ni);
-
-		down_write(&NM_I(sbi)->nat_tree_lock);
 		nat_reset_flag(ne);
 		__clear_nat_cache_dirty(NM_I(sbi), ne);
-		up_write(&NM_I(sbi)->nat_tree_lock);
-
 		if (nat_get_blkaddr(ne) == NULL_ADDR)
 			add_free_nid(sbi, nid, false);
 	}
@@ -1937,9 +1931,7 @@ static void __flush_nat_entry_set(struct
 
 	f2fs_bug_on(sbi, set->entry_cnt);
 
-	down_write(&nm_i->nat_tree_lock);
 	radix_tree_delete(&NM_I(sbi)->nat_set_root, set->set);
-	up_write(&nm_i->nat_tree_lock);
 	kmem_cache_free(nat_entry_set_slab, set);
 }
 
@@ -1959,6 +1951,9 @@ void flush_nat_entries(struct f2fs_sb_in
 
 	if (!nm_i->dirty_nat_cnt)
 		return;
+
+	down_write(&nm_i->nat_tree_lock);
+
 	/*
 	 * if there are no enough space in journal to store dirty nat
 	 * entries, remove all entries from journal and merge them
@@ -1967,7 +1962,6 @@ void flush_nat_entries(struct f2fs_sb_in
 	if (!__has_cursum_space(sum, nm_i->dirty_nat_cnt, NAT_JOURNAL))
 		remove_nats_in_journal(sbi);
 
-	down_write(&nm_i->nat_tree_lock);
 	while ((found = __gang_lookup_nat_set(nm_i,
 					set_idx, SETVEC_SIZE, setvec))) {
 		unsigned idx;
@@ -1976,12 +1970,13 @@ void flush_nat_entries(struct f2fs_sb_in
 			__adjust_nat_entry_set(setvec[idx], &sets,
 							MAX_NAT_JENTRIES(sum));
 	}
-	up_write(&nm_i->nat_tree_lock);
 
 	/* flush dirty nats in nat entry set */
 	list_for_each_entry_safe(set, tmp, &sets, set_list)
 		__flush_nat_entry_set(sbi, set);
 
+	up_write(&nm_i->nat_tree_lock);
+
 	f2fs_bug_on(sbi, nm_i->dirty_nat_cnt);
 }
 



  parent reply	other threads:[~2019-01-24 20:13 UTC|newest]

Thread overview: 111+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-01-24 19:18 [PATCH 4.4 000/104] 4.4.172-stable review Greg Kroah-Hartman
2019-01-24 19:18 ` [PATCH 4.4 001/104] tty/ldsem: Wake up readers after timed out down_write() Greg Kroah-Hartman
2019-01-24 19:18 ` [PATCH 4.4 002/104] can: gw: ensure DLC boundaries after CAN frame modification Greg Kroah-Hartman
2019-01-24 19:18 ` [PATCH 4.4 003/104] f2fs: clean up argument of recover_data Greg Kroah-Hartman
2019-01-24 19:18 ` Greg Kroah-Hartman [this message]
2019-01-24 19:18 ` [PATCH 4.4 005/104] f2fs: move sanity checking of cp into get_valid_checkpoint Greg Kroah-Hartman
2019-01-24 19:18 ` [PATCH 4.4 006/104] f2fs: fix to convert inline directory correctly Greg Kroah-Hartman
2019-01-24 19:18 ` [PATCH 4.4 007/104] f2fs: give -EINVAL for norecovery and rw mount Greg Kroah-Hartman
2019-01-24 19:18 ` [PATCH 4.4 008/104] f2fs: remove an obsolete variable Greg Kroah-Hartman
2019-01-24 19:18 ` [PATCH 4.4 009/104] f2fs: factor out fsync inode entry operations Greg Kroah-Hartman
2019-01-24 19:18 ` [PATCH 4.4 010/104] f2fs: fix inode cache leak Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 011/104] f2fs: fix to avoid reading out encrypted data in page cache Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 012/104] f2fs: not allow to write illegal blkaddr Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 013/104] f2fs: avoid unneeded loop in build_sit_entries Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 014/104] f2fs: use crc and cp version to determine roll-forward recovery Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 015/104] f2fs: introduce get_checkpoint_version for cleanup Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 016/104] f2fs: put directory inodes before checkpoint in roll-forward recovery Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 017/104] f2fs: fix to determine start_cp_addr by sbi->cur_cp_pack Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 018/104] f2fs: detect wrong layout Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 019/104] f2fs: free meta pages if sanity check for ckpt is failed Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 020/104] f2fs: fix race condition in between free nid allocator/initializer Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 021/104] f2fs: return error during fill_super Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 022/104] f2fs: check blkaddr more accuratly before issue a bio Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 023/104] f2fs: sanity check on sit entry Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 024/104] f2fs: enhance sanity_check_raw_super() to avoid potential overflow Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 025/104] f2fs: clean up with is_valid_blkaddr() Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 026/104] f2fs: introduce and spread verify_blkaddr Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 027/104] f2fs: fix to do sanity check with secs_per_zone Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 028/104] f2fs: fix to do sanity check with user_block_count Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 029/104] f2fs: Add sanity_check_inode() function Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 030/104] f2fs: fix to do sanity check with node footer and iblocks Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 031/104] f2fs: fix to do sanity check with reserved blkaddr of inline inode Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 032/104] f2fs: fix to do sanity check with block address in main area Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 033/104] f2fs: fix to do sanity check with block address in main area v2 Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 034/104] f2fs: fix to do sanity check with cp_pack_start_sum Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 035/104] f2fs: fix invalid memory access Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 036/104] f2fs: fix missing up_read Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 037/104] f2fs: fix validation of the block count in sanity_check_raw_super Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 038/104] media: em28xx: Fix misplaced reset of dev->v4l::field_count Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 039/104] proc: Remove empty line in /proc/self/status Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 040/104] arm64/kvm: consistently handle host HCR_EL2 flags Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 041/104] arm64: Dont trap host pointer auth use to EL2 Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 042/104] ipv6: fix kernel-infoleak in ipv6_local_error() Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 043/104] net: bridge: fix a bug on using a neighbour cache entry without checking its state Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 044/104] packet: Do not leak dev refcounts on error exit Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 045/104] ip: on queued skb use skb_header_pointer instead of pskb_may_pull Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 046/104] crypto: authencesn - Avoid twice completion call in decrypt path Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 047/104] crypto: authenc - fix parsing key with misaligned rta_len Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 048/104] btrfs: wait on ordered extents on abort cleanup Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 049/104] Yama: Check for pid death before checking ancestry Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 050/104] scsi: sd: Fix cache_type_store() Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 051/104] mips: fix n32 compat_ipc_parse_version Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 052/104] mfd: tps6586x: Handle interrupts on suspend Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 053/104] Disable MSI also when pcie-octeon.pcie_disable on Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 054/104] omap2fb: Fix stack memory disclosure Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 055/104] media: vivid: fix error handling of kthread_run Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 056/104] media: vivid: set min width/height to a value > 0 Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 057/104] LSM: Check for NULL cred-security on free Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 058/104] media: vb2: vb2_mmap: move lock up Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 059/104] sunrpc: handle ENOMEM in rpcb_getport_async Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 060/104] selinux: fix GPF on invalid policy Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 061/104] sctp: allocate sctp_sockaddr_entry with kzalloc Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 062/104] tipc: fix uninit-value in tipc_nl_compat_link_reset_stats Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 063/104] tipc: fix uninit-value in tipc_nl_compat_bearer_enable Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 064/104] tipc: fix uninit-value in tipc_nl_compat_link_set Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 065/104] tipc: fix uninit-value in tipc_nl_compat_name_table_dump Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 066/104] tipc: fix uninit-value in tipc_nl_compat_doit Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 067/104] block/loop: Use global lock for ioctl() operation Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 068/104] loop: Fold __loop_release into loop_release Greg Kroah-Hartman
2019-01-28 13:31   ` Jan Kara
2019-01-30  7:30     ` Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 069/104] loop: Get rid of loop_index_mutex Greg Kroah-Hartman
2019-01-24 19:19 ` [PATCH 4.4 070/104] loop: Fix double mutex_unlock(&loop_ctl_mutex) in loop_control_ioctl() Greg Kroah-Hartman
2019-01-24 19:20 ` [PATCH 4.4 071/104] drm/fb-helper: Ignore the value of fb_var_screeninfo.pixclock Greg Kroah-Hartman
2019-01-24 19:20 ` [PATCH 4.4 072/104] media: vb2: be sure to unlock mutex on errors Greg Kroah-Hartman
2019-01-24 19:20 ` [PATCH 4.4 073/104] r8169: Add support for new Realtek Ethernet Greg Kroah-Hartman
2019-01-24 19:20 ` [PATCH 4.4 074/104] ipv6: Consider sk_bound_dev_if when binding a socket to a v4 mapped address Greg Kroah-Hartman
2019-01-24 19:20 ` [PATCH 4.4 075/104] ipv6: Take rcu_read_lock in __inet6_bind for mapped addresses Greg Kroah-Hartman
2019-01-24 19:20 ` [PATCH 4.4 076/104] xfs: dont fail when converting shortform attr to long form during ATTR_REPLACE Greg Kroah-Hartman
2019-01-24 19:20 ` [PATCH 4.4 077/104] platform/x86: asus-wmi: Tell the EC the OS will handle the display off hotkey Greg Kroah-Hartman
2019-01-24 19:20 ` [PATCH 4.4 078/104] e1000e: allow non-monotonic SYSTIM readings Greg Kroah-Hartman
2019-01-24 19:20 ` [PATCH 4.4 079/104] writeback: dont decrement wb->refcnt if !wb->bdi Greg Kroah-Hartman
2019-01-24 19:20 ` [PATCH 4.4 080/104] MIPS: SiByte: Enable swiotlb for SWARM, LittleSur and BigSur Greg Kroah-Hartman
2019-01-24 19:20 ` [PATCH 4.4 081/104] arm64: perf: set suppress_bind_attrs flag to true Greg Kroah-Hartman
2019-01-24 19:20 ` [PATCH 4.4 082/104] jffs2: Fix use of uninitialized delayed_work, lockdep breakage Greg Kroah-Hartman
2019-01-24 19:20 ` [PATCH 4.4 083/104] pstore/ram: Do not treat empty buffers as valid Greg Kroah-Hartman
2019-01-24 19:20 ` [PATCH 4.4 084/104] powerpc/pseries/cpuidle: Fix preempt warning Greg Kroah-Hartman
2019-01-24 19:20 ` [PATCH 4.4 085/104] media: firewire: Fix app_info parameter type in avc_ca{,_app}_info Greg Kroah-Hartman
2019-01-24 19:20 ` [PATCH 4.4 086/104] net: call sk_dst_reset when set SO_DONTROUTE Greg Kroah-Hartman
2019-01-24 19:20 ` [PATCH 4.4 087/104] scsi: target: use consistent left-aligned ASCII INQUIRY data Greg Kroah-Hartman
2019-01-24 19:20 ` [PATCH 4.4 088/104] clk: imx6q: reset exclusive gates on init Greg Kroah-Hartman
2019-01-24 19:20 ` [PATCH 4.4 089/104] kconfig: fix file name and line number of warn_ignored_character() Greg Kroah-Hartman
2019-01-24 19:20 ` [PATCH 4.4 090/104] kconfig: fix memory leak when EOF is encountered in quotation Greg Kroah-Hartman
2019-01-24 19:20 ` [PATCH 4.4 091/104] mmc: atmel-mci: do not assume idle after atmci_request_end Greg Kroah-Hartman
2019-01-24 19:20 ` [PATCH 4.4 092/104] perf intel-pt: Fix error with config term "pt=0" Greg Kroah-Hartman
2019-01-24 19:20 ` [PATCH 4.4 093/104] perf svghelper: Fix unchecked usage of strncpy() Greg Kroah-Hartman
2019-01-24 19:20 ` [PATCH 4.4 094/104] perf parse-events: " Greg Kroah-Hartman
2019-01-24 19:20 ` [PATCH 4.4 095/104] dm kcopyd: Fix bug causing workqueue stalls Greg Kroah-Hartman
2019-01-24 19:20 ` [PATCH 4.4 096/104] dm snapshot: Fix excessive memory usage and " Greg Kroah-Hartman
2019-01-24 19:20 ` [PATCH 4.4 097/104] ALSA: bebob: fix model-id of unit for Apogee Ensemble Greg Kroah-Hartman
2019-01-24 19:20 ` [PATCH 4.4 098/104] sysfs: Disable lockdep for driver bind/unbind files Greg Kroah-Hartman
2019-01-24 19:20 ` [PATCH 4.4 099/104] scsi: megaraid: fix out-of-bound array accesses Greg Kroah-Hartman
2019-01-24 19:20 ` [PATCH 4.4 100/104] ocfs2: fix panic due to unrecovered local alloc Greg Kroah-Hartman
2019-01-24 19:20 ` [PATCH 4.4 101/104] mm/page-writeback.c: dont break integrity writeback on ->writepage() error Greg Kroah-Hartman
2019-01-24 19:20 ` [PATCH 4.4 102/104] mm, proc: be more verbose about unstable VMA flags in /proc/<pid>/smaps Greg Kroah-Hartman
2019-01-24 19:20 ` [PATCH 4.4 103/104] net: speed up skb_rbtree_purge() Greg Kroah-Hartman
2019-01-24 19:20 ` [PATCH 4.4 104/104] ipmi:ssif: Fix handling of multi-part return messages Greg Kroah-Hartman
2019-01-25 16:32 ` [PATCH 4.4 000/104] 4.4.172-stable review Naresh Kamboju
2019-01-25 16:34 ` shuah
2019-01-25 23:16 ` Guenter Roeck
2019-01-26 12:06 ` Jon Hunter

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=20190124190155.361874013@linuxfoundation.org \
    --to=gregkh@linuxfoundation.org \
    --cc=ben.hutchings@codethink.co.uk \
    --cc=jaegeuk@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=stable@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).