All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jason Gunthorpe <jgg@nvidia.com>
To: Leon Romanovsky <leon@kernel.org>
Cc: David Airlie <airlied@linux.ie>,
	Mike Marciniszyn <mike.marciniszyn@cornelisnetworks.com>,
	dri-devel@lists.freedesktop.org,
	Zhu Yanjun <zyjzyj2000@gmail.com>,
	Dennis Dalessandro <dennis.dalessandro@cornelisnetworks.com>,
	linux-rdma@vger.kernel.org, Christoph Hellwig <hch@infradead.org>,
	Doug Ledford <dledford@redhat.com>,
	VMware Graphics <linux-graphics-maintainer@vmware.com>,
	intel-gfx@lists.freedesktop.org,
	Roland Scheidegger <sroland@vmware.com>,
	Maxime Ripard <mripard@kernel.org>,
	Yishai Hadas <yishaih@nvidia.com>,
	linux-kernel@vger.kernel.org,
	Thomas Zimmermann <tzimmermann@suse.de>,
	Maor Gottlieb <maorg@nvidia.com>, Zack Rusin <zackr@vmware.com>
Subject: Re: [Intel-gfx] [PATCH rdma-next v2 1/2] lib/scatterlist: Fix wrong update of orig_nents
Date: Thu, 22 Jul 2021 10:00:40 -0300	[thread overview]
Message-ID: <20210722130040.GH1117491@nvidia.com> (raw)
In-Reply-To: <36d655a0ff45f4c86762358c7b6a7b58939313fb.1626605893.git.leonro@nvidia.com>

On Sun, Jul 18, 2021 at 02:09:12PM +0300, Leon Romanovsky wrote:
> @@ -386,12 +414,14 @@ static struct scatterlist *get_next_sg(struct sg_table *table,
>  		return ERR_PTR(-ENOMEM);
>  	sg_init_table(new_sg, alloc_size);
>  	if (cur) {
> +		if (total_nents)
> +			*total_nents += alloc_size - 1;
>  		__sg_chain(next_sg, new_sg);
> -		table->orig_nents += alloc_size - 1;
>  	} else {
>  		table->sgl = new_sg;
> -		table->orig_nents = alloc_size;
>  		table->nents = 0;

Why does this still touch nents?

> @@ -515,6 +548,7 @@ struct scatterlist *__sg_alloc_table_from_pages(struct sg_table *sgt,
>  		cur_page = j;
>  	}
>  	sgt->nents += added_nents;
> +	sgt->orig_nents = sgt->nents;

And here too?

nents should only be set by the dma mapper, right?


I'm also trying to understand why it is OK to pass in NULL for
total_nents?

Any situation where _sg_alloc_table_from_pages() returns with
sgt->orig_nents != total_nents requires the use of
sg_free_table_entries()

It looks like there is some trouble here:

	for (i = 0; i < chunks; i++) {
		s = get_next_sg(sgt, s, chunks - i + left_pages, gfp_mask,
				total_nents);
		if (IS_ERR(s)) {

This will update total_nents but after a few loops it can exit without
synchronizing sgt->orig_nents - thus any caller handling an error
return from __sg_alloc_table_from_pages() must not pass in NULL and
must use sg_free_table_entries()

So I would see two options:

 1) Remove the possiblity to return NULL and fix all callers to use
    sg_free_table_entries() on error

 2) Once __sg_alloc_table_from_pages() fails the sg_table is corrupted
    and the user must call sg_free_table_entries().
    ie forcibly store total_nents in the orig_nents and thus destroy
    the ability to continue to use the sg_table.

    This is what sg_alloc_table_from_pages() already has to do

Further upon success of __sg_alloc_table_from_pages() it should be
true that sgt->orig_nents == total_nents so the ib_umem change is
confusing. total_nents should be removed from the struct and only the
failure paths in the function calling __sg_alloc_table_from_pages()
need a stack local variable and sg_free_table_entries()

IMHO this API may have become unwieldly and complicated, I wonder if
this is better:

   struct sg_append_table state;

   sg_append_init(&state, sgt, gfp_mask);

   while (..)
     ret = sg_append_pages(&state, pages, n_pages, ..)
     if (ret)
	 sg_append_abort(&state); // Frees the sgt and puts it to NULL
   sg_append_complete(&state)

Which allows sg_alloc_table_from_pages() to be written as

   struct sg_append_table state;
   sg_append_init(&state, sgt, gfp_mask);
   ret = sg_append_pages(&state,pages, n_pages, offset, size, UINT_MAX)
   if (ret) {
      sg_append_abort(&state);
      return ret;
   }
   sg_append_complete(&state);
   return 0;

And then the API can manage all of this in some sane and
understandable way.

Jason
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

WARNING: multiple messages have this Message-ID (diff)
From: Jason Gunthorpe <jgg@nvidia.com>
To: Leon Romanovsky <leon@kernel.org>
Cc: Doug Ledford <dledford@redhat.com>,
	Christoph Hellwig <hch@infradead.org>,
	Maor Gottlieb <maorg@nvidia.com>, Daniel Vetter <daniel@ffwll.ch>,
	David Airlie <airlied@linux.ie>,
	Dennis Dalessandro <dennis.dalessandro@cornelisnetworks.com>,
	dri-devel@lists.freedesktop.org, intel-gfx@lists.freedesktop.org,
	Jani Nikula <jani.nikula@linux.intel.com>,
	Joonas Lahtinen <joonas.lahtinen@linux.intel.com>,
	linux-kernel@vger.kernel.org, linux-rdma@vger.kernel.org,
	Maarten Lankhorst <maarten.lankhorst@linux.intel.com>,
	Maxime Ripard <mripard@kernel.org>,
	Mike Marciniszyn <mike.marciniszyn@cornelisnetworks.com>,
	Rodrigo Vivi <rodrigo.vivi@intel.com>,
	Roland Scheidegger <sroland@vmware.com>,
	Thomas Zimmermann <tzimmermann@suse.de>,
	VMware Graphics <linux-graphics-maintainer@vmware.com>,
	Yishai Hadas <yishaih@nvidia.com>, Zack Rusin <zackr@vmware.com>,
	Zhu Yanjun <zyjzyj2000@gmail.com>
Subject: Re: [PATCH rdma-next v2 1/2] lib/scatterlist: Fix wrong update of orig_nents
Date: Thu, 22 Jul 2021 10:00:40 -0300	[thread overview]
Message-ID: <20210722130040.GH1117491@nvidia.com> (raw)
In-Reply-To: <36d655a0ff45f4c86762358c7b6a7b58939313fb.1626605893.git.leonro@nvidia.com>

On Sun, Jul 18, 2021 at 02:09:12PM +0300, Leon Romanovsky wrote:
> @@ -386,12 +414,14 @@ static struct scatterlist *get_next_sg(struct sg_table *table,
>  		return ERR_PTR(-ENOMEM);
>  	sg_init_table(new_sg, alloc_size);
>  	if (cur) {
> +		if (total_nents)
> +			*total_nents += alloc_size - 1;
>  		__sg_chain(next_sg, new_sg);
> -		table->orig_nents += alloc_size - 1;
>  	} else {
>  		table->sgl = new_sg;
> -		table->orig_nents = alloc_size;
>  		table->nents = 0;

Why does this still touch nents?

> @@ -515,6 +548,7 @@ struct scatterlist *__sg_alloc_table_from_pages(struct sg_table *sgt,
>  		cur_page = j;
>  	}
>  	sgt->nents += added_nents;
> +	sgt->orig_nents = sgt->nents;

And here too?

nents should only be set by the dma mapper, right?


I'm also trying to understand why it is OK to pass in NULL for
total_nents?

Any situation where _sg_alloc_table_from_pages() returns with
sgt->orig_nents != total_nents requires the use of
sg_free_table_entries()

It looks like there is some trouble here:

	for (i = 0; i < chunks; i++) {
		s = get_next_sg(sgt, s, chunks - i + left_pages, gfp_mask,
				total_nents);
		if (IS_ERR(s)) {

This will update total_nents but after a few loops it can exit without
synchronizing sgt->orig_nents - thus any caller handling an error
return from __sg_alloc_table_from_pages() must not pass in NULL and
must use sg_free_table_entries()

So I would see two options:

 1) Remove the possiblity to return NULL and fix all callers to use
    sg_free_table_entries() on error

 2) Once __sg_alloc_table_from_pages() fails the sg_table is corrupted
    and the user must call sg_free_table_entries().
    ie forcibly store total_nents in the orig_nents and thus destroy
    the ability to continue to use the sg_table.

    This is what sg_alloc_table_from_pages() already has to do

Further upon success of __sg_alloc_table_from_pages() it should be
true that sgt->orig_nents == total_nents so the ib_umem change is
confusing. total_nents should be removed from the struct and only the
failure paths in the function calling __sg_alloc_table_from_pages()
need a stack local variable and sg_free_table_entries()

IMHO this API may have become unwieldly and complicated, I wonder if
this is better:

   struct sg_append_table state;

   sg_append_init(&state, sgt, gfp_mask);

   while (..)
     ret = sg_append_pages(&state, pages, n_pages, ..)
     if (ret)
	 sg_append_abort(&state); // Frees the sgt and puts it to NULL
   sg_append_complete(&state)

Which allows sg_alloc_table_from_pages() to be written as

   struct sg_append_table state;
   sg_append_init(&state, sgt, gfp_mask);
   ret = sg_append_pages(&state,pages, n_pages, offset, size, UINT_MAX)
   if (ret) {
      sg_append_abort(&state);
      return ret;
   }
   sg_append_complete(&state);
   return 0;

And then the API can manage all of this in some sane and
understandable way.

Jason

WARNING: multiple messages have this Message-ID (diff)
From: Jason Gunthorpe <jgg@nvidia.com>
To: Leon Romanovsky <leon@kernel.org>
Cc: David Airlie <airlied@linux.ie>,
	Mike Marciniszyn <mike.marciniszyn@cornelisnetworks.com>,
	dri-devel@lists.freedesktop.org,
	Zhu Yanjun <zyjzyj2000@gmail.com>,
	Dennis Dalessandro <dennis.dalessandro@cornelisnetworks.com>,
	linux-rdma@vger.kernel.org, Christoph Hellwig <hch@infradead.org>,
	Doug Ledford <dledford@redhat.com>,
	VMware Graphics <linux-graphics-maintainer@vmware.com>,
	intel-gfx@lists.freedesktop.org,
	Roland Scheidegger <sroland@vmware.com>,
	Rodrigo Vivi <rodrigo.vivi@intel.com>,
	Yishai Hadas <yishaih@nvidia.com>,
	linux-kernel@vger.kernel.org,
	Thomas Zimmermann <tzimmermann@suse.de>,
	Maor Gottlieb <maorg@nvidia.com>
Subject: Re: [PATCH rdma-next v2 1/2] lib/scatterlist: Fix wrong update of orig_nents
Date: Thu, 22 Jul 2021 10:00:40 -0300	[thread overview]
Message-ID: <20210722130040.GH1117491@nvidia.com> (raw)
In-Reply-To: <36d655a0ff45f4c86762358c7b6a7b58939313fb.1626605893.git.leonro@nvidia.com>

On Sun, Jul 18, 2021 at 02:09:12PM +0300, Leon Romanovsky wrote:
> @@ -386,12 +414,14 @@ static struct scatterlist *get_next_sg(struct sg_table *table,
>  		return ERR_PTR(-ENOMEM);
>  	sg_init_table(new_sg, alloc_size);
>  	if (cur) {
> +		if (total_nents)
> +			*total_nents += alloc_size - 1;
>  		__sg_chain(next_sg, new_sg);
> -		table->orig_nents += alloc_size - 1;
>  	} else {
>  		table->sgl = new_sg;
> -		table->orig_nents = alloc_size;
>  		table->nents = 0;

Why does this still touch nents?

> @@ -515,6 +548,7 @@ struct scatterlist *__sg_alloc_table_from_pages(struct sg_table *sgt,
>  		cur_page = j;
>  	}
>  	sgt->nents += added_nents;
> +	sgt->orig_nents = sgt->nents;

And here too?

nents should only be set by the dma mapper, right?


I'm also trying to understand why it is OK to pass in NULL for
total_nents?

Any situation where _sg_alloc_table_from_pages() returns with
sgt->orig_nents != total_nents requires the use of
sg_free_table_entries()

It looks like there is some trouble here:

	for (i = 0; i < chunks; i++) {
		s = get_next_sg(sgt, s, chunks - i + left_pages, gfp_mask,
				total_nents);
		if (IS_ERR(s)) {

This will update total_nents but after a few loops it can exit without
synchronizing sgt->orig_nents - thus any caller handling an error
return from __sg_alloc_table_from_pages() must not pass in NULL and
must use sg_free_table_entries()

So I would see two options:

 1) Remove the possiblity to return NULL and fix all callers to use
    sg_free_table_entries() on error

 2) Once __sg_alloc_table_from_pages() fails the sg_table is corrupted
    and the user must call sg_free_table_entries().
    ie forcibly store total_nents in the orig_nents and thus destroy
    the ability to continue to use the sg_table.

    This is what sg_alloc_table_from_pages() already has to do

Further upon success of __sg_alloc_table_from_pages() it should be
true that sgt->orig_nents == total_nents so the ib_umem change is
confusing. total_nents should be removed from the struct and only the
failure paths in the function calling __sg_alloc_table_from_pages()
need a stack local variable and sg_free_table_entries()

IMHO this API may have become unwieldly and complicated, I wonder if
this is better:

   struct sg_append_table state;

   sg_append_init(&state, sgt, gfp_mask);

   while (..)
     ret = sg_append_pages(&state, pages, n_pages, ..)
     if (ret)
	 sg_append_abort(&state); // Frees the sgt and puts it to NULL
   sg_append_complete(&state)

Which allows sg_alloc_table_from_pages() to be written as

   struct sg_append_table state;
   sg_append_init(&state, sgt, gfp_mask);
   ret = sg_append_pages(&state,pages, n_pages, offset, size, UINT_MAX)
   if (ret) {
      sg_append_abort(&state);
      return ret;
   }
   sg_append_complete(&state);
   return 0;

And then the API can manage all of this in some sane and
understandable way.

Jason

  parent reply	other threads:[~2021-07-22 13:00 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-18 11:09 [Intel-gfx] [PATCH rdma-next v2 0/2] SG fix together with update to RDMA umem Leon Romanovsky
2021-07-18 11:09 ` Leon Romanovsky
2021-07-18 11:09 ` Leon Romanovsky
2021-07-18 11:09 ` [Intel-gfx] [PATCH rdma-next v2 1/2] lib/scatterlist: Fix wrong update of orig_nents Leon Romanovsky
2021-07-18 11:09   ` Leon Romanovsky
2021-07-18 11:09   ` Leon Romanovsky
2021-07-21 16:13   ` [Intel-gfx] " Christoph Hellwig
2021-07-21 16:13     ` Christoph Hellwig
2021-07-22 13:00   ` Jason Gunthorpe [this message]
2021-07-22 13:00     ` Jason Gunthorpe
2021-07-22 13:00     ` Jason Gunthorpe
2021-07-22 13:07     ` [Intel-gfx] " Christoph Hellwig
2021-07-22 13:07       ` Christoph Hellwig
2021-07-22 13:39       ` [Intel-gfx] " Jason Gunthorpe
2021-07-22 13:39         ` Jason Gunthorpe
2021-07-22 13:39         ` Jason Gunthorpe
2021-07-18 11:09 ` [Intel-gfx] [PATCH rdma-next v2 2/2] RDMA: Use dma_map_sgtable for map umem pages Leon Romanovsky
2021-07-18 11:09   ` Leon Romanovsky
2021-07-18 11:09   ` Leon Romanovsky
2021-07-21 16:16   ` [Intel-gfx] " Christoph Hellwig
2021-07-21 16:16     ` Christoph Hellwig
2021-07-18 11:14 ` [Intel-gfx] ✗ Fi.CI.BUILD: failure for SG fix together with update to RDMA umem Patchwork
2021-07-22 14:31 ` [Intel-gfx] ✗ Fi.CI.BUILD: failure for SG fix together with update to RDMA umem (rev2) Patchwork

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=20210722130040.GH1117491@nvidia.com \
    --to=jgg@nvidia.com \
    --cc=airlied@linux.ie \
    --cc=dennis.dalessandro@cornelisnetworks.com \
    --cc=dledford@redhat.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=hch@infradead.org \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=leon@kernel.org \
    --cc=linux-graphics-maintainer@vmware.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-rdma@vger.kernel.org \
    --cc=maorg@nvidia.com \
    --cc=mike.marciniszyn@cornelisnetworks.com \
    --cc=mripard@kernel.org \
    --cc=sroland@vmware.com \
    --cc=tzimmermann@suse.de \
    --cc=yishaih@nvidia.com \
    --cc=zackr@vmware.com \
    --cc=zyjzyj2000@gmail.com \
    /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.