* [PATCH 1/9] SQUASHME: pmem: Remove unused #include headers
2014-09-09 15:37 ` [PATCH 0/9] pmem: Fixes and farther development (mm: add_persistent_memory) Boaz Harrosh
@ 2014-09-09 15:40 ` Boaz Harrosh
2014-09-09 22:29 ` Ross Zwisler
2014-09-09 15:41 ` [PATCH 2/9] SQUASHME: pmem: Request from fdisk 4k alignment Boaz Harrosh
` (9 subsequent siblings)
10 siblings, 1 reply; 58+ messages in thread
From: Boaz Harrosh @ 2014-09-09 15:40 UTC (permalink / raw)
To: Ross Zwisler, Jens Axboe, Matthew Wilcox, linux-fsdevel,
linux-nvdimm
Cc: Andrew Morton
From: Boaz Harrosh <boaz@plexistor.com>
Removed:
-#include <linux/bio.h>
-#include <linux/fs.h>
These two are included in linux/blkdev.h
-#include <linux/highmem.h>
-#include <linux/major.h>
-#include <linux/uaccess.h>
These 3 are not used anymore
Signed-off-by: Boaz Harrosh <boaz@plexistor.com>
---
drivers/block/pmem.c | 5 -----
1 file changed, 5 deletions(-)
diff --git a/drivers/block/pmem.c b/drivers/block/pmem.c
index d63bc96..8b0b9b0 100644
--- a/drivers/block/pmem.c
+++ b/drivers/block/pmem.c
@@ -16,17 +16,12 @@
* Copyright (C) 2007 Novell Inc.
*/
-#include <linux/bio.h>
#include <linux/blkdev.h>
-#include <linux/fs.h>
#include <linux/hdreg.h>
-#include <linux/highmem.h>
#include <linux/init.h>
-#include <linux/major.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
-#include <linux/uaccess.h>
#define SECTOR_SHIFT 9
#define PAGE_SECTORS_SHIFT (PAGE_SHIFT - SECTOR_SHIFT)
--
1.9.3
^ permalink raw reply related [flat|nested] 58+ messages in thread* Re: [PATCH 1/9] SQUASHME: pmem: Remove unused #include headers
2014-09-09 15:40 ` [PATCH 1/9] SQUASHME: pmem: Remove unused #include headers Boaz Harrosh
@ 2014-09-09 22:29 ` Ross Zwisler
2014-09-10 11:36 ` Boaz Harrosh
2014-09-10 19:16 ` [Linux-nvdimm] " Matthew Wilcox
0 siblings, 2 replies; 58+ messages in thread
From: Ross Zwisler @ 2014-09-09 22:29 UTC (permalink / raw)
To: Boaz Harrosh
Cc: Jens Axboe, Matthew Wilcox, linux-fsdevel, linux-nvdimm,
Andrew Morton
On Tue, 2014-09-09 at 18:40 +0300, Boaz Harrosh wrote:
> From: Boaz Harrosh <boaz@plexistor.com>
>
> Removed:
> -#include <linux/bio.h>
> -#include <linux/fs.h>
>
> These two are included in linux/blkdev.h
>
> -#include <linux/highmem.h>
I think this was present in the BRD code for flush_dcache_page(), but we
should probably be direct and include <asm/cacheflush.h> instead.
> -#include <linux/major.h>
Yep, not needed.
> -#include <linux/uaccess.h>
Yep, not needed.
> These 3 are not used anymore
I was under the impression that the philosophy regarding includes was that you
should directly include header files for the things that you use, and not rely
on headers that include other headers? That way a change to a header file
where you remove an unneeded #include doesn't cascade into a bunch of changes
in .c files for now undefined symbols?
If this isn't the case, I think we can actually pare things down to just these
three include files:
#include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <linux/module.h>
Here are the other include files that you left:
> #include <linux/init.h>
Included from include/linux/printk.h:5:0,
from include/linux/kernel.h:13,
from include/linux/sched.h:17,
from include/linux/blkdev.h:4
> #include <linux/moduleparam.h>
Included by <linux/module.h>
> #include <linux/slab.h>
Included from include/linux/genhd.h:15:0,
from include/linux/blkdev.h:9
If we *should* directly include the header files for anything that we use, we
can probably pare it down to this:
#include <asm/cacheflush.h>
#include <linux/bio.h>
#include <linux/blkdev.h>
#include <linux/fs.h>
#include <linux/hdreg.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
> Signed-off-by: Boaz Harrosh <boaz@plexistor.com>
> ---
> drivers/block/pmem.c | 5 -----
> 1 file changed, 5 deletions(-)
>
> diff --git a/drivers/block/pmem.c b/drivers/block/pmem.c
> index d63bc96..8b0b9b0 100644
> --- a/drivers/block/pmem.c
> +++ b/drivers/block/pmem.c
> @@ -16,17 +16,12 @@
> * Copyright (C) 2007 Novell Inc.
> */
>
> -#include <linux/bio.h>
> #include <linux/blkdev.h>
> -#include <linux/fs.h>
> #include <linux/hdreg.h>
> -#include <linux/highmem.h>
> #include <linux/init.h>
> -#include <linux/major.h>
> #include <linux/module.h>
> #include <linux/moduleparam.h>
> #include <linux/slab.h>
> -#include <linux/uaccess.h>
>
> #define SECTOR_SHIFT 9
> #define PAGE_SECTORS_SHIFT (PAGE_SHIFT - SECTOR_SHIFT)
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 1/9] SQUASHME: pmem: Remove unused #include headers
2014-09-09 22:29 ` Ross Zwisler
@ 2014-09-10 11:36 ` Boaz Harrosh
2014-09-10 19:16 ` [Linux-nvdimm] " Matthew Wilcox
1 sibling, 0 replies; 58+ messages in thread
From: Boaz Harrosh @ 2014-09-10 11:36 UTC (permalink / raw)
To: Ross Zwisler, Boaz Harrosh
Cc: Jens Axboe, Matthew Wilcox, linux-fsdevel, linux-nvdimm,
Andrew Morton
On 09/10/2014 01:29 AM, Ross Zwisler wrote:
<>
>
> I was under the impression that the philosophy regarding includes was that you
> should directly include header files for the things that you use, and not rely
> on headers that include other headers? That way a change to a header file
> where you remove an unneeded #include doesn't cascade into a bunch of changes
> in .c files for now undefined symbols?
>
> If this isn't the case, I think we can actually pare things down to just these
> three include files:
>
> #include <linux/blkdev.h>
> #include <linux/hdreg.h>
> #include <linux/module.h>
>
You are right I like this set + maybe add slab.h because we are
using kzalloc directly not regarding any driver API
>
> Here are the other include files that you left:
>> #include <linux/init.h>
> Included from include/linux/printk.h:5:0,
> from include/linux/kernel.h:13,
> from include/linux/sched.h:17,
> from include/linux/blkdev.h:4
>
>> #include <linux/moduleparam.h>
> Included by <linux/module.h>
>
I agree both init.h and moduleparam.h are implicit with being a "module".
I need them because that is what module needs, not for my own sake.
They are brought in by module.h APIs I am using types and defs from
these headers but because "module" API needs them
>> #include <linux/slab.h>
> Included from include/linux/genhd.h:15:0,
> from include/linux/blkdev.h:9
>
slab.h I would leave that might theoretically change
>
> If we *should* directly include the header files for anything that we use, we
> can probably pare it down to this:
>
> #include <asm/cacheflush.h>
What ? why
> #include <linux/fs.h>
> #include <linux/bio.h>
Both fs.h && bio.h are a part of blkdev API. As a block device
API implementing driver we must use some of these types. It is
not possible that blkdev will ever "not use" bio or fs.h types
any more and the only fix to my code will be a missing include.
> #include <linux/blkdev.h>
> #include <linux/hdreg.h>
Yes
> #include <linux/init.h>
> #include <linux/moduleparam.h>
Again brought in by "module" I would drop them
> #include <linux/module.h>
> #include <linux/slab.h>
Yes
so I'd say our set should be:
#include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <linux/module.h>
#include <linux/slab.h>
But it is such a trivial issue do what you decide
Thanks
Boaz
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [Linux-nvdimm] [PATCH 1/9] SQUASHME: pmem: Remove unused #include headers
2014-09-09 22:29 ` Ross Zwisler
2014-09-10 11:36 ` Boaz Harrosh
@ 2014-09-10 19:16 ` Matthew Wilcox
2014-09-11 11:35 ` Boaz Harrosh
1 sibling, 1 reply; 58+ messages in thread
From: Matthew Wilcox @ 2014-09-10 19:16 UTC (permalink / raw)
To: Ross Zwisler
Cc: Boaz Harrosh, Jens Axboe, linux-fsdevel, Andrew Morton,
Matthew Wilcox, linux-nvdimm
On Tue, Sep 09, 2014 at 04:29:43PM -0600, Ross Zwisler wrote:
> On Tue, 2014-09-09 at 18:40 +0300, Boaz Harrosh wrote:
> > From: Boaz Harrosh <boaz@plexistor.com>
> >
> > Removed:
> > -#include <linux/bio.h>
> > -#include <linux/fs.h>
> >
> > These two are included in linux/blkdev.h
Woah, woah, woah, what is this craziness? You shouldn't ever rely on
implicitly included files.
> > -#include <linux/highmem.h>
> I think this was present in the BRD code for flush_dcache_page(), but we
> should probably be direct and include <asm/cacheflush.h> instead.
Reasonable.
> > -#include <linux/major.h>
> Yep, not needed.
Agreed.
> > -#include <linux/uaccess.h>
> Yep, not needed.
I don't see a need for it either.
> > These 3 are not used anymore
>
> I was under the impression that the philosophy regarding includes was that you
> should directly include header files for the things that you use, and not rely
> on headers that include other headers? That way a change to a header file
> where you remove an unneeded #include doesn't cascade into a bunch of changes
> in .c files for now undefined symbols?
Correct.
> If we *should* directly include the header files for anything that we use, we
> can probably pare it down to this:
>
> #include <asm/cacheflush.h>
> #include <linux/bio.h>
> #include <linux/blkdev.h>
> #include <linux/fs.h>
> #include <linux/hdreg.h>
> #include <linux/init.h>
> #include <linux/module.h>
> #include <linux/moduleparam.h>
> #include <linux/slab.h>
Looks reasonable.
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [Linux-nvdimm] [PATCH 1/9] SQUASHME: pmem: Remove unused #include headers
2014-09-10 19:16 ` [Linux-nvdimm] " Matthew Wilcox
@ 2014-09-11 11:35 ` Boaz Harrosh
2014-09-11 19:34 ` Matthew Wilcox
0 siblings, 1 reply; 58+ messages in thread
From: Boaz Harrosh @ 2014-09-11 11:35 UTC (permalink / raw)
To: Matthew Wilcox, Ross Zwisler
Cc: Jens Axboe, linux-fsdevel, Andrew Morton, Matthew Wilcox,
linux-nvdimm
On 09/10/2014 10:16 PM, Matthew Wilcox wrote:
<>
>
> Woah, woah, woah, what is this craziness? You shouldn't ever rely on
> implicitly included files.
>
It is fine I do not mind the language ;-)
I'm not going to fight you over this *I could really care less*, but for
the record you are wrong.
If header B has an API like
typeA1 b_foo(typeA2 a2, typeA3 a3);
where typeA1, typeA2, typeA3 are from an included header A
and code in C.c needs the use of b_foo(), or even say b_foo is a vector
that C.c needs to implement. Then typeA1, typeA2, typeA3 are explicit
by B not implicit.
Implicit is if B has private structures with say typeXy from header X
but my code does not need to declare or implement any X types. in order
to use public API of B.
[Ax]
The mathematical proof as I said is. If B can be changed in such a way
that C.c code will not compile, but the only changes to C.c will be an
#include <X> directive "then X is implicitly included from B".
But if for C.c to compile after the changes to B more than #include
fixes, but actual code need changing, "then X is explicitly included from B"
That said. my opinion from 35 years of coding (Yes 1989) is that since there
is no tool that can measure [Ax] then the only sane/logical programming model
is actually the "minimal set". Which has performance merits as well.
And when a developer changes such an important aspects of B, its includes
chain, he needs to pay and fix miss-compiling users. All efforts measured,
this is a least-maintenance effort. My $0.017
sigh
Boaz
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [Linux-nvdimm] [PATCH 1/9] SQUASHME: pmem: Remove unused #include headers
2014-09-11 11:35 ` Boaz Harrosh
@ 2014-09-11 19:34 ` Matthew Wilcox
0 siblings, 0 replies; 58+ messages in thread
From: Matthew Wilcox @ 2014-09-11 19:34 UTC (permalink / raw)
To: Boaz Harrosh
Cc: Matthew Wilcox, Ross Zwisler, Jens Axboe, linux-fsdevel,
Andrew Morton, Matthew Wilcox, linux-nvdimm
On Thu, Sep 11, 2014 at 02:35:09PM +0300, Boaz Harrosh wrote:
> If header B has an API like
> typeA1 b_foo(typeA2 a2, typeA3 a3);
> where typeA1, typeA2, typeA3 are from an included header A
> and code in C.c needs the use of b_foo(), or even say b_foo is a vector
> that C.c needs to implement. Then typeA1, typeA2, typeA3 are explicit
> by B not implicit.
>
> Implicit is if B has private structures with say typeXy from header X
> but my code does not need to declare or implement any X types. in order
> to use public API of B.
If I change B to no longer include A, and declare, but not define types
A1-A3, a file which relies on the inclusion of B to define types A1-A3
is now broken.
^ permalink raw reply [flat|nested] 58+ messages in thread
* [PATCH 2/9] SQUASHME: pmem: Request from fdisk 4k alignment
2014-09-09 15:37 ` [PATCH 0/9] pmem: Fixes and farther development (mm: add_persistent_memory) Boaz Harrosh
2014-09-09 15:40 ` [PATCH 1/9] SQUASHME: pmem: Remove unused #include headers Boaz Harrosh
@ 2014-09-09 15:41 ` Boaz Harrosh
2014-09-11 18:39 ` Ross Zwisler
2014-09-09 15:43 ` [PATCH 3/9] SQUASHME: pmem: Let each device manage private memory region Boaz Harrosh
` (8 subsequent siblings)
10 siblings, 1 reply; 58+ messages in thread
From: Boaz Harrosh @ 2014-09-09 15:41 UTC (permalink / raw)
To: Ross Zwisler, Jens Axboe, Matthew Wilcox, linux-fsdevel,
linux-nvdimm
Cc: Andrew Morton
From: Boaz Harrosh <boaz@plexistor.com>
Because of the direct_access() API which returns a PFN. partitions
better start on 4K boundary, else offset ZERO of a partition will
not be aligned and blk_direct_access() will fail the call.
By setting blk_queue_physical_block_size(PAGE_SIZE) we can communicate
this to fdisk and friends.
Note that blk_queue_physical_block_size() also trashes io_min, but
we can leave this one to be 512.
Signed-off-by: Boaz Harrosh <boaz@plexistor.com>
---
drivers/block/pmem.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/block/pmem.c b/drivers/block/pmem.c
index 8b0b9b0..499536c 100644
--- a/drivers/block/pmem.c
+++ b/drivers/block/pmem.c
@@ -258,6 +258,12 @@ static struct pmem_device *pmem_alloc(int i)
blk_queue_max_hw_sectors(pmem->pmem_queue, 1024);
blk_queue_bounce_limit(pmem->pmem_queue, BLK_BOUNCE_ANY);
+ /* This is so fdisk will align partitions on 4k, because of
+ * direct_access API needing 4k alignment, returning a PFN
+ */
+ blk_queue_physical_block_size(pmem->pmem_queue, PAGE_SIZE);
+ pmem->pmem_queue->limits.io_min = 512; /* Don't use the accessor */
+
disk = pmem->pmem_disk = alloc_disk(0);
if (!disk)
goto out_free_queue;
--
1.9.3
^ permalink raw reply related [flat|nested] 58+ messages in thread* Re: [PATCH 2/9] SQUASHME: pmem: Request from fdisk 4k alignment
2014-09-09 15:41 ` [PATCH 2/9] SQUASHME: pmem: Request from fdisk 4k alignment Boaz Harrosh
@ 2014-09-11 18:39 ` Ross Zwisler
2014-09-14 11:25 ` Boaz Harrosh
0 siblings, 1 reply; 58+ messages in thread
From: Ross Zwisler @ 2014-09-11 18:39 UTC (permalink / raw)
To: Boaz Harrosh
Cc: Jens Axboe, Matthew Wilcox, linux-fsdevel, linux-nvdimm,
Andrew Morton
On Tue, 2014-09-09 at 18:41 +0300, Boaz Harrosh wrote:
> From: Boaz Harrosh <boaz@plexistor.com>
>
> Because of the direct_access() API which returns a PFN. partitions
> better start on 4K boundary, else offset ZERO of a partition will
> not be aligned and blk_direct_access() will fail the call.
>
> By setting blk_queue_physical_block_size(PAGE_SIZE) we can communicate
> this to fdisk and friends.
> Note that blk_queue_physical_block_size() also trashes io_min, but
> we can leave this one to be 512.
>
> Signed-off-by: Boaz Harrosh <boaz@plexistor.com>
> ---
> drivers/block/pmem.c | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/drivers/block/pmem.c b/drivers/block/pmem.c
> index 8b0b9b0..499536c 100644
> --- a/drivers/block/pmem.c
> +++ b/drivers/block/pmem.c
> @@ -258,6 +258,12 @@ static struct pmem_device *pmem_alloc(int i)
> blk_queue_max_hw_sectors(pmem->pmem_queue, 1024);
> blk_queue_bounce_limit(pmem->pmem_queue, BLK_BOUNCE_ANY);
>
> + /* This is so fdisk will align partitions on 4k, because of
> + * direct_access API needing 4k alignment, returning a PFN
> + */
> + blk_queue_physical_block_size(pmem->pmem_queue, PAGE_SIZE);
> + pmem->pmem_queue->limits.io_min = 512; /* Don't use the accessor */
> +
> disk = pmem->pmem_disk = alloc_disk(0);
> if (!disk)
> goto out_free_queue;
I've tested this a bit using the version of fdisk found in Fedora (fdisk from
util-linux 2.24.2), which I believe is what you are using.
So far I can't come up with a case where fdisk does the wrong thing without
this patch and the right thing with it. Can you please provide me more
details on the use case that you are trying to fix?
- Ross
^ permalink raw reply [flat|nested] 58+ messages in thread
* Re: [PATCH 2/9] SQUASHME: pmem: Request from fdisk 4k alignment
2014-09-11 18:39 ` Ross Zwisler
@ 2014-09-14 11:25 ` Boaz Harrosh
0 siblings, 0 replies; 58+ messages in thread
From: Boaz Harrosh @ 2014-09-14 11:25 UTC (permalink / raw)
To: Ross Zwisler
Cc: Jens Axboe, Matthew Wilcox, linux-fsdevel, linux-nvdimm,
Andrew Morton
On 09/11/2014 09:39 PM, Ross Zwisler wrote:
<>
>
> I've tested this a bit using the version of fdisk found in Fedora (fdisk from
> util-linux 2.24.2), which I believe is what you are using.
>
> So far I can't come up with a case where fdisk does the wrong thing without
> this patch and the right thing with it. Can you please provide me more
> details on the use case that you are trying to fix?
>
Try 4M disk for one.
And have you really tested? Do you always get a start sector aligned on 8 (4k) ?
Well I do not, I easily get partition start sectors not aligned on 8.
Note that fdisk will allow me to set none-4k-aligened start and size but at least
with this patch it will not suggest them
> - Ross
>
>
Thanks
Boaz
^ permalink raw reply [flat|nested] 58+ messages in thread
* [PATCH 3/9] SQUASHME: pmem: Let each device manage private memory region
2014-09-09 15:37 ` [PATCH 0/9] pmem: Fixes and farther development (mm: add_persistent_memory) Boaz Harrosh
2014-09-09 15:40 ` [PATCH 1/9] SQUASHME: pmem: Remove unused #include headers Boaz Harrosh
2014-09-09 15:41 ` [PATCH 2/9] SQUASHME: pmem: Request from fdisk 4k alignment Boaz Harrosh
@ 2014-09-09 15:43 ` Boaz Harrosh
2014-09-11 20:35 ` Ross Zwisler
2014-09-09 15:44 ` [PATCH 4/9] SQUASHME: pmem: Support of multiple memory regions Boaz Harrosh
` (7 subsequent siblings)
10 siblings, 1 reply; 58+ messages in thread
From: Boaz Harrosh @ 2014-09-09 15:43 UTC (permalink / raw)
To: Ross Zwisler, Jens Axboe, Matthew Wilcox, linux-fsdevel,
linux-nvdimm
Cc: Andrew Morton
From: Boaz Harrosh <boaz@plexistor.com>
This patch removes any global memory information. And lets
each pmem-device manage it's own memory region.
pmem_alloc() Now receives phys_addr and disk_size and will
map that region, also pmem_free will do the unmaping.
This is so we can support multiple discontinuous memory regions
in the next patch
Signed-off-by: Boaz Harrosh <boaz@plexistor.com>
---
drivers/block/pmem.c | 122 +++++++++++++++++++++++++++++++--------------------
1 file changed, 75 insertions(+), 47 deletions(-)
diff --git a/drivers/block/pmem.c b/drivers/block/pmem.c
index 499536c..d5c5c52 100644
--- a/drivers/block/pmem.c
+++ b/drivers/block/pmem.c
@@ -27,19 +27,12 @@
#define PAGE_SECTORS_SHIFT (PAGE_SHIFT - SECTOR_SHIFT)
#define PAGE_SECTORS (1 << PAGE_SECTORS_SHIFT)
-/*
- * driver-wide physical address and total_size - one single, contiguous memory
- * region that we divide up in to same-sized devices
- */
-phys_addr_t phys_addr;
-void *virt_addr;
-size_t total_size;
-
struct pmem_device {
struct request_queue *pmem_queue;
struct gendisk *pmem_disk;
struct list_head pmem_list;
+ /* One contiguous memory region per device */
phys_addr_t phys_addr;
void *virt_addr;
size_t size;
@@ -234,26 +227,70 @@ MODULE_PARM_DESC(pmem_count, "Number of pmem devices to evenly split allocated s
static LIST_HEAD(pmem_devices);
static int pmem_major;
-/* FIXME: move phys_addr, virt_addr, size calls up to caller */
-static struct pmem_device *pmem_alloc(int i)
+/* pmem->phys_addr and pmem->size need to be set.
+ * Will then set virt_addr if successful.
+ */
+int pmem_mapmem(struct pmem_device *pmem)
+{
+ struct resource *res_mem;
+ int err;
+
+ res_mem = request_mem_region_exclusive(pmem->phys_addr, pmem->size,
+ "pmem");
+ if (!res_mem) {
+ pr_warn("pmem: request_mem_region_exclusive phys=0x%llx size=0x%zx failed\n",
+ pmem->phys_addr, pmem->size);
+ return -EINVAL;
+ }
+
+ pmem->virt_addr = ioremap_cache(pmem->phys_addr, pmem->size);
+ if (unlikely(!pmem->virt_addr)) {
+ err = -ENXIO;
+ goto out_release;
+ }
+ return 0;
+
+out_release:
+ release_mem_region(pmem->phys_addr, pmem->size);
+ return err;
+}
+
+void pmem_unmapmem(struct pmem_device *pmem)
+{
+ if (unlikely(!pmem->virt_addr))
+ return;
+
+ iounmap(pmem->virt_addr);
+ release_mem_region(pmem->phys_addr, pmem->size);
+ pmem->virt_addr = NULL;
+}
+
+static struct pmem_device *pmem_alloc(phys_addr_t phys_addr, size_t disk_size,
+ int i)
{
struct pmem_device *pmem;
struct gendisk *disk;
- size_t disk_size = total_size / pmem_count;
- size_t disk_sectors = disk_size / 512;
+ int err;
pmem = kzalloc(sizeof(*pmem), GFP_KERNEL);
- if (!pmem)
+ if (unlikely(!pmem)) {
+ err = -ENOMEM;
goto out;
+ }
- pmem->phys_addr = phys_addr + i * disk_size;
- pmem->virt_addr = virt_addr + i * disk_size;
+ pmem->phys_addr = phys_addr;
pmem->size = disk_size;
- pmem->pmem_queue = blk_alloc_queue(GFP_KERNEL);
- if (!pmem->pmem_queue)
+ err = pmem_mapmem(pmem);
+ if (unlikely(err))
goto out_free_dev;
+ pmem->pmem_queue = blk_alloc_queue(GFP_KERNEL);
+ if (unlikely(!pmem->pmem_queue)) {
+ err = -ENOMEM;
+ goto out_unmap;
+ }
+
blk_queue_make_request(pmem->pmem_queue, pmem_make_request);
blk_queue_max_hw_sectors(pmem->pmem_queue, 1024);
blk_queue_bounce_limit(pmem->pmem_queue, BLK_BOUNCE_ANY);
@@ -264,9 +301,12 @@ static struct pmem_device *pmem_alloc(int i)
blk_queue_physical_block_size(pmem->pmem_queue, PAGE_SIZE);
pmem->pmem_queue->limits.io_min = 512; /* Don't use the accessor */
- disk = pmem->pmem_disk = alloc_disk(0);
- if (!disk)
+ disk = alloc_disk(0);
+ if (unlikely(!disk)) {
+ err = -ENOMEM;
goto out_free_queue;
+ }
+
disk->major = pmem_major;
disk->first_minor = 0;
disk->fops = &pmem_fops;
@@ -274,22 +314,26 @@ static struct pmem_device *pmem_alloc(int i)
disk->queue = pmem->pmem_queue;
disk->flags = GENHD_FL_EXT_DEVT;
sprintf(disk->disk_name, "pmem%d", i);
- set_capacity(disk, disk_sectors);
+ set_capacity(disk, disk_size >> SECTOR_SHIFT);
+ pmem->pmem_disk = disk;
return pmem;
out_free_queue:
blk_cleanup_queue(pmem->pmem_queue);
+out_unmap:
+ pmem_unmapmem(pmem);
out_free_dev:
kfree(pmem);
out:
- return NULL;
+ return ERR_PTR(err);
}
static void pmem_free(struct pmem_device *pmem)
{
put_disk(pmem->pmem_disk);
blk_cleanup_queue(pmem->pmem_queue);
+ pmem_unmapmem(pmem);
kfree(pmem);
}
@@ -303,36 +347,28 @@ static void pmem_del_one(struct pmem_device *pmem)
static int __init pmem_init(void)
{
int result, i;
- struct resource *res_mem;
struct pmem_device *pmem, *next;
+ phys_addr_t phys_addr;
+ size_t total_size, disk_size;
phys_addr = (phys_addr_t) pmem_start_gb * 1024 * 1024 * 1024;
total_size = (size_t) pmem_size_gb * 1024 * 1024 * 1024;
-
- res_mem = request_mem_region_exclusive(phys_addr, total_size, "pmem");
- if (!res_mem)
- return -ENOMEM;
-
- virt_addr = ioremap_cache(phys_addr, total_size);
- if (!virt_addr) {
- result = -ENOMEM;
- goto out_release;
- }
+ disk_size = total_size / pmem_count;
result = register_blkdev(0, "pmem");
- if (result < 0) {
- result = -EIO;
- goto out_unmap;
- } else
+ if (result < 0)
+ return -EIO;
+ else
pmem_major = result;
for (i = 0; i < pmem_count; i++) {
- pmem = pmem_alloc(i);
- if (!pmem) {
- result = -ENOMEM;
+ pmem = pmem_alloc(phys_addr, disk_size, i);
+ if (IS_ERR(pmem)) {
+ result = PTR_ERR(pmem);
goto out_free;
}
list_add_tail(&pmem->pmem_list, &pmem_devices);
+ phys_addr += disk_size;
}
list_for_each_entry(pmem, &pmem_devices, pmem_list)
@@ -348,11 +384,6 @@ out_free:
}
unregister_blkdev(pmem_major, "pmem");
-out_unmap:
- iounmap(virt_addr);
-
-out_release:
- release_mem_region(phys_addr, total_size);
return result;
}
@@ -364,9 +395,6 @@ static void __exit pmem_exit(void)
pmem_del_one(pmem);
unregister_blkdev(pmem_major, "pmem");
- iounmap(virt_addr);
- release_mem_region(phys_addr, total_size);
-
pr_info("pmem: module unloaded\n");
}
--
1.9.3
^ permalink raw reply related [flat|nested] 58+ messages in thread* Re: [PATCH 3/9] SQUASHME: pmem: Let each device manage private memory region
2014-09-09 15:43 ` [PATCH 3/9] SQUASHME: pmem: Let each device manage private memory region Boaz Harrosh
@ 2014-09-11 20:35 ` Ross Zwisler
0 siblings, 0 replies; 58+ messages in thread
From: Ross Zwisler @ 2014-09-11 20:35 UTC (permalink / raw)
To: Boaz Harrosh
Cc: Jens Axboe, Matthew Wilcox, linux-fsdevel, linux-nvdimm,
Andrew Morton
On Tue, 2014-09-09 at 18:43 +0300, Boaz Harrosh wrote:
> From: Boaz Harrosh <boaz@plexistor.com>
>
> This patch removes any global memory information. And lets
> each pmem-device manage it's own memory region.
>
> pmem_alloc() Now receives phys_addr and disk_size and will
> map that region, also pmem_free will do the unmaping.
>
> This is so we can support multiple discontinuous memory regions
> in the next patch
>
> Signed-off-by: Boaz Harrosh <boaz@plexistor.com>
> ---
> drivers/block/pmem.c | 122 +++++++++++++++++++++++++++++++--------------------
> 1 file changed, 75 insertions(+), 47 deletions(-)
<>
> @@ -234,26 +227,70 @@ MODULE_PARM_DESC(pmem_count, "Number of pmem devices to evenly split allocated s
> static LIST_HEAD(pmem_devices);
> static int pmem_major;
>
> -/* FIXME: move phys_addr, virt_addr, size calls up to caller */
> -static struct pmem_device *pmem_alloc(int i)
> +/* pmem->phys_addr and pmem->size need to be set.
> + * Will then set virt_addr if successful.
> + */
> +int pmem_mapmem(struct pmem_device *pmem)
Maybe just pmem_map() and pmem_unmap() for simplicity?
Looks good. You can add:
Reviewed-by: Ross Zwisler <ross.zwisler@linux.intel.com>
I'll pull it into the tree at https://github.com/01org/prd
^ permalink raw reply [flat|nested] 58+ messages in thread
* [PATCH 4/9] SQUASHME: pmem: Support of multiple memory regions
2014-09-09 15:37 ` [PATCH 0/9] pmem: Fixes and farther development (mm: add_persistent_memory) Boaz Harrosh
` (2 preceding siblings ...)
2014-09-09 15:43 ` [PATCH 3/9] SQUASHME: pmem: Let each device manage private memory region Boaz Harrosh
@ 2014-09-09 15:44 ` Boaz Harrosh
2014-09-09 15:45 ` [PATCH 5/9] mm: Let sparse_{add,remove}_one_section receive a node_id Boaz Harrosh
` (6 subsequent siblings)
10 siblings, 0 replies; 58+ messages in thread
From: Boaz Harrosh @ 2014-09-09 15:44 UTC (permalink / raw)
To: Ross Zwisler, Jens Axboe, Matthew Wilcox, linux-fsdevel,
linux-nvdimm
Cc: Andrew Morton, linux-kernel
From: Boaz Harrosh <boaz@plexistor.com>
After the last patch this is easy.
The API to pmem module is changed. We now have a single string
parameter named "map" of the form:
map=mapS[,mapS...]
where mapS=nn[KMG]$ss[KMG],
or mapS=nn[KMG]@ss[KMG],
nn=size, ss=offset
Just like the Kernel command line map && memmap parameters,
so anything you did at grub just copy/paste to here.
The "@" form is exactly the same as the "$" form only that
at bash prompt we need to escape the "$" with \$ so also
support the '@' char for convenience.
For each specified mapS there will be a device created.
So needless to say that all the previous prd_XXX params are
removed as well as the Kconfig defaults.
Signed-off-by: Boaz Harrosh <boaz@plexistor.com>
---
drivers/block/Kconfig | 28 -----------------------
drivers/block/pmem.c | 62 ++++++++++++++++++++++++++++++++++++---------------
2 files changed, 44 insertions(+), 46 deletions(-)
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index 2d50125..5da8cbf 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -416,34 +416,6 @@ config BLK_DEV_PMEM
Most normal users won't need this functionality, and can thus say N
here.
-config BLK_DEV_PMEM_START
- int "Offset in GiB of where to start claiming space"
- default "0"
- depends on BLK_DEV_PMEM
- help
- Starting offset in GiB that PMEM should use when claiming memory. This
- memory needs to be reserved from the OS at boot time using the
- "memmap" kernel parameter.
-
- If you provide PMEM with volatile memory it will act as a volatile
- RAM disk and your data will not be persistent.
-
-config BLK_DEV_PMEM_COUNT
- int "Default number of PMEM disks"
- default "4"
- depends on BLK_DEV_PMEM
- help
- Number of equal sized block devices that PMEM should create.
-
-config BLK_DEV_PMEM_SIZE
- int "Size in GiB of space to claim"
- depends on BLK_DEV_PMEM
- default "0"
- help
- Amount of memory in GiB that PMEM should use when creating block
- devices. This memory needs to be reserved from the OS at
- boot time using the "memmap" kernel parameter.
-
config CDROM_PKTCDVD
tristate "Packet writing on CD/DVD media"
depends on !UML
diff --git a/drivers/block/pmem.c b/drivers/block/pmem.c
index d5c5c52..e07a373 100644
--- a/drivers/block/pmem.c
+++ b/drivers/block/pmem.c
@@ -212,17 +212,11 @@ static const struct block_device_operations pmem_fops = {
};
/* Kernel module stuff */
-static int pmem_start_gb = CONFIG_BLK_DEV_PMEM_START;
-module_param(pmem_start_gb, int, S_IRUGO);
-MODULE_PARM_DESC(pmem_start_gb, "Offset in GB of where to start claiming space");
-
-static int pmem_size_gb = CONFIG_BLK_DEV_PMEM_SIZE;
-module_param(pmem_size_gb, int, S_IRUGO);
-MODULE_PARM_DESC(pmem_size_gb, "Total size in GB of space to claim for all disks");
-
-static int pmem_count = CONFIG_BLK_DEV_PMEM_COUNT;
-module_param(pmem_count, int, S_IRUGO);
-MODULE_PARM_DESC(pmem_count, "Number of pmem devices to evenly split allocated space");
+static char *map;
+module_param(map, charp, S_IRUGO);
+MODULE_PARM_DESC(map,
+ "pmem device mapping: map=mapS[,mapS...] where:\n"
+ "mapS=nn[KMG]$ss[KMG] or mapS=nn[KMG]@ss[KMG], nn=size, ss=offset.");
static LIST_HEAD(pmem_devices);
static int pmem_major;
@@ -272,6 +266,13 @@ static struct pmem_device *pmem_alloc(phys_addr_t phys_addr, size_t disk_size,
struct gendisk *disk;
int err;
+ if (unlikely((phys_addr & ~PAGE_MASK) || (disk_size & ~PAGE_MASK))) {
+ pr_err("phys_addr=0x%llx disk_size=0x%zx must be 4k aligned\n",
+ phys_addr, disk_size);
+ err = -EINVAL;
+ goto out;
+ }
+
pmem = kzalloc(sizeof(*pmem), GFP_KERNEL);
if (unlikely(!pmem)) {
err = -ENOMEM;
@@ -344,16 +345,32 @@ static void pmem_del_one(struct pmem_device *pmem)
pmem_free(pmem);
}
+static int pmem_parse_map_one(char *map, phys_addr_t *start, size_t *size)
+{
+ char *p = map;
+
+ *size = (size_t)memparse(p, &p);
+ if ((p == map) || ((*p != '$') && (*p != '@')))
+ return -EINVAL;
+
+ if (!*(++p))
+ return -EINVAL;
+
+ *start = (phys_addr_t)memparse(p, &p);
+
+ return *p == '\0' ? 0 : -EINVAL;
+}
+
static int __init pmem_init(void)
{
int result, i;
struct pmem_device *pmem, *next;
- phys_addr_t phys_addr;
- size_t total_size, disk_size;
+ char *p, *pmem_map = map;
- phys_addr = (phys_addr_t) pmem_start_gb * 1024 * 1024 * 1024;
- total_size = (size_t) pmem_size_gb * 1024 * 1024 * 1024;
- disk_size = total_size / pmem_count;
+ if (!pmem_map) {
+ pr_err("pmem: must specify map=nn@ss parameter.\n");
+ return -EINVAL;
+ }
result = register_blkdev(0, "pmem");
if (result < 0)
@@ -361,14 +378,23 @@ static int __init pmem_init(void)
else
pmem_major = result;
- for (i = 0; i < pmem_count; i++) {
+ i = 0;
+ while ((p = strsep(&pmem_map, ",")) != NULL) {
+ phys_addr_t phys_addr;
+ size_t disk_size;
+
+ if (!*p)
+ continue;
+ result = pmem_parse_map_one(p, &phys_addr, &disk_size);
+ if (result)
+ goto out_free;
pmem = pmem_alloc(phys_addr, disk_size, i);
if (IS_ERR(pmem)) {
result = PTR_ERR(pmem);
goto out_free;
}
list_add_tail(&pmem->pmem_list, &pmem_devices);
- phys_addr += disk_size;
+ ++i;
}
list_for_each_entry(pmem, &pmem_devices, pmem_list)
--
1.9.3
^ permalink raw reply related [flat|nested] 58+ messages in thread* [PATCH 5/9] mm: Let sparse_{add,remove}_one_section receive a node_id
2014-09-09 15:37 ` [PATCH 0/9] pmem: Fixes and farther development (mm: add_persistent_memory) Boaz Harrosh
` (3 preceding siblings ...)
2014-09-09 15:44 ` [PATCH 4/9] SQUASHME: pmem: Support of multiple memory regions Boaz Harrosh
@ 2014-09-09 15:45 ` Boaz Harrosh
2014-09-09 18:36 ` Dave Hansen
2014-09-09 15:47 ` [PATCH 6/9] mm: New add_persistent_memory/remove_persistent_memory Boaz Harrosh
` (5 subsequent siblings)
10 siblings, 1 reply; 58+ messages in thread
From: Boaz Harrosh @ 2014-09-09 15:45 UTC (permalink / raw)
To: Ross Zwisler, Jens Axboe, Matthew Wilcox, linux-fsdevel,
linux-nvdimm, Toshi Kani, Dave Hansen, linux-mm
Cc: Andrew Morton, linux-kernel
From: Yigal Korman <yigal@plexistor.com>
Refactored the arguments of sparse_add_one_section / sparse_remove_one_section
to use node id instead of struct zone * - A memory section has no direct
connection to zones, all that was needed from zone was the node id.
This is for add_persistent_memory that will want a section of pages
allocated but without any zone associated. This is because belonging
to a zone will give the memory to the page allocators, but
persistent_memory belongs to a block device, and is not available for
regular volatile usage.
Signed-off-by: Yigal Korman <yigal@plexistor.com>
Signed-off-by: Boaz Harrosh <boaz@plexistor.com>
---
include/linux/memory_hotplug.h | 4 ++--
mm/memory_hotplug.c | 4 ++--
mm/sparse.c | 9 +++++----
3 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h
index d9524c4..35ca1bb 100644
--- a/include/linux/memory_hotplug.h
+++ b/include/linux/memory_hotplug.h
@@ -264,8 +264,8 @@ extern int arch_add_memory(int nid, u64 start, u64 size);
extern int offline_pages(unsigned long start_pfn, unsigned long nr_pages);
extern bool is_memblock_offlined(struct memory_block *mem);
extern void remove_memory(int nid, u64 start, u64 size);
-extern int sparse_add_one_section(struct zone *zone, unsigned long start_pfn);
-extern void sparse_remove_one_section(struct zone *zone, struct mem_section *ms);
+extern int sparse_add_one_section(int nid, unsigned long start_pfn);
+extern void sparse_remove_one_section(int nid, struct mem_section *ms);
extern struct page *sparse_decode_mem_map(unsigned long coded_mem_map,
unsigned long pnum);
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 2ff8c23..e556a90 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -471,7 +471,7 @@ static int __meminit __add_section(int nid, struct zone *zone,
if (pfn_valid(phys_start_pfn))
return -EEXIST;
- ret = sparse_add_one_section(zone, phys_start_pfn);
+ ret = sparse_add_one_section(zone->zone_pgdat->node_id, phys_start_pfn);
if (ret < 0)
return ret;
@@ -737,7 +737,7 @@ static int __remove_section(struct zone *zone, struct mem_section *ms)
start_pfn = section_nr_to_pfn(scn_nr);
__remove_zone(zone, start_pfn);
- sparse_remove_one_section(zone, ms);
+ sparse_remove_one_section(zone->zone_pgdat->node_id, ms);
return 0;
}
diff --git a/mm/sparse.c b/mm/sparse.c
index d1b48b6..12a10ab 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -690,10 +690,10 @@ static void free_map_bootmem(struct page *memmap)
* set. If this is <=0, then that means that the passed-in
* map was not consumed and must be freed.
*/
-int __meminit sparse_add_one_section(struct zone *zone, unsigned long start_pfn)
+int __meminit sparse_add_one_section(int nid, unsigned long start_pfn)
{
unsigned long section_nr = pfn_to_section_nr(start_pfn);
- struct pglist_data *pgdat = zone->zone_pgdat;
+ struct pglist_data *pgdat = NODE_DATA(nid);
struct mem_section *ms;
struct page *memmap;
unsigned long *usemap;
@@ -788,11 +788,11 @@ static void free_section_usemap(struct page *memmap, unsigned long *usemap)
free_map_bootmem(memmap);
}
-void sparse_remove_one_section(struct zone *zone, struct mem_section *ms)
+void sparse_remove_one_section(int nid, struct mem_section *ms)
{
struct page *memmap = NULL;
unsigned long *usemap = NULL, flags;
- struct pglist_data *pgdat = zone->zone_pgdat;
+ struct pglist_data *pgdat = NODE_DATA(nid);
pgdat_resize_lock(pgdat, &flags);
if (ms->section_mem_map) {
@@ -807,5 +807,6 @@ void sparse_remove_one_section(struct zone *zone, struct mem_section *ms)
clear_hwpoisoned_pages(memmap, PAGES_PER_SECTION);
free_section_usemap(memmap, usemap);
}
+
#endif /* CONFIG_MEMORY_HOTREMOVE */
#endif /* CONFIG_MEMORY_HOTPLUG */
--
1.9.3
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related [flat|nested] 58+ messages in thread* Re: [PATCH 5/9] mm: Let sparse_{add,remove}_one_section receive a node_id
2014-09-09 15:45 ` [PATCH 5/9] mm: Let sparse_{add,remove}_one_section receive a node_id Boaz Harrosh
@ 2014-09-09 18:36 ` Dave Hansen
2014-09-10 10:07 ` Boaz Harrosh
0 siblings, 1 reply; 58+ messages in thread
From: Dave Hansen @ 2014-09-09 18:36 UTC (permalink / raw)
To: Boaz Harrosh, Ross Zwisler, Jens Axboe, Matthew Wilcox,
linux-fsdevel, linux-nvdimm, Toshi Kani, linux-mm
Cc: Andrew Morton, linux-kernel
On 09/09/2014 08:45 AM, Boaz Harrosh wrote:
> This is for add_persistent_memory that will want a section of pages
> allocated but without any zone associated. This is because belonging
> to a zone will give the memory to the page allocators, but
> persistent_memory belongs to a block device, and is not available for
> regular volatile usage.
I don't think we should be taking patches like this in to the kernel
until we've seen the other side of it. Where is the page allocator code
which will see a page belonging to no zone? Am I missing it in this set?
I see about 80 or so calls to page_zone() in the kernel. How will a
zone-less page look to all of these sites?
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 58+ messages in thread* Re: [PATCH 5/9] mm: Let sparse_{add,remove}_one_section receive a node_id
2014-09-09 18:36 ` Dave Hansen
@ 2014-09-10 10:07 ` Boaz Harrosh
2014-09-10 16:10 ` Dave Hansen
0 siblings, 1 reply; 58+ messages in thread
From: Boaz Harrosh @ 2014-09-10 10:07 UTC (permalink / raw)
To: Dave Hansen, Ross Zwisler, Jens Axboe, Matthew Wilcox,
linux-fsdevel, linux-nvdimm, Toshi Kani, linux-mm
Cc: Andrew Morton, linux-kernel
On 09/09/2014 09:36 PM, Dave Hansen wrote:
> On 09/09/2014 08:45 AM, Boaz Harrosh wrote:
>> This is for add_persistent_memory that will want a section of pages
>> allocated but without any zone associated. This is because belonging
>> to a zone will give the memory to the page allocators, but
>> persistent_memory belongs to a block device, and is not available for
>> regular volatile usage.
>
> I don't think we should be taking patches like this in to the kernel
> until we've seen the other side of it. Where is the page allocator code
> which will see a page belonging to no zone? Am I missing it in this set?
>
It is not missing. It will never be.
These pages do not belong to any allocator. They are not allocate-able
pages. In fact they are not "memory" they are "storage"
These pages belong wholesomely to a block-device. In turn the block
device grants ownership of a partition of this pages to an FS.
The FS loaded has its own block allocation schema. Which internally
circulate each pages usage around. But the page never goes beyond its
FS.
> I see about 80 or so calls to page_zone() in the kernel. How will a
> zone-less page look to all of these sites?
>
None of these 80 call site will be reached! the pages are always used
below the FS, like send them on the network, or send them to a slower
block device via a BIO. I have a full fledge FS on top of this code
and it all works very smoothly, and stable. (And fast ;))
It is up to the pMem-based FS to manage its pages's ref count so they are
never released outside of its own block allocator.
at the end of the day, struct pages has nothing to do with zones
and allocators and "memory", as it says in Documentation struct
page is a facility to track the state of a physical page in the
system. All the other structures are higher in the stack above
the physical layer, struct-pages for me are the upper API of the
memory physical layer. Which are in common with pmem, higher
on the stack where with memory we have a zone, pmem has a block-device.
Higher where we have page allocators, pmem has an FS block allocator,
higher where we have a slab, pmem has files for user consumption.
pmem is storage, which shares the physical layer with memory, and
this is what this patch describes. There will be no more mm interaction
at all for pmem. The rest of the picture is all there in plain site as
part of this patchset, the pmem.c driver then an FS on top of that. What
else do you need to see?
Thanks
Boaz
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 58+ messages in thread* Re: [PATCH 5/9] mm: Let sparse_{add,remove}_one_section receive a node_id
2014-09-10 10:07 ` Boaz Harrosh
@ 2014-09-10 16:10 ` Dave Hansen
2014-09-10 17:25 ` Boaz Harrosh
0 siblings, 1 reply; 58+ messages in thread
From: Dave Hansen @ 2014-09-10 16:10 UTC (permalink / raw)
To: Boaz Harrosh, Ross Zwisler, Jens Axboe, Matthew Wilcox,
linux-fsdevel, linux-nvdimm, Toshi Kani, linux-mm
Cc: Andrew Morton, linux-kernel
On 09/10/2014 03:07 AM, Boaz Harrosh wrote:
> On 09/09/2014 09:36 PM, Dave Hansen wrote:
>> On 09/09/2014 08:45 AM, Boaz Harrosh wrote:
>>> This is for add_persistent_memory that will want a section of pages
>>> allocated but without any zone associated. This is because belonging
>>> to a zone will give the memory to the page allocators, but
>>> persistent_memory belongs to a block device, and is not available for
>>> regular volatile usage.
>>
>> I don't think we should be taking patches like this in to the kernel
>> until we've seen the other side of it. Where is the page allocator code
>> which will see a page belonging to no zone? Am I missing it in this set?
>
> It is not missing. It will never be.
>
> These pages do not belong to any allocator. They are not allocate-able
> pages. In fact they are not "memory" they are "storage"
>
> These pages belong wholesomely to a block-device. In turn the block
> device grants ownership of a partition of this pages to an FS.
> The FS loaded has its own block allocation schema. Which internally
> circulate each pages usage around. But the page never goes beyond its
> FS.
I'm mostly worried about things that start with an mmap().
Imagine you mmap() a persistent memory file, fault some pages in, then
'cat /proc/$pid/numa_maps'. That code will look at the page to see
which zone and node it is in.
Or, consider if you mmap() then put a futex in the page. The page will
have get_user_pages() called on it by the futex code, and a reference
taken. The reference can outlast the mmap(). We either have to put the
file somewhere special and scan the page's reference occasionally, or we
need to hook something under put_page() to make sure that we keep the
page out of the normal allocator.
>> I see about 80 or so calls to page_zone() in the kernel. How will a
>> zone-less page look to all of these sites?
>
> None of these 80 call site will be reached! the pages are always used
> below the FS, like send them on the network, or send them to a slower
> block device via a BIO. I have a full fledge FS on top of this code
> and it all works very smoothly, and stable. (And fast ;))
Does the fs support mmap()?
The idea of layering is a nice one, but mmap() is a big fat layering
violation. :)
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 58+ messages in thread* Re: [PATCH 5/9] mm: Let sparse_{add,remove}_one_section receive a node_id
2014-09-10 16:10 ` Dave Hansen
@ 2014-09-10 17:25 ` Boaz Harrosh
2014-09-10 18:28 ` Dave Hansen
0 siblings, 1 reply; 58+ messages in thread
From: Boaz Harrosh @ 2014-09-10 17:25 UTC (permalink / raw)
To: Dave Hansen, Ross Zwisler, Jens Axboe, Matthew Wilcox,
linux-fsdevel, linux-nvdimm, Toshi Kani, linux-mm
Cc: Andrew Morton, linux-kernel
On 09/10/2014 07:10 PM, Dave Hansen wrote:
> On 09/10/2014 03:07 AM, Boaz Harrosh wrote:
>> On 09/09/2014 09:36 PM, Dave Hansen wrote:
>>> On 09/09/2014 08:45 AM, Boaz Harrosh wrote:
>>>> This is for add_persistent_memory that will want a section of pages
>>>> allocated but without any zone associated. This is because belonging
>>>> to a zone will give the memory to the page allocators, but
>>>> persistent_memory belongs to a block device, and is not available for
>>>> regular volatile usage.
>>>
>>> I don't think we should be taking patches like this in to the kernel
>>> until we've seen the other side of it. Where is the page allocator code
>>> which will see a page belonging to no zone? Am I missing it in this set?
>>
>> It is not missing. It will never be.
>>
>> These pages do not belong to any allocator. They are not allocate-able
>> pages. In fact they are not "memory" they are "storage"
>>
>> These pages belong wholesomely to a block-device. In turn the block
>> device grants ownership of a partition of this pages to an FS.
>> The FS loaded has its own block allocation schema. Which internally
>> circulate each pages usage around. But the page never goes beyond its
>> FS.
>
> I'm mostly worried about things that start with an mmap().
>
> Imagine you mmap() a persistent memory file, fault some pages in, then
> 'cat /proc/$pid/numa_maps'. That code will look at the page to see
> which zone and node it is in.
>
> Or, consider if you mmap() then put a futex in the page. The page will
> have get_user_pages() called on it by the futex code, and a reference
> taken. The reference can outlast the mmap(). We either have to put the
> file somewhere special and scan the page's reference occasionally, or we
> need to hook something under put_page() to make sure that we keep the
> page out of the normal allocator.
>
Yes the block_allocator of the pmem-FS always holds the final REF on this
page, as long as there is valid data on this block. Even cross boots, the
mount code re-initializes references. The only internal state that frees
these blocks is truncate, which only then return these pages to the block
allocator, all this is common practice in filesystems so the page-ref on
these blocks only ever drops to zero after they loose all visibility. And
yes the block allocator uses a special code to drop the count to zero
not using put_page().
So there is no chance these pages will ever be presented to page_allocators
through a put_page().
BTW: There is an hook in place that can be used today. By calling
SetPagePrivate(page) and setting a .release function on the page->mapping->a_ops
If .release() returns false the page is not released (and can be added on an
internal queue for garbage collection)
But with above schema this is not needed at all. I yet need to find a test
that keeps my free_block reference above 1. At which time I will exercise
a garbage collection queue.
>>> I see about 80 or so calls to page_zone() in the kernel. How will a
>>> zone-less page look to all of these sites?
>>
>> None of these 80 call site will be reached! the pages are always used
>> below the FS, like send them on the network, or send them to a slower
>> block device via a BIO. I have a full fledge FS on top of this code
>> and it all works very smoothly, and stable. (And fast ;))
>
> Does the fs support mmap()?
>
> The idea of layering is a nice one, but mmap() is a big fat layering
> violation. :)
>
No!
Yes the FS supports mmap, but through the DAX patchset. Please see
Matthew's DAX patchset how he implements mmap without using pages
at all, direct PFN to virtual_addr. So these pages do not get exposed
to the top of the FS.
My FS uses his technics exactly only when it wants to spill over to
slower device it will use these pages copy-less.
Cheers
Boaz
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 58+ messages in thread* Re: [PATCH 5/9] mm: Let sparse_{add,remove}_one_section receive a node_id
2014-09-10 17:25 ` Boaz Harrosh
@ 2014-09-10 18:28 ` Dave Hansen
2014-09-11 8:39 ` Boaz Harrosh
0 siblings, 1 reply; 58+ messages in thread
From: Dave Hansen @ 2014-09-10 18:28 UTC (permalink / raw)
To: Boaz Harrosh, Ross Zwisler, Jens Axboe, Matthew Wilcox,
linux-fsdevel, linux-nvdimm, Toshi Kani, linux-mm
Cc: Andrew Morton, linux-kernel
On 09/10/2014 10:25 AM, Boaz Harrosh wrote:
> Yes the block_allocator of the pmem-FS always holds the final REF on this
> page, as long as there is valid data on this block. Even cross boots, the
> mount code re-initializes references. The only internal state that frees
> these blocks is truncate, which only then return these pages to the block
> allocator, all this is common practice in filesystems so the page-ref on
> these blocks only ever drops to zero after they loose all visibility. And
> yes the block allocator uses a special code to drop the count to zero
> not using put_page().
OK, so what happens when a page is truncated out of a file and this
"last" block reference is dropped while a get_user_pages() still has a
reference?
> On 09/10/2014 07:10 PM, Dave Hansen wrote:
>> Does the fs support mmap()?
>>
> No!
>
> Yes the FS supports mmap, but through the DAX patchset. Please see
> Matthew's DAX patchset how he implements mmap without using pages
> at all, direct PFN to virtual_addr. So these pages do not get exposed
> to the top of the FS.
>
> My FS uses his technics exactly only when it wants to spill over to
> slower device it will use these pages copy-less.
>From my perspective, DAX is complicated, but it is necessary because we
don't have a 'struct page'. You're saying that even if we pay the cost
of a 'struct page' for the memory, we still don't get the benefit of
having it like getting rid of this DAX stuff?
Also, about not having a zone for these pages. Do you intend to support
32-bit systems? If so, I believe you will require the kmap() family of
functions to map the pages in order to copy data in and out. kmap()
currently requires knowing the zone of the page.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 58+ messages in thread* Re: [PATCH 5/9] mm: Let sparse_{add,remove}_one_section receive a node_id
2014-09-10 18:28 ` Dave Hansen
@ 2014-09-11 8:39 ` Boaz Harrosh
2014-09-11 17:07 ` Dave Hansen
0 siblings, 1 reply; 58+ messages in thread
From: Boaz Harrosh @ 2014-09-11 8:39 UTC (permalink / raw)
To: Dave Hansen, Boaz Harrosh, Ross Zwisler, Jens Axboe,
Matthew Wilcox, linux-fsdevel, linux-nvdimm, Toshi Kani, linux-mm
Cc: Andrew Morton, linux-kernel
On 09/10/2014 09:28 PM, Dave Hansen wrote:
<>
>
> OK, so what happens when a page is truncated out of a file and this
> "last" block reference is dropped while a get_user_pages() still has a
> reference?
>
I have a very simple plan for this scenario, as I said, hang these pages
with ref!=1 on a garbage list, and one of the clear threads can scan them
periodically and release them.
I have this test in place, currently what I do is just drop the block
and let it leak (that is, not be used any more) until a next mount where
this will be returned to free store. Yes stupid I know. But I have a big
fat message when this happens and I have not been able to reproduce it.
So I'm still waiting for this test case, I guess DAX protects me.
<>
> From my perspective, DAX is complicated, but it is necessary because we
> don't have a 'struct page'. You're saying that even if we pay the cost
> of a 'struct page' for the memory, we still don't get the benefit of
> having it like getting rid of this DAX stuff?
>
No DAX is still necessary because we map storage directly to app space,
and we still need it persistent. That is we can-not/need-not use an
in-ram radix tree but directly use on-storage btrees.
Regular VFS has this 2 tiers model, volatile-ram over persistent store.
DAX is an alternative VFS model where you have a single tier. the name
implies "Direct Access".
So this is nothing to do with page cost or "benefit". DAX is about a new
VFS model for new storage technologies.
And please be noted, the complexity you are talking about is just a learning
curve, on the developers side. Not a technological one. Actually if you
compare the two models, lets call them VFS-2t and VFS-1t, then you see that
DAX is an order of a magnitude simpler then the old model.
Life is hard and we do need the two models all at the same time, to support
all these different devices. So yes the complexity is added with the added
choice. But please do not confuse, DAX is not the complicated part. Having
a Choice is.
> Also, about not having a zone for these pages. Do you intend to support
> 32-bit systems? If so, I believe you will require the kmap() family of
> functions to map the pages in order to copy data in and out. kmap()
> currently requires knowing the zone of the page.
No!!! This is strictly 64 bit. A 32bit system is able to have at maximum
3Gb of low-ram + storage.
DAX implies always mapped. That is, no re-mapping. So this rules out
more then a G of storage. Since that is a joke then No! 32bit is out.
You need to understand current HW std talks about DDR4 and there are
DDR3 samples flouting around. So this is strictly 64bit, even on
phones.
Thanks
Boaz
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 58+ messages in thread* Re: [PATCH 5/9] mm: Let sparse_{add,remove}_one_section receive a node_id
2014-09-11 8:39 ` Boaz Harrosh
@ 2014-09-11 17:07 ` Dave Hansen
2014-09-14 9:36 ` Boaz Harrosh
0 siblings, 1 reply; 58+ messages in thread
From: Dave Hansen @ 2014-09-11 17:07 UTC (permalink / raw)
To: Boaz Harrosh, Boaz Harrosh, Ross Zwisler, Jens Axboe,
Matthew Wilcox, linux-fsdevel, linux-nvdimm, Toshi Kani, linux-mm
Cc: Andrew Morton, linux-kernel
On 09/11/2014 01:39 AM, Boaz Harrosh wrote:
> On 09/10/2014 09:28 PM, Dave Hansen wrote:
>> OK, so what happens when a page is truncated out of a file and this
>> "last" block reference is dropped while a get_user_pages() still has a
>> reference?
>
> I have a very simple plan for this scenario, as I said, hang these pages
> with ref!=1 on a garbage list, and one of the clear threads can scan them
> periodically and release them.
>
> I have this test in place, currently what I do is just drop the block
> and let it leak (that is, not be used any more) until a next mount where
> this will be returned to free store. Yes stupid I know. But I have a big
> fat message when this happens and I have not been able to reproduce it.
> So I'm still waiting for this test case, I guess DAX protects me.
OK, that sounds like it will work. The "leaked until the next mount"
sounds disastrous, but I'm sure you'll fix that. I can see how it might
lead to some fragmentation if only small amounts are ever pinned, but
not a deal-breaker.
>> From my perspective, DAX is complicated, but it is necessary because we
>> don't have a 'struct page'. You're saying that even if we pay the cost
>> of a 'struct page' for the memory, we still don't get the benefit of
>> having it like getting rid of this DAX stuff?
>
> No DAX is still necessary because we map storage directly to app space,
> and we still need it persistent. That is we can-not/need-not use an
> in-ram radix tree but directly use on-storage btrees.
Huh? We obviously don't need/want persistent memory pages in the page
*cache*. But, that's completely orthogonal to _having_ a 'struct page'
for them.
DAX does two major things:
1. avoids needing the page cache
2. creates "raw" page table entries that the VM does not manage
for mmap()s
I'm not saying to put persistent memory in the page cache.
I'm saying that, if we have a 'struct page' for the memory, we should
try to make the mmap()s more normal. This enables all kinds of things
that DAX does not support today, like direct I/O.
> Life is hard and we do need the two models all at the same time, to support
> all these different devices. So yes the complexity is added with the added
> choice. But please do not confuse, DAX is not the complicated part. Having
> a Choice is.
Great, so we at least agree that this adds complexity.
>> Also, about not having a zone for these pages. Do you intend to support
>> 32-bit systems? If so, I believe you will require the kmap() family of
>> functions to map the pages in order to copy data in and out. kmap()
>> currently requires knowing the zone of the page.
>
> No!!! This is strictly 64 bit. A 32bit system is able to have at maximum
> 3Gb of low-ram + storage.
> DAX implies always mapped. That is, no re-mapping. So this rules out
> more then a G of storage. Since that is a joke then No! 32bit is out.
>
> You need to understand current HW std talks about DDR4 and there are
> DDR3 samples flouting around. So this is strictly 64bit, even on
> phones.
OK, so I think I at least understand the scope of the patch set and the
limitations. I think I've summarized the limitations:
1. Approach requires all of RAM+Pmem to be direct-mapped (rules out
almost all 32-bit systems, or any 64-bit systems with more than 64TB
of RAM+pmem-storage)
2. Approach is currently incompatible with some kernel code that
requires a 'struct page' (such as direct I/O), and all kernel code
that requires knowledge of zones or NUMA nodes.
3. Approach requires 1/64 of the amount of storage to be consumed by
RAM for a pseudo 'struct page'. If you had 64GB of storage and 1GB
of RAM, you would simply run our of RAM.
Did I miss any?
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 58+ messages in thread* Re: [PATCH 5/9] mm: Let sparse_{add,remove}_one_section receive a node_id
2014-09-11 17:07 ` Dave Hansen
@ 2014-09-14 9:36 ` Boaz Harrosh
0 siblings, 0 replies; 58+ messages in thread
From: Boaz Harrosh @ 2014-09-14 9:36 UTC (permalink / raw)
To: Dave Hansen, Boaz Harrosh, Ross Zwisler, Jens Axboe,
Matthew Wilcox, linux-fsdevel, linux-nvdimm, Toshi Kani, linux-mm
Cc: Andrew Morton, linux-kernel
On 09/11/2014 08:07 PM, Dave Hansen wrote:
<>
>
> OK, that sounds like it will work. The "leaked until the next mount"
> sounds disastrous, but I'm sure you'll fix that. I can see how it might
> lead to some fragmentation if only small amounts are ever pinned, but
> not a deal-breaker.
>
There is no such thing as fragmentation with memory mapped storage ;-)
<>
> I'm saying that, if we have a 'struct page' for the memory, we should
> try to make the mmap()s more normal. This enables all kinds of things
> that DAX does not support today, like direct I/O.
>
What? no! direct I/O is fully supported. Including all API's of it. Do
you mean open(O_DIRECT) and io_submit(..) Yes it is fully supported.
In fact all IO is direct IO. there is never page-cache on the way, hence direct
BTW: These patches enable something else. Say FSA is DAX and FSB is regular
disk FS then
fda = open(/mnt/FSA);
pa = mmap(fda, ...);
fdb = open(/mnt/FSB, O_DIRECT);
io_submit(fdb,..,pa ,..);
/* I mean pa is put for IO into the passed iocb for fdb */
Before this patch above will not work and revert to buffered IO, but
with these patches it will work.
Please note this is true for the submitted pmem driver. With brd which
also supports DAX this will work, because brd always uses pages.
<>
> Great, so we at least agree that this adds complexity.
>
But the complexity is already there DAX by Matthew is to go in soon I hope.
Surly these added pages do not add to the complexity that much.
<>
>
> OK, so I think I at least understand the scope of the patch set and the
> limitations. I think I've summarized the limitations:
>
> 1. Approach requires all of RAM+Pmem to be direct-mapped (rules out
> almost all 32-bit systems, or any 64-bit systems with more than 64TB
> of RAM+pmem-storage)
Yes, for NOW
> 2. Approach is currently incompatible with some kernel code that
> requires a 'struct page' (such as direct I/O), and all kernel code
> that requires knowledge of zones or NUMA nodes.
NO!
Direct IO - supported
NUMA - supported
"all kernel code that requires knowledge of zones" - Not needed
> 3. Approach requires 1/64 of the amount of storage to be consumed by
> RAM for a pseudo 'struct page'. If you had 64GB of storage and 1GB
> of RAM, you would simply run our of RAM.
>
Yes so in a system as above of 64GB of pmem, 1GB of pmem will need to be
set aside and hotpluged as volatile memory. This already works today BTW
you can set aside a portion of NvDIMM and hotplug it as system memory.
We are already used to pay that ratio for RAM.
On a kernel-config choice that ratio can be also paid for pmem. This is
why I left it a configuration option
> Did I miss any?
>
Thanks
Boaz
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 58+ messages in thread
* [PATCH 6/9] mm: New add_persistent_memory/remove_persistent_memory
2014-09-09 15:37 ` [PATCH 0/9] pmem: Fixes and farther development (mm: add_persistent_memory) Boaz Harrosh
` (4 preceding siblings ...)
2014-09-09 15:45 ` [PATCH 5/9] mm: Let sparse_{add,remove}_one_section receive a node_id Boaz Harrosh
@ 2014-09-09 15:47 ` Boaz Harrosh
2014-09-09 15:48 ` [PATCH 7/9] pmem: Add support for page structs Boaz Harrosh
` (4 subsequent siblings)
10 siblings, 0 replies; 58+ messages in thread
From: Boaz Harrosh @ 2014-09-09 15:47 UTC (permalink / raw)
To: Ross Zwisler, Jens Axboe, Matthew Wilcox, linux-fsdevel,
linux-nvdimm, Toshi Kani, Dave Hansen, linux-mm
Cc: Andrew Morton, linux-kernel
From: Boaz Harrosh <boaz@plexistor.com>
Persistent Memory is not Memory. It is not presented as
a Memory Zone and is not available through the page allocators
for application/kernel volatile usage.
It belongs to A block device just as any other Persistent storage,
the novelty here is that it is directly mapped on the CPU Memory
bus, and usually as fast or almost as fast as system RAM.
The main motivation of add_persistent_memory is to allocate a
page-struct "Section" for a given physical memory region. This is because
The user of this memory mapped device might need to pass pages-struct
of this memory to a Kernel subsytem like block-layer or networking
and have it's content directly DMAed to other devices
(For example these pages can be put on a bio and sent to disk
in a copy-less manner)
It will also request_mem_region_exclusive(.., "persistent_memory")
to own that physical memory region.
And will map that physical region to the Kernel's VM at the
address expected for page_address() of those pages allocated
above
remove_persistent_memory() must be called to undo what
add_persistent_memory did.
A user of this API will then use pfn_to_page(PHISICAL_ADDR >> PAGE_SIZE)
to receive a page-struct for use on its pmem.
Any operation like page_address() page_to_pfn() page_lock() ... can
be preformed on these pages just as usual.
An example user is presented in the next patch to pmem.c Block Device
driver (There are 3 more such drivers in the Kernel that could use this
API)
This patch is based on research and patch made by
Yigal Korman <yigal@plexistor.com> to the pmem driver. I took his code
and adapted it to mm, where it belongs.
Signed-off-by: Yigal Korman <yigal@plexistor.com>
Signed-off-by: Boaz Harrosh <boaz@plexistor.com>
---
include/linux/memory_hotplug.h | 4 +
mm/Kconfig | 23 ++++++
mm/memory_hotplug.c | 177 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 204 insertions(+)
diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h
index 35ca1bb..9a16cec 100644
--- a/include/linux/memory_hotplug.h
+++ b/include/linux/memory_hotplug.h
@@ -191,6 +191,10 @@ extern void get_page_bootmem(unsigned long ingo, struct page *page,
void get_online_mems(void);
void put_online_mems(void);
+int add_persistent_memory(phys_addr_t phys_addr, size_t size,
+ void **o_virt_addr);
+void remove_persistent_memory(phys_addr_t phys_addr, size_t size);
+
#else /* ! CONFIG_MEMORY_HOTPLUG */
/*
* Stub functions for when hotplug is off
diff --git a/mm/Kconfig b/mm/Kconfig
index 886db21..2b78d19 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -197,6 +197,29 @@ config MEMORY_HOTREMOVE
depends on MEMORY_HOTPLUG && ARCH_ENABLE_MEMORY_HOTREMOVE
depends on MIGRATION
+
+# User of PERSISTENT_MEMORY_SECTION should:
+# depends on PERSISTENT_MEMORY_DEPENDENCY and
+# select DRIVER_NEEDS_PERSISTENT_MEMORY
+# Note that it will not be enabled if MEMORY_HOTPLUG is not enabled
+#
+# If you have changed the dependency/select of MEMORY_HOTREMOVE please also
+# update here
+#
+config PERSISTENT_MEMORY_DEPENDENCY
+ def_bool y
+ depends on MEMORY_HOTPLUG
+ depends on ARCH_ENABLE_MEMORY_HOTREMOVE && MIGRATION
+
+config DRIVER_NEEDS_PERSISTENT_MEMORY
+ bool
+
+config PERSISTENT_MEMORY_SECTION
+ def_bool y
+ depends on PERSISTENT_MEMORY_DEPENDENCY
+ depends on DRIVER_NEEDS_PERSISTENT_MEMORY
+ select MEMORY_HOTREMOVE
+
#
# If we have space for more page flags then we can enable additional
# optimizations and functionality.
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index e556a90..1682b0e 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -2004,3 +2004,180 @@ void __ref remove_memory(int nid, u64 start, u64 size)
}
EXPORT_SYMBOL_GPL(remove_memory);
#endif /* CONFIG_MEMORY_HOTREMOVE */
+
+#ifdef CONFIG_PERSISTENT_MEMORY_SECTION
+
+/* This helper is so we do not need to allocate a page_array bigger
+ * than PAGE_SIZE
+ */
+static int _map_sec_range(ulong sec_start_pfn, struct page **page_array)
+{
+ const uint NUM_PAGES = PAGE_SIZE / sizeof(*page_array);
+ const uint ARRAYS_IN_SECTION = PAGES_PER_SECTION / NUM_PAGES;
+ ulong pfn = sec_start_pfn;
+ uint a;
+
+ for (a = 0; a < ARRAYS_IN_SECTION; ++a) {
+ ulong virt_addr = (ulong)page_address(pfn_to_page(pfn));
+ uint p;
+ int ret;
+
+ for (p = 0; p < NUM_PAGES; ++p)
+ page_array[p] = pfn_to_page(pfn++);
+
+ ret = map_kernel_range_noflush(virt_addr, NUM_PAGES * PAGE_SIZE,
+ PAGE_KERNEL, page_array);
+ if (unlikely(ret < 0)) {
+ pr_warn("%s: map_kernel_range(0x%lx, 0x%lx) => %d\n",
+ __func__, sec_start_pfn, virt_addr, ret);
+ return ret;
+ }
+ if (unlikely(ret < NUM_PAGES)) {
+ pr_warn("%s: map_kernel_range(0x%lx) => %d != %d last_pfn=0x%lx\n",
+ __func__, virt_addr, NUM_PAGES, ret, pfn);
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * add_persistent_memory - Add memory sections and maps them to Kernel space
+ * @phys_addr: start of physical address to add & map
+ * @size: size of the memory range in bytes
+ * @o_virt_addr: The returned virtual address of the mapped memory range
+ *
+ * A persistent_memory block-device will use this function to add memory
+ * sections and map its physical memory range. After the call to this function
+ * There will be page-struct associated with each pfn added here, and it will
+ * be accessible from Kernel space through the returned @o_virt_addr
+ * @phys_addr will be rounded down to the nearest SECTION_SIZE, the range
+ * mapped will be in full SECTION_SIZE sections.
+ * @o_virt_addr is the address of @phys_addr not the start of the mapped section
+ * so usually mapping a range unaligned on SECTION_SIZE will work just that the
+ * unaligned start and/or end, will ignore the error and continue.
+ * (but will print "memory section XX already exists")
+ *
+ * NOTE:
+ * persistent_memory is not system ram and is not available through any
+ * allocator, for regular consumption. Therefore it does not belong to any
+ * memory zone.
+ * But it will need a memory-section allocated, so page-structs are available
+ * for this memory, so it can be DMA'd directly with zero copy.
+ * After a call to this function the ranged pages belong exclusively to the
+ * caller.
+ *
+ * RETURNS:
+ * zero on success, or -errno on failure. If successful @o_virt_addr will be set
+ */
+int add_persistent_memory(phys_addr_t phys_addr, size_t size,
+ void **o_virt_addr)
+{
+ ulong start_pfn = phys_addr >> PAGE_SHIFT;
+ ulong nr_pages = size >> PAGE_SHIFT;
+ ulong start_sec = pfn_to_section_nr(start_pfn);
+ ulong end_sec = pfn_to_section_nr(start_pfn + nr_pages +
+ PAGES_PER_SECTION - 1);
+ int nid = memory_add_physaddr_to_nid(phys_addr);
+ struct resource *res_mem;
+ struct page **page_array;
+ ulong i;
+ int ret = 0;
+
+ page_array = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (unlikely(!page_array))
+ return -ENOMEM;
+
+ res_mem = request_mem_region_exclusive(phys_addr, size,
+ "persistent_memory");
+ if (unlikely(!res_mem)) {
+ pr_warn("%s: request_mem_region_exclusive phys=0x%llx size=0x%zx failed\n",
+ __func__, phys_addr, size);
+ ret = -EINVAL;
+ goto free_array;
+ }
+
+ for (i = start_sec; i < end_sec; ++i) {
+ ulong sec_start_pfn = i << PFN_SECTION_SHIFT;
+
+ if (pfn_valid(sec_start_pfn)) {
+ pr_warn("%s: memory section %lu already exists.\n",
+ __func__, i);
+ continue;
+ }
+
+ ret = sparse_add_one_section(nid, sec_start_pfn);
+ if (unlikely(ret < 0)) {
+ if (ret == -EEXIST) {
+ ret = 0;
+ continue;
+ } else {
+ pr_warn("%s: sparse_add_one_section => %d\n",
+ __func__, ret);
+ goto release_region;
+ }
+ }
+
+ ret = _map_sec_range(sec_start_pfn, page_array);
+ if (unlikely(ret))
+ goto release_region;
+ }
+
+ *o_virt_addr = page_address(pfn_to_page(start_pfn));
+
+free_array:
+ kfree(page_array);
+ return ret;
+
+release_region:
+ release_mem_region(phys_addr, size);
+ goto free_array;
+}
+EXPORT_SYMBOL_GPL(add_persistent_memory);
+
+/**
+ * remove_persistent_memory - undo anything add_persistent_memory did
+ * @phys_addr: start of physical address to remove
+ * @size: size of the memory range in bytes
+ *
+ * A successful call to add_persistent_memory must be paired with
+ * remove_persistent_memory when done. It will unmap passed PFNs from
+ * Kernel virtual address, and will remove the memory sections.
+ * @phys_addr, @size must be exactly those passed to add_persistent_memory
+ * otherwise results are unexpected, there are no checks done on this.
+ */
+void remove_persistent_memory(phys_addr_t phys_addr, size_t size)
+{
+ ulong start_pfn = phys_addr >> PAGE_SHIFT;
+ ulong nr_pages = size >> PAGE_SHIFT;
+ ulong start_sec = pfn_to_section_nr(start_pfn);
+ ulong end_sec = pfn_to_section_nr(start_pfn + nr_pages +
+ PAGES_PER_SECTION - 1);
+ int nid = pfn_to_nid(start_pfn);
+ ulong virt_addr;
+ unsigned int i;
+
+ virt_addr = (ulong)page_address(
+ pfn_to_page(start_sec << PFN_SECTION_SHIFT));
+
+ for (i = start_sec; i < end_sec; ++i) {
+ struct mem_section *ms;
+
+ unmap_kernel_range(virt_addr, 1UL << SECTION_SIZE_BITS);
+ virt_addr += 1UL << SECTION_SIZE_BITS;
+
+ ms = __nr_to_section(i);
+ if (!valid_section(ms)) {
+ pr_warn("%s: memory section %d is missing.\n",
+ __func__, i);
+ continue;
+ }
+ sparse_remove_one_section(nid, ms);
+ }
+
+ release_mem_region(phys_addr, size);
+}
+EXPORT_SYMBOL_GPL(remove_persistent_memory);
+
+#endif /* def CONFIG_PERSISTENT_MEMORY_SECTION */
+
--
1.9.3
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related [flat|nested] 58+ messages in thread* [PATCH 7/9] pmem: Add support for page structs
2014-09-09 15:37 ` [PATCH 0/9] pmem: Fixes and farther development (mm: add_persistent_memory) Boaz Harrosh
` (5 preceding siblings ...)
2014-09-09 15:47 ` [PATCH 6/9] mm: New add_persistent_memory/remove_persistent_memory Boaz Harrosh
@ 2014-09-09 15:48 ` Boaz Harrosh
2014-09-09 15:49 ` [PATCH 8/9] SQUASHME: pmem: Fixs to getgeo Boaz Harrosh
` (3 subsequent siblings)
10 siblings, 0 replies; 58+ messages in thread
From: Boaz Harrosh @ 2014-09-09 15:48 UTC (permalink / raw)
To: Ross Zwisler, Jens Axboe, Matthew Wilcox, linux-fsdevel,
linux-nvdimm, Toshi Kani, Dave Hansen, linux-mm
Cc: Andrew Morton, linux-kernel
From: Boaz Harrosh <boaz@plexistor.com>
One of the current shortcomings of the NVDIMM/PMEM
support is that this memory does not have a page-struct(s)
associated with its memory and therefor cannot be passed
to a block-device or network or DMAed in any way through
another device in the system.
The use of add_persistent_memory() fixes all this. After this patch
an FS can do:
bdev_direct_access(,&pfn,);
page = pfn_to_page(pfn);
And use that page for a lock_page(), set_page_dirty(), and/or
anything else one might do with a page *.
(Note that with brd one can already do this)
[pmem-pages-ref-count]
pmem will serve it's pages with ref==0. Once an FS does
an blkdev_get_XXX(,FMODE_EXCL,), that memory is own by the FS.
The FS needs to manage its allocation, just as it already does
for its disk blocks. The fs should set page->count = 2, before
submission to any Kernel subsystem so when it returns it will
never be released to the Kernel's page-allocators. (page_freeze)
Signed-off-by: Boaz Harrosh <boaz@plexistor.com>
---
drivers/block/Kconfig | 13 +++++++++++++
drivers/block/pmem.c | 19 +++++++++++++++++++
2 files changed, 32 insertions(+)
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index 5da8cbf..8a5929c 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -416,6 +416,19 @@ config BLK_DEV_PMEM
Most normal users won't need this functionality, and can thus say N
here.
+config BLK_DEV_PMEM_USE_PAGES
+ bool "Enable use of page struct pages with pmem"
+ depends on BLK_DEV_PMEM
+ depends on PERSISTENT_MEMORY_DEPENDENCY
+ select DRIVER_NEEDS_PERSISTENT_MEMORY
+ default y
+ help
+ If a user of PMEM device needs "struct page" associated
+ with its memory, so this memory can be sent to other
+ block devices, or sent on the network, or be DMA transferred
+ to other devices in the system, then you must say "Yes" here.
+ If unsure leave as Yes.
+
config CDROM_PKTCDVD
tristate "Packet writing on CD/DVD media"
depends on !UML
diff --git a/drivers/block/pmem.c b/drivers/block/pmem.c
index e07a373..b415b61 100644
--- a/drivers/block/pmem.c
+++ b/drivers/block/pmem.c
@@ -221,6 +221,23 @@ MODULE_PARM_DESC(map,
static LIST_HEAD(pmem_devices);
static int pmem_major;
+#ifdef CONFIG_BLK_DEV_PMEM_USE_PAGES
+/* pmem->phys_addr and pmem->size need to be set.
+ * Will then set pmem->virt_addr if successful.
+ */
+int pmem_mapmem(struct pmem_device *pmem)
+{
+ return add_persistent_memory(pmem->phys_addr, pmem->size,
+ &pmem->virt_addr);
+}
+
+static void pmem_unmapmem(struct pmem_device *pmem)
+{
+ remove_persistent_memory(pmem->phys_addr, pmem->size);
+}
+
+#else /* !CONFIG_BLK_DEV_PMEM_USE_PAGES */
+
/* pmem->phys_addr and pmem->size need to be set.
* Will then set virt_addr if successful.
*/
@@ -258,6 +275,8 @@ void pmem_unmapmem(struct pmem_device *pmem)
release_mem_region(pmem->phys_addr, pmem->size);
pmem->virt_addr = NULL;
}
+#endif /* ! CONFIG_BLK_DEV_PMEM_USE_PAGES */
+
static struct pmem_device *pmem_alloc(phys_addr_t phys_addr, size_t disk_size,
int i)
--
1.9.3
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related [flat|nested] 58+ messages in thread* [PATCH 8/9] SQUASHME: pmem: Fixs to getgeo
2014-09-09 15:37 ` [PATCH 0/9] pmem: Fixes and farther development (mm: add_persistent_memory) Boaz Harrosh
` (6 preceding siblings ...)
2014-09-09 15:48 ` [PATCH 7/9] pmem: Add support for page structs Boaz Harrosh
@ 2014-09-09 15:49 ` Boaz Harrosh
2014-09-09 15:51 ` [PATCH 9/9] pmem: KISS, remove register_blkdev Boaz Harrosh
` (2 subsequent siblings)
10 siblings, 0 replies; 58+ messages in thread
From: Boaz Harrosh @ 2014-09-09 15:49 UTC (permalink / raw)
To: Ross Zwisler, Jens Axboe, Matthew Wilcox, linux-fsdevel,
linux-nvdimm
Cc: Andrew Morton
From: Boaz Harrosh <boaz@plexistor.com>
With current values fdisk does the wrong thing. On small disks
it will offer 40 (20K) as first possible sector.
With this patch fdisk will offer 8 (4k) as possible first
sector, which is what we want.
Note that current code had a BUG with anything bigger than
64G because hd_geometry->cylinders is ushort and it would
overflow at this value. Anyway capacity is not calculated
through getgeo so it does not matter what we set for cylinders.
I have tested with cfdisk parted/gparted and they behave the
same after this patch, with fdisk I have better expected behavior
after this patch.
Is there any other test I need to perform that might be affected
by this?
Signed-off-by: Boaz Harrosh <boaz@plexistor.com>
---
drivers/block/pmem.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/drivers/block/pmem.c b/drivers/block/pmem.c
index b415b61..600d225 100644
--- a/drivers/block/pmem.c
+++ b/drivers/block/pmem.c
@@ -40,10 +40,16 @@ struct pmem_device {
static int pmem_getgeo(struct block_device *bd, struct hd_geometry *geo)
{
- /* some standard values */
- geo->heads = 1 << 6;
- geo->sectors = 1 << 5;
- geo->cylinders = get_capacity(bd->bd_disk) >> 11;
+ /* Just tell fdisk to get out of the way. The CHS math here is so
+ * convoluted and does not make any sense at all. With all 1s
+ * The math just gets out of the way.
+ * When doing the usual lying to fdisk with the (64,32,X) common at the
+ * rest of the Kernel, fdisk will offer 34 as first sector, with this
+ * here plus the 4K physical_block_size it will offer 8 (4K)
+ */
+ geo->heads = 1;
+ geo->sectors = 1;
+ geo->cylinders = 1;
return 0;
}
--
1.9.3
^ permalink raw reply related [flat|nested] 58+ messages in thread* [PATCH 9/9] pmem: KISS, remove register_blkdev
2014-09-09 15:37 ` [PATCH 0/9] pmem: Fixes and farther development (mm: add_persistent_memory) Boaz Harrosh
` (7 preceding siblings ...)
2014-09-09 15:49 ` [PATCH 8/9] SQUASHME: pmem: Fixs to getgeo Boaz Harrosh
@ 2014-09-09 15:51 ` Boaz Harrosh
2014-09-10 16:50 ` [PATCH] SQUASHME pmem: Micro optimization for pmem_direct_access Boaz Harrosh
2014-09-10 17:50 ` [PATCH] SQUASHME: pmem: Add MODULE_ALIAS Boaz Harrosh
10 siblings, 0 replies; 58+ messages in thread
From: Boaz Harrosh @ 2014-09-09 15:51 UTC (permalink / raw)
To: Ross Zwisler, Jens Axboe, Matthew Wilcox, linux-fsdevel,
linux-nvdimm
Cc: Andrew Morton, linux-kernel
From: Boaz Harrosh <boaz@plexistor.com>
Though this looks revolutionary, it actually does nothing
but removes dead code.
Since the move of pmem to the dynamic BLOCK_EXT_MAJOR
range, by Ross, pmem_major returned from register_blkdev
is not used.
If inspecting the code at add_disk() we can see that
whatever number we will put at
disk->major = ...
disk->first_minor = ...
will be immediately overwritten with the BLOCK_EXT_MAJOR
and a dynamically allocated minor. Regardless of the
registration and/or what ever we put at disk->major.
I have tested all the tests that I know how to perform
on the devices, fdisk, partitions, multiple pmemX devices,
mknode, lsblk, blkid, and it all behaves exactly as
before this patch.
I have also done:
find /sys/ -name "*pmem*"
find /proc/ -name "*pmem*"
find /dev/ -name "*pmem*"
And get the same output as before this patch.
The only thing missing is an entry in /proc/devices of
the form: "250 pmem" (250 or what ever is free at the moment)
But this is good because if one tries to look for 250
devices after loading pmem he will fail because pmem
is always registered as 259 (blkext) now.
If anyone knows of what would work differently after this
patch please do tell.
But it looks like the calls to register_blkdev is just dead
code for us right now
Thanks
Signed-off-by: Boaz Harrosh <boaz@plexistor.com>
---
drivers/block/pmem.c | 11 -----------
1 file changed, 11 deletions(-)
diff --git a/drivers/block/pmem.c b/drivers/block/pmem.c
index 600d225..5eda95a 100644
--- a/drivers/block/pmem.c
+++ b/drivers/block/pmem.c
@@ -225,7 +225,6 @@ MODULE_PARM_DESC(map,
"mapS=nn[KMG]$ss[KMG] or mapS=nn[KMG]@ss[KMG], nn=size, ss=offset.");
static LIST_HEAD(pmem_devices);
-static int pmem_major;
#ifdef CONFIG_BLK_DEV_PMEM_USE_PAGES
/* pmem->phys_addr and pmem->size need to be set.
@@ -333,8 +332,6 @@ static struct pmem_device *pmem_alloc(phys_addr_t phys_addr, size_t disk_size,
goto out_free_queue;
}
- disk->major = pmem_major;
- disk->first_minor = 0;
disk->fops = &pmem_fops;
disk->private_data = pmem;
disk->queue = pmem->pmem_queue;
@@ -397,12 +394,6 @@ static int __init pmem_init(void)
return -EINVAL;
}
- result = register_blkdev(0, "pmem");
- if (result < 0)
- return -EIO;
- else
- pmem_major = result;
-
i = 0;
while ((p = strsep(&pmem_map, ",")) != NULL) {
phys_addr_t phys_addr;
@@ -433,7 +424,6 @@ out_free:
list_del(&pmem->pmem_list);
pmem_free(pmem);
}
- unregister_blkdev(pmem_major, "pmem");
return result;
}
@@ -445,7 +435,6 @@ static void __exit pmem_exit(void)
list_for_each_entry_safe(pmem, next, &pmem_devices, pmem_list)
pmem_del_one(pmem);
- unregister_blkdev(pmem_major, "pmem");
pr_info("pmem: module unloaded\n");
}
--
1.9.3
^ permalink raw reply related [flat|nested] 58+ messages in thread* [PATCH] SQUASHME pmem: Micro optimization for pmem_direct_access
2014-09-09 15:37 ` [PATCH 0/9] pmem: Fixes and farther development (mm: add_persistent_memory) Boaz Harrosh
` (8 preceding siblings ...)
2014-09-09 15:51 ` [PATCH 9/9] pmem: KISS, remove register_blkdev Boaz Harrosh
@ 2014-09-10 16:50 ` Boaz Harrosh
2014-09-10 22:32 ` Ross Zwisler
2014-09-14 14:58 ` [PATCH v2] SQUASHME pmem: Micro optimize the hotpath Boaz Harrosh
2014-09-10 17:50 ` [PATCH] SQUASHME: pmem: Add MODULE_ALIAS Boaz Harrosh
10 siblings, 2 replies; 58+ messages in thread
From: Boaz Harrosh @ 2014-09-10 16:50 UTC (permalink / raw)
To: Ross Zwisler; +Cc: Jens Axboe, Matthew Wilcox, linux-fsdevel, linux-nvdimm
From: Boaz Harrosh <boaz@plexistor.com>
Please note: This patch spans two patches in the set:
* The changes to pmem_lookup_pg_addr from [patch 1/4]
* The removal to pmem_lookup_pfn and changes to pmem_direct_access
from [patch 4/4]
This is the hotpath I care about / pmem_direct_access()
Easier on the eyes too
Signed-off-by: Boaz Harrosh <boaz@plexistor.com>
---
drivers/block/pmem.c | 20 ++++++--------------
1 file changed, 6 insertions(+), 14 deletions(-)
diff --git a/drivers/block/pmem.c b/drivers/block/pmem.c
index 5eda95a..4a9d65e 100644
--- a/drivers/block/pmem.c
+++ b/drivers/block/pmem.c
@@ -61,22 +61,12 @@ static int pmem_getgeo(struct block_device *bd, struct hd_geometry *geo)
*/
static void *pmem_lookup_pg_addr(struct pmem_device *pmem, sector_t sector)
{
- size_t page_offset = sector >> PAGE_SECTORS_SHIFT;
- size_t offset = page_offset << PAGE_SHIFT;
+ size_t offset = sector << SECTOR_SHIFT;
BUG_ON(offset >= pmem->size);
return pmem->virt_addr + offset;
}
-/* sector must be page aligned */
-static unsigned long pmem_lookup_pfn(struct pmem_device *pmem, sector_t sector)
-{
- size_t page_offset = sector >> PAGE_SECTORS_SHIFT;
-
- BUG_ON(sector & (PAGE_SECTORS - 1));
- return (pmem->phys_addr >> PAGE_SHIFT) + page_offset;
-}
-
/*
* sector is not required to be page aligned.
* n is at most a single page, but could be less.
@@ -200,14 +190,16 @@ static long pmem_direct_access(struct block_device *bdev, sector_t sector,
void **kaddr, unsigned long *pfn, long size)
{
struct pmem_device *pmem = bdev->bd_disk->private_data;
+ size_t offset = sector << SECTOR_SHIFT;
if (!pmem)
return -ENODEV;
- *kaddr = pmem_lookup_pg_addr(pmem, sector);
- *pfn = pmem_lookup_pfn(pmem, sector);
+ BUG_ON(offset >= pmem->size);
+ *kaddr = pmem->virt_addr + offset;
+ *pfn = (pmem->phys_addr + offset) >> PAGE_SHIFT;
- return pmem->size - (sector * 512);
+ return pmem->size - offset;
}
static const struct block_device_operations pmem_fops = {
--
1.9.3
^ permalink raw reply related [flat|nested] 58+ messages in thread* Re: [PATCH] SQUASHME pmem: Micro optimization for pmem_direct_access
2014-09-10 16:50 ` [PATCH] SQUASHME pmem: Micro optimization for pmem_direct_access Boaz Harrosh
@ 2014-09-10 22:32 ` Ross Zwisler
2014-09-11 11:42 ` Boaz Harrosh
2014-09-14 14:58 ` [PATCH v2] SQUASHME pmem: Micro optimize the hotpath Boaz Harrosh
1 sibling, 1 reply; 58+ messages in thread
From: Ross Zwisler @ 2014-09-10 22:32 UTC (permalink / raw)
To: Boaz Harrosh; +Cc: Jens Axboe, Matthew Wilcox, linux-fsdevel, linux-nvdimm
On Wed, 2014-09-10 at 19:50 +0300, Boaz Harrosh wrote:
> From: Boaz Harrosh <boaz@plexistor.com>
>
> Please note: This patch spans two patches in the set:
>
> * The changes to pmem_lookup_pg_addr from [patch 1/4]
> * The removal to pmem_lookup_pfn and changes to pmem_direct_access
> from [patch 4/4]
>
> This is the hotpath I care about / pmem_direct_access()
> Easier on the eyes too
> Signed-off-by: Boaz Harrosh <boaz@plexistor.com>
> ---
> drivers/block/pmem.c | 20 ++++++--------------
> 1 file changed, 6 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/block/pmem.c b/drivers/block/pmem.c
> index 5eda95a..4a9d65e 100644
> --- a/drivers/block/pmem.c
> +++ b/drivers/block/pmem.c
> @@ -61,22 +61,12 @@ static int pmem_getgeo(struct block_device *bd, struct hd_geometry *geo)
> */
> static void *pmem_lookup_pg_addr(struct pmem_device *pmem, sector_t sector)
> {
> - size_t page_offset = sector >> PAGE_SECTORS_SHIFT;
> - size_t offset = page_offset << PAGE_SHIFT;
> + size_t offset = sector << SECTOR_SHIFT;
You just broke the "The return value will point to the beginning of the page
containing the given sector, not to the sector itself." part of the contract
spelled out in the comments. This means that when you have an I/O that starts
at a sector that isn't page aligned, copy_to_pmem() or copy_from_pmem() will
get back a pointer to the *sector*, not the *page*, and the memcopy that takes
into account the offset will do the wrong thing.
> BUG_ON(offset >= pmem->size);
> return pmem->virt_addr + offset;
> }
>
> -/* sector must be page aligned */
> -static unsigned long pmem_lookup_pfn(struct pmem_device *pmem, sector_t sector)
> -{
> - size_t page_offset = sector >> PAGE_SECTORS_SHIFT;
> -
> - BUG_ON(sector & (PAGE_SECTORS - 1));
> - return (pmem->phys_addr >> PAGE_SHIFT) + page_offset;
> -}
> -
> /*
> * sector is not required to be page aligned.
> * n is at most a single page, but could be less.
> @@ -200,14 +190,16 @@ static long pmem_direct_access(struct block_device *bdev, sector_t sector,
> void **kaddr, unsigned long *pfn, long size)
> {
> struct pmem_device *pmem = bdev->bd_disk->private_data;
> + size_t offset = sector << SECTOR_SHIFT;
>
> if (!pmem)
> return -ENODEV;
>
> - *kaddr = pmem_lookup_pg_addr(pmem, sector);
> - *pfn = pmem_lookup_pfn(pmem, sector);
> + BUG_ON(offset >= pmem->size);
No need to add this - bounds checking is done in bdev_direct_access().
> + *kaddr = pmem->virt_addr + offset;
> + *pfn = (pmem->phys_addr + offset) >> PAGE_SHIFT;
>
> - return pmem->size - (sector * 512);
> + return pmem->size - offset;
> }
>
> static const struct block_device_operations pmem_fops = {
^ permalink raw reply [flat|nested] 58+ messages in thread* Re: [PATCH] SQUASHME pmem: Micro optimization for pmem_direct_access
2014-09-10 22:32 ` Ross Zwisler
@ 2014-09-11 11:42 ` Boaz Harrosh
0 siblings, 0 replies; 58+ messages in thread
From: Boaz Harrosh @ 2014-09-11 11:42 UTC (permalink / raw)
To: Ross Zwisler; +Cc: Jens Axboe, Matthew Wilcox, linux-fsdevel, linux-nvdimm
On 09/11/2014 01:32 AM, Ross Zwisler wrote:
> On Wed, 2014-09-10 at 19:50 +0300, Boaz Harrosh wrote:
<>
>> @@ -61,22 +61,12 @@ static int pmem_getgeo(struct block_device *bd, struct hd_geometry *geo)
>> */
>> static void *pmem_lookup_pg_addr(struct pmem_device *pmem, sector_t sector)
>> {
>> - size_t page_offset = sector >> PAGE_SECTORS_SHIFT;
>> - size_t offset = page_offset << PAGE_SHIFT;
>> + size_t offset = sector << SECTOR_SHIFT;
>
> You just broke the "The return value will point to the beginning of the page
> containing the given sector, not to the sector itself." part of the contract
> spelled out in the comments. This means that when you have an I/O that starts
> at a sector that isn't page aligned, copy_to_pmem() or copy_from_pmem() will
> get back a pointer to the *sector*, not the *page*, and the memcopy that takes
> into account the offset will do the wrong thing.
>
Yes! I just saw this in testing. (Which means I did not test right ;-))
Sorry. I'll resend
>> BUG_ON(offset >= pmem->size);
>> return pmem->virt_addr + offset;
>> }
>>
>> -/* sector must be page aligned */
>> -static unsigned long pmem_lookup_pfn(struct pmem_device *pmem, sector_t sector)
>> -{
>> - size_t page_offset = sector >> PAGE_SECTORS_SHIFT;
>> -
>> - BUG_ON(sector & (PAGE_SECTORS - 1));
>> - return (pmem->phys_addr >> PAGE_SHIFT) + page_offset;
>> -}
>> -
>> /*
>> * sector is not required to be page aligned.
>> * n is at most a single page, but could be less.
>> @@ -200,14 +190,16 @@ static long pmem_direct_access(struct block_device *bdev, sector_t sector,
>> void **kaddr, unsigned long *pfn, long size)
>> {
>> struct pmem_device *pmem = bdev->bd_disk->private_data;
>> + size_t offset = sector << SECTOR_SHIFT;
>>
>> if (!pmem)
>> return -ENODEV;
>>
>> - *kaddr = pmem_lookup_pg_addr(pmem, sector);
>> - *pfn = pmem_lookup_pfn(pmem, sector);
>> + BUG_ON(offset >= pmem->size);
>
> No need to add this - bounds checking is done in bdev_direct_access().
>
Right thanks, copy/paste for you
>> + *kaddr = pmem->virt_addr + offset;
>> + *pfn = (pmem->phys_addr + offset) >> PAGE_SHIFT;
>>
>> - return pmem->size - (sector * 512);
>> + return pmem->size - offset;
>> }
>>
>> static const struct block_device_operations pmem_fops = {
>
>
Boaz
^ permalink raw reply [flat|nested] 58+ messages in thread
* [PATCH v2] SQUASHME pmem: Micro optimize the hotpath
2014-09-10 16:50 ` [PATCH] SQUASHME pmem: Micro optimization for pmem_direct_access Boaz Harrosh
2014-09-10 22:32 ` Ross Zwisler
@ 2014-09-14 14:58 ` Boaz Harrosh
2014-09-14 16:02 ` [PATCH] SQUASHME: pmem: no need to copy a page at a time Boaz Harrosh
1 sibling, 1 reply; 58+ messages in thread
From: Boaz Harrosh @ 2014-09-14 14:58 UTC (permalink / raw)
To: Ross Zwisler; +Cc: Jens Axboe, Matthew Wilcox, linux-fsdevel, linux-nvdimm
This is the hotpath I care about - pmem_direct_access()
Please note: This patch spans two patches in the set:
* The changes to pmem_lookup_pg_addr from [patch 1/4]
* The removal to pmem_lookup_pfn and changes to pmem_direct_access
from [patch 4/4]
Easier on the eyes too
Signed-off-by: Boaz Harrosh <boaz@plexistor.com>
---
drivers/block/pmem.c | 19 +++++--------------
1 file changed, 5 insertions(+), 14 deletions(-)
diff --git a/drivers/block/pmem.c b/drivers/block/pmem.c
index 5eda95a..8e15c19 100644
--- a/drivers/block/pmem.c
+++ b/drivers/block/pmem.c
@@ -61,22 +61,12 @@ static int pmem_getgeo(struct block_device *bd, struct hd_geometry *geo)
*/
static void *pmem_lookup_pg_addr(struct pmem_device *pmem, sector_t sector)
{
- size_t page_offset = sector >> PAGE_SECTORS_SHIFT;
- size_t offset = page_offset << PAGE_SHIFT;
+ size_t offset = round_down(sector << SECTOR_SHIFT, PAGE_SIZE);
BUG_ON(offset >= pmem->size);
return pmem->virt_addr + offset;
}
-/* sector must be page aligned */
-static unsigned long pmem_lookup_pfn(struct pmem_device *pmem, sector_t sector)
-{
- size_t page_offset = sector >> PAGE_SECTORS_SHIFT;
-
- BUG_ON(sector & (PAGE_SECTORS - 1));
- return (pmem->phys_addr >> PAGE_SHIFT) + page_offset;
-}
-
/*
* sector is not required to be page aligned.
* n is at most a single page, but could be less.
@@ -200,14 +190,15 @@ static long pmem_direct_access(struct block_device *bdev, sector_t sector,
void **kaddr, unsigned long *pfn, long size)
{
struct pmem_device *pmem = bdev->bd_disk->private_data;
+ size_t offset = sector << SECTOR_SHIFT;
if (!pmem)
return -ENODEV;
- *kaddr = pmem_lookup_pg_addr(pmem, sector);
- *pfn = pmem_lookup_pfn(pmem, sector);
+ *kaddr = pmem->virt_addr + offset;
+ *pfn = (pmem->phys_addr + offset) >> PAGE_SHIFT;
- return pmem->size - (sector * 512);
+ return pmem->size - offset;
}
static const struct block_device_operations pmem_fops = {
--
1.9.3
^ permalink raw reply related [flat|nested] 58+ messages in thread* [PATCH] SQUASHME: pmem: no need to copy a page at a time
2014-09-14 14:58 ` [PATCH v2] SQUASHME pmem: Micro optimize the hotpath Boaz Harrosh
@ 2014-09-14 16:02 ` Boaz Harrosh
2014-09-15 0:23 ` Wilcox, Matthew R
0 siblings, 1 reply; 58+ messages in thread
From: Boaz Harrosh @ 2014-09-14 16:02 UTC (permalink / raw)
To: Ross Zwisler; +Cc: Jens Axboe, Matthew Wilcox, linux-fsdevel, linux-nvdimm
With current code structure a single pmem device always spans
a single contiguous memory range both in the physical as well
as the Kernel virtual space. So this means a contiguous block's
sectors means contiguous virtual addressing.
So we do not need to memcpy a page boundary at a time we can
memcpy any arbitrary memory range.
TODO: Further optimization can be done at callers of
copy_to/from_pmem
Signed-off-by: Boaz Harrosh <boaz@plexistor.com>
---
drivers/block/pmem.c | 37 +++----------------------------------
1 file changed, 3 insertions(+), 34 deletions(-)
diff --git a/drivers/block/pmem.c b/drivers/block/pmem.c
index 8e15c19..780ed94 100644
--- a/drivers/block/pmem.c
+++ b/drivers/block/pmem.c
@@ -56,12 +56,10 @@ static int pmem_getgeo(struct block_device *bd, struct hd_geometry *geo)
/*
* direct translation from (pmem,sector) => void*
* We do not require that sector be page aligned.
- * The return value will point to the beginning of the page containing the
- * given sector, not to the sector itself.
*/
static void *pmem_lookup_pg_addr(struct pmem_device *pmem, sector_t sector)
{
- size_t offset = round_down(sector << SECTOR_SHIFT, PAGE_SIZE);
+ size_t offset = sector << SECTOR_SHIFT;
BUG_ON(offset >= pmem->size);
return pmem->virt_addr + offset;
@@ -69,55 +67,26 @@ static void *pmem_lookup_pg_addr(struct pmem_device *pmem, sector_t sector)
/*
* sector is not required to be page aligned.
- * n is at most a single page, but could be less.
*/
static void copy_to_pmem(struct pmem_device *pmem, const void *src,
sector_t sector, size_t n)
{
void *dst;
- unsigned int offset = (sector & (PAGE_SECTORS - 1)) << SECTOR_SHIFT;
- size_t copy;
-
- BUG_ON(n > PAGE_SIZE);
- copy = min_t(size_t, n, PAGE_SIZE - offset);
dst = pmem_lookup_pg_addr(pmem, sector);
- memcpy(dst + offset, src, copy);
-
- if (copy < n) {
- src += copy;
- sector += copy >> SECTOR_SHIFT;
- copy = n - copy;
- dst = pmem_lookup_pg_addr(pmem, sector);
- memcpy(dst, src, copy);
- }
+ memcpy(dst, src, n);
}
/*
* sector is not required to be page aligned.
- * n is at most a single page, but could be less.
*/
static void copy_from_pmem(void *dst, struct pmem_device *pmem,
sector_t sector, size_t n)
{
void *src;
- unsigned int offset = (sector & (PAGE_SECTORS - 1)) << SECTOR_SHIFT;
- size_t copy;
-
- BUG_ON(n > PAGE_SIZE);
- copy = min_t(size_t, n, PAGE_SIZE - offset);
src = pmem_lookup_pg_addr(pmem, sector);
-
- memcpy(dst, src + offset, copy);
-
- if (copy < n) {
- dst += copy;
- sector += copy >> SECTOR_SHIFT;
- copy = n - copy;
- src = pmem_lookup_pg_addr(pmem, sector);
- memcpy(dst, src, copy);
- }
+ memcpy(dst, src, n);
}
static void pmem_do_bvec(struct pmem_device *pmem, struct page *page,
--
1.9.3
^ permalink raw reply related [flat|nested] 58+ messages in thread* RE: [PATCH] SQUASHME: pmem: no need to copy a page at a time
2014-09-14 16:02 ` [PATCH] SQUASHME: pmem: no need to copy a page at a time Boaz Harrosh
@ 2014-09-15 0:23 ` Wilcox, Matthew R
2014-09-15 8:47 ` Boaz Harrosh
0 siblings, 1 reply; 58+ messages in thread
From: Wilcox, Matthew R @ 2014-09-15 0:23 UTC (permalink / raw)
To: Boaz Harrosh, Ross Zwisler
Cc: Jens Axboe, linux-fsdevel, linux-nvdimm@lists.01.org
Ummpf. No. The current code needs a cond_resched() thrown into that loop, but we can't afford the latency of calling memcpy() for a potentially 2GB+ write. (current CPUs have memory bandwidth somewhere around 20GB/s, iirc, so that would take a tenth of a second; utterly unacceptalbe scheduling latency).
Also, copying to pmem should be using cache-bypassing stores, since there's not going to be any discernible benefit to having this data in cache. Copying from pmem is arguable ... surely it's being read so that it can be used, but on the other hand if we have a 2GB write, we're going to blow away the entire LLC.
________________________________________
From: Boaz Harrosh [boaz@plexistor.com]
Sent: September 14, 2014 9:02 AM
To: Ross Zwisler
Cc: Jens Axboe; Wilcox, Matthew R; linux-fsdevel; linux-nvdimm@lists.01.org
Subject: [PATCH] SQUASHME: pmem: no need to copy a page at a time
With current code structure a single pmem device always spans
a single contiguous memory range both in the physical as well
as the Kernel virtual space. So this means a contiguous block's
sectors means contiguous virtual addressing.
So we do not need to memcpy a page boundary at a time we can
memcpy any arbitrary memory range.
TODO: Further optimization can be done at callers of
copy_to/from_pmem
Signed-off-by: Boaz Harrosh <boaz@plexistor.com>
---
drivers/block/pmem.c | 37 +++----------------------------------
1 file changed, 3 insertions(+), 34 deletions(-)
diff --git a/drivers/block/pmem.c b/drivers/block/pmem.c
index 8e15c19..780ed94 100644
--- a/drivers/block/pmem.c
+++ b/drivers/block/pmem.c
@@ -56,12 +56,10 @@ static int pmem_getgeo(struct block_device *bd, struct hd_geometry *geo)
/*
* direct translation from (pmem,sector) => void*
* We do not require that sector be page aligned.
- * The return value will point to the beginning of the page containing the
- * given sector, not to the sector itself.
*/
static void *pmem_lookup_pg_addr(struct pmem_device *pmem, sector_t sector)
{
- size_t offset = round_down(sector << SECTOR_SHIFT, PAGE_SIZE);
+ size_t offset = sector << SECTOR_SHIFT;
BUG_ON(offset >= pmem->size);
return pmem->virt_addr + offset;
@@ -69,55 +67,26 @@ static void *pmem_lookup_pg_addr(struct pmem_device *pmem, sector_t sector)
/*
* sector is not required to be page aligned.
- * n is at most a single page, but could be less.
*/
static void copy_to_pmem(struct pmem_device *pmem, const void *src,
sector_t sector, size_t n)
{
void *dst;
- unsigned int offset = (sector & (PAGE_SECTORS - 1)) << SECTOR_SHIFT;
- size_t copy;
-
- BUG_ON(n > PAGE_SIZE);
- copy = min_t(size_t, n, PAGE_SIZE - offset);
dst = pmem_lookup_pg_addr(pmem, sector);
- memcpy(dst + offset, src, copy);
-
- if (copy < n) {
- src += copy;
- sector += copy >> SECTOR_SHIFT;
- copy = n - copy;
- dst = pmem_lookup_pg_addr(pmem, sector);
- memcpy(dst, src, copy);
- }
+ memcpy(dst, src, n);
}
/*
* sector is not required to be page aligned.
- * n is at most a single page, but could be less.
*/
static void copy_from_pmem(void *dst, struct pmem_device *pmem,
sector_t sector, size_t n)
{
void *src;
- unsigned int offset = (sector & (PAGE_SECTORS - 1)) << SECTOR_SHIFT;
- size_t copy;
-
- BUG_ON(n > PAGE_SIZE);
- copy = min_t(size_t, n, PAGE_SIZE - offset);
src = pmem_lookup_pg_addr(pmem, sector);
-
- memcpy(dst, src + offset, copy);
-
- if (copy < n) {
- dst += copy;
- sector += copy >> SECTOR_SHIFT;
- copy = n - copy;
- src = pmem_lookup_pg_addr(pmem, sector);
- memcpy(dst, src, copy);
- }
+ memcpy(dst, src, n);
}
static void pmem_do_bvec(struct pmem_device *pmem, struct page *page,
--
1.9.3
^ permalink raw reply related [flat|nested] 58+ messages in thread* Re: [PATCH] SQUASHME: pmem: no need to copy a page at a time
2014-09-15 0:23 ` Wilcox, Matthew R
@ 2014-09-15 8:47 ` Boaz Harrosh
0 siblings, 0 replies; 58+ messages in thread
From: Boaz Harrosh @ 2014-09-15 8:47 UTC (permalink / raw)
To: Wilcox, Matthew R, Boaz Harrosh, Ross Zwisler
Cc: Jens Axboe, linux-fsdevel, linux-nvdimm@lists.01.org
No this can only be PAGE_SIZE at the time because it comes from a bio
page. It might split because that user-page may not be aligned to
a disk 4k. So the original code copy/pasted from brd had this
split since each brd-page is random.
But with pmem we do not need the split it is mute. Please read the all
code.
About write-with-cache-though. It is your call. FS/APP will need to
do fsync in which case we can implement flush. But I think
write-with-cache-though might be more efficient with most ARCHs.
Your call please send a patch
Thanks
Boaz
On 09/15/2014 03:23 AM, Wilcox, Matthew R wrote:
> Ummpf. No. The current code needs a cond_resched() thrown into that
> loop, but we can't afford the latency of calling memcpy() for a
> potentially 2GB+ write. (current CPUs have memory bandwidth somewhere
> around 20GB/s, iirc, so that would take a tenth of a second; utterly
> unacceptalbe scheduling latency).
>
> Also, copying to pmem should be using cache-bypassing stores, since
> there's not going to be any discernible benefit to having this data
> in cache. Copying from pmem is arguable ... surely it's being read so
> that it can be used, but on the other hand if we have a 2GB write,
> we're going to blow away the entire LLC.>
> ________________________________________
> From: Boaz Harrosh [boaz@plexistor.com]
> Sent: September 14, 2014 9:02 AM
> To: Ross Zwisler
> Cc: Jens Axboe; Wilcox, Matthew R; linux-fsdevel; linux-nvdimm@lists.01.org
> Subject: [PATCH] SQUASHME: pmem: no need to copy a page at a time
>
> With current code structure a single pmem device always spans
> a single contiguous memory range both in the physical as well
> as the Kernel virtual space. So this means a contiguous block's
> sectors means contiguous virtual addressing.
>
> So we do not need to memcpy a page boundary at a time we can
> memcpy any arbitrary memory range.
>
> TODO: Further optimization can be done at callers of
> copy_to/from_pmem
>
> Signed-off-by: Boaz Harrosh <boaz@plexistor.com>
> ---
> drivers/block/pmem.c | 37 +++----------------------------------
> 1 file changed, 3 insertions(+), 34 deletions(-)
>
> diff --git a/drivers/block/pmem.c b/drivers/block/pmem.c
> index 8e15c19..780ed94 100644
> --- a/drivers/block/pmem.c
> +++ b/drivers/block/pmem.c
> @@ -56,12 +56,10 @@ static int pmem_getgeo(struct block_device *bd, struct hd_geometry *geo)
> /*
> * direct translation from (pmem,sector) => void*
> * We do not require that sector be page aligned.
> - * The return value will point to the beginning of the page containing the
> - * given sector, not to the sector itself.
> */
> static void *pmem_lookup_pg_addr(struct pmem_device *pmem, sector_t sector)
> {
> - size_t offset = round_down(sector << SECTOR_SHIFT, PAGE_SIZE);
> + size_t offset = sector << SECTOR_SHIFT;
>
> BUG_ON(offset >= pmem->size);
> return pmem->virt_addr + offset;
> @@ -69,55 +67,26 @@ static void *pmem_lookup_pg_addr(struct pmem_device *pmem, sector_t sector)
>
> /*
> * sector is not required to be page aligned.
> - * n is at most a single page, but could be less.
> */
> static void copy_to_pmem(struct pmem_device *pmem, const void *src,
> sector_t sector, size_t n)
> {
> void *dst;
> - unsigned int offset = (sector & (PAGE_SECTORS - 1)) << SECTOR_SHIFT;
> - size_t copy;
> -
> - BUG_ON(n > PAGE_SIZE);
>
> - copy = min_t(size_t, n, PAGE_SIZE - offset);
> dst = pmem_lookup_pg_addr(pmem, sector);
> - memcpy(dst + offset, src, copy);
> -
> - if (copy < n) {
> - src += copy;
> - sector += copy >> SECTOR_SHIFT;
> - copy = n - copy;
> - dst = pmem_lookup_pg_addr(pmem, sector);
> - memcpy(dst, src, copy);
> - }
> + memcpy(dst, src, n);
> }
>
> /*
> * sector is not required to be page aligned.
> - * n is at most a single page, but could be less.
> */
> static void copy_from_pmem(void *dst, struct pmem_device *pmem,
> sector_t sector, size_t n)
> {
> void *src;
> - unsigned int offset = (sector & (PAGE_SECTORS - 1)) << SECTOR_SHIFT;
> - size_t copy;
> -
> - BUG_ON(n > PAGE_SIZE);
>
> - copy = min_t(size_t, n, PAGE_SIZE - offset);
> src = pmem_lookup_pg_addr(pmem, sector);
> -
> - memcpy(dst, src + offset, copy);
> -
> - if (copy < n) {
> - dst += copy;
> - sector += copy >> SECTOR_SHIFT;
> - copy = n - copy;
> - src = pmem_lookup_pg_addr(pmem, sector);
> - memcpy(dst, src, copy);
> - }
> + memcpy(dst, src, n);
> }
>
> static void pmem_do_bvec(struct pmem_device *pmem, struct page *page,
> --
> 1.9.3
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply [flat|nested] 58+ messages in thread
* [PATCH] SQUASHME: pmem: Add MODULE_ALIAS
2014-09-09 15:37 ` [PATCH 0/9] pmem: Fixes and farther development (mm: add_persistent_memory) Boaz Harrosh
` (9 preceding siblings ...)
2014-09-10 16:50 ` [PATCH] SQUASHME pmem: Micro optimization for pmem_direct_access Boaz Harrosh
@ 2014-09-10 17:50 ` Boaz Harrosh
2014-09-10 19:22 ` Ross Zwisler
10 siblings, 1 reply; 58+ messages in thread
From: Boaz Harrosh @ 2014-09-10 17:50 UTC (permalink / raw)
To: Boaz Harrosh, Ross Zwisler, Jens Axboe, Matthew Wilcox,
linux-fsdevel, linux-nvdimm
From: Boaz Harrosh <boaz@plexistor.com>
This is customary and will become useful soon with udev and events
Signed-off-by: Boaz Harrosh <boaz@plexistor.com>
---
drivers/block/pmem.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/block/pmem.c b/drivers/block/pmem.c
index 4a9d65e..f63cb31 100644
--- a/drivers/block/pmem.c
+++ b/drivers/block/pmem.c
@@ -432,5 +430,6 @@ static void __exit pmem_exit(void)
MODULE_AUTHOR("Ross Zwisler <ross.zwisler@linux.intel.com>");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("pmem");
module_init(pmem_init);
module_exit(pmem_exit);
--
1.9.3
^ permalink raw reply related [flat|nested] 58+ messages in thread* Re: [PATCH] SQUASHME: pmem: Add MODULE_ALIAS
2014-09-10 17:50 ` [PATCH] SQUASHME: pmem: Add MODULE_ALIAS Boaz Harrosh
@ 2014-09-10 19:22 ` Ross Zwisler
2014-09-11 11:44 ` Boaz Harrosh
0 siblings, 1 reply; 58+ messages in thread
From: Ross Zwisler @ 2014-09-10 19:22 UTC (permalink / raw)
To: Boaz Harrosh; +Cc: Jens Axboe, Matthew Wilcox, linux-fsdevel, linux-nvdimm
On Wed, 2014-09-10 at 20:50 +0300, Boaz Harrosh wrote:
> From: Boaz Harrosh <boaz@plexistor.com>
>
> This is customary and will become useful soon with udev and events
>
> Signed-off-by: Boaz Harrosh <boaz@plexistor.com>
> ---
> drivers/block/pmem.c | 3 +--
> 1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/drivers/block/pmem.c b/drivers/block/pmem.c
> index 4a9d65e..f63cb31 100644
> --- a/drivers/block/pmem.c
> +++ b/drivers/block/pmem.c
> @@ -432,5 +430,6 @@ static void __exit pmem_exit(void)
>
> MODULE_AUTHOR("Ross Zwisler <ross.zwisler@linux.intel.com>");
> MODULE_LICENSE("GPL");
> +MODULE_ALIAS("pmem");
> module_init(pmem_init);
> module_exit(pmem_exit);
Umm...but the module is *already* named pmem?
Let's not set up an alias that is the same as our real name for code that
isn't written yet?
- Ross
^ permalink raw reply [flat|nested] 58+ messages in thread