0001
0002
0003
0004
0005
0006
0007 #include <linux/kernel.h>
0008 #include <linux/blkdev.h>
0009 #include <linux/slab.h>
0010 #include <linux/init.h>
0011
0012 #include "blk.h"
0013
0014 static ssize_t
0015 blk_ia_range_sector_show(struct blk_independent_access_range *iar,
0016 char *buf)
0017 {
0018 return sprintf(buf, "%llu\n", iar->sector);
0019 }
0020
0021 static ssize_t
0022 blk_ia_range_nr_sectors_show(struct blk_independent_access_range *iar,
0023 char *buf)
0024 {
0025 return sprintf(buf, "%llu\n", iar->nr_sectors);
0026 }
0027
0028 struct blk_ia_range_sysfs_entry {
0029 struct attribute attr;
0030 ssize_t (*show)(struct blk_independent_access_range *iar, char *buf);
0031 };
0032
0033 static struct blk_ia_range_sysfs_entry blk_ia_range_sector_entry = {
0034 .attr = { .name = "sector", .mode = 0444 },
0035 .show = blk_ia_range_sector_show,
0036 };
0037
0038 static struct blk_ia_range_sysfs_entry blk_ia_range_nr_sectors_entry = {
0039 .attr = { .name = "nr_sectors", .mode = 0444 },
0040 .show = blk_ia_range_nr_sectors_show,
0041 };
0042
0043 static struct attribute *blk_ia_range_attrs[] = {
0044 &blk_ia_range_sector_entry.attr,
0045 &blk_ia_range_nr_sectors_entry.attr,
0046 NULL,
0047 };
0048 ATTRIBUTE_GROUPS(blk_ia_range);
0049
0050 static ssize_t blk_ia_range_sysfs_show(struct kobject *kobj,
0051 struct attribute *attr, char *buf)
0052 {
0053 struct blk_ia_range_sysfs_entry *entry =
0054 container_of(attr, struct blk_ia_range_sysfs_entry, attr);
0055 struct blk_independent_access_range *iar =
0056 container_of(kobj, struct blk_independent_access_range, kobj);
0057
0058 return entry->show(iar, buf);
0059 }
0060
0061 static const struct sysfs_ops blk_ia_range_sysfs_ops = {
0062 .show = blk_ia_range_sysfs_show,
0063 };
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074 static void blk_ia_range_sysfs_nop_release(struct kobject *kobj)
0075 {
0076 }
0077
0078 static struct kobj_type blk_ia_range_ktype = {
0079 .sysfs_ops = &blk_ia_range_sysfs_ops,
0080 .default_groups = blk_ia_range_groups,
0081 .release = blk_ia_range_sysfs_nop_release,
0082 };
0083
0084
0085
0086
0087
0088
0089 static void blk_ia_ranges_sysfs_release(struct kobject *kobj)
0090 {
0091 struct blk_independent_access_ranges *iars =
0092 container_of(kobj, struct blk_independent_access_ranges, kobj);
0093
0094 kfree(iars);
0095 }
0096
0097 static struct kobj_type blk_ia_ranges_ktype = {
0098 .release = blk_ia_ranges_sysfs_release,
0099 };
0100
0101
0102
0103
0104
0105
0106
0107
0108 int disk_register_independent_access_ranges(struct gendisk *disk)
0109 {
0110 struct blk_independent_access_ranges *iars = disk->ia_ranges;
0111 struct request_queue *q = disk->queue;
0112 int i, ret;
0113
0114 lockdep_assert_held(&q->sysfs_dir_lock);
0115 lockdep_assert_held(&q->sysfs_lock);
0116
0117 if (!iars)
0118 return 0;
0119
0120
0121
0122
0123
0124 WARN_ON(iars->sysfs_registered);
0125 ret = kobject_init_and_add(&iars->kobj, &blk_ia_ranges_ktype,
0126 &q->kobj, "%s", "independent_access_ranges");
0127 if (ret) {
0128 disk->ia_ranges = NULL;
0129 kobject_put(&iars->kobj);
0130 return ret;
0131 }
0132
0133 for (i = 0; i < iars->nr_ia_ranges; i++) {
0134 ret = kobject_init_and_add(&iars->ia_range[i].kobj,
0135 &blk_ia_range_ktype, &iars->kobj,
0136 "%d", i);
0137 if (ret) {
0138 while (--i >= 0)
0139 kobject_del(&iars->ia_range[i].kobj);
0140 kobject_del(&iars->kobj);
0141 kobject_put(&iars->kobj);
0142 return ret;
0143 }
0144 }
0145
0146 iars->sysfs_registered = true;
0147
0148 return 0;
0149 }
0150
0151 void disk_unregister_independent_access_ranges(struct gendisk *disk)
0152 {
0153 struct request_queue *q = disk->queue;
0154 struct blk_independent_access_ranges *iars = disk->ia_ranges;
0155 int i;
0156
0157 lockdep_assert_held(&q->sysfs_dir_lock);
0158 lockdep_assert_held(&q->sysfs_lock);
0159
0160 if (!iars)
0161 return;
0162
0163 if (iars->sysfs_registered) {
0164 for (i = 0; i < iars->nr_ia_ranges; i++)
0165 kobject_del(&iars->ia_range[i].kobj);
0166 kobject_del(&iars->kobj);
0167 kobject_put(&iars->kobj);
0168 } else {
0169 kfree(iars);
0170 }
0171
0172 disk->ia_ranges = NULL;
0173 }
0174
0175 static struct blk_independent_access_range *
0176 disk_find_ia_range(struct blk_independent_access_ranges *iars,
0177 sector_t sector)
0178 {
0179 struct blk_independent_access_range *iar;
0180 int i;
0181
0182 for (i = 0; i < iars->nr_ia_ranges; i++) {
0183 iar = &iars->ia_range[i];
0184 if (sector >= iar->sector &&
0185 sector < iar->sector + iar->nr_sectors)
0186 return iar;
0187 }
0188
0189 return NULL;
0190 }
0191
0192 static bool disk_check_ia_ranges(struct gendisk *disk,
0193 struct blk_independent_access_ranges *iars)
0194 {
0195 struct blk_independent_access_range *iar, *tmp;
0196 sector_t capacity = get_capacity(disk);
0197 sector_t sector = 0;
0198 int i;
0199
0200 if (WARN_ON_ONCE(!iars->nr_ia_ranges))
0201 return false;
0202
0203
0204
0205
0206
0207
0208 for (i = 0; i < iars->nr_ia_ranges; i++) {
0209 tmp = disk_find_ia_range(iars, sector);
0210 if (!tmp || tmp->sector != sector) {
0211 pr_warn("Invalid non-contiguous independent access ranges\n");
0212 return false;
0213 }
0214
0215 iar = &iars->ia_range[i];
0216 if (tmp != iar) {
0217 swap(iar->sector, tmp->sector);
0218 swap(iar->nr_sectors, tmp->nr_sectors);
0219 }
0220
0221 sector += iar->nr_sectors;
0222 }
0223
0224 if (sector != capacity) {
0225 pr_warn("Independent access ranges do not match disk capacity\n");
0226 return false;
0227 }
0228
0229 return true;
0230 }
0231
0232 static bool disk_ia_ranges_changed(struct gendisk *disk,
0233 struct blk_independent_access_ranges *new)
0234 {
0235 struct blk_independent_access_ranges *old = disk->ia_ranges;
0236 int i;
0237
0238 if (!old)
0239 return true;
0240
0241 if (old->nr_ia_ranges != new->nr_ia_ranges)
0242 return true;
0243
0244 for (i = 0; i < old->nr_ia_ranges; i++) {
0245 if (new->ia_range[i].sector != old->ia_range[i].sector ||
0246 new->ia_range[i].nr_sectors != old->ia_range[i].nr_sectors)
0247 return true;
0248 }
0249
0250 return false;
0251 }
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262 struct blk_independent_access_ranges *
0263 disk_alloc_independent_access_ranges(struct gendisk *disk, int nr_ia_ranges)
0264 {
0265 struct blk_independent_access_ranges *iars;
0266
0267 iars = kzalloc_node(struct_size(iars, ia_range, nr_ia_ranges),
0268 GFP_KERNEL, disk->queue->node);
0269 if (iars)
0270 iars->nr_ia_ranges = nr_ia_ranges;
0271 return iars;
0272 }
0273 EXPORT_SYMBOL_GPL(disk_alloc_independent_access_ranges);
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286 void disk_set_independent_access_ranges(struct gendisk *disk,
0287 struct blk_independent_access_ranges *iars)
0288 {
0289 struct request_queue *q = disk->queue;
0290
0291 mutex_lock(&q->sysfs_dir_lock);
0292 mutex_lock(&q->sysfs_lock);
0293 if (iars && !disk_check_ia_ranges(disk, iars)) {
0294 kfree(iars);
0295 iars = NULL;
0296 }
0297 if (iars && !disk_ia_ranges_changed(disk, iars)) {
0298 kfree(iars);
0299 goto unlock;
0300 }
0301
0302
0303
0304
0305
0306
0307
0308
0309 disk_unregister_independent_access_ranges(disk);
0310 disk->ia_ranges = iars;
0311 if (blk_queue_registered(q))
0312 disk_register_independent_access_ranges(disk);
0313 unlock:
0314 mutex_unlock(&q->sysfs_lock);
0315 mutex_unlock(&q->sysfs_dir_lock);
0316 }
0317 EXPORT_SYMBOL_GPL(disk_set_independent_access_ranges);