Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 15532
b: refs/heads/master
c: 3305b80
h: refs/heads/master
v: v3
  • Loading branch information
Herbert Xu authored and David S. Miller committed Jan 3, 2006
1 parent 9d3c593 commit 90955d8
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 42 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 57cca05af1e20fdc65b55be52c042c234f86c866
refs/heads/master: 3305b80c214c642b89cd5c21af83bc91ec13f8bd
2 changes: 2 additions & 0 deletions trunk/include/linux/skbuff.h
Original file line number Diff line number Diff line change
Expand Up @@ -1239,6 +1239,8 @@ extern int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb,
int hlen,
struct iovec *iov);
extern void skb_free_datagram(struct sock *sk, struct sk_buff *skb);
extern void skb_kill_datagram(struct sock *sk, struct sk_buff *skb,
unsigned int flags);
extern unsigned int skb_checksum(const struct sk_buff *skb, int offset,
int len, unsigned int csum);
extern int skb_copy_bits(const struct sk_buff *skb, int offset,
Expand Down
36 changes: 36 additions & 0 deletions trunk/net/core/datagram.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#include <linux/rtnetlink.h>
#include <linux/poll.h>
#include <linux/highmem.h>
#include <linux/spinlock.h>

#include <net/protocol.h>
#include <linux/skbuff.h>
Expand Down Expand Up @@ -199,6 +200,41 @@ void skb_free_datagram(struct sock *sk, struct sk_buff *skb)
kfree_skb(skb);
}

/**
* skb_kill_datagram - Free a datagram skbuff forcibly
* @sk: socket
* @skb: datagram skbuff
* @flags: MSG_ flags
*
* This function frees a datagram skbuff that was received by
* skb_recv_datagram. The flags argument must match the one
* used for skb_recv_datagram.
*
* If the MSG_PEEK flag is set, and the packet is still on the
* receive queue of the socket, it will be taken off the queue
* before it is freed.
*
* This function currently only disables BH when acquiring the
* sk_receive_queue lock. Therefore it must not be used in a
* context where that lock is acquired in an IRQ context.
*/

void skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags)
{
if (flags & MSG_PEEK) {
spin_lock_bh(&sk->sk_receive_queue.lock);
if (skb == skb_peek(&sk->sk_receive_queue)) {
__skb_unlink(skb, &sk->sk_receive_queue);
atomic_dec(&skb->users);
}
spin_unlock_bh(&sk->sk_receive_queue.lock);
}

kfree_skb(skb);
}

EXPORT_SYMBOL(skb_kill_datagram);

/**
* skb_copy_datagram_iovec - Copy a datagram to an iovec.
* @skb: buffer to copy
Expand Down
15 changes: 1 addition & 14 deletions trunk/net/ipv4/udp.c
Original file line number Diff line number Diff line change
Expand Up @@ -846,20 +846,7 @@ static int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
csum_copy_err:
UDP_INC_STATS_BH(UDP_MIB_INERRORS);

/* Clear queue. */
if (flags&MSG_PEEK) {
int clear = 0;
spin_lock_bh(&sk->sk_receive_queue.lock);
if (skb == skb_peek(&sk->sk_receive_queue)) {
__skb_unlink(skb, &sk->sk_receive_queue);
clear = 1;
}
spin_unlock_bh(&sk->sk_receive_queue.lock);
if (clear)
kfree_skb(skb);
}

skb_free_datagram(sk, skb);
skb_kill_datagram(sk, skb, flags);

if (noblock)
return -EAGAIN;
Expand Down
16 changes: 3 additions & 13 deletions trunk/net/ipv6/raw.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <linux/icmpv6.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv6.h>
#include <linux/skbuff.h>
#include <asm/uaccess.h>
#include <asm/ioctls.h>
#include <asm/bug.h>
Expand Down Expand Up @@ -433,25 +434,14 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk,
return err;

csum_copy_err:
/* Clear queue. */
if (flags&MSG_PEEK) {
int clear = 0;
spin_lock_bh(&sk->sk_receive_queue.lock);
if (skb == skb_peek(&sk->sk_receive_queue)) {
__skb_unlink(skb, &sk->sk_receive_queue);
clear = 1;
}
spin_unlock_bh(&sk->sk_receive_queue.lock);
if (clear)
kfree_skb(skb);
}
skb_kill_datagram(sk, skb, flags);

/* Error for blocking case is chosen to masquerade
as some normal condition.
*/
err = (flags&MSG_DONTWAIT) ? -EAGAIN : -EHOSTUNREACH;
/* FIXME: increment a raw6 drops counter here */
goto out_free;
goto out;
}

static int rawv6_push_pending_frames(struct sock *sk, struct flowi *fl,
Expand Down
16 changes: 2 additions & 14 deletions trunk/net/ipv6/udp.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include <linux/ipv6.h>
#include <linux/icmpv6.h>
#include <linux/init.h>
#include <linux/skbuff.h>
#include <asm/uaccess.h>

#include <net/sock.h>
Expand Down Expand Up @@ -300,20 +301,7 @@ static int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk,
return err;

csum_copy_err:
/* Clear queue. */
if (flags&MSG_PEEK) {
int clear = 0;
spin_lock_bh(&sk->sk_receive_queue.lock);
if (skb == skb_peek(&sk->sk_receive_queue)) {
__skb_unlink(skb, &sk->sk_receive_queue);
clear = 1;
}
spin_unlock_bh(&sk->sk_receive_queue.lock);
if (clear)
kfree_skb(skb);
}

skb_free_datagram(sk, skb);
skb_kill_datagram(sk, skb, flags);

if (flags & MSG_DONTWAIT) {
UDP6_INC_STATS_USER(UDP_MIB_INERRORS);
Expand Down

0 comments on commit 90955d8

Please sign in to comment.