X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=lib%2Fringbuffer%2Fbackend.h;h=ed913325e2ddb70070392226cc9b27b39df18fad;hb=7801e9f45613e82205af194218f1910c4640855f;hp=541dc531ca76765e990635edc1c2a526e2ccdddb;hpb=4ea00e4f764eb18686121161a98e4ef442fed2c0;p=lttng-modules.git diff --git a/lib/ringbuffer/backend.h b/lib/ringbuffer/backend.h index 541dc531..ed913325 100644 --- a/lib/ringbuffer/backend.h +++ b/lib/ringbuffer/backend.h @@ -1,14 +1,26 @@ -#ifndef _LINUX_RING_BUFFER_BACKEND_H -#define _LINUX_RING_BUFFER_BACKEND_H +#ifndef _LIB_RING_BUFFER_BACKEND_H +#define _LIB_RING_BUFFER_BACKEND_H /* - * linux/ringbuffer/backend.h - * - * Copyright (C) 2008-2010 - Mathieu Desnoyers + * lib/ringbuffer/backend.h * * Ring buffer backend (API). * - * Dual LGPL v2.1/GPL v2 license. + * Copyright (C) 2010-2012 Mathieu Desnoyers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; only + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Credits to Steven Rostedt for proposing to use an extra-subbuffer owned by * the reader in flight recorder mode. @@ -22,6 +34,7 @@ #include #include #include +#include /* Internal helpers */ #include "../../wrapper/ringbuffer/backend_internal.h" @@ -149,7 +162,7 @@ void lib_ring_buffer_memset(const struct lib_ring_buffer_config *config, } /** - * lib_ring_buffer_copy_from_user - write userspace data to a buffer backend + * lib_ring_buffer_copy_from_user_inatomic - write userspace data to a buffer backend * @config : ring buffer instance configuration * @ctx: ring buffer context. (input arguments only) * @src : userspace source pointer to copy from @@ -158,10 +171,11 @@ void lib_ring_buffer_memset(const struct lib_ring_buffer_config *config, * This function copies "len" bytes of data from a userspace pointer to a * buffer backend, at the current context offset. This is more or less a buffer * backend-specific memcpy() operation. Calls the slow path - * (_ring_buffer_write_from_user) if copy is crossing a page boundary. + * (_ring_buffer_write_from_user_inatomic) if copy is crossing a page boundary. + * Disable the page fault handler to ensure we never try to take the mmap_sem. */ static inline -void lib_ring_buffer_copy_from_user(const struct lib_ring_buffer_config *config, +void lib_ring_buffer_copy_from_user_inatomic(const struct lib_ring_buffer_config *config, struct lib_ring_buffer_ctx *ctx, const void __user *src, size_t len) { @@ -173,6 +187,7 @@ void lib_ring_buffer_copy_from_user(const struct lib_ring_buffer_config *config, struct lib_ring_buffer_backend_pages *rpages; unsigned long sb_bindex, id; unsigned long ret; + mm_segment_t old_fs = get_fs(); offset &= chanb->buf_size - 1; sbidx = offset >> chanb->subbuf_size_order; @@ -185,11 +200,13 @@ void lib_ring_buffer_copy_from_user(const struct lib_ring_buffer_config *config, config->mode == RING_BUFFER_OVERWRITE && subbuffer_id_is_noref(config, id)); + set_fs(KERNEL_DS); + pagefault_disable(); if (unlikely(!access_ok(VERIFY_READ, src, len))) goto fill_buffer; if (likely(pagecpy == len)) { - ret = lib_ring_buffer_do_copy_from_user( + ret = lib_ring_buffer_do_copy_from_user_inatomic( rpages->p[index].virt + (offset & ~PAGE_MASK), src, len); if (unlikely(ret > 0)) { @@ -198,13 +215,17 @@ void lib_ring_buffer_copy_from_user(const struct lib_ring_buffer_config *config, goto fill_buffer; } } else { - _lib_ring_buffer_copy_from_user(bufb, offset, src, len, 0); + _lib_ring_buffer_copy_from_user_inatomic(bufb, offset, src, len, 0); } + pagefault_enable(); + set_fs(old_fs); ctx->buf_offset += len; return; fill_buffer: + pagefault_enable(); + set_fs(old_fs); /* * In the error path we call the slow path version to avoid * the pollution of static inline code. @@ -242,9 +263,4 @@ unsigned long lib_ring_buffer_get_records_unread( return records_unread; } -ssize_t lib_ring_buffer_file_splice_read(struct file *in, loff_t *ppos, - struct pipe_inode_info *pipe, - size_t len, unsigned int flags); -loff_t lib_ring_buffer_no_llseek(struct file *file, loff_t offset, int origin); - -#endif /* _LINUX_RING_BUFFER_BACKEND_H */ +#endif /* _LIB_RING_BUFFER_BACKEND_H */