ptp: reduce stack usage when reading external time stamps
authorRichard Cochran <richardcochran@gmail.com>
Mon, 26 Nov 2012 01:44:34 +0000 (01:44 +0000)
committerDavid S. Miller <davem@davemloft.net>
Mon, 26 Nov 2012 22:22:14 +0000 (17:22 -0500)
This patch removes the large buffer from the stack of the read file
operation and replaces it with a kmalloced buffer.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/ptp/ptp_chardev.c

index 4f8ae8057a7e2a6e1e72cc9b607e4f21e8f5c195..9d7542efb1750535246a4d276a2b346dad06c741 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/posix-clock.h>
 #include <linux/poll.h>
 #include <linux/sched.h>
+#include <linux/slab.h>
 
 #include "ptp_private.h"
 
@@ -136,20 +137,23 @@ unsigned int ptp_poll(struct posix_clock *pc, struct file *fp, poll_table *wait)
        return queue_cnt(&ptp->tsevq) ? POLLIN : 0;
 }
 
+#define EXTTS_BUFSIZE (PTP_BUF_TIMESTAMPS * sizeof(struct ptp_extts_event))
+
 ssize_t ptp_read(struct posix_clock *pc,
                 uint rdflags, char __user *buf, size_t cnt)
 {
        struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
        struct timestamp_event_queue *queue = &ptp->tsevq;
-       struct ptp_extts_event event[PTP_BUF_TIMESTAMPS];
+       struct ptp_extts_event *event;
        unsigned long flags;
        size_t qcnt, i;
+       int result;
 
        if (cnt % sizeof(struct ptp_extts_event) != 0)
                return -EINVAL;
 
-       if (cnt > sizeof(event))
-               cnt = sizeof(event);
+       if (cnt > EXTTS_BUFSIZE)
+               cnt = EXTTS_BUFSIZE;
 
        cnt = cnt / sizeof(struct ptp_extts_event);
 
@@ -167,6 +171,12 @@ ssize_t ptp_read(struct posix_clock *pc,
                return -ENODEV;
        }
 
+       event = kmalloc(EXTTS_BUFSIZE, GFP_KERNEL);
+       if (!event) {
+               mutex_unlock(&ptp->tsevq_mux);
+               return -ENOMEM;
+       }
+
        spin_lock_irqsave(&queue->lock, flags);
 
        qcnt = queue_cnt(queue);
@@ -185,8 +195,10 @@ ssize_t ptp_read(struct posix_clock *pc,
 
        mutex_unlock(&ptp->tsevq_mux);
 
+       result = cnt;
        if (copy_to_user(buf, event, cnt))
-               return -EFAULT;
+               result = -EFAULT;
 
-       return cnt;
+       kfree(event);
+       return result;
 }