Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

svcrpc: ensure cache_check caller sees updated entry

Supposes cache_check runs simultaneously with an update on a different
CPU:

cache_check task doing update
^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^

1. test for CACHE_VALID 1'. set entry->data
& !CACHE_NEGATIVE

2. use entry->data 2'. set CACHE_VALID

If the two memory writes performed in step 1' and 2' appear misordered
with respect to the reads in step 1 and 2, then the caller could get
stale data at step 2 even though it saw CACHE_VALID set on the cache
entry.

Add memory barriers to prevent this.

Reviewed-by: NeilBrown <neilb@suse.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>

+10 -1
+10 -1
net/sunrpc/cache.c
··· 128 128 { 129 129 head->expiry_time = expiry; 130 130 head->last_refresh = seconds_since_boot(); 131 + smp_wmb(); /* paired with smp_rmb() in cache_is_valid() */ 131 132 set_bit(CACHE_VALID, &head->flags); 132 133 } 133 134 ··· 209 208 /* entry is valid */ 210 209 if (test_bit(CACHE_NEGATIVE, &h->flags)) 211 210 return -ENOENT; 212 - else 211 + else { 212 + /* 213 + * In combination with write barrier in 214 + * sunrpc_cache_update, ensures that anyone 215 + * using the cache entry after this sees the 216 + * updated contents: 217 + */ 218 + smp_rmb(); 213 219 return 0; 220 + } 214 221 } 215 222 } 216 223