Merge branch 'v2.6.37-rc2' into for-2.6.38/core
authorJens Axboe <jaxboe@fusionio.com>
Tue, 16 Nov 2010 09:09:42 +0000 (10:09 +0100)
committerJens Axboe <jaxboe@fusionio.com>
Tue, 16 Nov 2010 09:09:42 +0000 (10:09 +0100)
1  2 
block/cfq-iosched.c
fs/partitions/check.c

diff --combined block/cfq-iosched.c
@@@ -160,6 -160,7 +160,7 @@@ enum wl_prio_t 
        BE_WORKLOAD = 0,
        RT_WORKLOAD = 1,
        IDLE_WORKLOAD = 2,
+       CFQ_PRIO_NR,
  };
  
  /*
@@@ -184,10 -185,19 +185,19 @@@ struct cfq_group 
        /* number of cfqq currently on this group */
        int nr_cfqq;
  
-       /* Per group busy queus average. Useful for workload slice calc. */
-       unsigned int busy_queues_avg[2];
        /*
-        * rr lists of queues with requests, onle rr for each priority class.
+        * Per group busy queus average. Useful for workload slice calc. We
+        * create the array for each prio class but at run time it is used
+        * only for RT and BE class and slot for IDLE class remains unused.
+        * This is primarily done to avoid confusion and a gcc warning.
+        */
+       unsigned int busy_queues_avg[CFQ_PRIO_NR];
+       /*
+        * rr lists of queues with requests. We maintain service trees for
+        * RT and BE classes. These trees are subdivided in subclasses
+        * of SYNC, SYNC_NOIDLE and ASYNC based on workload type. For IDLE
+        * class there is no subclassification and all the cfq queues go on
+        * a single tree service_tree_idle.
         * Counts are embedded in the cfq_rb_root
         */
        struct cfq_rb_root service_trees[2][3];
@@@ -221,7 -231,6 +231,6 @@@ struct cfq_data 
        enum wl_type_t serving_type;
        unsigned long workload_expires;
        struct cfq_group *serving_group;
-       bool noidle_tree_requires_idle;
  
        /*
         * Each priority tree is sorted by next_request position.  These
@@@ -637,11 -646,11 +646,11 @@@ cfq_set_prio_slice(struct cfq_data *cfq
  static inline bool cfq_slice_used(struct cfq_queue *cfqq)
  {
        if (cfq_cfqq_slice_new(cfqq))
 -              return 0;
 +              return false;
        if (time_before(jiffies, cfqq->slice_end))
 -              return 0;
 +              return false;
  
 -      return 1;
 +      return true;
  }
  
  /*
@@@ -977,8 -986,8 +986,8 @@@ static inline struct cfq_group *cfqg_of
        return NULL;
  }
  
- void
cfq_update_blkio_group_weight(struct blkio_group *blkg, unsigned int weight)
+ void cfq_update_blkio_group_weight(void *key, struct blkio_group *blkg,
                                      unsigned int weight)
  {
        cfqg_of_blkg(blkg)->weight = weight;
  }
@@@ -1892,10 -1901,10 +1901,10 @@@ static bool cfq_should_idle(struct cfq_
         * in their service tree.
         */
        if (service_tree->count == 1 && cfq_cfqq_sync(cfqq))
 -              return 1;
 +              return true;
        cfq_log_cfqq(cfqd, cfqq, "Not idling. st->count:%d",
                        service_tree->count);
 -      return 0;
 +      return false;
  }
  
  static void cfq_arm_slice_timer(struct cfq_data *cfqd)
@@@ -2180,7 -2189,6 +2189,6 @@@ static void choose_service_tree(struct 
        slice = max_t(unsigned, slice, CFQ_MIN_TT);
        cfq_log(cfqd, "workload slice:%d", slice);
        cfqd->workload_expires = jiffies + slice;
-       cfqd->noidle_tree_requires_idle = false;
  }
  
  static struct cfq_group *cfq_get_next_cfqg(struct cfq_data *cfqd)
@@@ -2285,17 -2293,6 +2293,17 @@@ static struct cfq_queue *cfq_select_que
                goto keep_queue;
        }
  
 +      /*
 +       * This is a deep seek queue, but the device is much faster than
 +       * the queue can deliver, don't idle
 +       **/
 +      if (CFQQ_SEEKY(cfqq) && cfq_cfqq_idle_window(cfqq) &&
 +          (cfq_cfqq_slice_new(cfqq) ||
 +          (cfqq->slice_end - jiffies > jiffies - cfqq->slice_start))) {
 +              cfq_clear_cfqq_deep(cfqq);
 +              cfq_clear_cfqq_idle_window(cfqq);
 +      }
 +
        if (cfqq->dispatched && cfq_should_idle(cfqd, cfqq)) {
                cfqq = NULL;
                goto keep_queue;
@@@ -2370,12 -2367,12 +2378,12 @@@ static inline bool cfq_slice_used_soon(
  {
        /* the queue hasn't finished any request, can't estimate */
        if (cfq_cfqq_slice_new(cfqq))
 -              return 1;
 +              return true;
        if (time_after(jiffies + cfqd->cfq_slice_idle * cfqq->dispatched,
                cfqq->slice_end))
 -              return 1;
 +              return true;
  
 -      return 0;
 +      return false;
  }
  
  static bool cfq_may_dispatch(struct cfq_data *cfqd, struct cfq_queue *cfqq)
@@@ -3188,7 -3185,9 +3196,9 @@@ cfq_update_idle_window(struct cfq_data 
        if (cfqq->queued[0] + cfqq->queued[1] >= 4)
                cfq_mark_cfqq_deep(cfqq);
  
-       if (!atomic_read(&cic->ioc->nr_tasks) || !cfqd->cfq_slice_idle ||
+       if (cfqq->next_rq && (cfqq->next_rq->cmd_flags & REQ_NOIDLE))
+               enable_idle = 0;
+       else if (!atomic_read(&cic->ioc->nr_tasks) || !cfqd->cfq_slice_idle ||
            (!cfq_cfqq_deep(cfqq) && CFQQ_SEEKY(cfqq)))
                enable_idle = 0;
        else if (sample_valid(cic->ttime_samples)) {
@@@ -3266,10 -3265,6 +3276,10 @@@ cfq_should_preempt(struct cfq_data *cfq
        if (cfq_class_rt(new_cfqq) && !cfq_class_rt(cfqq))
                return true;
  
 +      /* An idle queue should not be idle now for some reason */
 +      if (RB_EMPTY_ROOT(&cfqq->sort_list) && !cfq_should_idle(cfqd, cfqq))
 +              return true;
 +
        if (!cfqd->active_cic || !cfq_cfqq_wait_request(cfqq))
                return false;
  
@@@ -3509,17 -3504,7 +3519,7 @@@ static void cfq_completed_request(struc
                        cfq_slice_expired(cfqd, 1);
                else if (sync && cfqq_empty &&
                         !cfq_close_cooperator(cfqd, cfqq)) {
-                       cfqd->noidle_tree_requires_idle |=
-                               !(rq->cmd_flags & REQ_NOIDLE);
-                       /*
-                        * Idling is enabled for SYNC_WORKLOAD.
-                        * SYNC_NOIDLE_WORKLOAD idles at the end of the tree
-                        * only if we processed at least one !REQ_NOIDLE request
-                        */
-                       if (cfqd->serving_type == SYNC_WORKLOAD
-                           || cfqd->noidle_tree_requires_idle
-                           || cfqq->cfqg->nr_cfqq == 1)
-                               cfq_arm_slice_timer(cfqd);
+                       cfq_arm_slice_timer(cfqd);
                }
        }
  
@@@ -4105,6 -4090,7 +4105,7 @@@ static struct blkio_policy_type blkio_p
                .blkio_unlink_group_fn =        cfq_unlink_blkio_group,
                .blkio_update_group_weight_fn = cfq_update_blkio_group_weight,
        },
+       .plid = BLKIO_POLICY_PROP,
  };
  #else
  static struct blkio_policy_type blkio_policy_cfq;
diff --combined fs/partitions/check.c
@@@ -237,13 -237,6 +237,13 @@@ ssize_t part_size_show(struct device *d
        return sprintf(buf, "%llu\n",(unsigned long long)p->nr_sects);
  }
  
 +ssize_t part_ro_show(struct device *dev,
 +                     struct device_attribute *attr, char *buf)
 +{
 +      struct hd_struct *p = dev_to_part(dev);
 +      return sprintf(buf, "%d\n", p->policy ? 1 : 0);
 +}
 +
  ssize_t part_alignment_offset_show(struct device *dev,
                                   struct device_attribute *attr, char *buf)
  {
@@@ -319,7 -312,6 +319,7 @@@ ssize_t part_fail_store(struct device *
  static DEVICE_ATTR(partition, S_IRUGO, part_partition_show, NULL);
  static DEVICE_ATTR(start, S_IRUGO, part_start_show, NULL);
  static DEVICE_ATTR(size, S_IRUGO, part_size_show, NULL);
 +static DEVICE_ATTR(ro, S_IRUGO, part_ro_show, NULL);
  static DEVICE_ATTR(alignment_offset, S_IRUGO, part_alignment_offset_show, NULL);
  static DEVICE_ATTR(discard_alignment, S_IRUGO, part_discard_alignment_show,
                   NULL);
@@@ -334,7 -326,6 +334,7 @@@ static struct attribute *part_attrs[] 
        &dev_attr_partition.attr,
        &dev_attr_start.attr,
        &dev_attr_size.attr,
 +      &dev_attr_ro.attr,
        &dev_attr_alignment_offset.attr,
        &dev_attr_discard_alignment.attr,
        &dev_attr_stat.attr,
@@@ -361,6 -352,7 +361,7 @@@ static void part_release(struct device 
  {
        struct hd_struct *p = dev_to_part(dev);
        free_part_stats(p);
+       free_part_info(p);
        kfree(p);
  }
  
@@@ -410,7 -402,8 +411,8 @@@ static DEVICE_ATTR(whole_disk, S_IRUSR 
                   whole_disk_show, NULL);
  
  struct hd_struct *add_partition(struct gendisk *disk, int partno,
-                               sector_t start, sector_t len, int flags)
+                               sector_t start, sector_t len, int flags,
+                               struct partition_meta_info *info)
  {
        struct hd_struct *p;
        dev_t devt = MKDEV(0, 0);
        p->partno = partno;
        p->policy = get_disk_ro(disk);
  
+       if (info) {
+               struct partition_meta_info *pinfo = alloc_part_info(disk);
+               if (!pinfo)
+                       goto out_free_stats;
+               memcpy(pinfo, info, sizeof(*info));
+               p->info = pinfo;
+       }
        dname = dev_name(ddev);
        if (isdigit(dname[strlen(dname) - 1]))
                dev_set_name(pdev, "%sp%d", dname, partno);
  
        err = blk_alloc_devt(p, &devt);
        if (err)
-               goto out_free_stats;
+               goto out_free_info;
        pdev->devt = devt;
  
        /* delay uevent until 'holders' subdir is created */
  
        return p;
  
+ out_free_info:
+       free_part_info(p);
  out_free_stats:
        free_part_stats(p);
  out_free:
@@@ -522,14 -525,14 +534,14 @@@ void register_disk(struct gendisk *disk
  
        if (device_add(ddev))
                return;
- #ifndef CONFIG_SYSFS_DEPRECATED
-       err = sysfs_create_link(block_depr, &ddev->kobj,
-                               kobject_name(&ddev->kobj));
-       if (err) {
-               device_del(ddev);
-               return;
+       if (!sysfs_deprecated) {
+               err = sysfs_create_link(block_depr, &ddev->kobj,
+                                       kobject_name(&ddev->kobj));
+               if (err) {
+                       device_del(ddev);
+                       return;
+               }
        }
- #endif
        disk->part0.holder_dir = kobject_create_and_add("holders", &ddev->kobj);
        disk->slave_dir = kobject_create_and_add("slaves", &ddev->kobj);
  
@@@ -651,6 -654,7 +663,7 @@@ rescan
        /* add partitions */
        for (p = 1; p < state->limit; p++) {
                sector_t size, from;
+               struct partition_meta_info *info = NULL;
  
                size = state->parts[p].size;
                if (!size)
                                size = get_capacity(disk) - from;
                        }
                }
+               if (state->parts[p].has_info)
+                       info = &state->parts[p].info;
                part = add_partition(disk, p, from, size,
-                                    state->parts[p].flags);
+                                    state->parts[p].flags,
+                                    &state->parts[p].info);
                if (IS_ERR(part)) {
                        printk(KERN_ERR " %s: p%d could not be added: %ld\n",
                               disk->disk_name, p, -PTR_ERR(part));
@@@ -746,8 -754,7 +763,7 @@@ void del_gendisk(struct gendisk *disk
        kobject_put(disk->part0.holder_dir);
        kobject_put(disk->slave_dir);
        disk->driverfs_dev = NULL;
- #ifndef CONFIG_SYSFS_DEPRECATED
-       sysfs_remove_link(block_depr, dev_name(disk_to_dev(disk)));
- #endif
+       if (!sysfs_deprecated)
+               sysfs_remove_link(block_depr, dev_name(disk_to_dev(disk)));
        device_del(disk_to_dev(disk));
  }