{"action":"created","comment":{"url":"https://api.github.com/repos/zfsonlinux/zfs/pulls/comments/77237884","id":77237884,"diff_hunk":"@@ -0,0 +1,1198 @@\n+/*\n+ * CDDL HEADER START\n+ *\n+ * The contents of this file are subject to the terms of the\n+ * Common Development and Distribution License (the \"License\").\n+ * You may not use this file except in compliance with the License.\n+ *\n+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE\n+ * or http://www.opensolaris.org/os/licensing.\n+ * See the License for the specific language governing permissions\n+ * and limitations under the License.\n+ *\n+ * When distributing Covered Code, include this CDDL HEADER in each\n+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.\n+ * If applicable, add the following below this CDDL HEADER, with the\n+ * fields enclosed by brackets \"[]\" replaced with your own identifying\n+ * information: Portions Copyright [yyyy] [name of copyright owner]\n+ *\n+ * CDDL HEADER END\n+ */\n+/*\n+ * Copyright (c) 2014 by Chunwei Chen. All rights reserved.\n+ * Copyright (c) 2016 by Delphix. All rights reserved.\n+ */\n+\n+/*\n+ * ARC buffer data (ABD).\n+ *\n+ * ABDs are an abstract data structure for the ARC which can use two\n+ * different ways of storing the underlying data:\n+ *\n+ * (a) Linear buffer. In this case, all the data in the ABD is stored in one\n+ *     contiguous buffer in memory (from a zio_[data_]buf_* kmem cache).\n+ *\n+ *         +-------------------+\n+ *         | ABD (linear)      |\n+ *         |   abd_flags = ... |\n+ *         |   abd_size = ...  |     +--------------------------------+\n+ *         |   abd_buf ------------->| raw buffer of size abd_size    |\n+ *         +-------------------+     +--------------------------------+\n+ *              no abd_chunks\n+ *\n+ * (b) Scattered buffer. In this case, the data in the ABD is split into\n+ *     equal-sized chunks (from the abd_chunk_cache kmem_cache), with pointers\n+ *     to the chunks recorded in an array at the end of the ABD structure.\n+ *\n+ *         +-------------------+\n+ *         | ABD (scattered)   |\n+ *         |   abd_flags = ... |\n+ *         |   abd_size = ...  |\n+ *         |   abd_offset = 0  |                           +-----------+\n+ *         |   abd_chunks[0] ----------------------------->| chunk 0   |\n+ *         |   abd_chunks[1] ---------------------+        +-----------+\n+ *         |   ...             |                  |        +-----------+\n+ *         |   abd_chunks[N-1] ---------+         +------->| chunk 1   |\n+ *         +-------------------+        |                  +-----------+\n+ *                                      |                      ...\n+ *                                      |                  +-----------+\n+ *                                      +----------------->| chunk N-1 |\n+ *                                                         +-----------+\n+ *\n+ * Linear buffers act exactly like normal buffers and are always mapped into the\n+ * kernel's virtual memory space, while scattered ABD data chunks are allocated\n+ * as physical pages and then mapped in only while they are actually being\n+ * accessed through one of the abd_* library functions. Using scattered ABDs\n+ * provides several benefits:\n+ *\n+ *  (1) They avoid use of kmem_*, preventing performance problems where running\n+ *      kmem_reap on very large memory systems never finishes and causes\n+ *      constant TLB shootdowns.\n+ *\n+ *  (2) Fragmentation is less of an issue since when we are at the limit of\n+ *      allocatable space, we won't have to search around for a long free\n+ *      hole in the VA space for large ARC allocations. Each chunk is mapped in\n+ *      individually, so even if we weren't using segkpm (see next point) we\n+ *      wouldn't need to worry about finding a contiguous address range.\n+ *\n+ *  (3) Use of segkpm will avoid the need for map / unmap / TLB shootdown costs\n+ *      on each ABD access. (If segkpm isn't available then we use all linear\n+ *      ABDs to avoid this penalty.) See seg_kpm.c for more details.\n+ *\n+ * It is possible to make all ABDs linear by setting zfs_abd_scatter_enabled to\n+ * B_FALSE. However, it is not possible to use scattered ABDs if segkpm is not\n+ * available, which is the case on all 32-bit systems and any 64-bit systems\n+ * where kpm_enable is turned off.\n+ *\n+ * In addition to directly allocating a linear or scattered ABD, it is also\n+ * possible to create an ABD by requesting the \"sub-ABD\" starting at an offset\n+ * within an existing ABD. In linear buffers this is simple (set abd_buf of\n+ * the new ABD to the starting point within the original raw buffer), but\n+ * scattered ABDs are a little more complex. The new ABD makes a copy of the\n+ * relevant abd_chunks pointers (but not the underlying data). However, to\n+ * provide arbitrary rather than only chunk-aligned starting offsets, it also\n+ * tracks an abd_offset field which represents the starting point of the data\n+ * within the first chunk in abd_chunks. For both linear and scattered ABDs,\n+ * creating an offset ABD marks the original ABD as the offset's parent, and the\n+ * original ABD's abd_children refcount is incremented. This data allows us to\n+ * ensure the root ABD isn't deleted before its children.\n+ *\n+ * Most consumers should never need to know what type of ABD they're using --\n+ * the ABD public API ensures that it's possible to transparently switch from\n+ * using a linear ABD to a scattered one when doing so would be beneficial.\n+ *\n+ * If you need to use the data within an ABD directly, if you know it's linear\n+ * (because you allocated it) you can use abd_to_buf() to access the underlying\n+ * raw buffer. Otherwise, you should use one of the abd_borrow_buf* functions\n+ * which will allocate a raw buffer if necessary. Use the abd_return_buf*\n+ * functions to return any raw buffers that are no longer necessary when you're\n+ * done using them.\n+ *\n+ * There are a variety of ABD APIs that implement basic buffer operations:\n+ * compare, copy, read, write, and fill with zeroes. If you need a custom\n+ * function which progressively accesses the whole ABD, use the abd_iterate_*\n+ * functions.\n+ */\n+\n+#include <sys/abd.h>\n+#include <sys/param.h>\n+#include <sys/zio.h>\n+#include <sys/zfs_context.h>\n+#include <sys/zfs_znode.h>\n+\n+#ifndef KMC_NOTOUCH\n+#define\tKMC_NOTOUCH\t0\n+#endif\n+\n+typedef struct abd_stats {\n+\tkstat_named_t abdstat_struct_size;\n+\tkstat_named_t abdstat_scatter_cnt;\n+\tkstat_named_t abdstat_scatter_data_size;\n+\tkstat_named_t abdstat_scatter_chunk_waste;\n+\tkstat_named_t abdstat_linear_cnt;\n+\tkstat_named_t abdstat_linear_data_size;\n+} abd_stats_t;\n+\n+static abd_stats_t abd_stats = {\n+\t/* Amount of memory occupied by all of the abd_t struct allocations */\n+\t{ \"struct_size\",\t\t\tKSTAT_DATA_UINT64 },\n+\t/*\n+\t * The number of scatter ABDs which are currently allocated, excluding\n+\t * ABDs which don't own their data (for instance the ones which were\n+\t * allocated through abd_get_offset()).\n+\t */\n+\t{ \"scatter_cnt\",\t\t\tKSTAT_DATA_UINT64 },\n+\t/* Amount of data stored in all scatter ABDs tracked by scatter_cnt */\n+\t{ \"scatter_data_size\",\t\t\tKSTAT_DATA_UINT64 },\n+\t/*\n+\t * The amount of space wasted at the end of the last chunk across all\n+\t * scatter ABDs tracked by scatter_cnt.\n+\t */\n+\t{ \"scatter_chunk_waste\",\t\tKSTAT_DATA_UINT64 },\n+\t/*\n+\t * The number of linear ABDs which are currently allocated, excluding\n+\t * ABDs which don't own their data (for instance the ones which were\n+\t * allocated through abd_get_offset() and abd_get_from_buf()). If an\n+\t * ABD takes ownership of its buf then it will become tracked.\n+\t */\n+\t{ \"linear_cnt\",\t\t\t\tKSTAT_DATA_UINT64 },\n+\t/* Amount of data stored in all linear ABDs tracked by linear_cnt */\n+\t{ \"linear_data_size\",\t\t\tKSTAT_DATA_UINT64 },\n+};\n+\n+#define\tABDSTAT(stat)\t\t(abd_stats.stat.value.ui64)\n+#define\tABDSTAT_INCR(stat, val) \\\n+\tatomic_add_64(&abd_stats.stat.value.ui64, (val))\n+#define\tABDSTAT_BUMP(stat)\tABDSTAT_INCR(stat, 1)\n+#define\tABDSTAT_BUMPDOWN(stat)\tABDSTAT_INCR(stat, -1)\n+\n+/* see block comment above for description */\n+int zfs_abd_scatter_enabled = B_TRUE;\n+\n+\n+#ifdef _KERNEL\n+static kstat_t *abd_ksp;\n+\n+static struct page *\n+abd_alloc_chunk(void)\n+{\n+\tstruct page *c = alloc_page(kmem_flags_convert(KM_SLEEP));\n+\tASSERT3P(c, !=, NULL);\n+\treturn (c);\n+}\n+\n+static void\n+abd_free_chunk(struct page *c)\n+{\n+\t__free_pages(c, 0);\n+}\n+\n+static void *\n+abd_map_chunk(struct page *c)\n+{\n+\t/*\n+\t * Use of segkpm means we don't care if this is mapped S_READ or S_WRITE\n+\t * but S_WRITE is conceptually more accurate.\n+\t */\n+\treturn (kmap(c));\n+}\n+\n+static void\n+abd_unmap_chunk(struct page *c)\n+{\n+\tkunmap(c);\n+}\n+\n+void\n+abd_init(void)\n+{\n+\tabd_ksp = kstat_create(\"zfs\", 0, \"abdstats\", \"misc\", KSTAT_TYPE_NAMED,\n+\t    sizeof (abd_stats) / sizeof (kstat_named_t), KSTAT_FLAG_VIRTUAL);\n+\tif (abd_ksp != NULL) {\n+\t\tabd_ksp->ks_data = &abd_stats;\n+\t\tkstat_install(abd_ksp);\n+\t}\n+}\n+\n+void\n+abd_fini(void)\n+{\n+\tif (abd_ksp != NULL) {\n+\t\tkstat_delete(abd_ksp);\n+\t\tabd_ksp = NULL;\n+\t}\n+}\n+\n+#else\n+\n+struct page;\n+#define\tkpm_enable\t\t\t1\n+#define\tabd_alloc_chunk() \\\n+\t((struct page *) umem_alloc_aligned(PAGESIZE, 64, KM_SLEEP))\n+#define\tabd_free_chunk(chunk) \t\tumem_free(chunk, PAGESIZE)\n+#define\tabd_map_chunk(chunk)\t\t((void *)chunk)\n+static void\n+abd_unmap_chunk(struct page *c)\n+{\n+}\n+\n+void\n+abd_init(void)\n+{\n+}\n+\n+void\n+abd_fini(void)\n+{\n+}\n+\n+#endif /* _KERNEL */\n+\n+static inline size_t\n+abd_chunkcnt_for_bytes(size_t size)\n+{\n+\treturn (P2ROUNDUP(size, PAGESIZE) / PAGESIZE);\n+}\n+\n+static inline size_t\n+abd_scatter_chunkcnt(abd_t *abd)\n+{\n+\tASSERT(!abd_is_linear(abd));\n+\treturn (abd_chunkcnt_for_bytes(\n+\t    abd->abd_u.abd_scatter.abd_offset + abd->abd_size));\n+}\n+\n+static inline void\n+abd_verify(abd_t *abd)\n+{\n+\tASSERT3U(abd->abd_size, >, 0);\n+\tASSERT3U(abd->abd_size, <=, SPA_MAXBLOCKSIZE);\n+\tASSERT3U(abd->abd_flags, ==, abd->abd_flags & (ABD_FLAG_LINEAR |\n+\t    ABD_FLAG_OWNER | ABD_FLAG_META));\n+\tIMPLY(abd->abd_parent != NULL, !(abd->abd_flags & ABD_FLAG_OWNER));\n+\tIMPLY(abd->abd_flags & ABD_FLAG_META, abd->abd_flags & ABD_FLAG_OWNER);\n+\tif (abd_is_linear(abd)) {\n+\t\tASSERT3P(abd->abd_u.abd_linear.abd_buf, !=, NULL);\n+\t} else {\n+\t\tsize_t n;\n+\t\tint i;\n+\n+\t\tASSERT3U(abd->abd_u.abd_scatter.abd_offset, <, PAGESIZE);\n+\t\tn = abd_scatter_chunkcnt(abd);\n+\t\tfor (i = 0; i < n; i++) {\n+\t\t\tASSERT3P(\n+\t\t\t    abd->abd_u.abd_scatter.abd_chunks[i], !=, NULL);\n+\t\t}\n+\t}\n+}\n+\n+static inline abd_t *\n+abd_alloc_struct(size_t chunkcnt)\n+{\n+\tsize_t size = offsetof(abd_t, abd_u.abd_scatter.abd_chunks[chunkcnt]);\n+\tabd_t *abd = kmem_alloc(size, KM_PUSHPAGE);\n+\tASSERT3P(abd, !=, NULL);\n+\tABDSTAT_INCR(abdstat_struct_size, size);\n+\n+\treturn (abd);\n+}\n+\n+static inline void\n+abd_free_struct(abd_t *abd)\n+{\n+\tsize_t chunkcnt = abd_is_linear(abd) ? 0 : abd_scatter_chunkcnt(abd);\n+\tint size = offsetof(abd_t, abd_u.abd_scatter.abd_chunks[chunkcnt]);\n+\tkmem_free(abd, size);\n+\tABDSTAT_INCR(abdstat_struct_size, -size);\n+}\n+\n+/*\n+ * Allocate an ABD, along with its own underlying data buffers. Use this if you\n+ * don't care whether the ABD is linear or not.\n+ */\n+abd_t *\n+abd_alloc(size_t size, boolean_t is_metadata)\n+{\n+\tint i;\n+\tsize_t n;\n+\tabd_t *abd;\n+\n+\tif (!zfs_abd_scatter_enabled)\n+\t\treturn (abd_alloc_linear(size, is_metadata));\n+\n+\tVERIFY3U(size, <=, SPA_MAXBLOCKSIZE);\n+\n+\tn = abd_chunkcnt_for_bytes(size);\n+\tabd = abd_alloc_struct(n);\n+\n+\tabd->abd_flags = ABD_FLAG_OWNER;\n+\tif (is_metadata) {\n+\t\tabd->abd_flags |= ABD_FLAG_META;\n+\t}\n+\tabd->abd_size = size;\n+\tabd->abd_parent = NULL;\n+\trefcount_create(&abd->abd_children);\n+\n+\tabd->abd_u.abd_scatter.abd_offset = 0;\n+\tabd->abd_u.abd_scatter.abd_chunk_size = PAGESIZE;\n+\n+\tfor (i = 0; i < n; i++) {\n+\t\tvoid *c = abd_alloc_chunk();\n+\t\tASSERT3P(c, !=, NULL);\n+\t\tabd->abd_u.abd_scatter.abd_chunks[i] = c;\n+\t}\n+\n+\tABDSTAT_BUMP(abdstat_scatter_cnt);\n+\tABDSTAT_INCR(abdstat_scatter_data_size, size);\n+\tABDSTAT_INCR(abdstat_scatter_chunk_waste,\n+\t    n * PAGESIZE - size);\n+\n+\treturn (abd);\n+}\n+\n+static void\n+abd_free_scatter(abd_t *abd)\n+{\n+\tsize_t n = abd_scatter_chunkcnt(abd);\n+\tint i;\n+\n+\tfor (i = 0; i < n; i++) {\n+\t\tabd_free_chunk(abd->abd_u.abd_scatter.abd_chunks[i]);\n+\t}\n+\n+\trefcount_destroy(&abd->abd_children);\n+\tABDSTAT_BUMPDOWN(abdstat_scatter_cnt);\n+\tABDSTAT_INCR(abdstat_scatter_data_size, -(int)abd->abd_size);\n+\tABDSTAT_INCR(abdstat_scatter_chunk_waste,\n+\t    abd->abd_size - n * PAGESIZE);\n+\n+\tabd_free_struct(abd);\n+}\n+\n+/*\n+ * Allocate an ABD that must be linear, along with its own underlying data\n+ * buffer. Only use this when it would be very annoying to write your ABD\n+ * consumer with a scattered ABD.\n+ */\n+abd_t *\n+abd_alloc_linear(size_t size, boolean_t is_metadata)\n+{\n+\tabd_t *abd = abd_alloc_struct(0);\n+\n+\tVERIFY3U(size, <=, SPA_MAXBLOCKSIZE);\n+\n+\tabd->abd_flags = ABD_FLAG_LINEAR | ABD_FLAG_OWNER;\n+\tif (is_metadata) {\n+\t\tabd->abd_flags |= ABD_FLAG_META;\n+\t}\n+\tabd->abd_size = size;\n+\tabd->abd_parent = NULL;\n+\trefcount_create(&abd->abd_children);\n+\n+\tif (is_metadata) {\n+\t\tabd->abd_u.abd_linear.abd_buf = zio_buf_alloc(size);\n+\t} else {\n+\t\tabd->abd_u.abd_linear.abd_buf = zio_data_buf_alloc(size);\n+\t}\n+\n+\tABDSTAT_BUMP(abdstat_linear_cnt);\n+\tABDSTAT_INCR(abdstat_linear_data_size, size);\n+\n+\treturn (abd);\n+}\n+\n+static void\n+abd_free_linear(abd_t *abd)\n+{\n+\tif (abd->abd_flags & ABD_FLAG_META) {\n+\t\tzio_buf_free(abd->abd_u.abd_linear.abd_buf, abd->abd_size);\n+\t} else {\n+\t\tzio_data_buf_free(abd->abd_u.abd_linear.abd_buf, abd->abd_size);\n+\t}\n+\n+\trefcount_destroy(&abd->abd_children);\n+\tABDSTAT_BUMPDOWN(abdstat_linear_cnt);\n+\tABDSTAT_INCR(abdstat_linear_data_size, -(int)abd->abd_size);\n+\n+\tabd_free_struct(abd);\n+}\n+\n+/*\n+ * Free an ABD. Only use this on ABDs allocated with abd_alloc() or\n+ * abd_alloc_linear().\n+ */\n+void\n+abd_free(abd_t *abd)\n+{\n+\tabd_verify(abd);\n+\tASSERT3P(abd->abd_parent, ==, NULL);\n+\tASSERT(abd->abd_flags & ABD_FLAG_OWNER);\n+\tif (abd_is_linear(abd))\n+\t\tabd_free_linear(abd);\n+\telse\n+\t\tabd_free_scatter(abd);\n+}\n+\n+/*\n+ * Allocate an ABD of the same format (same metadata flag, same scatterize\n+ * setting) as another ABD.\n+ */\n+abd_t *\n+abd_alloc_sametype(abd_t *sabd, size_t size)\n+{\n+\tboolean_t is_metadata = (sabd->abd_flags | ABD_FLAG_META) != 0;\n+\tif (abd_is_linear(sabd)) {\n+\t\treturn (abd_alloc_linear(size, is_metadata));\n+\t} else {\n+\t\treturn (abd_alloc(size, is_metadata));\n+\t}\n+}\n+\n+/*\n+ * If we're going to use this ABD for doing I/O using the block layer, the\n+ * consumer of the ABD data doesn't care if it's scattered or not, and we don't\n+ * plan to store this ABD in memory for a long period of time, we should\n+ * allocate the ABD type that requires the least data copying to do the I/O.\n+ *\n+ * Currently this is linear ABDs, however if ldi_strategy() can ever issue I/Os\n+ * using a scatter/gather list we should switch to that and replace this call\n+ * with vanilla abd_alloc().\n+ *\n+ * LINUX ABD TODO - once vdev_disk.c has ABD page support change to vanilla\n+ */\n+abd_t *\n+abd_alloc_for_io(size_t size, boolean_t is_metadata)\n+{\n+\treturn (abd_alloc_linear(size, is_metadata));\n+}\n+\n+abd_t *\n+abd_alloc_for_io_nosleep(size_t size, boolean_t is_metadata)\n+{\n+\t/*\n+\t * ABD TODO -- Need to refactor to allow for nosleep option\n+\t */\n+\treturn (abd_alloc_linear(size, is_metadata));\n+}\n+\n+\n+/*\n+ * Allocate a new ABD to point to offset off of sabd. It shares the underlying\n+ * buffer data with sabd. Use abd_put() to free. sabd must not be freed while\n+ * any derived ABDs exist.\n+ */\n+static inline abd_t *\n+abd_get_offset_impl(abd_t *sabd, size_t off, size_t size)\n+{\n+\tabd_t *abd;\n+\n+\tabd_verify(sabd);\n+\tASSERT3U(off, <=, sabd->abd_size);\n+\n+\tif (abd_is_linear(sabd)) {\n+\t\tabd = abd_alloc_struct(0);\n+\n+\t\t/*\n+\t\t * Even if this buf is filesystem metadata, we only track that\n+\t\t * if we own the underlying data buffer, which is not true in\n+\t\t * this case. Therefore, we don't ever use ABD_FLAG_META here.\n+\t\t */\n+\t\tabd->abd_flags = ABD_FLAG_LINEAR;\n+\n+\t\tabd->abd_u.abd_linear.abd_buf =\n+\t\t    (char *)sabd->abd_u.abd_linear.abd_buf + off;\n+\t} else {\n+\t\tsize_t new_offset = sabd->abd_u.abd_scatter.abd_offset + off;\n+\t\tsize_t chunkcnt = abd_scatter_chunkcnt(sabd) -","path":"module/zfs/abd.c","position":506,"original_position":506,"commit_id":"644518621c76193c482fc562a34166032147d8d0","original_commit_id":"644518621c76193c482fc562a34166032147d8d0","user":{"login":"thegreatgazoo","id":6722662,"avatar_url":"https://avatars.githubusercontent.com/u/6722662?v=3","gravatar_id":"","url":"https://api.github.com/users/thegreatgazoo","html_url":"https://github.com/thegreatgazoo","followers_url":"https://api.github.com/users/thegreatgazoo/followers","following_url":"https://api.github.com/users/thegreatgazoo/following{/other_user}","gists_url":"https://api.github.com/users/thegreatgazoo/gists{/gist_id}","starred_url":"https://api.github.com/users/thegreatgazoo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/thegreatgazoo/subscriptions","organizations_url":"https://api.github.com/users/thegreatgazoo/orgs","repos_url":"https://api.github.com/users/thegreatgazoo/repos","events_url":"https://api.github.com/users/thegreatgazoo/events{/privacy}","received_events_url":"https://api.github.com/users/thegreatgazoo/received_events","type":"User","site_admin":false},"body":"It seemed that **chunkcnt** calculation ignored the **size** parameter. If true, then:\r\n- The returned _abd_ may have more pages than the caller actually wanted. This can be wasteful, e.g. raidz calls _abd_get_offset_size(16M_zio_abd, 0, 2M)_ to write the 1st 2M to the 1st data drive.\r\n- When the returned _abd_ is later freed, it may cause leaks as the _abd_ may have more pages than _abd->abd_size_ would indicate.","created_at":"2016-09-01T19:26:56Z","updated_at":"2016-09-01T19:26:56Z","html_url":"https://github.com/zfsonlinux/zfs/pull/5020#discussion_r77237884","pull_request_url":"https://api.github.com/repos/zfsonlinux/zfs/pulls/5020","_links":{"self":{"href":"https://api.github.com/repos/zfsonlinux/zfs/pulls/comments/77237884"},"html":{"href":"https://github.com/zfsonlinux/zfs/pull/5020#discussion_r77237884"},"pull_request":{"href":"https://api.github.com/repos/zfsonlinux/zfs/pulls/5020"}}},"pull_request":{"url":"https://api.github.com/repos/zfsonlinux/zfs/pulls/5020","id":82564094,"html_url":"https://github.com/zfsonlinux/zfs/pull/5020","diff_url":"https://github.com/zfsonlinux/zfs/pull/5020.diff","patch_url":"https://github.com/zfsonlinux/zfs/pull/5020.patch","issue_url":"https://api.github.com/repos/zfsonlinux/zfs/issues/5020","number":5020,"state":"open","locked":false,"title":"[WIP] SIMD RAIDZ on top of openzfs-abd","user":{"login":"ironMann","id":276684,"avatar_url":"https://avatars.githubusercontent.com/u/276684?v=3","gravatar_id":"","url":"https://api.github.com/users/ironMann","html_url":"https://github.com/ironMann","followers_url":"https://api.github.com/users/ironMann/followers","following_url":"https://api.github.com/users/ironMann/following{/other_user}","gists_url":"https://api.github.com/users/ironMann/gists{/gist_id}","starred_url":"https://api.github.com/users/ironMann/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ironMann/subscriptions","organizations_url":"https://api.github.com/users/ironMann/orgs","repos_url":"https://api.github.com/users/ironMann/repos","events_url":"https://api.github.com/users/ironMann/events{/privacy}","received_events_url":"https://api.github.com/users/ironMann/received_events","type":"User","site_admin":false},"body":"Enable zol simd on top of #5009\r\n\r\nTODO:\r\n\r\n- [x] use SIMD raidz with ABD\r\n- [x] use SIMD fletcher4 with ABD\r\n- [x] init userspace `PAGESIZE` in .ctor\r\n- [ ] use `kmap_atomic()` for raidz iterators. Preemption is already disabled during simd calculation, and `kmap()` is [\"prone to deadlocks when using in a nested fashion\"](https://www.kernel.org/doc/Documentation/vm/highmem.txt). Also, performance.\r\n- [ ] remove original raidz code? ABD buffers add lot of complexity to `vdev_raidz.c`","created_at":"2016-08-24T15:26:06Z","updated_at":"2016-09-01T19:26:56Z","closed_at":null,"merged_at":null,"merge_commit_sha":"55d128b26399e3ac0a429d0b80572e73d06a7821","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/zfsonlinux/zfs/pulls/5020/commits","review_comments_url":"https://api.github.com/repos/zfsonlinux/zfs/pulls/5020/comments","review_comment_url":"https://api.github.com/repos/zfsonlinux/zfs/pulls/comments{/number}","comments_url":"https://api.github.com/repos/zfsonlinux/zfs/issues/5020/comments","statuses_url":"https://api.github.com/repos/zfsonlinux/zfs/statuses/644518621c76193c482fc562a34166032147d8d0","head":{"label":"ironMann:openzfs-abd-raidz","ref":"openzfs-abd-raidz","sha":"644518621c76193c482fc562a34166032147d8d0","user":{"login":"ironMann","id":276684,"avatar_url":"https://avatars.githubusercontent.com/u/276684?v=3","gravatar_id":"","url":"https://api.github.com/users/ironMann","html_url":"https://github.com/ironMann","followers_url":"https://api.github.com/users/ironMann/followers","following_url":"https://api.github.com/users/ironMann/following{/other_user}","gists_url":"https://api.github.com/users/ironMann/gists{/gist_id}","starred_url":"https://api.github.com/users/ironMann/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ironMann/subscriptions","organizations_url":"https://api.github.com/users/ironMann/orgs","repos_url":"https://api.github.com/users/ironMann/repos","events_url":"https://api.github.com/users/ironMann/events{/privacy}","received_events_url":"https://api.github.com/users/ironMann/received_events","type":"User","site_admin":false},"repo":{"id":34014985,"name":"zfs","full_name":"ironMann/zfs","owner":{"login":"ironMann","id":276684,"avatar_url":"https://avatars.githubusercontent.com/u/276684?v=3","gravatar_id":"","url":"https://api.github.com/users/ironMann","html_url":"https://github.com/ironMann","followers_url":"https://api.github.com/users/ironMann/followers","following_url":"https://api.github.com/users/ironMann/following{/other_user}","gists_url":"https://api.github.com/users/ironMann/gists{/gist_id}","starred_url":"https://api.github.com/users/ironMann/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ironMann/subscriptions","organizations_url":"https://api.github.com/users/ironMann/orgs","repos_url":"https://api.github.com/users/ironMann/repos","events_url":"https://api.github.com/users/ironMann/events{/privacy}","received_events_url":"https://api.github.com/users/ironMann/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/ironMann/zfs","description":"Native ZFS for Linux","fork":true,"url":"https://api.github.com/repos/ironMann/zfs","forks_url":"https://api.github.com/repos/ironMann/zfs/forks","keys_url":"https://api.github.com/repos/ironMann/zfs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ironMann/zfs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ironMann/zfs/teams","hooks_url":"https://api.github.com/repos/ironMann/zfs/hooks","issue_events_url":"https://api.github.com/repos/ironMann/zfs/issues/events{/number}","events_url":"https://api.github.com/repos/ironMann/zfs/events","assignees_url":"https://api.github.com/repos/ironMann/zfs/assignees{/user}","branches_url":"https://api.github.com/repos/ironMann/zfs/branches{/branch}","tags_url":"https://api.github.com/repos/ironMann/zfs/tags","blobs_url":"https://api.github.com/repos/ironMann/zfs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ironMann/zfs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ironMann/zfs/git/refs{/sha}","trees_url":"https://api.github.com/repos/ironMann/zfs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ironMann/zfs/statuses/{sha}","languages_url":"https://api.github.com/repos/ironMann/zfs/languages","stargazers_url":"https://api.github.com/repos/ironMann/zfs/stargazers","contributors_url":"https://api.github.com/repos/ironMann/zfs/contributors","subscribers_url":"https://api.github.com/repos/ironMann/zfs/subscribers","subscription_url":"https://api.github.com/repos/ironMann/zfs/subscription","commits_url":"https://api.github.com/repos/ironMann/zfs/commits{/sha}","git_commits_url":"https://api.github.com/repos/ironMann/zfs/git/commits{/sha}","comments_url":"https://api.github.com/repos/ironMann/zfs/comments{/number}","issue_comment_url":"https://api.github.com/repos/ironMann/zfs/issues/comments{/number}","contents_url":"https://api.github.com/repos/ironMann/zfs/contents/{+path}","compare_url":"https://api.github.com/repos/ironMann/zfs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ironMann/zfs/merges","archive_url":"https://api.github.com/repos/ironMann/zfs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ironMann/zfs/downloads","issues_url":"https://api.github.com/repos/ironMann/zfs/issues{/number}","pulls_url":"https://api.github.com/repos/ironMann/zfs/pulls{/number}","milestones_url":"https://api.github.com/repos/ironMann/zfs/milestones{/number}","notifications_url":"https://api.github.com/repos/ironMann/zfs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ironMann/zfs/labels{/name}","releases_url":"https://api.github.com/repos/ironMann/zfs/releases{/id}","deployments_url":"https://api.github.com/repos/ironMann/zfs/deployments","created_at":"2015-04-15T19:47:05Z","updated_at":"2016-02-10T14:11:48Z","pushed_at":"2016-09-01T17:47:50Z","git_url":"git://github.com/ironMann/zfs.git","ssh_url":"git@github.com:ironMann/zfs.git","clone_url":"https://github.com/ironMann/zfs.git","svn_url":"https://github.com/ironMann/zfs","homepage":"http://zfsonlinux.org/","size":32477,"stargazers_count":0,"watchers_count":0,"language":"C","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"zfsonlinux:master","ref":"master","sha":"9907cc1cc8c16fa2c7c03aa33264153ca2bdad6c","user":{"login":"zfsonlinux","id":575083,"avatar_url":"https://avatars.githubusercontent.com/u/575083?v=3","gravatar_id":"","url":"https://api.github.com/users/zfsonlinux","html_url":"https://github.com/zfsonlinux","followers_url":"https://api.github.com/users/zfsonlinux/followers","following_url":"https://api.github.com/users/zfsonlinux/following{/other_user}","gists_url":"https://api.github.com/users/zfsonlinux/gists{/gist_id}","starred_url":"https://api.github.com/users/zfsonlinux/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zfsonlinux/subscriptions","organizations_url":"https://api.github.com/users/zfsonlinux/orgs","repos_url":"https://api.github.com/users/zfsonlinux/repos","events_url":"https://api.github.com/users/zfsonlinux/events{/privacy}","received_events_url":"https://api.github.com/users/zfsonlinux/received_events","type":"Organization","site_admin":false},"repo":{"id":437011,"name":"zfs","full_name":"zfsonlinux/zfs","owner":{"login":"zfsonlinux","id":575083,"avatar_url":"https://avatars.githubusercontent.com/u/575083?v=3","gravatar_id":"","url":"https://api.github.com/users/zfsonlinux","html_url":"https://github.com/zfsonlinux","followers_url":"https://api.github.com/users/zfsonlinux/followers","following_url":"https://api.github.com/users/zfsonlinux/following{/other_user}","gists_url":"https://api.github.com/users/zfsonlinux/gists{/gist_id}","starred_url":"https://api.github.com/users/zfsonlinux/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zfsonlinux/subscriptions","organizations_url":"https://api.github.com/users/zfsonlinux/orgs","repos_url":"https://api.github.com/users/zfsonlinux/repos","events_url":"https://api.github.com/users/zfsonlinux/events{/privacy}","received_events_url":"https://api.github.com/users/zfsonlinux/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/zfsonlinux/zfs","description":"ZFS on Linux - the official OpenZFS implementation for Linux.","fork":false,"url":"https://api.github.com/repos/zfsonlinux/zfs","forks_url":"https://api.github.com/repos/zfsonlinux/zfs/forks","keys_url":"https://api.github.com/repos/zfsonlinux/zfs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/zfsonlinux/zfs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/zfsonlinux/zfs/teams","hooks_url":"https://api.github.com/repos/zfsonlinux/zfs/hooks","issue_events_url":"https://api.github.com/repos/zfsonlinux/zfs/issues/events{/number}","events_url":"https://api.github.com/repos/zfsonlinux/zfs/events","assignees_url":"https://api.github.com/repos/zfsonlinux/zfs/assignees{/user}","branches_url":"https://api.github.com/repos/zfsonlinux/zfs/branches{/branch}","tags_url":"https://api.github.com/repos/zfsonlinux/zfs/tags","blobs_url":"https://api.github.com/repos/zfsonlinux/zfs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/zfsonlinux/zfs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/zfsonlinux/zfs/git/refs{/sha}","trees_url":"https://api.github.com/repos/zfsonlinux/zfs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/zfsonlinux/zfs/statuses/{sha}","languages_url":"https://api.github.com/repos/zfsonlinux/zfs/languages","stargazers_url":"https://api.github.com/repos/zfsonlinux/zfs/stargazers","contributors_url":"https://api.github.com/repos/zfsonlinux/zfs/contributors","subscribers_url":"https://api.github.com/repos/zfsonlinux/zfs/subscribers","subscription_url":"https://api.github.com/repos/zfsonlinux/zfs/subscription","commits_url":"https://api.github.com/repos/zfsonlinux/zfs/commits{/sha}","git_commits_url":"https://api.github.com/repos/zfsonlinux/zfs/git/commits{/sha}","comments_url":"https://api.github.com/repos/zfsonlinux/zfs/comments{/number}","issue_comment_url":"https://api.github.com/repos/zfsonlinux/zfs/issues/comments{/number}","contents_url":"https://api.github.com/repos/zfsonlinux/zfs/contents/{+path}","compare_url":"https://api.github.com/repos/zfsonlinux/zfs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/zfsonlinux/zfs/merges","archive_url":"https://api.github.com/repos/zfsonlinux/zfs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/zfsonlinux/zfs/downloads","issues_url":"https://api.github.com/repos/zfsonlinux/zfs/issues{/number}","pulls_url":"https://api.github.com/repos/zfsonlinux/zfs/pulls{/number}","milestones_url":"https://api.github.com/repos/zfsonlinux/zfs/milestones{/number}","notifications_url":"https://api.github.com/repos/zfsonlinux/zfs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/zfsonlinux/zfs/labels{/name}","releases_url":"https://api.github.com/repos/zfsonlinux/zfs/releases{/id}","deployments_url":"https://api.github.com/repos/zfsonlinux/zfs/deployments","created_at":"2009-12-14T20:20:34Z","updated_at":"2016-09-01T14:46:42Z","pushed_at":"2016-09-01T18:42:42Z","git_url":"git://github.com/zfsonlinux/zfs.git","ssh_url":"git@github.com:zfsonlinux/zfs.git","clone_url":"https://github.com/zfsonlinux/zfs.git","svn_url":"https://github.com/zfsonlinux/zfs","homepage":"http://zfsonlinux.org/","size":58951,"stargazers_count":2022,"watchers_count":2022,"language":"C","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":506,"mirror_url":null,"open_issues_count":1032,"forks":506,"open_issues":1032,"watchers":2022,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/zfsonlinux/zfs/pulls/5020"},"html":{"href":"https://github.com/zfsonlinux/zfs/pull/5020"},"issue":{"href":"https://api.github.com/repos/zfsonlinux/zfs/issues/5020"},"comments":{"href":"https://api.github.com/repos/zfsonlinux/zfs/issues/5020/comments"},"review_comments":{"href":"https://api.github.com/repos/zfsonlinux/zfs/pulls/5020/comments"},"review_comment":{"href":"https://api.github.com/repos/zfsonlinux/zfs/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/zfsonlinux/zfs/pulls/5020/commits"},"statuses":{"href":"https://api.github.com/repos/zfsonlinux/zfs/statuses/644518621c76193c482fc562a34166032147d8d0"}}}}
{"actor":{"display_login":"thegreatgazoo"}}