struct sk_buff *__skb_try_recv_from_queue(struct sock *sk,
                                          struct sk_buff_head *queue,
                                          unsigned int flags,
-                                         void (*destructor)(struct sock *sk,
-                                                          struct sk_buff *skb),
                                          int *off, int *err,
                                          struct sk_buff **last);
 struct sk_buff *__skb_try_recv_datagram(struct sock *sk,
                                        struct sk_buff_head *queue,
-                                       unsigned int flags,
-                                       void (*destructor)(struct sock *sk,
-                                                          struct sk_buff *skb),
-                                       int *off, int *err,
+                                       unsigned int flags, int *off, int *err,
                                        struct sk_buff **last);
 struct sk_buff *__skb_recv_datagram(struct sock *sk,
                                    struct sk_buff_head *sk_queue,
-                                   unsigned int flags,
-                                   void (*destructor)(struct sock *sk,
-                                                      struct sk_buff *skb),
-                                   int *off, int *err);
+                                   unsigned int flags, int *off, int *err);
 struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, int noblock,
                                  int *err);
 __poll_t datagram_poll(struct file *file, struct socket *sock,
 
 struct sk_buff *__skb_try_recv_from_queue(struct sock *sk,
                                          struct sk_buff_head *queue,
                                          unsigned int flags,
-                                         void (*destructor)(struct sock *sk,
-                                                          struct sk_buff *skb),
                                          int *off, int *err,
                                          struct sk_buff **last)
 {
                        refcount_inc(&skb->users);
                } else {
                        __skb_unlink(skb, queue);
-                       if (destructor)
-                               destructor(sk, skb);
                }
                *off = _off;
                return skb;
  *     @sk: socket
  *     @queue: socket queue from which to receive
  *     @flags: MSG\_ flags
- *     @destructor: invoked under the receive lock on successful dequeue
  *     @off: an offset in bytes to peek skb from. Returns an offset
  *           within an skb where data actually starts
  *     @err: error code returned
  */
 struct sk_buff *__skb_try_recv_datagram(struct sock *sk,
                                        struct sk_buff_head *queue,
-                                       unsigned int flags,
-                                       void (*destructor)(struct sock *sk,
-                                                          struct sk_buff *skb),
-                                       int *off, int *err,
+                                       unsigned int flags, int *off, int *err,
                                        struct sk_buff **last)
 {
        struct sk_buff *skb;
                 * However, this function was correct in any case. 8)
                 */
                spin_lock_irqsave(&queue->lock, cpu_flags);
-               skb = __skb_try_recv_from_queue(sk, queue, flags, destructor,
-                                               off, &error, last);
+               skb = __skb_try_recv_from_queue(sk, queue, flags, off, &error,
+                                               last);
                spin_unlock_irqrestore(&queue->lock, cpu_flags);
                if (error)
                        goto no_packet;
 
 struct sk_buff *__skb_recv_datagram(struct sock *sk,
                                    struct sk_buff_head *sk_queue,
-                                   unsigned int flags,
-                                   void (*destructor)(struct sock *sk,
-                                                      struct sk_buff *skb),
-                                   int *off, int *err)
+                                   unsigned int flags, int *off, int *err)
 {
        struct sk_buff *skb, *last;
        long timeo;
        timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
 
        do {
-               skb = __skb_try_recv_datagram(sk, sk_queue, flags, destructor,
-                                             off, err, &last);
+               skb = __skb_try_recv_datagram(sk, sk_queue, flags, off, err,
+                                             &last);
                if (skb)
                        return skb;
 
 
        return __skb_recv_datagram(sk, &sk->sk_receive_queue,
                                   flags | (noblock ? MSG_DONTWAIT : 0),
-                                  NULL, &off, err);
+                                  &off, err);
 }
 EXPORT_SYMBOL(skb_recv_datagram);
 
 
                error = -EAGAIN;
                do {
                        spin_lock_bh(&queue->lock);
-                       skb = __skb_try_recv_from_queue(sk, queue, flags,
-                                                       udp_skb_destructor,
-                                                       off, err, &last);
+                       skb = __skb_try_recv_from_queue(sk, queue, flags, off,
+                                                       err, &last);
                        if (skb) {
+                               if (!(flags & MSG_PEEK))
+                                       udp_skb_destructor(sk, skb);
                                spin_unlock_bh(&queue->lock);
                                return skb;
                        }
                        spin_lock(&sk_queue->lock);
                        skb_queue_splice_tail_init(sk_queue, queue);
 
-                       skb = __skb_try_recv_from_queue(sk, queue, flags,
-                                                       udp_skb_dtor_locked,
-                                                       off, err, &last);
+                       skb = __skb_try_recv_from_queue(sk, queue, flags, off,
+                                                       err, &last);
+                       if (skb && !(flags & MSG_PEEK))
+                               udp_skb_dtor_locked(sk, skb);
                        spin_unlock(&sk_queue->lock);
                        spin_unlock_bh(&queue->lock);
                        if (skb)
 
 
                skip = sk_peek_offset(sk, flags);
                skb = __skb_try_recv_datagram(sk, &sk->sk_receive_queue, flags,
-                                             scm_stat_del, &skip, &err, &last);
-               if (skb)
+                                             &skip, &err, &last);
+               if (skb) {
+                       if (!(flags & MSG_PEEK))
+                               scm_stat_del(sk, skb);
                        break;
+               }
 
                mutex_unlock(&u->iolock);
 
 
 
        flags |= nonblock ? MSG_DONTWAIT : 0;
 
-       skb = __skb_recv_datagram(sk, &ctx->ike_queue, flags, NULL, &off, &err);
+       skb = __skb_recv_datagram(sk, &ctx->ike_queue, flags, &off, &err);
        if (!skb)
                return err;