* [PATCH v1] Bluetooth: btintel_pcie: Avoid redundant buffer allocation
@ 2025-04-02 2:20 Kiran K
2025-04-02 3:04 ` [v1] " bluez.test.bot
2025-04-02 20:57 ` [PATCH v1] " Luiz Augusto von Dentz
0 siblings, 2 replies; 4+ messages in thread
From: Kiran K @ 2025-04-02 2:20 UTC (permalink / raw)
To: linux-bluetooth
Cc: ravishankar.srivatsa, chethan.tumkur.narayan,
chandrashekar.devegowda, vijay.satija, Kiran K
Reuse the skb buffer provided by the PCIe driver to pass it onto the
stack, instead of copying it to a new skb.
Fixes: c2b636b3f788 ("Bluetooth: btintel_pcie: Add support for PCIe transport")
Signed-off-by: Kiran K <kiran.k@intel.com>
---
drivers/bluetooth/btintel_pcie.c | 58 ++++++++++++--------------------
1 file changed, 22 insertions(+), 36 deletions(-)
diff --git a/drivers/bluetooth/btintel_pcie.c b/drivers/bluetooth/btintel_pcie.c
index e0b50513403f..ebc36fd33de8 100644
--- a/drivers/bluetooth/btintel_pcie.c
+++ b/drivers/bluetooth/btintel_pcie.c
@@ -947,8 +947,10 @@ static int btintel_pcie_recv_event(struct hci_dev *hdev, struct sk_buff *skb)
/* This is a debug event that comes from IML and OP image when it
* starts execution. There is no need pass this event to stack.
*/
- if (skb->data[2] == 0x97)
+ if (skb->data[2] == 0x97) {
+ kfree_skb(skb);
return 0;
+ }
}
return hci_recv_frame(hdev, skb);
@@ -964,7 +966,6 @@ static int btintel_pcie_recv_frame(struct btintel_pcie_data *data,
u8 pkt_type;
u16 plen;
u32 pcie_pkt_type;
- struct sk_buff *new_skb;
void *pdata;
struct hci_dev *hdev = data->hdev;
@@ -974,8 +975,7 @@ static int btintel_pcie_recv_frame(struct btintel_pcie_data *data,
pdata = skb_pull_data(skb, BTINTEL_PCIE_HCI_TYPE_LEN);
if (!pdata) {
bt_dev_err(hdev, "Corrupted packet received");
- ret = -EILSEQ;
- goto exit_error;
+ goto no_or_short_data;
}
pcie_pkt_type = get_unaligned_le32(pdata);
@@ -987,8 +987,7 @@ static int btintel_pcie_recv_frame(struct btintel_pcie_data *data,
pkt_type = HCI_ACLDATA_PKT;
} else {
bt_dev_err(hdev, "ACL packet is too short");
- ret = -EILSEQ;
- goto exit_error;
+ goto no_or_short_data;
}
break;
@@ -998,8 +997,7 @@ static int btintel_pcie_recv_frame(struct btintel_pcie_data *data,
pkt_type = HCI_SCODATA_PKT;
} else {
bt_dev_err(hdev, "SCO packet is too short");
- ret = -EILSEQ;
- goto exit_error;
+ goto no_or_short_data;
}
break;
@@ -1009,8 +1007,7 @@ static int btintel_pcie_recv_frame(struct btintel_pcie_data *data,
pkt_type = HCI_EVENT_PKT;
} else {
bt_dev_err(hdev, "Event packet is too short");
- ret = -EILSEQ;
- goto exit_error;
+ goto no_or_short_data;
}
break;
@@ -1020,45 +1017,40 @@ static int btintel_pcie_recv_frame(struct btintel_pcie_data *data,
pkt_type = HCI_ISODATA_PKT;
} else {
bt_dev_err(hdev, "ISO packet is too short");
- ret = -EILSEQ;
- goto exit_error;
+ goto no_or_short_data;
}
break;
default:
bt_dev_err(hdev, "Invalid packet type received: 0x%4.4x",
pcie_pkt_type);
- ret = -EINVAL;
- goto exit_error;
+ goto no_or_short_data;
}
if (skb->len < plen) {
bt_dev_err(hdev, "Received corrupted packet. type: 0x%2.2x",
pkt_type);
- ret = -EILSEQ;
- goto exit_error;
+ goto no_or_short_data;
}
bt_dev_dbg(hdev, "pkt_type: 0x%2.2x len: %u", pkt_type, plen);
- new_skb = bt_skb_alloc(plen, GFP_ATOMIC);
- if (!new_skb) {
- bt_dev_err(hdev, "Failed to allocate memory for skb of len: %u",
- skb->len);
- ret = -ENOMEM;
- goto exit_error;
- }
-
- hci_skb_pkt_type(new_skb) = pkt_type;
- skb_put_data(new_skb, skb->data, plen);
+ hci_skb_pkt_type(skb) = pkt_type;
hdev->stat.byte_rx += plen;
+ skb_trim(skb, plen);
if (pcie_pkt_type == BTINTEL_PCIE_HCI_EVT_PKT)
- ret = btintel_pcie_recv_event(hdev, new_skb);
+ ret = btintel_pcie_recv_event(hdev, skb);
else
- ret = hci_recv_frame(hdev, new_skb);
+ ret = hci_recv_frame(hdev, skb);
-exit_error:
+goto out;
+
+no_or_short_data:
+ ret = -EILSEQ;
+ kfree_skb(skb);
+
+out:
if (ret)
hdev->stat.err_rx++;
@@ -1192,8 +1184,6 @@ static void btintel_pcie_rx_work(struct work_struct *work)
struct btintel_pcie_data *data = container_of(work,
struct btintel_pcie_data, rx_work);
struct sk_buff *skb;
- int err;
- struct hci_dev *hdev = data->hdev;
if (test_bit(BTINTEL_PCIE_HWEXP_INPROGRESS, &data->flags)) {
/* Unlike usb products, controller will not send hardware
@@ -1214,11 +1204,7 @@ static void btintel_pcie_rx_work(struct work_struct *work)
/* Process the sk_buf in queue and send to the HCI layer */
while ((skb = skb_dequeue(&data->rx_skb_q))) {
- err = btintel_pcie_recv_frame(data, skb);
- if (err)
- bt_dev_err(hdev, "Failed to send received frame: %d",
- err);
- kfree_skb(skb);
+ btintel_pcie_recv_frame(data, skb);
}
}
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* RE: [v1] Bluetooth: btintel_pcie: Avoid redundant buffer allocation
2025-04-02 2:20 [PATCH v1] Bluetooth: btintel_pcie: Avoid redundant buffer allocation Kiran K
@ 2025-04-02 3:04 ` bluez.test.bot
2025-04-02 20:57 ` [PATCH v1] " Luiz Augusto von Dentz
1 sibling, 0 replies; 4+ messages in thread
From: bluez.test.bot @ 2025-04-02 3:04 UTC (permalink / raw)
To: linux-bluetooth, kiran.k
[-- Attachment #1: Type: text/plain, Size: 2087 bytes --]
This is automated email and please do not reply to this email!
Dear submitter,
Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=949144
---Test result---
Test Summary:
CheckPatch PENDING 0.28 seconds
GitLint PENDING 0.26 seconds
SubjectPrefix PASS 0.12 seconds
BuildKernel PASS 24.57 seconds
CheckAllWarning PASS 26.86 seconds
CheckSparse PASS 30.99 seconds
BuildKernel32 PASS 24.06 seconds
TestRunnerSetup PASS 432.91 seconds
TestRunner_l2cap-tester PASS 21.22 seconds
TestRunner_iso-tester PASS 39.09 seconds
TestRunner_bnep-tester PASS 4.78 seconds
TestRunner_mgmt-tester PASS 120.00 seconds
TestRunner_rfcomm-tester PASS 7.84 seconds
TestRunner_sco-tester PASS 12.58 seconds
TestRunner_ioctl-tester PASS 8.33 seconds
TestRunner_mesh-tester FAIL 8.25 seconds
TestRunner_smp-tester PASS 7.19 seconds
TestRunner_userchan-tester PASS 4.93 seconds
IncrementalBuild PENDING 0.76 seconds
Details
##############################
Test: CheckPatch - PENDING
Desc: Run checkpatch.pl script
Output:
##############################
Test: GitLint - PENDING
Desc: Run gitlint
Output:
##############################
Test: TestRunner_mesh-tester - FAIL
Desc: Run mesh-tester with test-runner
Output:
BUG: KASAN: slab-use-after-free in run_timer_softirq+0x76f/0x7d0
WARNING: CPU: 0 PID: 36 at kernel/workqueue.c:2257 __queue_work+0x93e/0xba0
Total: 10, Passed: 9 (90.0%), Failed: 1, Not Run: 0
Failed Test Cases
Mesh - Send cancel - 1 Failed 0.116 seconds
##############################
Test: IncrementalBuild - PENDING
Desc: Incremental build with the patches in the series
Output:
---
Regards,
Linux Bluetooth
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v1] Bluetooth: btintel_pcie: Avoid redundant buffer allocation
2025-04-02 2:20 [PATCH v1] Bluetooth: btintel_pcie: Avoid redundant buffer allocation Kiran K
2025-04-02 3:04 ` [v1] " bluez.test.bot
@ 2025-04-02 20:57 ` Luiz Augusto von Dentz
2025-04-14 12:53 ` K, Kiran
1 sibling, 1 reply; 4+ messages in thread
From: Luiz Augusto von Dentz @ 2025-04-02 20:57 UTC (permalink / raw)
To: Kiran K
Cc: linux-bluetooth, ravishankar.srivatsa, chethan.tumkur.narayan,
chandrashekar.devegowda, vijay.satija
Hi Kiran,
On Tue, Apr 1, 2025 at 10:04 PM Kiran K <kiran.k@intel.com> wrote:
>
> Reuse the skb buffer provided by the PCIe driver to pass it onto the
> stack, instead of copying it to a new skb.
>
> Fixes: c2b636b3f788 ("Bluetooth: btintel_pcie: Add support for PCIe transport")
> Signed-off-by: Kiran K <kiran.k@intel.com>
> ---
> drivers/bluetooth/btintel_pcie.c | 58 ++++++++++++--------------------
> 1 file changed, 22 insertions(+), 36 deletions(-)
>
> diff --git a/drivers/bluetooth/btintel_pcie.c b/drivers/bluetooth/btintel_pcie.c
> index e0b50513403f..ebc36fd33de8 100644
> --- a/drivers/bluetooth/btintel_pcie.c
> +++ b/drivers/bluetooth/btintel_pcie.c
> @@ -947,8 +947,10 @@ static int btintel_pcie_recv_event(struct hci_dev *hdev, struct sk_buff *skb)
> /* This is a debug event that comes from IML and OP image when it
> * starts execution. There is no need pass this event to stack.
Is this logged/sent to monitor at least?
> */
> - if (skb->data[2] == 0x97)
> + if (skb->data[2] == 0x97) {
> + kfree_skb(skb);
> return 0;
> + }
> }
>
> return hci_recv_frame(hdev, skb);
> @@ -964,7 +966,6 @@ static int btintel_pcie_recv_frame(struct btintel_pcie_data *data,
> u8 pkt_type;
> u16 plen;
> u32 pcie_pkt_type;
> - struct sk_buff *new_skb;
> void *pdata;
> struct hci_dev *hdev = data->hdev;
>
> @@ -974,8 +975,7 @@ static int btintel_pcie_recv_frame(struct btintel_pcie_data *data,
> pdata = skb_pull_data(skb, BTINTEL_PCIE_HCI_TYPE_LEN);
> if (!pdata) {
> bt_dev_err(hdev, "Corrupted packet received");
> - ret = -EILSEQ;
> - goto exit_error;
> + goto no_or_short_data;
> }
>
> pcie_pkt_type = get_unaligned_le32(pdata);
> @@ -987,8 +987,7 @@ static int btintel_pcie_recv_frame(struct btintel_pcie_data *data,
> pkt_type = HCI_ACLDATA_PKT;
> } else {
> bt_dev_err(hdev, "ACL packet is too short");
> - ret = -EILSEQ;
> - goto exit_error;
> + goto no_or_short_data;
> }
> break;
>
> @@ -998,8 +997,7 @@ static int btintel_pcie_recv_frame(struct btintel_pcie_data *data,
> pkt_type = HCI_SCODATA_PKT;
> } else {
> bt_dev_err(hdev, "SCO packet is too short");
> - ret = -EILSEQ;
> - goto exit_error;
> + goto no_or_short_data;
> }
> break;
>
> @@ -1009,8 +1007,7 @@ static int btintel_pcie_recv_frame(struct btintel_pcie_data *data,
> pkt_type = HCI_EVENT_PKT;
> } else {
> bt_dev_err(hdev, "Event packet is too short");
> - ret = -EILSEQ;
> - goto exit_error;
> + goto no_or_short_data;
> }
> break;
>
> @@ -1020,45 +1017,40 @@ static int btintel_pcie_recv_frame(struct btintel_pcie_data *data,
> pkt_type = HCI_ISODATA_PKT;
> } else {
> bt_dev_err(hdev, "ISO packet is too short");
> - ret = -EILSEQ;
> - goto exit_error;
> + goto no_or_short_data;
> }
> break;
>
> default:
> bt_dev_err(hdev, "Invalid packet type received: 0x%4.4x",
> pcie_pkt_type);
> - ret = -EINVAL;
> - goto exit_error;
> + goto no_or_short_data;
> }
>
> if (skb->len < plen) {
> bt_dev_err(hdev, "Received corrupted packet. type: 0x%2.2x",
> pkt_type);
> - ret = -EILSEQ;
> - goto exit_error;
> + goto no_or_short_data;
> }
>
> bt_dev_dbg(hdev, "pkt_type: 0x%2.2x len: %u", pkt_type, plen);
>
> - new_skb = bt_skb_alloc(plen, GFP_ATOMIC);
> - if (!new_skb) {
> - bt_dev_err(hdev, "Failed to allocate memory for skb of len: %u",
> - skb->len);
> - ret = -ENOMEM;
> - goto exit_error;
> - }
> -
> - hci_skb_pkt_type(new_skb) = pkt_type;
> - skb_put_data(new_skb, skb->data, plen);
> + hci_skb_pkt_type(skb) = pkt_type;
> hdev->stat.byte_rx += plen;
> + skb_trim(skb, plen);
>
> if (pcie_pkt_type == BTINTEL_PCIE_HCI_EVT_PKT)
> - ret = btintel_pcie_recv_event(hdev, new_skb);
> + ret = btintel_pcie_recv_event(hdev, skb);
> else
> - ret = hci_recv_frame(hdev, new_skb);
> + ret = hci_recv_frame(hdev, skb);
>
> -exit_error:
> +goto out;
> +
> +no_or_short_data:
> + ret = -EILSEQ;
> + kfree_skb(skb);
Don't really like where this is going, having a goto label to cleanup
is fine, having multiple and the having to figure out which one does
what is rather confusing and doesn't help that much, anyway if we got
a negative ret you can probably just make it drop the skb on the if
(ret) statement.
> +out:
> if (ret)
> hdev->stat.err_rx++;
>
> @@ -1192,8 +1184,6 @@ static void btintel_pcie_rx_work(struct work_struct *work)
> struct btintel_pcie_data *data = container_of(work,
> struct btintel_pcie_data, rx_work);
> struct sk_buff *skb;
> - int err;
> - struct hci_dev *hdev = data->hdev;
>
> if (test_bit(BTINTEL_PCIE_HWEXP_INPROGRESS, &data->flags)) {
> /* Unlike usb products, controller will not send hardware
> @@ -1214,11 +1204,7 @@ static void btintel_pcie_rx_work(struct work_struct *work)
>
> /* Process the sk_buf in queue and send to the HCI layer */
> while ((skb = skb_dequeue(&data->rx_skb_q))) {
> - err = btintel_pcie_recv_frame(data, skb);
> - if (err)
> - bt_dev_err(hdev, "Failed to send received frame: %d",
> - err);
> - kfree_skb(skb);
> + btintel_pcie_recv_frame(data, skb);
> }
> }
>
> --
> 2.43.0
>
>
--
Luiz Augusto von Dentz
^ permalink raw reply [flat|nested] 4+ messages in thread
* RE: [PATCH v1] Bluetooth: btintel_pcie: Avoid redundant buffer allocation
2025-04-02 20:57 ` [PATCH v1] " Luiz Augusto von Dentz
@ 2025-04-14 12:53 ` K, Kiran
0 siblings, 0 replies; 4+ messages in thread
From: K, Kiran @ 2025-04-14 12:53 UTC (permalink / raw)
To: Luiz Augusto von Dentz
Cc: linux-bluetooth@vger.kernel.org, Srivatsa, Ravishankar,
Tumkur Narayan, Chethan, Devegowda, Chandrashekar, Satija, Vijay
Hi Luiz,
Thanks for your comments.
>Subject: Re: [PATCH v1] Bluetooth: btintel_pcie: Avoid redundant buffer
>allocation
>
>Hi Kiran,
>
>On Tue, Apr 1, 2025 at 10:04 PM Kiran K <kiran.k@intel.com> wrote:
>>
>> Reuse the skb buffer provided by the PCIe driver to pass it onto the
>> stack, instead of copying it to a new skb.
>>
>> Fixes: c2b636b3f788 ("Bluetooth: btintel_pcie: Add support for PCIe
>> transport")
>> Signed-off-by: Kiran K <kiran.k@intel.com>
>> ---
>> drivers/bluetooth/btintel_pcie.c | 58
>> ++++++++++++--------------------
>> 1 file changed, 22 insertions(+), 36 deletions(-)
>>
>> diff --git a/drivers/bluetooth/btintel_pcie.c
>> b/drivers/bluetooth/btintel_pcie.c
>> index e0b50513403f..ebc36fd33de8 100644
>> --- a/drivers/bluetooth/btintel_pcie.c
>> +++ b/drivers/bluetooth/btintel_pcie.c
>> @@ -947,8 +947,10 @@ static int btintel_pcie_recv_event(struct hci_dev
>*hdev, struct sk_buff *skb)
>> /* This is a debug event that comes from IML and OP image when it
>> * starts execution. There is no need pass this event to stack.
>
>Is this logged/sent to monitor at least?
No. I will log part HCI traces in the V2 version of the patch.
>
>> */
>> - if (skb->data[2] == 0x97)
>> + if (skb->data[2] == 0x97) {
>> + kfree_skb(skb);
>> return 0;
>> + }
>> }
>>
>> return hci_recv_frame(hdev, skb); @@ -964,7 +966,6 @@ static
>> int btintel_pcie_recv_frame(struct btintel_pcie_data *data,
>> u8 pkt_type;
>> u16 plen;
>> u32 pcie_pkt_type;
>> - struct sk_buff *new_skb;
>> void *pdata;
>> struct hci_dev *hdev = data->hdev;
>>
>> @@ -974,8 +975,7 @@ static int btintel_pcie_recv_frame(struct
>btintel_pcie_data *data,
>> pdata = skb_pull_data(skb, BTINTEL_PCIE_HCI_TYPE_LEN);
>> if (!pdata) {
>> bt_dev_err(hdev, "Corrupted packet received");
>> - ret = -EILSEQ;
>> - goto exit_error;
>> + goto no_or_short_data;
>> }
>>
>> pcie_pkt_type = get_unaligned_le32(pdata); @@ -987,8 +987,7 @@
>> static int btintel_pcie_recv_frame(struct btintel_pcie_data *data,
>> pkt_type = HCI_ACLDATA_PKT;
>> } else {
>> bt_dev_err(hdev, "ACL packet is too short");
>> - ret = -EILSEQ;
>> - goto exit_error;
>> + goto no_or_short_data;
>> }
>> break;
>>
>> @@ -998,8 +997,7 @@ static int btintel_pcie_recv_frame(struct
>btintel_pcie_data *data,
>> pkt_type = HCI_SCODATA_PKT;
>> } else {
>> bt_dev_err(hdev, "SCO packet is too short");
>> - ret = -EILSEQ;
>> - goto exit_error;
>> + goto no_or_short_data;
>> }
>> break;
>>
>> @@ -1009,8 +1007,7 @@ static int btintel_pcie_recv_frame(struct
>btintel_pcie_data *data,
>> pkt_type = HCI_EVENT_PKT;
>> } else {
>> bt_dev_err(hdev, "Event packet is too short");
>> - ret = -EILSEQ;
>> - goto exit_error;
>> + goto no_or_short_data;
>> }
>> break;
>>
>> @@ -1020,45 +1017,40 @@ static int btintel_pcie_recv_frame(struct
>btintel_pcie_data *data,
>> pkt_type = HCI_ISODATA_PKT;
>> } else {
>> bt_dev_err(hdev, "ISO packet is too short");
>> - ret = -EILSEQ;
>> - goto exit_error;
>> + goto no_or_short_data;
>> }
>> break;
>>
>> default:
>> bt_dev_err(hdev, "Invalid packet type received: 0x%4.4x",
>> pcie_pkt_type);
>> - ret = -EINVAL;
>> - goto exit_error;
>> + goto no_or_short_data;
>> }
>>
>> if (skb->len < plen) {
>> bt_dev_err(hdev, "Received corrupted packet. type: 0x%2.2x",
>> pkt_type);
>> - ret = -EILSEQ;
>> - goto exit_error;
>> + goto no_or_short_data;
>> }
>>
>> bt_dev_dbg(hdev, "pkt_type: 0x%2.2x len: %u", pkt_type, plen);
>>
>> - new_skb = bt_skb_alloc(plen, GFP_ATOMIC);
>> - if (!new_skb) {
>> - bt_dev_err(hdev, "Failed to allocate memory for skb of len: %u",
>> - skb->len);
>> - ret = -ENOMEM;
>> - goto exit_error;
>> - }
>> -
>> - hci_skb_pkt_type(new_skb) = pkt_type;
>> - skb_put_data(new_skb, skb->data, plen);
>> + hci_skb_pkt_type(skb) = pkt_type;
>> hdev->stat.byte_rx += plen;
>> + skb_trim(skb, plen);
>>
>> if (pcie_pkt_type == BTINTEL_PCIE_HCI_EVT_PKT)
>> - ret = btintel_pcie_recv_event(hdev, new_skb);
>> + ret = btintel_pcie_recv_event(hdev, skb);
>> else
>> - ret = hci_recv_frame(hdev, new_skb);
>> + ret = hci_recv_frame(hdev, skb);
>>
>> -exit_error:
>> +goto out;
>> +
>> +no_or_short_data:
>> + ret = -EILSEQ;
>> + kfree_skb(skb);
>
>Don't really like where this is going, having a goto label to cleanup is fine,
>having multiple and the having to figure out which one does what is rather
>confusing and doesn't help that much, anyway if we got a negative ret you can
>probably just make it drop the skb on the if
>(ret) statement.
Ok. I will revisit this patch and try to make it more readable.
>
>> +out:
>> if (ret)
>> hdev->stat.err_rx++;
>>
>> @@ -1192,8 +1184,6 @@ static void btintel_pcie_rx_work(struct work_struct
>*work)
>> struct btintel_pcie_data *data = container_of(work,
>> struct btintel_pcie_data, rx_work);
>> struct sk_buff *skb;
>> - int err;
>> - struct hci_dev *hdev = data->hdev;
>>
>> if (test_bit(BTINTEL_PCIE_HWEXP_INPROGRESS, &data->flags)) {
>> /* Unlike usb products, controller will not send
>> hardware @@ -1214,11 +1204,7 @@ static void
>> btintel_pcie_rx_work(struct work_struct *work)
>>
>> /* Process the sk_buf in queue and send to the HCI layer */
>> while ((skb = skb_dequeue(&data->rx_skb_q))) {
>> - err = btintel_pcie_recv_frame(data, skb);
>> - if (err)
>> - bt_dev_err(hdev, "Failed to send received frame: %d",
>> - err);
>> - kfree_skb(skb);
>> + btintel_pcie_recv_frame(data, skb);
>> }
>> }
>>
>> --
>> 2.43.0
>>
>>
>
>
>--
>Luiz Augusto von Dentz
Regards,
Kiran
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2025-04-14 12:54 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-04-02 2:20 [PATCH v1] Bluetooth: btintel_pcie: Avoid redundant buffer allocation Kiran K
2025-04-02 3:04 ` [v1] " bluez.test.bot
2025-04-02 20:57 ` [PATCH v1] " Luiz Augusto von Dentz
2025-04-14 12:53 ` K, Kiran
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.