linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
From: "Aneesh Kumar K.V" <aneesh.kumar@linux.ibm.com>
To: Dan Williams <dan.j.williams@intel.com>
Cc: "Kirill A . Shutemov" <kirill@shutemov.name>,
	linux-nvdimm <linux-nvdimm@lists.01.org>,
	Linux MM <linux-mm@kvack.org>
Subject: Re: [PATCH v8] libnvdimm/dax: Pick the right alignment default when creating dax devices
Date: Thu, 5 Sep 2019 07:26:54 +0530	[thread overview]
Message-ID: <33b377ac-86ea-b195-fd83-90c01df604cc@linux.ibm.com> (raw)
In-Reply-To: <CAPcyv4hD8SAFNNAWBP9q55wdPf-HYTEjpS4m+rT0VPoGodZULw@mail.gmail.com>

On 9/5/19 3:41 AM, Dan Williams wrote:
> On Tue, Sep 3, 2019 at 11:53 PM Aneesh Kumar K.V
> <aneesh.kumar@linux.ibm.com> wrote:
>>
>> Allow arch to provide the supported alignments and use hugepage alignment only
>> if we support hugepage. Right now we depend on compile time configs whereas this
>> patch switch this to runtime discovery.
>>
>> Architectures like ppc64 can have THP enabled in code, but then can have
>> hugepage size disabled by the hypervisor. This allows us to create dax devices
>> with PAGE_SIZE alignment in this case.
>>
>> Existing dax namespace with alignment larger than PAGE_SIZE will fail to
>> initialize in this specific case. We still allow fsdax namespace initialization.
>>
>> With respect to identifying whether to enable hugepage fault for a dax device,
>> if THP is enabled during compile, we default to taking hugepage fault and in dax
>> fault handler if we find the fault size > alignment we retry with PAGE_SIZE
>> fault size.
>>
>> This also addresses the below failure scenario on ppc64
>>
>> ndctl create-namespace --mode=devdax  | grep align
>>   "align":16777216,
>>   "align":16777216
>>
>> cat /sys/devices/ndbus0/region0/dax0.0/supported_alignments
>>   65536 16777216
>>
>> daxio.static-debug  -z -o /dev/dax0.0
>>    Bus error (core dumped)
>>
>>    $ dmesg | tail
>>     lpar: Failed hash pte insert with error -4
>>     hash-mmu: mm: Hashing failure ! EA=0x7fff17000000 access=0x8000000000000006 current=daxio
>>     hash-mmu:     trap=0x300 vsid=0x22cb7a3 ssize=1 base psize=2 psize 10 pte=0xc000000501002b86
>>     daxio[3860]: bus error (7) at 7fff17000000 nip 7fff973c007c lr 7fff973bff34 code 2 in libpmem.so.1.0.0[7fff973b0000+20000]
>>     daxio[3860]: code: 792945e4 7d494b78 e95f0098 7d494b78 f93f00a0 4800012c e93f0088 f93f0120
>>     daxio[3860]: code: e93f00a0 f93f0128 e93f0120 e95f0128 <f9490000> e93f0088 39290008 f93f0110
>>
>> The failure was due to guest kernel using wrong page size.
>>
>> The namespaces created with 16M alignment will appear as below on a config with
>> 16M page size disabled.
>>
>> $ ndctl list -Ni
>> [
>>    {
>>      "dev":"namespace0.1",
>>      "mode":"fsdax",
>>      "map":"dev",
>>      "size":5351931904,
>>      "uuid":"fc6e9667-461a-4718-82b4-69b24570bddb",
>>      "align":16777216,
>>      "blockdev":"pmem0.1",
>>      "supported_alignments":[
>>        65536
>>      ]
>>    },
>>    {
>>      "dev":"namespace0.0",
>>      "mode":"fsdax",    <==== devdax 16M alignment marked disabled.
>>      "map":"mem",
>>      "size":5368709120,
>>      "uuid":"a4bdf81a-f2ee-4bc6-91db-7b87eddd0484",
>>      "state":"disabled"
>>    }
>> ]
>>
>> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
>> ---
>>   drivers/nvdimm/nd.h       |  6 ----
>>   drivers/nvdimm/pfn_devs.c | 69 +++++++++++++++++++++++++++++----------
>>   include/linux/huge_mm.h   |  8 ++++-
>>   3 files changed, 59 insertions(+), 24 deletions(-)
>>
>> diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
>> index e89af4b2d8e9..401a78b02116 100644
>> --- a/drivers/nvdimm/nd.h
>> +++ b/drivers/nvdimm/nd.h
>> @@ -289,12 +289,6 @@ static inline struct device *nd_btt_create(struct nd_region *nd_region)
>>   struct nd_pfn *to_nd_pfn(struct device *dev);
>>   #if IS_ENABLED(CONFIG_NVDIMM_PFN)
>>
>> -#ifdef CONFIG_TRANSPARENT_HUGEPAGE
>> -#define PFN_DEFAULT_ALIGNMENT HPAGE_PMD_SIZE
>> -#else
>> -#define PFN_DEFAULT_ALIGNMENT PAGE_SIZE
>> -#endif
>> -
>>   int nd_pfn_probe(struct device *dev, struct nd_namespace_common *ndns);
>>   bool is_nd_pfn(struct device *dev);
>>   struct device *nd_pfn_create(struct nd_region *nd_region);
>> diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c
>> index ce9ef18282dd..4cb240b3d5b0 100644
>> --- a/drivers/nvdimm/pfn_devs.c
>> +++ b/drivers/nvdimm/pfn_devs.c
>> @@ -103,27 +103,36 @@ static ssize_t align_show(struct device *dev,
>>          return sprintf(buf, "%ld\n", nd_pfn->align);
>>   }
>>
>> -static const unsigned long *nd_pfn_supported_alignments(void)
>> +const unsigned long *nd_pfn_defining a supported_alignments(void)
> 
> Keep this 'static' there's no usage of this routine outside of pfn_devs.c
> 
>>   {
>> -       /*
>> -        * This needs to be a non-static variable because the *_SIZE
>> -        * macros aren't always constants.
>> -        */
>> -       const unsigned long supported_alignments[] = {
>> -               PAGE_SIZE,
>> -#ifdef CONFIG_TRANSPARENT_HUGEPAGE
>> -               HPAGE_PMD_SIZE,
>> +       static unsigned long supported_alignments[3];
> 
> Why is marked static? It's being dynamically populated each invocation
> so static is just wasting space in the .data section.
> 

The return of that function is address and that would require me to use 
a global variable. I could add a check

/* Check if initialized */
  if (supported_alignment[1])
	return supported_alignment;

in the function to updating that array every time called.

>> +
>> +       supported_alignments[0] = PAGE_SIZE;
>> +
>> +       if (has_transparent_hugepage()) {
>> +
>> +               supported_alignments[1] = HPAGE_PMD_SIZE;
>> +
>>   #ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD
>> -               HPAGE_PUD_SIZE,
>> -#endif
>> +               supported_alignments[2] = HPAGE_PUD_SIZE;
>>   #endif
> 
> This ifdef could be hidden in by:
> 
> if IS_ENABLED(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD)
> 
> ...or otherwise moving this to header file with something like
> NVDIMM_PUD_SIZE that is optionally 0 or HPAGE_PUD_SIZE depending on
> the config


I can switch to if IS_ENABLED but i am not sure that make it any 
different in the current code. So I will keep it same?

NVDIMM_PUD_SIZE is an indirection I find confusing.



> 
>> -               0,
>> -       };
>> -       static unsigned long data[ARRAY_SIZE(supported_alignments)];
>> +       } else {
>> +               supported_alignments[1] = 0;
>> +               supported_alignments[2] = 0;
>> +       }
>>
>> -       memcpy(data, supported_alignments, sizeof(data));
>> +       return supported_alignments;
>> +}
>> +
>> +/*
>> + * Use pmd mapping if supported as default alignment
>> + */
>> +unsigned long nd_pfn_default_alignment(void)
>> +{
>>
>> -       return data;
>> +       if (has_transparent_hugepage())
>> +               return HPAGE_PMD_SIZE;
>> +       return PAGE_SIZE;
>>   }
>>
>>   static ssize_t align_store(struct device *dev,
>> @@ -302,7 +311,7 @@ struct device *nd_pfn_devinit(struct nd_pfn *nd_pfn,
>>                  return NULL;
>>
>>          nd_pfn->mode = PFN_MODE_NONE;
>> -       nd_pfn->align = PFN_DEFAULT_ALIGNMENT;
>> +       nd_pfn->align = nd_pfn_default_alignment();
>>          dev = &nd_pfn->dev;
>>          device_initialize(&nd_pfn->dev);
>>          if (ndns && !__nd_attach_ndns(&nd_pfn->dev, ndns, &nd_pfn->ndns)) {
>> @@ -412,6 +421,20 @@ static int nd_pfn_clear_memmap_errors(struct nd_pfn *nd_pfn)
>>          return 0;
>>   }
>>
>> +static bool nd_supported_alignment(unsigned long align)
>> +{
>> +       int i;
>> +       const unsigned long *supported = nd_pfn_supported_alignments();
>> +
>> +       if (align == 0)
>> +               return false;
>> +
>> +       for (i = 0; supported[i]; i++)
>> +               if (align == supported[i])
>> +                       return true;
>> +       return false;
>> +}
>> +
>>   /**
>>    * nd_pfn_validate - read and validate info-block
>>    * @nd_pfn: fsdax namespace runtime state / properties
>> @@ -496,6 +519,18 @@ int nd_pfn_validate(struct nd_pfn *nd_pfn, const char *sig)
>>                  return -EOPNOTSUPP;
>>          }
>>
>> +       /*
>> +        * Check whether the we support the alignment. For Dax if the
>> +        * superblock alignment is not matching, we won't initialize
>> +        * the device.
>> +        */
>> +       if (!nd_supported_alignment(align) &&
>> +                       !memcmp(pfn_sb->signature, DAX_SIG, PFN_SIG_LEN)) {
>> +               dev_err(&nd_pfn->dev, "init failed, alignment mismatch: "
>> +                               "%ld:%ld\n", nd_pfn->align, align);
>> +               return -EOPNOTSUPP;
>> +       }
>> +
>>          if (!nd_pfn->uuid) {
>>                  /*
>>                   * When probing a namepace via nd_pfn_probe() the uuid
>> diff --git a/include/linux/huge_mm.h b/include/linux/huge_mm.h
>> index 45ede62aa85b..36708c43ef8e 100644
>> --- a/include/linux/huge_mm.h
>> +++ b/include/linux/huge_mm.h
>> @@ -108,7 +108,13 @@ static inline bool __transparent_hugepage_enabled(struct vm_area_struct *vma)
>>
>>          if (transparent_hugepage_flags & (1 << TRANSPARENT_HUGEPAGE_FLAG))
>>                  return true;
>> -
>> +       /*
>> +        * For dax let's try to do hugepage fault always. If the kernel doesn't
>> +        * support hugepages, namespaces with hugepage alignment will not be
>> +        * enabled. For namespace with PAGE_SIZE alignment, we try to handle
>> +        * hugepage fault but will fallback to PAGE_SIZE via the check in
>> +        * __dev_dax_pmd_fault
> 
> Ok, this is better, but I think it can be clarified further.
> 
> "For dax vmas, try to always use hugepage mappings. If the kernel does
> not support hugepages, fsdax mappings will fallback to PAGE_SIZE
> mappings, and device-dax namespaces, that try to guarantee a given
> mapping size, will fail to enable."
> 
> The last sentence about PAGE_SIZE namespaces is not relevant to
> __transparent_hugepage_enabled(), it's an internal implementation
> detail of the device-dax driver.
> 

I will use the above update.

-aneesh




  reply	other threads:[~2019-09-05  1:57 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-09-04  6:53 Aneesh Kumar K.V
2019-09-04 22:11 ` Dan Williams
2019-09-05  1:56   ` Aneesh Kumar K.V [this message]
2019-09-05  2:59     ` Dan Williams
2019-09-05  4:10       ` Aneesh Kumar K.V
2019-09-05  5:15         ` Dan Williams
2019-09-05  5:45           ` Aneesh Kumar K.V

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=33b377ac-86ea-b195-fd83-90c01df604cc@linux.ibm.com \
    --to=aneesh.kumar@linux.ibm.com \
    --cc=dan.j.williams@intel.com \
    --cc=kirill@shutemov.name \
    --cc=linux-mm@kvack.org \
    --cc=linux-nvdimm@lists.01.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox