From: kernel test robot <lkp@intel.com>
To: kbuild-all@lists.01.org
Subject: drivers/scsi/sg.c:1145 sg_ioctl_common() warn: inconsistent returns 'sfp->rq_list_lock'.
Date: Tue, 18 Aug 2020 11:54:31 +0800 [thread overview]
Message-ID: <202008181128.mwASthcZ%lkp@intel.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 9712 bytes --]
tree: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
head: 06a4ec1d9dc652e17ee3ac2ceb6c7cf6c2b75cdd
commit: d320a9551e394cb2d842fd32d28e9805c2a18fbb compat_ioctl: scsi: move ioctl handling into drivers
date: 8 months ago
config: ia64-randconfig-m031-20200818 (attached as .config)
compiler: ia64-linux-gcc (GCC) 9.3.0
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
New smatch warnings:
drivers/scsi/sg.c:1145 sg_ioctl_common() warn: inconsistent returns 'sfp->rq_list_lock'.
Old smatch warnings:
drivers/scsi/sg.c:1094 sg_ioctl_common() warn: inconsistent indenting
# https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d320a9551e394cb2d842fd32d28e9805c2a18fbb
git remote add linus https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
git fetch --no-tags linus master
git checkout d320a9551e394cb2d842fd32d28e9805c2a18fbb
vim +1145 drivers/scsi/sg.c
912
913 static long
914 sg_ioctl_common(struct file *filp, Sg_device *sdp, Sg_fd *sfp,
915 unsigned int cmd_in, void __user *p)
916 {
917 int __user *ip = p;
918 int result, val, read_only;
919 Sg_request *srp;
920 unsigned long iflags;
921
922 SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp,
923 "sg_ioctl: cmd=0x%x\n", (int) cmd_in));
924 read_only = (O_RDWR != (filp->f_flags & O_ACCMODE));
925
926 switch (cmd_in) {
927 case SG_IO:
928 if (atomic_read(&sdp->detaching))
929 return -ENODEV;
930 if (!scsi_block_when_processing_errors(sdp->device))
931 return -ENXIO;
932 result = sg_new_write(sfp, filp, p, SZ_SG_IO_HDR,
933 1, read_only, 1, &srp);
934 if (result < 0)
935 return result;
936 result = wait_event_interruptible(sfp->read_wait,
937 (srp_done(sfp, srp) || atomic_read(&sdp->detaching)));
938 if (atomic_read(&sdp->detaching))
939 return -ENODEV;
940 write_lock_irq(&sfp->rq_list_lock);
941 if (srp->done) {
942 srp->done = 2;
943 write_unlock_irq(&sfp->rq_list_lock);
944 result = sg_new_read(sfp, p, SZ_SG_IO_HDR, srp);
945 return (result < 0) ? result : 0;
946 }
947 srp->orphan = 1;
948 write_unlock_irq(&sfp->rq_list_lock);
949 return result; /* -ERESTARTSYS because signal hit process */
950 case SG_SET_TIMEOUT:
951 result = get_user(val, ip);
952 if (result)
953 return result;
954 if (val < 0)
955 return -EIO;
956 if (val >= mult_frac((s64)INT_MAX, USER_HZ, HZ))
957 val = min_t(s64, mult_frac((s64)INT_MAX, USER_HZ, HZ),
958 INT_MAX);
959 sfp->timeout_user = val;
960 sfp->timeout = mult_frac(val, HZ, USER_HZ);
961
962 return 0;
963 case SG_GET_TIMEOUT: /* N.B. User receives timeout as return value */
964 /* strange ..., for backward compatibility */
965 return sfp->timeout_user;
966 case SG_SET_FORCE_LOW_DMA:
967 /*
968 * N.B. This ioctl never worked properly, but failed to
969 * return an error value. So returning '0' to keep compability
970 * with legacy applications.
971 */
972 return 0;
973 case SG_GET_LOW_DMA:
974 return put_user((int) sdp->device->host->unchecked_isa_dma, ip);
975 case SG_GET_SCSI_ID:
976 {
977 sg_scsi_id_t v;
978
979 if (atomic_read(&sdp->detaching))
980 return -ENODEV;
981 memset(&v, 0, sizeof(v));
982 v.host_no = sdp->device->host->host_no;
983 v.channel = sdp->device->channel;
984 v.scsi_id = sdp->device->id;
985 v.lun = sdp->device->lun;
986 v.scsi_type = sdp->device->type;
987 v.h_cmd_per_lun = sdp->device->host->cmd_per_lun;
988 v.d_queue_depth = sdp->device->queue_depth;
989 if (copy_to_user(p, &v, sizeof(sg_scsi_id_t)))
990 return -EFAULT;
991 return 0;
992 }
993 case SG_SET_FORCE_PACK_ID:
994 result = get_user(val, ip);
995 if (result)
996 return result;
997 sfp->force_packid = val ? 1 : 0;
998 return 0;
999 case SG_GET_PACK_ID:
1000 read_lock_irqsave(&sfp->rq_list_lock, iflags);
1001 list_for_each_entry(srp, &sfp->rq_list, entry) {
1002 if ((1 == srp->done) && (!srp->sg_io_owned)) {
1003 read_unlock_irqrestore(&sfp->rq_list_lock,
1004 iflags);
1005 return put_user(srp->header.pack_id, ip);
1006 }
1007 }
1008 read_unlock_irqrestore(&sfp->rq_list_lock, iflags);
1009 return put_user(-1, ip);
1010 case SG_GET_NUM_WAITING:
1011 read_lock_irqsave(&sfp->rq_list_lock, iflags);
1012 val = 0;
1013 list_for_each_entry(srp, &sfp->rq_list, entry) {
1014 if ((1 == srp->done) && (!srp->sg_io_owned))
1015 ++val;
1016 }
1017 read_unlock_irqrestore(&sfp->rq_list_lock, iflags);
1018 return put_user(val, ip);
1019 case SG_GET_SG_TABLESIZE:
1020 return put_user(sdp->sg_tablesize, ip);
1021 case SG_SET_RESERVED_SIZE:
1022 result = get_user(val, ip);
1023 if (result)
1024 return result;
1025 if (val < 0)
1026 return -EINVAL;
1027 val = min_t(int, val,
1028 max_sectors_bytes(sdp->device->request_queue));
1029 mutex_lock(&sfp->f_mutex);
1030 if (val != sfp->reserve.bufflen) {
1031 if (sfp->mmap_called ||
1032 sfp->res_in_use) {
1033 mutex_unlock(&sfp->f_mutex);
1034 return -EBUSY;
1035 }
1036
1037 sg_remove_scat(sfp, &sfp->reserve);
1038 sg_build_reserve(sfp, val);
1039 }
1040 mutex_unlock(&sfp->f_mutex);
1041 return 0;
1042 case SG_GET_RESERVED_SIZE:
1043 val = min_t(int, sfp->reserve.bufflen,
1044 max_sectors_bytes(sdp->device->request_queue));
1045 return put_user(val, ip);
1046 case SG_SET_COMMAND_Q:
1047 result = get_user(val, ip);
1048 if (result)
1049 return result;
1050 sfp->cmd_q = val ? 1 : 0;
1051 return 0;
1052 case SG_GET_COMMAND_Q:
1053 return put_user((int) sfp->cmd_q, ip);
1054 case SG_SET_KEEP_ORPHAN:
1055 result = get_user(val, ip);
1056 if (result)
1057 return result;
1058 sfp->keep_orphan = val;
1059 return 0;
1060 case SG_GET_KEEP_ORPHAN:
1061 return put_user((int) sfp->keep_orphan, ip);
1062 case SG_NEXT_CMD_LEN:
1063 result = get_user(val, ip);
1064 if (result)
1065 return result;
1066 if (val > SG_MAX_CDB_SIZE)
1067 return -ENOMEM;
1068 sfp->next_cmd_len = (val > 0) ? val : 0;
1069 return 0;
1070 case SG_GET_VERSION_NUM:
1071 return put_user(sg_version_num, ip);
1072 case SG_GET_ACCESS_COUNT:
1073 /* faked - we don't have a real access count anymore */
1074 val = (sdp->device ? 1 : 0);
1075 return put_user(val, ip);
1076 case SG_GET_REQUEST_TABLE:
1077 {
1078 sg_req_info_t *rinfo;
1079
1080 rinfo = kcalloc(SG_MAX_QUEUE, SZ_SG_REQ_INFO,
1081 GFP_KERNEL);
1082 if (!rinfo)
1083 return -ENOMEM;
1084 read_lock_irqsave(&sfp->rq_list_lock, iflags);
1085 sg_fill_request_table(sfp, rinfo);
1086 read_unlock_irqrestore(&sfp->rq_list_lock, iflags);
1087 #ifdef CONFIG_COMPAT
1088 if (in_compat_syscall())
1089 result = put_compat_request_table(p, rinfo);
1090 else
1091 #endif
1092 result = copy_to_user(p, rinfo,
1093 SZ_SG_REQ_INFO * SG_MAX_QUEUE);
1094 result = result ? -EFAULT : 0;
1095 kfree(rinfo);
1096 return result;
1097 }
1098 case SG_EMULATED_HOST:
1099 if (atomic_read(&sdp->detaching))
1100 return -ENODEV;
1101 return put_user(sdp->device->host->hostt->emulated, ip);
1102 case SCSI_IOCTL_SEND_COMMAND:
1103 if (atomic_read(&sdp->detaching))
1104 return -ENODEV;
1105 return sg_scsi_ioctl(sdp->device->request_queue, NULL, filp->f_mode, p);
1106 case SG_SET_DEBUG:
1107 result = get_user(val, ip);
1108 if (result)
1109 return result;
1110 sdp->sgdebug = (char) val;
1111 return 0;
1112 case BLKSECTGET:
1113 return put_user(max_sectors_bytes(sdp->device->request_queue),
1114 ip);
1115 case BLKTRACESETUP:
1116 return blk_trace_setup(sdp->device->request_queue,
1117 sdp->disk->disk_name,
1118 MKDEV(SCSI_GENERIC_MAJOR, sdp->index),
1119 NULL, p);
1120 case BLKTRACESTART:
1121 return blk_trace_startstop(sdp->device->request_queue, 1);
1122 case BLKTRACESTOP:
1123 return blk_trace_startstop(sdp->device->request_queue, 0);
1124 case BLKTRACETEARDOWN:
1125 return blk_trace_remove(sdp->device->request_queue);
1126 case SCSI_IOCTL_GET_IDLUN:
1127 case SCSI_IOCTL_GET_BUS_NUMBER:
1128 case SCSI_IOCTL_PROBE_HOST:
1129 case SG_GET_TRANSFORM:
1130 case SG_SCSI_RESET:
1131 if (atomic_read(&sdp->detaching))
1132 return -ENODEV;
1133 break;
1134 default:
1135 if (read_only)
1136 return -EPERM; /* don't know so take safe approach */
1137 break;
1138 }
1139
1140 result = scsi_ioctl_block_when_processing_errors(sdp->device,
1141 cmd_in, filp->f_flags & O_NDELAY);
1142 if (result)
1143 return result;
1144
> 1145 return -ENOIOCTLCMD;
1146 }
1147
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org
[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 25415 bytes --]
WARNING: multiple messages have this Message-ID (diff)
From: kernel test robot <lkp@intel.com>
To: Arnd Bergmann <arnd@arndb.de>
Cc: kbuild-all@lists.01.org, linux-kernel@vger.kernel.org,
Ben Hutchings <bwh@kernel.org>
Subject: drivers/scsi/sg.c:1145 sg_ioctl_common() warn: inconsistent returns 'sfp->rq_list_lock'.
Date: Tue, 18 Aug 2020 11:54:31 +0800 [thread overview]
Message-ID: <202008181128.mwASthcZ%lkp@intel.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 9448 bytes --]
tree: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
head: 06a4ec1d9dc652e17ee3ac2ceb6c7cf6c2b75cdd
commit: d320a9551e394cb2d842fd32d28e9805c2a18fbb compat_ioctl: scsi: move ioctl handling into drivers
date: 8 months ago
config: ia64-randconfig-m031-20200818 (attached as .config)
compiler: ia64-linux-gcc (GCC) 9.3.0
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
New smatch warnings:
drivers/scsi/sg.c:1145 sg_ioctl_common() warn: inconsistent returns 'sfp->rq_list_lock'.
Old smatch warnings:
drivers/scsi/sg.c:1094 sg_ioctl_common() warn: inconsistent indenting
# https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d320a9551e394cb2d842fd32d28e9805c2a18fbb
git remote add linus https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
git fetch --no-tags linus master
git checkout d320a9551e394cb2d842fd32d28e9805c2a18fbb
vim +1145 drivers/scsi/sg.c
912
913 static long
914 sg_ioctl_common(struct file *filp, Sg_device *sdp, Sg_fd *sfp,
915 unsigned int cmd_in, void __user *p)
916 {
917 int __user *ip = p;
918 int result, val, read_only;
919 Sg_request *srp;
920 unsigned long iflags;
921
922 SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp,
923 "sg_ioctl: cmd=0x%x\n", (int) cmd_in));
924 read_only = (O_RDWR != (filp->f_flags & O_ACCMODE));
925
926 switch (cmd_in) {
927 case SG_IO:
928 if (atomic_read(&sdp->detaching))
929 return -ENODEV;
930 if (!scsi_block_when_processing_errors(sdp->device))
931 return -ENXIO;
932 result = sg_new_write(sfp, filp, p, SZ_SG_IO_HDR,
933 1, read_only, 1, &srp);
934 if (result < 0)
935 return result;
936 result = wait_event_interruptible(sfp->read_wait,
937 (srp_done(sfp, srp) || atomic_read(&sdp->detaching)));
938 if (atomic_read(&sdp->detaching))
939 return -ENODEV;
940 write_lock_irq(&sfp->rq_list_lock);
941 if (srp->done) {
942 srp->done = 2;
943 write_unlock_irq(&sfp->rq_list_lock);
944 result = sg_new_read(sfp, p, SZ_SG_IO_HDR, srp);
945 return (result < 0) ? result : 0;
946 }
947 srp->orphan = 1;
948 write_unlock_irq(&sfp->rq_list_lock);
949 return result; /* -ERESTARTSYS because signal hit process */
950 case SG_SET_TIMEOUT:
951 result = get_user(val, ip);
952 if (result)
953 return result;
954 if (val < 0)
955 return -EIO;
956 if (val >= mult_frac((s64)INT_MAX, USER_HZ, HZ))
957 val = min_t(s64, mult_frac((s64)INT_MAX, USER_HZ, HZ),
958 INT_MAX);
959 sfp->timeout_user = val;
960 sfp->timeout = mult_frac(val, HZ, USER_HZ);
961
962 return 0;
963 case SG_GET_TIMEOUT: /* N.B. User receives timeout as return value */
964 /* strange ..., for backward compatibility */
965 return sfp->timeout_user;
966 case SG_SET_FORCE_LOW_DMA:
967 /*
968 * N.B. This ioctl never worked properly, but failed to
969 * return an error value. So returning '0' to keep compability
970 * with legacy applications.
971 */
972 return 0;
973 case SG_GET_LOW_DMA:
974 return put_user((int) sdp->device->host->unchecked_isa_dma, ip);
975 case SG_GET_SCSI_ID:
976 {
977 sg_scsi_id_t v;
978
979 if (atomic_read(&sdp->detaching))
980 return -ENODEV;
981 memset(&v, 0, sizeof(v));
982 v.host_no = sdp->device->host->host_no;
983 v.channel = sdp->device->channel;
984 v.scsi_id = sdp->device->id;
985 v.lun = sdp->device->lun;
986 v.scsi_type = sdp->device->type;
987 v.h_cmd_per_lun = sdp->device->host->cmd_per_lun;
988 v.d_queue_depth = sdp->device->queue_depth;
989 if (copy_to_user(p, &v, sizeof(sg_scsi_id_t)))
990 return -EFAULT;
991 return 0;
992 }
993 case SG_SET_FORCE_PACK_ID:
994 result = get_user(val, ip);
995 if (result)
996 return result;
997 sfp->force_packid = val ? 1 : 0;
998 return 0;
999 case SG_GET_PACK_ID:
1000 read_lock_irqsave(&sfp->rq_list_lock, iflags);
1001 list_for_each_entry(srp, &sfp->rq_list, entry) {
1002 if ((1 == srp->done) && (!srp->sg_io_owned)) {
1003 read_unlock_irqrestore(&sfp->rq_list_lock,
1004 iflags);
1005 return put_user(srp->header.pack_id, ip);
1006 }
1007 }
1008 read_unlock_irqrestore(&sfp->rq_list_lock, iflags);
1009 return put_user(-1, ip);
1010 case SG_GET_NUM_WAITING:
1011 read_lock_irqsave(&sfp->rq_list_lock, iflags);
1012 val = 0;
1013 list_for_each_entry(srp, &sfp->rq_list, entry) {
1014 if ((1 == srp->done) && (!srp->sg_io_owned))
1015 ++val;
1016 }
1017 read_unlock_irqrestore(&sfp->rq_list_lock, iflags);
1018 return put_user(val, ip);
1019 case SG_GET_SG_TABLESIZE:
1020 return put_user(sdp->sg_tablesize, ip);
1021 case SG_SET_RESERVED_SIZE:
1022 result = get_user(val, ip);
1023 if (result)
1024 return result;
1025 if (val < 0)
1026 return -EINVAL;
1027 val = min_t(int, val,
1028 max_sectors_bytes(sdp->device->request_queue));
1029 mutex_lock(&sfp->f_mutex);
1030 if (val != sfp->reserve.bufflen) {
1031 if (sfp->mmap_called ||
1032 sfp->res_in_use) {
1033 mutex_unlock(&sfp->f_mutex);
1034 return -EBUSY;
1035 }
1036
1037 sg_remove_scat(sfp, &sfp->reserve);
1038 sg_build_reserve(sfp, val);
1039 }
1040 mutex_unlock(&sfp->f_mutex);
1041 return 0;
1042 case SG_GET_RESERVED_SIZE:
1043 val = min_t(int, sfp->reserve.bufflen,
1044 max_sectors_bytes(sdp->device->request_queue));
1045 return put_user(val, ip);
1046 case SG_SET_COMMAND_Q:
1047 result = get_user(val, ip);
1048 if (result)
1049 return result;
1050 sfp->cmd_q = val ? 1 : 0;
1051 return 0;
1052 case SG_GET_COMMAND_Q:
1053 return put_user((int) sfp->cmd_q, ip);
1054 case SG_SET_KEEP_ORPHAN:
1055 result = get_user(val, ip);
1056 if (result)
1057 return result;
1058 sfp->keep_orphan = val;
1059 return 0;
1060 case SG_GET_KEEP_ORPHAN:
1061 return put_user((int) sfp->keep_orphan, ip);
1062 case SG_NEXT_CMD_LEN:
1063 result = get_user(val, ip);
1064 if (result)
1065 return result;
1066 if (val > SG_MAX_CDB_SIZE)
1067 return -ENOMEM;
1068 sfp->next_cmd_len = (val > 0) ? val : 0;
1069 return 0;
1070 case SG_GET_VERSION_NUM:
1071 return put_user(sg_version_num, ip);
1072 case SG_GET_ACCESS_COUNT:
1073 /* faked - we don't have a real access count anymore */
1074 val = (sdp->device ? 1 : 0);
1075 return put_user(val, ip);
1076 case SG_GET_REQUEST_TABLE:
1077 {
1078 sg_req_info_t *rinfo;
1079
1080 rinfo = kcalloc(SG_MAX_QUEUE, SZ_SG_REQ_INFO,
1081 GFP_KERNEL);
1082 if (!rinfo)
1083 return -ENOMEM;
1084 read_lock_irqsave(&sfp->rq_list_lock, iflags);
1085 sg_fill_request_table(sfp, rinfo);
1086 read_unlock_irqrestore(&sfp->rq_list_lock, iflags);
1087 #ifdef CONFIG_COMPAT
1088 if (in_compat_syscall())
1089 result = put_compat_request_table(p, rinfo);
1090 else
1091 #endif
1092 result = copy_to_user(p, rinfo,
1093 SZ_SG_REQ_INFO * SG_MAX_QUEUE);
1094 result = result ? -EFAULT : 0;
1095 kfree(rinfo);
1096 return result;
1097 }
1098 case SG_EMULATED_HOST:
1099 if (atomic_read(&sdp->detaching))
1100 return -ENODEV;
1101 return put_user(sdp->device->host->hostt->emulated, ip);
1102 case SCSI_IOCTL_SEND_COMMAND:
1103 if (atomic_read(&sdp->detaching))
1104 return -ENODEV;
1105 return sg_scsi_ioctl(sdp->device->request_queue, NULL, filp->f_mode, p);
1106 case SG_SET_DEBUG:
1107 result = get_user(val, ip);
1108 if (result)
1109 return result;
1110 sdp->sgdebug = (char) val;
1111 return 0;
1112 case BLKSECTGET:
1113 return put_user(max_sectors_bytes(sdp->device->request_queue),
1114 ip);
1115 case BLKTRACESETUP:
1116 return blk_trace_setup(sdp->device->request_queue,
1117 sdp->disk->disk_name,
1118 MKDEV(SCSI_GENERIC_MAJOR, sdp->index),
1119 NULL, p);
1120 case BLKTRACESTART:
1121 return blk_trace_startstop(sdp->device->request_queue, 1);
1122 case BLKTRACESTOP:
1123 return blk_trace_startstop(sdp->device->request_queue, 0);
1124 case BLKTRACETEARDOWN:
1125 return blk_trace_remove(sdp->device->request_queue);
1126 case SCSI_IOCTL_GET_IDLUN:
1127 case SCSI_IOCTL_GET_BUS_NUMBER:
1128 case SCSI_IOCTL_PROBE_HOST:
1129 case SG_GET_TRANSFORM:
1130 case SG_SCSI_RESET:
1131 if (atomic_read(&sdp->detaching))
1132 return -ENODEV;
1133 break;
1134 default:
1135 if (read_only)
1136 return -EPERM; /* don't know so take safe approach */
1137 break;
1138 }
1139
1140 result = scsi_ioctl_block_when_processing_errors(sdp->device,
1141 cmd_in, filp->f_flags & O_NDELAY);
1142 if (result)
1143 return result;
1144
> 1145 return -ENOIOCTLCMD;
1146 }
1147
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 25415 bytes --]
next reply other threads:[~2020-08-18 3:54 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-08-18 3:54 kernel test robot [this message]
2020-08-18 3:54 ` drivers/scsi/sg.c:1145 sg_ioctl_common() warn: inconsistent returns 'sfp->rq_list_lock' kernel test robot
-- strict thread matches above, loose matches on Subject: below --
2020-11-09 11:41 kernel test robot
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=202008181128.mwASthcZ%lkp@intel.com \
--to=lkp@intel.com \
--cc=kbuild-all@lists.01.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.