diff options
Diffstat (limited to 'kernel/trace/trace.c')
| -rw-r--r-- | kernel/trace/trace.c | 37 | 
1 files changed, 22 insertions, 15 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 9d28476a985..a884c09006c 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -3277,19 +3277,13 @@ static int tracing_buffers_open(struct inode *inode, struct file *filp)  	info->tr	= &global_trace;  	info->cpu	= cpu; -	info->spare	= ring_buffer_alloc_read_page(info->tr->buffer); +	info->spare	= NULL;  	/* Force reading ring buffer for first read */  	info->read	= (unsigned int)-1; -	if (!info->spare) -		goto out;  	filp->private_data = info; -	return 0; - - out: -	kfree(info); -	return -ENOMEM; +	return nonseekable_open(inode, filp);  }  static ssize_t @@ -3304,6 +3298,11 @@ tracing_buffers_read(struct file *filp, char __user *ubuf,  	if (!count)  		return 0; +	if (!info->spare) +		info->spare = ring_buffer_alloc_read_page(info->tr->buffer); +	if (!info->spare) +		return -ENOMEM; +  	/* Do we have previous read data to read? */  	if (info->read < PAGE_SIZE)  		goto read; @@ -3342,7 +3341,8 @@ static int tracing_buffers_release(struct inode *inode, struct file *file)  {  	struct ftrace_buffer_info *info = file->private_data; -	ring_buffer_free_read_page(info->tr->buffer, info->spare); +	if (info->spare) +		ring_buffer_free_read_page(info->tr->buffer, info->spare);  	kfree(info);  	return 0; @@ -3428,14 +3428,19 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,  	int size, i;  	size_t ret; -	/* -	 * We can't seek on a buffer input -	 */ -	if (unlikely(*ppos)) -		return -ESPIPE; +	if (*ppos & (PAGE_SIZE - 1)) { +		WARN_ONCE(1, "Ftrace: previous read must page-align\n"); +		return -EINVAL; +	} +	if (len & (PAGE_SIZE - 1)) { +		WARN_ONCE(1, "Ftrace: splice_read should page-align\n"); +		if (len < PAGE_SIZE) +			return -EINVAL; +		len &= PAGE_MASK; +	} -	for (i = 0; i < PIPE_BUFFERS && len; i++, len -= size) { +	for (i = 0; i < PIPE_BUFFERS && len; i++, len -= PAGE_SIZE) {  		struct page *page;  		int r; @@ -3443,6 +3448,7 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,  		if (!ref)  			break; +		ref->ref = 1;  		ref->buffer = info->tr->buffer;  		ref->page = ring_buffer_alloc_read_page(ref->buffer);  		if (!ref->page) { @@ -3474,6 +3480,7 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,  		spd.partial[i].offset = 0;  		spd.partial[i].private = (unsigned long)ref;  		spd.nr_pages++; +		*ppos += PAGE_SIZE;  	}  	spd.nr_pages = i;  |