Merge git://git.infradead.org/~dwmw2/rbtree-2.6
Linus Torvalds [Tue, 20 Jun 2006 21:51:22 +0000 (14:51 -0700)]
* git://git.infradead.org/~dwmw2/rbtree-2.6:
  [RBTREE] Switch rb_colour() et al to en_US spelling of 'color' for consistency
  Update UML kernel/physmem.c to use rb_parent() accessor macro
  [RBTREE] Update hrtimers to use rb_parent() accessor macro.
  [RBTREE] Add explicit alignment to sizeof(long) for struct rb_node.
  [RBTREE] Merge colour and parent fields of struct rb_node.
  [RBTREE] Remove dead code in rb_erase()
  [RBTREE] Update JFFS2 to use rb_parent() accessor macro.
  [RBTREE] Update eventpoll.c to use rb_parent() accessor macro.
  [RBTREE] Update key.c to use rb_parent() accessor macro.
  [RBTREE] Update ext3 to use rb_parent() accessor macro.
  [RBTREE] Change rbtree off-tree marking in I/O schedulers.
  [RBTREE] Add accessor macros for colour and parent fields of rb_node

1  2 
arch/um/kernel/physmem.c
block/as-iosched.c
block/cfq-iosched.c
block/deadline-iosched.c
fs/jffs2/nodelist.h
fs/jffs2/readinode.c
kernel/hrtimer.c

diff --combined arch/um/kernel/physmem.c
@@@ -69,7 -69,7 +69,7 @@@ static void insert_phys_mapping(struct 
                panic("Physical remapping for %p already present",
                      desc->virt);
  
-       rb_link_node(&desc->rb, (*n)->rb_parent, n);
+       rb_link_node(&desc->rb, rb_parent(*n), n);
        rb_insert_color(&desc->rb, &phys_mappings);
  }
  
@@@ -407,8 -407,6 +407,8 @@@ unsigned long find_iomem(char *driver, 
                        *len_out = region->size;
                        return(region->virt);
                }
 +
 +              region = region->next;
        }
  
        return(0);
diff --combined block/as-iosched.c
@@@ -353,10 -353,9 +353,9 @@@ static struct request *as_find_arq_hash
  /*
   * rb tree support functions
   */
- #define RB_NONE               (2)
  #define RB_EMPTY(root)        ((root)->rb_node == NULL)
- #define ON_RB(node)   ((node)->rb_color != RB_NONE)
- #define RB_CLEAR(node)        ((node)->rb_color = RB_NONE)
+ #define ON_RB(node)   (rb_parent(node) != node)
+ #define RB_CLEAR(node)        (rb_set_parent(node, node))
  #define rb_entry_arq(node)    rb_entry((node), struct as_rq, rb_node)
  #define ARQ_RB_ROOT(ad, arq)  (&(ad)->sort_list[(arq)->is_sync])
  #define rq_rb_key(rq)         (rq)->sector
@@@ -1648,17 -1647,17 +1647,17 @@@ static void as_exit_queue(elevator_t *e
   * initialize elevator private data (as_data), and alloc a arq for
   * each request on the free lists
   */
 -static int as_init_queue(request_queue_t *q, elevator_t *e)
 +static void *as_init_queue(request_queue_t *q, elevator_t *e)
  {
        struct as_data *ad;
        int i;
  
        if (!arq_pool)
 -              return -ENOMEM;
 +              return NULL;
  
        ad = kmalloc_node(sizeof(*ad), GFP_KERNEL, q->node);
        if (!ad)
 -              return -ENOMEM;
 +              return NULL;
        memset(ad, 0, sizeof(*ad));
  
        ad->q = q; /* Identify what queue the data belongs to */
                                GFP_KERNEL, q->node);
        if (!ad->hash) {
                kfree(ad);
 -              return -ENOMEM;
 +              return NULL;
        }
  
        ad->arq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab,
        if (!ad->arq_pool) {
                kfree(ad->hash);
                kfree(ad);
 -              return -ENOMEM;
 +              return NULL;
        }
  
        /* anticipatory scheduling helpers */
        ad->antic_expire = default_antic_expire;
        ad->batch_expire[REQ_SYNC] = default_read_batch_expire;
        ad->batch_expire[REQ_ASYNC] = default_write_batch_expire;
 -      e->elevator_data = ad;
  
        ad->current_batch_expires = jiffies + ad->batch_expire[REQ_SYNC];
        ad->write_batch_count = ad->batch_expire[REQ_ASYNC] / 10;
        if (ad->write_batch_count < 2)
                ad->write_batch_count = 2;
  
 -      return 0;
 +      return ad;
  }
  
  /*
diff --combined block/cfq-iosched.c
@@@ -33,7 -33,7 +33,7 @@@ static int cfq_slice_idle = HZ / 70
  
  #define CFQ_KEY_ASYNC         (0)
  
 -static DEFINE_RWLOCK(cfq_exit_lock);
 +static DEFINE_SPINLOCK(cfq_exit_lock);
  
  /*
   * for the hash of cfqq inside the cfqd
  /*
   * rb-tree defines
   */
- #define RB_NONE                       (2)
  #define RB_EMPTY(node)                ((node)->rb_node == NULL)
- #define RB_CLEAR_COLOR(node)  (node)->rb_color = RB_NONE
  #define RB_CLEAR(node)                do {    \
-       (node)->rb_parent = NULL;       \
-       RB_CLEAR_COLOR((node));         \
-       (node)->rb_right = NULL;        \
-       (node)->rb_left = NULL;         \
+               memset(node, 0, sizeof(*node)); \
  } while (0)
  #define RB_CLEAR_ROOT(root)   ((root)->rb_node = NULL)
  #define rb_entry_crq(node)    rb_entry((node), struct cfq_rq, rb_node)
@@@ -133,7 -128,6 +128,7 @@@ struct cfq_data 
        mempool_t *crq_pool;
  
        int rq_in_driver;
 +      int hw_tag;
  
        /*
         * schedule slice state info
@@@ -501,13 -495,10 +496,13 @@@ static void cfq_resort_rr_list(struct c
  
        /*
         * if queue was preempted, just add to front to be fair. busy_rr
 -       * isn't sorted.
 +       * isn't sorted, but insert at the back for fairness.
         */
        if (preempted || list == &cfqd->busy_rr) {
 -              list_add(&cfqq->cfq_list, list);
 +              if (preempted)
 +                      list = list->prev;
 +
 +              list_add_tail(&cfqq->cfq_list, list);
                return;
        }
  
@@@ -567,7 -558,6 +562,6 @@@ static inline void cfq_del_crq_rb(struc
        cfq_update_next_crq(crq);
  
        rb_erase(&crq->rb_node, &cfqq->sort_list);
-       RB_CLEAR_COLOR(&crq->rb_node);
  
        if (cfq_cfqq_on_rr(cfqq) && RB_EMPTY(&cfqq->sort_list))
                cfq_del_cfqq_rr(cfqd, cfqq);
@@@ -668,15 -658,6 +662,15 @@@ static void cfq_activate_request(reques
        struct cfq_data *cfqd = q->elevator->elevator_data;
  
        cfqd->rq_in_driver++;
 +
 +      /*
 +       * If the depth is larger 1, it really could be queueing. But lets
 +       * make the mark a little higher - idling could still be good for
 +       * low queueing, and a low queueing number could also just indicate
 +       * a SCSI mid layer like behaviour where limit+1 is often seen.
 +       */
 +      if (!cfqd->hw_tag && cfqd->rq_in_driver > 4)
 +              cfqd->hw_tag = 1;
  }
  
  static void cfq_deactivate_request(request_queue_t *q, struct request *rq)
@@@ -892,13 -873,6 +886,13 @@@ static struct cfq_queue *cfq_set_active
                cfqq = list_entry_cfqq(cfqd->cur_rr.next);
  
        /*
 +       * If no new queues are available, check if the busy list has some
 +       * before falling back to idle io.
 +       */
 +      if (!cfqq && !list_empty(&cfqd->busy_rr))
 +              cfqq = list_entry_cfqq(cfqd->busy_rr.next);
 +
 +      /*
         * if we have idle queues and no rt or be queues had pending
         * requests, either allow immediate service if the grace period
         * has passed or arm the idle grace timer
@@@ -1304,7 -1278,7 +1298,7 @@@ static void cfq_exit_io_context(struct 
        /*
         * put the reference this task is holding to the various queues
         */
 -      read_lock_irqsave(&cfq_exit_lock, flags);
 +      spin_lock_irqsave(&cfq_exit_lock, flags);
  
        n = rb_first(&ioc->cic_root);
        while (n != NULL) {
                n = rb_next(n);
        }
  
 -      read_unlock_irqrestore(&cfq_exit_lock, flags);
 +      spin_unlock_irqrestore(&cfq_exit_lock, flags);
  }
  
  static struct cfq_io_context *
@@@ -1323,12 -1297,17 +1317,12 @@@ cfq_alloc_io_context(struct cfq_data *c
        struct cfq_io_context *cic = kmem_cache_alloc(cfq_ioc_pool, gfp_mask);
  
        if (cic) {
 -              RB_CLEAR(&cic->rb_node);
 -              cic->key = NULL;
 -              cic->cfqq[ASYNC] = NULL;
 -              cic->cfqq[SYNC] = NULL;
 +              memset(cic, 0, sizeof(*cic));
 +              RB_CLEAR_COLOR(&cic->rb_node);
                cic->last_end_request = jiffies;
 -              cic->ttime_total = 0;
 -              cic->ttime_samples = 0;
 -              cic->ttime_mean = 0;
 +              INIT_LIST_HEAD(&cic->queue_list);
                cic->dtor = cfq_free_io_context;
                cic->exit = cfq_exit_io_context;
 -              INIT_LIST_HEAD(&cic->queue_list);
                atomic_inc(&ioc_count);
        }
  
@@@ -1415,17 -1394,17 +1409,17 @@@ static int cfq_ioc_set_ioprio(struct io
        struct cfq_io_context *cic;
        struct rb_node *n;
  
 -      write_lock(&cfq_exit_lock);
 +      spin_lock(&cfq_exit_lock);
  
        n = rb_first(&ioc->cic_root);
        while (n != NULL) {
                cic = rb_entry(n, struct cfq_io_context, rb_node);
 - 
 +
                changed_ioprio(cic);
                n = rb_next(n);
        }
  
 -      write_unlock(&cfq_exit_lock);
 +      spin_unlock(&cfq_exit_lock);
  
        return 0;
  }
@@@ -1473,8 -1452,7 +1467,8 @@@ retry
                 * set ->slice_left to allow preemption for a new process
                 */
                cfqq->slice_left = 2 * cfqd->cfq_slice_idle;
 -              cfq_mark_cfqq_idle_window(cfqq);
 +              if (!cfqd->hw_tag)
 +                      cfq_mark_cfqq_idle_window(cfqq);
                cfq_mark_cfqq_prio_changed(cfqq);
                cfq_init_prio_data(cfqq);
        }
  static void
  cfq_drop_dead_cic(struct io_context *ioc, struct cfq_io_context *cic)
  {
 -      read_lock(&cfq_exit_lock);
 +      spin_lock(&cfq_exit_lock);
        rb_erase(&cic->rb_node, &ioc->cic_root);
 -      read_unlock(&cfq_exit_lock);
 +      list_del_init(&cic->queue_list);
 +      spin_unlock(&cfq_exit_lock);
        kmem_cache_free(cfq_ioc_pool, cic);
        atomic_dec(&ioc_count);
  }
@@@ -1562,11 -1539,11 +1556,11 @@@ restart
                        BUG();
        }
  
 -      read_lock(&cfq_exit_lock);
 +      spin_lock(&cfq_exit_lock);
        rb_link_node(&cic->rb_node, parent, p);
        rb_insert_color(&cic->rb_node, &ioc->cic_root);
        list_add(&cic->queue_list, &cfqd->cic_list);
 -      read_unlock(&cfq_exit_lock);
 +      spin_unlock(&cfq_exit_lock);
  }
  
  /*
@@@ -1665,7 -1642,7 +1659,7 @@@ cfq_update_idle_window(struct cfq_data 
  {
        int enable_idle = cfq_cfqq_idle_window(cfqq);
  
 -      if (!cic->ioc->task || !cfqd->cfq_slice_idle)
 +      if (!cic->ioc->task || !cfqd->cfq_slice_idle || cfqd->hw_tag)
                enable_idle = 0;
        else if (sample_valid(cic->ttime_samples)) {
                if (cic->ttime_mean > cfqd->cfq_slice_idle)
@@@ -1756,24 -1733,14 +1750,24 @@@ cfq_crq_enqueued(struct cfq_data *cfqd
  
        cfqq->next_crq = cfq_choose_req(cfqd, cfqq->next_crq, crq);
  
 +      cic = crq->io_context;
 +
        /*
         * we never wait for an async request and we don't allow preemption
         * of an async request. so just return early
         */
 -      if (!cfq_crq_is_sync(crq))
 +      if (!cfq_crq_is_sync(crq)) {
 +              /*
 +               * sync process issued an async request, if it's waiting
 +               * then expire it and kick rq handling.
 +               */
 +              if (cic == cfqd->active_cic &&
 +                  del_timer(&cfqd->idle_slice_timer)) {
 +                      cfq_slice_expired(cfqd, 0);
 +                      cfq_start_queueing(cfqd, cfqq);
 +              }
                return;
 -
 -      cic = crq->io_context;
 +      }
  
        cfq_update_io_thinktime(cfqd, cic);
        cfq_update_io_seektime(cfqd, cic, crq);
@@@ -2191,9 -2158,10 +2185,9 @@@ static void cfq_idle_class_timer(unsign
         * race with a non-idle queue, reset timer
         */
        end = cfqd->last_end_request + CFQ_IDLE_GRACE;
 -      if (!time_after_eq(jiffies, end)) {
 -              cfqd->idle_class_timer.expires = end;
 -              add_timer(&cfqd->idle_class_timer);
 -      } else
 +      if (!time_after_eq(jiffies, end))
 +              mod_timer(&cfqd->idle_class_timer, end);
 +      else
                cfq_schedule_dispatch(cfqd);
  
        spin_unlock_irqrestore(cfqd->queue->queue_lock, flags);
@@@ -2213,7 -2181,7 +2207,7 @@@ static void cfq_exit_queue(elevator_t *
  
        cfq_shutdown_timer_wq(cfqd);
  
 -      write_lock(&cfq_exit_lock);
 +      spin_lock(&cfq_exit_lock);
        spin_lock_irq(q->queue_lock);
  
        if (cfqd->active_queue)
        }
  
        spin_unlock_irq(q->queue_lock);
 -      write_unlock(&cfq_exit_lock);
 +      spin_unlock(&cfq_exit_lock);
  
        cfq_shutdown_timer_wq(cfqd);
  
        kfree(cfqd);
  }
  
 -static int cfq_init_queue(request_queue_t *q, elevator_t *e)
 +static void *cfq_init_queue(request_queue_t *q, elevator_t *e)
  {
        struct cfq_data *cfqd;
        int i;
  
        cfqd = kmalloc(sizeof(*cfqd), GFP_KERNEL);
        if (!cfqd)
 -              return -ENOMEM;
 +              return NULL;
  
        memset(cfqd, 0, sizeof(*cfqd));
  
        for (i = 0; i < CFQ_QHASH_ENTRIES; i++)
                INIT_HLIST_HEAD(&cfqd->cfq_hash[i]);
  
 -      e->elevator_data = cfqd;
 -
        cfqd->queue = q;
  
        cfqd->max_queued = q->nr_requests / 4;
        cfqd->cfq_slice_async_rq = cfq_slice_async_rq;
        cfqd->cfq_slice_idle = cfq_slice_idle;
  
 -      return 0;
 +      return cfqd;
  out_crqpool:
        kfree(cfqd->cfq_hash);
  out_cfqhash:
        kfree(cfqd->crq_hash);
  out_crqhash:
        kfree(cfqd);
 -      return -ENOMEM;
 +      return NULL;
  }
  
  static void cfq_slab_kill(void)
diff --combined block/deadline-iosched.c
@@@ -165,10 -165,9 +165,9 @@@ deadline_find_drq_hash(struct deadline_
  /*
   * rb tree support functions
   */
- #define RB_NONE               (2)
  #define RB_EMPTY(root)        ((root)->rb_node == NULL)
- #define ON_RB(node)   ((node)->rb_color != RB_NONE)
- #define RB_CLEAR(node)        ((node)->rb_color = RB_NONE)
+ #define ON_RB(node)   (rb_parent(node) != node)
+ #define RB_CLEAR(node)        (rb_set_parent(node, node))
  #define rb_entry_drq(node)    rb_entry((node), struct deadline_rq, rb_node)
  #define DRQ_RB_ROOT(dd, drq)  (&(dd)->sort_list[rq_data_dir((drq)->request)])
  #define rq_rb_key(rq)         (rq)->sector
@@@ -613,24 -612,24 +612,24 @@@ static void deadline_exit_queue(elevato
   * initialize elevator private data (deadline_data), and alloc a drq for
   * each request on the free lists
   */
 -static int deadline_init_queue(request_queue_t *q, elevator_t *e)
 +static void *deadline_init_queue(request_queue_t *q, elevator_t *e)
  {
        struct deadline_data *dd;
        int i;
  
        if (!drq_pool)
 -              return -ENOMEM;
 +              return NULL;
  
        dd = kmalloc_node(sizeof(*dd), GFP_KERNEL, q->node);
        if (!dd)
 -              return -ENOMEM;
 +              return NULL;
        memset(dd, 0, sizeof(*dd));
  
        dd->hash = kmalloc_node(sizeof(struct list_head)*DL_HASH_ENTRIES,
                                GFP_KERNEL, q->node);
        if (!dd->hash) {
                kfree(dd);
 -              return -ENOMEM;
 +              return NULL;
        }
  
        dd->drq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab,
        if (!dd->drq_pool) {
                kfree(dd->hash);
                kfree(dd);
 -              return -ENOMEM;
 +              return NULL;
        }
  
        for (i = 0; i < DL_HASH_ENTRIES; i++)
        dd->writes_starved = writes_starved;
        dd->front_merges = 1;
        dd->fifo_batch = fifo_batch;
 -      e->elevator_data = dd;
 -      return 0;
 +      return dd;
  }
  
  static void deadline_put_request(request_queue_t *q, struct request *rq)
diff --combined fs/jffs2/nodelist.h
  #include <linux/fs.h>
  #include <linux/types.h>
  #include <linux/jffs2.h>
 -#include <linux/jffs2_fs_sb.h>
 -#include <linux/jffs2_fs_i.h>
 +#include "jffs2_fs_sb.h"
 +#include "jffs2_fs_i.h"
 +#include "xattr.h"
 +#include "acl.h"
  #include "summary.h"
  
  #ifdef __ECOS
  struct jffs2_raw_node_ref
  {
        struct jffs2_raw_node_ref *next_in_ino; /* Points to the next raw_node_ref
 -              for this inode. If this is the last, it points to the inode_cache
 -              for this inode instead. The inode_cache will have NULL in the first
 -              word so you know when you've got there :) */
 -      struct jffs2_raw_node_ref *next_phys;
 +              for this object. If this _is_ the last, it points to the inode_cache,
 +              xattr_ref or xattr_datum instead. The common part of those structures
 +              has NULL in the first word. See jffs2_raw_ref_to_ic() below */
        uint32_t flash_offset;
 +#define TEST_TOTLEN
 +#ifdef TEST_TOTLEN
        uint32_t __totlen; /* This may die; use ref_totlen(c, jeb, ) below */
 +#endif
  };
  
 +#define REF_LINK_NODE ((int32_t)-1)
 +#define REF_EMPTY_NODE ((int32_t)-2)
 +
 +/* Use blocks of about 256 bytes */
 +#define REFS_PER_BLOCK ((255/sizeof(struct jffs2_raw_node_ref))-1)
 +
 +static inline struct jffs2_raw_node_ref *ref_next(struct jffs2_raw_node_ref *ref)
 +{
 +      ref++;
 +
 +      /* Link to another block of refs */
 +      if (ref->flash_offset == REF_LINK_NODE) {
 +              ref = ref->next_in_ino;
 +              if (!ref)
 +                      return ref;
 +      }
 +
 +      /* End of chain */
 +      if (ref->flash_offset == REF_EMPTY_NODE)
 +              return NULL;
 +
 +      return ref;
 +}
 +
 +static inline struct jffs2_inode_cache *jffs2_raw_ref_to_ic(struct jffs2_raw_node_ref *raw)
 +{
 +      while(raw->next_in_ino)
 +              raw = raw->next_in_ino;
 +
 +      /* NB. This can be a jffs2_xattr_datum or jffs2_xattr_ref and
 +         not actually a jffs2_inode_cache. Check ->class */
 +      return ((struct jffs2_inode_cache *)raw);
 +}
 +
          /* flash_offset & 3 always has to be zero, because nodes are
           always aligned at 4 bytes. So we have a couple of extra bits
           to play with, which indicate the node's status; see below: */
  #define ref_obsolete(ref)     (((ref)->flash_offset & 3) == REF_OBSOLETE)
  #define mark_ref_normal(ref)    do { (ref)->flash_offset = ref_offset(ref) | REF_NORMAL; } while(0)
  
 +/* NB: REF_PRISTINE for an inode-less node (ref->next_in_ino == NULL) indicates
 +   it is an unknown node of type JFFS2_NODETYPE_RWCOMPAT_COPY, so it'll get
 +   copied. If you need to do anything different to GC inode-less nodes, then
 +   you need to modify gc.c accordingly. */
 +
  /* For each inode in the filesystem, we need to keep a record of
     nlink, because it would be a PITA to scan the whole directory tree
     at read_inode() time to calculate it, and to keep sufficient information
     a pointer to the first physical node which is part of this inode, too.
  */
  struct jffs2_inode_cache {
 +      /* First part of structure is shared with other objects which
 +         can terminate the raw node refs' next_in_ino list -- which
 +         currently struct jffs2_xattr_datum and struct jffs2_xattr_ref. */
 +
        struct jffs2_full_dirent *scan_dents; /* Used during scan to hold
                temporary lists of dirents, and later must be set to
                NULL to mark the end of the raw_node_ref->next_in_ino
                chain. */
 -      struct jffs2_inode_cache *next;
        struct jffs2_raw_node_ref *nodes;
 +      uint8_t class;  /* It's used for identification */
 +
 +      /* end of shared structure */
 +
 +      uint8_t flags;
 +      uint16_t state;
        uint32_t ino;
 +      struct jffs2_inode_cache *next;
 +#ifdef CONFIG_JFFS2_FS_XATTR
 +      struct jffs2_xattr_ref *xref;
 +#endif
        int nlink;
 -      int state;
  };
  
  /* Inode states for 'state' above. We need the 'GC' state to prevent
  #define INO_STATE_READING     5       /* In read_inode() */
  #define INO_STATE_CLEARING    6       /* In clear_inode() */
  
 +#define INO_FLAGS_XATTR_CHECKED       0x01    /* has no duplicate xattr_ref */
 +
 +#define RAWNODE_CLASS_INODE_CACHE     0
 +#define RAWNODE_CLASS_XATTR_DATUM     1
 +#define RAWNODE_CLASS_XATTR_REF               2
 +
  #define INOCACHE_HASHSIZE 128
  
 +#define write_ofs(c) ((c)->nextblock->offset + (c)->sector_size - (c)->nextblock->free_size)
 +
  /*
    Larger representation of a raw node, kept in-core only when the
    struct inode for this particular ino is instantiated.
@@@ -255,7 -192,6 +255,7 @@@ struct jffs2_erasebloc
        uint32_t wasted_size;
        uint32_t free_size;     /* Note that sector_size - free_size
                                   is the address of the first free space */
 +      uint32_t allocated_refs;
        struct jffs2_raw_node_ref *first_node;
        struct jffs2_raw_node_ref *last_node;
  
@@@ -267,7 -203,57 +267,7 @@@ static inline int jffs2_blocks_use_vmal
        return ((c->flash_size / c->sector_size) * sizeof (struct jffs2_eraseblock)) > (128 * 1024);
  }
  
 -/* Calculate totlen from surrounding nodes or eraseblock */
 -static inline uint32_t __ref_totlen(struct jffs2_sb_info *c,
 -                                  struct jffs2_eraseblock *jeb,
 -                                  struct jffs2_raw_node_ref *ref)
 -{
 -      uint32_t ref_end;
 -
 -      if (ref->next_phys)
 -              ref_end = ref_offset(ref->next_phys);
 -      else {
 -              if (!jeb)
 -                      jeb = &c->blocks[ref->flash_offset / c->sector_size];
 -
 -              /* Last node in block. Use free_space */
 -              BUG_ON(ref != jeb->last_node);
 -              ref_end = jeb->offset + c->sector_size - jeb->free_size;
 -      }
 -      return ref_end - ref_offset(ref);
 -}
 -
 -static inline uint32_t ref_totlen(struct jffs2_sb_info *c,
 -                                struct jffs2_eraseblock *jeb,
 -                                struct jffs2_raw_node_ref *ref)
 -{
 -      uint32_t ret;
 -
 -#if CONFIG_JFFS2_FS_DEBUG > 0
 -      if (jeb && jeb != &c->blocks[ref->flash_offset / c->sector_size]) {
 -              printk(KERN_CRIT "ref_totlen called with wrong block -- at 0x%08x instead of 0x%08x; ref 0x%08x\n",
 -                     jeb->offset, c->blocks[ref->flash_offset / c->sector_size].offset, ref_offset(ref));
 -              BUG();
 -      }
 -#endif
 -
 -#if 1
 -      ret = ref->__totlen;
 -#else
 -      /* This doesn't actually work yet */
 -      ret = __ref_totlen(c, jeb, ref);
 -      if (ret != ref->__totlen) {
 -              printk(KERN_CRIT "Totlen for ref at %p (0x%08x-0x%08x) miscalculated as 0x%x instead of %x\n",
 -                     ref, ref_offset(ref), ref_offset(ref)+ref->__totlen,
 -                     ret, ref->__totlen);
 -              if (!jeb)
 -                      jeb = &c->blocks[ref->flash_offset / c->sector_size];
 -              jffs2_dbg_dump_node_refs_nolock(c, jeb);
 -              BUG();
 -      }
 -#endif
 -      return ret;
 -}
 +#define ref_totlen(a, b, c) __jffs2_ref_totlen((a), (b), (c))
  
  #define ALLOC_NORMAL  0       /* Normal allocation */
  #define ALLOC_DELETION        1       /* Deletion node. Best to allow it */
  
  #define PAD(x) (((x)+3)&~3)
  
 -static inline struct jffs2_inode_cache *jffs2_raw_ref_to_ic(struct jffs2_raw_node_ref *raw)
 +static inline int jffs2_encode_dev(union jffs2_device_node *jdev, dev_t rdev)
  {
 -      while(raw->next_in_ino) {
 -              raw = raw->next_in_ino;
 +      if (old_valid_dev(rdev)) {
 +              jdev->old = cpu_to_je16(old_encode_dev(rdev));
 +              return sizeof(jdev->old);
 +      } else {
 +              jdev->new = cpu_to_je32(new_encode_dev(rdev));
 +              return sizeof(jdev->new);
        }
 -
 -      return ((struct jffs2_inode_cache *)raw);
  }
  
  static inline struct jffs2_node_frag *frag_first(struct rb_root *root)
@@@ -315,7 -299,6 +315,6 @@@ static inline struct jffs2_node_frag *f
        return rb_entry(node, struct jffs2_node_frag, rb);
  }
  
- #define rb_parent(rb) ((rb)->rb_parent)
  #define frag_next(frag) rb_entry(rb_next(&(frag)->rb), struct jffs2_node_frag, rb)
  #define frag_prev(frag) rb_entry(rb_prev(&(frag)->rb), struct jffs2_node_frag, rb)
  #define frag_parent(frag) rb_entry(rb_parent(&(frag)->rb), struct jffs2_node_frag, rb)
@@@ -340,44 -323,28 +339,44 @@@ void jffs2_obsolete_node_frag(struct jf
  int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn);
  void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size);
  int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn);
 +struct jffs2_raw_node_ref *jffs2_link_node_ref(struct jffs2_sb_info *c,
 +                                             struct jffs2_eraseblock *jeb,
 +                                             uint32_t ofs, uint32_t len,
 +                                             struct jffs2_inode_cache *ic);
 +extern uint32_t __jffs2_ref_totlen(struct jffs2_sb_info *c,
 +                                 struct jffs2_eraseblock *jeb,
 +                                 struct jffs2_raw_node_ref *ref);
  
  /* nodemgmt.c */
  int jffs2_thread_should_wake(struct jffs2_sb_info *c);
 -int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs,
 +int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
                        uint32_t *len, int prio, uint32_t sumsize);
 -int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs,
 +int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize,
                        uint32_t *len, uint32_t sumsize);
 -int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new);
 +struct jffs2_raw_node_ref *jffs2_add_physical_node_ref(struct jffs2_sb_info *c, 
 +                                                     uint32_t ofs, uint32_t len,
 +                                                     struct jffs2_inode_cache *ic);
  void jffs2_complete_reservation(struct jffs2_sb_info *c);
  void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *raw);
  
  /* write.c */
  int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t mode, struct jffs2_raw_inode *ri);
  
 -struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const unsigned char *data, uint32_t datalen, uint32_t flash_ofs, int alloc_mode);
 -struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_dirent *rd, const unsigned char *name, uint32_t namelen, uint32_t flash_ofs, int alloc_mode);
 +struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
 +                                         struct jffs2_raw_inode *ri, const unsigned char *data,
 +                                         uint32_t datalen, int alloc_mode);
 +struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
 +                                           struct jffs2_raw_dirent *rd, const unsigned char *name,
 +                                           uint32_t namelen, int alloc_mode);
  int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
                            struct jffs2_raw_inode *ri, unsigned char *buf,
                            uint32_t offset, uint32_t writelen, uint32_t *retlen);
 -int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const char *name, int namelen);
 -int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, const char *name, int namelen, struct jffs2_inode_info *dead_f, uint32_t time);
 -int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino, uint8_t type, const char *name, int namelen, uint32_t time);
 +int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, struct jffs2_inode_info *f,
 +                  struct jffs2_raw_inode *ri, const char *name, int namelen);
 +int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, const char *name,
 +                  int namelen, struct jffs2_inode_info *dead_f, uint32_t time);
 +int jffs2_do_link(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino,
 +                 uint8_t type, const char *name, int namelen, uint32_t time);
  
  
  /* readinode.c */
@@@ -400,19 -367,12 +399,19 @@@ struct jffs2_raw_inode *jffs2_alloc_raw
  void jffs2_free_raw_inode(struct jffs2_raw_inode *);
  struct jffs2_tmp_dnode_info *jffs2_alloc_tmp_dnode_info(void);
  void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *);
 -struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void);
 -void jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *);
 +int jffs2_prealloc_raw_node_refs(struct jffs2_sb_info *c,
 +                               struct jffs2_eraseblock *jeb, int nr);
 +void jffs2_free_refblock(struct jffs2_raw_node_ref *);
  struct jffs2_node_frag *jffs2_alloc_node_frag(void);
  void jffs2_free_node_frag(struct jffs2_node_frag *);
  struct jffs2_inode_cache *jffs2_alloc_inode_cache(void);
  void jffs2_free_inode_cache(struct jffs2_inode_cache *);
 +#ifdef CONFIG_JFFS2_FS_XATTR
 +struct jffs2_xattr_datum *jffs2_alloc_xattr_datum(void);
 +void jffs2_free_xattr_datum(struct jffs2_xattr_datum *);
 +struct jffs2_xattr_ref *jffs2_alloc_xattr_ref(void);
 +void jffs2_free_xattr_ref(struct jffs2_xattr_ref *);
 +#endif
  
  /* gc.c */
  int jffs2_garbage_collect_pass(struct jffs2_sb_info *c);
@@@ -432,14 -392,12 +431,14 @@@ int jffs2_fill_scan_buf(struct jffs2_sb
                                uint32_t ofs, uint32_t len);
  struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uint32_t ino);
  int jffs2_scan_classify_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
 +int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t size);
  
  /* build.c */
  int jffs2_do_mount_fs(struct jffs2_sb_info *c);
  
  /* erase.c */
  void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count);
 +void jffs2_free_jeb_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
  
  #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
  /* wbuf.c */
diff --combined fs/jffs2/readinode.c
@@@ -66,7 -66,7 +66,7 @@@ static void jffs2_free_tmp_dnode_info_l
                        jffs2_free_full_dnode(tn->fn);
                        jffs2_free_tmp_dnode_info(tn);
  
-                       this = this->rb_parent;
+                       this = rb_parent(this);
                        if (!this)
                                break;
  
@@@ -116,42 -116,19 +116,42 @@@ static inline int read_direntry(struct 
                                uint32_t *latest_mctime, uint32_t *mctime_ver)
  {
        struct jffs2_full_dirent *fd;
 +      uint32_t crc;
  
        /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */
        BUG_ON(ref_obsolete(ref));
  
 -      /* Sanity check */
 -      if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) {
 -              JFFS2_ERROR("illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n",
 -                     ref_offset(ref), rd->nsize, je32_to_cpu(rd->totlen));
 +      crc = crc32(0, rd, sizeof(*rd) - 8);
 +      if (unlikely(crc != je32_to_cpu(rd->node_crc))) {
 +              JFFS2_NOTICE("header CRC failed on dirent node at %#08x: read %#08x, calculated %#08x\n",
 +                           ref_offset(ref), je32_to_cpu(rd->node_crc), crc);
                return 1;
        }
  
 +      /* If we've never checked the CRCs on this node, check them now */
 +      if (ref_flags(ref) == REF_UNCHECKED) {
 +              struct jffs2_eraseblock *jeb;
 +              int len;
 +
 +              /* Sanity check */
 +              if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) {
 +                      JFFS2_ERROR("illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n",
 +                                  ref_offset(ref), rd->nsize, je32_to_cpu(rd->totlen));
 +                      return 1;
 +              }
 +
 +              jeb = &c->blocks[ref->flash_offset / c->sector_size];
 +              len = ref_totlen(c, jeb, ref);
 +
 +              spin_lock(&c->erase_completion_lock);
 +              jeb->used_size += len;
 +              jeb->unchecked_size -= len;
 +              c->used_size += len;
 +              c->unchecked_size -= len;
 +              ref->flash_offset = ref_offset(ref) | REF_PRISTINE;
 +              spin_unlock(&c->erase_completion_lock);
 +      }
 +
        fd = jffs2_alloc_full_dirent(rd->nsize + 1);
        if (unlikely(!fd))
                return -ENOMEM;
@@@ -221,21 -198,13 +221,21 @@@ static inline int read_dnode(struct jff
        struct jffs2_tmp_dnode_info *tn;
        uint32_t len, csize;
        int ret = 1;
 +      uint32_t crc;
  
        /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */
        BUG_ON(ref_obsolete(ref));
  
 +      crc = crc32(0, rd, sizeof(*rd) - 8);
 +      if (unlikely(crc != je32_to_cpu(rd->node_crc))) {
 +              JFFS2_NOTICE("node CRC failed on dnode at %#08x: read %#08x, calculated %#08x\n",
 +                           ref_offset(ref), je32_to_cpu(rd->node_crc), crc);
 +              return 1;
 +      }
 +
        tn = jffs2_alloc_tmp_dnode_info();
        if (!tn) {
 -              JFFS2_ERROR("failed to allocate tn (%d bytes).\n", sizeof(*tn));
 +              JFFS2_ERROR("failed to allocate tn (%zu bytes).\n", sizeof(*tn));
                return -ENOMEM;
        }
  
  
        /* If we've never checked the CRCs on this node, check them now */
        if (ref_flags(ref) == REF_UNCHECKED) {
 -              uint32_t crc;
 -
 -              crc = crc32(0, rd, sizeof(*rd) - 8);
 -              if (unlikely(crc != je32_to_cpu(rd->node_crc))) {
 -                      JFFS2_NOTICE("header CRC failed on node at %#08x: read %#08x, calculated %#08x\n",
 -                                      ref_offset(ref), je32_to_cpu(rd->node_crc), crc);
 -                      goto free_out;
 -              }
  
                /* Sanity checks */
                if (unlikely(je32_to_cpu(rd->offset) > je32_to_cpu(rd->isize)) ||
@@@ -366,7 -343,7 +366,7 @@@ free_out
   * Helper function for jffs2_get_inode_nodes().
   * It is called every time an unknown node is found.
   *
 - * Returns: 0 on succes;
 + * Returns: 0 on success;
   *        1 if the node should be marked obsolete;
   *        negative error code on failure.
   */
@@@ -377,30 -354,37 +377,30 @@@ static inline int read_unknown(struct j
  
        un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype));
  
 -      if (crc32(0, un, sizeof(struct jffs2_unknown_node) - 4) != je32_to_cpu(un->hdr_crc)) {
 -              /* Hmmm. This should have been caught at scan time. */
 -              JFFS2_NOTICE("node header CRC failed at %#08x. But it must have been OK earlier.\n", ref_offset(ref));
 -              jffs2_dbg_dump_node(c, ref_offset(ref));
 +      switch(je16_to_cpu(un->nodetype) & JFFS2_COMPAT_MASK) {
 +
 +      case JFFS2_FEATURE_INCOMPAT:
 +              JFFS2_ERROR("unknown INCOMPAT nodetype %#04X at %#08x\n",
 +                          je16_to_cpu(un->nodetype), ref_offset(ref));
 +              /* EEP */
 +              BUG();
 +              break;
 +
 +      case JFFS2_FEATURE_ROCOMPAT:
 +              JFFS2_ERROR("unknown ROCOMPAT nodetype %#04X at %#08x\n",
 +                          je16_to_cpu(un->nodetype), ref_offset(ref));
 +              BUG_ON(!(c->flags & JFFS2_SB_FLAG_RO));
 +              break;
 +
 +      case JFFS2_FEATURE_RWCOMPAT_COPY:
 +              JFFS2_NOTICE("unknown RWCOMPAT_COPY nodetype %#04X at %#08x\n",
 +                           je16_to_cpu(un->nodetype), ref_offset(ref));
 +              break;
 +
 +      case JFFS2_FEATURE_RWCOMPAT_DELETE:
 +              JFFS2_NOTICE("unknown RWCOMPAT_DELETE nodetype %#04X at %#08x\n",
 +                           je16_to_cpu(un->nodetype), ref_offset(ref));
                return 1;
 -      } else {
 -              switch(je16_to_cpu(un->nodetype) & JFFS2_COMPAT_MASK) {
 -
 -              case JFFS2_FEATURE_INCOMPAT:
 -                      JFFS2_ERROR("unknown INCOMPAT nodetype %#04X at %#08x\n",
 -                              je16_to_cpu(un->nodetype), ref_offset(ref));
 -                      /* EEP */
 -                      BUG();
 -                      break;
 -
 -              case JFFS2_FEATURE_ROCOMPAT:
 -                      JFFS2_ERROR("unknown ROCOMPAT nodetype %#04X at %#08x\n",
 -                                      je16_to_cpu(un->nodetype), ref_offset(ref));
 -                      BUG_ON(!(c->flags & JFFS2_SB_FLAG_RO));
 -                      break;
 -
 -              case JFFS2_FEATURE_RWCOMPAT_COPY:
 -                      JFFS2_NOTICE("unknown RWCOMPAT_COPY nodetype %#04X at %#08x\n",
 -                                      je16_to_cpu(un->nodetype), ref_offset(ref));
 -                      break;
 -
 -              case JFFS2_FEATURE_RWCOMPAT_DELETE:
 -                      JFFS2_NOTICE("unknown RWCOMPAT_DELETE nodetype %#04X at %#08x\n",
 -                                      je16_to_cpu(un->nodetype), ref_offset(ref));
 -                      return 1;
 -              }
        }
  
        return 0;
@@@ -450,7 -434,7 +450,7 @@@ static int read_more(struct jffs2_sb_in
        }
  
        if (retlen < len) {
 -              JFFS2_ERROR("short read at %#08x: %d instead of %d.\n",
 +              JFFS2_ERROR("short read at %#08x: %zu instead of %d.\n",
                                offs, retlen, len);
                return -EIO;
        }
@@@ -558,25 -542,13 +558,25 @@@ static int jffs2_get_inode_nodes(struc
                }
  
                if (retlen < len) {
 -                      JFFS2_ERROR("short read at %#08x: %d instead of %d.\n", ref_offset(ref), retlen, len);
 +                      JFFS2_ERROR("short read at %#08x: %zu instead of %d.\n", ref_offset(ref), retlen, len);
                        err = -EIO;
                        goto free_out;
                }
  
                node = (union jffs2_node_union *)bufstart;
  
 +              /* No need to mask in the valid bit; it shouldn't be invalid */
 +              if (je32_to_cpu(node->u.hdr_crc) != crc32(0, node, sizeof(node->u)-4)) {
 +                      JFFS2_NOTICE("Node header CRC failed at %#08x. {%04x,%04x,%08x,%08x}\n",
 +                                   ref_offset(ref), je16_to_cpu(node->u.magic),
 +                                   je16_to_cpu(node->u.nodetype),
 +                                   je32_to_cpu(node->u.totlen),
 +                                   je32_to_cpu(node->u.hdr_crc));
 +                      jffs2_dbg_dump_node(c, ref_offset(ref));
 +                      jffs2_mark_node_obsolete(c, ref);
 +                      goto cont;
 +              }
 +
                switch (je16_to_cpu(node->u.nodetype)) {
  
                case JFFS2_NODETYPE_DIRENT:
                                goto free_out;
  
                }
 +      cont:
                spin_lock(&c->erase_completion_lock);
        }
  
@@@ -708,12 -679,12 +708,12 @@@ static int jffs2_do_read_inode_internal
                        jffs2_mark_node_obsolete(c, fn->raw);
  
                BUG_ON(rb->rb_left);
-               if (rb->rb_parent && rb->rb_parent->rb_left == rb) {
+               if (rb_parent(rb) && rb_parent(rb)->rb_left == rb) {
                        /* We were then left-hand child of our parent. We need
                         * to move our own right-hand child into our place. */
                        repl_rb = rb->rb_right;
                        if (repl_rb)
-                               repl_rb->rb_parent = rb->rb_parent;
+                               rb_set_parent(repl_rb, rb_parent(rb));
                } else
                        repl_rb = NULL;
  
  
                /* Remove the spent tn from the tree; don't bother rebalancing
                 * but put our right-hand child in our own place. */
-               if (tn->rb.rb_parent) {
-                       if (tn->rb.rb_parent->rb_left == &tn->rb)
-                               tn->rb.rb_parent->rb_left = repl_rb;
-                       else if (tn->rb.rb_parent->rb_right == &tn->rb)
-                               tn->rb.rb_parent->rb_right = repl_rb;
+               if (rb_parent(&tn->rb)) {
+                       if (rb_parent(&tn->rb)->rb_left == &tn->rb)
+                               rb_parent(&tn->rb)->rb_left = repl_rb;
+                       else if (rb_parent(&tn->rb)->rb_right == &tn->rb)
+                               rb_parent(&tn->rb)->rb_right = repl_rb;
                        else BUG();
                } else if (tn->rb.rb_right)
-                       tn->rb.rb_right->rb_parent = NULL;
+                       rb_set_parent(tn->rb.rb_right, NULL);
  
                jffs2_free_tmp_dnode_info(tn);
                if (ret) {
diff --combined kernel/hrtimer.c
@@@ -393,7 -393,7 +393,7 @@@ static void __remove_hrtimer(struct hrt
        if (base->first == &timer->node)
                base->first = rb_next(&timer->node);
        rb_erase(&timer->node, &base->active);
-       timer->node.rb_parent = HRTIMER_INACTIVE;
+       rb_set_parent(&timer->node, &timer->node);
  }
  
  /*
@@@ -456,7 -456,6 +456,7 @@@ hrtimer_start(struct hrtimer *timer, kt
  
        return ret;
  }
 +EXPORT_SYMBOL_GPL(hrtimer_start);
  
  /**
   * hrtimer_try_to_cancel - try to deactivate a timer
@@@ -485,7 -484,6 +485,7 @@@ int hrtimer_try_to_cancel(struct hrtime
        return ret;
  
  }
 +EXPORT_SYMBOL_GPL(hrtimer_try_to_cancel);
  
  /**
   * hrtimer_cancel - cancel a timer and wait for the handler to finish.
@@@ -506,7 -504,6 +506,7 @@@ int hrtimer_cancel(struct hrtimer *time
                cpu_relax();
        }
  }
 +EXPORT_SYMBOL_GPL(hrtimer_cancel);
  
  /**
   * hrtimer_get_remaining - get remaining time for the timer
@@@ -525,7 -522,6 +525,7 @@@ ktime_t hrtimer_get_remaining(const str
  
        return rem;
  }
 +EXPORT_SYMBOL_GPL(hrtimer_get_remaining);
  
  #ifdef CONFIG_NO_IDLE_HZ
  /**
@@@ -582,9 -578,8 +582,9 @@@ void hrtimer_init(struct hrtimer *timer
                clock_id = CLOCK_MONOTONIC;
  
        timer->base = &bases[clock_id];
-       timer->node.rb_parent = HRTIMER_INACTIVE;
+       rb_set_parent(&timer->node, &timer->node);
  }
 +EXPORT_SYMBOL_GPL(hrtimer_init);
  
  /**
   * hrtimer_get_res - get the timer resolution for a clock
@@@ -604,7 -599,6 +604,7 @@@ int hrtimer_get_res(const clockid_t whi
  
        return 0;
  }
 +EXPORT_SYMBOL_GPL(hrtimer_get_res);
  
  /*
   * Expire the per base hrtimer-queue:
@@@ -842,7 -836,7 +842,7 @@@ static void migrate_hrtimers(int cpu
  }
  #endif /* CONFIG_HOTPLUG_CPU */
  
 -static int __devinit hrtimer_cpu_notify(struct notifier_block *self,
 +static int hrtimer_cpu_notify(struct notifier_block *self,
                                        unsigned long action, void *hcpu)
  {
        long cpu = (long)hcpu;
        return NOTIFY_OK;
  }
  
 -static struct notifier_block __devinitdata hrtimers_nb = {
 +static struct notifier_block hrtimers_nb = {
        .notifier_call = hrtimer_cpu_notify,
  };