All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Hildenbrand <david@redhat.com>
To: Dan Williams <dan.j.williams@intel.com>, linux-kernel@vger.kernel.org
Cc: Dave Hansen <dave.hansen@linux.intel.com>,
	Pavel Tatashin <pasha.tatashin@soleen.com>,
	Brice Goglin <Brice.Goglin@inria.fr>, Jia He <justin.he@arm.com>,
	Joao Martins <joao.m.martins@oracle.com>,
	Jonathan Cameron <Jonathan.Cameron@huawei.com>,
	akpm@linux-foundation.org, linux-nvdimm@lists.01.org,
	linux-mm@kvack.org
Subject: Re: [PATCH 1/2] device-dax/kmem: Fix resource release
Date: Thu, 15 Oct 2020 11:28:55 +0200	[thread overview]
Message-ID: <9b463afd-6e33-8afd-23ff-84d602029fc9@redhat.com> (raw)
In-Reply-To: <160272252925.3136502.17220638073995895400.stgit@dwillia2-desk3.amr.corp.intel.com>

On 15.10.20 02:42, Dan Williams wrote:
> The conversion to request_mem_region() is broken because it assumes that
> the range is marked busy prior to release. However, due to the way that
> the kmem driver manipulates the IORESOURCE_BUSY flag (clears it to
> let {add,remove}_memory() handle busy) it requires a manual
> release_resource() to perform cleanup.
> 
> Given that the actual 'struct resource *' needs to be recalled, not just
> the range, add that tracking to the kmem driver-data.
> 
> Reported-by: David Hildenbrand <david@redhat.com>
> Fixes: 0513bd5bb114 ("device-dax/kmem: replace release_resource() with release_mem_region()")
> Cc: Vishal Verma <vishal.l.verma@intel.com>
> Cc: Dave Hansen <dave.hansen@linux.intel.com>
> Cc: Pavel Tatashin <pasha.tatashin@soleen.com>
> Cc: Brice Goglin <Brice.Goglin@inria.fr>
> Cc: Dave Jiang <dave.jiang@intel.com>
> Cc: Ira Weiny <ira.weiny@intel.com>
> Cc: Jia He <justin.he@arm.com>
> Cc: Joao Martins <joao.m.martins@oracle.com>
> Cc: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> ---
>  drivers/dax/kmem.c |   48 ++++++++++++++++++++++++++++++++++--------------
>  1 file changed, 34 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/dax/kmem.c b/drivers/dax/kmem.c
> index 6c933f2b604e..af04b6d1d263 100644
> --- a/drivers/dax/kmem.c
> +++ b/drivers/dax/kmem.c
> @@ -35,11 +35,17 @@ static int dax_kmem_range(struct dev_dax *dev_dax, int i, struct range *r)
>  	return 0;
>  }
>  
> +struct dax_kmem_data {
> +	const char *res_name;
> +	struct resource *res[];
> +};
> +
>  static int dev_dax_kmem_probe(struct dev_dax *dev_dax)
>  {
>  	struct device *dev = &dev_dax->dev;
> +	struct dax_kmem_data *data;
> +	int rc = -ENOMEM;
>  	int i, mapped = 0;
> -	char *res_name;
>  	int numa_node;
>  
>  	/*
> @@ -55,14 +61,17 @@ static int dev_dax_kmem_probe(struct dev_dax *dev_dax)
>  		return -EINVAL;
>  	}
>  
> -	res_name = kstrdup(dev_name(dev), GFP_KERNEL);
> -	if (!res_name)
> +	data = kzalloc(sizeof(*data) + sizeof(struct resource *) * dev_dax->nr_range, GFP_KERNEL);
> +	if (!data)
>  		return -ENOMEM;
>  
> +	data->res_name = kstrdup(dev_name(dev), GFP_KERNEL);
> +	if (!data->res_name)
> +		goto err_res_name;
> +
>  	for (i = 0; i < dev_dax->nr_range; i++) {
>  		struct resource *res;
>  		struct range range;
> -		int rc;
>  
>  		rc = dax_kmem_range(dev_dax, i, &range);
>  		if (rc) {
> @@ -72,7 +81,7 @@ static int dev_dax_kmem_probe(struct dev_dax *dev_dax)
>  		}
>  
>  		/* Region is permanently reserved if hotremove fails. */
> -		res = request_mem_region(range.start, range_len(&range), res_name);
> +		res = request_mem_region(range.start, range_len(&range), data->res_name);
>  		if (!res) {
>  			dev_warn(dev, "mapping%d: %#llx-%#llx could not reserve region\n",
>  					i, range.start, range.end);
> @@ -82,9 +91,10 @@ static int dev_dax_kmem_probe(struct dev_dax *dev_dax)
>  			 */
>  			if (mapped)
>  				continue;
> -			kfree(res_name);
> -			return -EBUSY;
> +			rc = -EBUSY;
> +			goto err_request_mem;
>  		}
> +		data->res[i] = res;
>  
>  		/*
>  		 * Set flags appropriate for System RAM.  Leave ..._BUSY clear
> @@ -104,18 +114,25 @@ static int dev_dax_kmem_probe(struct dev_dax *dev_dax)
>  		if (rc) {
>  			dev_warn(dev, "mapping%d: %#llx-%#llx memory add failed\n",
>  					i, range.start, range.end);
> -			release_mem_region(range.start, range_len(&range));
> +			release_resource(res);
> +			kfree(res);
> +			data->res[i] = NULL;
>  			if (mapped)
>  				continue;
> -			kfree(res_name);
> -			return rc;
> +			goto err_request_mem;
>  		}
>  		mapped++;
>  	}
>  
> -	dev_set_drvdata(dev, res_name);
> +	dev_set_drvdata(dev, data);
>  
>  	return 0;
> +
> +err_request_mem:
> +	kfree(data->res_name);
> +err_res_name:
> +	kfree(data);
> +	return rc;
>  }
>  
>  #ifdef CONFIG_MEMORY_HOTREMOVE
> @@ -123,7 +140,7 @@ static int dev_dax_kmem_remove(struct dev_dax *dev_dax)
>  {
>  	int i, success = 0;
>  	struct device *dev = &dev_dax->dev;
> -	const char *res_name = dev_get_drvdata(dev);
> +	struct dax_kmem_data *data = dev_get_drvdata(dev);
>  
>  	/*
>  	 * We have one shot for removing memory, if some memory blocks were not
> @@ -142,7 +159,9 @@ static int dev_dax_kmem_remove(struct dev_dax *dev_dax)
>  		rc = remove_memory(dev_dax->target_node, range.start,
>  				range_len(&range));
>  		if (rc == 0) {
> -			release_mem_region(range.start, range_len(&range));
> +			release_resource(data->res[i]);
> +			kfree(data->res[i]);
> +			data->res[i] = NULL;
>  			success++;
>  			continue;
>  		}
> @@ -153,7 +172,8 @@ static int dev_dax_kmem_remove(struct dev_dax *dev_dax)
>  	}
>  
>  	if (success >= dev_dax->nr_range) {
> -		kfree(res_name);
> +		kfree(data->res_name);
> +		kfree(data);
>  		dev_set_drvdata(dev, NULL);
>  	}
>  
> 

Looks sane to me

Reviewed-by: David Hildenbrand <david@redhat.com>

-- 
Thanks,

David / dhildenb
_______________________________________________
Linux-nvdimm mailing list -- linux-nvdimm@lists.01.org
To unsubscribe send an email to linux-nvdimm-leave@lists.01.org

WARNING: multiple messages have this Message-ID (diff)
From: David Hildenbrand <david@redhat.com>
To: Dan Williams <dan.j.williams@intel.com>, linux-kernel@vger.kernel.org
Cc: Vishal Verma <vishal.l.verma@intel.com>,
	Dave Hansen <dave.hansen@linux.intel.com>,
	Pavel Tatashin <pasha.tatashin@soleen.com>,
	Brice Goglin <Brice.Goglin@inria.fr>,
	Dave Jiang <dave.jiang@intel.com>,
	Ira Weiny <ira.weiny@intel.com>, Jia He <justin.he@arm.com>,
	Joao Martins <joao.m.martins@oracle.com>,
	Jonathan Cameron <Jonathan.Cameron@huawei.com>,
	akpm@linux-foundation.org, linux-nvdimm@lists.01.org,
	linux-mm@kvack.org
Subject: Re: [PATCH 1/2] device-dax/kmem: Fix resource release
Date: Thu, 15 Oct 2020 11:28:55 +0200	[thread overview]
Message-ID: <9b463afd-6e33-8afd-23ff-84d602029fc9@redhat.com> (raw)
In-Reply-To: <160272252925.3136502.17220638073995895400.stgit@dwillia2-desk3.amr.corp.intel.com>

On 15.10.20 02:42, Dan Williams wrote:
> The conversion to request_mem_region() is broken because it assumes that
> the range is marked busy prior to release. However, due to the way that
> the kmem driver manipulates the IORESOURCE_BUSY flag (clears it to
> let {add,remove}_memory() handle busy) it requires a manual
> release_resource() to perform cleanup.
> 
> Given that the actual 'struct resource *' needs to be recalled, not just
> the range, add that tracking to the kmem driver-data.
> 
> Reported-by: David Hildenbrand <david@redhat.com>
> Fixes: 0513bd5bb114 ("device-dax/kmem: replace release_resource() with release_mem_region()")
> Cc: Vishal Verma <vishal.l.verma@intel.com>
> Cc: Dave Hansen <dave.hansen@linux.intel.com>
> Cc: Pavel Tatashin <pasha.tatashin@soleen.com>
> Cc: Brice Goglin <Brice.Goglin@inria.fr>
> Cc: Dave Jiang <dave.jiang@intel.com>
> Cc: Ira Weiny <ira.weiny@intel.com>
> Cc: Jia He <justin.he@arm.com>
> Cc: Joao Martins <joao.m.martins@oracle.com>
> Cc: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> ---
>  drivers/dax/kmem.c |   48 ++++++++++++++++++++++++++++++++++--------------
>  1 file changed, 34 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/dax/kmem.c b/drivers/dax/kmem.c
> index 6c933f2b604e..af04b6d1d263 100644
> --- a/drivers/dax/kmem.c
> +++ b/drivers/dax/kmem.c
> @@ -35,11 +35,17 @@ static int dax_kmem_range(struct dev_dax *dev_dax, int i, struct range *r)
>  	return 0;
>  }
>  
> +struct dax_kmem_data {
> +	const char *res_name;
> +	struct resource *res[];
> +};
> +
>  static int dev_dax_kmem_probe(struct dev_dax *dev_dax)
>  {
>  	struct device *dev = &dev_dax->dev;
> +	struct dax_kmem_data *data;
> +	int rc = -ENOMEM;
>  	int i, mapped = 0;
> -	char *res_name;
>  	int numa_node;
>  
>  	/*
> @@ -55,14 +61,17 @@ static int dev_dax_kmem_probe(struct dev_dax *dev_dax)
>  		return -EINVAL;
>  	}
>  
> -	res_name = kstrdup(dev_name(dev), GFP_KERNEL);
> -	if (!res_name)
> +	data = kzalloc(sizeof(*data) + sizeof(struct resource *) * dev_dax->nr_range, GFP_KERNEL);
> +	if (!data)
>  		return -ENOMEM;
>  
> +	data->res_name = kstrdup(dev_name(dev), GFP_KERNEL);
> +	if (!data->res_name)
> +		goto err_res_name;
> +
>  	for (i = 0; i < dev_dax->nr_range; i++) {
>  		struct resource *res;
>  		struct range range;
> -		int rc;
>  
>  		rc = dax_kmem_range(dev_dax, i, &range);
>  		if (rc) {
> @@ -72,7 +81,7 @@ static int dev_dax_kmem_probe(struct dev_dax *dev_dax)
>  		}
>  
>  		/* Region is permanently reserved if hotremove fails. */
> -		res = request_mem_region(range.start, range_len(&range), res_name);
> +		res = request_mem_region(range.start, range_len(&range), data->res_name);
>  		if (!res) {
>  			dev_warn(dev, "mapping%d: %#llx-%#llx could not reserve region\n",
>  					i, range.start, range.end);
> @@ -82,9 +91,10 @@ static int dev_dax_kmem_probe(struct dev_dax *dev_dax)
>  			 */
>  			if (mapped)
>  				continue;
> -			kfree(res_name);
> -			return -EBUSY;
> +			rc = -EBUSY;
> +			goto err_request_mem;
>  		}
> +		data->res[i] = res;
>  
>  		/*
>  		 * Set flags appropriate for System RAM.  Leave ..._BUSY clear
> @@ -104,18 +114,25 @@ static int dev_dax_kmem_probe(struct dev_dax *dev_dax)
>  		if (rc) {
>  			dev_warn(dev, "mapping%d: %#llx-%#llx memory add failed\n",
>  					i, range.start, range.end);
> -			release_mem_region(range.start, range_len(&range));
> +			release_resource(res);
> +			kfree(res);
> +			data->res[i] = NULL;
>  			if (mapped)
>  				continue;
> -			kfree(res_name);
> -			return rc;
> +			goto err_request_mem;
>  		}
>  		mapped++;
>  	}
>  
> -	dev_set_drvdata(dev, res_name);
> +	dev_set_drvdata(dev, data);
>  
>  	return 0;
> +
> +err_request_mem:
> +	kfree(data->res_name);
> +err_res_name:
> +	kfree(data);
> +	return rc;
>  }
>  
>  #ifdef CONFIG_MEMORY_HOTREMOVE
> @@ -123,7 +140,7 @@ static int dev_dax_kmem_remove(struct dev_dax *dev_dax)
>  {
>  	int i, success = 0;
>  	struct device *dev = &dev_dax->dev;
> -	const char *res_name = dev_get_drvdata(dev);
> +	struct dax_kmem_data *data = dev_get_drvdata(dev);
>  
>  	/*
>  	 * We have one shot for removing memory, if some memory blocks were not
> @@ -142,7 +159,9 @@ static int dev_dax_kmem_remove(struct dev_dax *dev_dax)
>  		rc = remove_memory(dev_dax->target_node, range.start,
>  				range_len(&range));
>  		if (rc == 0) {
> -			release_mem_region(range.start, range_len(&range));
> +			release_resource(data->res[i]);
> +			kfree(data->res[i]);
> +			data->res[i] = NULL;
>  			success++;
>  			continue;
>  		}
> @@ -153,7 +172,8 @@ static int dev_dax_kmem_remove(struct dev_dax *dev_dax)
>  	}
>  
>  	if (success >= dev_dax->nr_range) {
> -		kfree(res_name);
> +		kfree(data->res_name);
> +		kfree(data);
>  		dev_set_drvdata(dev, NULL);
>  	}
>  
> 

Looks sane to me

Reviewed-by: David Hildenbrand <david@redhat.com>

-- 
Thanks,

David / dhildenb


  reply	other threads:[~2020-10-15  9:29 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-10-15  0:42 [PATCH 0/2] device-dax subdivision v5 to v6 fixups Dan Williams
2020-10-15  0:42 ` Dan Williams
2020-10-15  0:42 ` [PATCH 1/2] device-dax/kmem: Fix resource release Dan Williams
2020-10-15  0:42   ` Dan Williams
2020-10-15  9:28   ` David Hildenbrand [this message]
2020-10-15  9:28     ` David Hildenbrand
2020-10-15  0:42 ` [PATCH 2/2] xen/unpopulated-alloc: Consolidate pgmap manipulation Dan Williams
2020-10-15  0:42   ` Dan Williams

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=9b463afd-6e33-8afd-23ff-84d602029fc9@redhat.com \
    --to=david@redhat.com \
    --cc=Brice.Goglin@inria.fr \
    --cc=Jonathan.Cameron@huawei.com \
    --cc=akpm@linux-foundation.org \
    --cc=dan.j.williams@intel.com \
    --cc=dave.hansen@linux.intel.com \
    --cc=joao.m.martins@oracle.com \
    --cc=justin.he@arm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=linux-nvdimm@lists.01.org \
    --cc=pasha.tatashin@soleen.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.