summaryrefslogtreecommitdiffstats
path: root/drivers/char/drm
diff options
context:
space:
mode:
authorThomas Hellstrom <thomas@tungstengraphics.com>2006-08-07 22:22:10 +1000
committerDave Airlie <airlied@linux.ie>2006-09-22 05:32:31 +1000
commit8669cbc5e651bf4effa20e8c244a5a7d67da6fe9 (patch)
treea97ac359c8041bc39efc0f32cac26772a43a0736 /drivers/char/drm
parent3d45dbd611d1441d667b06acced9fbad3c8fcb1b (diff)
downloadop-kernel-dev-8669cbc5e651bf4effa20e8c244a5a7d67da6fe9.zip
op-kernel-dev-8669cbc5e651bf4effa20e8c244a5a7d67da6fe9.tar.gz
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: Dave Airlie <airlied@linux.ie>
Diffstat (limited to 'drivers/char/drm')
-rw-r--r--drivers/char/drm/drmP.h8
-rw-r--r--drivers/char/drm/drm_auth.c62
-rw-r--r--drivers/char/drm/drm_drv.c10
-rw-r--r--drivers/char/drm/drm_fops.c6
-rw-r--r--drivers/char/drm/drm_hashtab.h2
5 files changed, 26 insertions, 62 deletions
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
index c93985b..fedaf01 100644
--- a/drivers/char/drm/drmP.h
+++ b/drivers/char/drm/drmP.h
@@ -105,7 +105,7 @@
#define DRM_DEBUG_CODE 2 /**< Include debugging code if > 1, then
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_RESERVED_CONTEXTS 1 /**< Change drm_resctx if changed */
#define DRM_LOOPING_LIMIT 5000000
@@ -277,7 +277,8 @@ typedef struct drm_devstate {
} drm_devstate_t;
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_magic_entry *next;
} drm_magic_entry_t;
@@ -653,7 +654,8 @@ typedef struct drm_device {
/*@{ */
drm_file_t *file_first; /**< file list head */
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 */
diff --git a/drivers/char/drm/drm_auth.c b/drivers/char/drm/drm_auth.c
index 2a37586..40cd262 100644
--- a/drivers/char/drm/drm_auth.c
+++ b/drivers/char/drm/drm_auth.c
@@ -36,20 +36,6 @@
#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.
*
* \param dev DRM device.
@@ -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_magic_entry_t *pt;
- int hash = drm_hash_magic(magic);
+ drm_hash_item_t *hash;
mutex_lock(&dev->struct_mutex);
- for (pt = dev->magiclist[hash].head; pt; pt = pt->next) {
- if (pt->magic == magic) {
- retval = pt->priv;
- break;
- }
+ if (!drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) {
+ pt = drm_hash_entry(hash, drm_magic_entry_t, hash_item);
+ retval = pt->priv;
}
mutex_unlock(&dev->struct_mutex);
return retval;
@@ -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,
drm_magic_t magic)
{
- int hash;
drm_magic_entry_t *entry;
DRM_DEBUG("%d\n", magic);
- hash = drm_hash_magic(magic);
entry = drm_alloc(sizeof(*entry), DRM_MEM_MAGIC);
if (!entry)
return -ENOMEM;
memset(entry, 0, sizeof(*entry));
- entry->magic = magic;
entry->priv = priv;
- entry->next = NULL;
+ entry->hash_item.key = (unsigned long)magic;
mutex_lock(&dev->struct_mutex);
- if (dev->magiclist[hash].tail) {
- dev->magiclist[hash].tail->next = entry;
- dev->magiclist[hash].tail = entry;
- } else {
- dev->magiclist[hash].head = entry;
- dev->magiclist[hash].tail = entry;
- }
+ drm_ht_insert_item(&dev->magiclist, &entry->hash_item);
+ list_add_tail(&entry->head, &dev->magicfree);
mutex_unlock(&dev->struct_mutex);
return 0;
@@ -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)
{
- drm_magic_entry_t *prev = NULL;
drm_magic_entry_t *pt;
- int hash;
+ drm_hash_item_t *hash;
DRM_DEBUG("%d\n", magic);
- hash = drm_hash_magic(magic);
mutex_lock(&dev->struct_mutex);
- for (pt = dev->magiclist[hash].head; pt; prev = pt, pt = pt->next) {
- 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);
- return 0;
- }
+ if (drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) {
+ mutex_unlock(&dev->struct_mutex);
+ 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);
drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c
index 3da72f7..f9ecc84 100644
--- a/drivers/char/drm/drm_drv.c
+++ b/drivers/char/drm/drm_drv.c
@@ -155,12 +155,10 @@ int drm_lastclose(drm_device_t * dev)
del_timer(&dev->timer);
/* Clear pid list */
- for (i = 0; i < DRM_HASH_SIZE; i++) {
- for (pt = dev->magiclist[i].head; pt; pt = next) {
- next = pt->next;
- drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
- }
- dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
+ list_for_each_entry_safe(pt, next, &dev->magicfree, head) {
+ list_del(&pt->head);
+ drm_ht_remove_item(&dev->magiclist, &pt->hash_item);
+ drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
}
/* Clear AGP information */
diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c
index 51ccc82b..2bbf45d 100644
--- a/drivers/char/drm/drm_fops.c
+++ b/drivers/char/drm/drm_fops.c
@@ -72,10 +72,8 @@ static int drm_setup(drm_device_t * dev)
for (i = 0; i < ARRAY_SIZE(dev->counts); i++)
atomic_set(&dev->counts[i], 0);
- for (i = 0; i < DRM_HASH_SIZE; i++) {
- dev->magiclist[i].head = NULL;
- dev->magiclist[i].tail = NULL;
- }
+ drm_ht_create(&dev->magiclist, DRM_MAGIC_HASH_ORDER);
+ INIT_LIST_HEAD(&dev->magicfree);
dev->ctxlist = drm_alloc(sizeof(*dev->ctxlist), DRM_MEM_CTXLIST);
if (dev->ctxlist == NULL)
diff --git a/drivers/char/drm/drm_hashtab.h b/drivers/char/drm/drm_hashtab.h
index 40afec0..9e19ef1 100644
--- a/drivers/char/drm/drm_hashtab.h
+++ b/drivers/char/drm/drm_hashtab.h
@@ -35,7 +35,7 @@
#ifndef 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{
struct hlist_node head;
OpenPOWER on IntegriCloud