Received: by 2002:a05:6a10:a0d1:0:0:0:0 with SMTP id j17csp3448562pxa; Wed, 26 Aug 2020 00:02:50 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxTKypLdrCRI51CgAp39b4jc4qPSFGClbmX2aJoEeKugLRg3zfmqN8Spn8jdhf5V/oA8FSa X-Received: by 2002:a17:906:2296:: with SMTP id p22mr14198292eja.510.1598425370130; Wed, 26 Aug 2020 00:02:50 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1598425370; cv=none; d=google.com; s=arc-20160816; b=pQ7arIIPnUHiPeF9JWc9I/1fL6tjf2kgPagyRtwtr4/RWD0AV5fH5T3uU7J6cLmIwZ aTXfxArMX8l/HmJqAcjMdesNrdL3/BZUGCffJUf8rB26vppzq+MjRgaGbK+co4aYFER+ X0+e1TRjLlnqSnOtb9L9PhLIFRiE15qNBSSGSbFnrfSZUIvjLnhea+7WmW3Bxpk4laPB cbb8piHg+Kd34l0pZ5ErgIjyNDkxIF3s/bbUNnY4phmhUwn7VnzPuVyIu2HUKZtRcU/N yuo4Yo066ir1z2k56rtoZ+um178Ofoze2oZFUORDPCnYqhKMCllRbIw5UZG3v3yzhXH0 ejVg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=BZmzuzcN7BR56jKzhMqx/iElPzxOZdyo7h8lorg9pJU=; b=It4CZrHIv4wLLTPbvleE6AbRa51C0+aOvyolkqsnk3q4+XPutyca+1Lw+3KXIEBgf+ eB9FjcHasZNGBl/kxEd5jVel2pyruAjvVW4jOQKHj/zOoHzziq/LWLexDfhBoq0HplPz X9131ZUOnOXmWHvdDokk9U1mywp39JUUbZr14QhePX2b4IOL7f2RpsyLmQWiKrCFunHM F5MqPAqzb/o6LpcQc8hutd+tI10RyUpDKL9gaqLgf98ahc6wofVgko50AOR1B9QSfR4c WuNQiaL1NASybkeUKeaBd9NMoEKjBzYxUJzmRExHYbwN4YR4vbYFVIarvYy6i7IV3geW NyVw== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@infradead.org header.s=casper.20170209 header.b=NMSwFWI0; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id d21si922185edp.267.2020.08.26.00.02.27; Wed, 26 Aug 2020 00:02:50 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=fail header.i=@infradead.org header.s=casper.20170209 header.b=NMSwFWI0; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727012AbgHZHBn (ORCPT + 99 others); Wed, 26 Aug 2020 03:01:43 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45458 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726856AbgHZHAM (ORCPT ); Wed, 26 Aug 2020 03:00:12 -0400 Received: from casper.infradead.org (casper.infradead.org [IPv6:2001:8b0:10b:1236::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9A2F6C061786; Wed, 26 Aug 2020 00:00:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To: Content-Type:Content-ID:Content-Description; bh=BZmzuzcN7BR56jKzhMqx/iElPzxOZdyo7h8lorg9pJU=; b=NMSwFWI0aNVPdmlBwry20ZNi6/ 75ZWifY6T3b+V/5F0sil22u77lVXgraoNSPHkGMc/pqPPaDxM2KFL/iearEYoWx4QBNLyhJexOe3x xVqVByMQE4bwC7fOh02QoKY/EbWU/u+VIB0p9fFDyTTQk7QAkvIyun623cucCZHq4cANTmm4Tqpn3 EkRxj1nl95YjEFO+vB1Qum+8AJyPky620MqlUcS2zpVIHr7kV9+MnDICbKC10Ctrr4JX09lpmtTQi VsXYyxljmbYJgClPxYZbiOFuuBRg7BsJqsxDyuueHo0ZyRAXSRrFQY7qPOFiwvgVPEwYuX40bLbV/ 09bYaf1A==; Received: from [2001:4bb8:18c:45ba:9892:9e86:5202:32f0] (helo=localhost) by casper.infradead.org with esmtpsa (Exim 4.92.3 #3 (Red Hat Linux)) id 1kApPg-0003lr-Jz; Wed, 26 Aug 2020 07:00:05 +0000 From: Christoph Hellwig To: Jens Axboe Cc: Greg Kroah-Hartman , "Rafael J. Wysocki" , Denis Efremov , "David S. Miller" , Song Liu , Al Viro , linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-ide@vger.kernel.org, linux-raid@vger.kernel.org, linux-scsi@vger.kernel.org, linux-m68k@lists.linux-m68k.org Subject: [PATCH 19/19] block: switch gendisk lookup to a simple xarray Date: Wed, 26 Aug 2020 08:24:46 +0200 Message-Id: <20200826062446.31860-20-hch@lst.de> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200826062446.31860-1-hch@lst.de> References: <20200826062446.31860-1-hch@lst.de> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SRS-Rewrite: SMTP reverse-path rewritten from by casper.infradead.org. See http://www.infradead.org/rpr.html Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Now that bdev_map is only used for finding gendisks, we can use a simple xarray instead of the regions tracking structure for it. Signed-off-by: Christoph Hellwig --- block/genhd.c | 210 ++++++++---------------------------------- include/linux/genhd.h | 7 -- 2 files changed, 38 insertions(+), 179 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index 4cbeff3ec1ef5a..80afacaf15f740 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -27,15 +27,7 @@ static struct kobject *block_depr; -struct bdev_map { - struct bdev_map *next; - dev_t dev; - unsigned long range; - struct module *owner; - struct kobject *(*probe)(dev_t, int *, void *); - int (*lock)(dev_t, void *); - void *data; -} *bdev_map[255]; +static DEFINE_XARRAY(bdev_map); static DEFINE_MUTEX(bdev_map_lock); /* for extended dynamic devt allocation, currently only one major is used */ @@ -649,85 +641,26 @@ static char *bdevt_str(dev_t devt, char *buf) return buf; } -/* - * Register device numbers dev..(dev+range-1) - * range must be nonzero - * The hash chain is sorted on range, so that subranges can override. - */ -void blk_register_region(dev_t devt, unsigned long range, struct module *module, - struct kobject *(*probe)(dev_t, int *, void *), - int (*lock)(dev_t, void *), void *data) -{ - unsigned n = MAJOR(devt + range - 1) - MAJOR(devt) + 1; - unsigned index = MAJOR(devt); - unsigned i; - struct bdev_map *p; - - n = min(n, 255u); - p = kmalloc_array(n, sizeof(struct bdev_map), GFP_KERNEL); - if (p == NULL) - return; - - for (i = 0; i < n; i++, p++) { - p->owner = module; - p->probe = probe; - p->lock = lock; - p->dev = devt; - p->range = range; - p->data = data; - } - - mutex_lock(&bdev_map_lock); - for (i = 0, p -= n; i < n; i++, p++, index++) { - struct bdev_map **s = &bdev_map[index % 255]; - while (*s && (*s)->range < range) - s = &(*s)->next; - p->next = *s; - *s = p; - } - mutex_unlock(&bdev_map_lock); -} -EXPORT_SYMBOL(blk_register_region); - -void blk_unregister_region(dev_t devt, unsigned long range) +static void blk_register_region(struct gendisk *disk) { - unsigned n = MAJOR(devt + range - 1) - MAJOR(devt) + 1; - unsigned index = MAJOR(devt); - unsigned i; - struct bdev_map *found = NULL; + int i; mutex_lock(&bdev_map_lock); - for (i = 0; i < min(n, 255u); i++, index++) { - struct bdev_map **s; - for (s = &bdev_map[index % 255]; *s; s = &(*s)->next) { - struct bdev_map *p = *s; - if (p->dev == devt && p->range == range) { - *s = p->next; - if (!found) - found = p; - break; - } - } + for (i = 0; i < disk->minors; i++) { + if (xa_insert(&bdev_map, disk_devt(disk) + i, disk, GFP_KERNEL)) + WARN_ON_ONCE(1); } mutex_unlock(&bdev_map_lock); - kfree(found); } -EXPORT_SYMBOL(blk_unregister_region); -static struct kobject *exact_match(dev_t devt, int *partno, void *data) +static void blk_unregister_region(struct gendisk *disk) { - struct gendisk *p = data; - - return &disk_to_dev(p)->kobj; -} - -static int exact_lock(dev_t devt, void *data) -{ - struct gendisk *p = data; + int i; - if (!get_disk_and_module(p)) - return -1; - return 0; + mutex_lock(&bdev_map_lock); + for (i = 0; i < disk->minors; i++) + xa_erase(&bdev_map, disk_devt(disk) + i); + mutex_lock(&bdev_map_lock); } static void register_disk(struct device *parent, struct gendisk *disk, @@ -878,8 +811,7 @@ static void __device_add_disk(struct device *parent, struct gendisk *disk, ret = bdi_register(bdi, "%u:%u", MAJOR(devt), MINOR(devt)); WARN_ON(ret); bdi_set_owner(bdi, dev); - blk_register_region(disk_devt(disk), disk->minors, NULL, - exact_match, exact_lock, disk); + blk_register_region(disk); } register_disk(parent, disk, groups); if (register_queue) @@ -987,7 +919,7 @@ void del_gendisk(struct gendisk *disk) */ bdi_unregister(disk->queue->backing_dev_info); blk_unregister_queue(disk); - blk_unregister_region(disk_devt(disk), disk->minors); + blk_unregister_region(disk); } else { blk_unregister_queue(disk); } @@ -1057,54 +989,22 @@ static void request_gendisk_module(dev_t devt) request_module("block-major-%d", MAJOR(devt)); } -static struct gendisk *lookup_gendisk(dev_t dev, int *partno) +static bool get_disk_and_module(struct gendisk *disk) { - struct kobject *kobj; - struct bdev_map *p; - unsigned long best = ~0UL; - -retry: - mutex_lock(&bdev_map_lock); - for (p = bdev_map[MAJOR(dev) % 255]; p; p = p->next) { - struct kobject *(*probe)(dev_t, int *, void *); - struct module *owner; - void *data; - - if (p->dev > dev || p->dev + p->range - 1 < dev) - continue; - if (p->range - 1 >= best) - break; - if (!try_module_get(p->owner)) - continue; - owner = p->owner; - data = p->data; - probe = p->probe; - best = p->range - 1; - *partno = dev - p->dev; - - if (!probe) { - mutex_unlock(&bdev_map_lock); - module_put(owner); - request_gendisk_module(dev); - goto retry; - } + struct module *owner; - if (p->lock && p->lock(dev, data) < 0) { - module_put(owner); - continue; - } - mutex_unlock(&bdev_map_lock); - kobj = probe(dev, partno, data); - /* Currently ->owner protects _only_ ->probe() itself. */ + if (!disk->fops) + return false; + owner = disk->fops->owner; + if (owner && !try_module_get(owner)) + return false; + if (!kobject_get_unless_zero(&disk_to_dev(disk)->kobj)) { module_put(owner); - if (kobj) - return dev_to_disk(kobj_to_dev(kobj)); - goto retry; + return false; } - mutex_unlock(&bdev_map_lock); - return NULL; -} + return true; +} /** * get_gendisk - get partitioning information for a given device @@ -1123,7 +1023,19 @@ struct gendisk *get_gendisk(dev_t devt, int *partno) might_sleep(); if (MAJOR(devt) != BLOCK_EXT_MAJOR) { - disk = lookup_gendisk(devt, partno); + mutex_lock(&bdev_map_lock); + disk = xa_load(&bdev_map, devt); + if (!disk) { + mutex_unlock(&bdev_map_lock); + request_gendisk_module(devt); + mutex_lock(&bdev_map_lock); + disk = xa_load(&bdev_map, devt); + } + if (disk && !get_disk_and_module(disk)) + disk = NULL; + if (disk) + *partno = devt - disk_devt(disk); + mutex_unlock(&bdev_map_lock); } else { struct hd_struct *part; @@ -1327,21 +1239,6 @@ static const struct seq_operations partitions_op = { }; #endif -static void bdev_map_init(void) -{ - struct bdev_map *base; - int i; - - base = kzalloc(sizeof(*base), GFP_KERNEL); - if (!base) - panic("cannot allocate bdev_map"); - - base->dev = 1; - base->range = ~0 ; - for (i = 0; i < 255; i++) - bdev_map[i] = base; -} - static int __init genhd_device_init(void) { int error; @@ -1350,7 +1247,6 @@ static int __init genhd_device_init(void) error = class_register(&block_class); if (unlikely(error)) return error; - bdev_map_init(); blk_dev_init(); register_blkdev(BLOCK_EXT_MAJOR, "blkext"); @@ -1896,35 +1792,6 @@ struct gendisk *__alloc_disk_node(int minors, int node_id) } EXPORT_SYMBOL(__alloc_disk_node); -/** - * get_disk_and_module - increments the gendisk and gendisk fops module refcount - * @disk: the struct gendisk to increment the refcount for - * - * This increments the refcount for the struct gendisk, and the gendisk's - * fops module owner. - * - * Context: Any context. - */ -struct kobject *get_disk_and_module(struct gendisk *disk) -{ - struct module *owner; - struct kobject *kobj; - - if (!disk->fops) - return NULL; - owner = disk->fops->owner; - if (owner && !try_module_get(owner)) - return NULL; - kobj = kobject_get_unless_zero(&disk_to_dev(disk)->kobj); - if (kobj == NULL) { - module_put(owner); - return NULL; - } - return kobj; - -} -EXPORT_SYMBOL(get_disk_and_module); - /** * put_disk - decrements the gendisk refcount * @disk: the struct gendisk to decrement the refcount for @@ -1961,7 +1828,6 @@ void put_disk_and_module(struct gendisk *disk) module_put(owner); } } -EXPORT_SYMBOL(put_disk_and_module); static void set_disk_ro_uevent(struct gendisk *gd, int ro) { diff --git a/include/linux/genhd.h b/include/linux/genhd.h index c0bde190a3dd0c..c6bdc8ce69bd87 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -341,15 +341,8 @@ int blk_add_partitions(struct gendisk *disk, struct block_device *bdev); int blk_drop_partitions(struct block_device *bdev); extern struct gendisk *__alloc_disk_node(int minors, int node_id); -extern struct kobject *get_disk_and_module(struct gendisk *disk); extern void put_disk(struct gendisk *disk); extern void put_disk_and_module(struct gendisk *disk); -extern void blk_register_region(dev_t devt, unsigned long range, - struct module *module, - struct kobject *(*probe)(dev_t, int *, void *), - int (*lock)(dev_t, void *), - void *data); -extern void blk_unregister_region(dev_t devt, unsigned long range); #define alloc_disk_node(minors, node_id) \ ({ \ -- 2.28.0