Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ohad/hwspinlock
[pandora-kernel.git] / security / keys / key.c
index f7f9d93..4414abd 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/user_namespace.h>
 #include "internal.h"
 
-static struct kmem_cache       *key_jar;
+struct kmem_cache *key_jar;
 struct rb_root         key_serial_tree; /* tree of keys indexed by serial */
 DEFINE_SPINLOCK(key_serial_lock);
 
@@ -36,17 +36,9 @@ unsigned int key_quota_maxbytes = 20000;     /* general key space quota */
 static LIST_HEAD(key_types_list);
 static DECLARE_RWSEM(key_types_sem);
 
-static void key_cleanup(struct work_struct *work);
-static DECLARE_WORK(key_cleanup_task, key_cleanup);
-
 /* We serialise key instantiation and link */
 DEFINE_MUTEX(key_construction_mutex);
 
-/* Any key who's type gets unegistered will be re-typed to this */
-static struct key_type key_type_dead = {
-       .name           = "dead",
-};
-
 #ifdef KEY_DEBUGGING
 void __key_check(const struct key *key)
 {
@@ -591,71 +583,6 @@ int key_reject_and_link(struct key *key,
 }
 EXPORT_SYMBOL(key_reject_and_link);
 
-/*
- * Garbage collect keys in process context so that we don't have to disable
- * interrupts all over the place.
- *
- * key_put() schedules this rather than trying to do the cleanup itself, which
- * means key_put() doesn't have to sleep.
- */
-static void key_cleanup(struct work_struct *work)
-{
-       struct rb_node *_n;
-       struct key *key;
-
-go_again:
-       /* look for a dead key in the tree */
-       spin_lock(&key_serial_lock);
-
-       for (_n = rb_first(&key_serial_tree); _n; _n = rb_next(_n)) {
-               key = rb_entry(_n, struct key, serial_node);
-
-               if (atomic_read(&key->usage) == 0)
-                       goto found_dead_key;
-       }
-
-       spin_unlock(&key_serial_lock);
-       return;
-
-found_dead_key:
-       /* we found a dead key - once we've removed it from the tree, we can
-        * drop the lock */
-       rb_erase(&key->serial_node, &key_serial_tree);
-       spin_unlock(&key_serial_lock);
-
-       key_check(key);
-
-       security_key_free(key);
-
-       /* deal with the user's key tracking and quota */
-       if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) {
-               spin_lock(&key->user->lock);
-               key->user->qnkeys--;
-               key->user->qnbytes -= key->quotalen;
-               spin_unlock(&key->user->lock);
-       }
-
-       atomic_dec(&key->user->nkeys);
-       if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags))
-               atomic_dec(&key->user->nikeys);
-
-       key_user_put(key->user);
-
-       /* now throw away the key memory */
-       if (key->type->destroy)
-               key->type->destroy(key);
-
-       kfree(key->description);
-
-#ifdef KEY_DEBUGGING
-       key->magic = KEY_DEBUG_MAGIC_X;
-#endif
-       kmem_cache_free(key_jar, key);
-
-       /* there may, of course, be more than one key to destroy */
-       goto go_again;
-}
-
 /**
  * key_put - Discard a reference to a key.
  * @key: The key to discard a reference from.
@@ -670,7 +597,7 @@ void key_put(struct key *key)
                key_check(key);
 
                if (atomic_dec_and_test(&key->usage))
-                       schedule_work(&key_cleanup_task);
+                       queue_work(system_nrt_wq, &key_gc_work);
        }
 }
 EXPORT_SYMBOL(key_put);
@@ -1048,49 +975,11 @@ EXPORT_SYMBOL(register_key_type);
  */
 void unregister_key_type(struct key_type *ktype)
 {
-       struct rb_node *_n;
-       struct key *key;
-
        down_write(&key_types_sem);
-
-       /* withdraw the key type */
        list_del_init(&ktype->link);
-
-       /* mark all the keys of this type dead */
-       spin_lock(&key_serial_lock);
-
-       for (_n = rb_first(&key_serial_tree); _n; _n = rb_next(_n)) {
-               key = rb_entry(_n, struct key, serial_node);
-
-               if (key->type == ktype) {
-                       key->type = &key_type_dead;
-                       set_bit(KEY_FLAG_DEAD, &key->flags);
-               }
-       }
-
-       spin_unlock(&key_serial_lock);
-
-       /* make sure everyone revalidates their keys */
-       synchronize_rcu();
-
-       /* we should now be able to destroy the payloads of all the keys of
-        * this type with impunity */
-       spin_lock(&key_serial_lock);
-
-       for (_n = rb_first(&key_serial_tree); _n; _n = rb_next(_n)) {
-               key = rb_entry(_n, struct key, serial_node);
-
-               if (key->type == ktype) {
-                       if (ktype->destroy)
-                               ktype->destroy(key);
-                       memset(&key->payload, KEY_DESTROY, sizeof(key->payload));
-               }
-       }
-
-       spin_unlock(&key_serial_lock);
-       up_write(&key_types_sem);
-
-       key_schedule_gc(0);
+       downgrade_write(&key_types_sem);
+       key_gc_keytype(ktype);
+       up_read(&key_types_sem);
 }
 EXPORT_SYMBOL(unregister_key_type);