From: Shiyang Ruan <ruansy.fnst@cn.fujitsu.com> To: <linux-kernel@vger.kernel.org>, <linux-xfs@vger.kernel.org>, <linux-nvdimm@lists.01.org>, <linux-mm@kvack.org> Cc: linux-fsdevel@vger.kernel.org, linux-raid@vger.kernel.org, darrick.wong@oracle.com, david@fromorbit.com, hch@lst.de, song@kernel.org, rgoldwyn@suse.de, qi.fuli@fujitsu.com, y-goto@fujitsu.com Subject: [RFC PATCH v2 2/6] blk: introduce ->block_lost() to handle memory-failure Date: Mon, 23 Nov 2020 08:41:12 +0800 [thread overview] Message-ID: <20201123004116.2453-3-ruansy.fnst@cn.fujitsu.com> (raw) In-Reply-To: <20201123004116.2453-1-ruansy.fnst@cn.fujitsu.com> In fsdax mode, the memory failure happens on block device. So, it is needed to introduce an interface for block devices. Each kind of block device can handle the memory failure in ther own ways. Usually, a block device is used directly to mkfs on it. The filesystem on it is easily to obtain by 'get_super()'. The block device can also be divided into several partitions, or used as a target by mapped device. It is hard to get filesystem's superblock in this two ways. So, add 'bdget_disk_sector()' to get the block device of a partition where the broken sector located in. And add 'bd_disk_holder_block_lost()' iterate the mapped devices on it. Signed-off-by: Shiyang Ruan <ruansy.fnst@cn.fujitsu.com> --- block/genhd.c | 12 ++++++++++++ drivers/nvdimm/pmem.c | 27 +++++++++++++++++++++++++++ fs/block_dev.c | 23 +++++++++++++++++++++++ include/linux/blkdev.h | 2 ++ include/linux/genhd.h | 9 +++++++++ 5 files changed, 73 insertions(+) diff --git a/block/genhd.c b/block/genhd.c index 0a273211fec2..2c7304f123fa 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -1055,6 +1055,18 @@ struct block_device *bdget_disk(struct gendisk *disk, int partno) } EXPORT_SYMBOL(bdget_disk); +struct block_device *bdget_disk_sector(struct gendisk *disk, sector_t sector) +{ + struct block_device *bdev = NULL; + struct hd_struct *part = disk_map_sector_rcu(disk, sector); + + if (part) + bdev = bdget_part(part); + + return bdev; +} +EXPORT_SYMBOL(bdget_disk_sector); + /* * print a full list of all partitions - intended for places where the root * filesystem can't be mounted and thus to give the victim some idea of what diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index 875076b0ea6c..d75a3f370f3c 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c @@ -253,6 +253,32 @@ static int pmem_rw_page(struct block_device *bdev, sector_t sector, return blk_status_to_errno(rc); } +int pmem_block_lost(struct gendisk *disk, struct block_device *bdev, + loff_t disk_offset, void *data) +{ + struct super_block *sb; + sector_t bdev_sector, disk_sector = disk_offset >> SECTOR_SHIFT; + int rc = 0; + + bdev = bdget_disk_sector(disk, disk_sector); + if (!bdev) + return -ENODEV; + + bdev_sector = disk_sector - get_start_sect(bdev); + sb = get_super(bdev); + if (!sb) { + rc = bd_disk_holder_block_lost(bdev, bdev_sector, data); + goto out; + } else if (sb->s_op->storage_lost) + rc = sb->s_op->storage_lost(sb, bdev, + bdev_sector << SECTOR_SHIFT, data); + drop_super(sb); + +out: + bdput(bdev); + return rc; +} + /* see "strong" declaration in tools/testing/nvdimm/pmem-dax.c */ __weak long __pmem_direct_access(struct pmem_device *pmem, pgoff_t pgoff, long nr_pages, void **kaddr, pfn_t *pfn) @@ -281,6 +307,7 @@ static const struct block_device_operations pmem_fops = { .owner = THIS_MODULE, .submit_bio = pmem_submit_bio, .rw_page = pmem_rw_page, + .block_lost = pmem_block_lost, }; static int pmem_dax_zero_page_range(struct dax_device *dax_dev, pgoff_t pgoff, diff --git a/fs/block_dev.c b/fs/block_dev.c index 9e84b1928b94..e1e30828fb9f 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1171,6 +1171,29 @@ struct bd_holder_disk { int refcnt; }; +int bd_disk_holder_block_lost(struct block_device *bdev, sector_t offset, + void *data) +{ + struct bd_holder_disk *holder; + struct gendisk *disk; + int rc = 0; + + if (list_empty(&(bdev->bd_holder_disks))) + return -ENODEV; + + list_for_each_entry(holder, &bdev->bd_holder_disks, list) { + disk = holder->disk; + if (disk->fops->block_lost) { + rc = disk->fops->block_lost(disk, bdev, + offset << SECTOR_SHIFT, data); + if (rc != -ENODEV) + break; + } + } + return rc; +} +EXPORT_SYMBOL_GPL(bd_disk_holder_block_lost); + static struct bd_holder_disk *bd_find_holder_disk(struct block_device *bdev, struct gendisk *disk) { diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 639cae2c158b..ddeb268cc938 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -1855,6 +1855,8 @@ struct block_device_operations { int (*report_zones)(struct gendisk *, sector_t sector, unsigned int nr_zones, report_zones_cb cb, void *data); char *(*devnode)(struct gendisk *disk, umode_t *mode); + int (*block_lost)(struct gendisk *disk, struct block_device *bdev, + loff_t offset, void *data); struct module *owner; const struct pr_ops *pr_ops; }; diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 38f23d757013..9d8f5b5dab9f 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -303,6 +303,8 @@ static inline void add_disk_no_queue_reg(struct gendisk *disk) extern void del_gendisk(struct gendisk *gp); extern struct gendisk *get_gendisk(dev_t dev, int *partno); extern struct block_device *bdget_disk(struct gendisk *disk, int partno); +extern struct block_device *bdget_disk_sector(struct gendisk *disk, + sector_t sector); extern void set_device_ro(struct block_device *bdev, int flag); extern void set_disk_ro(struct gendisk *disk, int flag); @@ -381,9 +383,16 @@ int blkdev_ioctl(struct block_device *, fmode_t, unsigned, unsigned long); long compat_blkdev_ioctl(struct file *, unsigned, unsigned long); #ifdef CONFIG_SYSFS +int bd_disk_holder_block_lost(struct block_device *bdev, sector_t offset, + void *data); int bd_link_disk_holder(struct block_device *bdev, struct gendisk *disk); void bd_unlink_disk_holder(struct block_device *bdev, struct gendisk *disk); #else +static inline int bd_disk_holder_block_lost(struct block_device *bdev, + sector_t offset, void *data) +{ + return 0; +} static inline int bd_link_disk_holder(struct block_device *bdev, struct gendisk *disk) { -- 2.29.2 _______________________________________________ Linux-nvdimm mailing list -- linux-nvdimm@lists.01.org To unsubscribe send an email to linux-nvdimm-leave@lists.01.org
WARNING: multiple messages have this Message-ID (diff)
From: Shiyang Ruan <ruansy.fnst@cn.fujitsu.com> To: <linux-kernel@vger.kernel.org>, <linux-xfs@vger.kernel.org>, <linux-nvdimm@lists.01.org>, <linux-mm@kvack.org> Cc: <linux-fsdevel@vger.kernel.org>, <linux-raid@vger.kernel.org>, <darrick.wong@oracle.com>, <dan.j.williams@intel.com>, <david@fromorbit.com>, <hch@lst.de>, <song@kernel.org>, <rgoldwyn@suse.de>, <qi.fuli@fujitsu.com>, <y-goto@fujitsu.com> Subject: [RFC PATCH v2 2/6] blk: introduce ->block_lost() to handle memory-failure Date: Mon, 23 Nov 2020 08:41:12 +0800 [thread overview] Message-ID: <20201123004116.2453-3-ruansy.fnst@cn.fujitsu.com> (raw) In-Reply-To: <20201123004116.2453-1-ruansy.fnst@cn.fujitsu.com> In fsdax mode, the memory failure happens on block device. So, it is needed to introduce an interface for block devices. Each kind of block device can handle the memory failure in ther own ways. Usually, a block device is used directly to mkfs on it. The filesystem on it is easily to obtain by 'get_super()'. The block device can also be divided into several partitions, or used as a target by mapped device. It is hard to get filesystem's superblock in this two ways. So, add 'bdget_disk_sector()' to get the block device of a partition where the broken sector located in. And add 'bd_disk_holder_block_lost()' iterate the mapped devices on it. Signed-off-by: Shiyang Ruan <ruansy.fnst@cn.fujitsu.com> --- block/genhd.c | 12 ++++++++++++ drivers/nvdimm/pmem.c | 27 +++++++++++++++++++++++++++ fs/block_dev.c | 23 +++++++++++++++++++++++ include/linux/blkdev.h | 2 ++ include/linux/genhd.h | 9 +++++++++ 5 files changed, 73 insertions(+) diff --git a/block/genhd.c b/block/genhd.c index 0a273211fec2..2c7304f123fa 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -1055,6 +1055,18 @@ struct block_device *bdget_disk(struct gendisk *disk, int partno) } EXPORT_SYMBOL(bdget_disk); +struct block_device *bdget_disk_sector(struct gendisk *disk, sector_t sector) +{ + struct block_device *bdev = NULL; + struct hd_struct *part = disk_map_sector_rcu(disk, sector); + + if (part) + bdev = bdget_part(part); + + return bdev; +} +EXPORT_SYMBOL(bdget_disk_sector); + /* * print a full list of all partitions - intended for places where the root * filesystem can't be mounted and thus to give the victim some idea of what diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index 875076b0ea6c..d75a3f370f3c 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c @@ -253,6 +253,32 @@ static int pmem_rw_page(struct block_device *bdev, sector_t sector, return blk_status_to_errno(rc); } +int pmem_block_lost(struct gendisk *disk, struct block_device *bdev, + loff_t disk_offset, void *data) +{ + struct super_block *sb; + sector_t bdev_sector, disk_sector = disk_offset >> SECTOR_SHIFT; + int rc = 0; + + bdev = bdget_disk_sector(disk, disk_sector); + if (!bdev) + return -ENODEV; + + bdev_sector = disk_sector - get_start_sect(bdev); + sb = get_super(bdev); + if (!sb) { + rc = bd_disk_holder_block_lost(bdev, bdev_sector, data); + goto out; + } else if (sb->s_op->storage_lost) + rc = sb->s_op->storage_lost(sb, bdev, + bdev_sector << SECTOR_SHIFT, data); + drop_super(sb); + +out: + bdput(bdev); + return rc; +} + /* see "strong" declaration in tools/testing/nvdimm/pmem-dax.c */ __weak long __pmem_direct_access(struct pmem_device *pmem, pgoff_t pgoff, long nr_pages, void **kaddr, pfn_t *pfn) @@ -281,6 +307,7 @@ static const struct block_device_operations pmem_fops = { .owner = THIS_MODULE, .submit_bio = pmem_submit_bio, .rw_page = pmem_rw_page, + .block_lost = pmem_block_lost, }; static int pmem_dax_zero_page_range(struct dax_device *dax_dev, pgoff_t pgoff, diff --git a/fs/block_dev.c b/fs/block_dev.c index 9e84b1928b94..e1e30828fb9f 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1171,6 +1171,29 @@ struct bd_holder_disk { int refcnt; }; +int bd_disk_holder_block_lost(struct block_device *bdev, sector_t offset, + void *data) +{ + struct bd_holder_disk *holder; + struct gendisk *disk; + int rc = 0; + + if (list_empty(&(bdev->bd_holder_disks))) + return -ENODEV; + + list_for_each_entry(holder, &bdev->bd_holder_disks, list) { + disk = holder->disk; + if (disk->fops->block_lost) { + rc = disk->fops->block_lost(disk, bdev, + offset << SECTOR_SHIFT, data); + if (rc != -ENODEV) + break; + } + } + return rc; +} +EXPORT_SYMBOL_GPL(bd_disk_holder_block_lost); + static struct bd_holder_disk *bd_find_holder_disk(struct block_device *bdev, struct gendisk *disk) { diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 639cae2c158b..ddeb268cc938 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -1855,6 +1855,8 @@ struct block_device_operations { int (*report_zones)(struct gendisk *, sector_t sector, unsigned int nr_zones, report_zones_cb cb, void *data); char *(*devnode)(struct gendisk *disk, umode_t *mode); + int (*block_lost)(struct gendisk *disk, struct block_device *bdev, + loff_t offset, void *data); struct module *owner; const struct pr_ops *pr_ops; }; diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 38f23d757013..9d8f5b5dab9f 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -303,6 +303,8 @@ static inline void add_disk_no_queue_reg(struct gendisk *disk) extern void del_gendisk(struct gendisk *gp); extern struct gendisk *get_gendisk(dev_t dev, int *partno); extern struct block_device *bdget_disk(struct gendisk *disk, int partno); +extern struct block_device *bdget_disk_sector(struct gendisk *disk, + sector_t sector); extern void set_device_ro(struct block_device *bdev, int flag); extern void set_disk_ro(struct gendisk *disk, int flag); @@ -381,9 +383,16 @@ int blkdev_ioctl(struct block_device *, fmode_t, unsigned, unsigned long); long compat_blkdev_ioctl(struct file *, unsigned, unsigned long); #ifdef CONFIG_SYSFS +int bd_disk_holder_block_lost(struct block_device *bdev, sector_t offset, + void *data); int bd_link_disk_holder(struct block_device *bdev, struct gendisk *disk); void bd_unlink_disk_holder(struct block_device *bdev, struct gendisk *disk); #else +static inline int bd_disk_holder_block_lost(struct block_device *bdev, + sector_t offset, void *data) +{ + return 0; +} static inline int bd_link_disk_holder(struct block_device *bdev, struct gendisk *disk) { -- 2.29.2
next prev parent reply other threads:[~2020-11-23 0:41 UTC|newest] Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top 2020-11-23 0:41 [RFC PATCH v2 0/6] fsdax: introduce fs query to support reflink Shiyang Ruan 2020-11-23 0:41 ` Shiyang Ruan 2020-11-23 0:41 ` [RFC PATCH v2 1/6] fs: introduce ->storage_lost() for memory-failure Shiyang Ruan 2020-11-23 0:41 ` Shiyang Ruan 2020-11-23 0:41 ` Shiyang Ruan [this message] 2020-11-23 0:41 ` [RFC PATCH v2 2/6] blk: introduce ->block_lost() to handle memory-failure Shiyang Ruan 2020-11-23 0:41 ` [RFC PATCH v2 3/6] md: implement ->block_lost() for memory-failure Shiyang Ruan 2020-11-23 0:41 ` Shiyang Ruan 2020-11-23 0:41 ` [RFC PATCH v2 4/6] pagemap: introduce ->memory_failure() Shiyang Ruan 2020-11-23 0:41 ` Shiyang Ruan 2020-11-23 0:41 ` [RFC PATCH v2 5/6] mm, fsdax: refactor dax handler in memory-failure Shiyang Ruan 2020-11-23 0:41 ` Shiyang Ruan 2020-11-23 0:41 ` [RFC PATCH v2 6/6] fsdax: remove useless (dis)associate functions Shiyang Ruan 2020-11-23 0:41 ` Shiyang Ruan 2020-11-29 22:47 ` [RFC PATCH v2 0/6] fsdax: introduce fs query to support reflink Dave Chinner 2020-11-29 22:47 ` Dave Chinner 2020-12-02 7:12 ` Ruan Shiyang 2020-12-02 7:12 ` Ruan Shiyang 2020-12-06 22:55 ` Dave Chinner 2020-12-06 22:55 ` Dave Chinner 2020-12-14 20:58 ` Jane Chu 2020-12-14 20:58 ` Jane Chu 2020-12-15 11:58 ` Ruan Shiyang 2020-12-15 11:58 ` Ruan Shiyang 2020-12-15 19:05 ` Jane Chu 2020-12-15 19:05 ` Jane Chu 2020-12-15 23:10 ` Dave Chinner 2020-12-15 23:10 ` Dave Chinner 2020-12-16 2:46 ` Darrick J. Wong 2020-12-16 2:46 ` Darrick J. Wong
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20201123004116.2453-3-ruansy.fnst@cn.fujitsu.com \ --to=ruansy.fnst@cn.fujitsu.com \ --cc=darrick.wong@oracle.com \ --cc=david@fromorbit.com \ --cc=hch@lst.de \ --cc=linux-fsdevel@vger.kernel.org \ --cc=linux-kernel@vger.kernel.org \ --cc=linux-mm@kvack.org \ --cc=linux-nvdimm@lists.01.org \ --cc=linux-raid@vger.kernel.org \ --cc=linux-xfs@vger.kernel.org \ --cc=qi.fuli@fujitsu.com \ --cc=rgoldwyn@suse.de \ --cc=song@kernel.org \ --cc=y-goto@fujitsu.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.