diff options
author | Richard Cochran <richardcochran@gmail.com> | 2012-11-26 05:44:34 +0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-11-27 02:22:14 +0400 |
commit | c7ec0badcc54508d3ab052bb425cc677521a89be (patch) | |
tree | 9f34a5b1194510dba1bb1ff8e294c5726391e2f3 /drivers | |
parent | cfd1979e81c72386cb4dad51a957d6f154f23525 (diff) | |
download | linux-c7ec0badcc54508d3ab052bb425cc677521a89be.tar.xz |
ptp: reduce stack usage when reading external time stamps
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ptp/ptp_chardev.c | 22 |
1 files changed, 17 insertions, 5 deletions
diff --git a/drivers/ptp/ptp_chardev.c b/drivers/ptp/ptp_chardev.c index 4f8ae8057a7e..9d7542efb175 100644 --- a/drivers/ptp/ptp_chardev.c +++ b/drivers/ptp/ptp_chardev.c @@ -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; } |