--- /dev/null
+From foo@baz Sun Mar 7 04:13:19 PM CET 2021
+From: Jeffle Xu <jefflexu@linux.alibaba.com>
+Date: Tue, 23 Feb 2021 17:28:57 +0800
+Subject: aoe: register default groups with device_add_disk()
+To: gregkh@linuxfoundation.org, sashal@kernel.org
+Cc: stable@vger.kernel.org, joseph.qi@linux.alibaba.com, jefflexu@linux.alibaba.com, hare@suse.com
+Message-ID: <20210223092859.17033-5-jefflexu@linux.alibaba.com>
+
+From: Hannes Reinecke <hare@suse.de>
+
+commit 95cf7809bf9169fec4e4b7bb24b8069d8f354f96 upstream.
+
+Register default sysfs groups during device_add_disk() to avoid a
+race condition with udev during startup.
+
+Signed-off-by: Hannes Reinecke <hare@suse.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Acked-by: Ed L. Cachin <ed.cashin@acm.org>
+Reviewed-by: Bart Van Assche <bart.vanassche@wdc.com>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Jeffle Xu <jefflexu@linux.alibaba.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/block/aoe/aoe.h | 1 -
+ drivers/block/aoe/aoeblk.c | 21 +++++++--------------
+ drivers/block/aoe/aoedev.c | 1 -
+ 3 files changed, 7 insertions(+), 16 deletions(-)
+
+--- a/drivers/block/aoe/aoe.h
++++ b/drivers/block/aoe/aoe.h
+@@ -201,7 +201,6 @@ int aoeblk_init(void);
+ void aoeblk_exit(void);
+ void aoeblk_gdalloc(void *);
+ void aoedisk_rm_debugfs(struct aoedev *d);
+-void aoedisk_rm_sysfs(struct aoedev *d);
+
+ int aoechr_init(void);
+ void aoechr_exit(void);
+--- a/drivers/block/aoe/aoeblk.c
++++ b/drivers/block/aoe/aoeblk.c
+@@ -177,10 +177,15 @@ static struct attribute *aoe_attrs[] = {
+ NULL,
+ };
+
+-static const struct attribute_group attr_group = {
++static const struct attribute_group aoe_attr_group = {
+ .attrs = aoe_attrs,
+ };
+
++static const struct attribute_group *aoe_attr_groups[] = {
++ &aoe_attr_group,
++ NULL,
++};
++
+ static const struct file_operations aoe_debugfs_fops = {
+ .open = aoe_debugfs_open,
+ .read = seq_read,
+@@ -220,17 +225,6 @@ aoedisk_rm_debugfs(struct aoedev *d)
+ }
+
+ static int
+-aoedisk_add_sysfs(struct aoedev *d)
+-{
+- return sysfs_create_group(&disk_to_dev(d->gd)->kobj, &attr_group);
+-}
+-void
+-aoedisk_rm_sysfs(struct aoedev *d)
+-{
+- sysfs_remove_group(&disk_to_dev(d->gd)->kobj, &attr_group);
+-}
+-
+-static int
+ aoeblk_open(struct block_device *bdev, fmode_t mode)
+ {
+ struct aoedev *d = bdev->bd_disk->private_data;
+@@ -417,8 +411,7 @@ aoeblk_gdalloc(void *vp)
+
+ spin_unlock_irqrestore(&d->lock, flags);
+
+- add_disk(gd);
+- aoedisk_add_sysfs(d);
++ device_add_disk(NULL, gd, aoe_attr_groups);
+ aoedisk_add_debugfs(d);
+
+ spin_lock_irqsave(&d->lock, flags);
+--- a/drivers/block/aoe/aoedev.c
++++ b/drivers/block/aoe/aoedev.c
+@@ -275,7 +275,6 @@ freedev(struct aoedev *d)
+ del_timer_sync(&d->timer);
+ if (d->gd) {
+ aoedisk_rm_debugfs(d);
+- aoedisk_rm_sysfs(d);
+ del_gendisk(d->gd);
+ put_disk(d->gd);
+ blk_cleanup_queue(d->blkq);
--- /dev/null
+From foo@baz Sun Mar 7 04:13:19 PM CET 2021
+From: Jeffle Xu <jefflexu@linux.alibaba.com>
+Date: Tue, 23 Feb 2021 17:28:55 +0800
+Subject: block: genhd: add 'groups' argument to device_add_disk
+To: gregkh@linuxfoundation.org, sashal@kernel.org
+Cc: stable@vger.kernel.org, joseph.qi@linux.alibaba.com, jefflexu@linux.alibaba.com, hare@suse.com
+Message-ID: <20210223092859.17033-3-jefflexu@linux.alibaba.com>
+
+From: Hannes Reinecke <hare@suse.de>
+
+commit fef912bf860e8e7e48a2bfb978a356bba743a8b7 upstream.
+
+Update device_add_disk() to take an 'groups' argument so that
+individual drivers can register a device with additional sysfs
+attributes.
+This avoids race condition the driver would otherwise have if these
+groups were to be created with sysfs_add_groups().
+
+Signed-off-by: Martin Wilck <martin.wilck@suse.com>
+Signed-off-by: Hannes Reinecke <hare@suse.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Bart Van Assche <bvanassche@acm.org>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Jeffle Xu <jefflexu@linux.alibaba.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/um/drivers/ubd_kern.c | 2 +-
+ block/genhd.c | 19 ++++++++++++++-----
+ drivers/block/floppy.c | 2 +-
+ drivers/block/mtip32xx/mtip32xx.c | 2 +-
+ drivers/block/ps3disk.c | 2 +-
+ drivers/block/ps3vram.c | 2 +-
+ drivers/block/rsxx/dev.c | 2 +-
+ drivers/block/skd_main.c | 2 +-
+ drivers/block/sunvdc.c | 2 +-
+ drivers/block/virtio_blk.c | 2 +-
+ drivers/block/xen-blkfront.c | 2 +-
+ drivers/ide/ide-cd.c | 2 +-
+ drivers/ide/ide-gd.c | 2 +-
+ drivers/memstick/core/ms_block.c | 2 +-
+ drivers/memstick/core/mspro_block.c | 2 +-
+ drivers/mmc/core/block.c | 2 +-
+ drivers/mtd/mtd_blkdevs.c | 2 +-
+ drivers/nvdimm/blk.c | 2 +-
+ drivers/nvdimm/btt.c | 2 +-
+ drivers/nvdimm/pmem.c | 2 +-
+ drivers/nvme/host/core.c | 2 +-
+ drivers/nvme/host/multipath.c | 2 +-
+ drivers/s390/block/dasd_genhd.c | 2 +-
+ drivers/s390/block/dcssblk.c | 2 +-
+ drivers/s390/block/scm_blk.c | 2 +-
+ drivers/scsi/sd.c | 2 +-
+ drivers/scsi/sr.c | 2 +-
+ include/linux/genhd.h | 5 +++--
+ 28 files changed, 43 insertions(+), 33 deletions(-)
+
+--- a/arch/um/drivers/ubd_kern.c
++++ b/arch/um/drivers/ubd_kern.c
+@@ -891,7 +891,7 @@ static int ubd_disk_register(int major,
+
+ disk->private_data = &ubd_devs[unit];
+ disk->queue = ubd_devs[unit].queue;
+- device_add_disk(parent, disk);
++ device_add_disk(parent, disk, NULL);
+
+ *disk_out = disk;
+ return 0;
+--- a/block/genhd.c
++++ b/block/genhd.c
+@@ -582,7 +582,8 @@ static int exact_lock(dev_t devt, void *
+ return 0;
+ }
+
+-static void register_disk(struct device *parent, struct gendisk *disk)
++static void register_disk(struct device *parent, struct gendisk *disk,
++ const struct attribute_group **groups)
+ {
+ struct device *ddev = disk_to_dev(disk);
+ struct block_device *bdev;
+@@ -597,6 +598,10 @@ static void register_disk(struct device
+ /* delay uevents, until we scanned partition table */
+ dev_set_uevent_suppress(ddev, 1);
+
++ if (groups) {
++ WARN_ON(ddev->groups);
++ ddev->groups = groups;
++ }
+ if (device_add(ddev))
+ return;
+ if (!sysfs_deprecated) {
+@@ -664,6 +669,7 @@ exit:
+ * __device_add_disk - add disk information to kernel list
+ * @parent: parent device for the disk
+ * @disk: per-device partitioning information
++ * @groups: Additional per-device sysfs groups
+ * @register_queue: register the queue if set to true
+ *
+ * This function registers the partitioning information in @disk
+@@ -672,6 +678,7 @@ exit:
+ * FIXME: error handling
+ */
+ static void __device_add_disk(struct device *parent, struct gendisk *disk,
++ const struct attribute_group **groups,
+ bool register_queue)
+ {
+ dev_t devt;
+@@ -715,7 +722,7 @@ static void __device_add_disk(struct dev
+ blk_register_region(disk_devt(disk), disk->minors, NULL,
+ exact_match, exact_lock, disk);
+ }
+- register_disk(parent, disk);
++ register_disk(parent, disk, groups);
+ if (register_queue)
+ blk_register_queue(disk);
+
+@@ -729,15 +736,17 @@ static void __device_add_disk(struct dev
+ blk_integrity_add(disk);
+ }
+
+-void device_add_disk(struct device *parent, struct gendisk *disk)
++void device_add_disk(struct device *parent, struct gendisk *disk,
++ const struct attribute_group **groups)
++
+ {
+- __device_add_disk(parent, disk, true);
++ __device_add_disk(parent, disk, groups, true);
+ }
+ EXPORT_SYMBOL(device_add_disk);
+
+ void device_add_disk_no_queue_reg(struct device *parent, struct gendisk *disk)
+ {
+- __device_add_disk(parent, disk, false);
++ __device_add_disk(parent, disk, NULL, false);
+ }
+ EXPORT_SYMBOL(device_add_disk_no_queue_reg);
+
+--- a/drivers/block/floppy.c
++++ b/drivers/block/floppy.c
+@@ -4714,7 +4714,7 @@ static int __init do_floppy_init(void)
+ /* to be cleaned up... */
+ disks[drive]->private_data = (void *)(long)drive;
+ disks[drive]->flags |= GENHD_FL_REMOVABLE;
+- device_add_disk(&floppy_device[drive].dev, disks[drive]);
++ device_add_disk(&floppy_device[drive].dev, disks[drive], NULL);
+ }
+
+ return 0;
+--- a/drivers/block/mtip32xx/mtip32xx.c
++++ b/drivers/block/mtip32xx/mtip32xx.c
+@@ -3861,7 +3861,7 @@ skip_create_disk:
+ set_capacity(dd->disk, capacity);
+
+ /* Enable the block device and add it to /dev */
+- device_add_disk(&dd->pdev->dev, dd->disk);
++ device_add_disk(&dd->pdev->dev, dd->disk, NULL);
+
+ dd->bdev = bdget_disk(dd->disk, 0);
+ /*
+--- a/drivers/block/ps3disk.c
++++ b/drivers/block/ps3disk.c
+@@ -499,7 +499,7 @@ static int ps3disk_probe(struct ps3_syst
+ gendisk->disk_name, priv->model, priv->raw_capacity >> 11,
+ get_capacity(gendisk) >> 11);
+
+- device_add_disk(&dev->sbd.core, gendisk);
++ device_add_disk(&dev->sbd.core, gendisk, NULL);
+ return 0;
+
+ fail_cleanup_queue:
+--- a/drivers/block/ps3vram.c
++++ b/drivers/block/ps3vram.c
+@@ -769,7 +769,7 @@ static int ps3vram_probe(struct ps3_syst
+ dev_info(&dev->core, "%s: Using %lu MiB of GPU memory\n",
+ gendisk->disk_name, get_capacity(gendisk) >> 11);
+
+- device_add_disk(&dev->core, gendisk);
++ device_add_disk(&dev->core, gendisk, NULL);
+ return 0;
+
+ fail_cleanup_queue:
+--- a/drivers/block/rsxx/dev.c
++++ b/drivers/block/rsxx/dev.c
+@@ -226,7 +226,7 @@ int rsxx_attach_dev(struct rsxx_cardinfo
+ set_capacity(card->gendisk, card->size8 >> 9);
+ else
+ set_capacity(card->gendisk, 0);
+- device_add_disk(CARD_TO_DEV(card), card->gendisk);
++ device_add_disk(CARD_TO_DEV(card), card->gendisk, NULL);
+ card->bdev_attached = 1;
+ }
+
+--- a/drivers/block/skd_main.c
++++ b/drivers/block/skd_main.c
+@@ -3104,7 +3104,7 @@ static int skd_bdev_getgeo(struct block_
+ static int skd_bdev_attach(struct device *parent, struct skd_device *skdev)
+ {
+ dev_dbg(&skdev->pdev->dev, "add_disk\n");
+- device_add_disk(parent, skdev->disk);
++ device_add_disk(parent, skdev->disk, NULL);
+ return 0;
+ }
+
+--- a/drivers/block/sunvdc.c
++++ b/drivers/block/sunvdc.c
+@@ -862,7 +862,7 @@ static int probe_disk(struct vdc_port *p
+ port->vdisk_size, (port->vdisk_size >> (20 - 9)),
+ port->vio.ver.major, port->vio.ver.minor);
+
+- device_add_disk(&port->vio.vdev->dev, g);
++ device_add_disk(&port->vio.vdev->dev, g, NULL);
+
+ return 0;
+ }
+--- a/drivers/block/virtio_blk.c
++++ b/drivers/block/virtio_blk.c
+@@ -858,7 +858,7 @@ static int virtblk_probe(struct virtio_d
+ virtblk_update_capacity(vblk, false);
+ virtio_device_ready(vdev);
+
+- device_add_disk(&vdev->dev, vblk->disk);
++ device_add_disk(&vdev->dev, vblk->disk, NULL);
+ err = device_create_file(disk_to_dev(vblk->disk), &dev_attr_serial);
+ if (err)
+ goto out_del_disk;
+--- a/drivers/block/xen-blkfront.c
++++ b/drivers/block/xen-blkfront.c
+@@ -2422,7 +2422,7 @@ static void blkfront_connect(struct blkf
+ for (i = 0; i < info->nr_rings; i++)
+ kick_pending_request_queues(&info->rinfo[i]);
+
+- device_add_disk(&info->xbdev->dev, info->gd);
++ device_add_disk(&info->xbdev->dev, info->gd, NULL);
+
+ info->is_ready = 1;
+ return;
+--- a/drivers/ide/ide-cd.c
++++ b/drivers/ide/ide-cd.c
+@@ -1784,7 +1784,7 @@ static int ide_cd_probe(ide_drive_t *dri
+ ide_cd_read_toc(drive);
+ g->fops = &idecd_ops;
+ g->flags |= GENHD_FL_REMOVABLE | GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE;
+- device_add_disk(&drive->gendev, g);
++ device_add_disk(&drive->gendev, g, NULL);
+ return 0;
+
+ out_free_disk:
+--- a/drivers/ide/ide-gd.c
++++ b/drivers/ide/ide-gd.c
+@@ -416,7 +416,7 @@ static int ide_gd_probe(ide_drive_t *dri
+ if (drive->dev_flags & IDE_DFLAG_REMOVABLE)
+ g->flags = GENHD_FL_REMOVABLE;
+ g->fops = &ide_gd_ops;
+- device_add_disk(&drive->gendev, g);
++ device_add_disk(&drive->gendev, g, NULL);
+ return 0;
+
+ out_free_disk:
+--- a/drivers/memstick/core/ms_block.c
++++ b/drivers/memstick/core/ms_block.c
+@@ -2146,7 +2146,7 @@ static int msb_init_disk(struct memstick
+ set_disk_ro(msb->disk, 1);
+
+ msb_start(card);
+- device_add_disk(&card->dev, msb->disk);
++ device_add_disk(&card->dev, msb->disk, NULL);
+ dbg("Disk added");
+ return 0;
+
+--- a/drivers/memstick/core/mspro_block.c
++++ b/drivers/memstick/core/mspro_block.c
+@@ -1236,7 +1236,7 @@ static int mspro_block_init_disk(struct
+ set_capacity(msb->disk, capacity);
+ dev_dbg(&card->dev, "capacity set %ld\n", capacity);
+
+- device_add_disk(&card->dev, msb->disk);
++ device_add_disk(&card->dev, msb->disk, NULL);
+ msb->active = 1;
+ return 0;
+
+--- a/drivers/mmc/core/block.c
++++ b/drivers/mmc/core/block.c
+@@ -2671,7 +2671,7 @@ static int mmc_add_disk(struct mmc_blk_d
+ int ret;
+ struct mmc_card *card = md->queue.card;
+
+- device_add_disk(md->parent, md->disk);
++ device_add_disk(md->parent, md->disk, NULL);
+ md->force_ro.show = force_ro_show;
+ md->force_ro.store = force_ro_store;
+ sysfs_attr_init(&md->force_ro.attr);
+--- a/drivers/mtd/mtd_blkdevs.c
++++ b/drivers/mtd/mtd_blkdevs.c
+@@ -447,7 +447,7 @@ int add_mtd_blktrans_dev(struct mtd_blkt
+ if (new->readonly)
+ set_disk_ro(gd, 1);
+
+- device_add_disk(&new->mtd->dev, gd);
++ device_add_disk(&new->mtd->dev, gd, NULL);
+
+ if (new->disk_attributes) {
+ ret = sysfs_create_group(&disk_to_dev(gd)->kobj,
+--- a/drivers/nvdimm/blk.c
++++ b/drivers/nvdimm/blk.c
+@@ -290,7 +290,7 @@ static int nsblk_attach_disk(struct nd_n
+ }
+
+ set_capacity(disk, available_disk_size >> SECTOR_SHIFT);
+- device_add_disk(dev, disk);
++ device_add_disk(dev, disk, NULL);
+ revalidate_disk(disk);
+ return 0;
+ }
+--- a/drivers/nvdimm/btt.c
++++ b/drivers/nvdimm/btt.c
+@@ -1565,7 +1565,7 @@ static int btt_blk_init(struct btt *btt)
+ }
+ }
+ set_capacity(btt->btt_disk, btt->nlba * btt->sector_size >> 9);
+- device_add_disk(&btt->nd_btt->dev, btt->btt_disk);
++ device_add_disk(&btt->nd_btt->dev, btt->btt_disk, NULL);
+ btt->nd_btt->size = btt->nlba * (u64)btt->sector_size;
+ revalidate_disk(btt->btt_disk);
+
+--- a/drivers/nvdimm/pmem.c
++++ b/drivers/nvdimm/pmem.c
+@@ -479,7 +479,7 @@ static int pmem_attach_disk(struct devic
+ gendev = disk_to_dev(disk);
+ gendev->groups = pmem_attribute_groups;
+
+- device_add_disk(dev, disk);
++ device_add_disk(dev, disk, NULL);
+ if (devm_add_action_or_reset(dev, pmem_release_disk, pmem))
+ return -ENOMEM;
+
+--- a/drivers/nvme/host/core.c
++++ b/drivers/nvme/host/core.c
+@@ -3211,7 +3211,7 @@ static void nvme_alloc_ns(struct nvme_ct
+
+ nvme_get_ctrl(ctrl);
+
+- device_add_disk(ctrl->device, ns->disk);
++ device_add_disk(ctrl->device, ns->disk, NULL);
+ if (sysfs_create_group(&disk_to_dev(ns->disk)->kobj,
+ &nvme_ns_id_attr_group))
+ pr_warn("%s: failed to create sysfs group for identification\n",
+--- a/drivers/nvme/host/multipath.c
++++ b/drivers/nvme/host/multipath.c
+@@ -314,7 +314,7 @@ static void nvme_mpath_set_live(struct n
+ return;
+
+ if (!(head->disk->flags & GENHD_FL_UP)) {
+- device_add_disk(&head->subsys->dev, head->disk);
++ device_add_disk(&head->subsys->dev, head->disk, NULL);
+ if (sysfs_create_group(&disk_to_dev(head->disk)->kobj,
+ &nvme_ns_id_attr_group))
+ dev_warn(&head->subsys->dev,
+--- a/drivers/s390/block/dasd_genhd.c
++++ b/drivers/s390/block/dasd_genhd.c
+@@ -76,7 +76,7 @@ int dasd_gendisk_alloc(struct dasd_block
+ gdp->queue = block->request_queue;
+ block->gdp = gdp;
+ set_capacity(block->gdp, 0);
+- device_add_disk(&base->cdev->dev, block->gdp);
++ device_add_disk(&base->cdev->dev, block->gdp, NULL);
+ return 0;
+ }
+
+--- a/drivers/s390/block/dcssblk.c
++++ b/drivers/s390/block/dcssblk.c
+@@ -685,7 +685,7 @@ dcssblk_add_store(struct device *dev, st
+ }
+
+ get_device(&dev_info->dev);
+- device_add_disk(&dev_info->dev, dev_info->gd);
++ device_add_disk(&dev_info->dev, dev_info->gd, NULL);
+
+ switch (dev_info->segment_type) {
+ case SEG_TYPE_SR:
+--- a/drivers/s390/block/scm_blk.c
++++ b/drivers/s390/block/scm_blk.c
+@@ -500,7 +500,7 @@ int scm_blk_dev_setup(struct scm_blk_dev
+
+ /* 512 byte sectors */
+ set_capacity(bdev->gendisk, scmdev->size >> 9);
+- device_add_disk(&scmdev->dev, bdev->gendisk);
++ device_add_disk(&scmdev->dev, bdev->gendisk, NULL);
+ return 0;
+
+ out_queue:
+--- a/drivers/scsi/sd.c
++++ b/drivers/scsi/sd.c
+@@ -3348,7 +3348,7 @@ static void sd_probe_async(void *data, a
+ }
+
+ blk_pm_runtime_init(sdp->request_queue, dev);
+- device_add_disk(dev, gd);
++ device_add_disk(dev, gd, NULL);
+ if (sdkp->capacity)
+ sd_dif_config_host(sdkp);
+
+--- a/drivers/scsi/sr.c
++++ b/drivers/scsi/sr.c
+@@ -758,7 +758,7 @@ static int sr_probe(struct device *dev)
+
+ dev_set_drvdata(dev, cd);
+ disk->flags |= GENHD_FL_REMOVABLE;
+- device_add_disk(&sdev->sdev_gendev, disk);
++ device_add_disk(&sdev->sdev_gendev, disk, NULL);
+
+ sdev_printk(KERN_DEBUG, sdev,
+ "Attached scsi CD-ROM %s\n", cd->cdi.name);
+--- a/include/linux/genhd.h
++++ b/include/linux/genhd.h
+@@ -402,10 +402,11 @@ static inline void free_part_info(struct
+ extern void part_round_stats(struct request_queue *q, int cpu, struct hd_struct *part);
+
+ /* block/genhd.c */
+-extern void device_add_disk(struct device *parent, struct gendisk *disk);
++extern void device_add_disk(struct device *parent, struct gendisk *disk,
++ const struct attribute_group **groups);
+ static inline void add_disk(struct gendisk *disk)
+ {
+- device_add_disk(NULL, disk);
++ device_add_disk(NULL, disk, NULL);
+ }
+ extern void device_add_disk_no_queue_reg(struct device *parent, struct gendisk *disk);
+ static inline void add_disk_no_queue_reg(struct gendisk *disk)
--- /dev/null
+From foo@baz Sun Mar 7 04:13:19 PM CET 2021
+From: Jeffle Xu <jefflexu@linux.alibaba.com>
+Date: Tue, 23 Feb 2021 17:28:56 +0800
+Subject: nvme: register ns_id attributes as default sysfs groups
+To: gregkh@linuxfoundation.org, sashal@kernel.org
+Cc: stable@vger.kernel.org, joseph.qi@linux.alibaba.com, jefflexu@linux.alibaba.com, hare@suse.com
+Message-ID: <20210223092859.17033-4-jefflexu@linux.alibaba.com>
+
+From: Hannes Reinecke <hare@suse.de>
+
+commit 33b14f67a4e1eabd219fd6543da8f15ed86b641c upstream.
+
+We should be registering the ns_id attribute as default sysfs
+attribute groups, otherwise we have a race condition between
+the uevent and the attributes appearing in sysfs.
+
+[Backport Notes]
+Resolve two context conflicts introduced by following two commits. These
+two commits are applied after the current commit in upstream, while have
+been merged into 4.19.y stable tree before the current commit.
+1. drivers/nvme/host/core.c:nvme_ns_remove, introduced by commit
+2181e455612a ("nvme: fix possible io failures when removing multipathed
+ns").
+2. drivers/nvme/host/multipath.c:nvme_mpath_set_live, introduced by
+commit 5e416b11b4a9 ("nvme-multipath: fix possible I/O hang when paths
+are updated").
+
+Suggested-by: Bart van Assche <bvanassche@acm.org>
+Reviewed-by: Keith Busch <keith.busch@intel.com>
+Signed-off-by: Hannes Reinecke <hare@suse.com>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Jeffle Xu <jefflexu@linux.alibaba.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvme/host/core.c | 21 +++-----
+ drivers/nvme/host/lightnvm.c | 105 +++++++++++++++++-------------------------
+ drivers/nvme/host/multipath.c | 15 +-----
+ drivers/nvme/host/nvme.h | 10 ----
+ 4 files changed, 59 insertions(+), 92 deletions(-)
+
+--- a/drivers/nvme/host/core.c
++++ b/drivers/nvme/host/core.c
+@@ -2842,6 +2842,14 @@ const struct attribute_group nvme_ns_id_
+ .is_visible = nvme_ns_id_attrs_are_visible,
+ };
+
++const struct attribute_group *nvme_ns_id_attr_groups[] = {
++ &nvme_ns_id_attr_group,
++#ifdef CONFIG_NVM
++ &nvme_nvm_attr_group,
++#endif
++ NULL,
++};
++
+ #define nvme_show_str_function(field) \
+ static ssize_t field##_show(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
+@@ -3211,14 +3219,7 @@ static void nvme_alloc_ns(struct nvme_ct
+
+ nvme_get_ctrl(ctrl);
+
+- device_add_disk(ctrl->device, ns->disk, NULL);
+- if (sysfs_create_group(&disk_to_dev(ns->disk)->kobj,
+- &nvme_ns_id_attr_group))
+- pr_warn("%s: failed to create sysfs group for identification\n",
+- ns->disk->disk_name);
+- if (ns->ndev && nvme_nvm_register_sysfs(ns))
+- pr_warn("%s: failed to register lightnvm sysfs group for identification\n",
+- ns->disk->disk_name);
++ device_add_disk(ctrl->device, ns->disk, nvme_ns_id_attr_groups);
+
+ nvme_mpath_add_disk(ns, id);
+ nvme_fault_inject_init(ns);
+@@ -3252,10 +3253,6 @@ static void nvme_ns_remove(struct nvme_n
+ synchronize_srcu(&ns->head->srcu); /* wait for concurrent submissions */
+
+ if (ns->disk && ns->disk->flags & GENHD_FL_UP) {
+- sysfs_remove_group(&disk_to_dev(ns->disk)->kobj,
+- &nvme_ns_id_attr_group);
+- if (ns->ndev)
+- nvme_nvm_unregister_sysfs(ns);
+ del_gendisk(ns->disk);
+ blk_cleanup_queue(ns->queue);
+ if (blk_get_integrity(ns->disk))
+--- a/drivers/nvme/host/lightnvm.c
++++ b/drivers/nvme/host/lightnvm.c
+@@ -1193,10 +1193,29 @@ static NVM_DEV_ATTR_12_RO(multiplane_mod
+ static NVM_DEV_ATTR_12_RO(media_capabilities);
+ static NVM_DEV_ATTR_12_RO(max_phys_secs);
+
+-static struct attribute *nvm_dev_attrs_12[] = {
++/* 2.0 values */
++static NVM_DEV_ATTR_20_RO(groups);
++static NVM_DEV_ATTR_20_RO(punits);
++static NVM_DEV_ATTR_20_RO(chunks);
++static NVM_DEV_ATTR_20_RO(clba);
++static NVM_DEV_ATTR_20_RO(ws_min);
++static NVM_DEV_ATTR_20_RO(ws_opt);
++static NVM_DEV_ATTR_20_RO(maxoc);
++static NVM_DEV_ATTR_20_RO(maxocpu);
++static NVM_DEV_ATTR_20_RO(mw_cunits);
++static NVM_DEV_ATTR_20_RO(write_typ);
++static NVM_DEV_ATTR_20_RO(write_max);
++static NVM_DEV_ATTR_20_RO(reset_typ);
++static NVM_DEV_ATTR_20_RO(reset_max);
++
++static struct attribute *nvm_dev_attrs[] = {
++ /* version agnostic attrs */
+ &dev_attr_version.attr,
+ &dev_attr_capabilities.attr,
++ &dev_attr_read_typ.attr,
++ &dev_attr_read_max.attr,
+
++ /* 1.2 attrs */
+ &dev_attr_vendor_opcode.attr,
+ &dev_attr_device_mode.attr,
+ &dev_attr_media_manager.attr,
+@@ -1211,8 +1230,6 @@ static struct attribute *nvm_dev_attrs_1
+ &dev_attr_page_size.attr,
+ &dev_attr_hw_sector_size.attr,
+ &dev_attr_oob_sector_size.attr,
+- &dev_attr_read_typ.attr,
+- &dev_attr_read_max.attr,
+ &dev_attr_prog_typ.attr,
+ &dev_attr_prog_max.attr,
+ &dev_attr_erase_typ.attr,
+@@ -1221,33 +1238,7 @@ static struct attribute *nvm_dev_attrs_1
+ &dev_attr_media_capabilities.attr,
+ &dev_attr_max_phys_secs.attr,
+
+- NULL,
+-};
+-
+-static const struct attribute_group nvm_dev_attr_group_12 = {
+- .name = "lightnvm",
+- .attrs = nvm_dev_attrs_12,
+-};
+-
+-/* 2.0 values */
+-static NVM_DEV_ATTR_20_RO(groups);
+-static NVM_DEV_ATTR_20_RO(punits);
+-static NVM_DEV_ATTR_20_RO(chunks);
+-static NVM_DEV_ATTR_20_RO(clba);
+-static NVM_DEV_ATTR_20_RO(ws_min);
+-static NVM_DEV_ATTR_20_RO(ws_opt);
+-static NVM_DEV_ATTR_20_RO(maxoc);
+-static NVM_DEV_ATTR_20_RO(maxocpu);
+-static NVM_DEV_ATTR_20_RO(mw_cunits);
+-static NVM_DEV_ATTR_20_RO(write_typ);
+-static NVM_DEV_ATTR_20_RO(write_max);
+-static NVM_DEV_ATTR_20_RO(reset_typ);
+-static NVM_DEV_ATTR_20_RO(reset_max);
+-
+-static struct attribute *nvm_dev_attrs_20[] = {
+- &dev_attr_version.attr,
+- &dev_attr_capabilities.attr,
+-
++ /* 2.0 attrs */
+ &dev_attr_groups.attr,
+ &dev_attr_punits.attr,
+ &dev_attr_chunks.attr,
+@@ -1258,8 +1249,6 @@ static struct attribute *nvm_dev_attrs_2
+ &dev_attr_maxocpu.attr,
+ &dev_attr_mw_cunits.attr,
+
+- &dev_attr_read_typ.attr,
+- &dev_attr_read_max.attr,
+ &dev_attr_write_typ.attr,
+ &dev_attr_write_max.attr,
+ &dev_attr_reset_typ.attr,
+@@ -1268,44 +1257,38 @@ static struct attribute *nvm_dev_attrs_2
+ NULL,
+ };
+
+-static const struct attribute_group nvm_dev_attr_group_20 = {
+- .name = "lightnvm",
+- .attrs = nvm_dev_attrs_20,
+-};
+-
+-int nvme_nvm_register_sysfs(struct nvme_ns *ns)
++static umode_t nvm_dev_attrs_visible(struct kobject *kobj,
++ struct attribute *attr, int index)
+ {
++ struct device *dev = container_of(kobj, struct device, kobj);
++ struct gendisk *disk = dev_to_disk(dev);
++ struct nvme_ns *ns = disk->private_data;
+ struct nvm_dev *ndev = ns->ndev;
+- struct nvm_geo *geo = &ndev->geo;
++ struct device_attribute *dev_attr =
++ container_of(attr, typeof(*dev_attr), attr);
+
+ if (!ndev)
+- return -EINVAL;
+-
+- switch (geo->major_ver_id) {
+- case 1:
+- return sysfs_create_group(&disk_to_dev(ns->disk)->kobj,
+- &nvm_dev_attr_group_12);
+- case 2:
+- return sysfs_create_group(&disk_to_dev(ns->disk)->kobj,
+- &nvm_dev_attr_group_20);
+- }
++ return 0;
+
+- return -EINVAL;
+-}
++ if (dev_attr->show == nvm_dev_attr_show)
++ return attr->mode;
+
+-void nvme_nvm_unregister_sysfs(struct nvme_ns *ns)
+-{
+- struct nvm_dev *ndev = ns->ndev;
+- struct nvm_geo *geo = &ndev->geo;
+-
+- switch (geo->major_ver_id) {
++ switch (ndev->geo.major_ver_id) {
+ case 1:
+- sysfs_remove_group(&disk_to_dev(ns->disk)->kobj,
+- &nvm_dev_attr_group_12);
++ if (dev_attr->show == nvm_dev_attr_show_12)
++ return attr->mode;
+ break;
+ case 2:
+- sysfs_remove_group(&disk_to_dev(ns->disk)->kobj,
+- &nvm_dev_attr_group_20);
++ if (dev_attr->show == nvm_dev_attr_show_20)
++ return attr->mode;
+ break;
+ }
++
++ return 0;
+ }
++
++const struct attribute_group nvme_nvm_attr_group = {
++ .name = "lightnvm",
++ .attrs = nvm_dev_attrs,
++ .is_visible = nvm_dev_attrs_visible,
++};
+--- a/drivers/nvme/host/multipath.c
++++ b/drivers/nvme/host/multipath.c
+@@ -313,13 +313,9 @@ static void nvme_mpath_set_live(struct n
+ if (!head->disk)
+ return;
+
+- if (!(head->disk->flags & GENHD_FL_UP)) {
+- device_add_disk(&head->subsys->dev, head->disk, NULL);
+- if (sysfs_create_group(&disk_to_dev(head->disk)->kobj,
+- &nvme_ns_id_attr_group))
+- dev_warn(&head->subsys->dev,
+- "failed to create id group.\n");
+- }
++ if (!(head->disk->flags & GENHD_FL_UP))
++ device_add_disk(&head->subsys->dev, head->disk,
++ nvme_ns_id_attr_groups);
+
+ synchronize_srcu(&ns->head->srcu);
+ kblockd_schedule_work(&ns->head->requeue_work);
+@@ -541,11 +537,8 @@ void nvme_mpath_remove_disk(struct nvme_
+ {
+ if (!head->disk)
+ return;
+- if (head->disk->flags & GENHD_FL_UP) {
+- sysfs_remove_group(&disk_to_dev(head->disk)->kobj,
+- &nvme_ns_id_attr_group);
++ if (head->disk->flags & GENHD_FL_UP)
+ del_gendisk(head->disk);
+- }
+ blk_set_queue_dying(head->disk->queue);
+ /* make sure all pending bios are cleaned up */
+ kblockd_schedule_work(&head->requeue_work);
+--- a/drivers/nvme/host/nvme.h
++++ b/drivers/nvme/host/nvme.h
+@@ -464,7 +464,7 @@ int nvme_delete_ctrl_sync(struct nvme_ct
+ int nvme_get_log(struct nvme_ctrl *ctrl, u32 nsid, u8 log_page, u8 lsp,
+ void *log, size_t size, u64 offset);
+
+-extern const struct attribute_group nvme_ns_id_attr_group;
++extern const struct attribute_group *nvme_ns_id_attr_groups[];
+ extern const struct block_device_operations nvme_ns_head_ops;
+
+ #ifdef CONFIG_NVME_MULTIPATH
+@@ -589,8 +589,7 @@ static inline void nvme_mpath_update_dis
+ void nvme_nvm_update_nvm_info(struct nvme_ns *ns);
+ int nvme_nvm_register(struct nvme_ns *ns, char *disk_name, int node);
+ void nvme_nvm_unregister(struct nvme_ns *ns);
+-int nvme_nvm_register_sysfs(struct nvme_ns *ns);
+-void nvme_nvm_unregister_sysfs(struct nvme_ns *ns);
++extern const struct attribute_group nvme_nvm_attr_group;
+ int nvme_nvm_ioctl(struct nvme_ns *ns, unsigned int cmd, unsigned long arg);
+ #else
+ static inline void nvme_nvm_update_nvm_info(struct nvme_ns *ns) {};
+@@ -601,11 +600,6 @@ static inline int nvme_nvm_register(stru
+ }
+
+ static inline void nvme_nvm_unregister(struct nvme_ns *ns) {};
+-static inline int nvme_nvm_register_sysfs(struct nvme_ns *ns)
+-{
+- return 0;
+-}
+-static inline void nvme_nvm_unregister_sysfs(struct nvme_ns *ns) {};
+ static inline int nvme_nvm_ioctl(struct nvme_ns *ns, unsigned int cmd,
+ unsigned long arg)
+ {
--- /dev/null
+From foo@baz Sun Mar 7 04:13:19 PM CET 2021
+From: Jeffle Xu <jefflexu@linux.alibaba.com>
+Date: Tue, 23 Feb 2021 17:28:54 +0800
+Subject: Revert "zram: close udev startup race condition as default groups"
+To: gregkh@linuxfoundation.org, sashal@kernel.org
+Cc: stable@vger.kernel.org, joseph.qi@linux.alibaba.com, jefflexu@linux.alibaba.com, hare@suse.com
+Message-ID: <20210223092859.17033-2-jefflexu@linux.alibaba.com>
+
+From: Jeffle Xu <jefflexu@linux.alibaba.com>
+
+This reverts commit 9e07f4e243791e00a4086ad86e573705cf7b2c65.
+
+The original commit is actually a "merged" fix of [1] and [2], as
+described in [3]. Since now we have more fixes that rely on [1], revert
+this commit first, and then get the original [1] and [2] merged.
+
+[1] fef912bf860e, block: genhd: add 'groups' argument to device_add_disk
+[2] 98af4d4df889, zram: register default groups with device_add_disk()
+[3] https://www.spinics.net/lists/stable/msg442196.html
+
+Signed-off-by: Jeffle Xu <jefflexu@linux.alibaba.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/block/zram/zram_drv.c | 26 ++++++++++++++++++++------
+ 1 file changed, 20 insertions(+), 6 deletions(-)
+
+--- a/drivers/block/zram/zram_drv.c
++++ b/drivers/block/zram/zram_drv.c
+@@ -1644,11 +1644,6 @@ static const struct attribute_group zram
+ .attrs = zram_disk_attrs,
+ };
+
+-static const struct attribute_group *zram_disk_attr_groups[] = {
+- &zram_disk_attr_group,
+- NULL,
+-};
+-
+ /*
+ * Allocate and initialize new zram device. the function returns
+ * '>= 0' device_id upon success, and negative value otherwise.
+@@ -1729,15 +1724,24 @@ static int zram_add(void)
+
+ zram->disk->queue->backing_dev_info->capabilities |=
+ (BDI_CAP_STABLE_WRITES | BDI_CAP_SYNCHRONOUS_IO);
+- disk_to_dev(zram->disk)->groups = zram_disk_attr_groups;
+ add_disk(zram->disk);
+
++ ret = sysfs_create_group(&disk_to_dev(zram->disk)->kobj,
++ &zram_disk_attr_group);
++ if (ret < 0) {
++ pr_err("Error creating sysfs group for device %d\n",
++ device_id);
++ goto out_free_disk;
++ }
+ strlcpy(zram->compressor, default_compressor, sizeof(zram->compressor));
+
+ zram_debugfs_register(zram);
+ pr_info("Added device: %s\n", zram->disk->disk_name);
+ return device_id;
+
++out_free_disk:
++ del_gendisk(zram->disk);
++ put_disk(zram->disk);
+ out_free_queue:
+ blk_cleanup_queue(queue);
+ out_free_idr:
+@@ -1766,6 +1770,16 @@ static int zram_remove(struct zram *zram
+ mutex_unlock(&bdev->bd_mutex);
+
+ zram_debugfs_unregister(zram);
++ /*
++ * Remove sysfs first, so no one will perform a disksize
++ * store while we destroy the devices. This also helps during
++ * hot_remove -- zram_reset_device() is the last holder of
++ * ->init_lock, no later/concurrent disksize_store() or any
++ * other sysfs handlers are possible.
++ */
++ sysfs_remove_group(&disk_to_dev(zram->disk)->kobj,
++ &zram_disk_attr_group);
++
+ /* Make sure all the pending I/O are finished */
+ fsync_bdev(bdev);
+ zram_reset_device(zram);
pm-runtime-update-device-status-before-letting-suppliers-suspend.patch
dm-bufio-subtract-the-number-of-initial-sectors-in-dm_bufio_get_device_size.patch
drm-amdgpu-fix-parameter-error-of-rreg32_pcie-in-amdgpu_regs_pcie.patch
+usbip-tools-fix-build-error-for-multiple-definition.patch
+revert-zram-close-udev-startup-race-condition-as-default-groups.patch
+block-genhd-add-groups-argument-to-device_add_disk.patch
+nvme-register-ns_id-attributes-as-default-sysfs-groups.patch
+aoe-register-default-groups-with-device_add_disk.patch
+zram-register-default-groups-with-device_add_disk.patch
+virtio-blk-modernize-sysfs-attribute-creation.patch
--- /dev/null
+From d5efc2e6b98fe661dbd8dd0d5d5bfb961728e57a Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Thu, 18 Jun 2020 02:08:44 +0200
+Subject: usbip: tools: fix build error for multiple definition
+
+From: Antonio Borneo <borneo.antonio@gmail.com>
+
+commit d5efc2e6b98fe661dbd8dd0d5d5bfb961728e57a upstream.
+
+With GCC 10, building usbip triggers error for multiple definition
+of 'udev_context', in:
+- libsrc/vhci_driver.c:18 and
+- libsrc/usbip_host_common.c:27.
+
+Declare as extern the definition in libsrc/usbip_host_common.c.
+
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Acked-by: Shuah Khan <skhan@linuxfoundation.org>
+Link: https://lore.kernel.org/r/20200618000844.1048309-1-borneo.antonio@gmail.com
+Cc: Petr Štetiar <ynezz@true.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ tools/usb/usbip/libsrc/usbip_host_common.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/tools/usb/usbip/libsrc/usbip_host_common.c
++++ b/tools/usb/usbip/libsrc/usbip_host_common.c
+@@ -35,7 +35,7 @@
+ #include "list.h"
+ #include "sysfs_utils.h"
+
+-struct udev *udev_context;
++extern struct udev *udev_context;
+
+ static int32_t read_attr_usbip_status(struct usbip_usb_device *udev)
+ {
--- /dev/null
+From foo@baz Sun Mar 7 04:13:19 PM CET 2021
+From: Jeffle Xu <jefflexu@linux.alibaba.com>
+Date: Tue, 23 Feb 2021 17:28:59 +0800
+Subject: virtio-blk: modernize sysfs attribute creation
+To: gregkh@linuxfoundation.org, sashal@kernel.org
+Cc: stable@vger.kernel.org, joseph.qi@linux.alibaba.com, jefflexu@linux.alibaba.com, hare@suse.com
+Message-ID: <20210223092859.17033-7-jefflexu@linux.alibaba.com>
+
+From: Hannes Reinecke <hare@suse.de>
+
+commit e982c4d0a29b1d61fbe7716a8dcf8984936d6730 upstream.
+
+Use new-style DEVICE_ATTR_RO/DEVICE_ATTR_RW to create the sysfs attributes
+and register the disk with default sysfs attribute groups.
+
+Signed-off-by: Hannes Reinecke <hare@suse.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Acked-by: Michael S. Tsirkin <mst@redhat.com>
+Reviewed-by: Bart Van Assche <bart.vanassche@wdc.com>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Jeffle Xu <jefflexu@linux.alibaba.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/block/virtio_blk.c | 68 +++++++++++++++++++++++++--------------------
+ 1 file changed, 39 insertions(+), 29 deletions(-)
+
+--- a/drivers/block/virtio_blk.c
++++ b/drivers/block/virtio_blk.c
+@@ -423,8 +423,8 @@ static int minor_to_index(int minor)
+ return minor >> PART_BITS;
+ }
+
+-static ssize_t virtblk_serial_show(struct device *dev,
+- struct device_attribute *attr, char *buf)
++static ssize_t serial_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+ struct gendisk *disk = dev_to_disk(dev);
+ int err;
+@@ -443,7 +443,7 @@ static ssize_t virtblk_serial_show(struc
+ return err;
+ }
+
+-static DEVICE_ATTR(serial, 0444, virtblk_serial_show, NULL);
++static DEVICE_ATTR_RO(serial);
+
+ /* The queue's logical block size must be set before calling this */
+ static void virtblk_update_capacity(struct virtio_blk *vblk, bool resize)
+@@ -619,8 +619,8 @@ static const char *const virtblk_cache_t
+ };
+
+ static ssize_t
+-virtblk_cache_type_store(struct device *dev, struct device_attribute *attr,
+- const char *buf, size_t count)
++cache_type_store(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+ struct gendisk *disk = dev_to_disk(dev);
+ struct virtio_blk *vblk = disk->private_data;
+@@ -638,8 +638,7 @@ virtblk_cache_type_store(struct device *
+ }
+
+ static ssize_t
+-virtblk_cache_type_show(struct device *dev, struct device_attribute *attr,
+- char *buf)
++cache_type_show(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+ struct gendisk *disk = dev_to_disk(dev);
+ struct virtio_blk *vblk = disk->private_data;
+@@ -649,12 +648,38 @@ virtblk_cache_type_show(struct device *d
+ return snprintf(buf, 40, "%s\n", virtblk_cache_types[writeback]);
+ }
+
+-static const struct device_attribute dev_attr_cache_type_ro =
+- __ATTR(cache_type, 0444,
+- virtblk_cache_type_show, NULL);
+-static const struct device_attribute dev_attr_cache_type_rw =
+- __ATTR(cache_type, 0644,
+- virtblk_cache_type_show, virtblk_cache_type_store);
++static DEVICE_ATTR_RW(cache_type);
++
++static struct attribute *virtblk_attrs[] = {
++ &dev_attr_serial.attr,
++ &dev_attr_cache_type.attr,
++ NULL,
++};
++
++static umode_t virtblk_attrs_are_visible(struct kobject *kobj,
++ struct attribute *a, int n)
++{
++ struct device *dev = container_of(kobj, struct device, kobj);
++ struct gendisk *disk = dev_to_disk(dev);
++ struct virtio_blk *vblk = disk->private_data;
++ struct virtio_device *vdev = vblk->vdev;
++
++ if (a == &dev_attr_cache_type.attr &&
++ !virtio_has_feature(vdev, VIRTIO_BLK_F_CONFIG_WCE))
++ return S_IRUGO;
++
++ return a->mode;
++}
++
++static const struct attribute_group virtblk_attr_group = {
++ .attrs = virtblk_attrs,
++ .is_visible = virtblk_attrs_are_visible,
++};
++
++static const struct attribute_group *virtblk_attr_groups[] = {
++ &virtblk_attr_group,
++ NULL,
++};
+
+ static int virtblk_init_request(struct blk_mq_tag_set *set, struct request *rq,
+ unsigned int hctx_idx, unsigned int numa_node)
+@@ -858,24 +883,9 @@ static int virtblk_probe(struct virtio_d
+ virtblk_update_capacity(vblk, false);
+ virtio_device_ready(vdev);
+
+- device_add_disk(&vdev->dev, vblk->disk, NULL);
+- err = device_create_file(disk_to_dev(vblk->disk), &dev_attr_serial);
+- if (err)
+- goto out_del_disk;
+-
+- if (virtio_has_feature(vdev, VIRTIO_BLK_F_CONFIG_WCE))
+- err = device_create_file(disk_to_dev(vblk->disk),
+- &dev_attr_cache_type_rw);
+- else
+- err = device_create_file(disk_to_dev(vblk->disk),
+- &dev_attr_cache_type_ro);
+- if (err)
+- goto out_del_disk;
++ device_add_disk(&vdev->dev, vblk->disk, virtblk_attr_groups);
+ return 0;
+
+-out_del_disk:
+- del_gendisk(vblk->disk);
+- blk_cleanup_queue(vblk->disk->queue);
+ out_free_tags:
+ blk_mq_free_tag_set(&vblk->tag_set);
+ out_put_disk:
--- /dev/null
+From foo@baz Sun Mar 7 04:13:19 PM CET 2021
+From: Jeffle Xu <jefflexu@linux.alibaba.com>
+Date: Tue, 23 Feb 2021 17:28:58 +0800
+Subject: zram: register default groups with device_add_disk()
+To: gregkh@linuxfoundation.org, sashal@kernel.org
+Cc: stable@vger.kernel.org, joseph.qi@linux.alibaba.com, jefflexu@linux.alibaba.com, hare@suse.com
+Message-ID: <20210223092859.17033-6-jefflexu@linux.alibaba.com>
+
+From: Hannes Reinecke <hare@suse.de>
+
+commit 98af4d4df889dcea3bc0ce6b8a04759658ba8826 upstream.
+
+Register default sysfs groups during device_add_disk() to avoid a
+race condition with udev during startup.
+
+Signed-off-by: Hannes Reinecke <hare@suse.com>
+Cc: Minchan Kim <minchan@kernel.org>
+Cc: Nitin Gupta <ngupta@vflare.org>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Bart Van Assche <bart.vanassche@wdc.com>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Jeffle Xu <jefflexu@linux.alibaba.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/block/zram/zram_drv.c | 26 ++++++--------------------
+ 1 file changed, 6 insertions(+), 20 deletions(-)
+
+--- a/drivers/block/zram/zram_drv.c
++++ b/drivers/block/zram/zram_drv.c
+@@ -1644,6 +1644,11 @@ static const struct attribute_group zram
+ .attrs = zram_disk_attrs,
+ };
+
++static const struct attribute_group *zram_disk_attr_groups[] = {
++ &zram_disk_attr_group,
++ NULL,
++};
++
+ /*
+ * Allocate and initialize new zram device. the function returns
+ * '>= 0' device_id upon success, and negative value otherwise.
+@@ -1724,24 +1729,14 @@ static int zram_add(void)
+
+ zram->disk->queue->backing_dev_info->capabilities |=
+ (BDI_CAP_STABLE_WRITES | BDI_CAP_SYNCHRONOUS_IO);
+- add_disk(zram->disk);
++ device_add_disk(NULL, zram->disk, zram_disk_attr_groups);
+
+- ret = sysfs_create_group(&disk_to_dev(zram->disk)->kobj,
+- &zram_disk_attr_group);
+- if (ret < 0) {
+- pr_err("Error creating sysfs group for device %d\n",
+- device_id);
+- goto out_free_disk;
+- }
+ strlcpy(zram->compressor, default_compressor, sizeof(zram->compressor));
+
+ zram_debugfs_register(zram);
+ pr_info("Added device: %s\n", zram->disk->disk_name);
+ return device_id;
+
+-out_free_disk:
+- del_gendisk(zram->disk);
+- put_disk(zram->disk);
+ out_free_queue:
+ blk_cleanup_queue(queue);
+ out_free_idr:
+@@ -1770,15 +1765,6 @@ static int zram_remove(struct zram *zram
+ mutex_unlock(&bdev->bd_mutex);
+
+ zram_debugfs_unregister(zram);
+- /*
+- * Remove sysfs first, so no one will perform a disksize
+- * store while we destroy the devices. This also helps during
+- * hot_remove -- zram_reset_device() is the last holder of
+- * ->init_lock, no later/concurrent disksize_store() or any
+- * other sysfs handlers are possible.
+- */
+- sysfs_remove_group(&disk_to_dev(zram->disk)->kobj,
+- &zram_disk_attr_group);
+
+ /* Make sure all the pending I/O are finished */
+ fsync_bdev(bdev);