public inbox for stable@vger.kernel.org
 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, Josef Bacik <josef@toxicpanda.com>,
	Filipe Manana <fdmanana@suse.com>,
	David Sterba <dsterba@suse.com>, Sasha Levin <sashal@kernel.org>
Subject: [PATCH 5.15 47/73] btrfs: remove no longer needed logic for replaying directory deletes
Date: Fri,  2 Sep 2022 14:19:11 +0200	[thread overview]
Message-ID: <20220902121406.013105463@linuxfoundation.org> (raw)
In-Reply-To: <20220902121404.435662285@linuxfoundation.org>

From: Filipe Manana <fdmanana@suse.com>

[ Upstream commit ccae4a19c9140a34a0c5f0658812496dd8bbdeaf ]

Now that we log only dir index keys when logging a directory, we no longer
need to deal with dir item keys in the log replay code for replaying
directory deletes. This is also true for the case when we replay a log
tree created by a kernel that still logs dir items.

So remove the remaining code of the replay of directory deletes algorithm
that deals with dir item keys.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 fs/btrfs/tree-log.c             | 158 ++++++++++++++------------------
 include/uapi/linux/btrfs_tree.h |   4 +-
 2 files changed, 72 insertions(+), 90 deletions(-)

diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 6f51c4d922d48..4ab1bbc344760 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -2197,7 +2197,7 @@ static noinline int replay_one_dir_item(struct btrfs_trans_handle *trans,
  */
 static noinline int find_dir_range(struct btrfs_root *root,
 				   struct btrfs_path *path,
-				   u64 dirid, int key_type,
+				   u64 dirid,
 				   u64 *start_ret, u64 *end_ret)
 {
 	struct btrfs_key key;
@@ -2210,7 +2210,7 @@ static noinline int find_dir_range(struct btrfs_root *root,
 		return 1;
 
 	key.objectid = dirid;
-	key.type = key_type;
+	key.type = BTRFS_DIR_LOG_INDEX_KEY;
 	key.offset = *start_ret;
 
 	ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
@@ -2224,7 +2224,7 @@ static noinline int find_dir_range(struct btrfs_root *root,
 	if (ret != 0)
 		btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
 
-	if (key.type != key_type || key.objectid != dirid) {
+	if (key.type != BTRFS_DIR_LOG_INDEX_KEY || key.objectid != dirid) {
 		ret = 1;
 		goto next;
 	}
@@ -2251,7 +2251,7 @@ static noinline int find_dir_range(struct btrfs_root *root,
 
 	btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
 
-	if (key.type != key_type || key.objectid != dirid) {
+	if (key.type != BTRFS_DIR_LOG_INDEX_KEY || key.objectid != dirid) {
 		ret = 1;
 		goto out;
 	}
@@ -2282,95 +2282,82 @@ static noinline int check_item_in_log(struct btrfs_trans_handle *trans,
 	int ret;
 	struct extent_buffer *eb;
 	int slot;
-	u32 item_size;
 	struct btrfs_dir_item *di;
-	struct btrfs_dir_item *log_di;
 	int name_len;
-	unsigned long ptr;
-	unsigned long ptr_end;
 	char *name;
-	struct inode *inode;
+	struct inode *inode = NULL;
 	struct btrfs_key location;
 
-again:
+	/*
+	 * Currenly we only log dir index keys. Even if we replay a log created
+	 * by an older kernel that logged both dir index and dir item keys, all
+	 * we need to do is process the dir index keys, we (and our caller) can
+	 * safely ignore dir item keys (key type BTRFS_DIR_ITEM_KEY).
+	 */
+	ASSERT(dir_key->type == BTRFS_DIR_INDEX_KEY);
+
 	eb = path->nodes[0];
 	slot = path->slots[0];
-	item_size = btrfs_item_size_nr(eb, slot);
-	ptr = btrfs_item_ptr_offset(eb, slot);
-	ptr_end = ptr + item_size;
-	while (ptr < ptr_end) {
-		di = (struct btrfs_dir_item *)ptr;
-		name_len = btrfs_dir_name_len(eb, di);
-		name = kmalloc(name_len, GFP_NOFS);
-		if (!name) {
-			ret = -ENOMEM;
-			goto out;
-		}
-		read_extent_buffer(eb, name, (unsigned long)(di + 1),
-				  name_len);
-		log_di = NULL;
-		if (log && dir_key->type == BTRFS_DIR_ITEM_KEY) {
-			log_di = btrfs_lookup_dir_item(trans, log, log_path,
-						       dir_key->objectid,
-						       name, name_len, 0);
-		} else if (log && dir_key->type == BTRFS_DIR_INDEX_KEY) {
-			log_di = btrfs_lookup_dir_index_item(trans, log,
-						     log_path,
-						     dir_key->objectid,
-						     dir_key->offset,
-						     name, name_len, 0);
-		}
-		if (!log_di) {
-			btrfs_dir_item_key_to_cpu(eb, di, &location);
-			btrfs_release_path(path);
-			btrfs_release_path(log_path);
-			inode = read_one_inode(root, location.objectid);
-			if (!inode) {
-				kfree(name);
-				return -EIO;
-			}
+	di = btrfs_item_ptr(eb, slot, struct btrfs_dir_item);
+	name_len = btrfs_dir_name_len(eb, di);
+	name = kmalloc(name_len, GFP_NOFS);
+	if (!name) {
+		ret = -ENOMEM;
+		goto out;
+	}
 
-			ret = link_to_fixup_dir(trans, root,
-						path, location.objectid);
-			if (ret) {
-				kfree(name);
-				iput(inode);
-				goto out;
-			}
+	read_extent_buffer(eb, name, (unsigned long)(di + 1), name_len);
 
-			inc_nlink(inode);
-			ret = btrfs_unlink_inode(trans, BTRFS_I(dir),
-					BTRFS_I(inode), name, name_len);
-			if (!ret)
-				ret = btrfs_run_delayed_items(trans);
-			kfree(name);
-			iput(inode);
-			if (ret)
-				goto out;
+	if (log) {
+		struct btrfs_dir_item *log_di;
 
-			/* there might still be more names under this key
-			 * check and repeat if required
-			 */
-			ret = btrfs_search_slot(NULL, root, dir_key, path,
-						0, 0);
-			if (ret == 0)
-				goto again;
+		log_di = btrfs_lookup_dir_index_item(trans, log, log_path,
+						     dir_key->objectid,
+						     dir_key->offset,
+						     name, name_len, 0);
+		if (IS_ERR(log_di)) {
+			ret = PTR_ERR(log_di);
+			goto out;
+		} else if (log_di) {
+			/* The dentry exists in the log, we have nothing to do. */
 			ret = 0;
 			goto out;
-		} else if (IS_ERR(log_di)) {
-			kfree(name);
-			return PTR_ERR(log_di);
 		}
-		btrfs_release_path(log_path);
-		kfree(name);
+	}
 
-		ptr = (unsigned long)(di + 1);
-		ptr += name_len;
+	btrfs_dir_item_key_to_cpu(eb, di, &location);
+	btrfs_release_path(path);
+	btrfs_release_path(log_path);
+	inode = read_one_inode(root, location.objectid);
+	if (!inode) {
+		ret = -EIO;
+		goto out;
 	}
-	ret = 0;
+
+	ret = link_to_fixup_dir(trans, root, path, location.objectid);
+	if (ret)
+		goto out;
+
+	inc_nlink(inode);
+	ret = btrfs_unlink_inode(trans, BTRFS_I(dir), BTRFS_I(inode), name,
+				 name_len);
+	if (ret)
+		goto out;
+
+	ret = btrfs_run_delayed_items(trans);
+	if (ret)
+		goto out;
+
+	/*
+	 * Unlike dir item keys, dir index keys can only have one name (entry) in
+	 * them, as there are no key collisions since each key has a unique offset
+	 * (an index number), so we're done.
+	 */
 out:
 	btrfs_release_path(path);
 	btrfs_release_path(log_path);
+	kfree(name);
+	iput(inode);
 	return ret;
 }
 
@@ -2490,7 +2477,6 @@ static noinline int replay_dir_deletes(struct btrfs_trans_handle *trans,
 {
 	u64 range_start;
 	u64 range_end;
-	int key_type = BTRFS_DIR_LOG_ITEM_KEY;
 	int ret = 0;
 	struct btrfs_key dir_key;
 	struct btrfs_key found_key;
@@ -2498,7 +2484,7 @@ static noinline int replay_dir_deletes(struct btrfs_trans_handle *trans,
 	struct inode *dir;
 
 	dir_key.objectid = dirid;
-	dir_key.type = BTRFS_DIR_ITEM_KEY;
+	dir_key.type = BTRFS_DIR_INDEX_KEY;
 	log_path = btrfs_alloc_path();
 	if (!log_path)
 		return -ENOMEM;
@@ -2512,14 +2498,14 @@ static noinline int replay_dir_deletes(struct btrfs_trans_handle *trans,
 		btrfs_free_path(log_path);
 		return 0;
 	}
-again:
+
 	range_start = 0;
 	range_end = 0;
 	while (1) {
 		if (del_all)
 			range_end = (u64)-1;
 		else {
-			ret = find_dir_range(log, path, dirid, key_type,
+			ret = find_dir_range(log, path, dirid,
 					     &range_start, &range_end);
 			if (ret < 0)
 				goto out;
@@ -2546,8 +2532,10 @@ static noinline int replay_dir_deletes(struct btrfs_trans_handle *trans,
 			btrfs_item_key_to_cpu(path->nodes[0], &found_key,
 					      path->slots[0]);
 			if (found_key.objectid != dirid ||
-			    found_key.type != dir_key.type)
-				goto next_type;
+			    found_key.type != dir_key.type) {
+				ret = 0;
+				goto out;
+			}
 
 			if (found_key.offset > range_end)
 				break;
@@ -2566,15 +2554,7 @@ static noinline int replay_dir_deletes(struct btrfs_trans_handle *trans,
 			break;
 		range_start = range_end + 1;
 	}
-
-next_type:
 	ret = 0;
-	if (key_type == BTRFS_DIR_LOG_ITEM_KEY) {
-		key_type = BTRFS_DIR_LOG_INDEX_KEY;
-		dir_key.type = BTRFS_DIR_INDEX_KEY;
-		btrfs_release_path(path);
-		goto again;
-	}
 out:
 	btrfs_release_path(path);
 	btrfs_free_path(log_path);
diff --git a/include/uapi/linux/btrfs_tree.h b/include/uapi/linux/btrfs_tree.h
index e1c4c732aabac..5416f1f1a77a8 100644
--- a/include/uapi/linux/btrfs_tree.h
+++ b/include/uapi/linux/btrfs_tree.h
@@ -146,7 +146,9 @@
 
 /*
  * dir items are the name -> inode pointers in a directory.  There is one
- * for every name in a directory.
+ * for every name in a directory.  BTRFS_DIR_LOG_ITEM_KEY is no longer used
+ * but it's still defined here for documentation purposes and to help avoid
+ * having its numerical value reused in the future.
  */
 #define BTRFS_DIR_LOG_ITEM_KEY  60
 #define BTRFS_DIR_LOG_INDEX_KEY 72
-- 
2.35.1




  parent reply	other threads:[~2022-09-02 13:41 UTC|newest]

Thread overview: 82+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-09-02 12:18 [PATCH 5.15 00/73] 5.15.65-rc1 review Greg Kroah-Hartman
2022-09-02 12:18 ` [PATCH 5.15 01/73] mm: Force TLB flush for PFNMAP mappings before unlink_file_vma() Greg Kroah-Hartman
2022-09-02 12:18 ` [PATCH 5.15 02/73] drm/bridge: Add stubs for devm_drm_of_get_bridge when OF is disabled Greg Kroah-Hartman
2022-09-02 12:18 ` [PATCH 5.15 03/73] ACPI: thermal: drop an always true check Greg Kroah-Hartman
2022-09-02 12:18 ` [PATCH 5.15 04/73] drm/vc4: hdmi: Rework power up Greg Kroah-Hartman
2022-09-02 12:18 ` [PATCH 5.15 05/73] drm/vc4: hdmi: Depends on CONFIG_PM Greg Kroah-Hartman
2022-09-02 12:18 ` [PATCH 5.15 06/73] firmware: tegra: bpmp: Do only aligned access to IPC memory area Greg Kroah-Hartman
2022-09-02 12:18 ` [PATCH 5.15 07/73] crypto: lib - remove unneeded selection of XOR_BLOCKS Greg Kroah-Hartman
2022-09-02 12:18 ` [PATCH 5.15 08/73] Drivers: hv: balloon: Support status report for larger page sizes Greg Kroah-Hartman
2022-09-02 12:18 ` [PATCH 5.15 09/73] mm/hugetlb: avoid corrupting page->mapping in hugetlb_mcopy_atomic_pte Greg Kroah-Hartman
2022-09-02 12:18 ` [PATCH 5.15 10/73] arm64: errata: Add Cortex-A510 to the repeat tlbi list Greg Kroah-Hartman
2022-09-02 12:18 ` [PATCH 5.15 11/73] io_uring: correct fill events helpers types Greg Kroah-Hartman
2022-09-02 12:18 ` [PATCH 5.15 12/73] io_uring: clean cqe filling functions Greg Kroah-Hartman
2022-09-02 12:18 ` [PATCH 5.15 13/73] io_uring: refactor poll update Greg Kroah-Hartman
2022-09-02 12:18 ` [PATCH 5.15 14/73] io_uring: move common poll bits Greg Kroah-Hartman
2022-09-02 12:18 ` [PATCH 5.15 15/73] io_uring: kill poll linking optimisation Greg Kroah-Hartman
2022-09-02 12:18 ` [PATCH 5.15 16/73] io_uring: inline io_poll_complete Greg Kroah-Hartman
2022-09-02 12:18 ` [PATCH 5.15 17/73] io_uring: poll rework Greg Kroah-Hartman
2022-09-02 12:18 ` [PATCH 5.15 18/73] io_uring: Remove unused function req_ref_put Greg Kroah-Hartman
2022-09-02 12:18 ` [PATCH 5.15 19/73] io_uring: remove poll entry from list when canceling all Greg Kroah-Hartman
2022-09-02 12:18 ` [PATCH 5.15 20/73] io_uring: bump poll refs to full 31-bits Greg Kroah-Hartman
2022-09-02 12:18 ` [PATCH 5.15 21/73] io_uring: fail links when poll fails Greg Kroah-Hartman
2022-09-02 12:18 ` [PATCH 5.15 22/73] io_uring: fix wrong arm_poll error handling Greg Kroah-Hartman
2022-09-02 12:18 ` [PATCH 5.15 23/73] io_uring: fix UAF due to missing POLLFREE handling Greg Kroah-Hartman
2022-09-02 12:18 ` [PATCH 5.15 24/73] kbuild: Fix include path in scripts/Makefile.modpost Greg Kroah-Hartman
2022-09-02 12:18 ` [PATCH 5.15 25/73] Bluetooth: L2CAP: Fix build errors in some archs Greg Kroah-Hartman
2022-09-02 12:18 ` [PATCH 5.15 26/73] Revert "PCI/portdrv: Dont disable AER reporting in get_port_device_capability()" Greg Kroah-Hartman
2022-09-02 12:18 ` [PATCH 5.15 27/73] HID: steam: Prevent NULL pointer dereference in steam_{recv,send}_report Greg Kroah-Hartman
2022-09-02 12:18 ` [PATCH 5.15 28/73] udmabuf: Set the DMA mask for the udmabuf device (v2) Greg Kroah-Hartman
2022-09-02 12:18 ` [PATCH 5.15 29/73] media: pvrusb2: fix memory leak in pvr_probe Greg Kroah-Hartman
2022-09-02 12:18 ` [PATCH 5.15 30/73] HID: hidraw: fix memory leak in hidraw_release() Greg Kroah-Hartman
2022-09-02 12:18 ` [PATCH 5.15 31/73] net: fix refcount bug in sk_psock_get (2) Greg Kroah-Hartman
2022-09-02 12:18 ` [PATCH 5.15 32/73] fbdev: fb_pm2fb: Avoid potential divide by zero error Greg Kroah-Hartman
2022-09-02 12:18 ` [PATCH 5.15 33/73] ftrace: Fix NULL pointer dereference in is_ftrace_trampoline when ftrace is dead Greg Kroah-Hartman
2022-09-02 12:18 ` [PATCH 5.15 34/73] bpf: Dont redirect packets with invalid pkt_len Greg Kroah-Hartman
2022-09-02 12:18 ` [PATCH 5.15 35/73] mm/rmap: Fix anon_vma->degree ambiguity leading to double-reuse Greg Kroah-Hartman
2022-09-02 12:19 ` [PATCH 5.15 36/73] ALSA: usb-audio: Add quirk for LH Labs Geek Out HD Audio 1V5 Greg Kroah-Hartman
2022-09-02 12:19 ` [PATCH 5.15 37/73] HID: add Lenovo Yoga C630 battery quirk Greg Kroah-Hartman
2022-09-02 12:19 ` [PATCH 5.15 38/73] HID: AMD_SFH: Add a DMI quirk entry for Chromebooks Greg Kroah-Hartman
2022-09-02 12:19 ` [PATCH 5.15 39/73] HID: asus: ROG NKey: Ignore portion of 0x5a report Greg Kroah-Hartman
2022-09-02 12:19 ` [PATCH 5.15 40/73] HID: thrustmaster: Add sparco wheel and fix array length Greg Kroah-Hartman
2022-09-02 12:19 ` [PATCH 5.15 41/73] drm/i915/gt: Skip TLB invalidations once wedged Greg Kroah-Hartman
2022-09-02 12:19 ` [PATCH 5.15 42/73] mmc: mtk-sd: Clear interrupts when cqe off/disable Greg Kroah-Hartman
2022-09-02 12:19 ` [PATCH 5.15 43/73] mmc: sdhci-of-dwcmshc: add reset call back for rockchip Socs Greg Kroah-Hartman
2022-09-02 12:19 ` [PATCH 5.15 44/73] mmc: sdhci-of-dwcmshc: rename rk3568 to rk35xx Greg Kroah-Hartman
2022-09-02 12:19 ` [PATCH 5.15 45/73] mmc: sdhci-of-dwcmshc: Re-enable support for the BlueField-3 SoC Greg Kroah-Hartman
2022-09-02 12:19 ` [PATCH 5.15 46/73] btrfs: remove root argument from btrfs_unlink_inode() Greg Kroah-Hartman
2022-09-02 12:19 ` Greg Kroah-Hartman [this message]
2022-09-02 12:19 ` [PATCH 5.15 48/73] btrfs: add and use helper for unlinking inode during log replay Greg Kroah-Hartman
2022-09-02 12:19 ` [PATCH 5.15 49/73] btrfs: fix warning during log replay when bumping inode link count Greg Kroah-Hartman
2022-09-02 12:19 ` [PATCH 5.15 50/73] fs/ntfs3: Fix work with fragmented xattr Greg Kroah-Hartman
2022-09-02 12:19 ` [PATCH 5.15 51/73] ASoC: sh: rz-ssi: Improve error handling in rz_ssi_probe() error path Greg Kroah-Hartman
2022-09-02 12:19 ` [PATCH 5.15 52/73] drm/amd/display: Avoid MPC infinite loop Greg Kroah-Hartman
2022-09-02 12:19 ` [PATCH 5.15 53/73] drm/amd/display: Fix HDMI VSIF V3 incorrect issue Greg Kroah-Hartman
2022-09-02 12:19 ` [PATCH 5.15 54/73] drm/amd/display: For stereo keep "FLIP_ANY_FRAME" Greg Kroah-Hartman
2022-09-02 12:19 ` [PATCH 5.15 55/73] drm/amd/display: clear optc underflow before turn off odm clock Greg Kroah-Hartman
2022-09-02 12:19 ` [PATCH 5.15 56/73] ksmbd: return STATUS_BAD_NETWORK_NAME error status if share is not configured Greg Kroah-Hartman
2022-09-02 12:19 ` [PATCH 5.15 57/73] neigh: fix possible DoS due to net iface start/stop loop Greg Kroah-Hartman
2022-09-02 12:19 ` [PATCH 5.15 58/73] s390/hypfs: avoid error message under KVM Greg Kroah-Hartman
2022-09-02 12:19 ` [PATCH 5.15 59/73] ksmbd: dont remove dos attribute xattr on O_TRUNC open Greg Kroah-Hartman
2022-09-02 12:19 ` [PATCH 5.15 60/73] drm/amd/pm: add missing ->fini_microcode interface for Sienna Cichlid Greg Kroah-Hartman
2022-09-02 12:19 ` [PATCH 5.15 61/73] drm/amd/display: Fix pixel clock programming Greg Kroah-Hartman
2022-09-02 12:19 ` [PATCH 5.15 62/73] drm/amdgpu: Increase tlb flush timeout for sriov Greg Kroah-Hartman
2022-09-02 12:19 ` [PATCH 5.15 63/73] drm/amd/display: avoid doing vm_init multiple time Greg Kroah-Hartman
2022-09-02 12:19 ` [PATCH 5.15 64/73] netfilter: conntrack: NF_CONNTRACK_PROCFS should no longer default to y Greg Kroah-Hartman
2022-09-02 12:19 ` [PATCH 5.15 65/73] testing: selftests: nft_flowtable.sh: use random netns names Greg Kroah-Hartman
2022-09-02 12:19 ` [PATCH 5.15 66/73] btrfs: move lockdep class helpers to locking.c Greg Kroah-Hartman
2022-09-02 12:19 ` [PATCH 5.15 67/73] btrfs: fix lockdep splat with reloc root extent buffers Greg Kroah-Hartman
2022-09-02 12:19 ` [PATCH 5.15 68/73] btrfs: tree-checker: check for overlapping extent items Greg Kroah-Hartman
2022-09-02 12:19 ` [PATCH 5.15 69/73] kprobes: dont call disarm_kprobe() for disabled kprobes Greg Kroah-Hartman
2022-09-02 12:19 ` [PATCH 5.15 70/73] btrfs: fix space cache corruption and potential double allocations Greg Kroah-Hartman
2022-09-02 12:19 ` [PATCH 5.15 71/73] android: binder: fix lockdep check on clearing vma Greg Kroah-Hartman
2022-09-02 12:19 ` [PATCH 5.15 72/73] net/af_packet: check len when min_header_len equals to 0 Greg Kroah-Hartman
2022-09-02 12:19 ` [PATCH 5.15 73/73] net: neigh: dont call kfree_skb() under spin_lock_irqsave() Greg Kroah-Hartman
2022-09-02 16:36 ` [PATCH 5.15 00/73] 5.15.65-rc1 review Jon Hunter
2022-09-02 18:00 ` Florian Fainelli
2022-09-02 22:06 ` Shuah Khan
2022-09-03  0:36 ` Guenter Roeck
2022-09-03  3:33 ` Naresh Kamboju
2022-09-03  4:10 ` Bagas Sanjaya
2022-09-03  7:42 ` Ron Economos
2022-09-03 10:47 ` Sudip Mukherjee

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=20220902121406.013105463@linuxfoundation.org \
    --to=gregkh@linuxfoundation.org \
    --cc=dsterba@suse.com \
    --cc=fdmanana@suse.com \
    --cc=josef@toxicpanda.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=sashal@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