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

netfilter: ctnetlink: remove refcounting in dying list dumping

There is no need to keep the object alive via refcount, use a cookie and
then use that as the skip hint for dump resumption.

Unlike the two earlier, similar patches in this file, this is a cleanup
without intended side effects.

Signed-off-by: Florian Westphal <fw@strlen.de>

+10 -29
+10 -29
net/netfilter/nf_conntrack_netlink.c
··· 60 60 MODULE_DESCRIPTION("List and change connection tracking table"); 61 61 62 62 struct ctnetlink_list_dump_ctx { 63 - struct nf_conn *last; 63 + unsigned long last_id; 64 64 unsigned int cpu; 65 65 bool done; 66 66 }; ··· 1733 1733 return nfnetlink_unicast(skb2, info->net, NETLINK_CB(skb).portid); 1734 1734 } 1735 1735 1736 - static int ctnetlink_done_list(struct netlink_callback *cb) 1737 - { 1738 - struct ctnetlink_list_dump_ctx *ctx = (void *)cb->ctx; 1739 - 1740 - if (ctx->last) 1741 - nf_ct_put(ctx->last); 1742 - 1743 - return 0; 1744 - } 1745 - 1746 1736 #ifdef CONFIG_NF_CONNTRACK_EVENTS 1747 1737 static int ctnetlink_dump_one_entry(struct sk_buff *skb, 1748 1738 struct netlink_callback *cb, ··· 1747 1757 if (l3proto && nf_ct_l3num(ct) != l3proto) 1748 1758 return 0; 1749 1759 1750 - if (ctx->last) { 1751 - if (ct != ctx->last) 1760 + if (ctx->last_id) { 1761 + if (ctnetlink_get_id(ct) != ctx->last_id) 1752 1762 return 0; 1753 1763 1754 - ctx->last = NULL; 1764 + ctx->last_id = 0; 1755 1765 } 1756 1766 1757 1767 /* We can't dump extension info for the unconfirmed ··· 1765 1775 cb->nlh->nlmsg_seq, 1766 1776 NFNL_MSG_TYPE(cb->nlh->nlmsg_type), 1767 1777 ct, dying, 0); 1768 - if (res < 0) { 1769 - if (!refcount_inc_not_zero(&ct->ct_general.use)) 1770 - return 0; 1771 - 1772 - ctx->last = ct; 1773 - } 1778 + if (res < 0) 1779 + ctx->last_id = ctnetlink_get_id(ct); 1774 1780 1775 1781 return res; 1776 1782 } ··· 1782 1796 ctnetlink_dump_dying(struct sk_buff *skb, struct netlink_callback *cb) 1783 1797 { 1784 1798 struct ctnetlink_list_dump_ctx *ctx = (void *)cb->ctx; 1785 - struct nf_conn *last = ctx->last; 1786 1799 #ifdef CONFIG_NF_CONNTRACK_EVENTS 1787 1800 const struct net *net = sock_net(skb->sk); 1788 1801 struct nf_conntrack_net_ecache *ecache_net; 1802 + unsigned long last_id = ctx->last_id; 1789 1803 struct nf_conntrack_tuple_hash *h; 1790 1804 struct hlist_nulls_node *n; 1791 1805 #endif ··· 1793 1807 if (ctx->done) 1794 1808 return 0; 1795 1809 1796 - ctx->last = NULL; 1810 + ctx->last_id = 0; 1797 1811 1798 1812 #ifdef CONFIG_NF_CONNTRACK_EVENTS 1799 1813 ecache_net = nf_conn_pernet_ecache(net); ··· 1804 1818 int res; 1805 1819 1806 1820 ct = nf_ct_tuplehash_to_ctrack(h); 1807 - if (last && last != ct) 1821 + if (last_id && last_id != ctnetlink_get_id(ct)) 1808 1822 continue; 1809 1823 1810 1824 res = ctnetlink_dump_one_entry(skb, cb, ct, true); 1811 1825 if (res < 0) { 1812 1826 spin_unlock_bh(&ecache_net->dying_lock); 1813 - nf_ct_put(last); 1814 1827 return skb->len; 1815 1828 } 1816 1829 1817 - nf_ct_put(last); 1818 - last = NULL; 1830 + last_id = 0; 1819 1831 } 1820 1832 1821 1833 spin_unlock_bh(&ecache_net->dying_lock); 1822 1834 #endif 1823 1835 ctx->done = true; 1824 - nf_ct_put(last); 1825 1836 1826 1837 return skb->len; 1827 1838 } ··· 1830 1847 if (info->nlh->nlmsg_flags & NLM_F_DUMP) { 1831 1848 struct netlink_dump_control c = { 1832 1849 .dump = ctnetlink_dump_dying, 1833 - .done = ctnetlink_done_list, 1834 1850 }; 1835 1851 return netlink_dump_start(info->sk, skb, info->nlh, &c); 1836 1852 } ··· 1844 1862 if (info->nlh->nlmsg_flags & NLM_F_DUMP) { 1845 1863 struct netlink_dump_control c = { 1846 1864 .dump = ctnetlink_dump_unconfirmed, 1847 - .done = ctnetlink_done_list, 1848 1865 }; 1849 1866 return netlink_dump_start(info->sk, skb, info->nlh, &c); 1850 1867 }