Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1497528 > unrolled thread
| Started by | Ross Zwisler <ross.zwisler@linux.intel.com> |
|---|---|
| First post | 2016-10-07 23:10 +0200 |
| Last post | 2016-10-12 09:50 +0200 |
| Articles | 20 on this page of 39 — 4 participants |
Back to article view | Back to linux.kernel
[PATCH v5 00/17] re-enable DAX PMD support Ross Zwisler <ross.zwisler@linux.intel.com> - 2016-10-07 23:10 +0200
[PATCH v5 07/17] dax: remove the last BUG_ON() from fs/dax.c Ross Zwisler <ross.zwisler@linux.intel.com> - 2016-10-07 23:10 +0200
Re: [PATCH v5 07/17] dax: remove the last BUG_ON() from fs/dax.c Jan Kara <jack@suse.cz> - 2016-10-11 21:00 +0200
[PATCH v5 04/17] ext2: remove support for DAX PMD faults Ross Zwisler <ross.zwisler@linux.intel.com> - 2016-10-07 23:20 +0200
[PATCH v5 01/17] ext4: allow DAX writeback for hole punch Ross Zwisler <ross.zwisler@linux.intel.com> - 2016-10-07 23:20 +0200
[PATCH v5 12/17] dax: add dax_iomap_sector() helper function Ross Zwisler <ross.zwisler@linux.intel.com> - 2016-10-07 23:20 +0200
Re: [PATCH v5 12/17] dax: add dax_iomap_sector() helper function Christoph Hellwig <hch@lst.de> - 2016-10-10 17:50 +0200
Re: [PATCH v5 12/17] dax: add dax_iomap_sector() helper function Jan Kara <jack@suse.cz> - 2016-10-11 20:50 +0200
[PATCH v5 13/17] dax: dax_iomap_fault() needs to call iomap_end() Ross Zwisler <ross.zwisler@linux.intel.com> - 2016-10-07 23:20 +0200
Re: [PATCH v5 13/17] dax: dax_iomap_fault() needs to call iomap_end() Christoph Hellwig <hch@lst.de> - 2016-10-10 18:00 +0200
Re: [PATCH v5 13/17] dax: dax_iomap_fault() needs to call iomap_end() Ross Zwisler <ross.zwisler@linux.intel.com> - 2016-10-11 00:10 +0200
Re: [PATCH v5 13/17] dax: dax_iomap_fault() needs to call iomap_end() Jan Kara <jack@suse.cz> - 2016-10-11 20:50 +0200
[PATCH v5 16/17] xfs: use struct iomap based DAX PMD fault path Ross Zwisler <ross.zwisler@linux.intel.com> - 2016-10-07 23:20 +0200
Re: [PATCH v5 16/17] xfs: use struct iomap based DAX PMD fault path Jan Kara <jack@suse.cz> - 2016-10-11 20:50 +0200
[PATCH v5 08/17] dax: consistent variable naming for DAX entries Ross Zwisler <ross.zwisler@linux.intel.com> - 2016-10-07 23:20 +0200
[PATCH v5 05/17] ext2: return -EIO on ext2_iomap_end() failure Ross Zwisler <ross.zwisler@linux.intel.com> - 2016-10-07 23:20 +0200
Re: [PATCH v5 05/17] ext2: return -EIO on ext2_iomap_end() failure Jan Kara <jack@suse.cz> - 2016-10-11 21:00 +0200
[PATCH v5 03/17] dax: remove buffer_size_valid() Ross Zwisler <ross.zwisler@linux.intel.com> - 2016-10-07 23:20 +0200
[PATCH v5 09/17] dax: coordinate locking for offsets in PMD range Ross Zwisler <ross.zwisler@linux.intel.com> - 2016-10-07 23:20 +0200
Re: [PATCH v5 09/17] dax: coordinate locking for offsets in PMD range Christoph Hellwig <hch@lst.de> - 2016-10-10 17:50 +0200
Re: [PATCH v5 09/17] dax: coordinate locking for offsets in PMD range Jan Kara <jack@suse.cz> - 2016-10-11 20:50 +0200
Re: [PATCH v5 09/17] dax: coordinate locking for offsets in PMD range Ross Zwisler <ross.zwisler@linux.intel.com> - 2016-10-11 23:20 +0200
[PATCH v5 02/17] ext4: tell DAX the size of allocation holes Ross Zwisler <ross.zwisler@linux.intel.com> - 2016-10-07 23:20 +0200
[PATCH v5 11/17] dax: correct dax iomap code namespace Ross Zwisler <ross.zwisler@linux.intel.com> - 2016-10-07 23:20 +0200
Re: [PATCH v5 11/17] dax: correct dax iomap code namespace Christoph Hellwig <hch@lst.de> - 2016-10-09 17:30 +0200
[PATCH] dax: correct dax iomap code namespace Ross Zwisler <ross.zwisler@linux.intel.com> - 2016-10-10 21:10 +0200
Re: [PATCH] dax: correct dax iomap code namespace Dave Chinner <david@fromorbit.com> - 2016-10-10 22:50 +0200
[PATCH v5 17/17] dax: remove "depends on BROKEN" from FS_DAX_PMD Ross Zwisler <ross.zwisler@linux.intel.com> - 2016-10-07 23:20 +0200
[PATCH v5 14/17] dax: move RADIX_DAX_* defines to dax.h Ross Zwisler <ross.zwisler@linux.intel.com> - 2016-10-07 23:20 +0200
Re: [PATCH v5 14/17] dax: move RADIX_DAX_* defines to dax.h Christoph Hellwig <hch@lst.de> - 2016-10-10 18:00 +0200
Re: [PATCH v5 14/17] dax: move RADIX_DAX_* defines to dax.h Jan Kara <jack@suse.cz> - 2016-10-11 20:50 +0200
[PATCH v5 10/17] dax: remove dax_pmd_fault() Ross Zwisler <ross.zwisler@linux.intel.com> - 2016-10-07 23:20 +0200
[PATCH v5 15/17] dax: add struct iomap based DAX PMD support Ross Zwisler <ross.zwisler@linux.intel.com> - 2016-10-07 23:20 +0200
Re: [PATCH v5 15/17] dax: add struct iomap based DAX PMD support Christoph Hellwig <hch@lst.de> - 2016-10-10 18:00 +0200
Re: [PATCH v5 15/17] dax: add struct iomap based DAX PMD support Ross Zwisler <ross.zwisler@linux.intel.com> - 2016-10-11 00:10 +0200
Re: [PATCH v5 15/17] dax: add struct iomap based DAX PMD support Ross Zwisler <ross.zwisler@linux.intel.com> - 2016-10-11 23:50 +0200
Re: [PATCH v5 15/17] dax: add struct iomap based DAX PMD support Jan Kara <jack@suse.cz> - 2016-10-11 21:00 +0200
Re: [PATCH v5 15/17] dax: add struct iomap based DAX PMD support Ross Zwisler <ross.zwisler@linux.intel.com> - 2016-10-12 01:00 +0200
Re: [PATCH v5 15/17] dax: add struct iomap based DAX PMD support Jan Kara <jack@suse.cz> - 2016-10-12 09:50 +0200
Page 1 of 2 [1] 2 Next page →
| From | Ross Zwisler <ross.zwisler@linux.intel.com> |
|---|---|
| Date | 2016-10-07 23:10 +0200 |
| Subject | [PATCH v5 00/17] re-enable DAX PMD support |
| Message-ID | <spKyZ-65z-11@gated-at.bofh.it> |
DAX PMDs have been disabled since Jan Kara introduced DAX radix tree based locking. This series allows DAX PMDs to participate in the DAX radix tree based locking scheme so that they can be re-enabled. Dave, can you please take this through the XFS tree as we discussed during the v4 review? Changes since v4: - Reworked the DAX flags handling to simplify things and get rid of RADIX_DAX_PTE. (Jan & Christoph) - Moved RADIX_DAX_* macros to be inline functions in include/linux/dax.h. (Christoph) - Got rid of unneeded macros RADIX_DAX_HZP_ENTRY() and RADIX_DAX_EMPTY_ENTRY(), and instead just pass arbitrary flags to radix_dax_entry(). - Re-ordered the arguments to dax_wake_mapping_entry_waiter() to be more consistent with the rest of the code. (Jan) - Moved radix_dax_order() inside of the #ifdef CONFIG_FS_DAX_PMD block. This was causing a build error on various systems that don't define PMD_SHIFT. - Patch 5 fixes what I believe is a missing error return in ext2_iomap_end(). - Fixed the page_start calculation for PMDs that was previously found in dax_entry_start(). (Jan) This code is now included directly in dax_entry_waitqueue(). (Christoph) - dax_entry_waitqueue() now sets up the struct exceptional_entry_key() of the caller as a service to reduce code duplication. (Christoph) - In grab_mapping_entry() we now hold the radix tree entry lock for PMD downgrades while we release the tree_lock and do an unmap_mapping_range(). (Jan) - Removed our last BUG_ON() in dax.c, replacing it with a WARN_ON_ONCE() and an error return. - The dax_iomap_fault() and dax_iomap_pmd_fault() handlers both now call ops->iomap_end() to ensure that we properly balance the ops->iomap_begin() calls with respect to locking, allocations, etc. (Jan) - Removed __GFP_FS from the vmf.gfp_mask used in dax_iomap_pmd_fault(). (Jan) Thank you again to Jan, Christoph and Dave for their review feedback. Here are some related things that are not included in this patch set, but which I plan on doing in the near future: - Add tracepoint support for the PTE and PMD based DAX fault handlers. (Dave) - Move the DAX 4k zero page handling to use a single 4k zero page instead of allocating pages on demand. This will mirror the way that things are done for the 2 MiB case, and will reduce the amount of memory we use when reading 4k holes in DAX. - Change the API to the PMD fault hanlder so it takes a vmf, and at a layer above DAX make sure that the vmf.gfp_mask given to DAX for both PMD and PTE faults doesn't include __GFP_FS. (Jan) These work items will happen after review & integration with Jan's patch set for DAX radix tree cleaning. This series was built upon xfs/xfs-4.9-reflink with PMD performance fixes from Toshi Kani and Dan Williams. Dan's patch has already been merged for v4.8, and Toshi's patches are currently queued in Andrew Morton's mm tree for v4.9 inclusion. These patches are not needed for correct operation, only for good performance. Here is a tree containing my changes: https://git.kernel.org/cgit/linux/kernel/git/zwisler/linux.git/log/?h=dax_pmd_v5 This tree has passed xfstests for ext2, ext4 and XFS both with and without DAX, and has passed targeted testing where I inserted, removed and flushed DAX PTEs and PMDs in every combination I could think of. Previously reported performance numbers: In some simple mmap I/O testing with FIO the use of PMD faults more than doubles I/O performance as compared with PTE faults. Here is the FIO script I used for my testing: [global] bs=4k size=2G directory=/mnt/pmem0 ioengine=mmap [randrw] rw=randrw Here are the performance results with XFS using only pte faults: READ: io=1022.7MB, aggrb=557610KB/s, minb=557610KB/s, maxb=557610KB/s, mint=1878msec, maxt=1878msec WRITE: io=1025.4MB, aggrb=559084KB/s, minb=559084KB/s, maxb=559084KB/s, mint=1878msec, maxt=1878msec Here are performance numbers for that same test using PMD faults: READ: io=1022.7MB, aggrb=1406.7MB/s, minb=1406.7MB/s, maxb=1406.7MB/s, mint=727msec, maxt=727msec WRITE: io=1025.4MB, aggrb=1410.4MB/s, minb=1410.4MB/s, maxb=1410.4MB/s, mint=727msec, maxt=727msec This was done on a random lab machine with a PMEM device made from memmap'd RAM. To get XFS to use PMD faults, I did the following: mkfs.xfs -f -d su=2m,sw=1 /dev/pmem0 mount -o dax /dev/pmem0 /mnt/pmem0 xfs_io -c "extsize 2m" /mnt/pmem0 Ross Zwisler (17): ext4: allow DAX writeback for hole punch ext4: tell DAX the size of allocation holes dax: remove buffer_size_valid() ext2: remove support for DAX PMD faults ext2: return -EIO on ext2_iomap_end() failure dax: make 'wait_table' global variable static dax: remove the last BUG_ON() from fs/dax.c dax: consistent variable naming for DAX entries dax: coordinate locking for offsets in PMD range dax: remove dax_pmd_fault() dax: correct dax iomap code namespace dax: add dax_iomap_sector() helper function dax: dax_iomap_fault() needs to call iomap_end() dax: move RADIX_DAX_* defines to dax.h dax: add struct iomap based DAX PMD support xfs: use struct iomap based DAX PMD fault path dax: remove "depends on BROKEN" from FS_DAX_PMD fs/Kconfig | 1 - fs/dax.c | 718 ++++++++++++++++++++++++++++------------------------ fs/ext2/file.c | 35 +-- fs/ext2/inode.c | 4 +- fs/ext4/inode.c | 7 +- fs/xfs/xfs_aops.c | 26 +- fs/xfs/xfs_aops.h | 3 - fs/xfs/xfs_file.c | 10 +- include/linux/dax.h | 60 ++++- mm/filemap.c | 6 +- 10 files changed, 466 insertions(+), 404 deletions(-) -- 2.7.4
[toc] | [next] | [standalone]
| From | Ross Zwisler <ross.zwisler@linux.intel.com> |
|---|---|
| Date | 2016-10-07 23:10 +0200 |
| Subject | [PATCH v5 07/17] dax: remove the last BUG_ON() from fs/dax.c |
| Message-ID | <spKz0-65z-19@gated-at.bofh.it> |
| In reply to | #1497528 |
Don't take down the kernel if we get an invalid 'from' and 'length' argument pair. Just warn once and return an error. Signed-off-by: Ross Zwisler <ross.zwisler@linux.intel.com> --- fs/dax.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/dax.c b/fs/dax.c index ac28cdf..98189ac 100644 --- a/fs/dax.c +++ b/fs/dax.c @@ -1194,7 +1194,8 @@ int dax_zero_page_range(struct inode *inode, loff_t from, unsigned length, /* Block boundary? Nothing to do */ if (!length) return 0; - BUG_ON((offset + length) > PAGE_SIZE); + if (WARN_ON_ONCE((offset + length) > PAGE_SIZE)) + return -EINVAL; memset(&bh, 0, sizeof(bh)); bh.b_bdev = inode->i_sb->s_bdev; -- 2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Jan Kara <jack@suse.cz> |
|---|---|
| Date | 2016-10-11 21:00 +0200 |
| Subject | Re: [PATCH v5 07/17] dax: remove the last BUG_ON() from fs/dax.c |
| Message-ID | <sraro-1SH-9@gated-at.bofh.it> |
| In reply to | #1497531 |
On Fri 07-10-16 15:08:54, Ross Zwisler wrote: > Don't take down the kernel if we get an invalid 'from' and 'length' > argument pair. Just warn once and return an error. > > Signed-off-by: Ross Zwisler <ross.zwisler@linux.intel.com> Looks good. You can add: Reviewed-by: Jan Kara <jack@suse.cz> Honza > --- > fs/dax.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/fs/dax.c b/fs/dax.c > index ac28cdf..98189ac 100644 > --- a/fs/dax.c > +++ b/fs/dax.c > @@ -1194,7 +1194,8 @@ int dax_zero_page_range(struct inode *inode, loff_t from, unsigned length, > /* Block boundary? Nothing to do */ > if (!length) > return 0; > - BUG_ON((offset + length) > PAGE_SIZE); > + if (WARN_ON_ONCE((offset + length) > PAGE_SIZE)) > + return -EINVAL; > > memset(&bh, 0, sizeof(bh)); > bh.b_bdev = inode->i_sb->s_bdev; > -- > 2.7.4 > > -- Jan Kara <jack@suse.com> SUSE Labs, CR
[toc] | [prev] | [next] | [standalone]
| From | Ross Zwisler <ross.zwisler@linux.intel.com> |
|---|---|
| Date | 2016-10-07 23:20 +0200 |
| Subject | [PATCH v5 04/17] ext2: remove support for DAX PMD faults |
| Message-ID | <spKIF-69y-1@gated-at.bofh.it> |
| In reply to | #1497528 |
DAX PMD support was added via the following commit:
commit e7b1ea2ad658 ("ext2: huge page fault support")
I believe this path to be untested as ext2 doesn't reliably provide block
allocations that are aligned to 2MiB. In my testing I've been unable to
get ext2 to actually fault in a PMD. It always fails with a "pfn
unaligned" message because the sector returned by ext2_get_block() isn't
aligned.
I've tried various settings for the "stride" and "stripe_width" extended
options to mkfs.ext2, without any luck.
Since we can't reliably get PMDs, remove support so that we don't have an
untested code path that we may someday traverse when we happen to get an
aligned block allocation. This should also make 4k DAX faults in ext2 a
bit faster since they will no longer have to call the PMD fault handler
only to get a response of VM_FAULT_FALLBACK.
Signed-off-by: Ross Zwisler <ross.zwisler@linux.intel.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jan Kara <jack@suse.cz>
---
fs/ext2/file.c | 29 ++++++-----------------------
1 file changed, 6 insertions(+), 23 deletions(-)
diff --git a/fs/ext2/file.c b/fs/ext2/file.c
index 0ca363d..0f257f8 100644
--- a/fs/ext2/file.c
+++ b/fs/ext2/file.c
@@ -107,27 +107,6 @@ static int ext2_dax_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
return ret;
}
-static int ext2_dax_pmd_fault(struct vm_area_struct *vma, unsigned long addr,
- pmd_t *pmd, unsigned int flags)
-{
- struct inode *inode = file_inode(vma->vm_file);
- struct ext2_inode_info *ei = EXT2_I(inode);
- int ret;
-
- if (flags & FAULT_FLAG_WRITE) {
- sb_start_pagefault(inode->i_sb);
- file_update_time(vma->vm_file);
- }
- down_read(&ei->dax_sem);
-
- ret = dax_pmd_fault(vma, addr, pmd, flags, ext2_get_block);
-
- up_read(&ei->dax_sem);
- if (flags & FAULT_FLAG_WRITE)
- sb_end_pagefault(inode->i_sb);
- return ret;
-}
-
static int ext2_dax_pfn_mkwrite(struct vm_area_struct *vma,
struct vm_fault *vmf)
{
@@ -154,7 +133,11 @@ static int ext2_dax_pfn_mkwrite(struct vm_area_struct *vma,
static const struct vm_operations_struct ext2_dax_vm_ops = {
.fault = ext2_dax_fault,
- .pmd_fault = ext2_dax_pmd_fault,
+ /*
+ * .pmd_fault is not supported for DAX because allocation in ext2
+ * cannot be reliably aligned to huge page sizes and so pmd faults
+ * will always fail and fail back to regular faults.
+ */
.page_mkwrite = ext2_dax_fault,
.pfn_mkwrite = ext2_dax_pfn_mkwrite,
};
@@ -166,7 +149,7 @@ static int ext2_file_mmap(struct file *file, struct vm_area_struct *vma)
file_accessed(file);
vma->vm_ops = &ext2_dax_vm_ops;
- vma->vm_flags |= VM_MIXEDMAP | VM_HUGEPAGE;
+ vma->vm_flags |= VM_MIXEDMAP;
return 0;
}
#else
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Ross Zwisler <ross.zwisler@linux.intel.com> |
|---|---|
| Date | 2016-10-07 23:20 +0200 |
| Subject | [PATCH v5 01/17] ext4: allow DAX writeback for hole punch |
| Message-ID | <spKIF-69y-3@gated-at.bofh.it> |
| In reply to | #1497528 |
Currently when doing a DAX hole punch with ext4 we fail to do a writeback.
This is because the logic around filemap_write_and_wait_range() in
ext4_punch_hole() only looks for dirty page cache pages in the radix tree,
not for dirty DAX exceptional entries.
Signed-off-by: Ross Zwisler <ross.zwisler@linux.intel.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Cc: <stable@vger.kernel.org>
---
fs/ext4/inode.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 3131747..0900cb4 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -3890,7 +3890,7 @@ int ext4_update_disksize_before_punch(struct inode *inode, loff_t offset,
}
/*
- * ext4_punch_hole: punches a hole in a file by releaseing the blocks
+ * ext4_punch_hole: punches a hole in a file by releasing the blocks
* associated with the given offset and length
*
* @inode: File inode
@@ -3919,7 +3919,7 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
* Write out all dirty pages to avoid race conditions
* Then release them.
*/
- if (mapping->nrpages && mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) {
+ if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) {
ret = filemap_write_and_wait_range(mapping, offset,
offset + length - 1);
if (ret)
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Ross Zwisler <ross.zwisler@linux.intel.com> |
|---|---|
| Date | 2016-10-07 23:20 +0200 |
| Subject | [PATCH v5 12/17] dax: add dax_iomap_sector() helper function |
| Message-ID | <spKIG-69y-5@gated-at.bofh.it> |
| In reply to | #1497528 |
To be able to correctly calculate the sector from a file position and a
struct iomap there is a complex little bit of logic that currently happens
in both dax_iomap_actor() and dax_iomap_fault(). This will need to be
repeated yet again in the DAX PMD fault handler when it is added, so break
it out into a helper function.
Signed-off-by: Ross Zwisler <ross.zwisler@linux.intel.com>
---
fs/dax.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/fs/dax.c b/fs/dax.c
index 982ccbb..7689ab0 100644
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -1023,6 +1023,11 @@ int dax_truncate_page(struct inode *inode, loff_t from, get_block_t get_block)
EXPORT_SYMBOL_GPL(dax_truncate_page);
#ifdef CONFIG_FS_IOMAP
+static inline sector_t dax_iomap_sector(struct iomap *iomap, loff_t pos)
+{
+ return iomap->blkno + (((pos & PAGE_MASK) - iomap->offset) >> 9);
+}
+
static loff_t
dax_iomap_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
struct iomap *iomap)
@@ -1048,8 +1053,7 @@ dax_iomap_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
struct blk_dax_ctl dax = { 0 };
ssize_t map_len;
- dax.sector = iomap->blkno +
- (((pos & PAGE_MASK) - iomap->offset) >> 9);
+ dax.sector = dax_iomap_sector(iomap, pos);
dax.size = (length + offset + PAGE_SIZE - 1) & PAGE_MASK;
map_len = dax_map_atomic(iomap->bdev, &dax);
if (map_len < 0) {
@@ -1186,7 +1190,7 @@ int dax_iomap_fault(struct vm_area_struct *vma, struct vm_fault *vmf,
goto unlock_entry;
}
- sector = iomap.blkno + (((pos & PAGE_MASK) - iomap.offset) >> 9);
+ sector = dax_iomap_sector(&iomap, pos);
if (vmf->cow_page) {
switch (iomap.type) {
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Christoph Hellwig <hch@lst.de> |
|---|---|
| Date | 2016-10-10 17:50 +0200 |
| Subject | Re: [PATCH v5 12/17] dax: add dax_iomap_sector() helper function |
| Message-ID | <sqKZX-2ZY-7@gated-at.bofh.it> |
| In reply to | #1497534 |
Looks fine, Reviewed-by: Christoph Hellwig <hch@lst.de>
[toc] | [prev] | [next] | [standalone]
| From | Jan Kara <jack@suse.cz> |
|---|---|
| Date | 2016-10-11 20:50 +0200 |
| Subject | Re: [PATCH v5 12/17] dax: add dax_iomap_sector() helper function |
| Message-ID | <srahI-1Pi-33@gated-at.bofh.it> |
| In reply to | #1497534 |
On Fri 07-10-16 15:08:59, Ross Zwisler wrote:
> To be able to correctly calculate the sector from a file position and a
> struct iomap there is a complex little bit of logic that currently happens
> in both dax_iomap_actor() and dax_iomap_fault(). This will need to be
> repeated yet again in the DAX PMD fault handler when it is added, so break
> it out into a helper function.
>
> Signed-off-by: Ross Zwisler <ross.zwisler@linux.intel.com>
Looks good. You can add:
Reviewed-by: Jan Kara <jack@suse.cz>
Honza
> ---
> fs/dax.c | 10 +++++++---
> 1 file changed, 7 insertions(+), 3 deletions(-)
>
> diff --git a/fs/dax.c b/fs/dax.c
> index 982ccbb..7689ab0 100644
> --- a/fs/dax.c
> +++ b/fs/dax.c
> @@ -1023,6 +1023,11 @@ int dax_truncate_page(struct inode *inode, loff_t from, get_block_t get_block)
> EXPORT_SYMBOL_GPL(dax_truncate_page);
>
> #ifdef CONFIG_FS_IOMAP
> +static inline sector_t dax_iomap_sector(struct iomap *iomap, loff_t pos)
> +{
> + return iomap->blkno + (((pos & PAGE_MASK) - iomap->offset) >> 9);
> +}
> +
> static loff_t
> dax_iomap_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
> struct iomap *iomap)
> @@ -1048,8 +1053,7 @@ dax_iomap_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
> struct blk_dax_ctl dax = { 0 };
> ssize_t map_len;
>
> - dax.sector = iomap->blkno +
> - (((pos & PAGE_MASK) - iomap->offset) >> 9);
> + dax.sector = dax_iomap_sector(iomap, pos);
> dax.size = (length + offset + PAGE_SIZE - 1) & PAGE_MASK;
> map_len = dax_map_atomic(iomap->bdev, &dax);
> if (map_len < 0) {
> @@ -1186,7 +1190,7 @@ int dax_iomap_fault(struct vm_area_struct *vma, struct vm_fault *vmf,
> goto unlock_entry;
> }
>
> - sector = iomap.blkno + (((pos & PAGE_MASK) - iomap.offset) >> 9);
> + sector = dax_iomap_sector(&iomap, pos);
>
> if (vmf->cow_page) {
> switch (iomap.type) {
> --
> 2.7.4
>
>
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
[toc] | [prev] | [next] | [standalone]
| From | Ross Zwisler <ross.zwisler@linux.intel.com> |
|---|---|
| Date | 2016-10-07 23:20 +0200 |
| Subject | [PATCH v5 13/17] dax: dax_iomap_fault() needs to call iomap_end() |
| Message-ID | <spKIG-69y-9@gated-at.bofh.it> |
| In reply to | #1497528 |
Currently iomap_end() doesn't do anything for DAX page faults for both ext2
and XFS. ext2_iomap_end() just checks for a write underrun, and
xfs_file_iomap_end() checks to see if it needs to finish a delayed
allocation. However, in the future iomap_end() calls might be needed to
make sure we have balanced allocations, locks, etc. So, add calls to
iomap_end() with appropriate error handling to dax_iomap_fault().
Signed-off-by: Ross Zwisler <ross.zwisler@linux.intel.com>
Suggested-by: Jan Kara <jack@suse.cz>
---
fs/dax.c | 31 ++++++++++++++++++++++++++++---
1 file changed, 28 insertions(+), 3 deletions(-)
diff --git a/fs/dax.c b/fs/dax.c
index 7689ab0..5e8febe 100644
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -1187,7 +1187,7 @@ int dax_iomap_fault(struct vm_area_struct *vma, struct vm_fault *vmf,
goto unlock_entry;
if (WARN_ON_ONCE(iomap.offset + iomap.length < pos + PAGE_SIZE)) {
error = -EIO; /* fs corruption? */
- goto unlock_entry;
+ goto finish_iomap;
}
sector = dax_iomap_sector(&iomap, pos);
@@ -1209,7 +1209,14 @@ int dax_iomap_fault(struct vm_area_struct *vma, struct vm_fault *vmf,
}
if (error)
- goto unlock_entry;
+ goto finish_iomap;
+
+ if (ops->iomap_end) {
+ error = ops->iomap_end(inode, pos, PAGE_SIZE,
+ PAGE_SIZE, flags, &iomap);
+ if (error)
+ goto unlock_entry;
+ }
if (!radix_tree_exceptional_entry(entry)) {
vmf->page = entry;
return VM_FAULT_LOCKED;
@@ -1230,8 +1237,15 @@ int dax_iomap_fault(struct vm_area_struct *vma, struct vm_fault *vmf,
break;
case IOMAP_UNWRITTEN:
case IOMAP_HOLE:
- if (!(vmf->flags & FAULT_FLAG_WRITE))
+ if (!(vmf->flags & FAULT_FLAG_WRITE)) {
+ if (ops->iomap_end) {
+ error = ops->iomap_end(inode, pos, PAGE_SIZE,
+ PAGE_SIZE, flags, &iomap);
+ if (error)
+ goto unlock_entry;
+ }
return dax_load_hole(mapping, entry, vmf);
+ }
/*FALLTHRU*/
default:
WARN_ON_ONCE(1);
@@ -1239,6 +1253,17 @@ int dax_iomap_fault(struct vm_area_struct *vma, struct vm_fault *vmf,
break;
}
+ finish_iomap:
+ if (ops->iomap_end) {
+ if (error) {
+ /* keep previous error */
+ ops->iomap_end(inode, pos, PAGE_SIZE, PAGE_SIZE, flags,
+ &iomap);
+ } else {
+ error = ops->iomap_end(inode, pos, PAGE_SIZE,
+ PAGE_SIZE, flags, &iomap);
+ }
+ }
unlock_entry:
put_locked_mapping_entry(mapping, vmf->pgoff, entry);
out:
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Christoph Hellwig <hch@lst.de> |
|---|---|
| Date | 2016-10-10 18:00 +0200 |
| Subject | Re: [PATCH v5 13/17] dax: dax_iomap_fault() needs to call iomap_end() |
| Message-ID | <sqL9E-33e-9@gated-at.bofh.it> |
| In reply to | #1497535 |
On Fri, Oct 07, 2016 at 03:09:00PM -0600, Ross Zwisler wrote:
> Currently iomap_end() doesn't do anything for DAX page faults for both ext2
> and XFS. ext2_iomap_end() just checks for a write underrun, and
> xfs_file_iomap_end() checks to see if it needs to finish a delayed
> allocation. However, in the future iomap_end() calls might be needed to
> make sure we have balanced allocations, locks, etc. So, add calls to
> iomap_end() with appropriate error handling to dax_iomap_fault().
Is there a way to just have a single call to iomap_end at the end of
the function, after which we just return a previosuly setup return
value?
e.g.
out:
if (ops->iomap_end) {
error = ops->iomap_end(inode, pos, PAGE_SIZE,
PAGE_SIZE, flags, &iomap);
}
if (error == -ENOMEM)
return VM_FAULT_OOM | major;
if (error < 0 && error != -EBUSY)
return VM_FAULT_SIGBUS | major;
return ret;
[toc] | [prev] | [next] | [standalone]
| From | Ross Zwisler <ross.zwisler@linux.intel.com> |
|---|---|
| Date | 2016-10-11 00:10 +0200 |
| Subject | Re: [PATCH v5 13/17] dax: dax_iomap_fault() needs to call iomap_end() |
| Message-ID | <sqQVH-6Kg-11@gated-at.bofh.it> |
| In reply to | #1498392 |
On Mon, Oct 10, 2016 at 05:50:04PM +0200, Christoph Hellwig wrote:
> On Fri, Oct 07, 2016 at 03:09:00PM -0600, Ross Zwisler wrote:
> > Currently iomap_end() doesn't do anything for DAX page faults for both ext2
> > and XFS. ext2_iomap_end() just checks for a write underrun, and
> > xfs_file_iomap_end() checks to see if it needs to finish a delayed
> > allocation. However, in the future iomap_end() calls might be needed to
> > make sure we have balanced allocations, locks, etc. So, add calls to
> > iomap_end() with appropriate error handling to dax_iomap_fault().
>
> Is there a way to just have a single call to iomap_end at the end of
> the function, after which we just return a previosuly setup return
> value?
>
> e.g.
>
> out:
> if (ops->iomap_end) {
> error = ops->iomap_end(inode, pos, PAGE_SIZE,
> PAGE_SIZE, flags, &iomap);
> }
>
> if (error == -ENOMEM)
> return VM_FAULT_OOM | major;
> if (error < 0 && error != -EBUSY)
> return VM_FAULT_SIGBUS | major;
> return ret;
Sure, will do.
[toc] | [prev] | [next] | [standalone]
| From | Jan Kara <jack@suse.cz> |
|---|---|
| Date | 2016-10-11 20:50 +0200 |
| Subject | Re: [PATCH v5 13/17] dax: dax_iomap_fault() needs to call iomap_end() |
| Message-ID | <srahI-1Pi-39@gated-at.bofh.it> |
| In reply to | #1497535 |
On Fri 07-10-16 15:09:00, Ross Zwisler wrote:
> Currently iomap_end() doesn't do anything for DAX page faults for both ext2
> and XFS. ext2_iomap_end() just checks for a write underrun, and
> xfs_file_iomap_end() checks to see if it needs to finish a delayed
> allocation. However, in the future iomap_end() calls might be needed to
> make sure we have balanced allocations, locks, etc. So, add calls to
> iomap_end() with appropriate error handling to dax_iomap_fault().
>
> Signed-off-by: Ross Zwisler <ross.zwisler@linux.intel.com>
> Suggested-by: Jan Kara <jack@suse.cz>
...
> @@ -1239,6 +1253,17 @@ int dax_iomap_fault(struct vm_area_struct *vma, struct vm_fault *vmf,
> break;
> }
>
> + finish_iomap:
> + if (ops->iomap_end) {
> + if (error) {
> + /* keep previous error */
> + ops->iomap_end(inode, pos, PAGE_SIZE, PAGE_SIZE, flags,
> + &iomap);
I think for the error case we should set number of 'written' bytes to 0 to
tell fs to cancel what it has prepared. This is mostly cosmetic since the
only case where I can imagine this would matter is shared write fault and
in that case we have currently no error path but still it could bite us in
the future.
Other than that the patch looks good so you can add:
Reviewed-by: Jan Kara <jack@suse.cz>
Honza
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
[toc] | [prev] | [next] | [standalone]
| From | Ross Zwisler <ross.zwisler@linux.intel.com> |
|---|---|
| Date | 2016-10-07 23:20 +0200 |
| Subject | [PATCH v5 16/17] xfs: use struct iomap based DAX PMD fault path |
| Message-ID | <spKIG-69y-19@gated-at.bofh.it> |
| In reply to | #1497528 |
Switch xfs_filemap_pmd_fault() from using dax_pmd_fault() to the new and
improved dax_iomap_pmd_fault(). Also, now that it has no more users,
remove xfs_get_blocks_dax_fault().
Signed-off-by: Ross Zwisler <ross.zwisler@linux.intel.com>
---
fs/xfs/xfs_aops.c | 26 +++++---------------------
fs/xfs/xfs_aops.h | 3 ---
fs/xfs/xfs_file.c | 2 +-
3 files changed, 6 insertions(+), 25 deletions(-)
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index 0e2a931..1c73d0a 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -1298,8 +1298,7 @@ __xfs_get_blocks(
sector_t iblock,
struct buffer_head *bh_result,
int create,
- bool direct,
- bool dax_fault)
+ bool direct)
{
struct xfs_inode *ip = XFS_I(inode);
struct xfs_mount *mp = ip->i_mount;
@@ -1420,13 +1419,8 @@ __xfs_get_blocks(
if (ISUNWRITTEN(&imap))
set_buffer_unwritten(bh_result);
/* direct IO needs special help */
- if (create) {
- if (dax_fault)
- ASSERT(!ISUNWRITTEN(&imap));
- else
- xfs_map_direct(inode, bh_result, &imap, offset,
- is_cow);
- }
+ if (create)
+ xfs_map_direct(inode, bh_result, &imap, offset, is_cow);
}
/*
@@ -1466,7 +1460,7 @@ xfs_get_blocks(
struct buffer_head *bh_result,
int create)
{
- return __xfs_get_blocks(inode, iblock, bh_result, create, false, false);
+ return __xfs_get_blocks(inode, iblock, bh_result, create, false);
}
int
@@ -1476,17 +1470,7 @@ xfs_get_blocks_direct(
struct buffer_head *bh_result,
int create)
{
- return __xfs_get_blocks(inode, iblock, bh_result, create, true, false);
-}
-
-int
-xfs_get_blocks_dax_fault(
- struct inode *inode,
- sector_t iblock,
- struct buffer_head *bh_result,
- int create)
-{
- return __xfs_get_blocks(inode, iblock, bh_result, create, true, true);
+ return __xfs_get_blocks(inode, iblock, bh_result, create, true);
}
/*
diff --git a/fs/xfs/xfs_aops.h b/fs/xfs/xfs_aops.h
index b3c6634..34dc00d 100644
--- a/fs/xfs/xfs_aops.h
+++ b/fs/xfs/xfs_aops.h
@@ -59,9 +59,6 @@ int xfs_get_blocks(struct inode *inode, sector_t offset,
struct buffer_head *map_bh, int create);
int xfs_get_blocks_direct(struct inode *inode, sector_t offset,
struct buffer_head *map_bh, int create);
-int xfs_get_blocks_dax_fault(struct inode *inode, sector_t offset,
- struct buffer_head *map_bh, int create);
-
int xfs_end_io_direct_write(struct kiocb *iocb, loff_t offset,
ssize_t size, void *private);
int xfs_setfilesize(struct xfs_inode *ip, xfs_off_t offset, size_t size);
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 8f12152..7b13dda 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -1750,7 +1750,7 @@ xfs_filemap_pmd_fault(
}
xfs_ilock(XFS_I(inode), XFS_MMAPLOCK_SHARED);
- ret = dax_pmd_fault(vma, addr, pmd, flags, xfs_get_blocks_dax_fault);
+ ret = dax_iomap_pmd_fault(vma, addr, pmd, flags, &xfs_iomap_ops);
xfs_iunlock(XFS_I(inode), XFS_MMAPLOCK_SHARED);
if (flags & FAULT_FLAG_WRITE)
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Jan Kara <jack@suse.cz> |
|---|---|
| Date | 2016-10-11 20:50 +0200 |
| Subject | Re: [PATCH v5 16/17] xfs: use struct iomap based DAX PMD fault path |
| Message-ID | <srahI-1Pi-19@gated-at.bofh.it> |
| In reply to | #1497536 |
On Fri 07-10-16 15:09:03, Ross Zwisler wrote:
> Switch xfs_filemap_pmd_fault() from using dax_pmd_fault() to the new and
> improved dax_iomap_pmd_fault(). Also, now that it has no more users,
> remove xfs_get_blocks_dax_fault().
>
> Signed-off-by: Ross Zwisler <ross.zwisler@linux.intel.com>
The patch looks good to me. You can add:
Reviewed-by: Jan Kara <jack@suse.cz>
Honza
> ---
> fs/xfs/xfs_aops.c | 26 +++++---------------------
> fs/xfs/xfs_aops.h | 3 ---
> fs/xfs/xfs_file.c | 2 +-
> 3 files changed, 6 insertions(+), 25 deletions(-)
>
> diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
> index 0e2a931..1c73d0a 100644
> --- a/fs/xfs/xfs_aops.c
> +++ b/fs/xfs/xfs_aops.c
> @@ -1298,8 +1298,7 @@ __xfs_get_blocks(
> sector_t iblock,
> struct buffer_head *bh_result,
> int create,
> - bool direct,
> - bool dax_fault)
> + bool direct)
> {
> struct xfs_inode *ip = XFS_I(inode);
> struct xfs_mount *mp = ip->i_mount;
> @@ -1420,13 +1419,8 @@ __xfs_get_blocks(
> if (ISUNWRITTEN(&imap))
> set_buffer_unwritten(bh_result);
> /* direct IO needs special help */
> - if (create) {
> - if (dax_fault)
> - ASSERT(!ISUNWRITTEN(&imap));
> - else
> - xfs_map_direct(inode, bh_result, &imap, offset,
> - is_cow);
> - }
> + if (create)
> + xfs_map_direct(inode, bh_result, &imap, offset, is_cow);
> }
>
> /*
> @@ -1466,7 +1460,7 @@ xfs_get_blocks(
> struct buffer_head *bh_result,
> int create)
> {
> - return __xfs_get_blocks(inode, iblock, bh_result, create, false, false);
> + return __xfs_get_blocks(inode, iblock, bh_result, create, false);
> }
>
> int
> @@ -1476,17 +1470,7 @@ xfs_get_blocks_direct(
> struct buffer_head *bh_result,
> int create)
> {
> - return __xfs_get_blocks(inode, iblock, bh_result, create, true, false);
> -}
> -
> -int
> -xfs_get_blocks_dax_fault(
> - struct inode *inode,
> - sector_t iblock,
> - struct buffer_head *bh_result,
> - int create)
> -{
> - return __xfs_get_blocks(inode, iblock, bh_result, create, true, true);
> + return __xfs_get_blocks(inode, iblock, bh_result, create, true);
> }
>
> /*
> diff --git a/fs/xfs/xfs_aops.h b/fs/xfs/xfs_aops.h
> index b3c6634..34dc00d 100644
> --- a/fs/xfs/xfs_aops.h
> +++ b/fs/xfs/xfs_aops.h
> @@ -59,9 +59,6 @@ int xfs_get_blocks(struct inode *inode, sector_t offset,
> struct buffer_head *map_bh, int create);
> int xfs_get_blocks_direct(struct inode *inode, sector_t offset,
> struct buffer_head *map_bh, int create);
> -int xfs_get_blocks_dax_fault(struct inode *inode, sector_t offset,
> - struct buffer_head *map_bh, int create);
> -
> int xfs_end_io_direct_write(struct kiocb *iocb, loff_t offset,
> ssize_t size, void *private);
> int xfs_setfilesize(struct xfs_inode *ip, xfs_off_t offset, size_t size);
> diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
> index 8f12152..7b13dda 100644
> --- a/fs/xfs/xfs_file.c
> +++ b/fs/xfs/xfs_file.c
> @@ -1750,7 +1750,7 @@ xfs_filemap_pmd_fault(
> }
>
> xfs_ilock(XFS_I(inode), XFS_MMAPLOCK_SHARED);
> - ret = dax_pmd_fault(vma, addr, pmd, flags, xfs_get_blocks_dax_fault);
> + ret = dax_iomap_pmd_fault(vma, addr, pmd, flags, &xfs_iomap_ops);
> xfs_iunlock(XFS_I(inode), XFS_MMAPLOCK_SHARED);
>
> if (flags & FAULT_FLAG_WRITE)
> --
> 2.7.4
>
>
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
[toc] | [prev] | [next] | [standalone]
| From | Ross Zwisler <ross.zwisler@linux.intel.com> |
|---|---|
| Date | 2016-10-07 23:20 +0200 |
| Subject | [PATCH v5 08/17] dax: consistent variable naming for DAX entries |
| Message-ID | <spKIG-69y-11@gated-at.bofh.it> |
| In reply to | #1497528 |
No functional change.
Consistently use the variable name 'entry' instead of 'ret' for DAX radix
tree entries. This was already happening in most of the code, so update
get_unlocked_mapping_entry(), grab_mapping_entry() and
dax_unlock_mapping_entry().
Signed-off-by: Ross Zwisler <ross.zwisler@linux.intel.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jan Kara <jack@suse.cz>
---
fs/dax.c | 34 +++++++++++++++++-----------------
1 file changed, 17 insertions(+), 17 deletions(-)
diff --git a/fs/dax.c b/fs/dax.c
index 98189ac..152a6e1 100644
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -357,7 +357,7 @@ static inline void *unlock_slot(struct address_space *mapping, void **slot)
static void *get_unlocked_mapping_entry(struct address_space *mapping,
pgoff_t index, void ***slotp)
{
- void *ret, **slot;
+ void *entry, **slot;
struct wait_exceptional_entry_queue ewait;
wait_queue_head_t *wq = dax_entry_waitqueue(mapping, index);
@@ -367,13 +367,13 @@ static void *get_unlocked_mapping_entry(struct address_space *mapping,
ewait.key.index = index;
for (;;) {
- ret = __radix_tree_lookup(&mapping->page_tree, index, NULL,
+ entry = __radix_tree_lookup(&mapping->page_tree, index, NULL,
&slot);
- if (!ret || !radix_tree_exceptional_entry(ret) ||
+ if (!entry || !radix_tree_exceptional_entry(entry) ||
!slot_locked(mapping, slot)) {
if (slotp)
*slotp = slot;
- return ret;
+ return entry;
}
prepare_to_wait_exclusive(wq, &ewait.wait,
TASK_UNINTERRUPTIBLE);
@@ -396,13 +396,13 @@ static void *get_unlocked_mapping_entry(struct address_space *mapping,
*/
static void *grab_mapping_entry(struct address_space *mapping, pgoff_t index)
{
- void *ret, **slot;
+ void *entry, **slot;
restart:
spin_lock_irq(&mapping->tree_lock);
- ret = get_unlocked_mapping_entry(mapping, index, &slot);
+ entry = get_unlocked_mapping_entry(mapping, index, &slot);
/* No entry for given index? Make sure radix tree is big enough. */
- if (!ret) {
+ if (!entry) {
int err;
spin_unlock_irq(&mapping->tree_lock);
@@ -410,10 +410,10 @@ restart:
mapping_gfp_mask(mapping) & ~__GFP_HIGHMEM);
if (err)
return ERR_PTR(err);
- ret = (void *)(RADIX_TREE_EXCEPTIONAL_ENTRY |
+ entry = (void *)(RADIX_TREE_EXCEPTIONAL_ENTRY |
RADIX_DAX_ENTRY_LOCK);
spin_lock_irq(&mapping->tree_lock);
- err = radix_tree_insert(&mapping->page_tree, index, ret);
+ err = radix_tree_insert(&mapping->page_tree, index, entry);
radix_tree_preload_end();
if (err) {
spin_unlock_irq(&mapping->tree_lock);
@@ -425,11 +425,11 @@ restart:
/* Good, we have inserted empty locked entry into the tree. */
mapping->nrexceptional++;
spin_unlock_irq(&mapping->tree_lock);
- return ret;
+ return entry;
}
/* Normal page in radix tree? */
- if (!radix_tree_exceptional_entry(ret)) {
- struct page *page = ret;
+ if (!radix_tree_exceptional_entry(entry)) {
+ struct page *page = entry;
get_page(page);
spin_unlock_irq(&mapping->tree_lock);
@@ -442,9 +442,9 @@ restart:
}
return page;
}
- ret = lock_slot(mapping, slot);
+ entry = lock_slot(mapping, slot);
spin_unlock_irq(&mapping->tree_lock);
- return ret;
+ return entry;
}
void dax_wake_mapping_entry_waiter(struct address_space *mapping,
@@ -469,11 +469,11 @@ void dax_wake_mapping_entry_waiter(struct address_space *mapping,
void dax_unlock_mapping_entry(struct address_space *mapping, pgoff_t index)
{
- void *ret, **slot;
+ void *entry, **slot;
spin_lock_irq(&mapping->tree_lock);
- ret = __radix_tree_lookup(&mapping->page_tree, index, NULL, &slot);
- if (WARN_ON_ONCE(!ret || !radix_tree_exceptional_entry(ret) ||
+ entry = __radix_tree_lookup(&mapping->page_tree, index, NULL, &slot);
+ if (WARN_ON_ONCE(!entry || !radix_tree_exceptional_entry(entry) ||
!slot_locked(mapping, slot))) {
spin_unlock_irq(&mapping->tree_lock);
return;
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Ross Zwisler <ross.zwisler@linux.intel.com> |
|---|---|
| Date | 2016-10-07 23:20 +0200 |
| Subject | [PATCH v5 05/17] ext2: return -EIO on ext2_iomap_end() failure |
| Message-ID | <spKIG-69y-27@gated-at.bofh.it> |
| In reply to | #1497528 |
Right now we just return 0 for success, but we really want to let callers
know about this failure.
Signed-off-by: Ross Zwisler <ross.zwisler@linux.intel.com>
---
fs/ext2/inode.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index c7dbb46..368913c 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -830,8 +830,10 @@ ext2_iomap_end(struct inode *inode, loff_t offset, loff_t length,
{
if (iomap->type == IOMAP_MAPPED &&
written < length &&
- (flags & IOMAP_WRITE))
+ (flags & IOMAP_WRITE)) {
ext2_write_failed(inode->i_mapping, offset + length);
+ return -EIO;
+ }
return 0;
}
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Jan Kara <jack@suse.cz> |
|---|---|
| Date | 2016-10-11 21:00 +0200 |
| Subject | Re: [PATCH v5 05/17] ext2: return -EIO on ext2_iomap_end() failure |
| Message-ID | <srarn-1SH-3@gated-at.bofh.it> |
| In reply to | #1497541 |
On Fri 07-10-16 15:08:52, Ross Zwisler wrote:
> Right now we just return 0 for success, but we really want to let callers
> know about this failure.
>
> Signed-off-by: Ross Zwisler <ross.zwisler@linux.intel.com>
> ---
> fs/ext2/inode.c | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
> index c7dbb46..368913c 100644
> --- a/fs/ext2/inode.c
> +++ b/fs/ext2/inode.c
> @@ -830,8 +830,10 @@ ext2_iomap_end(struct inode *inode, loff_t offset, loff_t length,
> {
> if (iomap->type == IOMAP_MAPPED &&
> written < length &&
> - (flags & IOMAP_WRITE))
> + (flags & IOMAP_WRITE)) {
> ext2_write_failed(inode->i_mapping, offset + length);
> + return -EIO;
> + }
So this is wrong. This (written < length) happens when we fail to copy data
to / from userspace buffer into pagecache pages / DAX blocks. It may be
because the passed buffer pointer is just wrong, or just because the page
got swapped out and we have to swap it back in. It is a role of upper
layers to decide what went wrong and proceed accordingly but from filesystem
point of view we just have to cancel the operation we have prepared and
return to upper layers. So returning 0 in this case is correct.
Honza
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
[toc] | [prev] | [next] | [standalone]
| From | Ross Zwisler <ross.zwisler@linux.intel.com> |
|---|---|
| Date | 2016-10-07 23:20 +0200 |
| Subject | [PATCH v5 03/17] dax: remove buffer_size_valid() |
| Message-ID | <spKIG-69y-33@gated-at.bofh.it> |
| In reply to | #1497528 |
Now that ext4 properly sets bh.b_size when we call get_block() for a hole,
rely on that value and remove the buffer_size_valid() sanity check.
Signed-off-by: Ross Zwisler <ross.zwisler@linux.intel.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Christoph Hellwig <hch@lst.de>
---
fs/dax.c | 22 +---------------------
1 file changed, 1 insertion(+), 21 deletions(-)
diff --git a/fs/dax.c b/fs/dax.c
index cc025f8..9b9be8a 100644
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -123,19 +123,6 @@ static bool buffer_written(struct buffer_head *bh)
return buffer_mapped(bh) && !buffer_unwritten(bh);
}
-/*
- * When ext4 encounters a hole, it returns without modifying the buffer_head
- * which means that we can't trust b_size. To cope with this, we set b_state
- * to 0 before calling get_block and, if any bit is set, we know we can trust
- * b_size. Unfortunate, really, since ext4 knows precisely how long a hole is
- * and would save us time calling get_block repeatedly.
- */
-static bool buffer_size_valid(struct buffer_head *bh)
-{
- return bh->b_state != 0;
-}
-
-
static sector_t to_sector(const struct buffer_head *bh,
const struct inode *inode)
{
@@ -177,8 +164,6 @@ static ssize_t dax_io(struct inode *inode, struct iov_iter *iter,
rc = get_block(inode, block, bh, rw == WRITE);
if (rc)
break;
- if (!buffer_size_valid(bh))
- bh->b_size = 1 << blkbits;
bh_max = pos - first + bh->b_size;
bdev = bh->b_bdev;
/*
@@ -1012,12 +997,7 @@ int dax_pmd_fault(struct vm_area_struct *vma, unsigned long address,
bdev = bh.b_bdev;
- /*
- * If the filesystem isn't willing to tell us the length of a hole,
- * just fall back to PTEs. Calling get_block 512 times in a loop
- * would be silly.
- */
- if (!buffer_size_valid(&bh) || bh.b_size < PMD_SIZE) {
+ if (bh.b_size < PMD_SIZE) {
dax_pmd_dbg(&bh, address, "allocated block too small");
return VM_FAULT_FALLBACK;
}
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Ross Zwisler <ross.zwisler@linux.intel.com> |
|---|---|
| Date | 2016-10-07 23:20 +0200 |
| Subject | [PATCH v5 09/17] dax: coordinate locking for offsets in PMD range |
| Message-ID | <spKIG-69y-29@gated-at.bofh.it> |
| In reply to | #1497528 |
DAX radix tree locking currently locks entries based on the unique
combination of the 'mapping' pointer and the pgoff_t 'index' for the entry.
This works for PTEs, but as we move to PMDs we will need to have all the
offsets within the range covered by the PMD to map to the same bit lock.
To accomplish this, for ranges covered by a PMD entry we will instead lock
based on the page offset of the beginning of the PMD entry. The 'mapping'
pointer is still used in the same way.
Signed-off-by: Ross Zwisler <ross.zwisler@linux.intel.com>
---
fs/dax.c | 58 +++++++++++++++++++++++++++++++----------------------
include/linux/dax.h | 2 +-
mm/filemap.c | 2 +-
3 files changed, 36 insertions(+), 26 deletions(-)
diff --git a/fs/dax.c b/fs/dax.c
index 152a6e1..608cee9 100644
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -64,14 +64,6 @@ static int __init init_dax_wait_table(void)
}
fs_initcall(init_dax_wait_table);
-static wait_queue_head_t *dax_entry_waitqueue(struct address_space *mapping,
- pgoff_t index)
-{
- unsigned long hash = hash_long((unsigned long)mapping ^ index,
- DAX_WAIT_TABLE_BITS);
- return wait_table + hash;
-}
-
static long dax_map_atomic(struct block_device *bdev, struct blk_dax_ctl *dax)
{
struct request_queue *q = bdev->bd_queue;
@@ -285,7 +277,7 @@ EXPORT_SYMBOL_GPL(dax_do_io);
*/
struct exceptional_entry_key {
struct address_space *mapping;
- unsigned long index;
+ pgoff_t entry_start;
};
struct wait_exceptional_entry_queue {
@@ -293,6 +285,26 @@ struct wait_exceptional_entry_queue {
struct exceptional_entry_key key;
};
+static wait_queue_head_t *dax_entry_waitqueue(struct address_space *mapping,
+ pgoff_t index, void *entry, struct exceptional_entry_key *key)
+{
+ unsigned long hash;
+
+ /*
+ * If 'entry' is a PMD, align the 'index' that we use for the wait
+ * queue to the start of that PMD. This ensures that all offsets in
+ * the range covered by the PMD map to the same bit lock.
+ */
+ if (RADIX_DAX_TYPE(entry) == RADIX_DAX_PMD)
+ index &= ~((1UL << (PMD_SHIFT - PAGE_SHIFT)) - 1);
+
+ key->mapping = mapping;
+ key->entry_start = index;
+
+ hash = hash_long((unsigned long)mapping ^ index, DAX_WAIT_TABLE_BITS);
+ return wait_table + hash;
+}
+
static int wake_exceptional_entry_func(wait_queue_t *wait, unsigned int mode,
int sync, void *keyp)
{
@@ -301,7 +313,7 @@ static int wake_exceptional_entry_func(wait_queue_t *wait, unsigned int mode,
container_of(wait, struct wait_exceptional_entry_queue, wait);
if (key->mapping != ewait->key.mapping ||
- key->index != ewait->key.index)
+ key->entry_start != ewait->key.entry_start)
return 0;
return autoremove_wake_function(wait, mode, sync, NULL);
}
@@ -359,12 +371,10 @@ static void *get_unlocked_mapping_entry(struct address_space *mapping,
{
void *entry, **slot;
struct wait_exceptional_entry_queue ewait;
- wait_queue_head_t *wq = dax_entry_waitqueue(mapping, index);
+ wait_queue_head_t *wq;
init_wait(&ewait.wait);
ewait.wait.func = wake_exceptional_entry_func;
- ewait.key.mapping = mapping;
- ewait.key.index = index;
for (;;) {
entry = __radix_tree_lookup(&mapping->page_tree, index, NULL,
@@ -375,6 +385,8 @@ static void *get_unlocked_mapping_entry(struct address_space *mapping,
*slotp = slot;
return entry;
}
+
+ wq = dax_entry_waitqueue(mapping, index, entry, &ewait.key);
prepare_to_wait_exclusive(wq, &ewait.wait,
TASK_UNINTERRUPTIBLE);
spin_unlock_irq(&mapping->tree_lock);
@@ -448,9 +460,12 @@ restart:
}
void dax_wake_mapping_entry_waiter(struct address_space *mapping,
- pgoff_t index, bool wake_all)
+ pgoff_t index, void *entry, bool wake_all)
{
- wait_queue_head_t *wq = dax_entry_waitqueue(mapping, index);
+ struct exceptional_entry_key key;
+ wait_queue_head_t *wq;
+
+ wq = dax_entry_waitqueue(mapping, index, entry, &key);
/*
* Checking for locked entry and prepare_to_wait_exclusive() happens
@@ -458,13 +473,8 @@ void dax_wake_mapping_entry_waiter(struct address_space *mapping,
* So at this point all tasks that could have seen our entry locked
* must be in the waitqueue and the following check will see them.
*/
- if (waitqueue_active(wq)) {
- struct exceptional_entry_key key;
-
- key.mapping = mapping;
- key.index = index;
+ if (waitqueue_active(wq))
__wake_up(wq, TASK_NORMAL, wake_all ? 0 : 1, &key);
- }
}
void dax_unlock_mapping_entry(struct address_space *mapping, pgoff_t index)
@@ -480,7 +490,7 @@ void dax_unlock_mapping_entry(struct address_space *mapping, pgoff_t index)
}
unlock_slot(mapping, slot);
spin_unlock_irq(&mapping->tree_lock);
- dax_wake_mapping_entry_waiter(mapping, index, false);
+ dax_wake_mapping_entry_waiter(mapping, index, entry, false);
}
static void put_locked_mapping_entry(struct address_space *mapping,
@@ -505,7 +515,7 @@ static void put_unlocked_mapping_entry(struct address_space *mapping,
return;
/* We have to wake up next waiter for the radix tree entry lock */
- dax_wake_mapping_entry_waiter(mapping, index, false);
+ dax_wake_mapping_entry_waiter(mapping, index, entry, false);
}
/*
@@ -532,7 +542,7 @@ int dax_delete_mapping_entry(struct address_space *mapping, pgoff_t index)
radix_tree_delete(&mapping->page_tree, index);
mapping->nrexceptional--;
spin_unlock_irq(&mapping->tree_lock);
- dax_wake_mapping_entry_waiter(mapping, index, true);
+ dax_wake_mapping_entry_waiter(mapping, index, entry, true);
return 1;
}
diff --git a/include/linux/dax.h b/include/linux/dax.h
index add6c4b..a41a747 100644
--- a/include/linux/dax.h
+++ b/include/linux/dax.h
@@ -22,7 +22,7 @@ int iomap_dax_fault(struct vm_area_struct *vma, struct vm_fault *vmf,
int dax_fault(struct vm_area_struct *, struct vm_fault *, get_block_t);
int dax_delete_mapping_entry(struct address_space *mapping, pgoff_t index);
void dax_wake_mapping_entry_waiter(struct address_space *mapping,
- pgoff_t index, bool wake_all);
+ pgoff_t index, void *entry, bool wake_all);
#ifdef CONFIG_FS_DAX
struct page *read_dax_sector(struct block_device *bdev, sector_t n);
diff --git a/mm/filemap.c b/mm/filemap.c
index 2f1175e..a596462 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -617,7 +617,7 @@ static int page_cache_tree_insert(struct address_space *mapping,
if (node)
workingset_node_pages_dec(node);
/* Wakeup waiters for exceptional entry lock */
- dax_wake_mapping_entry_waiter(mapping, page->index,
+ dax_wake_mapping_entry_waiter(mapping, page->index, p,
false);
}
}
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Christoph Hellwig <hch@lst.de> |
|---|---|
| Date | 2016-10-10 17:50 +0200 |
| Subject | Re: [PATCH v5 09/17] dax: coordinate locking for offsets in PMD range |
| Message-ID | <sqKZX-2ZY-1@gated-at.bofh.it> |
| In reply to | #1497544 |
Looks fine, Reviewed-by: Christoph Hellwig <hch@lst.de>
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | linux.kernel
csiph-web