Commit 80b15c7389caa81a3860f9fc2ee47ec0ea572a63

Authored by Konstantin Khlebnikov
Committed by Jens Axboe
1 parent bca4b914b5

cfq-iosched: compact io_context radix_tree

Use small consequent indexes as radix tree keys instead of sparse cfqd address.

This change will reduce radix tree depth from 11 (6 for 32-bit hosts)
to 1 if host have <=64 disks under cfq control, or to 0 if there only one disk.
So, this patch save 10*560 bytes for each process (5*296 for 32-bit hosts)

For each cfqd allocate cic index from ida.
To unlink dead cic from tree without cfqd access store index into ->key.
(bit 0 -- dead mark, bits 1..30 -- index: ida produce id in range 0..2^31-1)

Signed-off-by: Konstantin Khlebnikov <khlebnikov@openvz.org>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>

Showing 1 changed file with 39 additions and 5 deletions Side-by-side Diff

... ... @@ -64,6 +64,9 @@
64 64 static struct completion *ioc_gone;
65 65 static DEFINE_SPINLOCK(ioc_gone_lock);
66 66  
  67 +static DEFINE_SPINLOCK(cic_index_lock);
  68 +static DEFINE_IDA(cic_index_ida);
  69 +
67 70 #define CFQ_PRIO_LISTS IOPRIO_BE_NR
68 71 #define cfq_class_idle(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_IDLE)
69 72 #define cfq_class_rt(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_RT)
... ... @@ -271,6 +274,7 @@
271 274 unsigned int cfq_latency;
272 275 unsigned int cfq_group_isolation;
273 276  
  277 + unsigned int cic_index;
274 278 struct list_head cic_list;
275 279  
276 280 /*
277 281  
... ... @@ -431,10 +435,11 @@
431 435 }
432 436  
433 437 #define CIC_DEAD_KEY 1ul
  438 +#define CIC_DEAD_INDEX_SHIFT 1
434 439  
435 440 static inline void *cfqd_dead_key(struct cfq_data *cfqd)
436 441 {
437   - return (void *)((unsigned long) cfqd | CIC_DEAD_KEY);
  442 + return (void *)(cfqd->cic_index << CIC_DEAD_INDEX_SHIFT | CIC_DEAD_KEY);
438 443 }
439 444  
440 445 static inline struct cfq_data *cic_to_cfqd(struct cfq_io_context *cic)
... ... @@ -2532,7 +2537,7 @@
2532 2537 BUG_ON(!(dead_key & CIC_DEAD_KEY));
2533 2538  
2534 2539 spin_lock_irqsave(&ioc->lock, flags);
2535   - radix_tree_delete(&ioc->radix_root, dead_key & ~CIC_DEAD_KEY);
  2540 + radix_tree_delete(&ioc->radix_root, dead_key >> CIC_DEAD_INDEX_SHIFT);
2536 2541 hlist_del_rcu(&cic->cic_list);
2537 2542 spin_unlock_irqrestore(&ioc->lock, flags);
2538 2543  
... ... @@ -2906,7 +2911,7 @@
2906 2911  
2907 2912 BUG_ON(ioc->ioc_data == cic);
2908 2913  
2909   - radix_tree_delete(&ioc->radix_root, (unsigned long) cfqd);
  2914 + radix_tree_delete(&ioc->radix_root, cfqd->cic_index);
2910 2915 hlist_del_rcu(&cic->cic_list);
2911 2916 spin_unlock_irqrestore(&ioc->lock, flags);
2912 2917  
... ... @@ -2934,7 +2939,7 @@
2934 2939 }
2935 2940  
2936 2941 do {
2937   - cic = radix_tree_lookup(&ioc->radix_root, (unsigned long) cfqd);
  2942 + cic = radix_tree_lookup(&ioc->radix_root, cfqd->cic_index);
2938 2943 rcu_read_unlock();
2939 2944 if (!cic)
2940 2945 break;
... ... @@ -2971,7 +2976,7 @@
2971 2976  
2972 2977 spin_lock_irqsave(&ioc->lock, flags);
2973 2978 ret = radix_tree_insert(&ioc->radix_root,
2974   - (unsigned long) cfqd, cic);
  2979 + cfqd->cic_index, cic);
2975 2980 if (!ret)
2976 2981 hlist_add_head_rcu(&cic->cic_list, &ioc->cic_list);
2977 2982 spin_unlock_irqrestore(&ioc->lock, flags);
2978 2983  
... ... @@ -3723,10 +3728,32 @@
3723 3728  
3724 3729 cfq_shutdown_timer_wq(cfqd);
3725 3730  
  3731 + spin_lock(&cic_index_lock);
  3732 + ida_remove(&cic_index_ida, cfqd->cic_index);
  3733 + spin_unlock(&cic_index_lock);
  3734 +
3726 3735 /* Wait for cfqg->blkg->key accessors to exit their grace periods. */
3727 3736 call_rcu(&cfqd->rcu, cfq_cfqd_free);
3728 3737 }
3729 3738  
  3739 +static int cfq_alloc_cic_index(void)
  3740 +{
  3741 + int index, error;
  3742 +
  3743 + do {
  3744 + if (!ida_pre_get(&cic_index_ida, GFP_KERNEL))
  3745 + return -ENOMEM;
  3746 +
  3747 + spin_lock(&cic_index_lock);
  3748 + error = ida_get_new(&cic_index_ida, &index);
  3749 + spin_unlock(&cic_index_lock);
  3750 + if (error && error != -EAGAIN)
  3751 + return error;
  3752 + } while (error);
  3753 +
  3754 + return index;
  3755 +}
  3756 +
3730 3757 static void *cfq_init_queue(struct request_queue *q)
3731 3758 {
3732 3759 struct cfq_data *cfqd;
3733 3760  
... ... @@ -3734,10 +3761,16 @@
3734 3761 struct cfq_group *cfqg;
3735 3762 struct cfq_rb_root *st;
3736 3763  
  3764 + i = cfq_alloc_cic_index();
  3765 + if (i < 0)
  3766 + return NULL;
  3767 +
3737 3768 cfqd = kmalloc_node(sizeof(*cfqd), GFP_KERNEL | __GFP_ZERO, q->node);
3738 3769 if (!cfqd)
3739 3770 return NULL;
3740 3771  
  3772 + cfqd->cic_index = i;
  3773 +
3741 3774 /* Init root service tree */
3742 3775 cfqd->grp_service_tree = CFQ_RB_ROOT;
3743 3776  
... ... @@ -3999,6 +4032,7 @@
3999 4032 */
4000 4033 if (elv_ioc_count_read(cfq_ioc_count))
4001 4034 wait_for_completion(&all_gone);
  4035 + ida_destroy(&cic_index_ida);
4002 4036 cfq_slab_kill();
4003 4037 }
4004 4038