1// SPDX-License-Identifier: GPL-2.0
2/*
3 *  Block device concurrent positioning ranges.
4 *
5 *  Copyright (C) 2021 Western Digital Corporation or its Affiliates.
6 */
7#include <linux/kernel.h>
8#include <linux/blkdev.h>
9#include <linux/slab.h>
10#include <linux/init.h>
11
12#include "blk.h"
13
14static ssize_t
15blk_ia_range_sector_show(struct blk_independent_access_range *iar,
16			 char *buf)
17{
18	return sprintf(buf, "%llu\n", iar->sector);
19}
20
21static ssize_t
22blk_ia_range_nr_sectors_show(struct blk_independent_access_range *iar,
23			     char *buf)
24{
25	return sprintf(buf, "%llu\n", iar->nr_sectors);
26}
27
28struct blk_ia_range_sysfs_entry {
29	struct attribute attr;
30	ssize_t (*show)(struct blk_independent_access_range *iar, char *buf);
31};
32
33static struct blk_ia_range_sysfs_entry blk_ia_range_sector_entry = {
34	.attr = { .name = "sector", .mode = 0444 },
35	.show = blk_ia_range_sector_show,
36};
37
38static struct blk_ia_range_sysfs_entry blk_ia_range_nr_sectors_entry = {
39	.attr = { .name = "nr_sectors", .mode = 0444 },
40	.show = blk_ia_range_nr_sectors_show,
41};
42
43static struct attribute *blk_ia_range_attrs[] = {
44	&blk_ia_range_sector_entry.attr,
45	&blk_ia_range_nr_sectors_entry.attr,
46	NULL,
47};
48ATTRIBUTE_GROUPS(blk_ia_range);
49
50static ssize_t blk_ia_range_sysfs_show(struct kobject *kobj,
51				      struct attribute *attr, char *buf)
52{
53	struct blk_ia_range_sysfs_entry *entry =
54		container_of(attr, struct blk_ia_range_sysfs_entry, attr);
55	struct blk_independent_access_range *iar =
56		container_of(kobj, struct blk_independent_access_range, kobj);
57
58	return entry->show(iar, buf);
59}
60
61static const struct sysfs_ops blk_ia_range_sysfs_ops = {
62	.show	= blk_ia_range_sysfs_show,
63};
64
65/*
66 * Independent access range entries are not freed individually, but alltogether
67 * with struct blk_independent_access_ranges and its array of ranges. Since
68 * kobject_add() takes a reference on the parent kobject contained in
69 * struct blk_independent_access_ranges, the array of independent access range
70 * entries cannot be freed until kobject_del() is called for all entries.
71 * So we do not need to do anything here, but still need this no-op release
72 * operation to avoid complaints from the kobject code.
73 */
74static void blk_ia_range_sysfs_nop_release(struct kobject *kobj)
75{
76}
77
78static const struct kobj_type blk_ia_range_ktype = {
79	.sysfs_ops	= &blk_ia_range_sysfs_ops,
80	.default_groups	= blk_ia_range_groups,
81	.release	= blk_ia_range_sysfs_nop_release,
82};
83
84/*
85 * This will be executed only after all independent access range entries are
86 * removed with kobject_del(), at which point, it is safe to free everything,
87 * including the array of ranges.
88 */
89static void blk_ia_ranges_sysfs_release(struct kobject *kobj)
90{
91	struct blk_independent_access_ranges *iars =
92		container_of(kobj, struct blk_independent_access_ranges, kobj);
93
94	kfree(iars);
95}
96
97static const struct kobj_type blk_ia_ranges_ktype = {
98	.release	= blk_ia_ranges_sysfs_release,
99};
100
101/**
102 * disk_register_independent_access_ranges - register with sysfs a set of
103 *		independent access ranges
104 * @disk:	Target disk
105 *
106 * Register with sysfs a set of independent access ranges for @disk.
107 */
108int disk_register_independent_access_ranges(struct gendisk *disk)
109{
110	struct blk_independent_access_ranges *iars = disk->ia_ranges;
111	struct request_queue *q = disk->queue;
112	int i, ret;
113
114	lockdep_assert_held(&q->sysfs_dir_lock);
115	lockdep_assert_held(&q->sysfs_lock);
116
117	if (!iars)
118		return 0;
119
120	/*
121	 * At this point, iars is the new set of sector access ranges that needs
122	 * to be registered with sysfs.
123	 */
124	WARN_ON(iars->sysfs_registered);
125	ret = kobject_init_and_add(&iars->kobj, &blk_ia_ranges_ktype,
126				   &disk->queue_kobj, "%s",
127				   "independent_access_ranges");
128	if (ret) {
129		disk->ia_ranges = NULL;
130		kobject_put(&iars->kobj);
131		return ret;
132	}
133
134	for (i = 0; i < iars->nr_ia_ranges; i++) {
135		ret = kobject_init_and_add(&iars->ia_range[i].kobj,
136					   &blk_ia_range_ktype, &iars->kobj,
137					   "%d", i);
138		if (ret) {
139			while (--i >= 0)
140				kobject_del(&iars->ia_range[i].kobj);
141			kobject_del(&iars->kobj);
142			kobject_put(&iars->kobj);
143			return ret;
144		}
145	}
146
147	iars->sysfs_registered = true;
148
149	return 0;
150}
151
152void disk_unregister_independent_access_ranges(struct gendisk *disk)
153{
154	struct request_queue *q = disk->queue;
155	struct blk_independent_access_ranges *iars = disk->ia_ranges;
156	int i;
157
158	lockdep_assert_held(&q->sysfs_dir_lock);
159	lockdep_assert_held(&q->sysfs_lock);
160
161	if (!iars)
162		return;
163
164	if (iars->sysfs_registered) {
165		for (i = 0; i < iars->nr_ia_ranges; i++)
166			kobject_del(&iars->ia_range[i].kobj);
167		kobject_del(&iars->kobj);
168		kobject_put(&iars->kobj);
169	} else {
170		kfree(iars);
171	}
172
173	disk->ia_ranges = NULL;
174}
175
176static struct blk_independent_access_range *
177disk_find_ia_range(struct blk_independent_access_ranges *iars,
178		  sector_t sector)
179{
180	struct blk_independent_access_range *iar;
181	int i;
182
183	for (i = 0; i < iars->nr_ia_ranges; i++) {
184		iar = &iars->ia_range[i];
185		if (sector >= iar->sector &&
186		    sector < iar->sector + iar->nr_sectors)
187			return iar;
188	}
189
190	return NULL;
191}
192
193static bool disk_check_ia_ranges(struct gendisk *disk,
194				struct blk_independent_access_ranges *iars)
195{
196	struct blk_independent_access_range *iar, *tmp;
197	sector_t capacity = get_capacity(disk);
198	sector_t sector = 0;
199	int i;
200
201	if (WARN_ON_ONCE(!iars->nr_ia_ranges))
202		return false;
203
204	/*
205	 * While sorting the ranges in increasing LBA order, check that the
206	 * ranges do not overlap, that there are no sector holes and that all
207	 * sectors belong to one range.
208	 */
209	for (i = 0; i < iars->nr_ia_ranges; i++) {
210		tmp = disk_find_ia_range(iars, sector);
211		if (!tmp || tmp->sector != sector) {
212			pr_warn("Invalid non-contiguous independent access ranges\n");
213			return false;
214		}
215
216		iar = &iars->ia_range[i];
217		if (tmp != iar) {
218			swap(iar->sector, tmp->sector);
219			swap(iar->nr_sectors, tmp->nr_sectors);
220		}
221
222		sector += iar->nr_sectors;
223	}
224
225	if (sector != capacity) {
226		pr_warn("Independent access ranges do not match disk capacity\n");
227		return false;
228	}
229
230	return true;
231}
232
233static bool disk_ia_ranges_changed(struct gendisk *disk,
234				   struct blk_independent_access_ranges *new)
235{
236	struct blk_independent_access_ranges *old = disk->ia_ranges;
237	int i;
238
239	if (!old)
240		return true;
241
242	if (old->nr_ia_ranges != new->nr_ia_ranges)
243		return true;
244
245	for (i = 0; i < old->nr_ia_ranges; i++) {
246		if (new->ia_range[i].sector != old->ia_range[i].sector ||
247		    new->ia_range[i].nr_sectors != old->ia_range[i].nr_sectors)
248			return true;
249	}
250
251	return false;
252}
253
254/**
255 * disk_alloc_independent_access_ranges - Allocate an independent access ranges
256 *                                        data structure
257 * @disk:		target disk
258 * @nr_ia_ranges:	Number of independent access ranges
259 *
260 * Allocate a struct blk_independent_access_ranges structure with @nr_ia_ranges
261 * access range descriptors.
262 */
263struct blk_independent_access_ranges *
264disk_alloc_independent_access_ranges(struct gendisk *disk, int nr_ia_ranges)
265{
266	struct blk_independent_access_ranges *iars;
267
268	iars = kzalloc_node(struct_size(iars, ia_range, nr_ia_ranges),
269			    GFP_KERNEL, disk->queue->node);
270	if (iars)
271		iars->nr_ia_ranges = nr_ia_ranges;
272	return iars;
273}
274EXPORT_SYMBOL_GPL(disk_alloc_independent_access_ranges);
275
276/**
277 * disk_set_independent_access_ranges - Set a disk independent access ranges
278 * @disk:	target disk
279 * @iars:	independent access ranges structure
280 *
281 * Set the independent access ranges information of the request queue
282 * of @disk to @iars. If @iars is NULL and the independent access ranges
283 * structure already set is cleared. If there are no differences between
284 * @iars and the independent access ranges structure already set, @iars
285 * is freed.
286 */
287void disk_set_independent_access_ranges(struct gendisk *disk,
288				struct blk_independent_access_ranges *iars)
289{
290	struct request_queue *q = disk->queue;
291
292	mutex_lock(&q->sysfs_dir_lock);
293	mutex_lock(&q->sysfs_lock);
294	if (iars && !disk_check_ia_ranges(disk, iars)) {
295		kfree(iars);
296		iars = NULL;
297	}
298	if (iars && !disk_ia_ranges_changed(disk, iars)) {
299		kfree(iars);
300		goto unlock;
301	}
302
303	/*
304	 * This may be called for a registered queue. E.g. during a device
305	 * revalidation. If that is the case, we need to unregister the old
306	 * set of independent access ranges and register the new set. If the
307	 * queue is not registered, registration of the device request queue
308	 * will register the independent access ranges.
309	 */
310	disk_unregister_independent_access_ranges(disk);
311	disk->ia_ranges = iars;
312	if (blk_queue_registered(q))
313		disk_register_independent_access_ranges(disk);
314unlock:
315	mutex_unlock(&q->sysfs_lock);
316	mutex_unlock(&q->sysfs_dir_lock);
317}
318EXPORT_SYMBOL_GPL(disk_set_independent_access_ranges);
319