Skip to content

Commit

Permalink
RDS: Fix potential race around rds_i[bw]_allocation
Browse files Browse the repository at this point in the history
"At rds_ib_recv_refill_one(), it first executes atomic_read(&rds_ib_allocation)
for if-condition checking,

and then executes atomic_inc(&rds_ib_allocation) if the condition was
not satisfied.

However, if any other code which updates rds_ib_allocation executes
between these two atomic operation executions,
it seems that it may result race condition. (especially when
rds_ib_allocation + 1 == rds_ib_sysctl_max_recv_allocation)"

This patch fixes this by using atomic_inc_unless to eliminate the
possibility of allocating more than rds_ib_sysctl_max_recv_allocation
and then decrementing the count if the allocation fails. It also
makes an identical change to the iwarp transport.

Reported-by: Shin Hong <[email protected]>
Signed-off-by: Andy Grover <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
Andy Grover authored and davem330 committed Oct 30, 2009
1 parent 244546f commit 86357b1
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 6 deletions.
7 changes: 4 additions & 3 deletions net/rds/ib_recv.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,15 +143,16 @@ static int rds_ib_recv_refill_one(struct rds_connection *conn,
int ret = -ENOMEM;

if (recv->r_ibinc == NULL) {
if (atomic_read(&rds_ib_allocation) >= rds_ib_sysctl_max_recv_allocation) {
if (!atomic_add_unless(&rds_ib_allocation, 1, rds_ib_sysctl_max_recv_allocation)) {
rds_ib_stats_inc(s_ib_rx_alloc_limit);
goto out;
}
recv->r_ibinc = kmem_cache_alloc(rds_ib_incoming_slab,
kptr_gfp);
if (recv->r_ibinc == NULL)
if (recv->r_ibinc == NULL) {
atomic_dec(&rds_ib_allocation);
goto out;
atomic_inc(&rds_ib_allocation);
}
INIT_LIST_HEAD(&recv->r_ibinc->ii_frags);
rds_inc_init(&recv->r_ibinc->ii_inc, conn, conn->c_faddr);
}
Expand Down
7 changes: 4 additions & 3 deletions net/rds/iw_recv.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,15 +143,16 @@ static int rds_iw_recv_refill_one(struct rds_connection *conn,
int ret = -ENOMEM;

if (recv->r_iwinc == NULL) {
if (atomic_read(&rds_iw_allocation) >= rds_iw_sysctl_max_recv_allocation) {
if (!atomic_add_unless(&rds_iw_allocation, 1, rds_iw_sysctl_max_recv_allocation)) {
rds_iw_stats_inc(s_iw_rx_alloc_limit);
goto out;
}
recv->r_iwinc = kmem_cache_alloc(rds_iw_incoming_slab,
kptr_gfp);
if (recv->r_iwinc == NULL)
if (recv->r_iwinc == NULL) {
atomic_dec(&rds_iw_allocation);
goto out;
atomic_inc(&rds_iw_allocation);
}
INIT_LIST_HEAD(&recv->r_iwinc->ii_frags);
rds_inc_init(&recv->r_iwinc->ii_inc, conn, conn->c_faddr);
}
Expand Down

0 comments on commit 86357b1

Please sign in to comment.