sfc: Assert filter_sem write locked when required
Based on a patch by Andrew Rybchenko <Andrew.Rybchenko@oktetlabs.ru> Signed-off-by: Edward Cree <ecree@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
ebfcd0fd90
commit
dd98708cf6
@ -3735,6 +3735,12 @@ static int efx_ef10_filter_table_probe(struct efx_nic *efx)
|
|||||||
size_t outlen;
|
size_t outlen;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
if (!efx_rwsem_assert_write_locked(&efx->filter_sem))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (efx->filter_state) /* already probed */
|
||||||
|
return 0;
|
||||||
|
|
||||||
table = kzalloc(sizeof(*table), GFP_KERNEL);
|
table = kzalloc(sizeof(*table), GFP_KERNEL);
|
||||||
if (!table)
|
if (!table)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@ -3846,7 +3852,6 @@ static void efx_ef10_filter_table_restore(struct efx_nic *efx)
|
|||||||
nic_data->must_restore_filters = false;
|
nic_data->must_restore_filters = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Caller must hold efx->filter_sem for write */
|
|
||||||
static void efx_ef10_filter_table_remove(struct efx_nic *efx)
|
static void efx_ef10_filter_table_remove(struct efx_nic *efx)
|
||||||
{
|
{
|
||||||
struct efx_ef10_filter_table *table = efx->filter_state;
|
struct efx_ef10_filter_table *table = efx->filter_state;
|
||||||
@ -3856,6 +3861,15 @@ static void efx_ef10_filter_table_remove(struct efx_nic *efx)
|
|||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
efx->filter_state = NULL;
|
efx->filter_state = NULL;
|
||||||
|
/* If we were called without locking, then it's not safe to free
|
||||||
|
* the table as others might be using it. So we just WARN, leak
|
||||||
|
* the memory, and potentially get an inconsistent filter table
|
||||||
|
* state.
|
||||||
|
* This should never actually happen.
|
||||||
|
*/
|
||||||
|
if (!efx_rwsem_assert_write_locked(&efx->filter_sem))
|
||||||
|
return;
|
||||||
|
|
||||||
if (!table)
|
if (!table)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -274,4 +274,13 @@ static inline void efx_device_detach_sync(struct efx_nic *efx)
|
|||||||
netif_tx_unlock_bh(dev);
|
netif_tx_unlock_bh(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool efx_rwsem_assert_write_locked(struct rw_semaphore *sem)
|
||||||
|
{
|
||||||
|
if (WARN_ON(down_read_trylock(sem))) {
|
||||||
|
up_read(sem);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* EFX_EFX_H */
|
#endif /* EFX_EFX_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user