From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9515FC63798 for ; Mon, 23 Nov 2020 00:41:47 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 3B2A12076E for ; Mon, 23 Nov 2020 00:41:47 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 3B2A12076E Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=cn.fujitsu.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id AC5396B0070; Sun, 22 Nov 2020 19:41:46 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id A9C7C8D0002; Sun, 22 Nov 2020 19:41:46 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 9DA9A8D0001; Sun, 22 Nov 2020 19:41:46 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0223.hostedemail.com [216.40.44.223]) by kanga.kvack.org (Postfix) with ESMTP id 720826B0070 for ; Sun, 22 Nov 2020 19:41:46 -0500 (EST) Received: from smtpin19.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay01.hostedemail.com (Postfix) with ESMTP id 09792180AD817 for ; Mon, 23 Nov 2020 00:41:46 +0000 (UTC) X-FDA: 77513830212.19.route90_1403cd227361 Received: from filter.hostedemail.com (10.5.16.251.rfc1918.com [10.5.16.251]) by smtpin19.hostedemail.com (Postfix) with ESMTP id DB9131ACEA4 for ; Mon, 23 Nov 2020 00:41:45 +0000 (UTC) X-HE-Tag: route90_1403cd227361 X-Filterd-Recvd-Size: 7974 Received: from heian.cn.fujitsu.com (mail.cn.fujitsu.com [183.91.158.132]) by imf33.hostedemail.com (Postfix) with ESMTP for ; Mon, 23 Nov 2020 00:41:43 +0000 (UTC) X-IronPort-AV: E=Sophos;i="5.78,361,1599494400"; d="scan'208";a="101635235" Received: from unknown (HELO cn.fujitsu.com) ([10.167.33.5]) by heian.cn.fujitsu.com with ESMTP; 23 Nov 2020 08:41:41 +0800 Received: from G08CNEXMBPEKD04.g08.fujitsu.local (unknown [10.167.33.201]) by cn.fujitsu.com (Postfix) with ESMTP id 5390A48990F9; Mon, 23 Nov 2020 08:41:41 +0800 (CST) Received: from G08CNEXCHPEKD05.g08.fujitsu.local (10.167.33.203) by G08CNEXMBPEKD04.g08.fujitsu.local (10.167.33.201) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 23 Nov 2020 08:41:42 +0800 Received: from localhost.localdomain (10.167.225.141) by G08CNEXCHPEKD05.g08.fujitsu.local (10.167.33.209) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Mon, 23 Nov 2020 08:41:41 +0800 From: Shiyang Ruan To: , , , CC: , , , , , , , , , Subject: [RFC PATCH v2 2/6] blk: introduce ->block_lost() to handle memory-failure Date: Mon, 23 Nov 2020 08:41:12 +0800 Message-ID: <20201123004116.2453-3-ruansy.fnst@cn.fujitsu.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20201123004116.2453-1-ruansy.fnst@cn.fujitsu.com> References: <20201123004116.2453-1-ruansy.fnst@cn.fujitsu.com> MIME-Version: 1.0 Content-Type: text/plain X-yoursite-MailScanner-ID: 5390A48990F9.A8C41 X-yoursite-MailScanner: Found to be clean X-yoursite-MailScanner-From: ruansy.fnst@cn.fujitsu.com Content-Transfer-Encoding: quoted-printable X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: 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 --- 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 *di= sk, int partno) } EXPORT_SYMBOL(bdget_disk); =20 +struct block_device *bdget_disk_sector(struct gendisk *disk, sector_t se= ctor) +{ + struct block_device *bdev =3D NULL; + struct hd_struct *part =3D disk_map_sector_rcu(disk, sector); + + if (part) + bdev =3D bdget_part(part); + + return bdev; +} +EXPORT_SYMBOL(bdget_disk_sector); + /* * print a full list of all partitions - intended for places where the r= oot * 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, s= ector_t sector, return blk_status_to_errno(rc); } =20 +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 =3D disk_offset >> SECTOR_SHIFT; + int rc =3D 0; + + bdev =3D bdget_disk_sector(disk, disk_sector); + if (!bdev) + return -ENODEV; + + bdev_sector =3D disk_sector - get_start_sect(bdev); + sb =3D get_super(bdev); + if (!sb) { + rc =3D bd_disk_holder_block_lost(bdev, bdev_sector, data); + goto out; + } else if (sb->s_op->storage_lost) + rc =3D 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= =3D { .owner =3D THIS_MODULE, .submit_bio =3D pmem_submit_bio, .rw_page =3D pmem_rw_page, + .block_lost =3D pmem_block_lost, }; =20 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; }; =20 +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 =3D 0; + + if (list_empty(&(bdev->bd_holder_disks))) + return -ENODEV; + + list_for_each_entry(holder, &bdev->bd_holder_disks, list) { + disk =3D holder->disk; + if (disk->fops->block_lost) { + rc =3D disk->fops->block_lost(disk, bdev, + offset << SECTOR_SHIFT, data); + if (rc !=3D -ENODEV) + break; + } + } + return rc; +} +EXPORT_SYMBOL_GPL(bd_disk_holder_block_lost); + static struct bd_holder_disk *bd_find_holder_disk(struct block_device *b= dev, 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 gendi= sk *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); =20 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, uns= igned, unsigned long); long compat_blkdev_ioctl(struct file *, unsigned, unsigned long); =20 #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 *di= sk); #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) { --=20 2.29.2