root/block/blk-mq-sysfs.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. blk_mq_sysfs_release
  2. blk_mq_ctx_sysfs_release
  3. blk_mq_hw_sysfs_release
  4. blk_mq_sysfs_show
  5. blk_mq_sysfs_store
  6. blk_mq_hw_sysfs_show
  7. blk_mq_hw_sysfs_store
  8. blk_mq_hw_sysfs_nr_tags_show
  9. blk_mq_hw_sysfs_nr_reserved_tags_show
  10. blk_mq_hw_sysfs_cpus_show
  11. blk_mq_unregister_hctx
  12. blk_mq_register_hctx
  13. blk_mq_unregister_dev
  14. blk_mq_hctx_kobj_init
  15. blk_mq_sysfs_deinit
  16. blk_mq_sysfs_init
  17. __blk_mq_register_dev
  18. blk_mq_sysfs_unregister
  19. blk_mq_sysfs_register

   1 // SPDX-License-Identifier: GPL-2.0
   2 #include <linux/kernel.h>
   3 #include <linux/module.h>
   4 #include <linux/backing-dev.h>
   5 #include <linux/bio.h>
   6 #include <linux/blkdev.h>
   7 #include <linux/mm.h>
   8 #include <linux/init.h>
   9 #include <linux/slab.h>
  10 #include <linux/workqueue.h>
  11 #include <linux/smp.h>
  12 
  13 #include <linux/blk-mq.h>
  14 #include "blk.h"
  15 #include "blk-mq.h"
  16 #include "blk-mq-tag.h"
  17 
  18 static void blk_mq_sysfs_release(struct kobject *kobj)
  19 {
  20         struct blk_mq_ctxs *ctxs = container_of(kobj, struct blk_mq_ctxs, kobj);
  21 
  22         free_percpu(ctxs->queue_ctx);
  23         kfree(ctxs);
  24 }
  25 
  26 static void blk_mq_ctx_sysfs_release(struct kobject *kobj)
  27 {
  28         struct blk_mq_ctx *ctx = container_of(kobj, struct blk_mq_ctx, kobj);
  29 
  30         /* ctx->ctxs won't be released until all ctx are freed */
  31         kobject_put(&ctx->ctxs->kobj);
  32 }
  33 
  34 static void blk_mq_hw_sysfs_release(struct kobject *kobj)
  35 {
  36         struct blk_mq_hw_ctx *hctx = container_of(kobj, struct blk_mq_hw_ctx,
  37                                                   kobj);
  38 
  39         cancel_delayed_work_sync(&hctx->run_work);
  40 
  41         if (hctx->flags & BLK_MQ_F_BLOCKING)
  42                 cleanup_srcu_struct(hctx->srcu);
  43         blk_free_flush_queue(hctx->fq);
  44         sbitmap_free(&hctx->ctx_map);
  45         free_cpumask_var(hctx->cpumask);
  46         kfree(hctx->ctxs);
  47         kfree(hctx);
  48 }
  49 
  50 struct blk_mq_ctx_sysfs_entry {
  51         struct attribute attr;
  52         ssize_t (*show)(struct blk_mq_ctx *, char *);
  53         ssize_t (*store)(struct blk_mq_ctx *, const char *, size_t);
  54 };
  55 
  56 struct blk_mq_hw_ctx_sysfs_entry {
  57         struct attribute attr;
  58         ssize_t (*show)(struct blk_mq_hw_ctx *, char *);
  59         ssize_t (*store)(struct blk_mq_hw_ctx *, const char *, size_t);
  60 };
  61 
  62 static ssize_t blk_mq_sysfs_show(struct kobject *kobj, struct attribute *attr,
  63                                  char *page)
  64 {
  65         struct blk_mq_ctx_sysfs_entry *entry;
  66         struct blk_mq_ctx *ctx;
  67         struct request_queue *q;
  68         ssize_t res;
  69 
  70         entry = container_of(attr, struct blk_mq_ctx_sysfs_entry, attr);
  71         ctx = container_of(kobj, struct blk_mq_ctx, kobj);
  72         q = ctx->queue;
  73 
  74         if (!entry->show)
  75                 return -EIO;
  76 
  77         res = -ENOENT;
  78         mutex_lock(&q->sysfs_lock);
  79         if (!blk_queue_dying(q))
  80                 res = entry->show(ctx, page);
  81         mutex_unlock(&q->sysfs_lock);
  82         return res;
  83 }
  84 
  85 static ssize_t blk_mq_sysfs_store(struct kobject *kobj, struct attribute *attr,
  86                                   const char *page, size_t length)
  87 {
  88         struct blk_mq_ctx_sysfs_entry *entry;
  89         struct blk_mq_ctx *ctx;
  90         struct request_queue *q;
  91         ssize_t res;
  92 
  93         entry = container_of(attr, struct blk_mq_ctx_sysfs_entry, attr);
  94         ctx = container_of(kobj, struct blk_mq_ctx, kobj);
  95         q = ctx->queue;
  96 
  97         if (!entry->store)
  98                 return -EIO;
  99 
 100         res = -ENOENT;
 101         mutex_lock(&q->sysfs_lock);
 102         if (!blk_queue_dying(q))
 103                 res = entry->store(ctx, page, length);
 104         mutex_unlock(&q->sysfs_lock);
 105         return res;
 106 }
 107 
 108 static ssize_t blk_mq_hw_sysfs_show(struct kobject *kobj,
 109                                     struct attribute *attr, char *page)
 110 {
 111         struct blk_mq_hw_ctx_sysfs_entry *entry;
 112         struct blk_mq_hw_ctx *hctx;
 113         struct request_queue *q;
 114         ssize_t res;
 115 
 116         entry = container_of(attr, struct blk_mq_hw_ctx_sysfs_entry, attr);
 117         hctx = container_of(kobj, struct blk_mq_hw_ctx, kobj);
 118         q = hctx->queue;
 119 
 120         if (!entry->show)
 121                 return -EIO;
 122 
 123         res = -ENOENT;
 124         mutex_lock(&q->sysfs_lock);
 125         if (!blk_queue_dying(q))
 126                 res = entry->show(hctx, page);
 127         mutex_unlock(&q->sysfs_lock);
 128         return res;
 129 }
 130 
 131 static ssize_t blk_mq_hw_sysfs_store(struct kobject *kobj,
 132                                      struct attribute *attr, const char *page,
 133                                      size_t length)
 134 {
 135         struct blk_mq_hw_ctx_sysfs_entry *entry;
 136         struct blk_mq_hw_ctx *hctx;
 137         struct request_queue *q;
 138         ssize_t res;
 139 
 140         entry = container_of(attr, struct blk_mq_hw_ctx_sysfs_entry, attr);
 141         hctx = container_of(kobj, struct blk_mq_hw_ctx, kobj);
 142         q = hctx->queue;
 143 
 144         if (!entry->store)
 145                 return -EIO;
 146 
 147         res = -ENOENT;
 148         mutex_lock(&q->sysfs_lock);
 149         if (!blk_queue_dying(q))
 150                 res = entry->store(hctx, page, length);
 151         mutex_unlock(&q->sysfs_lock);
 152         return res;
 153 }
 154 
 155 static ssize_t blk_mq_hw_sysfs_nr_tags_show(struct blk_mq_hw_ctx *hctx,
 156                                             char *page)
 157 {
 158         return sprintf(page, "%u\n", hctx->tags->nr_tags);
 159 }
 160 
 161 static ssize_t blk_mq_hw_sysfs_nr_reserved_tags_show(struct blk_mq_hw_ctx *hctx,
 162                                                      char *page)
 163 {
 164         return sprintf(page, "%u\n", hctx->tags->nr_reserved_tags);
 165 }
 166 
 167 static ssize_t blk_mq_hw_sysfs_cpus_show(struct blk_mq_hw_ctx *hctx, char *page)
 168 {
 169         const size_t size = PAGE_SIZE - 1;
 170         unsigned int i, first = 1;
 171         int ret = 0, pos = 0;
 172 
 173         for_each_cpu(i, hctx->cpumask) {
 174                 if (first)
 175                         ret = snprintf(pos + page, size - pos, "%u", i);
 176                 else
 177                         ret = snprintf(pos + page, size - pos, ", %u", i);
 178 
 179                 if (ret >= size - pos)
 180                         break;
 181 
 182                 first = 0;
 183                 pos += ret;
 184         }
 185 
 186         ret = snprintf(pos + page, size + 1 - pos, "\n");
 187         return pos + ret;
 188 }
 189 
 190 static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_nr_tags = {
 191         .attr = {.name = "nr_tags", .mode = 0444 },
 192         .show = blk_mq_hw_sysfs_nr_tags_show,
 193 };
 194 static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_nr_reserved_tags = {
 195         .attr = {.name = "nr_reserved_tags", .mode = 0444 },
 196         .show = blk_mq_hw_sysfs_nr_reserved_tags_show,
 197 };
 198 static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_cpus = {
 199         .attr = {.name = "cpu_list", .mode = 0444 },
 200         .show = blk_mq_hw_sysfs_cpus_show,
 201 };
 202 
 203 static struct attribute *default_hw_ctx_attrs[] = {
 204         &blk_mq_hw_sysfs_nr_tags.attr,
 205         &blk_mq_hw_sysfs_nr_reserved_tags.attr,
 206         &blk_mq_hw_sysfs_cpus.attr,
 207         NULL,
 208 };
 209 ATTRIBUTE_GROUPS(default_hw_ctx);
 210 
 211 static const struct sysfs_ops blk_mq_sysfs_ops = {
 212         .show   = blk_mq_sysfs_show,
 213         .store  = blk_mq_sysfs_store,
 214 };
 215 
 216 static const struct sysfs_ops blk_mq_hw_sysfs_ops = {
 217         .show   = blk_mq_hw_sysfs_show,
 218         .store  = blk_mq_hw_sysfs_store,
 219 };
 220 
 221 static struct kobj_type blk_mq_ktype = {
 222         .sysfs_ops      = &blk_mq_sysfs_ops,
 223         .release        = blk_mq_sysfs_release,
 224 };
 225 
 226 static struct kobj_type blk_mq_ctx_ktype = {
 227         .sysfs_ops      = &blk_mq_sysfs_ops,
 228         .release        = blk_mq_ctx_sysfs_release,
 229 };
 230 
 231 static struct kobj_type blk_mq_hw_ktype = {
 232         .sysfs_ops      = &blk_mq_hw_sysfs_ops,
 233         .default_groups = default_hw_ctx_groups,
 234         .release        = blk_mq_hw_sysfs_release,
 235 };
 236 
 237 static void blk_mq_unregister_hctx(struct blk_mq_hw_ctx *hctx)
 238 {
 239         struct blk_mq_ctx *ctx;
 240         int i;
 241 
 242         if (!hctx->nr_ctx)
 243                 return;
 244 
 245         hctx_for_each_ctx(hctx, ctx, i)
 246                 kobject_del(&ctx->kobj);
 247 
 248         kobject_del(&hctx->kobj);
 249 }
 250 
 251 static int blk_mq_register_hctx(struct blk_mq_hw_ctx *hctx)
 252 {
 253         struct request_queue *q = hctx->queue;
 254         struct blk_mq_ctx *ctx;
 255         int i, ret;
 256 
 257         if (!hctx->nr_ctx)
 258                 return 0;
 259 
 260         ret = kobject_add(&hctx->kobj, q->mq_kobj, "%u", hctx->queue_num);
 261         if (ret)
 262                 return ret;
 263 
 264         hctx_for_each_ctx(hctx, ctx, i) {
 265                 ret = kobject_add(&ctx->kobj, &hctx->kobj, "cpu%u", ctx->cpu);
 266                 if (ret)
 267                         break;
 268         }
 269 
 270         return ret;
 271 }
 272 
 273 void blk_mq_unregister_dev(struct device *dev, struct request_queue *q)
 274 {
 275         struct blk_mq_hw_ctx *hctx;
 276         int i;
 277 
 278         lockdep_assert_held(&q->sysfs_dir_lock);
 279 
 280         queue_for_each_hw_ctx(q, hctx, i)
 281                 blk_mq_unregister_hctx(hctx);
 282 
 283         kobject_uevent(q->mq_kobj, KOBJ_REMOVE);
 284         kobject_del(q->mq_kobj);
 285         kobject_put(&dev->kobj);
 286 
 287         q->mq_sysfs_init_done = false;
 288 }
 289 
 290 void blk_mq_hctx_kobj_init(struct blk_mq_hw_ctx *hctx)
 291 {
 292         kobject_init(&hctx->kobj, &blk_mq_hw_ktype);
 293 }
 294 
 295 void blk_mq_sysfs_deinit(struct request_queue *q)
 296 {
 297         struct blk_mq_ctx *ctx;
 298         int cpu;
 299 
 300         for_each_possible_cpu(cpu) {
 301                 ctx = per_cpu_ptr(q->queue_ctx, cpu);
 302                 kobject_put(&ctx->kobj);
 303         }
 304         kobject_put(q->mq_kobj);
 305 }
 306 
 307 void blk_mq_sysfs_init(struct request_queue *q)
 308 {
 309         struct blk_mq_ctx *ctx;
 310         int cpu;
 311 
 312         kobject_init(q->mq_kobj, &blk_mq_ktype);
 313 
 314         for_each_possible_cpu(cpu) {
 315                 ctx = per_cpu_ptr(q->queue_ctx, cpu);
 316 
 317                 kobject_get(q->mq_kobj);
 318                 kobject_init(&ctx->kobj, &blk_mq_ctx_ktype);
 319         }
 320 }
 321 
 322 int __blk_mq_register_dev(struct device *dev, struct request_queue *q)
 323 {
 324         struct blk_mq_hw_ctx *hctx;
 325         int ret, i;
 326 
 327         WARN_ON_ONCE(!q->kobj.parent);
 328         lockdep_assert_held(&q->sysfs_dir_lock);
 329 
 330         ret = kobject_add(q->mq_kobj, kobject_get(&dev->kobj), "%s", "mq");
 331         if (ret < 0)
 332                 goto out;
 333 
 334         kobject_uevent(q->mq_kobj, KOBJ_ADD);
 335 
 336         queue_for_each_hw_ctx(q, hctx, i) {
 337                 ret = blk_mq_register_hctx(hctx);
 338                 if (ret)
 339                         goto unreg;
 340         }
 341 
 342         q->mq_sysfs_init_done = true;
 343 
 344 out:
 345         return ret;
 346 
 347 unreg:
 348         while (--i >= 0)
 349                 blk_mq_unregister_hctx(q->queue_hw_ctx[i]);
 350 
 351         kobject_uevent(q->mq_kobj, KOBJ_REMOVE);
 352         kobject_del(q->mq_kobj);
 353         kobject_put(&dev->kobj);
 354         return ret;
 355 }
 356 
 357 void blk_mq_sysfs_unregister(struct request_queue *q)
 358 {
 359         struct blk_mq_hw_ctx *hctx;
 360         int i;
 361 
 362         mutex_lock(&q->sysfs_dir_lock);
 363         if (!q->mq_sysfs_init_done)
 364                 goto unlock;
 365 
 366         queue_for_each_hw_ctx(q, hctx, i)
 367                 blk_mq_unregister_hctx(hctx);
 368 
 369 unlock:
 370         mutex_unlock(&q->sysfs_dir_lock);
 371 }
 372 
 373 int blk_mq_sysfs_register(struct request_queue *q)
 374 {
 375         struct blk_mq_hw_ctx *hctx;
 376         int i, ret = 0;
 377 
 378         mutex_lock(&q->sysfs_dir_lock);
 379         if (!q->mq_sysfs_init_done)
 380                 goto unlock;
 381 
 382         queue_for_each_hw_ctx(q, hctx, i) {
 383                 ret = blk_mq_register_hctx(hctx);
 384                 if (ret)
 385                         break;
 386         }
 387 
 388 unlock:
 389         mutex_unlock(&q->sysfs_dir_lock);
 390 
 391         return ret;
 392 }

/* [<][>][^][v][top][bottom][index][help] */