From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Greg KH <gregkh@linuxfoundation.org>,
torvalds@linux-foundation.org, akpm@linux-foundation.org,
alan@lxorguk.ukuu.org.uk, Junichi Nomura <j-nomura@ce.jp.nec.com>,
Bart Van Assche <bvanassche@acm.org>,
Mike Christie <michaelc@cs.wisc.edu>, Tejun Heo <tj@kernel.org>,
James Bottomley <JBottomley@Parallels.com>
Subject: [ 015/122] SCSI: Fix device removal NULL pointer dereference
Date: Tue, 7 Aug 2012 15:25:03 -0700 [thread overview]
Message-ID: <20120807221949.614324550@linuxfoundation.org> (raw)
In-Reply-To: <20120807221948.220495155@linuxfoundation.org>
From: Greg KH <gregkh@linuxfoundation.org>
3.5-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bart Van Assche <bvanassche@acm.org>
commit 67bd94130015c507011af37858989b199c52e1de upstream.
Use blk_queue_dead() to test whether the queue is dead instead
of !sdev. Since scsi_prep_fn() may be invoked concurrently with
__scsi_remove_device(), keep the queuedata (sdev) pointer in
__scsi_remove_device(). This patch fixes a kernel oops that
can be triggered by USB device removal. See also
http://www.spinics.net/lists/linux-scsi/msg56254.html.
Other changes included in this patch:
- Swap the blk_cleanup_queue() and kfree() calls in
scsi_host_dev_release() to make that code easier to grasp.
- Remove the queue dead check from scsi_run_queue() since the
queue state can change anyway at any point in that function
where the queue lock is not held.
- Remove the queue dead check from the start of scsi_request_fn()
since it is redundant with the scsi_device_online() check.
Reported-by: Jun'ichi Nomura <j-nomura@ce.jp.nec.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Reviewed-by: Mike Christie <michaelc@cs.wisc.edu>
Reviewed-by: Tejun Heo <tj@kernel.org>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/scsi/hosts.c | 7 ++++---
drivers/scsi/scsi_lib.c | 32 ++++----------------------------
drivers/scsi/scsi_priv.h | 1 -
drivers/scsi/scsi_sysfs.c | 5 +----
4 files changed, 9 insertions(+), 36 deletions(-)
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -290,6 +290,7 @@ static void scsi_host_dev_release(struct
struct Scsi_Host *shost = dev_to_shost(dev);
struct device *parent = dev->parent;
struct request_queue *q;
+ void *queuedata;
scsi_proc_hostdir_rm(shost->hostt);
@@ -299,9 +300,9 @@ static void scsi_host_dev_release(struct
destroy_workqueue(shost->work_q);
q = shost->uspace_req_q;
if (q) {
- kfree(q->queuedata);
- q->queuedata = NULL;
- scsi_free_queue(q);
+ queuedata = q->queuedata;
+ blk_cleanup_queue(q);
+ kfree(queuedata);
}
scsi_destroy_command_freelist(shost);
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -406,10 +406,6 @@ static void scsi_run_queue(struct reques
LIST_HEAD(starved_list);
unsigned long flags;
- /* if the device is dead, sdev will be NULL, so no queue to run */
- if (!sdev)
- return;
-
shost = sdev->host;
if (scsi_target(sdev)->single_lun)
scsi_single_lun_run(sdev);
@@ -1370,16 +1366,16 @@ static inline int scsi_host_queue_ready(
* may be changed after request stacking drivers call the function,
* regardless of taking lock or not.
*
- * When scsi can't dispatch I/Os anymore and needs to kill I/Os
- * (e.g. !sdev), scsi needs to return 'not busy'.
- * Otherwise, request stacking drivers may hold requests forever.
+ * When scsi can't dispatch I/Os anymore and needs to kill I/Os scsi
+ * needs to return 'not busy'. Otherwise, request stacking drivers
+ * may hold requests forever.
*/
static int scsi_lld_busy(struct request_queue *q)
{
struct scsi_device *sdev = q->queuedata;
struct Scsi_Host *shost;
- if (!sdev)
+ if (blk_queue_dead(q))
return 0;
shost = sdev->host;
@@ -1490,12 +1486,6 @@ static void scsi_request_fn(struct reque
struct scsi_cmnd *cmd;
struct request *req;
- if (!sdev) {
- while ((req = blk_peek_request(q)) != NULL)
- scsi_kill_request(req, q);
- return;
- }
-
if(!get_device(&sdev->sdev_gendev))
/* We must be tearing the block queue down already */
return;
@@ -1697,20 +1687,6 @@ struct request_queue *scsi_alloc_queue(s
return q;
}
-void scsi_free_queue(struct request_queue *q)
-{
- unsigned long flags;
-
- WARN_ON(q->queuedata);
-
- /* cause scsi_request_fn() to kill all non-finished requests */
- spin_lock_irqsave(q->queue_lock, flags);
- q->request_fn(q);
- spin_unlock_irqrestore(q->queue_lock, flags);
-
- blk_cleanup_queue(q);
-}
-
/*
* Function: scsi_block_requests()
*
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -84,7 +84,6 @@ extern void scsi_next_command(struct scs
extern void scsi_io_completion(struct scsi_cmnd *, unsigned int);
extern void scsi_run_host_queues(struct Scsi_Host *shost);
extern struct request_queue *scsi_alloc_queue(struct scsi_device *sdev);
-extern void scsi_free_queue(struct request_queue *q);
extern int scsi_init_queue(void);
extern void scsi_exit_queue(void);
struct request_queue;
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -971,11 +971,8 @@ void __scsi_remove_device(struct scsi_de
sdev->host->hostt->slave_destroy(sdev);
transport_destroy_device(dev);
- /* cause the request function to reject all I/O requests */
- sdev->request_queue->queuedata = NULL;
-
/* Freeing the queue signals to block that we're done */
- scsi_free_queue(sdev->request_queue);
+ blk_cleanup_queue(sdev->request_queue);
put_device(dev);
}
next prev parent reply other threads:[~2012-08-07 22:27 UTC|newest]
Thread overview: 127+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-08-07 22:24 [ 000/122] 3.5.1-stable review Greg Kroah-Hartman
2012-08-07 22:24 ` [ 001/122] target: Add generation of LOGICAL BLOCK ADDRESS OUT OF RANGE Greg Kroah-Hartman
2012-08-07 22:24 ` [ 002/122] iscsi-target: Drop bogus struct file usage for iSCSI/SCTP Greg Kroah-Hartman
2012-08-07 22:24 ` [ 003/122] mmc: sdhci-pci: CaFe has broken card detection Greg Kroah-Hartman
2012-08-07 22:24 ` [ 004/122] mmc: sdhci: fix incorrect command used in tuning Greg Kroah-Hartman
2012-08-07 22:24 ` [ 005/122] powerpc/ftrace: Fix assembly trampoline register usage Greg Kroah-Hartman
2012-08-07 22:24 ` [ 006/122] powerpc: Add "memory" attribute for mfmsr() Greg Kroah-Hartman
2012-08-07 22:24 ` [ 007/122] powerpc/eeh: Check handle_eeh_events() return value Greg Kroah-Hartman
2012-08-07 22:24 ` [ 008/122] be2net: Missing byteswap in be_get_fw_log_level causes oops on PowerPC Greg Kroah-Hartman
2012-08-07 22:24 ` [ 009/122] powerpc/85xx: use the BRx registers to enable indirect mode on the P1022DS Greg Kroah-Hartman
2012-08-07 22:24 ` [ 010/122] smack: off by one error Greg Kroah-Hartman
2012-08-07 22:53 ` Casey Schaufler
2012-08-08 0:11 ` Casey Schaufler
2012-08-07 22:24 ` [ 011/122] SCSI: libsas: continue revalidation Greg Kroah-Hartman
2012-08-07 22:25 ` [ 012/122] SCSI: libsas: fix sas_discover_devices return code handling Greg Kroah-Hartman
2012-08-07 22:25 ` [ 013/122] SCSI: fix eh wakeup (scsi_schedule_eh vs scsi_restart_operations) Greg Kroah-Hartman
2012-08-07 22:25 ` [ 014/122] SCSI: fix hot unplug vs async scan race Greg Kroah-Hartman
2012-08-07 22:25 ` Greg Kroah-Hartman [this message]
2012-08-07 22:25 ` [ 016/122] SCSI: Avoid dangling pointer in scsi_requeue_command() Greg Kroah-Hartman
2012-08-07 22:25 ` [ 017/122] rt2800usb: 2001:3c17 is an RT3370 device Greg Kroah-Hartman
2012-08-07 22:25 ` [ 018/122] ARM: dt: tegra trimslice: enable USB2 port Greg Kroah-Hartman
2012-08-07 22:25 ` [ 019/122] ARM: OMAP2+: OPP: Fix to ensure check of right oppdef after bad one Greg Kroah-Hartman
2012-08-07 22:25 ` [ 020/122] ARM: dt: tegra trimslice: add vbus-gpio property Greg Kroah-Hartman
2012-08-07 22:25 ` [ 021/122] ASoC: dapm: Fix locking during codec shutdown Greg Kroah-Hartman
2012-08-07 22:25 ` [ 022/122] ASoC: dapm: Fix _PRE and _POST events for DAPM performance improvements Greg Kroah-Hartman
2012-08-07 22:25 ` [ 023/122] ASoC: wm8962: Redo early init of the part on resume Greg Kroah-Hartman
2012-08-07 22:25 ` [ 024/122] ALSA: hda - Add support for Realtek ALC282 Greg Kroah-Hartman
2012-08-07 22:25 ` [ 025/122] ALSA: hda - Turn on PIN_OUT from hdmi playback prepare Greg Kroah-Hartman
2012-08-07 22:25 ` [ 026/122] ALSA: hda - Dont power up when not powered down Greg Kroah-Hartman
2012-08-07 22:25 ` [ 027/122] HID: hid-multitouch: fix input mode feature command Greg Kroah-Hartman
2012-08-07 22:25 ` [ 028/122] usbdevfs: Correct amount of data copied to user in processcompl_compat Greg Kroah-Hartman
2012-08-07 22:25 ` [ 029/122] usb: gadget: Fix g_ether interface link status Greg Kroah-Hartman
2012-08-07 22:25 ` [ 030/122] USB: option: add ZTE MF821D Greg Kroah-Hartman
2012-08-07 22:25 ` [ 031/122] Revert "usb/uas: make sure data urb is gone if we receive status before that" Greg Kroah-Hartman
2012-08-07 22:25 ` [ 032/122] USB: Disable LPM while the device is unconfigured Greg Kroah-Hartman
2012-08-07 22:25 ` [ 033/122] USB: Fix LPM disable/enable during device reset Greg Kroah-Hartman
2012-08-07 22:25 ` [ 034/122] USB: Remove unused LPM variable Greg Kroah-Hartman
2012-08-07 22:25 ` [ 035/122] USB: Fix LPM disable count mismatch on driver unbind Greg Kroah-Hartman
2012-08-07 22:25 ` [ 036/122] ALSA: hda - add dock support for Thinkpad X230 Tablet Greg Kroah-Hartman
2012-08-07 22:25 ` [ 037/122] x86, microcode: Sanitize per-cpu microcode reloading interface Greg Kroah-Hartman
2012-08-07 22:25 ` [ 038/122] x86/mce: Fix siginfo_t->si_addr value for non-recoverable memory faults Greg Kroah-Hartman
2012-08-07 22:25 ` [ 039/122] locks: fix checking of fcntl_setlease argument Greg Kroah-Hartman
2012-08-07 22:25 ` [ 040/122] batman-adv: fix skb->data assignment Greg Kroah-Hartman
2012-08-09 3:13 ` Ben Hutchings
2012-08-09 15:17 ` Greg Kroah-Hartman
2012-08-07 22:25 ` [ 041/122] ftrace: Disable function tracing during suspend/resume and hibernation, again Greg Kroah-Hartman
2012-08-07 22:25 ` [ 042/122] PM / Sleep: Require CAP_BLOCK_SUSPEND to use wake_lock/wake_unlock Greg Kroah-Hartman
2012-08-07 22:25 ` [ 043/122] PM / Sleep: call early resume handlers when suspend_noirq fails Greg Kroah-Hartman
2012-08-07 22:25 ` [ 044/122] TPM: chip disabled state erronously being reported as error Greg Kroah-Hartman
2012-08-07 22:25 ` [ 045/122] tun: fix a crash bug and a memory leak Greg Kroah-Hartman
2012-08-07 22:25 ` [ 046/122] mac80211: fix crash with single-queue drivers Greg Kroah-Hartman
2012-08-07 22:25 ` [ 047/122] b43: fix crash with OpenFWWF Greg Kroah-Hartman
2012-08-07 22:25 ` [ 048/122] mac80211: fix read outside array bounds Greg Kroah-Hartman
2012-08-07 22:25 ` [ 049/122] mac80211: fail authentication when AP denied authentication Greg Kroah-Hartman
2012-08-07 22:25 ` [ 050/122] iwlwifi: Check BSS ctx active before call mac80211 Greg Kroah-Hartman
2012-08-07 22:25 ` [ 051/122] iwlwifi: fix debug print in iwl_sta_calc_ht_flags Greg Kroah-Hartman
2012-08-07 22:25 ` [ 052/122] atl1c: fix issue of io access mode for AR8152 v2.1 Greg Kroah-Hartman
2012-08-07 22:25 ` [ 053/122] rtlwifi: rtl8192cu: Change buffer allocation for synchronous reads Greg Kroah-Hartman
2012-08-07 22:25 ` [ 054/122] rtlwifi: rtl8192de: Fix phy-based version calculation Greg Kroah-Hartman
2012-08-07 22:25 ` [ 055/122] mwifiex: correction in mcs index check Greg Kroah-Hartman
2012-08-07 22:25 ` [ 056/122] s390/idle: fix sequence handling vs cpu hotplug Greg Kroah-Hartman
2012-08-07 22:25 ` [ 057/122] s390/mm: downgrade page table after fork of a 31 bit process Greg Kroah-Hartman
2012-08-07 22:25 ` [ 058/122] s390/mm: fix fault handling for page table walk case Greg Kroah-Hartman
2012-08-07 22:25 ` [ 059/122] cgroup: cgroup_rm_files() was calling simple_unlink() with the wrong inode Greg Kroah-Hartman
2012-08-07 22:25 ` [ 060/122] iommu/amd: Add missing spin_lock initialization Greg Kroah-Hartman
2012-08-07 22:25 ` [ 061/122] iommu/amd: Fix hotplug with iommu=pt Greg Kroah-Hartman
2012-08-07 22:25 ` [ 062/122] udf: Improve table length check to avoid possible overflow Greg Kroah-Hartman
2012-08-07 22:25 ` [ 063/122] stable: update references to older 2.6 versions for 3.x Greg Kroah-Hartman
2012-08-07 22:25 ` [ 064/122] staging: zsmalloc: Finish conversion to a separate module Greg Kroah-Hartman
2012-08-07 22:25 ` [ 065/122] workqueue: perform cpu down operations from low priority cpu_notifier() Greg Kroah-Hartman
2012-08-07 22:25 ` [ 066/122] ACPI, APEI: Fixup common access width firmware bug Greg Kroah-Hartman
2012-08-07 22:25 ` [ 067/122] ACPI/AC: prevent OOPS on some boxes due to missing check power_supply_register() return value check Greg Kroah-Hartman
2012-08-07 22:25 ` [ 068/122] kmsg - properly print over-long continuation lines Greg Kroah-Hartman
2012-08-07 22:25 ` [ 069/122] Btrfs: call the ordered free operation without any locks held Greg Kroah-Hartman
2012-08-07 22:25 ` [ 070/122] cifs: reinstate sec=ntlmv2 mount option Greg Kroah-Hartman
2012-08-07 22:25 ` [ 071/122] cifs: ensure that we always do cifsFileInfo_get under the spinlock Greg Kroah-Hartman
2012-08-07 22:26 ` [ 072/122] spi/pl022: disable port when unused Greg Kroah-Hartman
2012-08-07 22:26 ` [ 073/122] qeth: repair crash in qeth_l3_vlan_rx_kill_vid() Greg Kroah-Hartman
2012-08-07 22:26 ` [ 074/122] tg3: add device id of Apple Thunderbolt Ethernet device Greg Kroah-Hartman
2012-08-07 22:26 ` [ 075/122] tg3: Fix Read DMA workaround for 5719 A0 Greg Kroah-Hartman
2012-08-07 22:26 ` [ 076/122] tg3: Fix race condition in tg3_get_stats64() Greg Kroah-Hartman
2012-08-07 22:26 ` [ 077/122] drm/radeon: fix fence related segfault in CS Greg Kroah-Hartman
2012-08-07 22:26 ` [ 078/122] drm/radeon: fix bo creation retry path Greg Kroah-Hartman
2012-08-07 22:26 ` [ 079/122] drm/radeon: Try harder to avoid HW cursor ending on a multiple of 128 columns Greg Kroah-Hartman
2012-08-07 22:26 ` [ 080/122] drm/radeon: fix non revealent error message Greg Kroah-Hartman
2012-08-07 22:26 ` [ 081/122] drm/radeon: fix hotplug of DP to DVI|HDMI passive adapters (v2) Greg Kroah-Hartman
2012-08-07 22:26 ` [ 082/122] drm/radeon: on hotplug force link training to happen (v2) Greg Kroah-Hartman
2012-08-07 22:26 ` [ 083/122] drm/radeon: fix dpms on/off on trinity/aruba v2 Greg Kroah-Hartman
2012-08-07 22:26 ` [ 084/122] drm/nouveau: init vblank requests list Greg Kroah-Hartman
2012-08-07 22:26 ` [ 085/122] posix_types.h: Cleanup stale __NFDBITS and related definitions Greg Kroah-Hartman
2012-08-07 22:26 ` [ 086/122] dm thin: reduce endio_hook pool size Greg Kroah-Hartman
2012-08-07 22:26 ` [ 087/122] dm thin: fix memory leak in process_prepared_mapping error paths Greg Kroah-Hartman
2012-08-07 22:26 ` [ 088/122] nfsd4: our filesystems are normally case sensitive Greg Kroah-Hartman
2012-08-07 22:26 ` [ 089/122] nfsd4: fix cr_principal comparison check in same_creds Greg Kroah-Hartman
2012-08-07 22:26 ` [ 090/122] nfs: skip commit in releasepage if were freeing memory for fs-related reasons Greg Kroah-Hartman
2012-08-07 22:26 ` [ 091/122] NFS: Fix a number of bugs in the idmapper Greg Kroah-Hartman
2012-08-07 22:26 ` [ 092/122] nouveau: Fix alignment requirements on src and dst addresses Greg Kroah-Hartman
2012-08-07 22:26 ` [ 093/122] ext4: pass a char * to ext4_count_free() instead of a buffer_head ptr Greg Kroah-Hartman
2012-08-07 22:26 ` [ 094/122] ext4: fix overhead calculation used by ext4_statfs() Greg Kroah-Hartman
2012-08-07 22:26 ` [ 095/122] ext4: fix hole punch failure when depth is greater than 0 Greg Kroah-Hartman
2012-08-07 22:26 ` [ 096/122] ext4: dont let i_reserved_meta_blocks go negative Greg Kroah-Hartman
2012-08-07 22:26 ` [ 097/122] ext4: undo ext4_calc_metadata_amount if we fail to claim space Greg Kroah-Hartman
2012-08-07 22:26 ` [ 098/122] ext4: use proper csum calculation in ext4_rename Greg Kroah-Hartman
2012-08-07 22:26 ` [ 099/122] ext4: use s_csum_seed instead of i_csum_seed for xattr block Greg Kroah-Hartman
2012-08-07 22:26 ` [ 100/122] net: Fix references to out-of-scope variables in put_cmsg_compat() Greg Kroah-Hartman
2012-08-07 22:26 ` [ 101/122] r8169: revert "add byte queue limit support" Greg Kroah-Hartman
2012-08-07 22:26 ` [ 102/122] caif: fix NULL pointer check Greg Kroah-Hartman
2012-08-07 22:26 ` [ 103/122] wanmain: comparing array with NULL Greg Kroah-Hartman
2012-08-07 22:26 ` [ 104/122] tcp: Add TCP_USER_TIMEOUT negative value check Greg Kroah-Hartman
2012-08-07 22:26 ` [ 105/122] USB: kaweth.c: use GFP_ATOMIC under spin_lock Greg Kroah-Hartman
2012-08-07 22:26 ` [ 106/122] net: fix rtnetlink IFF_PROMISC and IFF_ALLMULTI handling Greg Kroah-Hartman
2012-08-07 22:26 ` [ 107/122] tcp: perform DMA to userspace only if there is a task waiting for it Greg Kroah-Hartman
2012-08-07 22:26 ` [ 108/122] net/tun: fix ioctl() based info leaks Greg Kroah-Hartman
2012-08-07 22:26 ` [ 109/122] USB: echi-dbgp: increase the controller wait time to come out of halt Greg Kroah-Hartman
2012-08-07 22:26 ` [ 110/122] ALSA: snd-usb: fix clock source validity index Greg Kroah-Hartman
2012-08-07 22:26 ` [ 111/122] ALSA: mpu401: Fix missing initialization of irq field Greg Kroah-Hartman
2012-08-07 22:26 ` [ 112/122] ALSA: hda - Fix invalid D3 of headphone DAC on VT202x codecs Greg Kroah-Hartman
2012-08-07 22:26 ` [ 113/122] ALSA: hda - Fix mute-LED GPIO setup for HP Mini 210 Greg Kroah-Hartman
2012-08-07 22:26 ` [ 114/122] ALSA: hda - Fix polarity of mute LED on " Greg Kroah-Hartman
2012-08-07 22:26 ` [ 115/122] ALSA: hda - Fix mute-LED GPIO initialization for IDT codecs Greg Kroah-Hartman
2012-08-07 22:26 ` [ 116/122] ALSA: hda - Support dock on Lenovo Thinkpad T530 with ALC269VC Greg Kroah-Hartman
2012-08-07 22:26 ` [ 117/122] ASoC: wm8962: Allow VMID time to fully ramp Greg Kroah-Hartman
2012-08-07 22:26 ` [ 118/122] ASoC: wm8994: Ensure there are enough BCLKs for four channels Greg Kroah-Hartman
2012-08-07 22:26 ` [ 119/122] m68k: Make sys_atomic_cmpxchg_32 work on classic m68k Greg Kroah-Hartman
2012-08-07 22:26 ` [ 120/122] futex: Test for pi_mutex on fault in futex_wait_requeue_pi() Greg Kroah-Hartman
2012-08-07 22:26 ` [ 121/122] futex: Fix bug in WARN_ON for NULL q.pi_state Greg Kroah-Hartman
2012-08-07 22:26 ` [ 122/122] futex: Forbid uaddr == uaddr2 in futex_wait_requeue_pi() Greg Kroah-Hartman
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=20120807221949.614324550@linuxfoundation.org \
--to=gregkh@linuxfoundation.org \
--cc=JBottomley@Parallels.com \
--cc=akpm@linux-foundation.org \
--cc=alan@lxorguk.ukuu.org.uk \
--cc=bvanassche@acm.org \
--cc=j-nomura@ce.jp.nec.com \
--cc=linux-kernel@vger.kernel.org \
--cc=michaelc@cs.wisc.edu \
--cc=stable@vger.kernel.org \
--cc=tj@kernel.org \
--cc=torvalds@linux-foundation.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
Powered by JetHome