Commit 8669cbc5 authored by Thomas Hellstrom's avatar Thomas Hellstrom Committed by Dave Airlie

drm: move drm authentication to new generic hash table.

Fix drm_remove_magic potential memory leak / corruption. Move drm
authentication token hashing to new generic hash table implementation.
Signed-off-by: default avatarDave Airlie <airlied@linux.ie>
parent 3d45dbd6
...@@ -105,7 +105,7 @@ ...@@ -105,7 +105,7 @@
#define DRM_DEBUG_CODE 2 /**< Include debugging code if > 1, then #define DRM_DEBUG_CODE 2 /**< Include debugging code if > 1, then
also include looping detection. */ also include looping detection. */
#define DRM_HASH_SIZE 16 /**< Size of key hash table. Must be power of 2. */ #define DRM_MAGIC_HASH_ORDER 4 /**< Size of key hash table. Must be power of 2. */
#define DRM_KERNEL_CONTEXT 0 /**< Change drm_resctx if changed */ #define DRM_KERNEL_CONTEXT 0 /**< Change drm_resctx if changed */
#define DRM_RESERVED_CONTEXTS 1 /**< Change drm_resctx if changed */ #define DRM_RESERVED_CONTEXTS 1 /**< Change drm_resctx if changed */
#define DRM_LOOPING_LIMIT 5000000 #define DRM_LOOPING_LIMIT 5000000
...@@ -277,7 +277,8 @@ typedef struct drm_devstate { ...@@ -277,7 +277,8 @@ typedef struct drm_devstate {
} drm_devstate_t; } drm_devstate_t;
typedef struct drm_magic_entry { typedef struct drm_magic_entry {
drm_magic_t magic; drm_hash_item_t hash_item;
struct list_head head;
struct drm_file *priv; struct drm_file *priv;
struct drm_magic_entry *next; struct drm_magic_entry *next;
} drm_magic_entry_t; } drm_magic_entry_t;
...@@ -653,7 +654,8 @@ typedef struct drm_device { ...@@ -653,7 +654,8 @@ typedef struct drm_device {
/*@{ */ /*@{ */
drm_file_t *file_first; /**< file list head */ drm_file_t *file_first; /**< file list head */
drm_file_t *file_last; /**< file list tail */ drm_file_t *file_last; /**< file list tail */
drm_magic_head_t magiclist[DRM_HASH_SIZE]; /**< magic hash table */ drm_open_hash_t magiclist; /**< magic hash table */
struct list_head magicfree;
/*@} */ /*@} */
/** \name Memory management */ /** \name Memory management */
......
...@@ -35,20 +35,6 @@ ...@@ -35,20 +35,6 @@
#include "drmP.h" #include "drmP.h"
/**
* Generate a hash key from a magic.
*
* \param magic magic.
* \return hash key.
*
* The key is the modulus of the hash table size, #DRM_HASH_SIZE, which must be
* a power of 2.
*/
static int drm_hash_magic(drm_magic_t magic)
{
return magic & (DRM_HASH_SIZE - 1);
}
/** /**
* Find the file with the given magic number. * Find the file with the given magic number.
* *
...@@ -63,14 +49,12 @@ static drm_file_t *drm_find_file(drm_device_t * dev, drm_magic_t magic) ...@@ -63,14 +49,12 @@ static drm_file_t *drm_find_file(drm_device_t * dev, drm_magic_t magic)
{ {
drm_file_t *retval = NULL; drm_file_t *retval = NULL;
drm_magic_entry_t *pt; drm_magic_entry_t *pt;
int hash = drm_hash_magic(magic); drm_hash_item_t *hash;
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
for (pt = dev->magiclist[hash].head; pt; pt = pt->next) { if (!drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) {
if (pt->magic == magic) { pt = drm_hash_entry(hash, drm_magic_entry_t, hash_item);
retval = pt->priv; retval = pt->priv;
break;
}
} }
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
return retval; return retval;
...@@ -90,28 +74,20 @@ static drm_file_t *drm_find_file(drm_device_t * dev, drm_magic_t magic) ...@@ -90,28 +74,20 @@ static drm_file_t *drm_find_file(drm_device_t * dev, drm_magic_t magic)
static int drm_add_magic(drm_device_t * dev, drm_file_t * priv, static int drm_add_magic(drm_device_t * dev, drm_file_t * priv,
drm_magic_t magic) drm_magic_t magic)
{ {
int hash;
drm_magic_entry_t *entry; drm_magic_entry_t *entry;
DRM_DEBUG("%d\n", magic); DRM_DEBUG("%d\n", magic);
hash = drm_hash_magic(magic);
entry = drm_alloc(sizeof(*entry), DRM_MEM_MAGIC); entry = drm_alloc(sizeof(*entry), DRM_MEM_MAGIC);
if (!entry) if (!entry)
return -ENOMEM; return -ENOMEM;
memset(entry, 0, sizeof(*entry)); memset(entry, 0, sizeof(*entry));
entry->magic = magic;
entry->priv = priv; entry->priv = priv;
entry->next = NULL;
entry->hash_item.key = (unsigned long)magic;
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
if (dev->magiclist[hash].tail) { drm_ht_insert_item(&dev->magiclist, &entry->hash_item);
dev->magiclist[hash].tail->next = entry; list_add_tail(&entry->head, &dev->magicfree);
dev->magiclist[hash].tail = entry;
} else {
dev->magiclist[hash].head = entry;
dev->magiclist[hash].tail = entry;
}
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
return 0; return 0;
...@@ -128,29 +104,19 @@ static int drm_add_magic(drm_device_t * dev, drm_file_t * priv, ...@@ -128,29 +104,19 @@ static int drm_add_magic(drm_device_t * dev, drm_file_t * priv,
*/ */
static int drm_remove_magic(drm_device_t * dev, drm_magic_t magic) static int drm_remove_magic(drm_device_t * dev, drm_magic_t magic)
{ {
drm_magic_entry_t *prev = NULL;
drm_magic_entry_t *pt; drm_magic_entry_t *pt;
int hash; drm_hash_item_t *hash;
DRM_DEBUG("%d\n", magic); DRM_DEBUG("%d\n", magic);
hash = drm_hash_magic(magic);
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
for (pt = dev->magiclist[hash].head; pt; prev = pt, pt = pt->next) { if (drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) {
if (pt->magic == magic) {
if (dev->magiclist[hash].head == pt) {
dev->magiclist[hash].head = pt->next;
}
if (dev->magiclist[hash].tail == pt) {
dev->magiclist[hash].tail = prev;
}
if (prev) {
prev->next = pt->next;
}
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
return 0; return -EINVAL;
}
} }
pt = drm_hash_entry(hash, drm_magic_entry_t, hash_item);
drm_ht_remove_item(&dev->magiclist, hash);
list_del(&pt->head);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC); drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
......
...@@ -155,13 +155,11 @@ int drm_lastclose(drm_device_t * dev) ...@@ -155,13 +155,11 @@ int drm_lastclose(drm_device_t * dev)
del_timer(&dev->timer); del_timer(&dev->timer);
/* Clear pid list */ /* Clear pid list */
for (i = 0; i < DRM_HASH_SIZE; i++) { list_for_each_entry_safe(pt, next, &dev->magicfree, head) {
for (pt = dev->magiclist[i].head; pt; pt = next) { list_del(&pt->head);
next = pt->next; drm_ht_remove_item(&dev->magiclist, &pt->hash_item);
drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC); drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
} }
dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
}
/* Clear AGP information */ /* Clear AGP information */
if (drm_core_has_AGP(dev) && dev->agp) { if (drm_core_has_AGP(dev) && dev->agp) {
......
...@@ -72,10 +72,8 @@ static int drm_setup(drm_device_t * dev) ...@@ -72,10 +72,8 @@ static int drm_setup(drm_device_t * dev)
for (i = 0; i < ARRAY_SIZE(dev->counts); i++) for (i = 0; i < ARRAY_SIZE(dev->counts); i++)
atomic_set(&dev->counts[i], 0); atomic_set(&dev->counts[i], 0);
for (i = 0; i < DRM_HASH_SIZE; i++) { drm_ht_create(&dev->magiclist, DRM_MAGIC_HASH_ORDER);
dev->magiclist[i].head = NULL; INIT_LIST_HEAD(&dev->magicfree);
dev->magiclist[i].tail = NULL;
}
dev->ctxlist = drm_alloc(sizeof(*dev->ctxlist), DRM_MEM_CTXLIST); dev->ctxlist = drm_alloc(sizeof(*dev->ctxlist), DRM_MEM_CTXLIST);
if (dev->ctxlist == NULL) if (dev->ctxlist == NULL)
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
#ifndef DRM_HASHTAB_H #ifndef DRM_HASHTAB_H
#define DRM_HASHTAB_H #define DRM_HASHTAB_H
#define drm_hash_entry(_ptr, _type, _member) container_of(_ptr, _type, _member) #define drm_hash_entry(_ptr, _type, _member) list_entry(_ptr, _type, _member)
typedef struct drm_hash_item{ typedef struct drm_hash_item{
struct hlist_node head; struct hlist_node head;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment