Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc/perf/hv-24x7: Simplify catalog_read()

catalog_read() implements the read interface for the sysfs file

/sys/bus/event_source/devices/hv_24x7/interface/catalog

It essentially takes a buffer, an offset and count as parameters
to the read() call. It makes a hypervisor call to read a specific
page from the catalog and copy the required bytes into the given
buffer. Each call to catalog_read() returns at most one 4K page.

Given these requirements, we should be able to simplify the
catalog_read().

Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>

authored by

sukadev@linux.vnet.ibm.com and committed by
Michael Ellerman
56f12bee 48bee8a6

+14 -87
+14 -87
arch/powerpc/perf/hv-24x7.c
··· 75 75 76 76 static struct kmem_cache *hv_page_cache; 77 77 78 - /* 79 - * read_offset_data - copy data from one buffer to another while treating the 80 - * source buffer as a small view on the total avaliable 81 - * source data. 82 - * 83 - * @dest: buffer to copy into 84 - * @dest_len: length of @dest in bytes 85 - * @requested_offset: the offset within the source data we want. Must be > 0 86 - * @src: buffer to copy data from 87 - * @src_len: length of @src in bytes 88 - * @source_offset: the offset in the sorce data that (src,src_len) refers to. 89 - * Must be > 0 90 - * 91 - * returns the number of bytes copied. 92 - * 93 - * The following ascii art shows the various buffer possitioning we need to 94 - * handle, assigns some arbitrary varibles to points on the buffer, and then 95 - * shows how we fiddle with those values to get things we care about (copy 96 - * start in src and copy len) 97 - * 98 - * s = @src buffer 99 - * d = @dest buffer 100 - * '.' areas in d are written to. 101 - * 102 - * u 103 - * x w v z 104 - * d |.........| 105 - * s |----------------------| 106 - * 107 - * u 108 - * x w z v 109 - * d |........------| 110 - * s |------------------| 111 - * 112 - * x w u,z,v 113 - * d |........| 114 - * s |------------------| 115 - * 116 - * x,w u,v,z 117 - * d |..................| 118 - * s |------------------| 119 - * 120 - * x u 121 - * w v z 122 - * d |........| 123 - * s |------------------| 124 - * 125 - * x z w v 126 - * d |------| 127 - * s |------| 128 - * 129 - * x = source_offset 130 - * w = requested_offset 131 - * z = source_offset + src_len 132 - * v = requested_offset + dest_len 133 - * 134 - * w_offset_in_s = w - x = requested_offset - source_offset 135 - * z_offset_in_s = z - x = src_len 136 - * v_offset_in_s = v - x = request_offset + dest_len - src_len 137 - */ 138 - static ssize_t read_offset_data(void *dest, size_t dest_len, 139 - loff_t requested_offset, void *src, 140 - size_t src_len, loff_t source_offset) 141 - { 142 - size_t w_offset_in_s = requested_offset - source_offset; 143 - size_t z_offset_in_s = src_len; 144 - size_t v_offset_in_s = requested_offset + dest_len - src_len; 145 - size_t u_offset_in_s = min(z_offset_in_s, v_offset_in_s); 146 - size_t copy_len = u_offset_in_s - w_offset_in_s; 147 - 148 - if (requested_offset < 0 || source_offset < 0) 149 - return -EINVAL; 150 - 151 - if (z_offset_in_s <= w_offset_in_s) 152 - return 0; 153 - 154 - memcpy(dest, src + w_offset_in_s, copy_len); 155 - return copy_len; 156 - } 157 - 158 78 static unsigned long h_get_24x7_catalog_page_(unsigned long phys_4096, 159 79 unsigned long version, 160 80 unsigned long index) ··· 103 183 { 104 184 unsigned long hret; 105 185 ssize_t ret = 0; 106 - size_t catalog_len = 0, catalog_page_len = 0, page_count = 0; 186 + size_t catalog_len = 0, catalog_page_len = 0; 107 187 loff_t page_offset = 0; 188 + loff_t offset_in_page; 189 + size_t copy_len; 108 190 uint64_t catalog_version_num = 0; 109 191 void *page = kmem_cache_alloc(hv_page_cache, GFP_USER); 110 192 struct hv_24x7_catalog_page_0 *page_0 = page; ··· 124 202 catalog_len = catalog_page_len * 4096; 125 203 126 204 page_offset = offset / 4096; 127 - page_count = count / 4096; 205 + offset_in_page = offset % 4096; 128 206 129 207 if (page_offset >= catalog_page_len) 130 208 goto e_free; ··· 138 216 } 139 217 } 140 218 141 - ret = read_offset_data(buf, count, offset, 142 - page, 4096, page_offset * 4096); 219 + copy_len = 4096 - offset_in_page; 220 + if (copy_len > count) 221 + copy_len = count; 222 + 223 + memcpy(buf, page+offset_in_page, copy_len); 224 + ret = copy_len; 225 + 143 226 e_free: 144 227 if (hret) 145 228 pr_err("h_get_24x7_catalog_page(ver=%lld, page=%lld) failed:" ··· 152 225 catalog_version_num, page_offset, hret); 153 226 kmem_cache_free(hv_page_cache, page); 154 227 155 - pr_devel("catalog_read: offset=%lld(%lld) count=%zu(%zu) catalog_len=%zu(%zu) => %zd\n", 156 - offset, page_offset, count, page_count, catalog_len, 157 - catalog_page_len, ret); 228 + pr_devel("catalog_read: offset=%lld(%lld) count=%zu " 229 + "catalog_len=%zu(%zu) => %zd\n", offset, page_offset, 230 + count, catalog_len, catalog_page_len, ret); 158 231 159 232 return ret; 160 233 }