nfsd: track last inode only in use_wgather case
[safe/jmp/linux-2.6] / kernel / futex.c
index e43945e..d546b2d 100644 (file)
@@ -92,11 +92,12 @@ struct futex_pi_state {
  * A futex_q has a woken state, just like tasks have TASK_RUNNING.
  * It is considered woken when plist_node_empty(&q->list) || q->lock_ptr == 0.
  * The order of wakup is always to make the first condition true, then
- * wake up q->waiters, then make the second condition true.
+ * wake up q->waiter, then make the second condition true.
  */
 struct futex_q {
        struct plist_node list;
-       wait_queue_head_t waiters;
+       /* There can only be a single waiter */
+       wait_queue_head_t waiter;
 
        /* Which hash list lock to use: */
        spinlock_t *lock_ptr;
@@ -104,10 +105,6 @@ struct futex_q {
        /* Key which the futex is hashed on: */
        union futex_key key;
 
-       /* For fd, sigio sent using these: */
-       int fd;
-       struct file *filp;
-
        /* Optional priority inheritance state: */
        struct futex_pi_state *pi_state;
        struct task_struct *task;
@@ -117,7 +114,9 @@ struct futex_q {
 };
 
 /*
- * Split the global futex_lock into every hash list lock.
+ * Hash buckets are shared by all the futex_keys that hash to the same
+ * location.  Each key may have multiple futex_q structures, one for each task
+ * waiting on a futex.
  */
 struct futex_hash_bucket {
        spinlock_t lock;
@@ -126,27 +125,6 @@ struct futex_hash_bucket {
 
 static struct futex_hash_bucket futex_queues[1<<FUTEX_HASHBITS];
 
-/* Futex-fs vfsmount entry: */
-static struct vfsmount *futex_mnt;
-
-/*
- * Take mm->mmap_sem, when futex is shared
- */
-static inline void futex_lock_mm(struct rw_semaphore *fshared)
-{
-       if (fshared)
-               down_read(fshared);
-}
-
-/*
- * Release mm->mmap_sem, when the futex is shared
- */
-static inline void futex_unlock_mm(struct rw_semaphore *fshared)
-{
-       if (fshared)
-               up_read(fshared);
-}
-
 /*
  * We hash on the keys returned from get_futex_key (see below).
  */
@@ -168,12 +146,54 @@ static inline int match_futex(union futex_key *key1, union futex_key *key2)
                && key1->both.offset == key2->both.offset);
 }
 
+/*
+ * Take a reference to the resource addressed by a key.
+ * Can be called while holding spinlocks.
+ *
+ */
+static void get_futex_key_refs(union futex_key *key)
+{
+       if (!key->both.ptr)
+               return;
+
+       switch (key->both.offset & (FUT_OFF_INODE|FUT_OFF_MMSHARED)) {
+       case FUT_OFF_INODE:
+               atomic_inc(&key->shared.inode->i_count);
+               break;
+       case FUT_OFF_MMSHARED:
+               atomic_inc(&key->private.mm->mm_count);
+               break;
+       }
+}
+
+/*
+ * Drop a reference to the resource addressed by a key.
+ * The hash bucket spinlock must not be held.
+ */
+static void drop_futex_key_refs(union futex_key *key)
+{
+       if (!key->both.ptr) {
+               /* If we're here then we tried to put a key we failed to get */
+               WARN_ON_ONCE(1);
+               return;
+       }
+
+       switch (key->both.offset & (FUT_OFF_INODE|FUT_OFF_MMSHARED)) {
+       case FUT_OFF_INODE:
+               iput(key->shared.inode);
+               break;
+       case FUT_OFF_MMSHARED:
+               mmdrop(key->private.mm);
+               break;
+       }
+}
+
 /**
  * get_futex_key - Get parameters which are the keys for a futex.
  * @uaddr: virtual address of the futex
- * @shared: NULL for a PROCESS_PRIVATE futex,
- *     &current->mm->mmap_sem for a PROCESS_SHARED futex
+ * @fshared: 0 for a PROCESS_PRIVATE futex, 1 for PROCESS_SHARED
  * @key: address where result is stored.
+ * @rw: mapping needs to be read/write (values: VERIFY_READ, VERIFY_WRITE)
  *
  * Returns a negative error code or 0
  * The key words are stored in *key on success.
@@ -182,16 +202,13 @@ static inline int match_futex(union futex_key *key1, union futex_key *key2)
  * offset_within_page).  For private mappings, it's (uaddr, current->mm).
  * We can usually work out the index without swapping in the page.
  *
- * fshared is NULL for PROCESS_PRIVATE futexes
- * For other futexes, it points to &current->mm->mmap_sem and
- * caller must have taken the reader lock. but NOT any spinlocks.
+ * lock_page() might sleep, the caller should not hold a spinlock.
  */
-static int get_futex_key(u32 __user *uaddr, struct rw_semaphore *fshared,
-                        union futex_key *key)
+static int
+get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key, int rw)
 {
        unsigned long address = (unsigned long)uaddr;
        struct mm_struct *mm = current->mm;
-       struct vm_area_struct *vma;
        struct page *page;
        int err;
 
@@ -211,104 +228,54 @@ static int get_futex_key(u32 __user *uaddr, struct rw_semaphore *fshared,
         *        but access_ok() should be faster than find_vma()
         */
        if (!fshared) {
-               if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))))
+               if (unlikely(!access_ok(rw, uaddr, sizeof(u32))))
                        return -EFAULT;
                key->private.mm = mm;
                key->private.address = address;
+               get_futex_key_refs(key);
                return 0;
        }
-       /*
-        * The futex is hashed differently depending on whether
-        * it's in a shared or private mapping.  So check vma first.
-        */
-       vma = find_extend_vma(mm, address);
-       if (unlikely(!vma))
-               return -EFAULT;
 
-       /*
-        * Permissions.
-        */
-       if (unlikely((vma->vm_flags & (VM_IO|VM_READ)) != VM_READ))
-               return (vma->vm_flags & VM_IO) ? -EPERM : -EACCES;
+again:
+       err = get_user_pages_fast(address, 1, rw == VERIFY_WRITE, &page);
+       if (err < 0)
+               return err;
+
+       lock_page(page);
+       if (!page->mapping) {
+               unlock_page(page);
+               put_page(page);
+               goto again;
+       }
 
        /*
         * Private mappings are handled in a simple way.
         *
         * NOTE: When userspace waits on a MAP_SHARED mapping, even if
         * it's a read-only handle, it's expected that futexes attach to
-        * the object not the particular process.  Therefore we use
-        * VM_MAYSHARE here, not VM_SHARED which is restricted to shared
-        * mappings of _writable_ handles.
+        * the object not the particular process.
         */
-       if (likely(!(vma->vm_flags & VM_MAYSHARE))) {
-               key->both.offset |= FUT_OFF_MMSHARED; /* reference taken on mm */
+       if (PageAnon(page)) {
+               key->both.offset |= FUT_OFF_MMSHARED; /* ref taken on mm */
                key->private.mm = mm;
                key->private.address = address;
-               return 0;
+       } else {
+               key->both.offset |= FUT_OFF_INODE; /* inode-based key */
+               key->shared.inode = page->mapping->host;
+               key->shared.pgoff = page->index;
        }
 
-       /*
-        * Linear file mappings are also simple.
-        */
-       key->shared.inode = vma->vm_file->f_path.dentry->d_inode;
-       key->both.offset |= FUT_OFF_INODE; /* inode-based key. */
-       if (likely(!(vma->vm_flags & VM_NONLINEAR))) {
-               key->shared.pgoff = (((address - vma->vm_start) >> PAGE_SHIFT)
-                                    + vma->vm_pgoff);
-               return 0;
-       }
+       get_futex_key_refs(key);
 
-       /*
-        * We could walk the page table to read the non-linear
-        * pte, and get the page index without fetching the page
-        * from swap.  But that's a lot of code to duplicate here
-        * for a rare case, so we simply fetch the page.
-        */
-       err = get_user_pages(current, mm, address, 1, 0, 0, &page, NULL);
-       if (err >= 0) {
-               key->shared.pgoff =
-                       page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
-               put_page(page);
-               return 0;
-       }
-       return err;
+       unlock_page(page);
+       put_page(page);
+       return 0;
 }
 
-/*
- * Take a reference to the resource addressed by a key.
- * Can be called while holding spinlocks.
- *
- */
-static void get_futex_key_refs(union futex_key *key)
+static inline
+void put_futex_key(int fshared, union futex_key *key)
 {
-       if (key->both.ptr == NULL)
-               return;
-       switch (key->both.offset & (FUT_OFF_INODE|FUT_OFF_MMSHARED)) {
-               case FUT_OFF_INODE:
-                       atomic_inc(&key->shared.inode->i_count);
-                       break;
-               case FUT_OFF_MMSHARED:
-                       atomic_inc(&key->private.mm->mm_count);
-                       break;
-       }
-}
-
-/*
- * Drop a reference to the resource addressed by a key.
- * The hash bucket spinlock must not be held.
- */
-static void drop_futex_key_refs(union futex_key *key)
-{
-       if (!key->both.ptr)
-               return;
-       switch (key->both.offset & (FUT_OFF_INODE|FUT_OFF_MMSHARED)) {
-               case FUT_OFF_INODE:
-                       iput(key->shared.inode);
-                       break;
-               case FUT_OFF_MMSHARED:
-                       mmdrop(key->private.mm);
-                       break;
-       }
+       drop_futex_key_refs(key);
 }
 
 static u32 cmpxchg_futex_value_locked(u32 __user *uaddr, u32 uval, u32 newval)
@@ -333,45 +300,6 @@ static int get_futex_value_locked(u32 *dest, u32 __user *from)
        return ret ? -EFAULT : 0;
 }
 
-/*
- * Fault handling.
- * if fshared is non NULL, current->mm->mmap_sem is already held
- */
-static int futex_handle_fault(unsigned long address,
-                             struct rw_semaphore *fshared, int attempt)
-{
-       struct vm_area_struct * vma;
-       struct mm_struct *mm = current->mm;
-       int ret = -EFAULT;
-
-       if (attempt > 2)
-               return ret;
-
-       if (!fshared)
-               down_read(&mm->mmap_sem);
-       vma = find_vma(mm, address);
-       if (vma && address >= vma->vm_start &&
-           (vma->vm_flags & VM_WRITE)) {
-               int fault;
-               fault = handle_mm_fault(mm, vma, address, 1);
-               if (unlikely((fault & VM_FAULT_ERROR))) {
-#if 0
-                       /* XXX: let's do this when we verify it is OK */
-                       if (ret & VM_FAULT_OOM)
-                               ret = -ENOMEM;
-#endif
-               } else {
-                       ret = 0;
-                       if (fault & VM_FAULT_MAJOR)
-                               current->maj_flt++;
-                       else
-                               current->min_flt++;
-               }
-       }
-       if (!fshared)
-               up_read(&mm->mmap_sem);
-       return ret;
-}
 
 /*
  * PI code:
@@ -392,6 +320,7 @@ static int refill_pi_state_cache(void)
        /* pi_mutex gets initialized later */
        pi_state->owner = NULL;
        atomic_set(&pi_state->refcount, 1);
+       pi_state->key = FUTEX_KEY_INIT;
 
        current->pi_state_cache = pi_state;
 
@@ -446,13 +375,20 @@ static void free_pi_state(struct futex_pi_state *pi_state)
 static struct task_struct * futex_find_get_task(pid_t pid)
 {
        struct task_struct *p;
+       const struct cred *cred = current_cred(), *pcred;
 
        rcu_read_lock();
        p = find_task_by_vpid(pid);
-       if (!p || ((current->euid != p->euid) && (current->euid != p->uid)))
+       if (!p) {
                p = ERR_PTR(-ESRCH);
-       else
-               get_task_struct(p);
+       } else {
+               pcred = __task_cred(p);
+               if (cred->euid != pcred->euid &&
+                   cred->euid != pcred->uid)
+                       p = ERR_PTR(-ESRCH);
+               else
+                       get_task_struct(p);
+       }
 
        rcu_read_unlock();
 
@@ -469,7 +405,7 @@ void exit_pi_state_list(struct task_struct *curr)
        struct list_head *next, *head = &curr->pi_state_list;
        struct futex_pi_state *pi_state;
        struct futex_hash_bucket *hb;
-       union futex_key key;
+       union futex_key key = FUTEX_KEY_INIT;
 
        if (!futex_cmpxchg_enabled)
                return;
@@ -610,21 +546,18 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
 static void wake_futex(struct futex_q *q)
 {
        plist_del(&q->list, &q->list.plist);
-       if (q->filp)
-               send_sigio(&q->filp->f_owner, q->fd, POLL_IN);
        /*
         * The lock in wake_up_all() is a crucial memory barrier after the
         * plist_del() and also before assigning to q->lock_ptr.
         */
-       wake_up_all(&q->waiters);
+       wake_up(&q->waiter);
        /*
         * The waiting task can free the futex_q as soon as this is written,
         * without taking any locks.  This must come last.
         *
-        * A memory barrier is required here to prevent the following store
-        * to lock_ptr from getting ahead of the wakeup. Clearing the lock
-        * at the end of wake_up_all() does not prevent this store from
-        * moving.
+        * A memory barrier is required here to prevent the following store to
+        * lock_ptr from getting ahead of the wakeup. Clearing the lock at the
+        * end of wake_up() does not prevent this store from moving.
         */
        smp_wmb();
        q->lock_ptr = NULL;
@@ -724,25 +657,29 @@ double_lock_hb(struct futex_hash_bucket *hb1, struct futex_hash_bucket *hb2)
        }
 }
 
+static inline void
+double_unlock_hb(struct futex_hash_bucket *hb1, struct futex_hash_bucket *hb2)
+{
+       spin_unlock(&hb1->lock);
+       if (hb1 != hb2)
+               spin_unlock(&hb2->lock);
+}
+
 /*
- * Wake up all waiters hashed on the physical page that is mapped
- * to this virtual address:
+ * Wake up waiters matching bitset queued on this futex (uaddr).
  */
-static int futex_wake(u32 __user *uaddr, struct rw_semaphore *fshared,
-                     int nr_wake, u32 bitset)
+static int futex_wake(u32 __user *uaddr, int fshared, int nr_wake, u32 bitset)
 {
        struct futex_hash_bucket *hb;
        struct futex_q *this, *next;
        struct plist_head *head;
-       union futex_key key;
+       union futex_key key = FUTEX_KEY_INIT;
        int ret;
 
        if (!bitset)
                return -EINVAL;
 
-       futex_lock_mm(fshared);
-
-       ret = get_futex_key(uaddr, fshared, &key);
+       ret = get_futex_key(uaddr, fshared, &key, VERIFY_READ);
        if (unlikely(ret != 0))
                goto out;
 
@@ -768,8 +705,8 @@ static int futex_wake(u32 __user *uaddr, struct rw_semaphore *fshared,
        }
 
        spin_unlock(&hb->lock);
+       put_futex_key(fshared, &key);
 out:
-       futex_unlock_mm(fshared);
        return ret;
 }
 
@@ -778,39 +715,33 @@ out:
  * to this virtual address:
  */
 static int
-futex_wake_op(u32 __user *uaddr1, struct rw_semaphore *fshared,
-             u32 __user *uaddr2,
+futex_wake_op(u32 __user *uaddr1, int fshared, u32 __user *uaddr2,
              int nr_wake, int nr_wake2, int op)
 {
-       union futex_key key1, key2;
+       union futex_key key1 = FUTEX_KEY_INIT, key2 = FUTEX_KEY_INIT;
        struct futex_hash_bucket *hb1, *hb2;
        struct plist_head *head;
        struct futex_q *this, *next;
-       int ret, op_ret, attempt = 0;
+       int ret, op_ret;
 
-retryfull:
-       futex_lock_mm(fshared);
-
-       ret = get_futex_key(uaddr1, fshared, &key1);
+retry:
+       ret = get_futex_key(uaddr1, fshared, &key1, VERIFY_READ);
        if (unlikely(ret != 0))
                goto out;
-       ret = get_futex_key(uaddr2, fshared, &key2);
+       ret = get_futex_key(uaddr2, fshared, &key2, VERIFY_WRITE);
        if (unlikely(ret != 0))
-               goto out;
+               goto out_put_key1;
 
        hb1 = hash_futex(&key1);
        hb2 = hash_futex(&key2);
 
-retry:
        double_lock_hb(hb1, hb2);
-
+retry_private:
        op_ret = futex_atomic_op_inuser(op, uaddr2);
        if (unlikely(op_ret < 0)) {
                u32 dummy;
 
-               spin_unlock(&hb1->lock);
-               if (hb1 != hb2)
-                       spin_unlock(&hb2->lock);
+               double_unlock_hb(hb1, hb2);
 
 #ifndef CONFIG_MMU
                /*
@@ -818,40 +749,24 @@ retry:
                 * but we might get them from range checking
                 */
                ret = op_ret;
-               goto out;
+               goto out_put_keys;
 #endif
 
                if (unlikely(op_ret != -EFAULT)) {
                        ret = op_ret;
-                       goto out;
-               }
-
-               /*
-                * futex_atomic_op_inuser needs to both read and write
-                * *(int __user *)uaddr2, but we can't modify it
-                * non-atomically.  Therefore, if get_user below is not
-                * enough, we need to handle the fault ourselves, while
-                * still holding the mmap_sem.
-                */
-               if (attempt++) {
-                       ret = futex_handle_fault((unsigned long)uaddr2,
-                                                fshared, attempt);
-                       if (ret)
-                               goto out;
-                       goto retry;
+                       goto out_put_keys;
                }
 
-               /*
-                * If we would have faulted, release mmap_sem,
-                * fault it in and start all over again.
-                */
-               futex_unlock_mm(fshared);
-
                ret = get_user(dummy, uaddr2);
                if (ret)
-                       return ret;
+                       goto out_put_keys;
+
+               if (!fshared)
+                       goto retry_private;
 
-               goto retryfull;
+               put_futex_key(fshared, &key2);
+               put_futex_key(fshared, &key1);
+               goto retry;
        }
 
        head = &hb1->chain;
@@ -878,12 +793,12 @@ retry:
                ret += op_ret;
        }
 
-       spin_unlock(&hb1->lock);
-       if (hb1 != hb2)
-               spin_unlock(&hb2->lock);
+       double_unlock_hb(hb1, hb2);
+out_put_keys:
+       put_futex_key(fshared, &key2);
+out_put_key1:
+       put_futex_key(fshared, &key1);
 out:
-       futex_unlock_mm(fshared);
-
        return ret;
 }
 
@@ -891,29 +806,27 @@ out:
  * Requeue all waiters hashed on one physical page to another
  * physical page.
  */
-static int futex_requeue(u32 __user *uaddr1, struct rw_semaphore *fshared,
-                        u32 __user *uaddr2,
+static int futex_requeue(u32 __user *uaddr1, int fshared, u32 __user *uaddr2,
                         int nr_wake, int nr_requeue, u32 *cmpval)
 {
-       union futex_key key1, key2;
+       union futex_key key1 = FUTEX_KEY_INIT, key2 = FUTEX_KEY_INIT;
        struct futex_hash_bucket *hb1, *hb2;
        struct plist_head *head1;
        struct futex_q *this, *next;
        int ret, drop_count = 0;
 
- retry:
-       futex_lock_mm(fshared);
-
-       ret = get_futex_key(uaddr1, fshared, &key1);
+retry:
+       ret = get_futex_key(uaddr1, fshared, &key1, VERIFY_READ);
        if (unlikely(ret != 0))
                goto out;
-       ret = get_futex_key(uaddr2, fshared, &key2);
+       ret = get_futex_key(uaddr2, fshared, &key2, VERIFY_READ);
        if (unlikely(ret != 0))
-               goto out;
+               goto out_put_key1;
 
        hb1 = hash_futex(&key1);
        hb2 = hash_futex(&key2);
 
+retry_private:
        double_lock_hb(hb1, hb2);
 
        if (likely(cmpval != NULL)) {
@@ -922,22 +835,18 @@ static int futex_requeue(u32 __user *uaddr1, struct rw_semaphore *fshared,
                ret = get_futex_value_locked(&curval, uaddr1);
 
                if (unlikely(ret)) {
-                       spin_unlock(&hb1->lock);
-                       if (hb1 != hb2)
-                               spin_unlock(&hb2->lock);
-
-                       /*
-                        * If we would have faulted, release mmap_sem, fault
-                        * it in and start all over again.
-                        */
-                       futex_unlock_mm(fshared);
+                       double_unlock_hb(hb1, hb2);
 
                        ret = get_user(curval, uaddr1);
+                       if (ret)
+                               goto out_put_keys;
 
-                       if (!ret)
-                               goto retry;
+                       if (!fshared)
+                               goto retry_private;
 
-                       return ret;
+                       put_futex_key(fshared, &key2);
+                       put_futex_key(fshared, &key1);
+                       goto retry;
                }
                if (curval != *cmpval) {
                        ret = -EAGAIN;
@@ -974,29 +883,31 @@ static int futex_requeue(u32 __user *uaddr1, struct rw_semaphore *fshared,
        }
 
 out_unlock:
-       spin_unlock(&hb1->lock);
-       if (hb1 != hb2)
-               spin_unlock(&hb2->lock);
+       double_unlock_hb(hb1, hb2);
 
-       /* drop_futex_key_refs() must be called outside the spinlocks. */
+       /*
+        * drop_futex_key_refs() must be called outside the spinlocks. During
+        * the requeue we moved futex_q's from the hash bucket at key1 to the
+        * one at key2 and updated their key pointer.  We no longer need to
+        * hold the references to key1.
+        */
        while (--drop_count >= 0)
                drop_futex_key_refs(&key1);
 
+out_put_keys:
+       put_futex_key(fshared, &key2);
+out_put_key1:
+       put_futex_key(fshared, &key1);
 out:
-       futex_unlock_mm(fshared);
        return ret;
 }
 
 /* The key must be already stored in q->key. */
-static inline struct futex_hash_bucket *
-queue_lock(struct futex_q *q, int fd, struct file *filp)
+static inline struct futex_hash_bucket *queue_lock(struct futex_q *q)
 {
        struct futex_hash_bucket *hb;
 
-       q->fd = fd;
-       q->filp = filp;
-
-       init_waitqueue_head(&q->waiters);
+       init_waitqueue_head(&q->waiter);
 
        get_futex_key_refs(&q->key);
        hb = hash_futex(&q->key);
@@ -1006,7 +917,7 @@ queue_lock(struct futex_q *q, int fd, struct file *filp)
        return hb;
 }
 
-static inline void __queue_me(struct futex_q *q, struct futex_hash_bucket *hb)
+static inline void queue_me(struct futex_q *q, struct futex_hash_bucket *hb)
 {
        int prio;
 
@@ -1041,15 +952,6 @@ queue_unlock(struct futex_q *q, struct futex_hash_bucket *hb)
  * exactly once.  They are called with the hashed spinlock held.
  */
 
-/* The key must be already stored in q->key. */
-static void queue_me(struct futex_q *q, int fd, struct file *filp)
-{
-       struct futex_hash_bucket *hb;
-
-       hb = queue_lock(q, fd, filp);
-       __queue_me(q, hb);
-}
-
 /* Return 1 if we were still queued (ie. 0 means we were woken) */
 static int unqueue_me(struct futex_q *q)
 {
@@ -1057,7 +959,7 @@ static int unqueue_me(struct futex_q *q)
        int ret = 0;
 
        /* In the common case we don't take the spinlock, which is nice. */
- retry:
+retry:
        lock_ptr = q->lock_ptr;
        barrier();
        if (lock_ptr != NULL) {
@@ -1118,21 +1020,61 @@ static void unqueue_me_pi(struct futex_q *q)
  * private futexes.
  */
 static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q,
-                               struct task_struct *newowner)
+                               struct task_struct *newowner, int fshared)
 {
        u32 newtid = task_pid_vnr(newowner) | FUTEX_WAITERS;
        struct futex_pi_state *pi_state = q->pi_state;
+       struct task_struct *oldowner = pi_state->owner;
        u32 uval, curval, newval;
        int ret;
 
        /* Owner died? */
+       if (!pi_state->owner)
+               newtid |= FUTEX_OWNER_DIED;
+
+       /*
+        * We are here either because we stole the rtmutex from the
+        * pending owner or we are the pending owner which failed to
+        * get the rtmutex. We have to replace the pending owner TID
+        * in the user space variable. This must be atomic as we have
+        * to preserve the owner died bit here.
+        *
+        * Note: We write the user space value _before_ changing the pi_state
+        * because we can fault here. Imagine swapped out pages or a fork
+        * that marked all the anonymous memory readonly for cow.
+        *
+        * Modifying pi_state _before_ the user space value would
+        * leave the pi_state in an inconsistent state when we fault
+        * here, because we need to drop the hash bucket lock to
+        * handle the fault. This might be observed in the PID check
+        * in lookup_pi_state.
+        */
+retry:
+       if (get_futex_value_locked(&uval, uaddr))
+               goto handle_fault;
+
+       while (1) {
+               newval = (uval & FUTEX_OWNER_DIED) | newtid;
+
+               curval = cmpxchg_futex_value_locked(uaddr, uval, newval);
+
+               if (curval == -EFAULT)
+                       goto handle_fault;
+               if (curval == uval)
+                       break;
+               uval = curval;
+       }
+
+       /*
+        * We fixed up user space. Now we need to fix the pi_state
+        * itself.
+        */
        if (pi_state->owner != NULL) {
                spin_lock_irq(&pi_state->owner->pi_lock);
                WARN_ON(list_empty(&pi_state->list));
                list_del_init(&pi_state->list);
                spin_unlock_irq(&pi_state->owner->pi_lock);
-       } else
-               newtid |= FUTEX_OWNER_DIED;
+       }
 
        pi_state->owner = newowner;
 
@@ -1140,40 +1082,51 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q,
        WARN_ON(!list_empty(&pi_state->list));
        list_add(&pi_state->list, &newowner->pi_state_list);
        spin_unlock_irq(&newowner->pi_lock);
+       return 0;
 
        /*
-        * We own it, so we have to replace the pending owner
-        * TID. This must be atomic as we have preserve the
-        * owner died bit here.
+        * To handle the page fault we need to drop the hash bucket
+        * lock here. That gives the other task (either the pending
+        * owner itself or the task which stole the rtmutex) the
+        * chance to try the fixup of the pi_state. So once we are
+        * back from handling the fault we need to check the pi_state
+        * after reacquiring the hash bucket lock and before trying to
+        * do another fixup. When the fixup has been done already we
+        * simply return.
         */
-       ret = get_futex_value_locked(&uval, uaddr);
+handle_fault:
+       spin_unlock(q->lock_ptr);
 
-       while (!ret) {
-               newval = (uval & FUTEX_OWNER_DIED) | newtid;
+       ret = get_user(uval, uaddr);
 
-               curval = cmpxchg_futex_value_locked(uaddr, uval, newval);
+       spin_lock(q->lock_ptr);
 
-               if (curval == -EFAULT)
-                       ret = -EFAULT;
-               if (curval == uval)
-                       break;
-               uval = curval;
-       }
-       return ret;
+       /*
+        * Check if someone else fixed it for us:
+        */
+       if (pi_state->owner != oldowner)
+               return 0;
+
+       if (ret)
+               return ret;
+
+       goto retry;
 }
 
 /*
  * In case we must use restart_block to restart a futex_wait,
  * we encode in the 'flags' shared capability
  */
-#define FLAGS_SHARED  1
+#define FLAGS_SHARED           0x01
+#define FLAGS_CLOCKRT          0x02
 
 static long futex_wait_restart(struct restart_block *restart);
 
-static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared,
-                     u32 val, ktime_t *abs_time, u32 bitset)
+static int futex_wait(u32 __user *uaddr, int fshared,
+                     u32 val, ktime_t *abs_time, u32 bitset, int clockrt)
 {
        struct task_struct *curr = current;
+       struct restart_block *restart;
        DECLARE_WAITQUEUE(wait, curr);
        struct futex_hash_bucket *hb;
        struct futex_q q;
@@ -1187,17 +1140,17 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared,
 
        q.pi_state = NULL;
        q.bitset = bitset;
- retry:
-       futex_lock_mm(fshared);
-
-       ret = get_futex_key(uaddr, fshared, &q.key);
+retry:
+       q.key = FUTEX_KEY_INIT;
+       ret = get_futex_key(uaddr, fshared, &q.key, VERIFY_READ);
        if (unlikely(ret != 0))
-               goto out_release_sem;
+               goto out;
 
-       hb = queue_lock(&q, -1, NULL);
+retry_private:
+       hb = queue_lock(&q);
 
        /*
-        * Access the page AFTER the futex is queued.
+        * Access the page AFTER the hash-bucket is locked.
         * Order is important:
         *
         *   Userspace waiter: val = var; if (cond(val)) futex_wait(&var, val);
@@ -1213,7 +1166,7 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared,
         * a wakeup when *uaddr != val on entry to the syscall.  This is
         * rare, but normal.
         *
-        * for shared futexes, we hold the mmap semaphore, so the mapping
+        * For shared futexes, we hold the mmap semaphore, so the mapping
         * cannot have changed since we looked it up in get_futex_key.
         */
        ret = get_futex_value_locked(&uval, uaddr);
@@ -1221,30 +1174,24 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared,
        if (unlikely(ret)) {
                queue_unlock(&q, hb);
 
-               /*
-                * If we would have faulted, release mmap_sem, fault it in and
-                * start all over again.
-                */
-               futex_unlock_mm(fshared);
-
                ret = get_user(uval, uaddr);
+               if (ret)
+                       goto out_put_key;
 
-               if (!ret)
-                       goto retry;
-               return ret;
+               if (!fshared)
+                       goto retry_private;
+
+               put_futex_key(fshared, &q.key);
+               goto retry;
        }
        ret = -EWOULDBLOCK;
-       if (uval != val)
-               goto out_unlock_release_sem;
+       if (unlikely(uval != val)) {
+               queue_unlock(&q, hb);
+               goto out_put_key;
+       }
 
        /* Only actually queue if *uaddr contained val.  */
-       __queue_me(&q, hb);
-
-       /*
-        * Now the futex is queued and we have checked the data, we
-        * don't want to hold mmap_sem while we sleep.
-        */
-       futex_unlock_mm(fshared);
+       queue_me(&q, hb);
 
        /*
         * There might have been scheduling since the queue_me(), as we
@@ -1257,7 +1204,7 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared,
 
        /* add_wait_queue is the barrier after __set_current_state. */
        __set_current_state(TASK_INTERRUPTIBLE);
-       add_wait_queue(&q.waiters, &wait);
+       add_wait_queue(&q.waiter, &wait);
        /*
         * !plist_node_empty() is safe here without any lock.
         * q.lock_ptr != 0 is not safe, because of ordering against wakeup.
@@ -1266,11 +1213,15 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared,
                if (!abs_time)
                        schedule();
                else {
-                       hrtimer_init(&t.timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+                       hrtimer_init_on_stack(&t.timer,
+                                             clockrt ? CLOCK_REALTIME :
+                                             CLOCK_MONOTONIC,
+                                             HRTIMER_MODE_ABS);
                        hrtimer_init_sleeper(&t, current);
-                       t.timer.expires = *abs_time;
+                       hrtimer_set_expires_range_ns(&t.timer, *abs_time,
+                                                    current->timer_slack_ns);
 
-                       hrtimer_start(&t.timer, t.timer.expires, HRTIMER_MODE_ABS);
+                       hrtimer_start_expires(&t.timer, HRTIMER_MODE_ABS);
                        if (!hrtimer_active(&t.timer))
                                t.task = NULL;
 
@@ -1286,6 +1237,8 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared,
 
                        /* Flag if a timeout occured */
                        rem = (t.task == NULL);
+
+                       destroy_hrtimer_on_stack(&t.timer);
                }
        }
        __set_current_state(TASK_RUNNING);
@@ -1296,37 +1249,39 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared,
         */
 
        /* If we were woken (and unqueued), we succeeded, whatever. */
+       ret = 0;
        if (!unqueue_me(&q))
-               return 0;
+               goto out_put_key;
+       ret = -ETIMEDOUT;
        if (rem)
-               return -ETIMEDOUT;
+               goto out_put_key;
 
        /*
         * We expect signal_pending(current), but another thread may
         * have handled it for us already.
         */
+       ret = -ERESTARTSYS;
        if (!abs_time)
-               return -ERESTARTSYS;
-       else {
-               struct restart_block *restart;
-               restart = &current_thread_info()->restart_block;
-               restart->fn = futex_wait_restart;
-               restart->futex.uaddr = (u32 *)uaddr;
-               restart->futex.val = val;
-               restart->futex.time = abs_time->tv64;
-               restart->futex.bitset = bitset;
-               restart->futex.flags = 0;
-
-               if (fshared)
-                       restart->futex.flags |= FLAGS_SHARED;
-               return -ERESTART_RESTARTBLOCK;
-       }
+               goto out_put_key;
 
- out_unlock_release_sem:
-       queue_unlock(&q, hb);
+       restart = &current_thread_info()->restart_block;
+       restart->fn = futex_wait_restart;
+       restart->futex.uaddr = (u32 *)uaddr;
+       restart->futex.val = val;
+       restart->futex.time = abs_time->tv64;
+       restart->futex.bitset = bitset;
+       restart->futex.flags = 0;
+
+       if (fshared)
+               restart->futex.flags |= FLAGS_SHARED;
+       if (clockrt)
+               restart->futex.flags |= FLAGS_CLOCKRT;
+
+       ret = -ERESTART_RESTARTBLOCK;
 
- out_release_sem:
-       futex_unlock_mm(fshared);
+out_put_key:
+       put_futex_key(fshared, &q.key);
+out:
        return ret;
 }
 
@@ -1334,15 +1289,16 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared,
 static long futex_wait_restart(struct restart_block *restart)
 {
        u32 __user *uaddr = (u32 __user *)restart->futex.uaddr;
-       struct rw_semaphore *fshared = NULL;
+       int fshared = 0;
        ktime_t t;
 
        t.tv64 = restart->futex.time;
        restart->fn = do_no_restart_syscall;
        if (restart->futex.flags & FLAGS_SHARED)
-               fshared = &current->mm->mmap_sem;
+               fshared = 1;
        return (long)futex_wait(uaddr, fshared, restart->futex.val, &t,
-                               restart->futex.bitset);
+                               restart->futex.bitset,
+                               restart->futex.flags & FLAGS_CLOCKRT);
 }
 
 
@@ -1352,7 +1308,7 @@ static long futex_wait_restart(struct restart_block *restart)
  * if there are waiters then it will block, it does PI, etc. (Due to
  * races the kernel might see a 0 value of the futex too.)
  */
-static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
+static int futex_lock_pi(u32 __user *uaddr, int fshared,
                         int detect, ktime_t *time, int trylock)
 {
        struct hrtimer_sleeper timeout, *to = NULL;
@@ -1360,30 +1316,30 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
        struct futex_hash_bucket *hb;
        u32 uval, newval, curval;
        struct futex_q q;
-       int ret, lock_taken, ownerdied = 0, attempt = 0;
+       int ret, lock_taken, ownerdied = 0;
 
        if (refill_pi_state_cache())
                return -ENOMEM;
 
        if (time) {
                to = &timeout;
-               hrtimer_init(&to->timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
+               hrtimer_init_on_stack(&to->timer, CLOCK_REALTIME,
+                                     HRTIMER_MODE_ABS);
                hrtimer_init_sleeper(to, current);
-               to->timer.expires = *time;
+               hrtimer_set_expires(&to->timer, *time);
        }
 
        q.pi_state = NULL;
- retry:
-       futex_lock_mm(fshared);
-
-       ret = get_futex_key(uaddr, fshared, &q.key);
+retry:
+       q.key = FUTEX_KEY_INIT;
+       ret = get_futex_key(uaddr, fshared, &q.key, VERIFY_WRITE);
        if (unlikely(ret != 0))
-               goto out_release_sem;
+               goto out;
 
- retry_unlocked:
-       hb = queue_lock(&q, -1, NULL);
+retry_private:
+       hb = queue_lock(&q);
 
- retry_locked:
+retry_locked:
        ret = lock_taken = 0;
 
        /*
@@ -1404,14 +1360,14 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
         */
        if (unlikely((curval & FUTEX_TID_MASK) == task_pid_vnr(current))) {
                ret = -EDEADLK;
-               goto out_unlock_release_sem;
+               goto out_unlock_put_key;
        }
 
        /*
         * Surprise - we got the lock. Just return to userspace:
         */
        if (unlikely(!curval))
-               goto out_unlock_release_sem;
+               goto out_unlock_put_key;
 
        uval = curval;
 
@@ -1447,7 +1403,7 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
         * We took the lock due to owner died take over.
         */
        if (unlikely(lock_taken))
-               goto out_unlock_release_sem;
+               goto out_unlock_put_key;
 
        /*
         * We dont have the lock. Look up the PI state (or create it if
@@ -1464,7 +1420,7 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
                         * exit to complete.
                         */
                        queue_unlock(&q, hb);
-                       futex_unlock_mm(fshared);
+                       put_futex_key(fshared, &q.key);
                        cond_resched();
                        goto retry;
 
@@ -1487,20 +1443,14 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
                                goto retry_locked;
                        }
                default:
-                       goto out_unlock_release_sem;
+                       goto out_unlock_put_key;
                }
        }
 
        /*
         * Only actually queue now that the atomic ops are done:
         */
-       __queue_me(&q, hb);
-
-       /*
-        * Now the futex is queued and we have checked the data, we
-        * don't want to hold mmap_sem while we sleep.
-        */
-       futex_unlock_mm(fshared);
+       queue_me(&q, hb);
 
        WARN_ON(!q.pi_state);
        /*
@@ -1514,7 +1464,6 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
                ret = ret ? 0 : -EWOULDBLOCK;
        }
 
-       futex_lock_mm(fshared);
        spin_lock(q.lock_ptr);
 
        if (!ret) {
@@ -1524,7 +1473,7 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
                 * that case:
                 */
                if (q.pi_state->owner != curr)
-                       ret = fixup_pi_state_owner(uaddr, &q, curr);
+                       ret = fixup_pi_state_owner(uaddr, &q, curr, fshared);
        } else {
                /*
                 * Catch the rare case, where the lock was released
@@ -1556,7 +1505,8 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
                                int res;
 
                                owner = rt_mutex_owner(&q.pi_state->pi_mutex);
-                               res = fixup_pi_state_owner(uaddr, &q, owner);
+                               res = fixup_pi_state_owner(uaddr, &q, owner,
+                                                          fshared);
 
                                /* propagate -EFAULT, if the fixup failed */
                                if (res)
@@ -1577,60 +1527,65 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
                }
        }
 
+       /*
+        * If fixup_pi_state_owner() faulted and was unable to handle the
+        * fault, unlock it and return the fault to userspace.
+        */
+       if (ret && (rt_mutex_owner(&q.pi_state->pi_mutex) == current))
+               rt_mutex_unlock(&q.pi_state->pi_mutex);
+
        /* Unqueue and drop the lock */
        unqueue_me_pi(&q);
-       futex_unlock_mm(fshared);
 
+       if (to)
+               destroy_hrtimer_on_stack(&to->timer);
        return ret != -EINTR ? ret : -ERESTARTNOINTR;
 
- out_unlock_release_sem:
+out_unlock_put_key:
        queue_unlock(&q, hb);
 
- out_release_sem:
-       futex_unlock_mm(fshared);
+out_put_key:
+       put_futex_key(fshared, &q.key);
+out:
+       if (to)
+               destroy_hrtimer_on_stack(&to->timer);
        return ret;
 
- uaddr_faulted:
+uaddr_faulted:
        /*
-        * We have to r/w  *(int __user *)uaddr, but we can't modify it
-        * non-atomically.  Therefore, if get_user below is not
-        * enough, we need to handle the fault ourselves, while
-        * still holding the mmap_sem.
-        *
-        * ... and hb->lock. :-) --ANK
+        * We have to r/w  *(int __user *)uaddr, and we have to modify it
+        * atomically.  Therefore, if we continue to fault after get_user()
+        * below, we need to handle the fault ourselves, while still holding
+        * the mmap_sem.  This can occur if the uaddr is under contention as
+        * we have to drop the mmap_sem in order to call get_user().
         */
        queue_unlock(&q, hb);
 
-       if (attempt++) {
-               ret = futex_handle_fault((unsigned long)uaddr, fshared,
-                                        attempt);
-               if (ret)
-                       goto out_release_sem;
-               goto retry_unlocked;
-       }
-
-       futex_unlock_mm(fshared);
-
        ret = get_user(uval, uaddr);
-       if (!ret && (uval != -EFAULT))
-               goto retry;
+       if (ret)
+               goto out_put_key;
 
-       return ret;
+       if (!fshared)
+               goto retry_private;
+
+       put_futex_key(fshared, &q.key);
+       goto retry;
 }
 
+
 /*
  * Userspace attempted a TID -> 0 atomic transition, and failed.
  * This is the in-kernel slowpath: we look up the PI state (if any),
  * and do the rt-mutex unlock.
  */
-static int futex_unlock_pi(u32 __user *uaddr, struct rw_semaphore *fshared)
+static int futex_unlock_pi(u32 __user *uaddr, int fshared)
 {
        struct futex_hash_bucket *hb;
        struct futex_q *this, *next;
        u32 uval;
        struct plist_head *head;
-       union futex_key key;
-       int ret, attempt = 0;
+       union futex_key key = FUTEX_KEY_INIT;
+       int ret;
 
 retry:
        if (get_user(uval, uaddr))
@@ -1640,17 +1595,12 @@ retry:
         */
        if ((uval & FUTEX_TID_MASK) != task_pid_vnr(current))
                return -EPERM;
-       /*
-        * First take all the futex related locks:
-        */
-       futex_lock_mm(fshared);
 
-       ret = get_futex_key(uaddr, fshared, &key);
+       ret = get_futex_key(uaddr, fshared, &key, VERIFY_WRITE);
        if (unlikely(ret != 0))
                goto out;
 
        hb = hash_futex(&key);
-retry_unlocked:
        spin_lock(&hb->lock);
 
        /*
@@ -1701,155 +1651,29 @@ retry_unlocked:
 
 out_unlock:
        spin_unlock(&hb->lock);
-out:
-       futex_unlock_mm(fshared);
+       put_futex_key(fshared, &key);
 
+out:
        return ret;
 
 pi_faulted:
        /*
-        * We have to r/w  *(int __user *)uaddr, but we can't modify it
-        * non-atomically.  Therefore, if get_user below is not
-        * enough, we need to handle the fault ourselves, while
-        * still holding the mmap_sem.
-        *
-        * ... and hb->lock. --ANK
+        * We have to r/w  *(int __user *)uaddr, and we have to modify it
+        * atomically.  Therefore, if we continue to fault after get_user()
+        * below, we need to handle the fault ourselves, while still holding
+        * the mmap_sem.  This can occur if the uaddr is under contention as
+        * we have to drop the mmap_sem in order to call get_user().
         */
        spin_unlock(&hb->lock);
-
-       if (attempt++) {
-               ret = futex_handle_fault((unsigned long)uaddr, fshared,
-                                        attempt);
-               if (ret)
-                       goto out;
-               uval = 0;
-               goto retry_unlocked;
-       }
-
-       futex_unlock_mm(fshared);
+       put_futex_key(fshared, &key);
 
        ret = get_user(uval, uaddr);
-       if (!ret && (uval != -EFAULT))
+       if (!ret)
                goto retry;
 
        return ret;
 }
 
-static int futex_close(struct inode *inode, struct file *filp)
-{
-       struct futex_q *q = filp->private_data;
-
-       unqueue_me(q);
-       kfree(q);
-
-       return 0;
-}
-
-/* This is one-shot: once it's gone off you need a new fd */
-static unsigned int futex_poll(struct file *filp,
-                              struct poll_table_struct *wait)
-{
-       struct futex_q *q = filp->private_data;
-       int ret = 0;
-
-       poll_wait(filp, &q->waiters, wait);
-
-       /*
-        * plist_node_empty() is safe here without any lock.
-        * q->lock_ptr != 0 is not safe, because of ordering against wakeup.
-        */
-       if (plist_node_empty(&q->list))
-               ret = POLLIN | POLLRDNORM;
-
-       return ret;
-}
-
-static const struct file_operations futex_fops = {
-       .release        = futex_close,
-       .poll           = futex_poll,
-};
-
-/*
- * Signal allows caller to avoid the race which would occur if they
- * set the sigio stuff up afterwards.
- */
-static int futex_fd(u32 __user *uaddr, int signal)
-{
-       struct futex_q *q;
-       struct file *filp;
-       int ret, err;
-       struct rw_semaphore *fshared;
-       static unsigned long printk_interval;
-
-       if (printk_timed_ratelimit(&printk_interval, 60 * 60 * 1000)) {
-               printk(KERN_WARNING "Process `%s' used FUTEX_FD, which "
-                      "will be removed from the kernel in June 2007\n",
-                      current->comm);
-       }
-
-       ret = -EINVAL;
-       if (!valid_signal(signal))
-               goto out;
-
-       ret = get_unused_fd();
-       if (ret < 0)
-               goto out;
-       filp = get_empty_filp();
-       if (!filp) {
-               put_unused_fd(ret);
-               ret = -ENFILE;
-               goto out;
-       }
-       filp->f_op = &futex_fops;
-       filp->f_path.mnt = mntget(futex_mnt);
-       filp->f_path.dentry = dget(futex_mnt->mnt_root);
-       filp->f_mapping = filp->f_path.dentry->d_inode->i_mapping;
-
-       if (signal) {
-               err = __f_setown(filp, task_pid(current), PIDTYPE_PID, 1);
-               if (err < 0) {
-                       goto error;
-               }
-               filp->f_owner.signum = signal;
-       }
-
-       q = kmalloc(sizeof(*q), GFP_KERNEL);
-       if (!q) {
-               err = -ENOMEM;
-               goto error;
-       }
-       q->pi_state = NULL;
-
-       fshared = &current->mm->mmap_sem;
-       down_read(fshared);
-       err = get_futex_key(uaddr, fshared, &q->key);
-
-       if (unlikely(err != 0)) {
-               up_read(fshared);
-               kfree(q);
-               goto error;
-       }
-
-       /*
-        * queue_me() must be called before releasing mmap_sem, because
-        * key->shared.inode needs to be referenced while holding it.
-        */
-       filp->private_data = q;
-
-       queue_me(q, ret, filp);
-       up_read(fshared);
-
-       /* Now we map fd to filp, so userspace can access it */
-       fd_install(ret, filp);
-out:
-       return ret;
-error:
-       put_unused_fd(ret);
-       put_filp(filp);
-       ret = err;
-       goto out;
-}
-
 /*
  * Support for robust futexes: the kernel cleans up held futexes at
  * thread exit time.
@@ -1870,9 +1694,8 @@ error:
  * @head: pointer to the list-head
  * @len: length of the list-head, as userspace expects
  */
-asmlinkage long
-sys_set_robust_list(struct robust_list_head __user *head,
-                   size_t len)
+SYSCALL_DEFINE2(set_robust_list, struct robust_list_head __user *, head,
+               size_t, len)
 {
        if (!futex_cmpxchg_enabled)
                return -ENOSYS;
@@ -1893,12 +1716,13 @@ sys_set_robust_list(struct robust_list_head __user *head,
  * @head_ptr: pointer to a list-head pointer, the kernel fills it in
  * @len_ptr: pointer to a length field, the kernel fills in the header size
  */
-asmlinkage long
-sys_get_robust_list(int pid, struct robust_list_head __user * __user *head_ptr,
-                   size_t __user *len_ptr)
+SYSCALL_DEFINE3(get_robust_list, int, pid,
+               struct robust_list_head __user * __user *, head_ptr,
+               size_t __user *, len_ptr)
 {
        struct robust_list_head __user *head;
        unsigned long ret;
+       const struct cred *cred = current_cred(), *pcred;
 
        if (!futex_cmpxchg_enabled)
                return -ENOSYS;
@@ -1914,8 +1738,10 @@ sys_get_robust_list(int pid, struct robust_list_head __user * __user *head_ptr,
                if (!p)
                        goto err_unlock;
                ret = -EPERM;
-               if ((current->euid != p->euid) && (current->euid != p->uid) &&
-                               !capable(CAP_SYS_PTRACE))
+               pcred = __task_cred(p);
+               if (cred->euid != pcred->euid &&
+                   cred->euid != pcred->uid &&
+                   !capable(CAP_SYS_PTRACE))
                        goto err_unlock;
                head = p->robust_list;
                rcu_read_unlock();
@@ -1968,8 +1794,7 @@ retry:
                 * PI futexes happens in exit_pi_state():
                 */
                if (!pi && (uval & FUTEX_WAITERS))
-                       futex_wake(uaddr, &curr->mm->mmap_sem, 1,
-                                  FUTEX_BITSET_MATCH_ANY);
+                       futex_wake(uaddr, 1, 1, FUTEX_BITSET_MATCH_ANY);
        }
        return 0;
 }
@@ -2063,28 +1888,28 @@ void exit_robust_list(struct task_struct *curr)
 long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
                u32 __user *uaddr2, u32 val2, u32 val3)
 {
-       int ret = -ENOSYS;
+       int clockrt, ret = -ENOSYS;
        int cmd = op & FUTEX_CMD_MASK;
-       struct rw_semaphore *fshared = NULL;
+       int fshared = 0;
 
        if (!(op & FUTEX_PRIVATE_FLAG))
-               fshared = &current->mm->mmap_sem;
+               fshared = 1;
+
+       clockrt = op & FUTEX_CLOCK_REALTIME;
+       if (clockrt && cmd != FUTEX_WAIT_BITSET)
+               return -ENOSYS;
 
        switch (cmd) {
        case FUTEX_WAIT:
                val3 = FUTEX_BITSET_MATCH_ANY;
        case FUTEX_WAIT_BITSET:
-               ret = futex_wait(uaddr, fshared, val, timeout, val3);
+               ret = futex_wait(uaddr, fshared, val, timeout, val3, clockrt);
                break;
        case FUTEX_WAKE:
                val3 = FUTEX_BITSET_MATCH_ANY;
        case FUTEX_WAKE_BITSET:
                ret = futex_wake(uaddr, fshared, val, val3);
                break;
-       case FUTEX_FD:
-               /* non-zero val means F_SETOWN(getpid()) & F_SETSIG(val) */
-               ret = futex_fd(uaddr, val);
-               break;
        case FUTEX_REQUEUE:
                ret = futex_requeue(uaddr, fshared, uaddr2, val, val2, NULL);
                break;
@@ -2113,9 +1938,9 @@ long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
 }
 
 
-asmlinkage long sys_futex(u32 __user *uaddr, int op, u32 val,
-                         struct timespec __user *utime, u32 __user *uaddr2,
-                         u32 val3)
+SYSCALL_DEFINE6(futex, u32 __user *, uaddr, int, op, u32, val,
+               struct timespec __user *, utime, u32 __user *, uaddr2,
+               u32, val3)
 {
        struct timespec ts;
        ktime_t t, *tp = NULL;
@@ -2145,19 +1970,6 @@ asmlinkage long sys_futex(u32 __user *uaddr, int op, u32 val,
        return do_futex(uaddr, op, val, tp, uaddr2, val2, val3);
 }
 
-static int futexfs_get_sb(struct file_system_type *fs_type,
-                         int flags, const char *dev_name, void *data,
-                         struct vfsmount *mnt)
-{
-       return get_sb_pseudo(fs_type, "futex", NULL, FUTEXFS_SUPER_MAGIC, mnt);
-}
-
-static struct file_system_type futex_fs_type = {
-       .name           = "futexfs",
-       .get_sb         = futexfs_get_sb,
-       .kill_sb        = kill_anon_super,
-};
-
 static int __init futex_init(void)
 {
        u32 curval;
@@ -2182,16 +1994,6 @@ static int __init futex_init(void)
                spin_lock_init(&futex_queues[i].lock);
        }
 
-       i = register_filesystem(&futex_fs_type);
-       if (i)
-               return i;
-
-       futex_mnt = kern_mount(&futex_fs_type);
-       if (IS_ERR(futex_mnt)) {
-               unregister_filesystem(&futex_fs_type);
-               return PTR_ERR(futex_mnt);
-       }
-
        return 0;
 }
 __initcall(futex_init);