X-Git-Url: http://git.lttng.org/?a=blobdiff_plain;f=lib%2Fringbuffer%2Fring_buffer_backend.c;h=27554a1e46b447464b81f48c48d02eb87906a490;hb=df388b78db6422e49c9f628a8fa36d60092b35e1;hp=f9ec3d1e2327b3f16e79f1c8e0c47e576b495e38;hpb=f3bc08c50e1b302bceea699027d889fd6d9af525;p=lttng-modules.git diff --git a/lib/ringbuffer/ring_buffer_backend.c b/lib/ringbuffer/ring_buffer_backend.c index f9ec3d1e..27554a1e 100644 --- a/lib/ringbuffer/ring_buffer_backend.c +++ b/lib/ringbuffer/ring_buffer_backend.c @@ -1,12 +1,23 @@ /* * ring_buffer_backend.c * - * Copyright (C) 2005-2010 - Mathieu Desnoyers + * Copyright (C) 2005-2012 Mathieu Desnoyers * - * Dual LGPL v2.1/GPL v2 license. + * 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 */ -#include #include #include #include @@ -16,10 +27,12 @@ #include #include #include +#include -#include "../../wrapper/ringbuffer/config.h" -#include "../../wrapper/ringbuffer/backend.h" -#include "../../wrapper/ringbuffer/frontend.h" +#include /* for wrapper_vmalloc_sync_all() */ +#include +#include +#include /** * lib_ring_buffer_backend_allocate - allocate a channel buffer @@ -40,7 +53,6 @@ int lib_ring_buffer_backend_allocate(const struct lib_ring_buffer_config *config unsigned long subbuf_size, mmap_offset = 0; unsigned long num_subbuf_alloc; struct page **pages; - void **virt; unsigned long i; num_pages = size >> PAGE_SHIFT; @@ -53,31 +65,25 @@ int lib_ring_buffer_backend_allocate(const struct lib_ring_buffer_config *config num_subbuf_alloc++; } - pages = kmalloc_node(ALIGN(sizeof(*pages) * num_pages, + pages = vmalloc_node(ALIGN(sizeof(*pages) * num_pages, 1 << INTERNODE_CACHE_SHIFT), - GFP_KERNEL, cpu_to_node(max(bufb->cpu, 0))); + cpu_to_node(max(bufb->cpu, 0))); if (unlikely(!pages)) goto pages_error; - virt = kmalloc_node(ALIGN(sizeof(*virt) * num_pages, - 1 << INTERNODE_CACHE_SHIFT), - GFP_KERNEL, cpu_to_node(max(bufb->cpu, 0))); - if (unlikely(!virt)) - goto virt_error; - bufb->array = kmalloc_node(ALIGN(sizeof(*bufb->array) * num_subbuf_alloc, 1 << INTERNODE_CACHE_SHIFT), - GFP_KERNEL, cpu_to_node(max(bufb->cpu, 0))); + GFP_KERNEL | __GFP_NOWARN, + cpu_to_node(max(bufb->cpu, 0))); if (unlikely(!bufb->array)) goto array_error; for (i = 0; i < num_pages; i++) { pages[i] = alloc_pages_node(cpu_to_node(max(bufb->cpu, 0)), - GFP_KERNEL | __GFP_ZERO, 0); + GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO, 0); if (unlikely(!pages[i])) goto depopulate; - virt[i] = page_address(pages[i]); } bufb->num_pages_per_subbuf = num_pages_per_subbuf; @@ -89,7 +95,8 @@ int lib_ring_buffer_backend_allocate(const struct lib_ring_buffer_config *config sizeof(struct lib_ring_buffer_backend_page) * num_pages_per_subbuf, 1 << INTERNODE_CACHE_SHIFT), - GFP_KERNEL, cpu_to_node(max(bufb->cpu, 0))); + GFP_KERNEL | __GFP_NOWARN, + cpu_to_node(max(bufb->cpu, 0))); if (!bufb->array[i]) goto free_array; } @@ -99,7 +106,8 @@ int lib_ring_buffer_backend_allocate(const struct lib_ring_buffer_config *config sizeof(struct lib_ring_buffer_backend_subbuffer) * num_subbuf, 1 << INTERNODE_CACHE_SHIFT), - GFP_KERNEL, cpu_to_node(max(bufb->cpu, 0))); + GFP_KERNEL | __GFP_NOWARN, + cpu_to_node(max(bufb->cpu, 0))); if (unlikely(!bufb->buf_wsb)) goto free_array; @@ -113,12 +121,22 @@ int lib_ring_buffer_backend_allocate(const struct lib_ring_buffer_config *config else bufb->buf_rsb.id = subbuffer_id(config, 0, 1, 0); + /* Allocate subbuffer packet counter table */ + bufb->buf_cnt = kzalloc_node(ALIGN( + sizeof(struct lib_ring_buffer_backend_counts) + * num_subbuf, + 1 << INTERNODE_CACHE_SHIFT), + GFP_KERNEL | __GFP_NOWARN, + cpu_to_node(max(bufb->cpu, 0))); + if (unlikely(!bufb->buf_cnt)) + goto free_wsb; + /* Assign pages to page index */ for (i = 0; i < num_subbuf_alloc; i++) { for (j = 0; j < num_pages_per_subbuf; j++) { CHAN_WARN_ON(chanb, page_idx > num_pages); - bufb->array[i]->p[j].virt = virt[page_idx]; - bufb->array[i]->p[j].page = pages[page_idx]; + bufb->array[i]->p[j].virt = page_address(pages[page_idx]); + bufb->array[i]->p[j].pfn = page_to_pfn(pages[page_idx]); page_idx++; } if (config->output == RING_BUFFER_MMAP) { @@ -131,11 +149,12 @@ int lib_ring_buffer_backend_allocate(const struct lib_ring_buffer_config *config * If kmalloc ever uses vmalloc underneath, make sure the buffer pages * will not fault. */ - vmalloc_sync_all(); - kfree(virt); - kfree(pages); + wrapper_vmalloc_sync_all(); + vfree(pages); return 0; +free_wsb: + kfree(bufb->buf_wsb); free_array: for (i = 0; (i < num_subbuf_alloc && bufb->array[i]); i++) kfree(bufb->array[i]); @@ -145,9 +164,7 @@ depopulate: __free_page(pages[i]); kfree(bufb->array); array_error: - kfree(virt); -virt_error: - kfree(pages); + vfree(pages); pages_error: return -ENOMEM; } @@ -155,7 +172,7 @@ pages_error: int lib_ring_buffer_backend_create(struct lib_ring_buffer_backend *bufb, struct channel_backend *chanb, int cpu) { - const struct lib_ring_buffer_config *config = chanb->config; + const struct lib_ring_buffer_config *config = &chanb->config; bufb->chan = container_of(chanb, struct channel, backend); bufb->cpu = cpu; @@ -175,9 +192,10 @@ void lib_ring_buffer_backend_free(struct lib_ring_buffer_backend *bufb) num_subbuf_alloc++; kfree(bufb->buf_wsb); + kfree(bufb->buf_cnt); for (i = 0; i < num_subbuf_alloc; i++) { for (j = 0; j < bufb->num_pages_per_subbuf; j++) - __free_page(bufb->array[i]->p[j].page); + __free_page(pfn_to_page(bufb->array[i]->p[j].pfn)); kfree(bufb->array[i]); } kfree(bufb->array); @@ -187,7 +205,7 @@ void lib_ring_buffer_backend_free(struct lib_ring_buffer_backend *bufb) void lib_ring_buffer_backend_reset(struct lib_ring_buffer_backend *bufb) { struct channel_backend *chanb = &bufb->chan->backend; - const struct lib_ring_buffer_config *config = chanb->config; + const struct lib_ring_buffer_config *config = &chanb->config; unsigned long num_subbuf_alloc; unsigned int i; @@ -221,7 +239,7 @@ void lib_ring_buffer_backend_reset(struct lib_ring_buffer_backend *bufb) void channel_backend_reset(struct channel_backend *chanb) { struct channel *chan = container_of(chanb, struct channel, backend); - const struct lib_ring_buffer_config *config = chanb->config; + const struct lib_ring_buffer_config *config = &chanb->config; /* * Don't reset buf_size, subbuf_size, subbuf_size_order, @@ -241,14 +259,14 @@ void channel_backend_reset(struct channel_backend *chanb) * Returns the success/failure of the operation. (%NOTIFY_OK, %NOTIFY_BAD) */ static -int __cpuinit lib_ring_buffer_cpu_hp_callback(struct notifier_block *nb, +int lib_ring_buffer_cpu_hp_callback(struct notifier_block *nb, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long)hcpu; struct channel_backend *chanb = container_of(nb, struct channel_backend, cpu_hp_notifier); - const struct lib_ring_buffer_config *config = chanb->config; + const struct lib_ring_buffer_config *config = &chanb->config; struct lib_ring_buffer *buf; int ret; @@ -307,17 +325,24 @@ int channel_backend_init(struct channel_backend *chanb, if (!name) return -EPERM; - if (!(subbuf_size && num_subbuf)) - return -EPERM; - /* Check that the subbuffer size is larger than a page. */ - CHAN_WARN_ON(chanb, subbuf_size < PAGE_SIZE); + if (subbuf_size < PAGE_SIZE) + return -EINVAL; /* - * Make sure the number of subbuffers and subbuffer size are power of 2. + * Make sure the number of subbuffers and subbuffer size are + * power of 2 and nonzero. + */ + if (!subbuf_size || (subbuf_size & (subbuf_size - 1))) + return -EINVAL; + if (!num_subbuf || (num_subbuf & (num_subbuf - 1))) + return -EINVAL; + /* + * Overwrite mode buffers require at least 2 subbuffers per + * buffer. */ - CHAN_WARN_ON(chanb, hweight32(subbuf_size) != 1); - CHAN_WARN_ON(chanb, hweight32(num_subbuf) != 1); + if (config->mode == RING_BUFFER_OVERWRITE && num_subbuf < 2) + return -EINVAL; ret = subbuffer_id_check_index(config, num_subbuf); if (ret) @@ -333,7 +358,7 @@ int channel_backend_init(struct channel_backend *chanb, (config->mode == RING_BUFFER_OVERWRITE) ? 1 : 0; chanb->num_subbuf = num_subbuf; strlcpy(chanb->name, name, NAME_MAX); - chanb->config = config; + memcpy(&chanb->config, config, sizeof(chanb->config)); if (config->alloc == RING_BUFFER_ALLOC_PER_CPU) { if (!zalloc_cpumask_var(&chanb->cpumask, GFP_KERNEL)) @@ -402,6 +427,7 @@ free_bufs: } #ifdef CONFIG_HOTPLUG_CPU put_online_cpus(); + unregister_hotcpu_notifier(&chanb->cpu_hp_notifier); #endif free_percpu(chanb->buf); } else @@ -420,7 +446,7 @@ free_cpumask: */ void channel_backend_unregister_notifiers(struct channel_backend *chanb) { - const struct lib_ring_buffer_config *config = chanb->config; + const struct lib_ring_buffer_config *config = &chanb->config; if (config->alloc == RING_BUFFER_ALLOC_PER_CPU) unregister_hotcpu_notifier(&chanb->cpu_hp_notifier); @@ -434,7 +460,7 @@ void channel_backend_unregister_notifiers(struct channel_backend *chanb) */ void channel_backend_free(struct channel_backend *chanb) { - const struct lib_ring_buffer_config *config = chanb->config; + const struct lib_ring_buffer_config *config = &chanb->config; unsigned int i; if (config->alloc == RING_BUFFER_ALLOC_PER_CPU) { @@ -465,10 +491,10 @@ void channel_backend_free(struct channel_backend *chanb) * @pagecpy : page size copied so far */ void _lib_ring_buffer_write(struct lib_ring_buffer_backend *bufb, size_t offset, - const void *src, size_t len, ssize_t pagecpy) + const void *src, size_t len, size_t pagecpy) { struct channel_backend *chanb = &bufb->chan->backend; - const struct lib_ring_buffer_config *config = chanb->config; + const struct lib_ring_buffer_config *config = &chanb->config; size_t sbidx, index; struct lib_ring_buffer_backend_pages *rpages; unsigned long sb_bindex, id; @@ -500,6 +526,272 @@ void _lib_ring_buffer_write(struct lib_ring_buffer_backend *bufb, size_t offset, } EXPORT_SYMBOL_GPL(_lib_ring_buffer_write); + +/** + * lib_ring_buffer_memset - write len bytes of c to a ring_buffer buffer. + * @bufb : buffer backend + * @offset : offset within the buffer + * @c : the byte to write + * @len : length to write + * @pagecpy : page size copied so far + */ +void _lib_ring_buffer_memset(struct lib_ring_buffer_backend *bufb, + size_t offset, + int c, size_t len, size_t pagecpy) +{ + struct channel_backend *chanb = &bufb->chan->backend; + const struct lib_ring_buffer_config *config = &chanb->config; + size_t sbidx, index; + struct lib_ring_buffer_backend_pages *rpages; + unsigned long sb_bindex, id; + + do { + len -= pagecpy; + offset += pagecpy; + sbidx = offset >> chanb->subbuf_size_order; + index = (offset & (chanb->subbuf_size - 1)) >> PAGE_SHIFT; + + /* + * Underlying layer should never ask for writes across + * subbuffers. + */ + CHAN_WARN_ON(chanb, offset >= chanb->buf_size); + + pagecpy = min_t(size_t, len, PAGE_SIZE - (offset & ~PAGE_MASK)); + id = bufb->buf_wsb[sbidx].id; + sb_bindex = subbuffer_id_get_index(config, id); + rpages = bufb->array[sb_bindex]; + CHAN_WARN_ON(chanb, config->mode == RING_BUFFER_OVERWRITE + && subbuffer_id_is_noref(config, id)); + lib_ring_buffer_do_memset(rpages->p[index].virt + + (offset & ~PAGE_MASK), + c, pagecpy); + } while (unlikely(len != pagecpy)); +} +EXPORT_SYMBOL_GPL(_lib_ring_buffer_memset); + +/** + * lib_ring_buffer_strcpy - write string data to a ring_buffer buffer. + * @bufb : buffer backend + * @offset : offset within the buffer + * @src : source address + * @len : length to write + * @pagecpy : page size copied so far + * @pad : character to use for padding + */ +void _lib_ring_buffer_strcpy(struct lib_ring_buffer_backend *bufb, + size_t offset, const char *src, size_t len, + size_t pagecpy, int pad) +{ + struct channel_backend *chanb = &bufb->chan->backend; + const struct lib_ring_buffer_config *config = &chanb->config; + size_t sbidx, index; + struct lib_ring_buffer_backend_pages *rpages; + unsigned long sb_bindex, id; + int src_terminated = 0; + + CHAN_WARN_ON(chanb, !len); + offset += pagecpy; + do { + len -= pagecpy; + if (!src_terminated) + src += pagecpy; + sbidx = offset >> chanb->subbuf_size_order; + index = (offset & (chanb->subbuf_size - 1)) >> PAGE_SHIFT; + + /* + * Underlying layer should never ask for writes across + * subbuffers. + */ + CHAN_WARN_ON(chanb, offset >= chanb->buf_size); + + pagecpy = min_t(size_t, len, PAGE_SIZE - (offset & ~PAGE_MASK)); + id = bufb->buf_wsb[sbidx].id; + sb_bindex = subbuffer_id_get_index(config, id); + rpages = bufb->array[sb_bindex]; + CHAN_WARN_ON(chanb, config->mode == RING_BUFFER_OVERWRITE + && subbuffer_id_is_noref(config, id)); + + if (likely(!src_terminated)) { + size_t count, to_copy; + + to_copy = pagecpy; + if (pagecpy == len) + to_copy--; /* Final '\0' */ + count = lib_ring_buffer_do_strcpy(config, + rpages->p[index].virt + + (offset & ~PAGE_MASK), + src, to_copy); + offset += count; + /* Padding */ + if (unlikely(count < to_copy)) { + size_t pad_len = to_copy - count; + + /* Next pages will have padding */ + src_terminated = 1; + lib_ring_buffer_do_memset(rpages->p[index].virt + + (offset & ~PAGE_MASK), + pad, pad_len); + offset += pad_len; + } + } else { + size_t pad_len; + + pad_len = pagecpy; + if (pagecpy == len) + pad_len--; /* Final '\0' */ + lib_ring_buffer_do_memset(rpages->p[index].virt + + (offset & ~PAGE_MASK), + pad, pad_len); + offset += pad_len; + } + } while (unlikely(len != pagecpy)); + /* Ending '\0' */ + lib_ring_buffer_do_memset(rpages->p[index].virt + (offset & ~PAGE_MASK), + '\0', 1); +} +EXPORT_SYMBOL_GPL(_lib_ring_buffer_strcpy); + +/** + * lib_ring_buffer_copy_from_user_inatomic - write user data to a ring_buffer buffer. + * @bufb : buffer backend + * @offset : offset within the buffer + * @src : source address + * @len : length to write + * @pagecpy : page size copied so far + * + * This function deals with userspace pointers, it should never be called + * directly without having the src pointer checked with access_ok() + * previously. + */ +void _lib_ring_buffer_copy_from_user_inatomic(struct lib_ring_buffer_backend *bufb, + size_t offset, + const void __user *src, size_t len, + size_t pagecpy) +{ + struct channel_backend *chanb = &bufb->chan->backend; + const struct lib_ring_buffer_config *config = &chanb->config; + size_t sbidx, index; + struct lib_ring_buffer_backend_pages *rpages; + unsigned long sb_bindex, id; + int ret; + + do { + len -= pagecpy; + src += pagecpy; + offset += pagecpy; + sbidx = offset >> chanb->subbuf_size_order; + index = (offset & (chanb->subbuf_size - 1)) >> PAGE_SHIFT; + + /* + * Underlying layer should never ask for writes across + * subbuffers. + */ + CHAN_WARN_ON(chanb, offset >= chanb->buf_size); + + pagecpy = min_t(size_t, len, PAGE_SIZE - (offset & ~PAGE_MASK)); + id = bufb->buf_wsb[sbidx].id; + sb_bindex = subbuffer_id_get_index(config, id); + rpages = bufb->array[sb_bindex]; + CHAN_WARN_ON(chanb, config->mode == RING_BUFFER_OVERWRITE + && subbuffer_id_is_noref(config, id)); + ret = lib_ring_buffer_do_copy_from_user_inatomic(rpages->p[index].virt + + (offset & ~PAGE_MASK), + src, pagecpy) != 0; + if (ret > 0) { + /* Copy failed. */ + _lib_ring_buffer_memset(bufb, offset, 0, len, 0); + break; /* stop copy */ + } + } while (unlikely(len != pagecpy)); +} +EXPORT_SYMBOL_GPL(_lib_ring_buffer_copy_from_user_inatomic); + +/** + * lib_ring_buffer_strcpy_from_user_inatomic - write userspace string data to a ring_buffer buffer. + * @bufb : buffer backend + * @offset : offset within the buffer + * @src : source address + * @len : length to write + * @pagecpy : page size copied so far + * @pad : character to use for padding + * + * This function deals with userspace pointers, it should never be called + * directly without having the src pointer checked with access_ok() + * previously. + */ +void _lib_ring_buffer_strcpy_from_user_inatomic(struct lib_ring_buffer_backend *bufb, + size_t offset, const char __user *src, size_t len, + size_t pagecpy, int pad) +{ + struct channel_backend *chanb = &bufb->chan->backend; + const struct lib_ring_buffer_config *config = &chanb->config; + size_t sbidx, index; + struct lib_ring_buffer_backend_pages *rpages; + unsigned long sb_bindex, id; + int src_terminated = 0; + + offset += pagecpy; + do { + len -= pagecpy; + if (!src_terminated) + src += pagecpy; + sbidx = offset >> chanb->subbuf_size_order; + index = (offset & (chanb->subbuf_size - 1)) >> PAGE_SHIFT; + + /* + * Underlying layer should never ask for writes across + * subbuffers. + */ + CHAN_WARN_ON(chanb, offset >= chanb->buf_size); + + pagecpy = min_t(size_t, len, PAGE_SIZE - (offset & ~PAGE_MASK)); + id = bufb->buf_wsb[sbidx].id; + sb_bindex = subbuffer_id_get_index(config, id); + rpages = bufb->array[sb_bindex]; + CHAN_WARN_ON(chanb, config->mode == RING_BUFFER_OVERWRITE + && subbuffer_id_is_noref(config, id)); + + if (likely(!src_terminated)) { + size_t count, to_copy; + + to_copy = pagecpy; + if (pagecpy == len) + to_copy--; /* Final '\0' */ + count = lib_ring_buffer_do_strcpy_from_user_inatomic(config, + rpages->p[index].virt + + (offset & ~PAGE_MASK), + src, to_copy); + offset += count; + /* Padding */ + if (unlikely(count < to_copy)) { + size_t pad_len = to_copy - count; + + /* Next pages will have padding */ + src_terminated = 1; + lib_ring_buffer_do_memset(rpages->p[index].virt + + (offset & ~PAGE_MASK), + pad, pad_len); + offset += pad_len; + } + } else { + size_t pad_len; + + pad_len = pagecpy; + if (pagecpy == len) + pad_len--; /* Final '\0' */ + lib_ring_buffer_do_memset(rpages->p[index].virt + + (offset & ~PAGE_MASK), + pad, pad_len); + offset += pad_len; + } + } while (unlikely(len != pagecpy)); + /* Ending '\0' */ + lib_ring_buffer_do_memset(rpages->p[index].virt + (offset & ~PAGE_MASK), + '\0', 1); +} +EXPORT_SYMBOL_GPL(_lib_ring_buffer_strcpy_from_user_inatomic); + /** * lib_ring_buffer_read - read data from ring_buffer_buffer. * @bufb : buffer backend @@ -514,9 +806,8 @@ size_t lib_ring_buffer_read(struct lib_ring_buffer_backend *bufb, size_t offset, void *dest, size_t len) { struct channel_backend *chanb = &bufb->chan->backend; - const struct lib_ring_buffer_config *config = chanb->config; - size_t index; - ssize_t pagecpy, orig_len; + const struct lib_ring_buffer_config *config = &chanb->config; + size_t index, pagecpy, orig_len; struct lib_ring_buffer_backend_pages *rpages; unsigned long sb_bindex, id; @@ -566,13 +857,12 @@ int __lib_ring_buffer_copy_to_user(struct lib_ring_buffer_backend *bufb, size_t offset, void __user *dest, size_t len) { struct channel_backend *chanb = &bufb->chan->backend; - const struct lib_ring_buffer_config *config = chanb->config; + const struct lib_ring_buffer_config *config = &chanb->config; size_t index; - ssize_t pagecpy, orig_len; + ssize_t pagecpy; struct lib_ring_buffer_backend_pages *rpages; unsigned long sb_bindex, id; - orig_len = len; offset &= chanb->buf_size - 1; index = (offset & (chanb->subbuf_size - 1)) >> PAGE_SHIFT; if (unlikely(!len)) @@ -611,14 +901,15 @@ EXPORT_SYMBOL_GPL(__lib_ring_buffer_copy_to_user); * @dest : destination address * @len : destination's length * - * return string's length + * Return string's length, or -EINVAL on error. * Should be protected by get_subbuf/put_subbuf. + * Destination length should be at least 1 to hold '\0'. */ int lib_ring_buffer_read_cstr(struct lib_ring_buffer_backend *bufb, size_t offset, void *dest, size_t len) { struct channel_backend *chanb = &bufb->chan->backend; - const struct lib_ring_buffer_config *config = chanb->config; + const struct lib_ring_buffer_config *config = &chanb->config; size_t index; ssize_t pagecpy, pagelen, strpagelen, orig_offset; char *str; @@ -628,6 +919,8 @@ int lib_ring_buffer_read_cstr(struct lib_ring_buffer_backend *bufb, size_t offse offset &= chanb->buf_size - 1; index = (offset & (chanb->subbuf_size - 1)) >> PAGE_SHIFT; orig_offset = offset; + if (unlikely(!len)) + return -EINVAL; for (;;) { id = bufb->buf_rsb.id; sb_bindex = subbuffer_id_get_index(config, id); @@ -662,21 +955,21 @@ int lib_ring_buffer_read_cstr(struct lib_ring_buffer_backend *bufb, size_t offse EXPORT_SYMBOL_GPL(lib_ring_buffer_read_cstr); /** - * lib_ring_buffer_read_get_page - Get a whole page to read from + * lib_ring_buffer_read_get_pfn - Get a page frame number to read from * @bufb : buffer backend * @offset : offset within the buffer * @virt : pointer to page address (output) * * Should be protected by get_subbuf/put_subbuf. - * Returns the pointer to the page struct pointer. + * Returns the pointer to the page frame number unsigned long. */ -struct page **lib_ring_buffer_read_get_page(struct lib_ring_buffer_backend *bufb, +unsigned long *lib_ring_buffer_read_get_pfn(struct lib_ring_buffer_backend *bufb, size_t offset, void ***virt) { size_t index; struct lib_ring_buffer_backend_pages *rpages; struct channel_backend *chanb = &bufb->chan->backend; - const struct lib_ring_buffer_config *config = chanb->config; + const struct lib_ring_buffer_config *config = &chanb->config; unsigned long sb_bindex, id; offset &= chanb->buf_size - 1; @@ -687,9 +980,9 @@ struct page **lib_ring_buffer_read_get_page(struct lib_ring_buffer_backend *bufb CHAN_WARN_ON(chanb, config->mode == RING_BUFFER_OVERWRITE && subbuffer_id_is_noref(config, id)); *virt = &rpages->p[index].virt; - return &rpages->p[index].page; + return &rpages->p[index].pfn; } -EXPORT_SYMBOL_GPL(lib_ring_buffer_read_get_page); +EXPORT_SYMBOL_GPL(lib_ring_buffer_read_get_pfn); /** * lib_ring_buffer_read_offset_address - get address of a buffer location @@ -698,8 +991,9 @@ EXPORT_SYMBOL_GPL(lib_ring_buffer_read_get_page); * * Return the address where a given offset is located (for read). * Should be used to get the current subbuffer header pointer. Given we know - * it's never on a page boundary, it's safe to write directly to this address, - * as long as the write is never bigger than a page size. + * it's never on a page boundary, it's safe to read/write directly + * from/to this address, as long as the read/write is never bigger than a + * page size. */ void *lib_ring_buffer_read_offset_address(struct lib_ring_buffer_backend *bufb, size_t offset) @@ -707,7 +1001,7 @@ void *lib_ring_buffer_read_offset_address(struct lib_ring_buffer_backend *bufb, size_t index; struct lib_ring_buffer_backend_pages *rpages; struct channel_backend *chanb = &bufb->chan->backend; - const struct lib_ring_buffer_config *config = chanb->config; + const struct lib_ring_buffer_config *config = &chanb->config; unsigned long sb_bindex, id; offset &= chanb->buf_size - 1; @@ -737,7 +1031,7 @@ void *lib_ring_buffer_offset_address(struct lib_ring_buffer_backend *bufb, size_t sbidx, index; struct lib_ring_buffer_backend_pages *rpages; struct channel_backend *chanb = &bufb->chan->backend; - const struct lib_ring_buffer_config *config = chanb->config; + const struct lib_ring_buffer_config *config = &chanb->config; unsigned long sb_bindex, id; offset &= chanb->buf_size - 1;