On Wed, Nov 9, 2016 at 3:20 PM, Dave Jiang <[email protected]> wrote:
> We need to clear any poison when we are writing to pmem. The granularity
> will be sector size. If it's less then we can't do anything about it
> barring corruption.
>
> Signed-off-by: Dave Jiang <[email protected]>
> ---
>  drivers/nvdimm/claim.c |   20 ++++++++++++++++++--
>  1 file changed, 18 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/nvdimm/claim.c b/drivers/nvdimm/claim.c
> index d5dc80c..2078d25 100644
> --- a/drivers/nvdimm/claim.c
> +++ b/drivers/nvdimm/claim.c
> @@ -226,6 +226,7 @@ static int nsio_rw_bytes(struct nd_namespace_common *ndns,
>                 resource_size_t offset, void *buf, size_t size, int rw)
>  {
>         struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev);
> +       unsigned int sz_align = ALIGN(size + (offset & (512 - 1)), 512);
>
>         if (unlikely(offset + size > nsio->size)) {
>                 dev_WARN_ONCE(&ndns->dev, 1, "request out of range\n");
> @@ -233,12 +234,27 @@ static int nsio_rw_bytes(struct nd_namespace_common 
> *ndns,
>         }
>
>         if (rw == READ) {
> -               unsigned int sz_align = ALIGN(size + (offset & (512 - 1)), 
> 512);
> -
>                 if (unlikely(is_bad_pmem(&nsio->bb, offset / 512, sz_align)))
>                         return -EIO;
>                 return memcpy_from_pmem(buf, nsio->addr + offset, size);
>         } else {
> +               sector_t sector = offset / 512;
> +
> +               if (unlikely(is_bad_pmem(&nsio->bb, sector, sz_align))) {
> +                       if (IS_ALIGNED(offset, 512) &&
> +                           IS_ALIGNED(size, 512) && (size >= 512)) {
> +                               int rc;
> +
> +                               rc = nvdimm_clear_poison(&ndns->dev, offset,
> +                                                        size);
> +                               if (rc != size)
> +                                       return -EIO;
> +
> +                               badblocks_clear(&nsio->bb, sector, rc / 512);
> +                       } else
> +                               return -EIO;
> +               }
> +
>                 memcpy_to_pmem(nsio->addr + offset, buf, size);

Looks good.

After this the last piece remaining to fully close the "badblocks in
metadata" problem is to go update __nvdimm_setup_pfn().  Teach it to
walk and clear the badblocks in the range from the end of the 'pfn'
infoblock (8K offset from the start of the namespace) to the start of
data (pfn_sb->dataoff).
_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimm

Reply via email to