From 1bc4ee4088c9a502db0e9c87f675e61e57fa1734 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sun, 5 Jul 2009 19:45:48 +0000 Subject: [PATCH] sctp: fix warning at inet_sock_destruct() while release sctp socket Commit 'net: Move rx skb_orphan call to where needed' broken sctp protocol with warning at inet_sock_destruct(). Actually, sctp can do this right with sctp_sock_rfree_frag() and sctp_skb_set_owner_r_frag() pair. sctp_sock_rfree_frag(skb); sctp_skb_set_owner_r_frag(skb, newsk); This patch not revert the commit d55d87fdff8252d0e2f7c28c2d443aee17e9d70f, instead remove the sctp_sock_rfree_frag() function. ------------[ cut here ]------------ WARNING: at net/ipv4/af_inet.c:151 inet_sock_destruct+0xe0/0x142() Modules linked in: sctp ipv6 dm_mirror dm_region_hash dm_log dm_multipath scsi_mod ext3 jbd uhci_hcd ohci_hcd ehci_hcd [last unloaded: scsi_wait_scan] Pid: 1808, comm: sctp_test Not tainted 2.6.31-rc2 #40 Call Trace: [] warn_slowpath_common+0x6a/0x81 [] ? inet_sock_destruct+0xe0/0x142 [] warn_slowpath_null+0x12/0x15 [] inet_sock_destruct+0xe0/0x142 [] __sk_free+0x19/0xcc [] sk_free+0x18/0x1a [] sctp_close+0x192/0x1a1 [sctp] [] inet_release+0x47/0x4d [] sock_release+0x19/0x5e [] sock_close+0x21/0x25 [] __fput+0xde/0x189 [] fput+0x18/0x1a [] filp_close+0x56/0x60 [] put_files_struct+0x5d/0xa1 [] exit_files+0x39/0x3d [] do_exit+0x1a5/0x5dd [] ? d_kill+0x35/0x3b [] ? dequeue_signal+0xa6/0x115 [] do_group_exit+0x63/0x8a [] get_signal_to_deliver+0x2e1/0x2f9 [] do_notify_resume+0x7c/0x6b5 [] ? autoremove_wake_function+0x0/0x34 [] ? __d_free+0x3d/0x40 [] ? d_free+0x2a/0x3c [] ? vfs_write+0x103/0x117 [] ? sys_socketcall+0x178/0x182 [] work_notifysig+0x13/0x19 ---[ end trace 9db92c463e789fba ]--- Signed-off-by: Wei Yongjun Acked-by: Herbert Xu Acked-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/socket.c | 25 ++----------------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 35ba035970a2..971890dbfea0 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -6652,21 +6652,6 @@ static void sctp_wait_for_close(struct sock *sk, long timeout) finish_wait(sk->sk_sleep, &wait); } -static void sctp_sock_rfree_frag(struct sk_buff *skb) -{ - struct sk_buff *frag; - - if (!skb->data_len) - goto done; - - /* Don't forget the fragments. */ - skb_walk_frags(skb, frag) - sctp_sock_rfree_frag(frag); - -done: - sctp_sock_rfree(skb); -} - static void sctp_skb_set_owner_r_frag(struct sk_buff *skb, struct sock *sk) { struct sk_buff *frag; @@ -6776,7 +6761,6 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, sctp_skb_for_each(skb, &oldsk->sk_receive_queue, tmp) { event = sctp_skb2event(skb); if (event->asoc == assoc) { - sctp_sock_rfree_frag(skb); __skb_unlink(skb, &oldsk->sk_receive_queue); __skb_queue_tail(&newsk->sk_receive_queue, skb); sctp_skb_set_owner_r_frag(skb, newsk); @@ -6807,7 +6791,6 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, sctp_skb_for_each(skb, &oldsp->pd_lobby, tmp) { event = sctp_skb2event(skb); if (event->asoc == assoc) { - sctp_sock_rfree_frag(skb); __skb_unlink(skb, &oldsp->pd_lobby); __skb_queue_tail(queue, skb); sctp_skb_set_owner_r_frag(skb, newsk); @@ -6822,15 +6805,11 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, } - sctp_skb_for_each(skb, &assoc->ulpq.reasm, tmp) { - sctp_sock_rfree_frag(skb); + sctp_skb_for_each(skb, &assoc->ulpq.reasm, tmp) sctp_skb_set_owner_r_frag(skb, newsk); - } - sctp_skb_for_each(skb, &assoc->ulpq.lobby, tmp) { - sctp_sock_rfree_frag(skb); + sctp_skb_for_each(skb, &assoc->ulpq.lobby, tmp) sctp_skb_set_owner_r_frag(skb, newsk); - } /* Set the type of socket to indicate that it is peeled off from the * original UDP-style socket or created with the accept() call on a -- 2.30.2