X-Git-Url: http://git.lttng.org/?a=blobdiff_plain;f=lib%2Fringbuffer%2Fbackend.h;h=b5c4fb264e4203ee72aef594705d04b18da7e4bd;hb=43b690e5e7b2b58166722a478767703886e91aaa;hp=2ce6ce9cd752508484123d4997d0f18481913b85;hpb=886d51a3d7ed5fa6b41d7f19b3e14ae6c535a44c;p=lttng-modules.git diff --git a/lib/ringbuffer/backend.h b/lib/ringbuffer/backend.h index 2ce6ce9c..b5c4fb26 100644 --- a/lib/ringbuffer/backend.h +++ b/lib/ringbuffer/backend.h @@ -34,6 +34,7 @@ #include #include #include +#include /* Internal helpers */ #include "../../wrapper/ringbuffer/backend_internal.h" @@ -95,6 +96,8 @@ void lib_ring_buffer_write(const struct lib_ring_buffer_config *config, struct lib_ring_buffer_backend_pages *rpages; unsigned long sb_bindex, id; + if (unlikely(!len)) + return; offset &= chanb->buf_size - 1; sbidx = offset >> chanb->subbuf_size_order; index = (offset & (chanb->subbuf_size - 1)) >> PAGE_SHIFT; @@ -141,6 +144,8 @@ void lib_ring_buffer_memset(const struct lib_ring_buffer_config *config, struct lib_ring_buffer_backend_pages *rpages; unsigned long sb_bindex, id; + if (unlikely(!len)) + return; offset &= chanb->buf_size - 1; sbidx = offset >> chanb->subbuf_size_order; index = (offset & (chanb->subbuf_size - 1)) >> PAGE_SHIFT; @@ -161,7 +166,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 @@ -170,10 +175,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) { @@ -185,7 +191,10 @@ 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(); + if (unlikely(!len)) + return; offset &= chanb->buf_size - 1; sbidx = offset >> chanb->subbuf_size_order; index = (offset & (chanb->subbuf_size - 1)) >> PAGE_SHIFT; @@ -197,11 +206,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)) { @@ -210,13 +221,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.