Orabug:
28945039
Inspired by upstream commit
df08c32ce3be5be138c1dbfcba203314a3a7cd6f
The kABI breakage caused by the above upstream commit cannot be fixed
by the uek_abi facilities because it extends a data structure which is
embedded inside other data structures in block and filesystem codes.
This patch fixes the breakage by moving the "owner" field from
backing_dev_info to request_queue structure, it's safe to do this for
below reasons:
o the purpose of the upstream commit is just hold a reference to
the gendisk in backing_dev_info to sync their lifetimes
o the backing_dev_info is embedded into the request_queue, which
means their lifetimes are in sync
o so the lifetime of gendisk can be synced with any of request_queue
or backing_dev_info
o syncing with request_queue does not break kABI
o we extended the request_queue structure previously and no third
party binary driver breakage was reported
The reason why crafted another patch instead of cherry-picking the
upstream commit directly is that because including of blkdev.h
in mm/backing_dev.c broke kABI too, note it's just inclusion without
other changes.
Open coded the get/set of owner field of request_queue to reduce the
impact on blkdev.h to avoid other potential kABI breakage.
v2:
o move put owner after bdi_destroy(), followed the suggestion from
Ashish Samant <ashish.samant@oracle.com>
o update inline comment
Signed-off-by: Shan Hai <shan.hai@oracle.com>
Reviewed-by: Ashish Samant <ashish.samant@oracle.com>
Signed-off-by: Brian Maly <brian.maly@oracle.com>
bdi_destroy(&q->backing_dev_info);
+ if (q->owner) {
+ put_device(q->owner);
+ q->owner = NULL;
+ }
+
/* @q is and will stay empty, shutdown and put */
blk_put_queue(q);
}
/* Register BDI before referencing it from bdev */
bdi = &disk->queue->backing_dev_info;
bdi_register_dev(bdi, disk_devt(disk));
+ /*
+ * Get ref on gendisk and put it on blk_cleanup_queue() to avoid
+ * reuse of the same devt as name of bdi since the gendisk can be
+ * destroyed before bdi.
+ */
+ disk->queue->owner = disk_to_dev(disk);
+ get_device(disk->queue->owner);
blk_register_region(disk_devt(disk), disk->minors, NULL,
exact_match, exact_lock, disk);
struct blk_mq_tag_set *tag_set;
struct list_head tag_set_list;
UEK_KABI_EXTEND(struct work_struct timeout_work)
+ UEK_KABI_EXTEND(struct device *owner)
};
#define QUEUE_FLAG_QUEUED 1 /* uses generic tag queueing */