LCOV - code coverage report
Current view: top level - block - blk-mq-tag.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 80 0.0 %
Date: 2014-02-18 Functions: 0 12 0.0 %
Branches: 0 44 0.0 %

           Branch data     Line data    Source code
       1                 :            : #include <linux/kernel.h>
       2                 :            : #include <linux/module.h>
       3                 :            : #include <linux/percpu_ida.h>
       4                 :            : 
       5                 :            : #include <linux/blk-mq.h>
       6                 :            : #include "blk.h"
       7                 :            : #include "blk-mq.h"
       8                 :            : #include "blk-mq-tag.h"
       9                 :            : 
      10                 :            : /*
      11                 :            :  * Per tagged queue (tag address space) map
      12                 :            :  */
      13                 :            : struct blk_mq_tags {
      14                 :            :         unsigned int nr_tags;
      15                 :            :         unsigned int nr_reserved_tags;
      16                 :            :         unsigned int nr_batch_move;
      17                 :            :         unsigned int nr_max_cache;
      18                 :            : 
      19                 :            :         struct percpu_ida free_tags;
      20                 :            :         struct percpu_ida reserved_tags;
      21                 :            : };
      22                 :            : 
      23                 :          0 : void blk_mq_wait_for_tags(struct blk_mq_tags *tags)
      24                 :            : {
      25                 :          0 :         int tag = blk_mq_get_tag(tags, __GFP_WAIT, false);
      26                 :          0 :         blk_mq_put_tag(tags, tag);
      27                 :          0 : }
      28                 :            : 
      29                 :          0 : bool blk_mq_has_free_tags(struct blk_mq_tags *tags)
      30                 :            : {
      31   [ #  #  #  # ]:          0 :         return !tags ||
      32                 :          0 :                 percpu_ida_free_tags(&tags->free_tags, nr_cpu_ids) != 0;
      33                 :            : }
      34                 :            : 
      35                 :            : static unsigned int __blk_mq_get_tag(struct blk_mq_tags *tags, gfp_t gfp)
      36                 :            : {
      37                 :            :         int tag;
      38                 :            : 
      39                 :          0 :         tag = percpu_ida_alloc(&tags->free_tags, gfp);
      40         [ #  # ]:          0 :         if (tag < 0)
      41                 :            :                 return BLK_MQ_TAG_FAIL;
      42                 :          0 :         return tag + tags->nr_reserved_tags;
      43                 :            : }
      44                 :            : 
      45                 :          0 : static unsigned int __blk_mq_get_reserved_tag(struct blk_mq_tags *tags,
      46                 :            :                                               gfp_t gfp)
      47                 :            : {
      48                 :            :         int tag;
      49                 :            : 
      50         [ #  # ]:          0 :         if (unlikely(!tags->nr_reserved_tags)) {
      51 [ #  # ][ #  # ]:          0 :                 WARN_ON_ONCE(1);
      52                 :            :                 return BLK_MQ_TAG_FAIL;
      53                 :            :         }
      54                 :            : 
      55                 :          0 :         tag = percpu_ida_alloc(&tags->reserved_tags, gfp);
      56         [ #  # ]:          0 :         if (tag < 0)
      57                 :            :                 return BLK_MQ_TAG_FAIL;
      58                 :          0 :         return tag;
      59                 :            : }
      60                 :            : 
      61                 :          0 : unsigned int blk_mq_get_tag(struct blk_mq_tags *tags, gfp_t gfp, bool reserved)
      62                 :            : {
      63         [ #  # ]:          0 :         if (!reserved)
      64                 :          0 :                 return __blk_mq_get_tag(tags, gfp);
      65                 :            : 
      66                 :          0 :         return __blk_mq_get_reserved_tag(tags, gfp);
      67                 :            : }
      68                 :            : 
      69                 :          0 : static void __blk_mq_put_tag(struct blk_mq_tags *tags, unsigned int tag)
      70                 :            : {
      71         [ #  # ]:          0 :         BUG_ON(tag >= tags->nr_tags);
      72                 :            : 
      73                 :          0 :         percpu_ida_free(&tags->free_tags, tag - tags->nr_reserved_tags);
      74                 :          0 : }
      75                 :            : 
      76                 :          0 : static void __blk_mq_put_reserved_tag(struct blk_mq_tags *tags,
      77                 :            :                                       unsigned int tag)
      78                 :            : {
      79         [ #  # ]:          0 :         BUG_ON(tag >= tags->nr_reserved_tags);
      80                 :            : 
      81                 :          0 :         percpu_ida_free(&tags->reserved_tags, tag);
      82                 :          0 : }
      83                 :            : 
      84                 :          0 : void blk_mq_put_tag(struct blk_mq_tags *tags, unsigned int tag)
      85                 :            : {
      86         [ #  # ]:          0 :         if (tag >= tags->nr_reserved_tags)
      87                 :          0 :                 __blk_mq_put_tag(tags, tag);
      88                 :            :         else
      89                 :          0 :                 __blk_mq_put_reserved_tag(tags, tag);
      90                 :          0 : }
      91                 :            : 
      92                 :          0 : static int __blk_mq_tag_iter(unsigned id, void *data)
      93                 :            : {
      94                 :            :         unsigned long *tag_map = data;
      95                 :          0 :         __set_bit(id, tag_map);
      96                 :          0 :         return 0;
      97                 :            : }
      98                 :            : 
      99                 :          0 : void blk_mq_tag_busy_iter(struct blk_mq_tags *tags,
     100                 :            :                           void (*fn)(void *, unsigned long *), void *data)
     101                 :            : {
     102                 :            :         unsigned long *tag_map;
     103                 :            :         size_t map_size;
     104                 :            : 
     105                 :          0 :         map_size = ALIGN(tags->nr_tags, BITS_PER_LONG) / BITS_PER_LONG;
     106                 :          0 :         tag_map = kzalloc(map_size * sizeof(unsigned long), GFP_ATOMIC);
     107         [ #  # ]:          0 :         if (!tag_map)
     108                 :          0 :                 return;
     109                 :            : 
     110                 :          0 :         percpu_ida_for_each_free(&tags->free_tags, __blk_mq_tag_iter, tag_map);
     111         [ #  # ]:          0 :         if (tags->nr_reserved_tags)
     112                 :          0 :                 percpu_ida_for_each_free(&tags->reserved_tags, __blk_mq_tag_iter,
     113                 :            :                         tag_map);
     114                 :            : 
     115                 :          0 :         fn(data, tag_map);
     116                 :          0 :         kfree(tag_map);
     117                 :            : }
     118                 :            : 
     119                 :          0 : struct blk_mq_tags *blk_mq_init_tags(unsigned int total_tags,
     120                 :            :                                      unsigned int reserved_tags, int node)
     121                 :            : {
     122                 :            :         unsigned int nr_tags, nr_cache;
     123                 :            :         struct blk_mq_tags *tags;
     124                 :            :         int ret;
     125                 :            : 
     126         [ #  # ]:          0 :         if (total_tags > BLK_MQ_TAG_MAX) {
     127                 :          0 :                 pr_err("blk-mq: tag depth too large\n");
     128                 :          0 :                 return NULL;
     129                 :            :         }
     130                 :            : 
     131                 :            :         tags = kzalloc_node(sizeof(*tags), GFP_KERNEL, node);
     132         [ #  # ]:          0 :         if (!tags)
     133                 :            :                 return NULL;
     134                 :            : 
     135                 :          0 :         nr_tags = total_tags - reserved_tags;
     136                 :          0 :         nr_cache = nr_tags / num_possible_cpus();
     137                 :            : 
     138         [ #  # ]:          0 :         if (nr_cache < BLK_MQ_TAG_CACHE_MIN)
     139                 :            :                 nr_cache = BLK_MQ_TAG_CACHE_MIN;
     140         [ #  # ]:          0 :         else if (nr_cache > BLK_MQ_TAG_CACHE_MAX)
     141                 :            :                 nr_cache = BLK_MQ_TAG_CACHE_MAX;
     142                 :            : 
     143                 :          0 :         tags->nr_tags = total_tags;
     144                 :          0 :         tags->nr_reserved_tags = reserved_tags;
     145                 :          0 :         tags->nr_max_cache = nr_cache;
     146                 :          0 :         tags->nr_batch_move = max(1u, nr_cache / 2);
     147                 :            : 
     148                 :          0 :         ret = __percpu_ida_init(&tags->free_tags, tags->nr_tags -
     149                 :            :                                 tags->nr_reserved_tags,
     150                 :            :                                 tags->nr_max_cache,
     151                 :            :                                 tags->nr_batch_move);
     152         [ #  # ]:          0 :         if (ret)
     153                 :            :                 goto err_free_tags;
     154                 :            : 
     155         [ #  # ]:          0 :         if (reserved_tags) {
     156                 :            :                 /*
     157                 :            :                  * With max_cahe and batch set to 1, the allocator fallbacks to
     158                 :            :                  * no cached. It's fine reserved tags allocation is slow.
     159                 :            :                  */
     160                 :          0 :                 ret = __percpu_ida_init(&tags->reserved_tags, reserved_tags,
     161                 :            :                                 1, 1);
     162         [ #  # ]:          0 :                 if (ret)
     163                 :            :                         goto err_reserved_tags;
     164                 :            :         }
     165                 :            : 
     166                 :          0 :         return tags;
     167                 :            : 
     168                 :            : err_reserved_tags:
     169                 :          0 :         percpu_ida_destroy(&tags->free_tags);
     170                 :            : err_free_tags:
     171                 :          0 :         kfree(tags);
     172                 :          0 :         return NULL;
     173                 :            : }
     174                 :            : 
     175                 :          0 : void blk_mq_free_tags(struct blk_mq_tags *tags)
     176                 :            : {
     177                 :          0 :         percpu_ida_destroy(&tags->free_tags);
     178                 :          0 :         percpu_ida_destroy(&tags->reserved_tags);
     179                 :          0 :         kfree(tags);
     180                 :          0 : }
     181                 :            : 
     182                 :          0 : ssize_t blk_mq_tag_sysfs_show(struct blk_mq_tags *tags, char *page)
     183                 :            : {
     184                 :            :         char *orig_page = page;
     185                 :            :         int cpu;
     186                 :            : 
     187         [ #  # ]:          0 :         if (!tags)
     188                 :            :                 return 0;
     189                 :            : 
     190                 :          0 :         page += sprintf(page, "nr_tags=%u, reserved_tags=%u, batch_move=%u,"
     191                 :            :                         " max_cache=%u\n", tags->nr_tags, tags->nr_reserved_tags,
     192                 :            :                         tags->nr_batch_move, tags->nr_max_cache);
     193                 :            : 
     194                 :          0 :         page += sprintf(page, "nr_free=%u, nr_reserved=%u\n",
     195                 :            :                         percpu_ida_free_tags(&tags->free_tags, nr_cpu_ids),
     196                 :            :                         percpu_ida_free_tags(&tags->reserved_tags, nr_cpu_ids));
     197                 :            : 
     198         [ #  # ]:          0 :         for_each_possible_cpu(cpu) {
     199                 :          0 :                 page += sprintf(page, "  cpu%02u: nr_free=%u\n", cpu,
     200                 :            :                                 percpu_ida_free_tags(&tags->free_tags, cpu));
     201                 :            :         }
     202                 :            : 
     203                 :          0 :         return page - orig_page;
     204                 :            : }

Generated by: LCOV version 1.9