linux-nvme.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] nvmet: fixup processing async events
@ 2020-05-18 17:03 David Milburn
  2020-05-18 17:03 ` [PATCH 1/2] nvmet: check command slot before pulling and freeing aen David Milburn
  2020-05-18 17:03 ` [PATCH 2/2] nvmet: avoid memleak by freeing any remaining aens in nvmet_async_events_free David Milburn
  0 siblings, 2 replies; 5+ messages in thread
From: David Milburn @ 2020-05-18 17:03 UTC (permalink / raw)
  To: linux-nvme; +Cc: hch, chaitanya.kulkarni, dwagner

This patch series changes how async events are processed
and freed based upon review from Christoph Hellwig and
Daniel Wagner, this was discovered while debugging a memory 
leak after clearing connection on the target.


_______________________________________________
linux-nvme mailing list
linux-nvme@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-nvme

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/2] nvmet: check command slot before pulling and freeing aen
  2020-05-18 17:03 [PATCH 0/2] nvmet: fixup processing async events David Milburn
@ 2020-05-18 17:03 ` David Milburn
  2020-05-18 17:07   ` Christoph Hellwig
  2020-05-18 17:03 ` [PATCH 2/2] nvmet: avoid memleak by freeing any remaining aens in nvmet_async_events_free David Milburn
  1 sibling, 1 reply; 5+ messages in thread
From: David Milburn @ 2020-05-18 17:03 UTC (permalink / raw)
  To: linux-nvme; +Cc: hch, chaitanya.kulkarni, dwagner

Free aens while completing requests in nvmet_async_events_process() and
nvmet_async_events_free().

Based-on-a-patch-by: Christoph Hellwig <hch@infradead.org>
Tested-by: Yi Zhang <yi.zhang@redhat.com>
Signed-off-by: David Milburn <dmilburn@redhat.com>
---
 drivers/nvme/target/core.c | 23 +++++++++++++----------
 1 file changed, 13 insertions(+), 10 deletions(-)

diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c
index b685f99d56a1..c9d74ebeaa7d 100644
--- a/drivers/nvme/target/core.c
+++ b/drivers/nvme/target/core.c
@@ -134,15 +134,10 @@ static void nvmet_async_events_process(struct nvmet_ctrl *ctrl, u16 status)
 	struct nvmet_async_event *aen;
 	struct nvmet_req *req;
 
-	while (1) {
-		mutex_lock(&ctrl->lock);
-		aen = list_first_entry_or_null(&ctrl->async_events,
-				struct nvmet_async_event, entry);
-		if (!aen || !ctrl->nr_async_event_cmds) {
-			mutex_unlock(&ctrl->lock);
-			break;
-		}
-
+	mutex_lock(&ctrl->lock);
+	while (ctrl->nr_async_event_cmds && !list_empty(&ctrl->async_events)) {
+		aen = list_first_entry(&ctrl->async_events,
+				       struct nvmet_async_event, entry);
 		req = ctrl->async_event_cmds[--ctrl->nr_async_event_cmds];
 		if (status == 0)
 			nvmet_set_result(req, nvmet_async_event_result(aen));
@@ -152,15 +147,23 @@ static void nvmet_async_events_process(struct nvmet_ctrl *ctrl, u16 status)
 
 		mutex_unlock(&ctrl->lock);
 		nvmet_req_complete(req, status);
+		mutex_lock(&ctrl->lock);
 	}
+	mutex_unlock(&ctrl->lock);
 }
 
 static void nvmet_async_events_free(struct nvmet_ctrl *ctrl)
 {
+	struct nvmet_async_event *aen;
 	struct nvmet_req *req;
 
 	mutex_lock(&ctrl->lock);
-	while (ctrl->nr_async_event_cmds) {
+	while (ctrl->nr_async_event_cmds && !list_empty(&ctrl->async_events)) {
+		aen = list_first_entry(&ctrl->async_events,
+				       struct nvmet_async_event, entry);
+		list_del(&aen->entry);
+		kfree(aen);
+	  
 		req = ctrl->async_event_cmds[--ctrl->nr_async_event_cmds];
 		mutex_unlock(&ctrl->lock);
 		nvmet_req_complete(req, NVME_SC_INTERNAL | NVME_SC_DNR);
-- 
2.18.1


_______________________________________________
linux-nvme mailing list
linux-nvme@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-nvme

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/2] nvmet: avoid memleak by freeing any remaining aens in nvmet_async_events_free
  2020-05-18 17:03 [PATCH 0/2] nvmet: fixup processing async events David Milburn
  2020-05-18 17:03 ` [PATCH 1/2] nvmet: check command slot before pulling and freeing aen David Milburn
@ 2020-05-18 17:03 ` David Milburn
  1 sibling, 0 replies; 5+ messages in thread
From: David Milburn @ 2020-05-18 17:03 UTC (permalink / raw)
  To: linux-nvme; +Cc: hch, chaitanya.kulkarni, dwagner

Make sure we free all resources including any remaining aens
which may result in a memory leak.

$ cat /sys/kernel/debug/kmemleak
unreferenced object 0xffff888c1af2c000 (size 32):
  comm "nvmetcli", pid 5164, jiffies 4295220864 (age 6829.924s)
  hex dump (first 32 bytes):
    28 01 82 3b 8b 88 ff ff 28 01 82 3b 8b 88 ff ff  (..;....(..;....
    02 00 04 65 76 65 6e 74 5f 66 69 6c 65 00 00 00  ...event_file...
  backtrace:
    [<00000000217ae580>] nvmet_add_async_event+0x57/0x290 [nvmet]
    [<0000000012aa2ea9>] nvmet_ns_changed+0x206/0x300 [nvmet]
    [<00000000bb3fd52e>] nvmet_ns_disable+0x367/0x4f0 [nvmet]
    [<00000000e91ca9ec>] nvmet_ns_free+0x15/0x180 [nvmet]
    [<00000000a15deb52>] config_item_release+0xf1/0x1c0
    [<000000007e148432>] configfs_rmdir+0x555/0x7c0
    [<00000000f4506ea6>] vfs_rmdir+0x142/0x3c0
    [<0000000000acaaf0>] do_rmdir+0x2b2/0x340
    [<0000000034d1aa52>] do_syscall_64+0xa5/0x4d0
    [<00000000211f13bc>] entry_SYSCALL_64_after_hwframe+0x6a/0xdf

Steps to Reproduce:

target:
1. nvmetcli restore rdma.json

client:
2. nvme connect -t rdma -a $IP -s 4420 -n testnqn

target:
3. nvmetcli clear
4. sleep 5 && nvmetcli restore rdma.json
5. cat /sys/kernel/debug/kmemleak after 5 minutes

Reported-by: Yi Zhang <yi.zhang@redhat.com>
Signed-off-by: David Milburn <dmilburn@redhatcom>
---
 drivers/nvme/target/core.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c
index c9d74ebeaa7d..091d3c9ee490 100644
--- a/drivers/nvme/target/core.c
+++ b/drivers/nvme/target/core.c
@@ -169,6 +169,13 @@ static void nvmet_async_events_free(struct nvmet_ctrl *ctrl)
 		nvmet_req_complete(req, NVME_SC_INTERNAL | NVME_SC_DNR);
 		mutex_lock(&ctrl->lock);
 	}
+
+	while (!list_empty(&ctrl->async_events)) {
+		aen = list_first_entry(&ctrl->async_events,
+				       struct nvmet_async_event, entry);
+		list_del(&aen->entry);
+		kfree(aen);
+	}
 	mutex_unlock(&ctrl->lock);
 }
 
-- 
2.18.1


_______________________________________________
linux-nvme mailing list
linux-nvme@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-nvme

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/2] nvmet: check command slot before pulling and freeing aen
  2020-05-18 17:03 ` [PATCH 1/2] nvmet: check command slot before pulling and freeing aen David Milburn
@ 2020-05-18 17:07   ` Christoph Hellwig
  2020-05-18 17:16     ` David Milburn
  0 siblings, 1 reply; 5+ messages in thread
From: Christoph Hellwig @ 2020-05-18 17:07 UTC (permalink / raw)
  To: David Milburn; +Cc: chaitanya.kulkarni, hch, dwagner, linux-nvme

On Mon, May 18, 2020 at 12:03:05PM -0500, David Milburn wrote:
>  static void nvmet_async_events_free(struct nvmet_ctrl *ctrl)
>  {
> +	struct nvmet_async_event *aen;
>  	struct nvmet_req *req;
>  
>  	mutex_lock(&ctrl->lock);
> -	while (ctrl->nr_async_event_cmds) {
> +	while (ctrl->nr_async_event_cmds && !list_empty(&ctrl->async_events)) {
> +		aen = list_first_entry(&ctrl->async_events,
> +				       struct nvmet_async_event, entry);
> +		list_del(&aen->entry);
> +		kfree(aen);
> +	  
>  		req = ctrl->async_event_cmds[--ctrl->nr_async_event_cmds];
>  		mutex_unlock(&ctrl->lock);
>  		nvmet_req_complete(req, NVME_SC_INTERNAL | NVME_SC_DNR);

I don't think this change is correct.  This loop just needs to complete
all the requests that the host sent.

The new loop added in the new patch should free any aens still queued
on ->async_events, but be totally separate from the loop over the
requests.

_______________________________________________
linux-nvme mailing list
linux-nvme@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-nvme

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/2] nvmet: check command slot before pulling and freeing aen
  2020-05-18 17:07   ` Christoph Hellwig
@ 2020-05-18 17:16     ` David Milburn
  0 siblings, 0 replies; 5+ messages in thread
From: David Milburn @ 2020-05-18 17:16 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: chaitanya.kulkarni, dwagner, linux-nvme

On 05/18/2020 12:07 PM, Christoph Hellwig wrote:
> On Mon, May 18, 2020 at 12:03:05PM -0500, David Milburn wrote:
>>   static void nvmet_async_events_free(struct nvmet_ctrl *ctrl)
>>   {
>> +	struct nvmet_async_event *aen;
>>   	struct nvmet_req *req;
>>   
>>   	mutex_lock(&ctrl->lock);
>> -	while (ctrl->nr_async_event_cmds) {
>> +	while (ctrl->nr_async_event_cmds && !list_empty(&ctrl->async_events)) {
>> +		aen = list_first_entry(&ctrl->async_events,
>> +				       struct nvmet_async_event, entry);
>> +		list_del(&aen->entry);
>> +		kfree(aen);
>> +	
>>   		req = ctrl->async_event_cmds[--ctrl->nr_async_event_cmds];
>>   		mutex_unlock(&ctrl->lock);
>>   		nvmet_req_complete(req, NVME_SC_INTERNAL | NVME_SC_DNR);
> 
> I don't think this change is correct.  This loop just needs to complete
> all the requests that the host sent.
> 
> The new loop added in the new patch should free any aens still queued
> on ->async_events, but be totally separate from the loop over the
> requests.
> 

Yes, right, sorry I will fix that and resend.

Thanks,
David


_______________________________________________
linux-nvme mailing list
linux-nvme@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-nvme

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2020-05-18 17:16 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-18 17:03 [PATCH 0/2] nvmet: fixup processing async events David Milburn
2020-05-18 17:03 ` [PATCH 1/2] nvmet: check command slot before pulling and freeing aen David Milburn
2020-05-18 17:07   ` Christoph Hellwig
2020-05-18 17:16     ` David Milburn
2020-05-18 17:03 ` [PATCH 2/2] nvmet: avoid memleak by freeing any remaining aens in nvmet_async_events_free David Milburn

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).