Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1366853 > unrolled thread

[PATCH v2 0/5] dax: handling of media errors

Started byVishal Verma <vishal.l.verma@intel.com>
First post2016-03-30 04:10 +0200
Last post2016-03-30 09:00 +0200
Articles 10 — 4 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH v2 0/5] dax: handling of media errors Vishal Verma <vishal.l.verma@intel.com> - 2016-03-30 04:10 +0200
    [PATCH v2 3/5] dax: enable dax in the presence of known media errors (badblocks) Vishal Verma <vishal.l.verma@intel.com> - 2016-03-30 04:10 +0200
    [PATCH v2 4/5] dax: use sb_issue_zerout instead of calling dax_clear_sectors Vishal Verma <vishal.l.verma@intel.com> - 2016-03-30 04:10 +0200
    [PATCH v2 1/5] block, dax: pass blk_dax_ctl through to drivers Vishal Verma <vishal.l.verma@intel.com> - 2016-03-30 04:10 +0200
      Re: [PATCH v2 1/5] block, dax: pass blk_dax_ctl through to drivers kbuild test robot <lkp@intel.com> - 2016-03-30 06:30 +0200
    [PATCH v2 2/5] dax: fallback from pmd to pte on error Vishal Verma <vishal.l.verma@intel.com> - 2016-03-30 04:10 +0200
    [PATCH v2 5/5] dax: handle media errors in dax_do_io Vishal Verma <vishal.l.verma@intel.com> - 2016-03-30 04:10 +0200
      Re: [PATCH v2 5/5] dax: handle media errors in dax_do_io Christoph Hellwig <hch@infradead.org> - 2016-03-30 08:40 +0200
        Re: [PATCH v2 5/5] dax: handle media errors in dax_do_io Vishal Verma <vishal@kernel.org> - 2016-03-30 09:00 +0200
          Re: [PATCH v2 5/5] dax: handle media errors in dax_do_io Christoph Hellwig <hch@infradead.org> - 2016-03-30 09:00 +0200

#1366853 — [PATCH v2 0/5] dax: handling of media errors

FromVishal Verma <vishal.l.verma@intel.com>
Date2016-03-30 04:10 +0200
Subject[PATCH v2 0/5] dax: handling of media errors
Message-ID<ridK1-6VB-1@gated-at.bofh.it>
Until now, dax has been disabled if media errors were found on
any device. This series attempts to address that.

The first three patches from Dan re-enable dax even when media
errors are present.

The fourth patch from Matthew removes the
zeroout path from dax entirely, making zeroout operations always
go through the driver (The motivation is that if a backing device
has media errors, and we create a sparse file on it, we don't
want the initial zeroing to happen via dax, we want to give the
block driver a chance to clear the errors).

One pending item is addressing clear_pmem usages in dax.c. clear_pmem is
'unsafe' as it attempts to simply memcpy, and does not go through the driver.
We have a few options of solving this:
 1. Remove all usages of clear_pmem that are not sector-aligned. For the
    ones that are aligned, replace them with a bio submission that goes
    through the driver to clear errors.
 2. Export from the block layer, either an API to zero sub-sector ranges,
    or in general, clear errors in a range. The dax attempts to clear_pmem
    can then use either of these and not be hit be media errors.

I'll send out a v3 with a crack at option 1, but I wanted to get these
changes (especially the ones in xfs) out for review.

The fifth patch changes all the callers of dax_do_io to check for
EIO, and fallback to direct_IO as needed. This forces the IO to
go through the block driver, and can attempt to clear the error.


v2:
 - Use blockdev_issue_zeroout in xfs instead of sb_issue_zeroout (Christoph)
 - Un-wrapper-ize dax_do_io and leave the fallback to direct_IO to callers
   (Christoph)
 - Rebase to v4.6-rc1 (fixup a couple of conflicts in ext4 and xfs)


Dan Williams (3):
  block, dax: pass blk_dax_ctl through to drivers
  dax: fallback from pmd to pte on error
  dax: enable dax in the presence of known media errors (badblocks)

Vishal Verma (2):
  dax: use sb_issue_zerout instead of calling dax_clear_sectors
  dax: handle media errors in dax_do_io

 arch/powerpc/sysdev/axonram.c | 10 +++++-----
 block/ioctl.c                 |  9 ---------
 drivers/block/brd.c           |  9 +++++----
 drivers/nvdimm/pmem.c         | 17 +++++++++++++----
 drivers/s390/block/dcssblk.c  | 12 ++++++------
 fs/block_dev.c                | 19 +++++++++++++++----
 fs/dax.c                      | 36 ++----------------------------------
 fs/ext2/inode.c               | 29 ++++++++++++++++++-----------
 fs/ext4/indirect.c            | 18 +++++++++++++-----
 fs/ext4/inode.c               | 21 ++++++++++++++-------
 fs/xfs/xfs_aops.c             | 14 ++++++++++++--
 fs/xfs/xfs_bmap_util.c        | 15 ++++-----------
 include/linux/blkdev.h        |  3 +--
 include/linux/dax.h           |  1 -
 14 files changed, 108 insertions(+), 105 deletions(-)

-- 
2.5.5

[toc] | [next] | [standalone]


#1366856 — [PATCH v2 3/5] dax: enable dax in the presence of known media errors (badblocks)

FromVishal Verma <vishal.l.verma@intel.com>
Date2016-03-30 04:10 +0200
Subject[PATCH v2 3/5] dax: enable dax in the presence of known media errors (badblocks)
Message-ID<ridK1-6VB-7@gated-at.bofh.it>
In reply to#1366853
From: Dan Williams <dan.j.williams@intel.com>

1/ If a mapping overlaps a bad sector fail the request.

2/ Do not opportunistically report more dax-capable capacity than is
   requested when errors present.

[vishal: fix a conflict with system RAM collision patches]
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 block/ioctl.c         | 9 ---------
 drivers/nvdimm/pmem.c | 8 ++++++++
 2 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/block/ioctl.c b/block/ioctl.c
index d8996bb..cd7f392 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -423,15 +423,6 @@ bool blkdev_dax_capable(struct block_device *bdev)
 			|| (bdev->bd_part->nr_sects % (PAGE_SIZE / 512)))
 		return false;
 
-	/*
-	 * If the device has known bad blocks, force all I/O through the
-	 * driver / page cache.
-	 *
-	 * TODO: support finer grained dax error handling
-	 */
-	if (disk->bb && disk->bb->count)
-		return false;
-
 	return true;
 }
 #endif
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c
index da10554..eac5f93 100644
--- a/drivers/nvdimm/pmem.c
+++ b/drivers/nvdimm/pmem.c
@@ -174,9 +174,17 @@ static long pmem_direct_access(struct block_device *bdev,
 	struct pmem_device *pmem = bdev->bd_disk->private_data;
 	resource_size_t offset = sector * 512 + pmem->data_offset;
 
+	if (unlikely(is_bad_pmem(&pmem->bb, sector, dax->size)))
+		return -EIO;
 	dax->addr = pmem->virt_addr + offset;
 	dax->pfn = phys_to_pfn_t(pmem->phys_addr + offset, pmem->pfn_flags);
 
+	/*
+	 * If badblocks are present, limit known good range to the
+	 * requested range.
+	 */
+	if (unlikely(pmem->bb.count))
+		return dax->size;
 	return pmem->size - pmem->pfn_pad - offset;
 }
 
-- 
2.5.5

[toc] | [prev] | [next] | [standalone]


#1366858 — [PATCH v2 4/5] dax: use sb_issue_zerout instead of calling dax_clear_sectors

FromVishal Verma <vishal.l.verma@intel.com>
Date2016-03-30 04:10 +0200
Subject[PATCH v2 4/5] dax: use sb_issue_zerout instead of calling dax_clear_sectors
Message-ID<ridK1-6VB-11@gated-at.bofh.it>
In reply to#1366853
From: Matthew Wilcox <matthew.r.wilcox@intel.com>

dax_clear_sectors() cannot handle poisoned blocks.  These must be
zeroed using the BIO interface instead.  Convert ext2 and XFS to use
only sb_issue_zerout().

Signed-off-by: Matthew Wilcox <matthew.r.wilcox@intel.com>
[vishal: Also remove the dax_clear_sectors function entirely]
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
---
 fs/dax.c               | 32 --------------------------------
 fs/ext2/inode.c        |  7 +++----
 fs/xfs/xfs_bmap_util.c | 15 ++++-----------
 include/linux/dax.h    |  1 -
 4 files changed, 7 insertions(+), 48 deletions(-)

diff --git a/fs/dax.c b/fs/dax.c
index ec6417b..f4ac5f2 100644
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -78,38 +78,6 @@ struct page *read_dax_sector(struct block_device *bdev, sector_t n)
 	return page;
 }
 
-/*
- * dax_clear_sectors() is called from within transaction context from XFS,
- * and hence this means the stack from this point must follow GFP_NOFS
- * semantics for all operations.
- */
-int dax_clear_sectors(struct block_device *bdev, sector_t _sector, long _size)
-{
-	struct blk_dax_ctl dax = {
-		.sector = _sector,
-		.size = _size,
-	};
-
-	might_sleep();
-	do {
-		long count, sz;
-
-		count = dax_map_atomic(bdev, &dax);
-		if (count < 0)
-			return count;
-		sz = min_t(long, count, SZ_128K);
-		clear_pmem(dax.addr, sz);
-		dax.size -= sz;
-		dax.sector += sz / 512;
-		dax_unmap_atomic(bdev, &dax);
-		cond_resched();
-	} while (dax.size);
-
-	wmb_pmem();
-	return 0;
-}
-EXPORT_SYMBOL_GPL(dax_clear_sectors);
-
 /* the clear_pmem() calls are ordered by a wmb_pmem() in the caller */
 static void dax_new_buf(void __pmem *addr, unsigned size, unsigned first,
 		loff_t pos, loff_t end)
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index 6bd58e6..824f249 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -26,6 +26,7 @@
 #include <linux/highuid.h>
 #include <linux/pagemap.h>
 #include <linux/dax.h>
+#include <linux/blkdev.h>
 #include <linux/quotaops.h>
 #include <linux/writeback.h>
 #include <linux/buffer_head.h>
@@ -737,10 +738,8 @@ static int ext2_get_blocks(struct inode *inode,
 		 * so that it's not found by another thread before it's
 		 * initialised
 		 */
-		err = dax_clear_sectors(inode->i_sb->s_bdev,
-				le32_to_cpu(chain[depth-1].key) <<
-				(inode->i_blkbits - 9),
-				1 << inode->i_blkbits);
+		err = sb_issue_zeroout(inode->i_sb,
+				le32_to_cpu(chain[depth-1].key), 1, GFP_NOFS);
 		if (err) {
 			mutex_unlock(&ei->truncate_mutex);
 			goto cleanup;
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index a32c1dc..5b4351a 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -72,18 +72,11 @@ xfs_zero_extent(
 	struct xfs_mount *mp = ip->i_mount;
 	xfs_daddr_t	sector = xfs_fsb_to_db(ip, start_fsb);
 	sector_t	block = XFS_BB_TO_FSBT(mp, sector);
-	ssize_t		size = XFS_FSB_TO_B(mp, count_fsb);
-
-	if (IS_DAX(VFS_I(ip)))
-		return dax_clear_sectors(xfs_find_bdev_for_inode(VFS_I(ip)),
-				sector, size);
-
-	/*
-	 * let the block layer decide on the fastest method of
-	 * implementing the zeroing.
-	 */
-	return sb_issue_zeroout(mp->m_super, block, count_fsb, GFP_NOFS);
 
+	return blkdev_issue_zeroout(xfs_find_bdev_for_inode(VFS_I(ip)),
+		block << (mp->m_super->s_blocksize_bits - 9),
+		count_fsb << (mp->m_super->s_blocksize_bits - 9),
+		GFP_NOFS, true);
 }
 
 /*
diff --git a/include/linux/dax.h b/include/linux/dax.h
index 636dd59..933198a 100644
--- a/include/linux/dax.h
+++ b/include/linux/dax.h
@@ -7,7 +7,6 @@
 
 ssize_t dax_do_io(struct kiocb *, struct inode *, struct iov_iter *, loff_t,
 		  get_block_t, dio_iodone_t, int flags);
-int dax_clear_sectors(struct block_device *bdev, sector_t _sector, long _size);
 int dax_zero_page_range(struct inode *, loff_t from, unsigned len, get_block_t);
 int dax_truncate_page(struct inode *, loff_t from, get_block_t);
 int dax_fault(struct vm_area_struct *, struct vm_fault *, get_block_t,
-- 
2.5.5

[toc] | [prev] | [next] | [standalone]


#1366859 — [PATCH v2 1/5] block, dax: pass blk_dax_ctl through to drivers

FromVishal Verma <vishal.l.verma@intel.com>
Date2016-03-30 04:10 +0200
Subject[PATCH v2 1/5] block, dax: pass blk_dax_ctl through to drivers
Message-ID<ridK1-6VB-15@gated-at.bofh.it>
In reply to#1366853
From: Dan Williams <dan.j.williams@intel.com>

This is in preparation for doing badblocks checking against the
requested sector range in the driver.  Currently we opportunistically
return as much data that can be "dax'd" starting at the given sector.
When errors are present we want to limit that range to the first
encountered error, or fail the dax request if the range encompasses an
error.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 arch/powerpc/sysdev/axonram.c | 10 +++++-----
 drivers/block/brd.c           |  9 +++++----
 drivers/nvdimm/pmem.c         |  9 +++++----
 drivers/s390/block/dcssblk.c  | 12 ++++++------
 fs/block_dev.c                |  2 +-
 include/linux/blkdev.h        |  3 +--
 6 files changed, 23 insertions(+), 22 deletions(-)

diff --git a/arch/powerpc/sysdev/axonram.c b/arch/powerpc/sysdev/axonram.c
index 0d112b9..d85673f 100644
--- a/arch/powerpc/sysdev/axonram.c
+++ b/arch/powerpc/sysdev/axonram.c
@@ -139,17 +139,17 @@ axon_ram_make_request(struct request_queue *queue, struct bio *bio)
 
 /**
  * axon_ram_direct_access - direct_access() method for block device
- * @device, @sector, @data: see block_device_operations method
+ * @dax: see block_device_operations method
  */
 static long
-axon_ram_direct_access(struct block_device *device, sector_t sector,
-		       void __pmem **kaddr, pfn_t *pfn)
+axon_ram_direct_access(struct block_device *device, struct blk_dax_ctl *dax)
 {
+	sector_t sector = get_start_sect(device) + dax->sector;
 	struct axon_ram_bank *bank = device->bd_disk->private_data;
 	loff_t offset = (loff_t)sector << AXON_RAM_SECTOR_SHIFT;
 
-	*kaddr = (void __pmem __force *) bank->io_addr + offset;
-	*pfn = phys_to_pfn_t(bank->ph_addr + offset, PFN_DEV);
+	dax->addr = (void __pmem __force *) bank->io_addr + offset;
+	dax->pfn = phys_to_pfn_t(bank->ph_addr + offset, PFN_DEV);
 	return bank->size - offset;
 }
 
diff --git a/drivers/block/brd.c b/drivers/block/brd.c
index f7ecc28..e3e4780 100644
--- a/drivers/block/brd.c
+++ b/drivers/block/brd.c
@@ -380,9 +380,10 @@ static int brd_rw_page(struct block_device *bdev, sector_t sector,
 }
 
 #ifdef CONFIG_BLK_DEV_RAM_DAX
-static long brd_direct_access(struct block_device *bdev, sector_t sector,
-			void __pmem **kaddr, pfn_t *pfn)
+static long brd_direct_access(struct block_device *bdev,
+		struct blk_dax_ctl *dax)
 {
+	sector_t sector = get_start_sect(bdev) + dax->sector;
 	struct brd_device *brd = bdev->bd_disk->private_data;
 	struct page *page;
 
@@ -391,8 +392,8 @@ static long brd_direct_access(struct block_device *bdev, sector_t sector,
 	page = brd_insert_page(brd, sector);
 	if (!page)
 		return -ENOSPC;
-	*kaddr = (void __pmem *)page_address(page);
-	*pfn = page_to_pfn_t(page);
+	dax->addr = (void __pmem *)page_address(page);
+	dax->pfn = page_to_pfn_t(page);
 
 	return PAGE_SIZE;
 }
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c
index ca5721c..da10554 100644
--- a/drivers/nvdimm/pmem.c
+++ b/drivers/nvdimm/pmem.c
@@ -167,14 +167,15 @@ static int pmem_rw_page(struct block_device *bdev, sector_t sector,
 	return rc;
 }
 
-static long pmem_direct_access(struct block_device *bdev, sector_t sector,
-		      void __pmem **kaddr, pfn_t *pfn)
+static long pmem_direct_access(struct block_device *bdev,
+		struct blk_dax_ctl *dax)
 {
+	sector_t sector = get_start_sect(bdev) + dax->sector;
 	struct pmem_device *pmem = bdev->bd_disk->private_data;
 	resource_size_t offset = sector * 512 + pmem->data_offset;
 
-	*kaddr = pmem->virt_addr + offset;
-	*pfn = phys_to_pfn_t(pmem->phys_addr + offset, pmem->pfn_flags);
+	dax->addr = pmem->virt_addr + offset;
+	dax->pfn = phys_to_pfn_t(pmem->phys_addr + offset, pmem->pfn_flags);
 
 	return pmem->size - pmem->pfn_pad - offset;
 }
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
index 1bce9cf..5719c30 100644
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
@@ -30,8 +30,8 @@ static int dcssblk_open(struct block_device *bdev, fmode_t mode);
 static void dcssblk_release(struct gendisk *disk, fmode_t mode);
 static blk_qc_t dcssblk_make_request(struct request_queue *q,
 						struct bio *bio);
-static long dcssblk_direct_access(struct block_device *bdev, sector_t secnum,
-			 void __pmem **kaddr, pfn_t *pfn);
+static long dcssblk_direct_access(struct block_device *bdev,
+		struct blk_dax_ctl *dax)
 
 static char dcssblk_segments[DCSSBLK_PARM_LEN] = "\0";
 
@@ -882,9 +882,9 @@ fail:
 }
 
 static long
-dcssblk_direct_access (struct block_device *bdev, sector_t secnum,
-			void __pmem **kaddr, pfn_t *pfn)
+dcssblk_direct_access(struct block_device *bdev, struct blk_dax_ctl *dax)
 {
+	sector_t secnum = get_start_sect(bdev) + dax->sector;
 	struct dcssblk_dev_info *dev_info;
 	unsigned long offset, dev_sz;
 
@@ -893,8 +893,8 @@ dcssblk_direct_access (struct block_device *bdev, sector_t secnum,
 		return -ENODEV;
 	dev_sz = dev_info->end - dev_info->start;
 	offset = secnum * 512;
-	*kaddr = (void __pmem *) (dev_info->start + offset);
-	*pfn = __pfn_to_pfn_t(PFN_DOWN(dev_info->start + offset), PFN_DEV);
+	dax->addr = (void __pmem *) (dev_info->start + offset);
+	dax->pfn = __pfn_to_pfn_t(PFN_DOWN(dev_info->start + offset), PFN_DEV);
 
 	return dev_sz - offset;
 }
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 3172c4e..c5837fa 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -488,7 +488,7 @@ long bdev_direct_access(struct block_device *bdev, struct blk_dax_ctl *dax)
 	sector += get_start_sect(bdev);
 	if (sector % (PAGE_SIZE / 512))
 		return -EINVAL;
-	avail = ops->direct_access(bdev, sector, &dax->addr, &dax->pfn);
+	avail = ops->direct_access(bdev, dax);
 	if (!avail)
 		return -ERANGE;
 	if (avail > 0 && avail & ~PAGE_MASK)
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 7e5d7e0..92f8a1f 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -1656,8 +1656,7 @@ struct block_device_operations {
 	int (*rw_page)(struct block_device *, sector_t, struct page *, int rw);
 	int (*ioctl) (struct block_device *, fmode_t, unsigned, unsigned long);
 	int (*compat_ioctl) (struct block_device *, fmode_t, unsigned, unsigned long);
-	long (*direct_access)(struct block_device *, sector_t, void __pmem **,
-			pfn_t *);
+	long (*direct_access)(struct block_device *, struct blk_dax_ctl *dax);
 	unsigned int (*check_events) (struct gendisk *disk,
 				      unsigned int clearing);
 	/* ->media_changed() is DEPRECATED, use ->check_events() instead */
-- 
2.5.5

[toc] | [prev] | [next] | [standalone]


#1366891 — Re: [PATCH v2 1/5] block, dax: pass blk_dax_ctl through to drivers

Fromkbuild test robot <lkp@intel.com>
Date2016-03-30 06:30 +0200
SubjectRe: [PATCH v2 1/5] block, dax: pass blk_dax_ctl through to drivers
Message-ID<rifVw-5u-13@gated-at.bofh.it>
In reply to#1366859

[Multipart message — attachments visible in raw view] — view raw

Hi Dan,

[auto build test ERROR on linux-nvdimm/libnvdimm-for-next]
[also build test ERROR on v4.6-rc1 next-20160329]
[cannot apply to xfs/for-next]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Vishal-Verma/dax-handling-of-media-errors/20160330-100409
base:   https://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm libnvdimm-for-next
config: s390-default_defconfig (attached as .config)
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=s390 

All error/warnings (new ones prefixed by >>):

   drivers/s390/block/dcssblk.c: In function 'dcssblk_direct_access':
>> drivers/s390/block/dcssblk.c:36:13: error: storage class specified for parameter 'dcssblk_segments'
    static char dcssblk_segments[DCSSBLK_PARM_LEN] = "\0";
                ^
>> drivers/s390/block/dcssblk.c:36:1: error: parameter 'dcssblk_segments' is initialized
    static char dcssblk_segments[DCSSBLK_PARM_LEN] = "\0";
    ^
>> drivers/s390/block/dcssblk.c:38:12: error: storage class specified for parameter 'dcssblk_major'
    static int dcssblk_major;
               ^
>> drivers/s390/block/dcssblk.c:39:45: error: storage class specified for parameter 'dcssblk_devops'
    static const struct block_device_operations dcssblk_devops = {
                                                ^
>> drivers/s390/block/dcssblk.c:39:21: error: parameter 'dcssblk_devops' is initialized
    static const struct block_device_operations dcssblk_devops = {
                        ^
>> drivers/s390/block/dcssblk.c:46:1: warning: empty declaration
    struct dcssblk_dev_info {
    ^
   drivers/s390/block/dcssblk.c:62:1: warning: empty declaration
    struct segment_info {
    ^
>> drivers/s390/block/dcssblk.c:70:16: error: storage class specified for parameter 'dcssblk_add_store'
    static ssize_t dcssblk_add_store(struct device * dev, struct device_attribute *attr, const char * buf,
                   ^
>> drivers/s390/block/dcssblk.c:72:16: error: storage class specified for parameter 'dcssblk_remove_store'
    static ssize_t dcssblk_remove_store(struct device * dev, struct device_attribute *attr, const char * buf,
                   ^
   In file included from include/linux/genhd.h:63:0,
                    from include/linux/blkdev.h:9,
                    from drivers/s390/block/dcssblk.c:16:
>> include/linux/device.h:575:26: error: storage class specified for parameter 'dev_attr_add'
     struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
                             ^
>> drivers/s390/block/dcssblk.c:75:8: note: in expansion of macro 'DEVICE_ATTR'
    static DEVICE_ATTR(add, S_IWUSR, NULL, dcssblk_add_store);
           ^
>> include/linux/device.h:575:9: error: parameter 'dev_attr_add' is initialized
     struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
            ^
>> drivers/s390/block/dcssblk.c:75:8: note: in expansion of macro 'DEVICE_ATTR'
    static DEVICE_ATTR(add, S_IWUSR, NULL, dcssblk_add_store);
           ^
>> include/linux/device.h:575:26: error: storage class specified for parameter 'dev_attr_remove'
     struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
                             ^
   drivers/s390/block/dcssblk.c:76:8: note: in expansion of macro 'DEVICE_ATTR'
    static DEVICE_ATTR(remove, S_IWUSR, NULL, dcssblk_remove_store);
           ^
>> include/linux/device.h:575:9: error: parameter 'dev_attr_remove' is initialized
     struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
            ^
   drivers/s390/block/dcssblk.c:76:8: note: in expansion of macro 'DEVICE_ATTR'
    static DEVICE_ATTR(remove, S_IWUSR, NULL, dcssblk_remove_store);
           ^
>> drivers/s390/block/dcssblk.c:78:23: error: storage class specified for parameter 'dcssblk_root_dev'
    static struct device *dcssblk_root_dev;
                          ^
   In file included from include/linux/module.h:9:0,
                    from drivers/s390/block/dcssblk.c:10:
>> drivers/s390/block/dcssblk.c:80:18: error: storage class specified for parameter 'dcssblk_devices'
    static LIST_HEAD(dcssblk_devices);
                     ^
   include/linux/list.h:23:19: note: in definition of macro 'LIST_HEAD'
     struct list_head name = LIST_HEAD_INIT(name)
                      ^
>> include/linux/list.h:23:9: error: parameter 'dcssblk_devices' is initialized
     struct list_head name = LIST_HEAD_INIT(name)
            ^
>> drivers/s390/block/dcssblk.c:80:8: note: in expansion of macro 'LIST_HEAD'
    static LIST_HEAD(dcssblk_devices);
           ^
>> drivers/s390/block/dcssblk.c:81:28: error: storage class specified for parameter 'dcssblk_devices_sem'
    static struct rw_semaphore dcssblk_devices_sem;
                               ^
>> drivers/s390/block/dcssblk.c:88:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
    {
    ^
   drivers/s390/block/dcssblk.c:109:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
    {
    ^
   drivers/s390/block/dcssblk.c:136:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
    {
    ^
   drivers/s390/block/dcssblk.c:154:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
    {
    ^
   drivers/s390/block/dcssblk.c:172:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
    {
    ^
   drivers/s390/block/dcssblk.c:189:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
    {
    ^
   drivers/s390/block/dcssblk.c:213:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
    {
    ^
   drivers/s390/block/dcssblk.c:279:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
    {
    ^
   drivers/s390/block/dcssblk.c:315:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
    {
    ^
   drivers/s390/block/dcssblk.c:324:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
    {
    ^
   In file included from include/linux/genhd.h:63:0,
                    from include/linux/blkdev.h:9,
                    from drivers/s390/block/dcssblk.c:16:

vim +/dcssblk_segments +36 drivers/s390/block/dcssblk.c

^1da177e Linus Torvalds  2005-04-16  23  
^1da177e Linus Torvalds  2005-04-16  24  #define DCSSBLK_NAME "dcssblk"
^1da177e Linus Torvalds  2005-04-16  25  #define DCSSBLK_MINORS_PER_DISK 1
^1da177e Linus Torvalds  2005-04-16  26  #define DCSSBLK_PARM_LEN 400
98df67b3 Kay Sievers     2008-12-25  27  #define DCSS_BUS_ID_SIZE 20
^1da177e Linus Torvalds  2005-04-16  28  
46d74326 Al Viro         2008-03-02 @29  static int dcssblk_open(struct block_device *bdev, fmode_t mode);
db2a144b Al Viro         2013-05-05 @30  static void dcssblk_release(struct gendisk *disk, fmode_t mode);
dece1635 Jens Axboe      2015-11-05  31  static blk_qc_t dcssblk_make_request(struct request_queue *q,
dece1635 Jens Axboe      2015-11-05  32  						struct bio *bio);
e3cb53fb Dan Williams    2016-03-29 @33  static long dcssblk_direct_access(struct block_device *bdev,
e3cb53fb Dan Williams    2016-03-29  34  		struct blk_dax_ctl *dax)
^1da177e Linus Torvalds  2005-04-16  35  
^1da177e Linus Torvalds  2005-04-16 @36  static char dcssblk_segments[DCSSBLK_PARM_LEN] = "\0";
^1da177e Linus Torvalds  2005-04-16  37  
^1da177e Linus Torvalds  2005-04-16 @38  static int dcssblk_major;
83d5cde4 Alexey Dobriyan 2009-09-21 @39  static const struct block_device_operations dcssblk_devops = {
^1da177e Linus Torvalds  2005-04-16  40  	.owner   	= THIS_MODULE,
46d74326 Al Viro         2008-03-02  41  	.open    	= dcssblk_open,
46d74326 Al Viro         2008-03-02  42  	.release 	= dcssblk_release,
420edbcc Carsten Otte    2005-06-23  43  	.direct_access 	= dcssblk_direct_access,
^1da177e Linus Torvalds  2005-04-16  44  };
^1da177e Linus Torvalds  2005-04-16  45  
b2300b9e Hongjie Yang    2008-10-10 @46  struct dcssblk_dev_info {
b2300b9e Hongjie Yang    2008-10-10  47  	struct list_head lh;
b2300b9e Hongjie Yang    2008-10-10  48  	struct device dev;
98df67b3 Kay Sievers     2008-12-25  49  	char segment_name[DCSS_BUS_ID_SIZE];
b2300b9e Hongjie Yang    2008-10-10  50  	atomic_t use_count;
b2300b9e Hongjie Yang    2008-10-10  51  	struct gendisk *gd;
b2300b9e Hongjie Yang    2008-10-10  52  	unsigned long start;
b2300b9e Hongjie Yang    2008-10-10  53  	unsigned long end;
b2300b9e Hongjie Yang    2008-10-10  54  	int segment_type;
b2300b9e Hongjie Yang    2008-10-10  55  	unsigned char save_pending;
b2300b9e Hongjie Yang    2008-10-10  56  	unsigned char is_shared;
b2300b9e Hongjie Yang    2008-10-10  57  	struct request_queue *dcssblk_queue;
b2300b9e Hongjie Yang    2008-10-10  58  	int num_of_segments;
b2300b9e Hongjie Yang    2008-10-10  59  	struct list_head seg_list;
b2300b9e Hongjie Yang    2008-10-10  60  };
b2300b9e Hongjie Yang    2008-10-10  61  
b2300b9e Hongjie Yang    2008-10-10  62  struct segment_info {
b2300b9e Hongjie Yang    2008-10-10  63  	struct list_head lh;
98df67b3 Kay Sievers     2008-12-25  64  	char segment_name[DCSS_BUS_ID_SIZE];
b2300b9e Hongjie Yang    2008-10-10  65  	unsigned long start;
b2300b9e Hongjie Yang    2008-10-10  66  	unsigned long end;
b2300b9e Hongjie Yang    2008-10-10  67  	int segment_type;
b2300b9e Hongjie Yang    2008-10-10  68  };
b2300b9e Hongjie Yang    2008-10-10  69  
e404e274 Yani Ioannou    2005-05-17 @70  static ssize_t dcssblk_add_store(struct device * dev, struct device_attribute *attr, const char * buf,
^1da177e Linus Torvalds  2005-04-16  71  				  size_t count);
e404e274 Yani Ioannou    2005-05-17 @72  static ssize_t dcssblk_remove_store(struct device * dev, struct device_attribute *attr, const char * buf,
^1da177e Linus Torvalds  2005-04-16  73  				  size_t count);
^1da177e Linus Torvalds  2005-04-16  74  
^1da177e Linus Torvalds  2005-04-16 @75  static DEVICE_ATTR(add, S_IWUSR, NULL, dcssblk_add_store);
^1da177e Linus Torvalds  2005-04-16 @76  static DEVICE_ATTR(remove, S_IWUSR, NULL, dcssblk_remove_store);
^1da177e Linus Torvalds  2005-04-16  77  
^1da177e Linus Torvalds  2005-04-16 @78  static struct device *dcssblk_root_dev;
^1da177e Linus Torvalds  2005-04-16  79  
c11ca97e Denis Cheng     2008-01-26 @80  static LIST_HEAD(dcssblk_devices);
^1da177e Linus Torvalds  2005-04-16 @81  static struct rw_semaphore dcssblk_devices_sem;
^1da177e Linus Torvalds  2005-04-16  82  
^1da177e Linus Torvalds  2005-04-16  83  /*
^1da177e Linus Torvalds  2005-04-16  84   * release function for segment device.
^1da177e Linus Torvalds  2005-04-16  85   */
^1da177e Linus Torvalds  2005-04-16  86  static void
^1da177e Linus Torvalds  2005-04-16  87  dcssblk_release_segment(struct device *dev)
^1da177e Linus Torvalds  2005-04-16 @88  {
b2300b9e Hongjie Yang    2008-10-10  89  	struct dcssblk_dev_info *dev_info;
b2300b9e Hongjie Yang    2008-10-10  90  	struct segment_info *entry, *temp;
b2300b9e Hongjie Yang    2008-10-10  91  

:::::: The code at line 36 was first introduced by commit
:::::: 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 Linux-2.6.12-rc2

:::::: TO: Linus Torvalds <torvalds@ppc970.osdl.org>
:::::: CC: Linus Torvalds <torvalds@ppc970.osdl.org>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[toc] | [prev] | [next] | [standalone]


#1366860 — [PATCH v2 2/5] dax: fallback from pmd to pte on error

FromVishal Verma <vishal.l.verma@intel.com>
Date2016-03-30 04:10 +0200
Subject[PATCH v2 2/5] dax: fallback from pmd to pte on error
Message-ID<ridK1-6VB-13@gated-at.bofh.it>
In reply to#1366853
From: Dan Williams <dan.j.williams@intel.com>

In preparation for consulting a badblocks list in pmem_direct_access(),
teach dax_pmd_fault() to fallback rather than fail immediately upon
encountering an error.  The thought being that reducing the span of the
dax request may avoid the error region.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 fs/dax.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/fs/dax.c b/fs/dax.c
index 90322eb..ec6417b 100644
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -945,8 +945,8 @@ int __dax_pmd_fault(struct vm_area_struct *vma, unsigned long address,
 		long length = dax_map_atomic(bdev, &dax);
 
 		if (length < 0) {
-			result = VM_FAULT_SIGBUS;
-			goto out;
+			dax_pmd_dbg(&bh, address, "dax-error fallback");
+			goto fallback;
 		}
 		if (length < PMD_SIZE) {
 			dax_pmd_dbg(&bh, address, "dax-length too small");
-- 
2.5.5

[toc] | [prev] | [next] | [standalone]


#1366861 — [PATCH v2 5/5] dax: handle media errors in dax_do_io

FromVishal Verma <vishal.l.verma@intel.com>
Date2016-03-30 04:10 +0200
Subject[PATCH v2 5/5] dax: handle media errors in dax_do_io
Message-ID<ridK2-6VB-17@gated-at.bofh.it>
In reply to#1366853
dax_do_io (called for read() or write() for a dax file system) may fail
in the presence of bad blocks or media errors. Since we expect that a
write should clear media errors on nvdimms, make dax_do_io fall back to
the direct_IO path, which will send down a bio to the driver, which can
then attempt to clear the error.

Cc: Matthew Wilcox <matthew.r.wilcox@intel.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Ross Zwisler <ross.zwisler@linux.intel.com>
Cc: Dave Chinner <david@fromorbit.com>
Cc: Jan Kara <jack@suse.cz>
Cc: Jens Axboe <axboe@fb.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
---
 fs/block_dev.c     | 17 ++++++++++++++---
 fs/ext2/inode.c    | 22 +++++++++++++++-------
 fs/ext4/indirect.c | 18 +++++++++++++-----
 fs/ext4/inode.c    | 21 ++++++++++++++-------
 fs/xfs/xfs_aops.c  | 14 ++++++++++++--
 5 files changed, 68 insertions(+), 24 deletions(-)

diff --git a/fs/block_dev.c b/fs/block_dev.c
index c5837fa..d6113b9 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -166,13 +166,24 @@ blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, loff_t offset)
 {
 	struct file *file = iocb->ki_filp;
 	struct inode *inode = bdev_file_inode(file);
+	ssize_t ret, ret_saved = 0;
 
-	if (IS_DAX(inode))
-		return dax_do_io(iocb, inode, iter, offset, blkdev_get_block,
+	if (IS_DAX(inode)) {
+		ret = dax_do_io(iocb, inode, iter, offset, blkdev_get_block,
 				NULL, DIO_SKIP_DIO_COUNT);
-	return __blockdev_direct_IO(iocb, inode, I_BDEV(inode), iter, offset,
+		if (ret == -EIO && (iov_iter_rw(iter) == WRITE))
+			ret_saved = ret;
+		else
+			return ret;
+	}
+
+	ret = __blockdev_direct_IO(iocb, inode, I_BDEV(inode), iter, offset,
 				    blkdev_get_block, NULL, NULL,
 				    DIO_SKIP_DIO_COUNT);
+	if (ret < 0 && ret_saved)
+		return ret_saved;
+
+	return ret;
 }
 
 int __sync_blockdev(struct block_device *bdev, int wait)
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index 824f249..64792c6 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -859,14 +859,22 @@ ext2_direct_IO(struct kiocb *iocb, struct iov_iter *iter, loff_t offset)
 	struct address_space *mapping = file->f_mapping;
 	struct inode *inode = mapping->host;
 	size_t count = iov_iter_count(iter);
-	ssize_t ret;
+	ssize_t ret, ret_saved = 0;
 
-	if (IS_DAX(inode))
-		ret = dax_do_io(iocb, inode, iter, offset, ext2_get_block, NULL,
-				DIO_LOCKING);
-	else
-		ret = blockdev_direct_IO(iocb, inode, iter, offset,
-					 ext2_get_block);
+	if (IS_DAX(inode)) {
+		ret = dax_do_io(iocb, inode, iter, offset, ext2_get_block,
+				NULL, DIO_LOCKING | DIO_SKIP_HOLES);
+		if (ret == -EIO && iov_iter_rw(iter) == WRITE)
+			ret_saved = ret;
+		else
+			goto out;
+	}
+
+	ret = blockdev_direct_IO(iocb, inode, iter, offset, ext2_get_block);
+	if (ret < 0 && ret_saved)
+		ret = ret_saved;
+
+ out:
 	if (ret < 0 && iov_iter_rw(iter) == WRITE)
 		ext2_write_failed(mapping, offset + count);
 	return ret;
diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
index 3027fa6..798f341 100644
--- a/fs/ext4/indirect.c
+++ b/fs/ext4/indirect.c
@@ -716,14 +716,22 @@ retry:
 						   NULL, NULL, 0);
 		inode_dio_end(inode);
 	} else {
+		ssize_t ret_saved = 0;
+
 locked:
-		if (IS_DAX(inode))
+		if (IS_DAX(inode)) {
 			ret = dax_do_io(iocb, inode, iter, offset,
 					ext4_dio_get_block, NULL, DIO_LOCKING);
-		else
-			ret = blockdev_direct_IO(iocb, inode, iter, offset,
-						 ext4_dio_get_block);
-
+			if (ret == -EIO && iov_iter_rw(iter) == WRITE)
+				ret_saved = ret;
+			else
+				goto skip_dio;
+		}
+		ret = blockdev_direct_IO(iocb, inode, iter, offset,
+					 ext4_get_block);
+		if (ret < 0 && ret_saved)
+			ret = ret_saved;
+skip_dio:
 		if (unlikely(iov_iter_rw(iter) == WRITE && ret < 0)) {
 			loff_t isize = i_size_read(inode);
 			loff_t end = offset + count;
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index dab84a2..27f07c2 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -3341,7 +3341,7 @@ static ssize_t ext4_ext_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
 {
 	struct file *file = iocb->ki_filp;
 	struct inode *inode = file->f_mapping->host;
-	ssize_t ret;
+	ssize_t ret, ret_saved = 0;
 	size_t count = iov_iter_count(iter);
 	int overwrite = 0;
 	get_block_t *get_block_func = NULL;
@@ -3401,15 +3401,22 @@ static ssize_t ext4_ext_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
 #ifdef CONFIG_EXT4_FS_ENCRYPTION
 	BUG_ON(ext4_encrypted_inode(inode) && S_ISREG(inode->i_mode));
 #endif
-	if (IS_DAX(inode))
+	if (IS_DAX(inode)) {
 		ret = dax_do_io(iocb, inode, iter, offset, get_block_func,
 				ext4_end_io_dio, dio_flags);
-	else
-		ret = __blockdev_direct_IO(iocb, inode,
-					   inode->i_sb->s_bdev, iter, offset,
-					   get_block_func,
-					   ext4_end_io_dio, NULL, dio_flags);
+		if (ret == -EIO && iov_iter_rw(iter) == WRITE)
+			ret_saved = ret;
+		else
+			goto skip_dio;
+	}
 
+	ret = __blockdev_direct_IO(iocb, inode,
+				   inode->i_sb->s_bdev, iter, offset,
+				   get_block_func,
+				   ext4_end_io_dio, NULL, dio_flags);
+	if (ret < 0 && ret_saved)
+		ret = ret_saved;
+ skip_dio:
 	if (ret > 0 && !overwrite && ext4_test_inode_state(inode,
 						EXT4_STATE_DIO_UNWRITTEN)) {
 		int err;
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index d445a64..7cfcf86 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -1413,6 +1413,7 @@ xfs_vm_direct_IO(
 	dio_iodone_t		*endio = NULL;
 	int			flags = 0;
 	struct block_device	*bdev;
+	ssize_t 		ret, ret_saved = 0;
 
 	if (iov_iter_rw(iter) == WRITE) {
 		endio = xfs_end_io_direct_write;
@@ -1420,13 +1421,22 @@ xfs_vm_direct_IO(
 	}
 
 	if (IS_DAX(inode)) {
-		return dax_do_io(iocb, inode, iter, offset,
+		ret = dax_do_io(iocb, inode, iter, offset,
 				 xfs_get_blocks_direct, endio, 0);
+		if (ret == -EIO && iov_iter_rw(iter) == WRITE)
+			ret_saved = ret;
+		else
+			return ret;
 	}
 
 	bdev = xfs_find_bdev_for_inode(inode);
-	return  __blockdev_direct_IO(iocb, inode, bdev, iter, offset,
+	ret = __blockdev_direct_IO(iocb, inode, bdev, iter, offset,
 			xfs_get_blocks_direct, endio, NULL, flags);
+
+	if (ret < 0 && ret_saved)
+		ret = ret_saved;
+
+	return ret;
 }
 
 /*
-- 
2.5.5

[toc] | [prev] | [next] | [standalone]


#1366910 — Re: [PATCH v2 5/5] dax: handle media errors in dax_do_io

FromChristoph Hellwig <hch@infradead.org>
Date2016-03-30 08:40 +0200
SubjectRe: [PATCH v2 5/5] dax: handle media errors in dax_do_io
Message-ID<rihXk-1pR-9@gated-at.bofh.it>
In reply to#1366861
Hi Vishal,

still NAK to calling the direct I/O code directly from the dax code.

[toc] | [prev] | [next] | [standalone]


#1366924 — Re: [PATCH v2 5/5] dax: handle media errors in dax_do_io

FromVishal Verma <vishal@kernel.org>
Date2016-03-30 09:00 +0200
SubjectRe: [PATCH v2 5/5] dax: handle media errors in dax_do_io
Message-ID<riigF-1wq-7@gated-at.bofh.it>
In reply to#1366910
On Tue, 2016-03-29 at 23:34 -0700, Christoph Hellwig wrote:
> Hi Vishal,
> 
> still NAK to calling the direct I/O code directly from the dax code.

Hm, I thought this was what you meant -- do the fallback/retry attempts
at the callers of dax_do_io instead of the new dax wrapper function..
Did I misunderstand you?

[toc] | [prev] | [next] | [standalone]


#1366926 — Re: [PATCH v2 5/5] dax: handle media errors in dax_do_io

FromChristoph Hellwig <hch@infradead.org>
Date2016-03-30 09:00 +0200
SubjectRe: [PATCH v2 5/5] dax: handle media errors in dax_do_io
Message-ID<riigG-1wq-15@gated-at.bofh.it>
In reply to#1366924
On Wed, Mar 30, 2016 at 12:54:37AM -0600, Vishal Verma wrote:
> On Tue, 2016-03-29 at 23:34 -0700, Christoph Hellwig wrote:
> > Hi Vishal,
> > 
> > still NAK to calling the direct I/O code directly from the dax code.
> 
> Hm, I thought this was what you meant -- do the fallback/retry attempts
> at the callers of dax_do_io instead of the new dax wrapper function..
> Did I misunderstand you?

Sorry, it is.  I misread fs/block_dev.c as fs/dax.c before my first
coffee this morning.  I'll properly review the series in the afternoon..

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web