diff options
author | Thomas Hellstrom <thomas@tungstengraphics.com> | 2006-08-07 22:22:10 +1000 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2006-09-22 05:32:31 +1000 |
commit | 8669cbc5e651bf4effa20e8c244a5a7d67da6fe9 (patch) | |
tree | a97ac359c8041bc39efc0f32cac26772a43a0736 /drivers/char/drm | |
parent | 3d45dbd611d1441d667b06acced9fbad3c8fcb1b (diff) | |
download | linux-8669cbc5e651bf4effa20e8c244a5a7d67da6fe9.tar.bz2 |
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.h | 8 | ||||
-rw-r--r-- | drivers/char/drm/drm_auth.c | 62 | ||||
-rw-r--r-- | drivers/char/drm/drm_drv.c | 10 | ||||
-rw-r--r-- | drivers/char/drm/drm_fops.c | 6 | ||||
-rw-r--r-- | drivers/char/drm/drm_hashtab.h | 2 |
5 files changed, 26 insertions, 62 deletions
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index c93985bb91a2..fedaf013f848 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 2a37586a7ee8..40cd262ca9e1 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 3da72f7364f0..f9ecc8414b8a 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 51ccc82bf612..2bbf45d85c35 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 40afec05bff8..9e19ef1814ba 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; |