]> nv-tegra.nvidia Code Review - linux-2.6.git/blobdiff - net/packet/af_packet.c
[NET]: Add a dev_ioctl() fallback to sock_ioctl()
[linux-2.6.git] / net / packet / af_packet.c
index ee865d88183bb930d4d05faf01e584263a80f51f..f69e5ed9bd060b55f29212938d6f97efb27061bf 100644 (file)
@@ -251,10 +251,10 @@ static void packet_sock_destruct(struct sock *sk)
 }
 
 
-static struct proto_ops packet_ops;
+static const struct proto_ops packet_ops;
 
 #ifdef CONFIG_SOCK_PACKET
-static struct proto_ops packet_ops_spkt;
+static const struct proto_ops packet_ops_spkt;
 
 static int packet_rcv_spkt(struct sk_buff *skb, struct net_device *dev,  struct packet_type *pt, struct net_device *orig_dev)
 {
@@ -654,8 +654,8 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
                __net_timestamp(skb);
                sock_enable_timestamp(sk);
        }
-       h->tp_sec = skb_tv_base.tv_sec + skb->tstamp.off_sec;
-       h->tp_usec = skb_tv_base.tv_usec + skb->tstamp.off_usec;
+       h->tp_sec = skb->tstamp.off_sec;
+       h->tp_usec = skb->tstamp.off_usec;
 
        sll = (struct sockaddr_ll*)((u8*)h + TPACKET_ALIGN(sizeof(*h)));
        sll->sll_halen = 0;
@@ -761,12 +761,6 @@ static int packet_sendmsg(struct kiocb *iocb, struct socket *sock,
        if (dev->hard_header) {
                int res;
                err = -EINVAL;
-               if (saddr) {
-                       if (saddr->sll_halen != dev->addr_len)
-                               goto out_free;
-                       if (saddr->sll_hatype != dev->type)
-                               goto out_free;
-               }
                res = dev->hard_header(skb, dev, ntohs(proto), addr, NULL, len);
                if (sock->type != SOCK_DGRAM) {
                        skb->tail = skb->data;
@@ -1527,7 +1521,7 @@ static int packet_ioctl(struct socket *sock, unsigned int cmd,
 #endif
 
                default:
-                       return dev_ioctl(cmd, (void __user *)arg);
+                       return -ENOIOCTLCMD;
        }
        return 0;
 }
@@ -1593,23 +1587,47 @@ static inline struct page *pg_vec_endpage(char *one_pg_vec, unsigned int order)
        return virt_to_page(one_pg_vec + (PAGE_SIZE << order) - 1);
 }
 
-static void free_pg_vec(char **pg_vec, unsigned order, unsigned len)
+static void free_pg_vec(char **pg_vec, unsigned int order, unsigned int len)
 {
        int i;
 
-       for (i=0; i<len; i++) {
-               if (pg_vec[i]) {
-                       struct page *page, *pend;
-
-                       pend = pg_vec_endpage(pg_vec[i], order);
-                       for (page = virt_to_page(pg_vec[i]); page <= pend; page++)
-                               ClearPageReserved(page);
-                       free_pages((unsigned long)pg_vec[i], order);
-               }
+       for (i = 0; i < len; i++) {
+               if (likely(pg_vec[i]))
+                       free_pages((unsigned long) pg_vec[i], order);
        }
        kfree(pg_vec);
 }
 
+static inline char *alloc_one_pg_vec_page(unsigned long order)
+{
+       return (char *) __get_free_pages(GFP_KERNEL | __GFP_COMP | __GFP_ZERO,
+                                        order);
+}
+
+static char **alloc_pg_vec(struct tpacket_req *req, int order)
+{
+       unsigned int block_nr = req->tp_block_nr;
+       char **pg_vec;
+       int i;
+
+       pg_vec = kzalloc(block_nr * sizeof(char *), GFP_KERNEL);
+       if (unlikely(!pg_vec))
+               goto out;
+
+       for (i = 0; i < block_nr; i++) {
+               pg_vec[i] = alloc_one_pg_vec_page(order);
+               if (unlikely(!pg_vec[i]))
+                       goto out_free_pgvec;
+       }
+
+out:
+       return pg_vec;
+
+out_free_pgvec:
+       free_pg_vec(pg_vec, order, block_nr);
+       pg_vec = NULL;
+       goto out;
+}
 
 static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing)
 {
@@ -1623,64 +1641,46 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing
 
                /* Sanity tests and some calculations */
 
-               if (po->pg_vec)
+               if (unlikely(po->pg_vec))
                        return -EBUSY;
 
-               if ((int)req->tp_block_size <= 0)
+               if (unlikely((int)req->tp_block_size <= 0))
                        return -EINVAL;
-               if (req->tp_block_size&(PAGE_SIZE-1))
+               if (unlikely(req->tp_block_size & (PAGE_SIZE - 1)))
                        return -EINVAL;
-               if (req->tp_frame_size < TPACKET_HDRLEN)
+               if (unlikely(req->tp_frame_size < TPACKET_HDRLEN))
                        return -EINVAL;
-               if (req->tp_frame_size&(TPACKET_ALIGNMENT-1))
+               if (unlikely(req->tp_frame_size & (TPACKET_ALIGNMENT - 1)))
                        return -EINVAL;
 
                po->frames_per_block = req->tp_block_size/req->tp_frame_size;
-               if (po->frames_per_block <= 0)
+               if (unlikely(po->frames_per_block <= 0))
                        return -EINVAL;
-               if (po->frames_per_block*req->tp_block_nr != req->tp_frame_nr)
+               if (unlikely((po->frames_per_block * req->tp_block_nr) !=
+                            req->tp_frame_nr))
                        return -EINVAL;
-               /* OK! */
-
-               /* Allocate page vector */
-               while ((PAGE_SIZE<<order) < req->tp_block_size)
-                       order++;
 
                err = -ENOMEM;
-
-               pg_vec = kmalloc(req->tp_block_nr*sizeof(char *), GFP_KERNEL);
-               if (pg_vec == NULL)
+               order = get_order(req->tp_block_size);
+               pg_vec = alloc_pg_vec(req, order);
+               if (unlikely(!pg_vec))
                        goto out;
-               memset(pg_vec, 0, req->tp_block_nr*sizeof(char **));
-
-               for (i=0; i<req->tp_block_nr; i++) {
-                       struct page *page, *pend;
-                       pg_vec[i] = (char *)__get_free_pages(GFP_KERNEL, order);
-                       if (!pg_vec[i])
-                               goto out_free_pgvec;
-
-                       pend = pg_vec_endpage(pg_vec[i], order);
-                       for (page = virt_to_page(pg_vec[i]); page <= pend; page++)
-                               SetPageReserved(page);
-               }
-               /* Page vector is allocated */
 
                l = 0;
-               for (i=0; i<req->tp_block_nr; i++) {
+               for (i = 0; i < req->tp_block_nr; i++) {
                        char *ptr = pg_vec[i];
                        struct tpacket_hdr *header;
                        int k;
 
-                       for (k=0; k<po->frames_per_block; k++) {
-                               
-                               header = (struct tpacket_hdr*)ptr;
+                       for (k = 0; k < po->frames_per_block; k++) {
+                               header = (struct tpacket_hdr *) ptr;
                                header->tp_status = TP_STATUS_KERNEL;
                                ptr += req->tp_frame_size;
                        }
                }
                /* Done */
        } else {
-               if (req->tp_frame_nr)
+               if (unlikely(req->tp_frame_nr))
                        return -EINVAL;
        }
 
@@ -1707,7 +1707,7 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing
 
                spin_lock_bh(&sk->sk_receive_queue.lock);
                pg_vec = XC(po->pg_vec, pg_vec);
-               po->frame_max = req->tp_frame_nr-1;
+               po->frame_max = (req->tp_frame_nr - 1);
                po->head = 0;
                po->frame_size = req->tp_frame_size;
                spin_unlock_bh(&sk->sk_receive_queue.lock);
@@ -1734,7 +1734,6 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing
 
        release_sock(sk);
 
-out_free_pgvec:
        if (pg_vec)
                free_pg_vec(pg_vec, order, req->tp_block_nr);
 out:
@@ -1761,17 +1760,19 @@ static int packet_mmap(struct file *file, struct socket *sock, struct vm_area_st
        if (size != po->pg_vec_len*po->pg_vec_pages*PAGE_SIZE)
                goto out;
 
-       atomic_inc(&po->mapped);
        start = vma->vm_start;
-       err = -EAGAIN;
-       for (i=0; i<po->pg_vec_len; i++) {
-               if (remap_pfn_range(vma, start,
-                                    __pa(po->pg_vec[i]) >> PAGE_SHIFT,
-                                    po->pg_vec_pages*PAGE_SIZE,
-                                    vma->vm_page_prot))
-                       goto out;
-               start += po->pg_vec_pages*PAGE_SIZE;
+       for (i = 0; i < po->pg_vec_len; i++) {
+               struct page *page = virt_to_page(po->pg_vec[i]);
+               int pg_num;
+
+               for (pg_num = 0; pg_num < po->pg_vec_pages; pg_num++, page++) {
+                       err = vm_insert_page(vma, start, page);
+                       if (unlikely(err))
+                               goto out;
+                       start += PAGE_SIZE;
+               }
        }
+       atomic_inc(&po->mapped);
        vma->vm_ops = &packet_mmap_ops;
        err = 0;
 
@@ -1783,7 +1784,7 @@ out:
 
 
 #ifdef CONFIG_SOCK_PACKET
-static struct proto_ops packet_ops_spkt = {
+static const struct proto_ops packet_ops_spkt = {
        .family =       PF_PACKET,
        .owner =        THIS_MODULE,
        .release =      packet_release,
@@ -1805,7 +1806,7 @@ static struct proto_ops packet_ops_spkt = {
 };
 #endif
 
-static struct proto_ops packet_ops = {
+static const struct proto_ops packet_ops = {
        .family =       PF_PACKET,
        .owner =        THIS_MODULE,
        .release =      packet_release,