[linux-nvdimm:libnvdimm-fixes 2/3] drivers/dax/super.c:31:5: error:
redefinition of 'dax_read_lock'
by kernel test robot
tree: https://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm.git libnvdimm-fixes
head: 5ca46d3ef704a0d0ddd79a7dfa164a6a5b6ccef2
commit: 5ba388db58497496fbeb952c9454e8e6e59584ac [2/3] dm: Call proper helper to determine dax support
config: m68k-hp300_defconfig (attached as .config)
compiler: m68k-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
git checkout 5ba388db58497496fbeb952c9454e8e6e59584ac
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=m68k
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp(a)intel.com>
All errors (new ones prefixed by >>):
In file included from arch/m68k/include/asm/page.h:60,
from arch/m68k/include/asm/thread_info.h:6,
from include/linux/thread_info.h:38,
from include/asm-generic/preempt.h:5,
from ./arch/m68k/include/generated/asm/preempt.h:1,
from include/linux/preempt.h:78,
from include/linux/spinlock.h:51,
from include/linux/mmzone.h:8,
from include/linux/gfp.h:6,
from include/linux/mm.h:10,
from include/linux/pagemap.h:8,
from drivers/dax/super.c:5:
include/linux/pfn_t.h: In function 'pfn_t_valid':
arch/m68k/include/asm/page_mm.h:169:49: warning: ordered comparison of pointer with null pointer [-Wextra]
169 | #define virt_addr_valid(kaddr) ((void *)(kaddr) >= (void *)PAGE_OFFSET && (void *)(kaddr) < high_memory)
| ^~
arch/m68k/include/asm/page_mm.h:170:25: note: in expansion of macro 'virt_addr_valid'
170 | #define pfn_valid(pfn) virt_addr_valid(pfn_to_virt(pfn))
| ^~~~~~~~~~~~~~~
include/linux/pfn_t.h:76:9: note: in expansion of macro 'pfn_valid'
76 | return pfn_valid(pfn_t_to_pfn(pfn));
| ^~~~~~~~~
drivers/dax/super.c: At top level:
>> drivers/dax/super.c:31:5: error: redefinition of 'dax_read_lock'
31 | int dax_read_lock(void)
| ^~~~~~~~~~~~~
In file included from drivers/dax/super.c:16:
include/linux/dax.h:205:19: note: previous definition of 'dax_read_lock' was here
205 | static inline int dax_read_lock(void)
| ^~~~~~~~~~~~~
>> drivers/dax/super.c:37:6: error: redefinition of 'dax_read_unlock'
37 | void dax_read_unlock(int id)
| ^~~~~~~~~~~~~~~
In file included from drivers/dax/super.c:16:
include/linux/dax.h:210:20: note: previous definition of 'dax_read_unlock' was here
210 | static inline void dax_read_unlock(int id)
| ^~~~~~~~~~~~~~~
drivers/dax/super.c:69:6: warning: no previous prototype for '__generic_fsdax_supported' [-Wmissing-prototypes]
69 | bool __generic_fsdax_supported(struct dax_device *dax_dev,
| ^~~~~~~~~~~~~~~~~~~~~~~~~
drivers/dax/super.c:167:6: warning: no previous prototype for '__bdev_dax_supported' [-Wmissing-prototypes]
167 | bool __bdev_dax_supported(struct block_device *bdev, int blocksize)
| ^~~~~~~~~~~~~~~~~~~~
>> drivers/dax/super.c:325:6: error: redefinition of 'dax_supported'
325 | bool dax_supported(struct dax_device *dax_dev, struct block_device *bdev,
| ^~~~~~~~~~~~~
In file included from drivers/dax/super.c:16:
include/linux/dax.h:162:20: note: previous definition of 'dax_supported' was here
162 | static inline bool dax_supported(struct dax_device *dax_dev,
| ^~~~~~~~~~~~~
drivers/dax/super.c:451:6: warning: no previous prototype for 'run_dax' [-Wmissing-prototypes]
451 | void run_dax(struct dax_device *dax_dev)
| ^~~~~~~
# https://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm.git/commit/...
git remote add linux-nvdimm https://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm.git
git fetch --no-tags linux-nvdimm libnvdimm-fixes
git checkout 5ba388db58497496fbeb952c9454e8e6e59584ac
vim +/dax_read_lock +31 drivers/dax/super.c
72058005411ffd Dan Williams 2017-04-19 30
7b6be8444e0f0d Dan Williams 2017-04-11 @31 int dax_read_lock(void)
7b6be8444e0f0d Dan Williams 2017-04-11 32 {
7b6be8444e0f0d Dan Williams 2017-04-11 33 return srcu_read_lock(&dax_srcu);
7b6be8444e0f0d Dan Williams 2017-04-11 34 }
7b6be8444e0f0d Dan Williams 2017-04-11 35 EXPORT_SYMBOL_GPL(dax_read_lock);
7b6be8444e0f0d Dan Williams 2017-04-11 36
7b6be8444e0f0d Dan Williams 2017-04-11 @37 void dax_read_unlock(int id)
7b6be8444e0f0d Dan Williams 2017-04-11 38 {
7b6be8444e0f0d Dan Williams 2017-04-11 39 srcu_read_unlock(&dax_srcu, id);
7b6be8444e0f0d Dan Williams 2017-04-11 40 }
7b6be8444e0f0d Dan Williams 2017-04-11 41 EXPORT_SYMBOL_GPL(dax_read_unlock);
7b6be8444e0f0d Dan Williams 2017-04-11 42
:::::: The code at line 31 was first introduced by commit
:::::: 7b6be8444e0f0dd675b54d059793423d3c9b4c03 dax: refactor dax-fs into a generic provider of 'struct dax_device' instances
:::::: TO: Dan Williams <dan.j.williams(a)intel.com>
:::::: CC: Dan Williams <dan.j.williams(a)intel.com>
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
1 year, 9 months
[PATCH v2 1/1] libnvdimm: slightly simplify available_slots_show()
by Zhen Lei
The type of "nfree" is u32, so "nfree - 1" can only be overflowed when
"nfree" is zero. Replace "if (nfree - 1 > nfree)" with "if (nfree == 0)"
seems more clear. And remove the assignment "nfree = 0", no need for it.
Signed-off-by: Zhen Lei <thunder.leizhen(a)huawei.com>
---
v1 --> v2:
No change, just sent separately
v1:
https://lkml.org/lkml/2020/8/19/1465
drivers/nvdimm/dimm_devs.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c
index b59032e0859b7f3..d6835f127d83055 100644
--- a/drivers/nvdimm/dimm_devs.c
+++ b/drivers/nvdimm/dimm_devs.c
@@ -347,10 +347,9 @@ static ssize_t available_slots_show(struct device *dev,
nvdimm_bus_lock(dev);
nfree = nd_label_nfree(ndd);
- if (nfree - 1 > nfree) {
+ if (nfree == 0)
dev_WARN_ONCE(dev, 1, "we ate our last label?\n");
- nfree = 0;
- } else
+ else
nfree--;
rc = sprintf(buf, "%d\n", nfree);
nvdimm_bus_unlock(dev);
--
1.8.3
1 year, 9 months
[PATCH v2 1/1] libnvdimm: make sure EXPORT_SYMBOL_GPL(nvdimm_flush) close to its function
by Zhen Lei
Move EXPORT_SYMBOL_GPL(nvdimm_flush) close to nvdimm_flush(), currently
it's near to generic_nvdimm_flush().
Signed-off-by: Zhen Lei <thunder.leizhen(a)huawei.com>
Reviewed-by: Pankaj Gupta <pankaj.gupta.linux(a)gmail.com>
---
v1 --> v2
1. add "Reviewed-by: Pankaj Gupta <pankaj.gupta.linux(a)gmail.com>"
v1:
https://lkml.org/lkml/2020/8/20/904
drivers/nvdimm/region_devs.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
index 7cf9c7d857909ce..5df7c22df1529eb 100644
--- a/drivers/nvdimm/region_devs.c
+++ b/drivers/nvdimm/region_devs.c
@@ -1186,6 +1186,8 @@ int nvdimm_flush(struct nd_region *nd_region, struct bio *bio)
return rc;
}
+EXPORT_SYMBOL_GPL(nvdimm_flush);
+
/**
* nvdimm_flush - flush any posted write queues between the cpu and pmem media
* @nd_region: blk or interleaved pmem region
@@ -1217,7 +1219,6 @@ int generic_nvdimm_flush(struct nd_region *nd_region)
return 0;
}
-EXPORT_SYMBOL_GPL(nvdimm_flush);
/**
* nvdimm_has_flush - determine write flushing requirements
--
1.8.3
1 year, 9 months
[PATCH v2 1/1] libnvdimm/region: delete a piece of useless code in nd_region_create()
by Zhen Lei
The code snippet is as follows:
if (ndr_desc->flush)
1) nd_region->flush = ndr_desc->flush;
else
2) nd_region->flush = NULL;
When entering the "else" branch, the value of ndr_desc->flush is NULL.
After replaced "NULL" with "ndr_desc->flush" at 2), we will find that
it becomes the same to 1).
So the above code snippet can be reduced to one statement:
nd_region->flush = ndr_desc->flush;
No functional change.
Signed-off-by: Zhen Lei <thunder.leizhen(a)huawei.com>
---
v1 --> v2:
1. Only the title and description are modified.
v1:
https://lkml.org/lkml/2020/8/19/1469
drivers/nvdimm/region_devs.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
index ef23119db574663..7cf9c7d857909ce 100644
--- a/drivers/nvdimm/region_devs.c
+++ b/drivers/nvdimm/region_devs.c
@@ -1131,10 +1131,7 @@ static struct nd_region *nd_region_create(struct nvdimm_bus *nvdimm_bus,
nd_region->ndr_size = resource_size(ndr_desc->res);
nd_region->ndr_start = ndr_desc->res->start;
nd_region->align = default_align(nd_region);
- if (ndr_desc->flush)
- nd_region->flush = ndr_desc->flush;
- else
- nd_region->flush = NULL;
+ nd_region->flush = ndr_desc->flush;
nd_device_register(dev);
--
1.8.3
1 year, 9 months
[PATCH v2 1/1] libnvdimm/namespace: avoid repeated judgment in nvdimm_namespace_disk_name()
by Zhen Lei
The judgment (suffix ? suffix : "") appears three times, we do this just
because the initial value of local variable "suffix" is NULL, should be
replaced with empty string "" to avoid null pointer reference. It's easy
to get rid of it as below:
- const char *suffix = NULL;
+ const char *suffix = "";
To avoid having rows that exceed 80 columns, add a new local variable
"region_id".
No functional change, but it can reduce the code size.
Before:
text data bss dec hex filename
41749 3697 16 45462 b196 drivers/nvdimm/namespace_devs.o
After:
text data bss dec hex filename
41653 3697 16 45366 b136 drivers/nvdimm/namespace_devs.o
Signed-off-by: Zhen Lei <thunder.leizhen(a)huawei.com>
---
v1 --> v2:
1. Only the title and description are modified.
v1:
https://lore.kernel.org/patchwork/patch/1292584/
drivers/nvdimm/namespace_devs.c | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c
index 6da67f4d641a27c..ef2800c5da4c99c 100644
--- a/drivers/nvdimm/namespace_devs.c
+++ b/drivers/nvdimm/namespace_devs.c
@@ -157,7 +157,8 @@ const char *nvdimm_namespace_disk_name(struct nd_namespace_common *ndns,
char *name)
{
struct nd_region *nd_region = to_nd_region(ndns->dev.parent);
- const char *suffix = NULL;
+ const char *suffix = "";
+ int region_id = nd_region->id;
if (ndns->claim && is_nd_btt(ndns->claim))
suffix = "s";
@@ -173,17 +174,14 @@ const char *nvdimm_namespace_disk_name(struct nd_namespace_common *ndns,
}
if (nsidx)
- sprintf(name, "pmem%d.%d%s", nd_region->id, nsidx,
- suffix ? suffix : "");
+ sprintf(name, "pmem%d.%d%s", region_id, nsidx, suffix);
else
- sprintf(name, "pmem%d%s", nd_region->id,
- suffix ? suffix : "");
+ sprintf(name, "pmem%d%s", region_id, suffix);
} else if (is_namespace_blk(&ndns->dev)) {
struct nd_namespace_blk *nsblk;
nsblk = to_nd_namespace_blk(&ndns->dev);
- sprintf(name, "ndblk%d.%d%s", nd_region->id, nsblk->id,
- suffix ? suffix : "");
+ sprintf(name, "ndblk%d.%d%s", region_id, nsblk->id, suffix);
} else {
return NULL;
}
--
1.8.3
1 year, 9 months
[PATCH v2 1/1] libnvdimm/namespace: avoid repeated judgment in nvdimm_namespace_disk_name()
by Zhen Lei
The judgment (suffix ? suffix : "") appears three times, we do this just
because the initial value of local variable "suffix" is NULL, should be
replaced with empty string "" to avoid null pointer reference. It's easy
to get rid of it as below:
- const char *suffix = NULL;
+ const char *suffix = "";
To avoid having rows that exceed 80 columns, add a new local variable
"region_id".
No functional change, but it can reduce the code size.
Before:
text data bss dec hex filename
41749 3697 16 45462 b196 drivers/nvdimm/namespace_devs.o
After:
text data bss dec hex filename
41653 3697 16 45366 b136 drivers/nvdimm/namespace_devs.o
Signed-off-by: Zhen Lei <thunder.leizhen(a)huawei.com>
---
v1 --> v2:
1. Only the title and description are modified.
v1:
https://lore.kernel.org/patchwork/patch/1292584/
drivers/nvdimm/namespace_devs.c | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c
index 6da67f4d641a27c..ef2800c5da4c99c 100644
--- a/drivers/nvdimm/namespace_devs.c
+++ b/drivers/nvdimm/namespace_devs.c
@@ -157,7 +157,8 @@ const char *nvdimm_namespace_disk_name(struct nd_namespace_common *ndns,
char *name)
{
struct nd_region *nd_region = to_nd_region(ndns->dev.parent);
- const char *suffix = NULL;
+ const char *suffix = "";
+ int region_id = nd_region->id;
if (ndns->claim && is_nd_btt(ndns->claim))
suffix = "s";
@@ -173,17 +174,14 @@ const char *nvdimm_namespace_disk_name(struct nd_namespace_common *ndns,
}
if (nsidx)
- sprintf(name, "pmem%d.%d%s", nd_region->id, nsidx,
- suffix ? suffix : "");
+ sprintf(name, "pmem%d.%d%s", region_id, nsidx, suffix);
else
- sprintf(name, "pmem%d%s", nd_region->id,
- suffix ? suffix : "");
+ sprintf(name, "pmem%d%s", region_id, suffix);
} else if (is_namespace_blk(&ndns->dev)) {
struct nd_namespace_blk *nsblk;
nsblk = to_nd_namespace_blk(&ndns->dev);
- sprintf(name, "ndblk%d.%d%s", nd_region->id, nsblk->id,
- suffix ? suffix : "");
+ sprintf(name, "ndblk%d.%d%s", region_id, nsblk->id, suffix);
} else {
return NULL;
}
--
1.8.3
1 year, 9 months
[PATCH] dm/dax: Fix table reference counts
by Dan Williams
A recent fix to the dm_dax_supported() flow uncovered a latent bug. When
dm_get_live_table() fails it is still required to drop the
srcu_read_lock(). Without this change the lvm2 test-suite triggers this
warning:
# lvm2-testsuite --only pvmove-abort-all.sh
WARNING: lock held when returning to user space!
5.9.0-rc5+ #251 Tainted: G OE
------------------------------------------------
lvm/1318 is leaving the kernel with locks still held!
1 lock held by lvm/1318:
#0: ffff9372abb5a340 (&md->io_barrier){....}-{0:0}, at: dm_get_live_table+0x5/0xb0 [dm_mod]
...and later on this hang signature:
INFO: task lvm:1344 blocked for more than 122 seconds.
Tainted: G OE 5.9.0-rc5+ #251
"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
task:lvm state:D stack: 0 pid: 1344 ppid: 1 flags:0x00004000
Call Trace:
__schedule+0x45f/0xa80
? finish_task_switch+0x249/0x2c0
? wait_for_completion+0x86/0x110
schedule+0x5f/0xd0
schedule_timeout+0x212/0x2a0
? __schedule+0x467/0xa80
? wait_for_completion+0x86/0x110
wait_for_completion+0xb0/0x110
__synchronize_srcu+0xd1/0x160
? __bpf_trace_rcu_utilization+0x10/0x10
__dm_suspend+0x6d/0x210 [dm_mod]
dm_suspend+0xf6/0x140 [dm_mod]
Fixes: 7bf7eac8d648 ("dax: Arrange for dax_supported check to span multiple devices")
Cc: <stable(a)vger.kernel.org>
Cc: Jan Kara <jack(a)suse.cz>
Cc: Alasdair Kergon <agk(a)redhat.com>
Cc: Mike Snitzer <snitzer(a)redhat.com>
Reported-by: Adrian Huang <ahuang12(a)lenovo.com>
Signed-off-by: Dan Williams <dan.j.williams(a)intel.com>
---
drivers/md/dm.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index fb0255d25e4b..4a40df8af7d3 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -1136,15 +1136,16 @@ static bool dm_dax_supported(struct dax_device *dax_dev, struct block_device *bd
{
struct mapped_device *md = dax_get_private(dax_dev);
struct dm_table *map;
+ bool ret = false;
int srcu_idx;
- bool ret;
map = dm_get_live_table(md, &srcu_idx);
if (!map)
- return false;
+ goto out;
ret = dm_table_supports_dax(map, device_supports_dax, &blocksize);
+out:
dm_put_live_table(md, srcu_idx);
return ret;
1 year, 9 months
[PATCH v3] dm: Call proper helper to determine dax support
by Dan Williams
From: Jan Kara <jack(a)suse.cz>
DM was calling generic_fsdax_supported() to determine whether a device
referenced in the DM table supports DAX. However this is a helper for "leaf" device drivers so that
they don't have to duplicate common generic checks. High level code
should call dax_supported() helper which that calls into appropriate
helper for the particular device. This problem manifested itself as
kernel messages:
dm-3: error: dax access failed (-95)
when lvm2-testsuite run in cases where a DM device was stacked on top of
another DM device.
Fixes: 7bf7eac8d648 ("dax: Arrange for dax_supported check to span multiple devices")
Cc: <stable(a)vger.kernel.org>
Tested-by: Adrian Huang <ahuang12(a)lenovo.com>
Signed-off-by: Jan Kara <jack(a)suse.cz>
Acked-by: Mike Snitzer <snitzer(a)redhat.com>
Reported-by: kernel test robot <lkp(a)intel.com>
Signed-off-by: Dan Williams <dan.j.williams(a)intel.com>
---
Changes since v2 [1]:
- Add dummy definitions for dax_read_{lock,unlock} in the CONFIG_DAX=n
case (0day robot)
[1]: http://lore.kernel.org/r/160040692945.25320.13233625491405115889.stgit@dw...
drivers/dax/super.c | 4 ++++
drivers/md/dm-table.c | 10 +++++++---
include/linux/dax.h | 22 ++++++++++++++++++++--
3 files changed, 31 insertions(+), 5 deletions(-)
diff --git a/drivers/dax/super.c b/drivers/dax/super.c
index e5767c83ea23..b6284c5cae0a 100644
--- a/drivers/dax/super.c
+++ b/drivers/dax/super.c
@@ -325,11 +325,15 @@ EXPORT_SYMBOL_GPL(dax_direct_access);
bool dax_supported(struct dax_device *dax_dev, struct block_device *bdev,
int blocksize, sector_t start, sector_t len)
{
+ if (!dax_dev)
+ return false;
+
if (!dax_alive(dax_dev))
return false;
return dax_dev->ops->dax_supported(dax_dev, bdev, blocksize, start, len);
}
+EXPORT_SYMBOL_GPL(dax_supported);
size_t dax_copy_from_iter(struct dax_device *dax_dev, pgoff_t pgoff, void *addr,
size_t bytes, struct iov_iter *i)
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 5edc3079e7c1..229f461e7def 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -860,10 +860,14 @@ EXPORT_SYMBOL_GPL(dm_table_set_type);
int device_supports_dax(struct dm_target *ti, struct dm_dev *dev,
sector_t start, sector_t len, void *data)
{
- int blocksize = *(int *) data;
+ int blocksize = *(int *) data, id;
+ bool rc;
- return generic_fsdax_supported(dev->dax_dev, dev->bdev, blocksize,
- start, len);
+ id = dax_read_lock();
+ rc = dax_supported(dev->dax_dev, dev->bdev, blocksize, start, len);
+ dax_read_unlock(id);
+
+ return rc;
}
/* Check devices support synchronous DAX */
diff --git a/include/linux/dax.h b/include/linux/dax.h
index 6904d4e0b2e0..d0af16b23122 100644
--- a/include/linux/dax.h
+++ b/include/linux/dax.h
@@ -130,6 +130,8 @@ static inline bool generic_fsdax_supported(struct dax_device *dax_dev,
return __generic_fsdax_supported(dax_dev, bdev, blocksize, start,
sectors);
}
+bool dax_supported(struct dax_device *dax_dev, struct block_device *bdev,
+ int blocksize, sector_t start, sector_t len);
static inline void fs_put_dax(struct dax_device *dax_dev)
{
@@ -157,6 +159,13 @@ static inline bool generic_fsdax_supported(struct dax_device *dax_dev,
return false;
}
+static inline bool dax_supported(struct dax_device *dax_dev,
+ struct block_device *bdev, int blocksize, sector_t start,
+ sector_t len)
+{
+ return false;
+}
+
static inline void fs_put_dax(struct dax_device *dax_dev)
{
}
@@ -189,14 +198,23 @@ static inline void dax_unlock_page(struct page *page, dax_entry_t cookie)
}
#endif
+#ifdef CONFIG_DAX
int dax_read_lock(void);
void dax_read_unlock(int id);
+#else
+static inline int dax_read_lock(void)
+{
+ return 0;
+}
+
+static inline void dax_read_unlock(int id)
+{
+}
+#endif /* CONFIG_DAX */
bool dax_alive(struct dax_device *dax_dev);
void *dax_get_private(struct dax_device *dax_dev);
long dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, long nr_pages,
void **kaddr, pfn_t *pfn);
-bool dax_supported(struct dax_device *dax_dev, struct block_device *bdev,
- int blocksize, sector_t start, sector_t len);
size_t dax_copy_from_iter(struct dax_device *dax_dev, pgoff_t pgoff, void *addr,
size_t bytes, struct iov_iter *i);
size_t dax_copy_to_iter(struct dax_device *dax_dev, pgoff_t pgoff, void *addr,
1 year, 9 months