diff options
Diffstat (limited to 'net/sctp')
-rw-r--r-- | net/sctp/associola.c | 31 |
1 files changed, 15 insertions, 16 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 2f95f5a5145d..43cd0dd9149d 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
@@ -1591,32 +1591,31 @@ int sctp_assoc_lookup_laddr(struct sctp_association *asoc, | |||
1591 | /* Set an association id for a given association */ | 1591 | /* Set an association id for a given association */ |
1592 | int sctp_assoc_set_id(struct sctp_association *asoc, gfp_t gfp) | 1592 | int sctp_assoc_set_id(struct sctp_association *asoc, gfp_t gfp) |
1593 | { | 1593 | { |
1594 | int assoc_id; | 1594 | bool preload = gfp & __GFP_WAIT; |
1595 | int error = 0; | 1595 | int ret; |
1596 | 1596 | ||
1597 | /* If the id is already assigned, keep it. */ | 1597 | /* If the id is already assigned, keep it. */ |
1598 | if (asoc->assoc_id) | 1598 | if (asoc->assoc_id) |
1599 | return error; | 1599 | return 0; |
1600 | retry: | ||
1601 | if (unlikely(!idr_pre_get(&sctp_assocs_id, gfp))) | ||
1602 | return -ENOMEM; | ||
1603 | 1600 | ||
1601 | if (preload) | ||
1602 | idr_preload(gfp); | ||
1604 | spin_lock_bh(&sctp_assocs_id_lock); | 1603 | spin_lock_bh(&sctp_assocs_id_lock); |
1605 | error = idr_get_new_above(&sctp_assocs_id, (void *)asoc, | 1604 | /* 0 is not a valid id, idr_low is always >= 1 */ |
1606 | idr_low, &assoc_id); | 1605 | ret = idr_alloc(&sctp_assocs_id, asoc, idr_low, 0, GFP_NOWAIT); |
1607 | if (!error) { | 1606 | if (ret >= 0) { |
1608 | idr_low = assoc_id + 1; | 1607 | idr_low = ret + 1; |
1609 | if (idr_low == INT_MAX) | 1608 | if (idr_low == INT_MAX) |
1610 | idr_low = 1; | 1609 | idr_low = 1; |
1611 | } | 1610 | } |
1612 | spin_unlock_bh(&sctp_assocs_id_lock); | 1611 | spin_unlock_bh(&sctp_assocs_id_lock); |
1613 | if (error == -EAGAIN) | 1612 | if (preload) |
1614 | goto retry; | 1613 | idr_preload_end(); |
1615 | else if (error) | 1614 | if (ret < 0) |
1616 | return error; | 1615 | return ret; |
1617 | 1616 | ||
1618 | asoc->assoc_id = (sctp_assoc_t) assoc_id; | 1617 | asoc->assoc_id = (sctp_assoc_t)ret; |
1619 | return error; | 1618 | return 0; |
1620 | } | 1619 | } |
1621 | 1620 | ||
1622 | /* Free the ASCONF queue */ | 1621 | /* Free the ASCONF queue */ |