Problem about making dll shared data segment safe

I have two filter drivers. One is file system filter driver and another is volume filter driver.
I also write a kernel mode dll to share a hash table between these two filter drivers.
The file system driver only put the irp it filtered into hash table and then send the irp down to next driver.
And the volume filter driver will check if the irp it filtered is in the hash table. If it is, the volume filter driver
delete it from hash table.

To keep it safe, I use a shared spin_lock in the dll. Both hash table and spin_lock are put into
a shared data segment. So two drivers will share one lock. Like below:

#pragma data_seg("SharedHashSet") HashSet set; KSPIN_LOCK PLock; #pragma data_seg

The operation method is also int the dll. When a filter driver operate the hash table, it will firstly
get spin_lock. The operation method is like below:

`void insertValue(PIRP key)
{
KIRQL irql;
KeAcquireSpinLock(&PLock, &irql);

PEntry mEntry;
UINT64 i = getLocation(key);
PEntry entry = set.bucket[i];
if (entry == NULL) {
    mEntry = newEntry(key, NULL);
}
else {
    mEntry = newEntry(key, entry);
}
set.bucket[i] = mEntry;

KeReleaseSpinLock(&PLock, irql);

}`

The hash table structure is like this:

typedef struct _ENTRY { PIRP key; struct _ENTRY* next; }Entry , *PEntry;

typedef struct _HASHSET { PEntry bucket[BUCKETCAPICITY]; }HashSet, *PHashSet;

It should have worked safely. But I find that sometimes the volume filter driver can not
find the irp which upper file system filter already put into the table.

Could sombody tell me what is the problem?