Commit bca4b914b5da3d8e7b9b647f620b71dc85c0c394

Authored by Konstantin Khlebnikov
Committed by Jens Axboe
1 parent f4b87dee92

cfq-iosched: remove dead_key from cfq_io_context

Remove ->dead_key field from cfq_io_context to shrink its size to 128 bytes.
(64 bytes for 32-bit hosts)

Use lower bit in ->key as dead-mark, instead of moving key to separate field.
After this for dead cfq_io_context we got cic->key != cfqd automatically.
Thus, io_context's last-hit cache should work without changing.

Now to check ->key for non-dead state compare it with cfqd,
instead of checking ->key for non-null value as it was before.

Plus remove obsolete race protection in cfq_cic_lookup.
This race gone after v2.6.24-1728-g4ac845a

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

Showing 2 changed files with 28 additions and 14 deletions Side-by-side Diff

... ... @@ -430,6 +430,23 @@
430 430 cic->cfqq[is_sync] = cfqq;
431 431 }
432 432  
  433 +#define CIC_DEAD_KEY 1ul
  434 +
  435 +static inline void *cfqd_dead_key(struct cfq_data *cfqd)
  436 +{
  437 + return (void *)((unsigned long) cfqd | CIC_DEAD_KEY);
  438 +}
  439 +
  440 +static inline struct cfq_data *cic_to_cfqd(struct cfq_io_context *cic)
  441 +{
  442 + struct cfq_data *cfqd = cic->key;
  443 +
  444 + if (unlikely((unsigned long) cfqd & CIC_DEAD_KEY))
  445 + return NULL;
  446 +
  447 + return cfqd;
  448 +}
  449 +
433 450 /*
434 451 * We regard a request as SYNC, if it's either a read or has the SYNC bit
435 452 * set (in which case it could also be direct WRITE).
436 453  
437 454  
... ... @@ -2510,11 +2527,12 @@
2510 2527 static void cic_free_func(struct io_context *ioc, struct cfq_io_context *cic)
2511 2528 {
2512 2529 unsigned long flags;
  2530 + unsigned long dead_key = (unsigned long) cic->key;
2513 2531  
2514   - BUG_ON(!cic->dead_key);
  2532 + BUG_ON(!(dead_key & CIC_DEAD_KEY));
2515 2533  
2516 2534 spin_lock_irqsave(&ioc->lock, flags);
2517   - radix_tree_delete(&ioc->radix_root, cic->dead_key);
  2535 + radix_tree_delete(&ioc->radix_root, dead_key & ~CIC_DEAD_KEY);
2518 2536 hlist_del_rcu(&cic->cic_list);
2519 2537 spin_unlock_irqrestore(&ioc->lock, flags);
2520 2538  
2521 2539  
... ... @@ -2573,11 +2591,10 @@
2573 2591 list_del_init(&cic->queue_list);
2574 2592  
2575 2593 /*
2576   - * Make sure key == NULL is seen for dead queues
  2594 + * Make sure dead mark is seen for dead queues
2577 2595 */
2578 2596 smp_wmb();
2579   - cic->dead_key = (unsigned long) cic->key;
2580   - cic->key = NULL;
  2597 + cic->key = cfqd_dead_key(cfqd);
2581 2598  
2582 2599 if (ioc->ioc_data == cic)
2583 2600 rcu_assign_pointer(ioc->ioc_data, NULL);
... ... @@ -2596,7 +2613,7 @@
2596 2613 static void cfq_exit_single_io_context(struct io_context *ioc,
2597 2614 struct cfq_io_context *cic)
2598 2615 {
2599   - struct cfq_data *cfqd = cic->key;
  2616 + struct cfq_data *cfqd = cic_to_cfqd(cic);
2600 2617  
2601 2618 if (cfqd) {
2602 2619 struct request_queue *q = cfqd->queue;
... ... @@ -2609,7 +2626,7 @@
2609 2626 * race between exiting task and queue
2610 2627 */
2611 2628 smp_read_barrier_depends();
2612   - if (cic->key)
  2629 + if (cic->key == cfqd)
2613 2630 __cfq_exit_single_io_context(cfqd, cic);
2614 2631  
2615 2632 spin_unlock_irqrestore(q->queue_lock, flags);
... ... @@ -2689,7 +2706,7 @@
2689 2706  
2690 2707 static void changed_ioprio(struct io_context *ioc, struct cfq_io_context *cic)
2691 2708 {
2692   - struct cfq_data *cfqd = cic->key;
  2709 + struct cfq_data *cfqd = cic_to_cfqd(cic);
2693 2710 struct cfq_queue *cfqq;
2694 2711 unsigned long flags;
2695 2712  
... ... @@ -2746,7 +2763,7 @@
2746 2763 static void changed_cgroup(struct io_context *ioc, struct cfq_io_context *cic)
2747 2764 {
2748 2765 struct cfq_queue *sync_cfqq = cic_to_cfqq(cic, 1);
2749   - struct cfq_data *cfqd = cic->key;
  2766 + struct cfq_data *cfqd = cic_to_cfqd(cic);
2750 2767 unsigned long flags;
2751 2768 struct request_queue *q;
2752 2769  
... ... @@ -2883,6 +2900,7 @@
2883 2900 unsigned long flags;
2884 2901  
2885 2902 WARN_ON(!list_empty(&cic->queue_list));
  2903 + BUG_ON(cic->key != cfqd_dead_key(cfqd));
2886 2904  
2887 2905 spin_lock_irqsave(&ioc->lock, flags);
2888 2906  
... ... @@ -2900,7 +2918,6 @@
2900 2918 {
2901 2919 struct cfq_io_context *cic;
2902 2920 unsigned long flags;
2903   - void *k;
2904 2921  
2905 2922 if (unlikely(!ioc))
2906 2923 return NULL;
... ... @@ -2921,9 +2938,7 @@
2921 2938 rcu_read_unlock();
2922 2939 if (!cic)
2923 2940 break;
2924   - /* ->key must be copied to avoid race with cfq_exit_queue() */
2925   - k = cic->key;
2926   - if (unlikely(!k)) {
  2941 + if (unlikely(cic->key != cfqd)) {
2927 2942 cfq_drop_dead_cic(cfqd, ioc, cic);
2928 2943 rcu_read_lock();
2929 2944 continue;
include/linux/iocontext.h
... ... @@ -7,7 +7,6 @@
7 7 struct cfq_queue;
8 8 struct cfq_io_context {
9 9 void *key;
10   - unsigned long dead_key;
11 10  
12 11 struct cfq_queue *cfqq[2];
13 12