Merge branch 'block-dir' of git://brick.kernel.dk/data/git/linux-2.6-block
authorLinus Torvalds <torvalds@g5.osdl.org>
Mon, 7 Nov 2005 16:32:39 +0000 (08:32 -0800)
committerLinus Torvalds <torvalds@g5.osdl.org>
Mon, 7 Nov 2005 16:32:39 +0000 (08:32 -0800)
1  2 
Makefile
block/as-iosched.c
block/ll_rw_blk.c

diff --combined Makefile
index 2dac8010c14296bf71b20da92d7256d6a5b41f22,a0270c5c3f333b80801903cb007b9edf86670b10..ea96da1572d595de19daeda44b2364416e9bd3a0
+++ b/Makefile
@@@ -346,8 -346,7 +346,8 @@@ AFLAGS_KERNEL      
  # Use LINUXINCLUDE when you must reference the include/ directory.
  # Needed to be compatible with the O= option
  LINUXINCLUDE    := -Iinclude \
 -                   $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include)
 +                   $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) \
 +                 -imacros include/linux/autoconf.h
  
  CPPFLAGS        := -D__KERNEL__ $(LINUXINCLUDE)
  
@@@ -583,7 -582,7 +583,7 @@@ export MODLI
  
  
  ifeq ($(KBUILD_EXTMOD),)
- core-y                += kernel/ mm/ fs/ ipc/ security/ crypto/
+ core-y                += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
  
  vmlinux-dirs  := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
                     $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
@@@ -1250,6 -1249,11 +1250,6 @@@ tags: FORC
  # Scripts to check various things for consistency
  # ---------------------------------------------------------------------------
  
 -configcheck:
 -      find * $(RCS_FIND_IGNORE) \
 -              -name '*.[hcS]' -type f -print | sort \
 -              | xargs $(PERL) -w scripts/checkconfig.pl
 -
  includecheck:
        find * $(RCS_FIND_IGNORE) \
                -name '*.[hcS]' -type f -print | sort \
diff --combined block/as-iosched.c
index a78e160b59a3545b8a06b78e2c78e503f1494d24,c6744ff382944a590767cef1827e627c1915c7ad..a78e160b59a3545b8a06b78e2c78e503f1494d24
@@@ -4,7 -4,7 +4,7 @@@
   *  Anticipatory & deadline i/o scheduler.
   *
   *  Copyright (C) 2002 Jens Axboe <axboe@suse.de>
 - *                     Nick Piggin <piggin@cyberone.com.au>
 + *                     Nick Piggin <nickpiggin@yahoo.com.au>
   *
   */
  #include <linux/kernel.h>
@@@ -69,7 -69,7 +69,7 @@@
  
  /* Bits in as_io_context.state */
  enum as_io_states {
 -      AS_TASK_RUNNING=0,      /* Process has not exitted */
 +      AS_TASK_RUNNING=0,      /* Process has not exited */
        AS_TASK_IOSTARTED,      /* Process has started some IO */
        AS_TASK_IORUNNING,      /* Process has completed some IO */
  };
@@@ -102,9 -102,6 +102,9 @@@ struct as_data 
  
        unsigned long exit_prob;        /* probability a task will exit while
                                           being waited on */
 +      unsigned long exit_no_coop;     /* probablility an exited task will
 +                                         not be part of a later cooperating
 +                                         request */
        unsigned long new_ttime_total;  /* mean thinktime on new proc */
        unsigned long new_ttime_mean;
        u64 new_seek_total;             /* mean seek on new proc */
@@@ -639,152 -636,37 +639,152 @@@ static void as_antic_timeout(unsigned l
                kblockd_schedule_work(&ad->antic_work);
  
                if (aic->ttime_samples == 0) {
 -                      /* process anticipated on has exitted or timed out*/
 +                      /* process anticipated on has exited or timed out*/
                        ad->exit_prob = (7*ad->exit_prob + 256)/8;
                }
 +              if (!test_bit(AS_TASK_RUNNING, &aic->state)) {
 +                      /* process not "saved" by a cooperating request */
 +                      ad->exit_no_coop = (7*ad->exit_no_coop + 256)/8;
 +              }
        }
        spin_unlock_irqrestore(q->queue_lock, flags);
  }
  
 +static void as_update_thinktime(struct as_data *ad, struct as_io_context *aic,
 +                              unsigned long ttime)
 +{
 +      /* fixed point: 1.0 == 1<<8 */
 +      if (aic->ttime_samples == 0) {
 +              ad->new_ttime_total = (7*ad->new_ttime_total + 256*ttime) / 8;
 +              ad->new_ttime_mean = ad->new_ttime_total / 256;
 +
 +              ad->exit_prob = (7*ad->exit_prob)/8;
 +      }
 +      aic->ttime_samples = (7*aic->ttime_samples + 256) / 8;
 +      aic->ttime_total = (7*aic->ttime_total + 256*ttime) / 8;
 +      aic->ttime_mean = (aic->ttime_total + 128) / aic->ttime_samples;
 +}
 +
 +static void as_update_seekdist(struct as_data *ad, struct as_io_context *aic,
 +                              sector_t sdist)
 +{
 +      u64 total;
 +
 +      if (aic->seek_samples == 0) {
 +              ad->new_seek_total = (7*ad->new_seek_total + 256*(u64)sdist)/8;
 +              ad->new_seek_mean = ad->new_seek_total / 256;
 +      }
 +
 +      /*
 +       * Don't allow the seek distance to get too large from the
 +       * odd fragment, pagein, etc
 +       */
 +      if (aic->seek_samples <= 60) /* second&third seek */
 +              sdist = min(sdist, (aic->seek_mean * 4) + 2*1024*1024);
 +      else
 +              sdist = min(sdist, (aic->seek_mean * 4) + 2*1024*64);
 +
 +      aic->seek_samples = (7*aic->seek_samples + 256) / 8;
 +      aic->seek_total = (7*aic->seek_total + (u64)256*sdist) / 8;
 +      total = aic->seek_total + (aic->seek_samples/2);
 +      do_div(total, aic->seek_samples);
 +      aic->seek_mean = (sector_t)total;
 +}
 +
 +/*
 + * as_update_iohist keeps a decaying histogram of IO thinktimes, and
 + * updates @aic->ttime_mean based on that. It is called when a new
 + * request is queued.
 + */
 +static void as_update_iohist(struct as_data *ad, struct as_io_context *aic,
 +                              struct request *rq)
 +{
 +      struct as_rq *arq = RQ_DATA(rq);
 +      int data_dir = arq->is_sync;
 +      unsigned long thinktime = 0;
 +      sector_t seek_dist;
 +
 +      if (aic == NULL)
 +              return;
 +
 +      if (data_dir == REQ_SYNC) {
 +              unsigned long in_flight = atomic_read(&aic->nr_queued)
 +                                      + atomic_read(&aic->nr_dispatched);
 +              spin_lock(&aic->lock);
 +              if (test_bit(AS_TASK_IORUNNING, &aic->state) ||
 +                      test_bit(AS_TASK_IOSTARTED, &aic->state)) {
 +                      /* Calculate read -> read thinktime */
 +                      if (test_bit(AS_TASK_IORUNNING, &aic->state)
 +                                                      && in_flight == 0) {
 +                              thinktime = jiffies - aic->last_end_request;
 +                              thinktime = min(thinktime, MAX_THINKTIME-1);
 +                      }
 +                      as_update_thinktime(ad, aic, thinktime);
 +
 +                      /* Calculate read -> read seek distance */
 +                      if (aic->last_request_pos < rq->sector)
 +                              seek_dist = rq->sector - aic->last_request_pos;
 +                      else
 +                              seek_dist = aic->last_request_pos - rq->sector;
 +                      as_update_seekdist(ad, aic, seek_dist);
 +              }
 +              aic->last_request_pos = rq->sector + rq->nr_sectors;
 +              set_bit(AS_TASK_IOSTARTED, &aic->state);
 +              spin_unlock(&aic->lock);
 +      }
 +}
 +
  /*
   * as_close_req decides if one request is considered "close" to the
   * previous one issued.
   */
 -static int as_close_req(struct as_data *ad, struct as_rq *arq)
 +static int as_close_req(struct as_data *ad, struct as_io_context *aic,
 +                              struct as_rq *arq)
  {
        unsigned long delay;    /* milliseconds */
        sector_t last = ad->last_sector[ad->batch_data_dir];
        sector_t next = arq->request->sector;
        sector_t delta; /* acceptable close offset (in sectors) */
 +      sector_t s;
  
        if (ad->antic_status == ANTIC_OFF || !ad->ioc_finished)
                delay = 0;
        else
                delay = ((jiffies - ad->antic_start) * 1000) / HZ;
  
 -      if (delay <= 1)
 -              delta = 64;
 +      if (delay == 0)
 +              delta = 8192;
        else if (delay <= 20 && delay <= ad->antic_expire)
 -              delta = 64 << (delay-1);
 +              delta = 8192 << delay;
        else
                return 1;
  
 -      return (last - (delta>>1) <= next) && (next <= last + delta);
 +      if ((last <= next + (delta>>1)) && (next <= last + delta))
 +              return 1;
 +
 +      if (last < next)
 +              s = next - last;
 +      else
 +              s = last - next;
 +
 +      if (aic->seek_samples == 0) {
 +              /*
 +               * Process has just started IO. Use past statistics to
 +               * gauge success possibility
 +               */
 +              if (ad->new_seek_mean > s) {
 +                      /* this request is better than what we're expecting */
 +                      return 1;
 +              }
 +
 +      } else {
 +              if (aic->seek_mean > s) {
 +                      /* this request is better than what we're expecting */
 +                      return 1;
 +              }
 +      }
 +
 +      return 0;
  }
  
  /*
   * dispatch it ASAP, because we know that application will not be submitting
   * any new reads.
   *
 - * If the task which has submitted the request has exitted, break anticipation.
 + * If the task which has submitted the request has exited, break anticipation.
   *
   * If this task has queued some other IO, do not enter enticipation.
   */
@@@ -804,6 -686,7 +804,6 @@@ static int as_can_break_anticipation(st
  {
        struct io_context *ioc;
        struct as_io_context *aic;
 -      sector_t s;
  
        ioc = ad->io_context;
        BUG_ON(!ioc);
        if (!aic)
                return 0;
  
 -      if (!test_bit(AS_TASK_RUNNING, &aic->state)) {
 -              /* process anticipated on has exitted */
 -              if (aic->ttime_samples == 0)
 -                      ad->exit_prob = (7*ad->exit_prob + 256)/8;
 -              return 1;
 -      }
 -
        if (atomic_read(&aic->nr_queued) > 0) {
                /* process has more requests queued */
                return 1;
                return 1;
        }
  
 -      if (arq && arq->is_sync == REQ_SYNC && as_close_req(ad, arq)) {
 +      if (arq && arq->is_sync == REQ_SYNC && as_close_req(ad, aic, arq)) {
                /*
                 * Found a close request that is not one of ours.
                 *
 -               * This makes close requests from another process reset
 -               * our thinktime delay. Is generally useful when there are
 +               * This makes close requests from another process update
 +               * our IO history. Is generally useful when there are
                 * two or more cooperating processes working in the same
                 * area.
                 */
 -              spin_lock(&aic->lock);
 -              aic->last_end_request = jiffies;
 -              spin_unlock(&aic->lock);
 +              if (!test_bit(AS_TASK_RUNNING, &aic->state)) {
 +                      if (aic->ttime_samples == 0)
 +                              ad->exit_prob = (7*ad->exit_prob + 256)/8;
 +
 +                      ad->exit_no_coop = (7*ad->exit_no_coop)/8;
 +              }
 +
 +              as_update_iohist(ad, aic, arq->request);
                return 1;
        }
  
 +      if (!test_bit(AS_TASK_RUNNING, &aic->state)) {
 +              /* process anticipated on has exited */
 +              if (aic->ttime_samples == 0)
 +                      ad->exit_prob = (7*ad->exit_prob + 256)/8;
 +
 +              if (ad->exit_no_coop > 128)
 +                      return 1;
 +      }
  
        if (aic->ttime_samples == 0) {
                if (ad->new_ttime_mean > ad->antic_expire)
                        return 1;
 -              if (ad->exit_prob > 128)
 +              if (ad->exit_prob * ad->exit_no_coop > 128*256)
                        return 1;
        } else if (aic->ttime_mean > ad->antic_expire) {
                /* the process thinks too much between requests */
                return 1;
        }
  
 -      if (!arq)
 -              return 0;
 -
 -      if (ad->last_sector[REQ_SYNC] < arq->request->sector)
 -              s = arq->request->sector - ad->last_sector[REQ_SYNC];
 -      else
 -              s = ad->last_sector[REQ_SYNC] - arq->request->sector;
 -
 -      if (aic->seek_samples == 0) {
 -              /*
 -               * Process has just started IO. Use past statistics to
 -               * guage success possibility
 -               */
 -              if (ad->new_seek_mean > s) {
 -                      /* this request is better than what we're expecting */
 -                      return 1;
 -              }
 -
 -      } else {
 -              if (aic->seek_mean > s) {
 -                      /* this request is better than what we're expecting */
 -                      return 1;
 -              }
 -      }
 -
        return 0;
  }
  
@@@ -907,11 -809,94 +907,11 @@@ static int as_can_anticipate(struct as_
         * Status is either ANTIC_OFF so start waiting,
         * ANTIC_WAIT_REQ so continue waiting for request to finish
         * or ANTIC_WAIT_NEXT so continue waiting for an acceptable request.
 -       *
         */
  
        return 1;
  }
  
 -static void as_update_thinktime(struct as_data *ad, struct as_io_context *aic, unsigned long ttime)
 -{
 -      /* fixed point: 1.0 == 1<<8 */
 -      if (aic->ttime_samples == 0) {
 -              ad->new_ttime_total = (7*ad->new_ttime_total + 256*ttime) / 8;
 -              ad->new_ttime_mean = ad->new_ttime_total / 256;
 -
 -              ad->exit_prob = (7*ad->exit_prob)/8;
 -      }
 -      aic->ttime_samples = (7*aic->ttime_samples + 256) / 8;
 -      aic->ttime_total = (7*aic->ttime_total + 256*ttime) / 8;
 -      aic->ttime_mean = (aic->ttime_total + 128) / aic->ttime_samples;
 -}
 -
 -static void as_update_seekdist(struct as_data *ad, struct as_io_context *aic, sector_t sdist)
 -{
 -      u64 total;
 -
 -      if (aic->seek_samples == 0) {
 -              ad->new_seek_total = (7*ad->new_seek_total + 256*(u64)sdist)/8;
 -              ad->new_seek_mean = ad->new_seek_total / 256;
 -      }
 -
 -      /*
 -       * Don't allow the seek distance to get too large from the
 -       * odd fragment, pagein, etc
 -       */
 -      if (aic->seek_samples <= 60) /* second&third seek */
 -              sdist = min(sdist, (aic->seek_mean * 4) + 2*1024*1024);
 -      else
 -              sdist = min(sdist, (aic->seek_mean * 4) + 2*1024*64);
 -
 -      aic->seek_samples = (7*aic->seek_samples + 256) / 8;
 -      aic->seek_total = (7*aic->seek_total + (u64)256*sdist) / 8;
 -      total = aic->seek_total + (aic->seek_samples/2);
 -      do_div(total, aic->seek_samples);
 -      aic->seek_mean = (sector_t)total;
 -}
 -
 -/*
 - * as_update_iohist keeps a decaying histogram of IO thinktimes, and
 - * updates @aic->ttime_mean based on that. It is called when a new
 - * request is queued.
 - */
 -static void as_update_iohist(struct as_data *ad, struct as_io_context *aic, struct request *rq)
 -{
 -      struct as_rq *arq = RQ_DATA(rq);
 -      int data_dir = arq->is_sync;
 -      unsigned long thinktime;
 -      sector_t seek_dist;
 -
 -      if (aic == NULL)
 -              return;
 -
 -      if (data_dir == REQ_SYNC) {
 -              unsigned long in_flight = atomic_read(&aic->nr_queued)
 -                                      + atomic_read(&aic->nr_dispatched);
 -              spin_lock(&aic->lock);
 -              if (test_bit(AS_TASK_IORUNNING, &aic->state) ||
 -                      test_bit(AS_TASK_IOSTARTED, &aic->state)) {
 -                      /* Calculate read -> read thinktime */
 -                      if (test_bit(AS_TASK_IORUNNING, &aic->state)
 -                                                      && in_flight == 0) {
 -                              thinktime = jiffies - aic->last_end_request;
 -                              thinktime = min(thinktime, MAX_THINKTIME-1);
 -                      } else
 -                              thinktime = 0;
 -                      as_update_thinktime(ad, aic, thinktime);
 -
 -                      /* Calculate read -> read seek distance */
 -                      if (aic->last_request_pos < rq->sector)
 -                              seek_dist = rq->sector - aic->last_request_pos;
 -                      else
 -                              seek_dist = aic->last_request_pos - rq->sector;
 -                      as_update_seekdist(ad, aic, seek_dist);
 -              }
 -              aic->last_request_pos = rq->sector + rq->nr_sectors;
 -              set_bit(AS_TASK_IOSTARTED, &aic->state);
 -              spin_unlock(&aic->lock);
 -      }
 -}
 -
  /*
   * as_update_arq must be called whenever a request (arq) is added to
   * the sort_list. This function keeps caches up to date, and checks if the
@@@ -1216,7 -1201,7 +1216,7 @@@ static int as_dispatch_request(request_
                || ad->changed_batch)
                return 0;
  
 -      if (!(reads && writes && as_batch_expired(ad)) ) {
 +      if (!(reads && writes && as_batch_expired(ad))) {
                /*
                 * batch is still running or no reads or no writes
                 */
@@@ -1331,8 -1316,7 +1331,8 @@@ fifo_expired
   * Add arq to a list behind alias
   */
  static inline void
 -as_add_aliased_request(struct as_data *ad, struct as_rq *arq, struct as_rq *alias)
 +as_add_aliased_request(struct as_data *ad, struct as_rq *arq,
 +                              struct as_rq *alias)
  {
        struct request  *req = arq->request;
        struct list_head *insert = alias->request->queuelist.prev;
@@@ -1457,8 -1441,8 +1457,8 @@@ static int as_queue_empty(request_queue
                && list_empty(&ad->fifo_list[REQ_SYNC]);
  }
  
 -static struct request *
 -as_former_request(request_queue_t *q, struct request *rq)
 +static struct request *as_former_request(request_queue_t *q,
 +                                      struct request *rq)
  {
        struct as_rq *arq = RQ_DATA(rq);
        struct rb_node *rbprev = rb_prev(&arq->rb_node);
        return ret;
  }
  
 -static struct request *
 -as_latter_request(request_queue_t *q, struct request *rq)
 +static struct request *as_latter_request(request_queue_t *q,
 +                                      struct request *rq)
  {
        struct as_rq *arq = RQ_DATA(rq);
        struct rb_node *rbnext = rb_next(&arq->rb_node);
@@@ -1553,7 -1537,7 +1553,7 @@@ static void as_merged_request(request_q
                 * currently don't bother. Ditto the next function.
                 */
                as_del_arq_rb(ad, arq);
 -              if ((alias = as_add_arq_rb(ad, arq)) ) {
 +              if ((alias = as_add_arq_rb(ad, arq))) {
                        list_del_init(&arq->fifo);
                        as_add_aliased_request(ad, arq, alias);
                        if (next_arq)
        }
  }
  
 -static void
 -as_merged_requests(request_queue_t *q, struct request *req,
 -                       struct request *next)
 +static void as_merged_requests(request_queue_t *q, struct request *req,
 +                              struct request *next)
  {
        struct as_data *ad = q->elevator->elevator_data;
        struct as_rq *arq = RQ_DATA(req);
                        next_arq = as_find_next_arq(ad, arq);
  
                as_del_arq_rb(ad, arq);
 -              if ((alias = as_add_arq_rb(ad, arq)) ) {
 +              if ((alias = as_add_arq_rb(ad, arq))) {
                        list_del_init(&arq->fifo);
                        as_add_aliased_request(ad, arq, alias);
                        if (next_arq)
@@@ -1821,14 -1806,9 +1821,14 @@@ static ssize_t as_est_show(struct as_da
  {
        int pos = 0;
  
 -      pos += sprintf(page+pos, "%lu %% exit probability\n", 100*ad->exit_prob/256);
 +      pos += sprintf(page+pos, "%lu %% exit probability\n",
 +                              100*ad->exit_prob/256);
 +      pos += sprintf(page+pos, "%lu %% probability of exiting without a "
 +                              "cooperating process submitting IO\n",
 +                              100*ad->exit_no_coop/256);
        pos += sprintf(page+pos, "%lu ms new thinktime\n", ad->new_ttime_mean);
 -      pos += sprintf(page+pos, "%llu sectors new seek distance\n", (unsigned long long)ad->new_seek_mean);
 +      pos += sprintf(page+pos, "%llu sectors new seek distance\n",
 +                              (unsigned long long)ad->new_seek_mean);
  
        return pos;
  }
diff --combined block/ll_rw_blk.c
index 5f52e30b43f812c75cef8289571e9a1a35bd2808,2747741677fb0d92c10dc76c272763eb6f2b1a96..5f52e30b43f812c75cef8289571e9a1a35bd2808
@@@ -706,6 -706,7 +706,6 @@@ EXPORT_SYMBOL(blk_queue_dma_alignment)
  
  /**
   * blk_queue_find_tag - find a request by its tag and queue
 - *
   * @q:         The request queue for the device
   * @tag: The tag of the request
   *