Pull updates from Andrew Morton: "Most of -mm and quite a number of other subsystems: hotfixes, scripts, ocfs2, misc, lib, binfmt, init, reiserfs, exec, dma-mapping, kcov. MM is fairly quiet this time. Holidays, I assume" * emailed patches from Andrew Morton <akpm@linux-foundation.org>: (118 commits) kcov: ignore fault-inject and stacktrace include/linux/io-mapping.h-mapping: use PHYS_PFN() macro in io_mapping_map_atomic_wc() execve: warn if process starts with executable stack reiserfs: prevent NULL pointer dereference in reiserfs_insert_item() init/main.c: fix misleading "This architecture does not have kernel memory protection" message init/main.c: fix quoted value handling in unknown_bootoption init/main.c: remove unnecessary repair_env_string in do_initcall_level init/main.c: log arguments and environment passed to init fs/binfmt_elf.c: coredump: allow process with empty address space to coredump fs/binfmt_elf.c: coredump: delete duplicated overflow check fs/binfmt_elf.c: coredump: allocate core ELF header on stack fs/binfmt_elf.c: make BAD_ADDR() unlikely fs/binfmt_elf.c: better codegen around current->mm fs/binfmt_elf.c: don't copy ELF header around fs/binfmt_elf.c: fix ->start_code calculation fs/binfmt_elf.c: smaller code generation around auxv vector fill lib/find_bit.c: uninline helper _find_next_bit() lib/find_bit.c: join _find_next_bit{_le} uapi: rename ext2_swab() to swab() and share globally in swab.h lib/scatterlist.c: adjust indentation in __sg_alloc_table ...
Unified · Split
| @@ -834,6 +834,18 @@ · 833 unmodified lines | |||
| 834 | dump out devices still on the deferred probe list after | 834 | dump out devices still on the deferred probe list after |
| 835 | retrying. | 835 | retrying. |
| 836 | 836 | ||
| 837 | dfltcc= [HW,S390] | ||
| 838 | Format: { on | off | def_only | inf_only | always } | ||
| 839 | on: s390 zlib hardware support for compression on | ||
| 840 | level 1 and decompression (default) | ||
| 841 | off: No s390 zlib hardware support | ||
| 842 | def_only: s390 zlib hardware support for deflate | ||
| 843 | only (compression on level 1) | ||
| 844 | inf_only: s390 zlib hardware support for inflate | ||
| 845 | only (decompression) | ||
| 846 | always: Same as 'on' but ignores the selected compression | ||
| 847 | level always using hardware support (used for debugging) | ||
| 848 | |||
| 837 | dhash_entries= [KNL] | 849 | dhash_entries= [KNL] |
| 838 | Set number of hash buckets for dentry cache. | 850 | Set number of hash buckets for dentry cache. |
| 839 | 851 | ||
| @@ -31,6 +31,7 @@ Core utilities · 30 unmodified lines | |||
| 31 | generic-radix-tree | 31 | generic-radix-tree |
| 32 | memory-allocation | 32 | memory-allocation |
| 33 | mm-api | 33 | mm-api |
| 34 | pin_user_pages | ||
| 34 | gfp_mask-from-fs-io | 35 | gfp_mask-from-fs-io |
| 35 | timekeeping | 36 | timekeeping |
| 36 | boot-time-mm | 37 | boot-time-mm |
| @@ -0,0 +1,232 @@ | |||
| 1 | .. SPDX-License-Identifier: GPL-2.0 | ||
| 2 | |||
| 3 | ==================================================== | ||
| 4 | pin_user_pages() and related calls | ||
| 5 | ==================================================== | ||
| 6 | |||
| 7 | .. contents:: :local: | ||
| 8 | |||
| 9 | Overview | ||
| 10 | ======== | ||
| 11 | |||
| 12 | This document describes the following functions:: | ||
| 13 | |||
| 14 | pin_user_pages() | ||
| 15 | pin_user_pages_fast() | ||
| 16 | pin_user_pages_remote() | ||
| 17 | |||
| 18 | Basic description of FOLL_PIN | ||
| 19 | ============================= | ||
| 20 | |||
| 21 | FOLL_PIN and FOLL_LONGTERM are flags that can be passed to the get_user_pages*() | ||
| 22 | ("gup") family of functions. FOLL_PIN has significant interactions and | ||
| 23 | interdependencies with FOLL_LONGTERM, so both are covered here. | ||
| 24 | |||
| 25 | FOLL_PIN is internal to gup, meaning that it should not appear at the gup call | ||
| 26 | sites. This allows the associated wrapper functions (pin_user_pages*() and | ||
| 27 | others) to set the correct combination of these flags, and to check for problems | ||
| 28 | as well. | ||
| 29 | |||
| 30 | FOLL_LONGTERM, on the other hand, *is* allowed to be set at the gup call sites. | ||
| 31 | This is in order to avoid creating a large number of wrapper functions to cover | ||
| 32 | all combinations of get*(), pin*(), FOLL_LONGTERM, and more. Also, the | ||
| 33 | pin_user_pages*() APIs are clearly distinct from the get_user_pages*() APIs, so | ||
| 34 | that's a natural dividing line, and a good point to make separate wrapper calls. | ||
| 35 | In other words, use pin_user_pages*() for DMA-pinned pages, and | ||
| 36 | get_user_pages*() for other cases. There are four cases described later on in | ||
| 37 | this document, to further clarify that concept. | ||
| 38 | |||
| 39 | FOLL_PIN and FOLL_GET are mutually exclusive for a given gup call. However, | ||
| 40 | multiple threads and call sites are free to pin the same struct pages, via both | ||
| 41 | FOLL_PIN and FOLL_GET. It's just the call site that needs to choose one or the | ||
| 42 | other, not the struct page(s). | ||
| 43 | |||
| 44 | The FOLL_PIN implementation is nearly the same as FOLL_GET, except that FOLL_PIN | ||
| 45 | uses a different reference counting technique. | ||
| 46 | |||
| 47 | FOLL_PIN is a prerequisite to FOLL_LONGTERM. Another way of saying that is, | ||
| 48 | FOLL_LONGTERM is a specific case, more restrictive case of FOLL_PIN. | ||
| 49 | |||
| 50 | Which flags are set by each wrapper | ||
| 51 | =================================== | ||
| 52 | |||
| 53 | For these pin_user_pages*() functions, FOLL_PIN is OR'd in with whatever gup | ||
| 54 | flags the caller provides. The caller is required to pass in a non-null struct | ||
| 55 | pages* array, and the function then pin pages by incrementing each by a special | ||
| 56 | value. For now, that value is +1, just like get_user_pages*().:: | ||
| 57 | |||
| 58 | Function | ||
| 59 | -------- | ||
| 60 | pin_user_pages FOLL_PIN is always set internally by this function. | ||
| 61 | pin_user_pages_fast FOLL_PIN is always set internally by this function. | ||
| 62 | pin_user_pages_remote FOLL_PIN is always set internally by this function. | ||
| 63 | |||
| 64 | For these get_user_pages*() functions, FOLL_GET might not even be specified. | ||
| 65 | Behavior is a little more complex than above. If FOLL_GET was *not* specified, | ||
| 66 | but the caller passed in a non-null struct pages* array, then the function | ||
| 67 | sets FOLL_GET for you, and proceeds to pin pages by incrementing the refcount | ||
| 68 | of each page by +1.:: | ||
| 69 | |||
| 70 | Function | ||
| 71 | -------- | ||
| 72 | get_user_pages FOLL_GET is sometimes set internally by this function. | ||
| 73 | get_user_pages_fast FOLL_GET is sometimes set internally by this function. | ||
| 74 | get_user_pages_remote FOLL_GET is sometimes set internally by this function. | ||
| 75 | |||
| 76 | Tracking dma-pinned pages | ||
| 77 | ========================= | ||
| 78 | |||
| 79 | Some of the key design constraints, and solutions, for tracking dma-pinned | ||
| 80 | pages: | ||
| 81 | |||
| 82 | * An actual reference count, per struct page, is required. This is because | ||
| 83 | multiple processes may pin and unpin a page. | ||
| 84 | |||
| 85 | * False positives (reporting that a page is dma-pinned, when in fact it is not) | ||
| 86 | are acceptable, but false negatives are not. | ||
| 87 | |||
| 88 | * struct page may not be increased in size for this, and all fields are already | ||
| 89 | used. | ||
| 90 | |||
| 91 | * Given the above, we can overload the page->_refcount field by using, sort of, | ||
| 92 | the upper bits in that field for a dma-pinned count. "Sort of", means that, | ||
| 93 | rather than dividing page->_refcount into bit fields, we simple add a medium- | ||
| 94 | large value (GUP_PIN_COUNTING_BIAS, initially chosen to be 1024: 10 bits) to | ||
| 95 | page->_refcount. This provides fuzzy behavior: if a page has get_page() called | ||
| 96 | on it 1024 times, then it will appear to have a single dma-pinned count. | ||
| 97 | And again, that's acceptable. | ||
| 98 | |||
| 99 | This also leads to limitations: there are only 31-10==21 bits available for a | ||
| 100 | counter that increments 10 bits at a time. | ||
| 101 | |||
| 102 | TODO: for 1GB and larger huge pages, this is cutting it close. That's because | ||
| 103 | when pin_user_pages() follows such pages, it increments the head page by "1" | ||
| 104 | (where "1" used to mean "+1" for get_user_pages(), but now means "+1024" for | ||
| 105 | pin_user_pages()) for each tail page. So if you have a 1GB huge page: | ||
| 106 | |||
| 107 | * There are 256K (18 bits) worth of 4 KB tail pages. | ||
| 108 | * There are 21 bits available to count up via GUP_PIN_COUNTING_BIAS (that is, | ||
| 109 | 10 bits at a time) | ||
| 110 | * There are 21 - 18 == 3 bits available to count. Except that there aren't, | ||
| 111 | because you need to allow for a few normal get_page() calls on the head page, | ||
| 112 | as well. Fortunately, the approach of using addition, rather than "hard" | ||
| 113 | bitfields, within page->_refcount, allows for sharing these bits gracefully. | ||
| 114 | But we're still looking at about 8 references. | ||
| 115 | |||
| 116 | This, however, is a missing feature more than anything else, because it's easily | ||
| 117 | solved by addressing an obvious inefficiency in the original get_user_pages() | ||
| 118 | approach of retrieving pages: stop treating all the pages as if they were | ||
| 119 | PAGE_SIZE. Retrieve huge pages as huge pages. The callers need to be aware of | ||
| 120 | this, so some work is required. Once that's in place, this limitation mostly | ||
| 121 | disappears from view, because there will be ample refcounting range available. | ||
| 122 | |||
| 123 | * Callers must specifically request "dma-pinned tracking of pages". In other | ||
| 124 | words, just calling get_user_pages() will not suffice; a new set of functions, | ||
| 125 | pin_user_page() and related, must be used. | ||
| 126 | |||
| 127 | FOLL_PIN, FOLL_GET, FOLL_LONGTERM: when to use which flags | ||
| 128 | ========================================================== | ||
| 129 | |||
| 130 | Thanks to Jan Kara, Vlastimil Babka and several other -mm people, for describing | ||
| 131 | these categories: | ||
| 132 | |||
| 133 | CASE 1: Direct IO (DIO) | ||
| 134 | ----------------------- | ||
| 135 | There are GUP references to pages that are serving | ||
| 136 | as DIO buffers. These buffers are needed for a relatively short time (so they | ||
| 137 | are not "long term"). No special synchronization with page_mkclean() or | ||
| 138 | munmap() is provided. Therefore, flags to set at the call site are: :: | ||
| 139 | |||
| 140 | FOLL_PIN | ||
| 141 | |||
| 142 | ...but rather than setting FOLL_PIN directly, call sites should use one of | ||
| 143 | the pin_user_pages*() routines that set FOLL_PIN. | ||
| 144 | |||
| 145 | CASE 2: RDMA | ||
| 146 | ------------ | ||
| 147 | There are GUP references to pages that are serving as DMA | ||
| 148 | buffers. These buffers are needed for a long time ("long term"). No special | ||
| 149 | synchronization with page_mkclean() or munmap() is provided. Therefore, flags | ||
| 150 | to set at the call site are: :: | ||
| 151 | |||
| 152 | FOLL_PIN | FOLL_LONGTERM | ||
| 153 | |||
| 154 | NOTE: Some pages, such as DAX pages, cannot be pinned with longterm pins. That's | ||
| 155 | because DAX pages do not have a separate page cache, and so "pinning" implies | ||
| 156 | locking down file system blocks, which is not (yet) supported in that way. | ||
| 157 | |||
| 158 | CASE 3: Hardware with page faulting support | ||
| 159 | ------------------------------------------- | ||
| 160 | Here, a well-written driver doesn't normally need to pin pages at all. However, | ||
| 161 | if the driver does choose to do so, it can register MMU notifiers for the range, | ||
| 162 | and will be called back upon invalidation. Either way (avoiding page pinning, or | ||
| 163 | using MMU notifiers to unpin upon request), there is proper synchronization with | ||
| 164 | both filesystem and mm (page_mkclean(), munmap(), etc). | ||
| 165 | |||
| 166 | Therefore, neither flag needs to be set. | ||
| 167 | |||
| 168 | In this case, ideally, neither get_user_pages() nor pin_user_pages() should be | ||
| 169 | called. Instead, the software should be written so that it does not pin pages. | ||
| 170 | This allows mm and filesystems to operate more efficiently and reliably. | ||
| 171 | |||
| 172 | CASE 4: Pinning for struct page manipulation only | ||
| 173 | ------------------------------------------------- | ||
| 174 | Here, normal GUP calls are sufficient, so neither flag needs to be set. | ||
| 175 | |||
| 176 | page_dma_pinned(): the whole point of pinning | ||
| 177 | ============================================= | ||
| 178 | |||
| 179 | The whole point of marking pages as "DMA-pinned" or "gup-pinned" is to be able | ||
| 180 | to query, "is this page DMA-pinned?" That allows code such as page_mkclean() | ||
| 181 | (and file system writeback code in general) to make informed decisions about | ||
| 182 | what to do when a page cannot be unmapped due to such pins. | ||
| 183 | |||
| 184 | What to do in those cases is the subject of a years-long series of discussions | ||
| 185 | and debates (see the References at the end of this document). It's a TODO item | ||
| 186 | here: fill in the details once that's worked out. Meanwhile, it's safe to say | ||
| 187 | that having this available: :: | ||
| 188 | |||
| 189 | static inline bool page_dma_pinned(struct page *page) | ||
| 190 | |||
| 191 | ...is a prerequisite to solving the long-running gup+DMA problem. | ||
| 192 | |||
| 193 | Another way of thinking about FOLL_GET, FOLL_PIN, and FOLL_LONGTERM | ||
| 194 | =================================================================== | ||
| 195 | |||
| 196 | Another way of thinking about these flags is as a progression of restrictions: | ||
| 197 | FOLL_GET is for struct page manipulation, without affecting the data that the | ||
| 198 | struct page refers to. FOLL_PIN is a *replacement* for FOLL_GET, and is for | ||
| 199 | short term pins on pages whose data *will* get accessed. As such, FOLL_PIN is | ||
| 200 | a "more severe" form of pinning. And finally, FOLL_LONGTERM is an even more | ||
| 201 | restrictive case that has FOLL_PIN as a prerequisite: this is for pages that | ||
| 202 | will be pinned longterm, and whose data will be accessed. | ||
| 203 | |||
| 204 | Unit testing | ||
| 205 | ============ | ||
| 206 | This file:: | ||
| 207 | |||
| 208 | tools/testing/selftests/vm/gup_benchmark.c | ||
| 209 | |||
| 210 | has the following new calls to exercise the new pin*() wrapper functions: | ||
| 211 | |||
| 212 | * PIN_FAST_BENCHMARK (./gup_benchmark -a) | ||
| 213 | * PIN_BENCHMARK (./gup_benchmark -b) | ||
| 214 | |||
| 215 | You can monitor how many total dma-pinned pages have been acquired and released | ||
| 216 | since the system was booted, via two new /proc/vmstat entries: :: | ||
| 217 | |||
| 218 | /proc/vmstat/nr_foll_pin_requested | ||
| 219 | /proc/vmstat/nr_foll_pin_requested | ||
| 220 | |||
| 221 | Those are both going to show zero, unless CONFIG_DEBUG_VM is set. This is | ||
| 222 | because there is a noticeable performance drop in unpin_user_page(), when they | ||
| 223 | are activated. | ||
| 224 | |||
| 225 | References | ||
| 226 | ========== | ||
| 227 | |||
| 228 | * `Some slow progress on get_user_pages() (Apr 2, 2019) <https://lwn.net/Articles/784574/>`_ | ||
| 229 | * `DMA and get_user_pages() (LPC: Dec 12, 2018) <https://lwn.net/Articles/774411/>`_ | ||
| 230 | * `The trouble with get_user_pages() (Apr 30, 2018) <https://lwn.net/Articles/753027/>`_ | ||
| 231 | |||
| 232 | John Hubbard, October, 2019 | ||
| @@ -130,6 +130,19 @@ checking for the same-value filled pages during store operation. However, the · 129 unmodified lines | |||
| 130 | existing pages which are marked as same-value filled pages remain stored | 130 | existing pages which are marked as same-value filled pages remain stored |
| 131 | unchanged in zswap until they are either loaded or invalidated. | 131 | unchanged in zswap until they are either loaded or invalidated. |
| 132 | 132 | ||
| 133 | To prevent zswap from shrinking pool when zswap is full and there's a high | ||
| 134 | pressure on swap (this will result in flipping pages in and out zswap pool | ||
| 135 | without any real benefit but with a performance drop for the system), a | ||
| 136 | special parameter has been introduced to implement a sort of hysteresis to | ||
| 137 | refuse taking pages into zswap pool until it has sufficient space if the limit | ||
| 138 | has been hit. To set the threshold at which zswap would start accepting pages | ||
| 139 | again after it became full, use the sysfs ``accept_threhsold_percent`` | ||
| 140 | attribute, e. g.:: | ||
| 141 | |||
| 142 | echo 80 > /sys/module/zswap/parameters/accept_threhsold_percent | ||
| 143 | |||
| 144 | Setting this parameter to 100 will disable the hysteresis. | ||
| 145 | |||
| 133 | A debugfs interface is provided for various statistic about pool size, number | 146 | A debugfs interface is provided for various statistic about pool size, number |
| 134 | of pages stored, same-value filled pages and various counters for the reasons | 147 | of pages stored, same-value filled pages and various counters for the reasons |
| 135 | pages are rejected. | 148 | pages are rejected. |
| @@ -103,7 +103,7 @@ static long mm_iommu_do_alloc(struct mm_struct *mm, unsigned long ua, · 102 unmodified lines | |||
| 103 | for (entry = 0; entry < entries; entry += chunk) { | 103 | for (entry = 0; entry < entries; entry += chunk) { |
| 104 | unsigned long n = min(entries - entry, chunk); | 104 | unsigned long n = min(entries - entry, chunk); |
| 105 | 105 | ||
| 106 | ret = get_user_pages(ua + (entry << PAGE_SHIFT), n, | 106 | ret = pin_user_pages(ua + (entry << PAGE_SHIFT), n, |
| 107 | FOLL_WRITE | FOLL_LONGTERM, | 107 | FOLL_WRITE | FOLL_LONGTERM, |
| 108 | mem->hpages + entry, NULL); | 108 | mem->hpages + entry, NULL); |
| 109 | if (ret == n) { | 109 | if (ret == n) { |
| @@ -167,9 +167,8 @@ good_exit: · 57 unmodified lines | |||
| 167 | return 0; | 167 | return 0; |
| 168 | 168 | ||
| 169 | free_exit: | 169 | free_exit: |
| 170 | /* free the reference taken */ | 170 | /* free the references taken */ |
| 171 | for (i = 0; i < pinned; i++) | 171 | unpin_user_pages(mem->hpages, pinned); |
| 172 | put_page(mem->hpages[i]); | ||
| 173 | 172 | ||
| 174 | vfree(mem->hpas); | 173 | vfree(mem->hpas); |
| 175 | kfree(mem); | 174 | kfree(mem); |
| @@ -215,7 +214,8 @@ static void mm_iommu_unpin(struct mm_iommu_table_group_mem_t *mem) · 39 unmodified lines | |||
| 215 | if (mem->hpas[i] & MM_IOMMU_TABLE_GROUP_PAGE_DIRTY) | 214 | if (mem->hpas[i] & MM_IOMMU_TABLE_GROUP_PAGE_DIRTY) |
| 216 | SetPageDirty(page); | 215 | SetPageDirty(page); |
| 217 | 216 | ||
| 218 | put_page(page); | 217 | unpin_user_page(page); |
| 218 | |||
| 219 | mem->hpas[i] = 0; | 219 | mem->hpas[i] = 0; |
| 220 | } | 220 | } |
| 221 | } | 221 | } |
| @@ -30,13 +30,13 @@ extern unsigned char _compressed_start[]; · 29 unmodified lines | |||
| 30 | extern unsigned char _compressed_end[]; | 30 | extern unsigned char _compressed_end[]; |
| 31 | 31 | ||
| 32 | #ifdef CONFIG_HAVE_KERNEL_BZIP2 | 32 | #ifdef CONFIG_HAVE_KERNEL_BZIP2 |
| 33 | #define HEAP_SIZE 0x400000 | 33 | #define BOOT_HEAP_SIZE 0x400000 |
| 34 | #else | 34 | #else |
| 35 | #define HEAP_SIZE 0x10000 | 35 | #define BOOT_HEAP_SIZE 0x10000 |
| 36 | #endif | 36 | #endif |
| 37 | 37 | ||
| 38 | static unsigned long free_mem_ptr = (unsigned long) _end; | 38 | static unsigned long free_mem_ptr = (unsigned long) _end; |
| 39 | static unsigned long free_mem_end_ptr = (unsigned long) _end + HEAP_SIZE; | 39 | static unsigned long free_mem_end_ptr = (unsigned long) _end + BOOT_HEAP_SIZE; |
| 40 | 40 | ||
| 41 | #ifdef CONFIG_KERNEL_GZIP | 41 | #ifdef CONFIG_KERNEL_GZIP |
| 42 | #include "../../../../lib/decompress_inflate.c" | 42 | #include "../../../../lib/decompress_inflate.c" |
| @@ -62,7 +62,7 @@ static unsigned long free_mem_end_ptr = (unsigned long) _end + HEAP_SIZE; · 19 unmodified lines | |||
| 62 | #include "../../../../lib/decompress_unxz.c" | 62 | #include "../../../../lib/decompress_unxz.c" |
| 63 | #endif | 63 | #endif |
| 64 | 64 | ||
| 65 | #define decompress_offset ALIGN((unsigned long)_end + HEAP_SIZE, PAGE_SIZE) | 65 | #define decompress_offset ALIGN((unsigned long)_end + BOOT_HEAP_SIZE, PAGE_SIZE) |
| 66 | 66 | ||
| 67 | unsigned long mem_safe_offset(void) | 67 | unsigned long mem_safe_offset(void) |
| 68 | { | 68 | { |
| @@ -14,6 +14,7 @@ · 13 unmodified lines | |||
| 14 | char __bootdata(early_command_line)[COMMAND_LINE_SIZE]; | 14 | char __bootdata(early_command_line)[COMMAND_LINE_SIZE]; |
| 15 | struct ipl_parameter_block __bootdata_preserved(ipl_block); | 15 | struct ipl_parameter_block __bootdata_preserved(ipl_block); |
| 16 | int __bootdata_preserved(ipl_block_valid); | 16 | int __bootdata_preserved(ipl_block_valid); |
| 17 | unsigned int __bootdata_preserved(zlib_dfltcc_support) = ZLIB_DFLTCC_FULL; | ||
| 17 | 18 | ||
| 18 | unsigned long __bootdata(vmalloc_size) = VMALLOC_DEFAULT_SIZE; | 19 | unsigned long __bootdata(vmalloc_size) = VMALLOC_DEFAULT_SIZE; |
| 19 | unsigned long __bootdata(memory_end); | 20 | unsigned long __bootdata(memory_end); |
| @@ -229,6 +230,19 @@ void parse_boot_command_line(void) · 209 unmodified lines | |||
| 229 | if (!strcmp(param, "vmalloc") && val) | 230 | if (!strcmp(param, "vmalloc") && val) |
| 230 | vmalloc_size = round_up(memparse(val, NULL), PAGE_SIZE); | 231 | vmalloc_size = round_up(memparse(val, NULL), PAGE_SIZE); |
| 231 | 232 | ||
| 233 | if (!strcmp(param, "dfltcc")) { | ||
| 234 | if (!strcmp(val, "off")) | ||
| 235 | zlib_dfltcc_support = ZLIB_DFLTCC_DISABLED; | ||
| 236 | else if (!strcmp(val, "on")) | ||
| 237 | zlib_dfltcc_support = ZLIB_DFLTCC_FULL; | ||
| 238 | else if (!strcmp(val, "def_only")) | ||
| 239 | zlib_dfltcc_support = ZLIB_DFLTCC_DEFLATE_ONLY; | ||
| 240 | else if (!strcmp(val, "inf_only")) | ||
| 241 | zlib_dfltcc_support = ZLIB_DFLTCC_INFLATE_ONLY; | ||
| 242 | else if (!strcmp(val, "always")) | ||
| 243 | zlib_dfltcc_support = ZLIB_DFLTCC_FULL_DEBUG; | ||
| 244 | } | ||
| 245 | |||
| 232 | if (!strcmp(param, "noexec")) { | 246 | if (!strcmp(param, "noexec")) { |
| 233 | rc = kstrtobool(val, &enabled); | 247 | rc = kstrtobool(val, &enabled); |
| 234 | if (!rc && !enabled) | 248 | if (!rc && !enabled) |
| @@ -79,6 +79,13 @@ struct parmarea { · 78 unmodified lines | |||
| 79 | char command_line[ARCH_COMMAND_LINE_SIZE]; /* 0x10480 */ | 79 | char command_line[ARCH_COMMAND_LINE_SIZE]; /* 0x10480 */ |
| 80 | }; | 80 | }; |
| 81 | 81 | ||
| 82 | extern unsigned int zlib_dfltcc_support; | ||
| 83 | #define ZLIB_DFLTCC_DISABLED 0 | ||
| 84 | #define ZLIB_DFLTCC_FULL 1 | ||
| 85 | #define ZLIB_DFLTCC_DEFLATE_ONLY 2 | ||
| 86 | #define ZLIB_DFLTCC_INFLATE_ONLY 3 | ||
| 87 | #define ZLIB_DFLTCC_FULL_DEBUG 4 | ||
| 88 | |||
| 82 | extern int noexec_disabled; | 89 | extern int noexec_disabled; |
| 83 | extern int memory_end_set; | 90 | extern int memory_end_set; |
| 84 | extern unsigned long memory_end; | 91 | extern unsigned long memory_end; |
| @@ -111,6 +111,8 @@ unsigned long __bootdata_preserved(__etext_dma); · 110 unmodified lines | |||
| 111 | unsigned long __bootdata_preserved(__sdma); | 111 | unsigned long __bootdata_preserved(__sdma); |
| 112 | unsigned long __bootdata_preserved(__edma); | 112 | unsigned long __bootdata_preserved(__edma); |
| 113 | unsigned long __bootdata_preserved(__kaslr_offset); | 113 | unsigned long __bootdata_preserved(__kaslr_offset); |
| 114 | unsigned int __bootdata_preserved(zlib_dfltcc_support); | ||
| 115 | EXPORT_SYMBOL(zlib_dfltcc_support); | ||
| 114 | 116 | ||
| 115 | unsigned long VMALLOC_START; | 117 | unsigned long VMALLOC_START; |
| 116 | EXPORT_SYMBOL(VMALLOC_START); | 118 | EXPORT_SYMBOL(VMALLOC_START); |
| @@ -759,14 +761,6 @@ static void __init free_mem_detect_info(void) · 642 unmodified lines | |||
| 759 | memblock_free(start, size); | 761 | memblock_free(start, size); |
| 760 | } | 762 | } |
| 761 | 763 | ||
| 762 | static void __init memblock_physmem_add(phys_addr_t start, phys_addr_t size) | ||
| 763 | { | ||
| 764 | memblock_dbg("memblock_physmem_add: [%#016llx-%#016llx]\n", | ||
| 765 | start, start + size - 1); | ||
| 766 | memblock_add_range(&memblock.memory, start, size, 0, 0); | ||
| 767 | memblock_add_range(&memblock.physmem, start, size, 0, 0); | ||
| 768 | } | ||
| 769 | |||
| 770 | static const char * __init get_mem_info_source(void) | 764 | static const char * __init get_mem_info_source(void) |
| 771 | { | 765 | { |
| 772 | switch (mem_detect.info_source) { | 766 | switch (mem_detect.info_source) { |
| @@ -791,8 +785,10 @@ static void __init memblock_add_mem_detect_info(void) · 18 unmodified lines | |||
| 791 | get_mem_info_source(), mem_detect.info_source); | 785 | get_mem_info_source(), mem_detect.info_source); |
| 792 | /* keep memblock lists close to the kernel */ | 786 | /* keep memblock lists close to the kernel */ |
| 793 | memblock_set_bottom_up(true); | 787 | memblock_set_bottom_up(true); |
| 794 | for_each_mem_detect_block(i, &start, &end) | 788 | for_each_mem_detect_block(i, &start, &end) { |
| 789 | memblock_add(start, end - start); | ||
| 795 | memblock_physmem_add(start, end - start); | 790 | memblock_physmem_add(start, end - start); |
| 791 | } | ||
| 796 | memblock_set_bottom_up(false); | 792 | memblock_set_bottom_up(false); |
| 797 | memblock_dump_all(); | 793 | memblock_dump_all(); |
| 798 | } | 794 | } |
| @@ -27,6 +27,7 @@ · 26 unmodified lines | |||
| 27 | #include <linux/acpi.h> | 27 | #include <linux/acpi.h> |
| 28 | #include <linux/workqueue.h> | 28 | #include <linux/workqueue.h> |
| 29 | #include <linux/uaccess.h> | 29 | #include <linux/uaccess.h> |
| 30 | #include <linux/units.h> | ||
| 30 | 31 | ||
| 31 | #define PREFIX "ACPI: " | 32 | #define PREFIX "ACPI: " |
| 32 | 33 | ||
| @@ -172,7 +173,7 @@ struct acpi_thermal { · 139 unmodified lines | |||
| 172 | struct acpi_handle_list devices; | 173 | struct acpi_handle_list devices; |
| 173 | struct thermal_zone_device *thermal_zone; | 174 | struct thermal_zone_device *thermal_zone; |
| 174 | int tz_enabled; | 175 | int tz_enabled; |
| 175 | int kelvin_offset; | 176 | int kelvin_offset; /* in millidegrees */ |
| 176 | struct work_struct thermal_check_work; | 177 | struct work_struct thermal_check_work; |
| 177 | }; | 178 | }; |
| 178 | 179 | ||
| @@ -297,7 +298,8 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) · 118 unmodified lines | |||
| 297 | if (crt == -1) { | 298 | if (crt == -1) { |
| 298 | tz->trips.critical.flags.valid = 0; | 299 | tz->trips.critical.flags.valid = 0; |
| 299 | } else if (crt > 0) { | 300 | } else if (crt > 0) { |
| 300 | unsigned long crt_k = CELSIUS_TO_DECI_KELVIN(crt); | 301 | unsigned long crt_k = celsius_to_deci_kelvin(crt); |
| 302 | |||
| 301 | /* | 303 | /* |
| 302 | * Allow override critical threshold | 304 | * Allow override critical threshold |
| 303 | */ | 305 | */ |
| @@ -333,7 +335,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) · 29 unmodified lines | |||
| 333 | if (psv == -1) { | 335 | if (psv == -1) { |
| 334 | status = AE_SUPPORT; | 336 | status = AE_SUPPORT; |
| 335 | } else if (psv > 0) { | 337 | } else if (psv > 0) { |
| 336 | tmp = CELSIUS_TO_DECI_KELVIN(psv); | 338 | tmp = celsius_to_deci_kelvin(psv); |
| 337 | status = AE_OK; | 339 | status = AE_OK; |
| 338 | } else { | 340 | } else { |
| 339 | status = acpi_evaluate_integer(tz->device->handle, | 341 | status = acpi_evaluate_integer(tz->device->handle, |
| @@ -413,7 +415,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) · 73 unmodified lines | |||
| 413 | break; | 415 | break; |
| 414 | if (i == 1) | 416 | if (i == 1) |
| 415 | tz->trips.active[0].temperature = | 417 | tz->trips.active[0].temperature = |
| 416 | CELSIUS_TO_DECI_KELVIN(act); | 418 | celsius_to_deci_kelvin(act); |
| 417 | else | 419 | else |
| 418 | /* | 420 | /* |
| 419 | * Don't allow override higher than | 421 | * Don't allow override higher than |
| @@ -421,9 +423,9 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) · 1 unmodified line | |||
| 421 | */ | 423 | */ |
| 422 | tz->trips.active[i - 1].temperature = | 424 | tz->trips.active[i - 1].temperature = |
| 423 | (tz->trips.active[i - 2].temperature < | 425 | (tz->trips.active[i - 2].temperature < |
| 424 | CELSIUS_TO_DECI_KELVIN(act) ? | 426 | celsius_to_deci_kelvin(act) ? |
| 425 | tz->trips.active[i - 2].temperature : | 427 | tz->trips.active[i - 2].temperature : |
| 426 | CELSIUS_TO_DECI_KELVIN(act)); | 428 | celsius_to_deci_kelvin(act)); |
| 427 | break; | 429 | break; |
| 428 | } else { | 430 | } else { |
| 429 | tz->trips.active[i].temperature = tmp; | 431 | tz->trips.active[i].temperature = tmp; |
| @@ -519,7 +521,7 @@ static int thermal_get_temp(struct thermal_zone_device *thermal, int *temp) · 89 unmodified lines | |||
| 519 | if (result) | 521 | if (result) |
| 520 | return result; | 522 | return result; |
| 521 | 523 | ||
| 522 | *temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(tz->temperature, | 524 | *temp = deci_kelvin_to_millicelsius_with_offset(tz->temperature, |
| 523 | tz->kelvin_offset); | 525 | tz->kelvin_offset); |
| 524 | return 0; | 526 | return 0; |
| 525 | } | 527 | } |
| @@ -624,7 +626,7 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal, · 98 unmodified lines | |||
| 624 | 626 | ||
| 625 | if (tz->trips.critical.flags.valid) { | 627 | if (tz->trips.critical.flags.valid) { |
| 626 | if (!trip) { | 628 | if (!trip) { |
| 627 | *temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET( | 629 | *temp = deci_kelvin_to_millicelsius_with_offset( |
| 628 | tz->trips.critical.temperature, | 630 | tz->trips.critical.temperature, |
| 629 | tz->kelvin_offset); | 631 | tz->kelvin_offset); |
| 630 | return 0; | 632 | return 0; |
| @@ -634,7 +636,7 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal, · 3 unmodified lines | |||
| 634 | 636 | ||
| 635 | if (tz->trips.hot.flags.valid) { | 637 | if (tz->trips.hot.flags.valid) { |
| 636 | if (!trip) { | 638 | if (!trip) { |
| 637 | *temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET( | 639 | *temp = deci_kelvin_to_millicelsius_with_offset( |
| 638 | tz->trips.hot.temperature, | 640 | tz->trips.hot.temperature, |
| 639 | tz->kelvin_offset); | 641 | tz->kelvin_offset); |
| 640 | return 0; | 642 | return 0; |
| @@ -644,7 +646,7 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal, · 3 unmodified lines | |||
| 644 | 646 | ||
| 645 | if (tz->trips.passive.flags.valid) { | 647 | if (tz->trips.passive.flags.valid) { |
| 646 | if (!trip) { | 648 | if (!trip) { |
| 647 | *temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET( | 649 | *temp = deci_kelvin_to_millicelsius_with_offset( |
| 648 | tz->trips.passive.temperature, | 650 | tz->trips.passive.temperature, |
| 649 | tz->kelvin_offset); | 651 | tz->kelvin_offset); |
| 650 | return 0; | 652 | return 0; |
| @@ -655,7 +657,7 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal, · 4 unmodified lines | |||
| 655 | for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && | 657 | for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && |
| 656 | tz->trips.active[i].flags.valid; i++) { | 658 | tz->trips.active[i].flags.valid; i++) { |
| 657 | if (!trip) { | 659 | if (!trip) { |
| 658 | *temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET( | 660 | *temp = deci_kelvin_to_millicelsius_with_offset( |
| 659 | tz->trips.active[i].temperature, | 661 | tz->trips.active[i].temperature, |
| 660 | tz->kelvin_offset); | 662 | tz->kelvin_offset); |
| 661 | return 0; | 663 | return 0; |
| @@ -672,7 +674,7 @@ static int thermal_get_crit_temp(struct thermal_zone_device *thermal, · 10 unmodified lines | |||
| 672 | struct acpi_thermal *tz = thermal->devdata; | 674 | struct acpi_thermal *tz = thermal->devdata; |
| 673 | 675 | ||
| 674 | if (tz->trips.critical.flags.valid) { | 676 | if (tz->trips.critical.flags.valid) { |
| 675 | *temperature = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET( | 677 | *temperature = deci_kelvin_to_millicelsius_with_offset( |
| 676 | tz->trips.critical.temperature, | 678 | tz->trips.critical.temperature, |
| 677 | tz->kelvin_offset); | 679 | tz->kelvin_offset); |
| 678 | return 0; | 680 | return 0; |
| @@ -692,7 +694,7 @@ static int thermal_get_trend(struct thermal_zone_device *thermal, · 13 unmodified lines | |||
| 692 | 694 | ||
| 693 | if (type == THERMAL_TRIP_ACTIVE) { | 695 | if (type == THERMAL_TRIP_ACTIVE) { |
| 694 | int trip_temp; | 696 | int trip_temp; |
| 695 | int temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET( | 697 | int temp = deci_kelvin_to_millicelsius_with_offset( |
| 696 | tz->temperature, tz->kelvin_offset); | 698 | tz->temperature, tz->kelvin_offset); |
| 697 | if (thermal_get_trip_temp(thermal, trip, &trip_temp)) | 699 | if (thermal_get_trip_temp(thermal, trip, &trip_temp)) |
| 698 | return -EINVAL; | 700 | return -EINVAL; |
| @@ -1043,9 +1045,9 @@ static void acpi_thermal_guess_offset(struct acpi_thermal *tz) · 344 unmodified lines | |||
| 1043 | { | 1045 | { |
| 1044 | if (tz->trips.critical.flags.valid && | 1046 | if (tz->trips.critical.flags.valid && |
| 1045 | (tz->trips.critical.temperature % 5) == 1) | 1047 | (tz->trips.critical.temperature % 5) == 1) |
| 1046 | tz->kelvin_offset = 2731; | 1048 | tz->kelvin_offset = 273100; |
| 1047 | else | 1049 | else |
| 1048 | tz->kelvin_offset = 2732; | 1050 | tz->kelvin_offset = 273200; |
| 1049 | } | 1051 | } |
| 1050 | 1052 | ||
| 1051 | static void acpi_thermal_check_fn(struct work_struct *work) | 1053 | static void acpi_thermal_check_fn(struct work_struct *work) |
| @@ -1087,7 +1089,7 @@ static int acpi_thermal_add(struct acpi_device *device) · 35 unmodified lines | |||
| 1087 | INIT_WORK(&tz->thermal_check_work, acpi_thermal_check_fn); | 1089 | INIT_WORK(&tz->thermal_check_work, acpi_thermal_check_fn); |
| 1088 | 1090 | ||
| 1089 | pr_info(PREFIX "%s [%s] (%ld C)\n", acpi_device_name(device), | 1091 | pr_info(PREFIX "%s [%s] (%ld C)\n", acpi_device_name(device), |
| 1090 | acpi_device_bid(device), DECI_KELVIN_TO_CELSIUS(tz->temperature)); | 1092 | acpi_device_bid(device), deci_kelvin_to_celsius(tz->temperature)); |
| 1091 | goto end; | 1093 | goto end; |
| 1092 | 1094 | ||
| 1093 | free_memory: | 1095 | free_memory: |
| @@ -70,20 +70,6 @@ void unregister_memory_notifier(struct notifier_block *nb) · 69 unmodified lines | |||
| 70 | } | 70 | } |
| 71 | EXPORT_SYMBOL(unregister_memory_notifier); | 71 | EXPORT_SYMBOL(unregister_memory_notifier); |
| 72 | 72 | ||
| 73 | static ATOMIC_NOTIFIER_HEAD(memory_isolate_chain); | ||
| 74 | |||
| 75 | int register_memory_isolate_notifier(struct notifier_block *nb) | ||
| 76 | { | ||
| 77 | return atomic_notifier_chain_register(&memory_isolate_chain, nb); | ||
| 78 | } | ||
| 79 | EXPORT_SYMBOL(register_memory_isolate_notifier); | ||
| 80 | |||
| 81 | void unregister_memory_isolate_notifier(struct notifier_block *nb) | ||
| 82 | { | ||
| 83 | atomic_notifier_chain_unregister(&memory_isolate_chain, nb); | ||
| 84 | } | ||
| 85 | EXPORT_SYMBOL(unregister_memory_isolate_notifier); | ||
| 86 | |||
| 87 | static void memory_block_release(struct device *dev) | 73 | static void memory_block_release(struct device *dev) |
| 88 | { | 74 | { |
| 89 | struct memory_block *mem = to_memory_block(dev); | 75 | struct memory_block *mem = to_memory_block(dev); |
| @@ -175,11 +161,6 @@ int memory_notify(unsigned long val, void *v) · 85 unmodified lines | |||
| 175 | return blocking_notifier_call_chain(&memory_chain, val, v); | 161 | return blocking_notifier_call_chain(&memory_chain, val, v); |
| 176 | } | 162 | } |
| 177 | 163 | ||
| 178 | int memory_isolate_notify(unsigned long val, void *v) | ||
| 179 | { | ||
| 180 | return atomic_notifier_call_chain(&memory_isolate_chain, val, v); | ||
| 181 | } | ||
| 182 | |||
| 183 | /* | 164 | /* |
| 184 | * The probe routines leave the pages uninitialized, just as the bootmem code | 165 | * The probe routines leave the pages uninitialized, just as the bootmem code |
| 185 | * does. Make sure we do not access them, but instead use only information from | 166 | * does. Make sure we do not access them, but instead use only information from |
| @@ -225,7 +206,7 @@ static bool pages_correctly_probed(unsigned long start_pfn) · 39 unmodified lines | |||
| 225 | */ | 206 | */ |
| 226 | static int | 207 | static int |
| 227 | memory_block_action(unsigned long start_section_nr, unsigned long action, | 208 | memory_block_action(unsigned long start_section_nr, unsigned long action, |
| 228 | int online_type) | 209 | int online_type, int nid) |
| 229 | { | 210 | { |
| 230 | unsigned long start_pfn; | 211 | unsigned long start_pfn; |
| 231 | unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block; | 212 | unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block; |
| @@ -238,7 +219,7 @@ memory_block_action(unsigned long start_section_nr, unsigned long action, · 6 unmodified lines | |||
| 238 | if (!pages_correctly_probed(start_pfn)) | 219 | if (!pages_correctly_probed(start_pfn)) |
| 239 | return -EBUSY; | 220 | return -EBUSY; |
| 240 | 221 | ||
| 241 | ret = online_pages(start_pfn, nr_pages, online_type); | 222 | ret = online_pages(start_pfn, nr_pages, online_type, nid); |
| 242 | break; | 223 | break; |
| 243 | case MEM_OFFLINE: | 224 | case MEM_OFFLINE: |
| 244 | ret = offline_pages(start_pfn, nr_pages); | 225 | ret = offline_pages(start_pfn, nr_pages); |
| @@ -264,7 +245,7 @@ static int memory_block_change_state(struct memory_block *mem, · 19 unmodified lines | |||
| 264 | mem->state = MEM_GOING_OFFLINE; | 245 | mem->state = MEM_GOING_OFFLINE; |
| 265 | 246 | ||
| 266 | ret = memory_block_action(mem->start_section_nr, to_state, | 247 | ret = memory_block_action(mem->start_section_nr, to_state, |
| 267 | mem->online_type); | 248 | mem->online_type, mem->nid); |
| 268 | 249 | ||
| 269 | mem->state = ret ? from_state_req : to_state; | 250 | mem->state = ret ? from_state_req : to_state; |
| 270 | 251 | ||
| @@ -207,14 +207,17 @@ static inline void zram_fill_page(void *ptr, unsigned long len, · 206 unmodified lines | |||
| 207 | 207 | ||
| 208 | static bool page_same_filled(void *ptr, unsigned long *element) | 208 | static bool page_same_filled(void *ptr, unsigned long *element) |
| 209 | { | 209 | { |
| 210 | unsigned int pos; | ||
| 211 | unsigned long *page; | 210 | unsigned long *page; |
| 212 | unsigned long val; | 211 | unsigned long val; |
| 212 | unsigned int pos, last_pos = PAGE_SIZE / sizeof(*page) - 1; | ||
| 213 | 213 | ||
| 214 | page = (unsigned long *)ptr; | 214 | page = (unsigned long *)ptr; |
| 215 | val = page[0]; | 215 | val = page[0]; |
| 216 | 216 | ||
| 217 | for (pos = 1; pos < PAGE_SIZE / sizeof(*page); pos++) { | 217 | if (val != page[last_pos]) |
| 218 | return false; | ||
| 219 | |||
| 220 | for (pos = 1; pos < last_pos; pos++) { | ||
| 218 | if (val != page[pos]) | 221 | if (val != page[pos]) |
| 219 | return false; | 222 | return false; |
| 220 | } | 223 | } |
| @@ -626,7 +629,7 @@ static ssize_t writeback_store(struct device *dev, · 405 unmodified lines | |||
| 626 | struct bio bio; | 629 | struct bio bio; |
| 627 | struct bio_vec bio_vec; | 630 | struct bio_vec bio_vec; |
| 628 | struct page *page; | 631 | struct page *page; |
| 629 | ssize_t ret; | 632 | ssize_t ret = len; |
| 630 | int mode; | 633 | int mode; |
| 631 | unsigned long blk_idx = 0; | 634 | unsigned long blk_idx = 0; |
| 632 | 635 | ||
| @@ -762,7 +765,6 @@ next: · 129 unmodified lines | |||
| 762 | 765 | ||
| 763 | if (blk_idx) | 766 | if (blk_idx) |
| 764 | free_block_bdev(zram, blk_idx); | 767 | free_block_bdev(zram, blk_idx); |
| 765 | ret = len; | ||
| 766 | __free_page(page); | 768 | __free_page(page); |
| 767 | release_init_lock: | 769 | release_init_lock: |
| 768 | up_read(&zram->init_lock); | 770 | up_read(&zram->init_lock); |
| @@ -188,8 +188,8 @@ via_free_sg_info(struct pci_dev *pdev, drm_via_sg_info_t *vsg) · 187 unmodified lines | |||
| 188 | kfree(vsg->desc_pages); | 188 | kfree(vsg->desc_pages); |
| 189 | /* fall through */ | 189 | /* fall through */ |
| 190 | case dr_via_pages_locked: | 190 | case dr_via_pages_locked: |
| 191 | put_user_pages_dirty_lock(vsg->pages, vsg->num_pages, | 191 | unpin_user_pages_dirty_lock(vsg->pages, vsg->num_pages, |
| 192 | (vsg->direction == DMA_FROM_DEVICE)); | 192 | (vsg->direction == DMA_FROM_DEVICE)); |
| 193 | /* fall through */ | 193 | /* fall through */ |
| 194 | case dr_via_pages_alloc: | 194 | case dr_via_pages_alloc: |
| 195 | vfree(vsg->pages); | 195 | vfree(vsg->pages); |
| @@ -239,7 +239,7 @@ via_lock_all_dma_pages(drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer) · 43 unmodified lines | |||
| 239 | vsg->pages = vzalloc(array_size(sizeof(struct page *), vsg->num_pages)); | 239 | vsg->pages = vzalloc(array_size(sizeof(struct page *), vsg->num_pages)); |
| 240 | if (NULL == vsg->pages) | 240 | if (NULL == vsg->pages) |
| 241 | return -ENOMEM; | 241 | return -ENOMEM; |
| 242 | ret = get_user_pages_fast((unsigned long)xfer->mem_addr, | 242 | ret = pin_user_pages_fast((unsigned long)xfer->mem_addr, |
| 243 | vsg->num_pages, | 243 | vsg->num_pages, |
| 244 | vsg->direction == DMA_FROM_DEVICE ? FOLL_WRITE : 0, | 244 | vsg->direction == DMA_FROM_DEVICE ? FOLL_WRITE : 0, |
| 245 | vsg->pages); | 245 | vsg->pages); |
| @@ -6,6 +6,7 @@ · 5 unmodified lines | |||
| 6 | #include <linux/log2.h> | 6 | #include <linux/log2.h> |
| 7 | #include <linux/err.h> | 7 | #include <linux/err.h> |
| 8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
| 9 | #include <linux/units.h> | ||
| 9 | 10 | ||
| 10 | #include "qcom-vadc-common.h" | 11 | #include "qcom-vadc-common.h" |
| 11 | 12 | ||
| @@ -236,8 +237,7 @@ static int qcom_vadc_scale_die_temp(const struct vadc_linear_graph *calib_graph, · 224 unmodified lines | |||
| 236 | voltage = 0; | 237 | voltage = 0; |
| 237 | } | 238 | } |
| 238 | 239 | ||
| 239 | voltage -= KELVINMIL_CELSIUSMIL; | 240 | *result_mdec = milli_kelvin_to_millicelsius(voltage); |
| 240 | *result_mdec = voltage; | ||
| 241 | 241 | ||
| 242 | return 0; | 242 | return 0; |
| 243 | } | 243 | } |
| @@ -325,7 +325,7 @@ static int qcom_vadc_scale_hw_calib_die_temp( · 81 unmodified lines | |||
| 325 | { | 325 | { |
| 326 | *result_mdec = qcom_vadc_scale_code_voltage_factor(adc_code, | 326 | *result_mdec = qcom_vadc_scale_code_voltage_factor(adc_code, |
| 327 | prescale, data, 2); | 327 | prescale, data, 2); |
| 328 | *result_mdec -= KELVINMIL_CELSIUSMIL; | 328 | *result_mdec = milli_kelvin_to_millicelsius(*result_mdec); |
| 329 | 329 | ||
| 330 | return 0; | 330 | return 0; |
| 331 | } | 331 | } |
| @@ -38,7 +38,6 @@ · 37 unmodified lines | |||
| 38 | #define VADC_AVG_SAMPLES_MAX 512 | 38 | #define VADC_AVG_SAMPLES_MAX 512 |
| 39 | #define ADC5_AVG_SAMPLES_MAX 16 | 39 | #define ADC5_AVG_SAMPLES_MAX 16 |
| 40 | 40 | ||
| 41 | #define KELVINMIL_CELSIUSMIL 273150 | ||
| 42 | #define PMIC5_CHG_TEMP_SCALE_FACTOR 377500 | 41 | #define PMIC5_CHG_TEMP_SCALE_FACTOR 377500 |
| 43 | #define PMIC5_SMB_TEMP_CONSTANT 419400 | 42 | #define PMIC5_SMB_TEMP_CONSTANT 419400 |
| 44 | #define PMIC5_SMB_TEMP_SCALE_FACTOR 356 | 43 | #define PMIC5_SMB_TEMP_SCALE_FACTOR 356 |
| @@ -54,7 +54,7 @@ static void __ib_umem_release(struct ib_device *dev, struct ib_umem *umem, int d · 53 unmodified lines | |||
| 54 | 54 | ||
| 55 | for_each_sg_page(umem->sg_head.sgl, &sg_iter, umem->sg_nents, 0) { | 55 | for_each_sg_page(umem->sg_head.sgl, &sg_iter, umem->sg_nents, 0) { |
| 56 | page = sg_page_iter_page(&sg_iter); | 56 | page = sg_page_iter_page(&sg_iter); |
| 57 | put_user_pages_dirty_lock(&page, 1, umem->writable && dirty); | 57 | unpin_user_pages_dirty_lock(&page, 1, umem->writable && dirty); |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | sg_free_table(&umem->sg_head); | 60 | sg_free_table(&umem->sg_head); |
| @@ -257,16 +257,13 @@ struct ib_umem *ib_umem_get(struct ib_device *device, unsigned long addr, · 196 unmodified lines | |||
| 257 | sg = umem->sg_head.sgl; | 257 | sg = umem->sg_head.sgl; |
| 258 | 258 | ||
| 259 | while (npages) { | 259 | while (npages) { |
| 260 | down_read(&mm->mmap_sem); | 260 | ret = pin_user_pages_fast(cur_base, |
| 261 | ret = get_user_pages(cur_base, | 261 | min_t(unsigned long, npages, |
| 262 | min_t(unsigned long, npages, | 262 | PAGE_SIZE / |
| 263 | PAGE_SIZE / sizeof (struct page *)), | 263 | sizeof(struct page *)), |
| 264 | gup_flags | FOLL_LONGTERM, | 264 | gup_flags | FOLL_LONGTERM, page_list); |
| 265 | page_list, NULL); | 265 | if (ret < 0) |
| 266 | if (ret < 0) { | ||
| 267 | up_read(&mm->mmap_sem); | ||
| 268 | goto umem_release; | 266 | goto umem_release; |
| 269 | } | ||
| 270 | 267 | ||
| 271 | cur_base += ret * PAGE_SIZE; | 268 | cur_base += ret * PAGE_SIZE; |
| 272 | npages -= ret; | 269 | npages -= ret; |
| @@ -274,8 +271,6 @@ struct ib_umem *ib_umem_get(struct ib_device *device, unsigned long addr, · 1 unmodified line | |||
| 274 | sg = ib_umem_add_sg_table(sg, page_list, ret, | 271 | sg = ib_umem_add_sg_table(sg, page_list, ret, |
| 275 | dma_get_max_seg_size(device->dma_device), | 272 | dma_get_max_seg_size(device->dma_device), |
| 276 | &umem->sg_nents); | 273 | &umem->sg_nents); |
| 277 | |||
| 278 | up_read(&mm->mmap_sem); | ||
| 279 | } | 274 | } |
| 280 | 275 | ||
| 281 | sg_mark_end(sg); | 276 | sg_mark_end(sg); |
| @@ -293,9 +293,8 @@ EXPORT_SYMBOL(ib_umem_odp_release); · 292 unmodified lines | |||
| 293 | * The function returns -EFAULT if the DMA mapping operation fails. It returns | 293 | * The function returns -EFAULT if the DMA mapping operation fails. It returns |
| 294 | * -EAGAIN if a concurrent invalidation prevents us from updating the page. | 294 | * -EAGAIN if a concurrent invalidation prevents us from updating the page. |
| 295 | * | 295 | * |
| 296 | * The page is released via put_user_page even if the operation failed. For | 296 | * The page is released via put_page even if the operation failed. For on-demand |
| 297 | * on-demand pinning, the page is released whenever it isn't stored in the | 297 | * pinning, the page is released whenever it isn't stored in the umem. |
| 298 | * umem. | ||
| 299 | */ | 298 | */ |
| 300 | static int ib_umem_odp_map_dma_single_page( | 299 | static int ib_umem_odp_map_dma_single_page( |
| 301 | struct ib_umem_odp *umem_odp, | 300 | struct ib_umem_odp *umem_odp, |
| @@ -348,7 +347,7 @@ static int ib_umem_odp_map_dma_single_page( · 46 unmodified lines | |||
| 348 | } | 347 | } |
| 349 | 348 | ||
| 350 | out: | 349 | out: |
| 351 | put_user_page(page); | 350 | put_page(page); |
| 352 | return ret; | 351 | return ret; |
| 353 | } | 352 | } |
| 354 | 353 | ||
| @@ -458,7 +457,7 @@ int ib_umem_odp_map_dma_pages(struct ib_umem_odp *umem_odp, u64 user_virt, · 103 unmodified lines | |||
| 458 | ret = -EFAULT; | 457 | ret = -EFAULT; |
| 459 | break; | 458 | break; |
| 460 | } | 459 | } |
| 461 | put_user_page(local_page_list[j]); | 460 | put_page(local_page_list[j]); |
| 462 | continue; | 461 | continue; |
| 463 | } | 462 | } |
| 464 | 463 | ||
| @@ -485,8 +484,8 @@ int ib_umem_odp_map_dma_pages(struct ib_umem_odp *umem_odp, u64 user_virt, · 20 unmodified lines | |||
| 485 | * ib_umem_odp_map_dma_single_page(). | 484 | * ib_umem_odp_map_dma_single_page(). |
| 486 | */ | 485 | */ |
| 487 | if (npages - (j + 1) > 0) | 486 | if (npages - (j + 1) > 0) |
| 488 | put_user_pages(&local_page_list[j+1], | 487 | release_pages(&local_page_list[j+1], |
| 489 | npages - (j + 1)); | 488 | npages - (j + 1)); |
| 490 | break; | 489 | break; |
| 491 | } | 490 | } |
| 492 | } | 491 | } |
| @@ -106,7 +106,7 @@ int hfi1_acquire_user_pages(struct mm_struct *mm, unsigned long vaddr, size_t np · 105 unmodified lines | |||
| 106 | int ret; | 106 | int ret; |
| 107 | unsigned int gup_flags = FOLL_LONGTERM | (writable ? FOLL_WRITE : 0); | 107 | unsigned int gup_flags = FOLL_LONGTERM | (writable ? FOLL_WRITE : 0); |
| 108 | 108 | ||
| 109 | ret = get_user_pages_fast(vaddr, npages, gup_flags, pages); | 109 | ret = pin_user_pages_fast(vaddr, npages, gup_flags, pages); |
| 110 | if (ret < 0) | 110 | if (ret < 0) |
| 111 | return ret; | 111 | return ret; |
| 112 | 112 | ||
| @@ -118,7 +118,7 @@ int hfi1_acquire_user_pages(struct mm_struct *mm, unsigned long vaddr, size_t np · 5 unmodified lines | |||
| 118 | void hfi1_release_user_pages(struct mm_struct *mm, struct page **p, | 118 | void hfi1_release_user_pages(struct mm_struct *mm, struct page **p, |
| 119 | size_t npages, bool dirty) | 119 | size_t npages, bool dirty) |
| 120 | { | 120 | { |
| 121 | put_user_pages_dirty_lock(p, npages, dirty); | 121 | unpin_user_pages_dirty_lock(p, npages, dirty); |
| 122 | 122 | ||
| 123 | if (mm) { /* during close after signal, mm can be NULL */ | 123 | if (mm) { /* during close after signal, mm can be NULL */ |
| 124 | atomic64_sub(npages, &mm->pinned_vm); | 124 | atomic64_sub(npages, &mm->pinned_vm); |
| @@ -472,7 +472,7 @@ int mthca_map_user_db(struct mthca_dev *dev, struct mthca_uar *uar, · 471 unmodified lines | |||
| 472 | goto out; | 472 | goto out; |
| 473 | } | 473 | } |
| 474 | 474 | ||
| 475 | ret = get_user_pages_fast(uaddr & PAGE_MASK, 1, | 475 | ret = pin_user_pages_fast(uaddr & PAGE_MASK, 1, |
| 476 | FOLL_WRITE | FOLL_LONGTERM, pages); | 476 | FOLL_WRITE | FOLL_LONGTERM, pages); |
| 477 | if (ret < 0) | 477 | if (ret < 0) |
| 478 | goto out; | 478 | goto out; |
| @@ -482,7 +482,7 @@ int mthca_map_user_db(struct mthca_dev *dev, struct mthca_uar *uar, · 3 unmodified lines | |||
| 482 | 482 | ||
| 483 | ret = pci_map_sg(dev->pdev, &db_tab->page[i].mem, 1, PCI_DMA_TODEVICE); | 483 | ret = pci_map_sg(dev->pdev, &db_tab->page[i].mem, 1, PCI_DMA_TODEVICE); |
| 484 | if (ret < 0) { | 484 | if (ret < 0) { |
| 485 | put_user_page(pages[0]); | 485 | unpin_user_page(pages[0]); |
| 486 | goto out; | 486 | goto out; |
| 487 | } | 487 | } |
| 488 | 488 | ||
| @@ -490,7 +490,7 @@ int mthca_map_user_db(struct mthca_dev *dev, struct mthca_uar *uar, · 1 unmodified line | |||
| 490 | mthca_uarc_virt(dev, uar, i)); | 490 | mthca_uarc_virt(dev, uar, i)); |
| 491 | if (ret) { | 491 | if (ret) { |
| 492 | pci_unmap_sg(dev->pdev, &db_tab->page[i].mem, 1, PCI_DMA_TODEVICE); | 492 | pci_unmap_sg(dev->pdev, &db_tab->page[i].mem, 1, PCI_DMA_TODEVICE); |
| 493 | put_user_page(sg_page(&db_tab->page[i].mem)); | 493 | unpin_user_page(sg_page(&db_tab->page[i].mem)); |
| 494 | goto out; | 494 | goto out; |
| 495 | } | 495 | } |
| 496 | 496 | ||
| @@ -556,7 +556,7 @@ void mthca_cleanup_user_db_tab(struct mthca_dev *dev, struct mthca_uar *uar, · 59 unmodified lines | |||
| 556 | if (db_tab->page[i].uvirt) { | 556 | if (db_tab->page[i].uvirt) { |
| 557 | mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, uar, i), 1); | 557 | mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, uar, i), 1); |
| 558 | pci_unmap_sg(dev->pdev, &db_tab->page[i].mem, 1, PCI_DMA_TODEVICE); | 558 | pci_unmap_sg(dev->pdev, &db_tab->page[i].mem, 1, PCI_DMA_TODEVICE); |
| 559 | put_user_page(sg_page(&db_tab->page[i].mem)); | 559 | unpin_user_page(sg_page(&db_tab->page[i].mem)); |
| 560 | } | 560 | } |
| 561 | } | 561 | } |
| 562 | 562 | ||
| @@ -40,7 +40,7 @@ · 39 unmodified lines | |||
| 40 | static void __qib_release_user_pages(struct page **p, size_t num_pages, | 40 | static void __qib_release_user_pages(struct page **p, size_t num_pages, |
| 41 | int dirty) | 41 | int dirty) |
| 42 | { | 42 | { |
| 43 | put_user_pages_dirty_lock(p, num_pages, dirty); | 43 | unpin_user_pages_dirty_lock(p, num_pages, dirty); |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | /** | 46 | /** |
| @@ -108,7 +108,7 @@ int qib_get_user_pages(unsigned long start_page, size_t num_pages, · 61 unmodified lines | |||
| 108 | 108 | ||
| 109 | down_read(¤t->mm->mmap_sem); | 109 | down_read(¤t->mm->mmap_sem); |
| 110 | for (got = 0; got < num_pages; got += ret) { | 110 | for (got = 0; got < num_pages; got += ret) { |
| 111 | ret = get_user_pages(start_page + got * PAGE_SIZE, | 111 | ret = pin_user_pages(start_page + got * PAGE_SIZE, |
| 112 | num_pages - got, | 112 | num_pages - got, |
| 113 | FOLL_LONGTERM | FOLL_WRITE | FOLL_FORCE, | 113 | FOLL_LONGTERM | FOLL_WRITE | FOLL_FORCE, |
| 114 | p + got, NULL); | 114 | p + got, NULL); |
| @@ -317,7 +317,7 @@ static int qib_user_sdma_page_to_frags(const struct qib_devdata *dd, · 316 unmodified lines | |||
| 317 | * the caller can ignore this page. | 317 | * the caller can ignore this page. |
| 318 | */ | 318 | */ |
| 319 | if (put) { | 319 | if (put) { |
| 320 | put_user_page(page); | 320 | unpin_user_page(page); |
| 321 | } else { | 321 | } else { |
| 322 | /* coalesce case */ | 322 | /* coalesce case */ |
| 323 | kunmap(page); | 323 | kunmap(page); |
| @@ -631,7 +631,7 @@ static void qib_user_sdma_free_pkt_frag(struct device *dev, · 307 unmodified lines | |||
| 631 | kunmap(pkt->addr[i].page); | 631 | kunmap(pkt->addr[i].page); |
| 632 | 632 | ||
| 633 | if (pkt->addr[i].put_page) | 633 | if (pkt->addr[i].put_page) |
| 634 | put_user_page(pkt->addr[i].page); | 634 | unpin_user_page(pkt->addr[i].page); |
| 635 | else | 635 | else |
| 636 | __free_page(pkt->addr[i].page); | 636 | __free_page(pkt->addr[i].page); |
| 637 | } else if (pkt->addr[i].kvaddr) { | 637 | } else if (pkt->addr[i].kvaddr) { |
| @@ -670,7 +670,7 @@ static int qib_user_sdma_pin_pages(const struct qib_devdata *dd, · 32 unmodified lines | |||
| 670 | else | 670 | else |
| 671 | j = npages; | 671 | j = npages; |
| 672 | 672 | ||
| 673 | ret = get_user_pages_fast(addr, j, FOLL_LONGTERM, pages); | 673 | ret = pin_user_pages_fast(addr, j, FOLL_LONGTERM, pages); |
| 674 | if (ret != j) { | 674 | if (ret != j) { |
| 675 | i = 0; | 675 | i = 0; |
| 676 | j = ret; | 676 | j = ret; |
| @@ -706,7 +706,7 @@ static int qib_user_sdma_pin_pages(const struct qib_devdata *dd, · 29 unmodified lines | |||
| 706 | /* if error, return all pages not managed by pkt */ | 706 | /* if error, return all pages not managed by pkt */ |
| 707 | free_pages: | 707 | free_pages: |
| 708 | while (i < j) | 708 | while (i < j) |
| 709 | put_user_page(pages[i++]); | 709 | unpin_user_page(pages[i++]); |
| 710 | 710 | ||
| 711 | done: | 711 | done: |
| 712 | return ret; | 712 | return ret; |
| @@ -75,7 +75,7 @@ static void usnic_uiom_put_pages(struct list_head *chunk_list, int dirty) · 74 unmodified lines | |||
| 75 | for_each_sg(chunk->page_list, sg, chunk->nents, i) { | 75 | for_each_sg(chunk->page_list, sg, chunk->nents, i) { |
| 76 | page = sg_page(sg); | 76 | page = sg_page(sg); |
| 77 | pa = sg_phys(sg); | 77 | pa = sg_phys(sg); |
| 78 | put_user_pages_dirty_lock(&page, 1, dirty); | 78 | unpin_user_pages_dirty_lock(&page, 1, dirty); |
| 79 | usnic_dbg("pa: %pa\n", &pa); | 79 | usnic_dbg("pa: %pa\n", &pa); |
| 80 | } | 80 | } |
| 81 | kfree(chunk); | 81 | kfree(chunk); |
| @@ -141,7 +141,7 @@ static int usnic_uiom_get_pages(unsigned long addr, size_t size, int writable, · 59 unmodified lines | |||
| 141 | ret = 0; | 141 | ret = 0; |
| 142 | 142 | ||
| 143 | while (npages) { | 143 | while (npages) { |
| 144 | ret = get_user_pages(cur_base, | 144 | ret = pin_user_pages(cur_base, |
| 145 | min_t(unsigned long, npages, | 145 | min_t(unsigned long, npages, |
| 146 | PAGE_SIZE / sizeof(struct page *)), | 146 | PAGE_SIZE / sizeof(struct page *)), |
| 147 | gup_flags | FOLL_LONGTERM, | 147 | gup_flags | FOLL_LONGTERM, |
| @@ -63,7 +63,7 @@ struct siw_mem *siw_mem_id2obj(struct siw_device *sdev, int stag_index) · 62 unmodified lines | |||
| 63 | static void siw_free_plist(struct siw_page_chunk *chunk, int num_pages, | 63 | static void siw_free_plist(struct siw_page_chunk *chunk, int num_pages, |
| 64 | bool dirty) | 64 | bool dirty) |
| 65 | { | 65 | { |
| 66 | put_user_pages_dirty_lock(chunk->plist, num_pages, dirty); | 66 | unpin_user_pages_dirty_lock(chunk->plist, num_pages, dirty); |
| 67 | } | 67 | } |
| 68 | 68 | ||
| 69 | void siw_umem_release(struct siw_umem *umem, bool dirty) | 69 | void siw_umem_release(struct siw_umem *umem, bool dirty) |
| @@ -426,7 +426,7 @@ struct siw_umem *siw_umem_get(u64 start, u64 len, bool writable) · 356 unmodified lines | |||
| 426 | while (nents) { | 426 | while (nents) { |
| 427 | struct page **plist = &umem->page_chunk[i].plist[got]; | 427 | struct page **plist = &umem->page_chunk[i].plist[got]; |
| 428 | 428 | ||
| 429 | rv = get_user_pages(first_page_va, nents, | 429 | rv = pin_user_pages(first_page_va, nents, |
| 430 | foll_flags | FOLL_LONGTERM, | 430 | foll_flags | FOLL_LONGTERM, |
| 431 | plist, NULL); | 431 | plist, NULL); |
| 432 | if (rv < 0) | 432 | if (rv < 0) |
| @@ -183,12 +183,12 @@ static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma, · 182 unmodified lines | |||
| 183 | dprintk(1, "init user [0x%lx+0x%lx => %d pages]\n", | 183 | dprintk(1, "init user [0x%lx+0x%lx => %d pages]\n", |
| 184 | data, size, dma->nr_pages); | 184 | data, size, dma->nr_pages); |
| 185 | 185 | ||
| 186 | err = get_user_pages(data & PAGE_MASK, dma->nr_pages, | 186 | err = pin_user_pages(data & PAGE_MASK, dma->nr_pages, |
| 187 | flags | FOLL_LONGTERM, dma->pages, NULL); | 187 | flags | FOLL_LONGTERM, dma->pages, NULL); |
| 188 | 188 | ||
| 189 | if (err != dma->nr_pages) { | 189 | if (err != dma->nr_pages) { |
| 190 | dma->nr_pages = (err >= 0) ? err : 0; | 190 | dma->nr_pages = (err >= 0) ? err : 0; |
| 191 | dprintk(1, "get_user_pages: err=%d [%d]\n", err, | 191 | dprintk(1, "pin_user_pages: err=%d [%d]\n", err, |
| 192 | dma->nr_pages); | 192 | dma->nr_pages); |
| 193 | return err < 0 ? err : -EINVAL; | 193 | return err < 0 ? err : -EINVAL; |
| 194 | } | 194 | } |
| @@ -349,8 +349,8 @@ int videobuf_dma_free(struct videobuf_dmabuf *dma) · 154 unmodified lines | |||
| 349 | BUG_ON(dma->sglen); | 349 | BUG_ON(dma->sglen); |
| 350 | 350 | ||
| 351 | if (dma->pages) { | 351 | if (dma->pages) { |
| 352 | for (i = 0; i < dma->nr_pages; i++) | 352 | unpin_user_pages_dirty_lock(dma->pages, dma->nr_pages, |
| 353 | put_page(dma->pages[i]); | 353 | dma->direction == DMA_FROM_DEVICE); |
| 354 | kfree(dma->pages); | 354 | kfree(dma->pages); |
| 355 | dma->pages = NULL; | 355 | dma->pages = NULL; |
| 356 | } | 356 | } |
| @@ -296,7 +296,6 @@ static inline void bnx2x_dcb_config_qm(struct bnx2x *bp, enum cos_mode mode, · 295 unmodified lines | |||
| 296 | * possible, the driver should only write the valid vnics into the internal | 296 | * possible, the driver should only write the valid vnics into the internal |
| 297 | * ram according to the appropriate port mode. | 297 | * ram according to the appropriate port mode. |
| 298 | */ | 298 | */ |
| 299 | #define BITS_TO_BYTES(x) ((x)/8) | ||
| 300 | 299 | ||
| 301 | /* CMNG constants, as derived from system spec calculations */ | 300 | /* CMNG constants, as derived from system spec calculations */ |
| 302 | 301 | ||
| @@ -27,6 +27,7 @@ · 26 unmodified lines | |||
| 27 | #include <linux/firmware.h> | 27 | #include <linux/firmware.h> |
| 28 | #include <linux/etherdevice.h> | 28 | #include <linux/etherdevice.h> |
| 29 | #include <linux/if_arp.h> | 29 | #include <linux/if_arp.h> |
| 30 | #include <linux/units.h> | ||
| 30 | 31 | ||
| 31 | #include <net/mac80211.h> | 32 | #include <net/mac80211.h> |
| 32 | 33 | ||
| @@ -6468,7 +6469,7 @@ il4965_set_hw_params(struct il_priv *il) · 6435 unmodified lines | |||
| 6468 | il->hw_params.valid_rx_ant = il->cfg->valid_rx_ant; | 6469 | il->hw_params.valid_rx_ant = il->cfg->valid_rx_ant; |
| 6469 | 6470 | ||
| 6470 | il->hw_params.ct_kill_threshold = | 6471 | il->hw_params.ct_kill_threshold = |
| 6471 | CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD_LEGACY); | 6472 | celsius_to_kelvin(CT_KILL_THRESHOLD_LEGACY); |
| 6472 | 6473 | ||
| 6473 | il->hw_params.sens = &il4965_sensitivity; | 6474 | il->hw_params.sens = &il4965_sensitivity; |
| 6474 | il->hw_params.beacon_time_tsf_bits = IL4965_EXT_BEACON_TIME_POS; | 6475 | il->hw_params.beacon_time_tsf_bits = IL4965_EXT_BEACON_TIME_POS; |
| @@ -17,6 +17,7 @@ · 16 unmodified lines | |||
| 17 | #include <linux/sched.h> | 17 | #include <linux/sched.h> |
| 18 | #include <linux/skbuff.h> | 18 | #include <linux/skbuff.h> |
| 19 | #include <linux/netdevice.h> | 19 | #include <linux/netdevice.h> |
| 20 | #include <linux/units.h> | ||
| 20 | #include <net/mac80211.h> | 21 | #include <net/mac80211.h> |
| 21 | #include <linux/etherdevice.h> | 22 | #include <linux/etherdevice.h> |
| 22 | #include <asm/unaligned.h> | 23 | #include <asm/unaligned.h> |
| @@ -1104,7 +1105,7 @@ il4965_fill_txpower_tbl(struct il_priv *il, u8 band, u16 channel, u8 is_ht40, · 1081 unmodified lines | |||
| 1104 | /* get current temperature (Celsius) */ | 1105 | /* get current temperature (Celsius) */ |
| 1105 | current_temp = max(il->temperature, IL_TX_POWER_TEMPERATURE_MIN); | 1106 | current_temp = max(il->temperature, IL_TX_POWER_TEMPERATURE_MIN); |
| 1106 | current_temp = min(il->temperature, IL_TX_POWER_TEMPERATURE_MAX); | 1107 | current_temp = min(il->temperature, IL_TX_POWER_TEMPERATURE_MAX); |
| 1107 | current_temp = KELVIN_TO_CELSIUS(current_temp); | 1108 | current_temp = kelvin_to_celsius(current_temp); |
| 1108 | 1109 | ||
| 1109 | /* select thermal txpower adjustment params, based on channel group | 1110 | /* select thermal txpower adjustment params, based on channel group |
| 1110 | * (same frequency group used for mimo txatten adjustment) */ | 1111 | * (same frequency group used for mimo txatten adjustment) */ |
| @@ -1610,8 +1611,8 @@ il4965_hw_get_temperature(struct il_priv *il) · 499 unmodified lines | |||
| 1610 | temperature = | 1611 | temperature = |
| 1611 | (temperature * 97) / 100 + TEMPERATURE_CALIB_KELVIN_OFFSET; | 1612 | (temperature * 97) / 100 + TEMPERATURE_CALIB_KELVIN_OFFSET; |
| 1612 | 1613 | ||
| 1613 | D_TEMP("Calibrated temperature: %dK, %dC\n", temperature, | 1614 | D_TEMP("Calibrated temperature: %dK, %ldC\n", temperature, |
| 1614 | KELVIN_TO_CELSIUS(temperature)); | 1615 | kelvin_to_celsius(temperature)); |
| 1615 | 1616 | ||
| 1616 | return temperature; | 1617 | return temperature; |
| 1617 | } | 1618 | } |
| @@ -1670,12 +1671,12 @@ il4965_temperature_calib(struct il_priv *il) · 52 unmodified lines | |||
| 1670 | 1671 | ||
| 1671 | if (il->temperature != temp) { | 1672 | if (il->temperature != temp) { |
| 1672 | if (il->temperature) | 1673 | if (il->temperature) |
| 1673 | D_TEMP("Temperature changed " "from %dC to %dC\n", | 1674 | D_TEMP("Temperature changed " "from %ldC to %ldC\n", |
| 1674 | KELVIN_TO_CELSIUS(il->temperature), | 1675 | kelvin_to_celsius(il->temperature), |
| 1675 | KELVIN_TO_CELSIUS(temp)); | 1676 | kelvin_to_celsius(temp)); |
| 1676 | else | 1677 | else |
| 1677 | D_TEMP("Temperature " "initialized to %dC\n", | 1678 | D_TEMP("Temperature " "initialized to %ldC\n", |
| 1678 | KELVIN_TO_CELSIUS(temp)); | 1679 | kelvin_to_celsius(temp)); |
| 1679 | } | 1680 | } |
| 1680 | 1681 | ||
| 1681 | il->temperature = temp; | 1682 | il->temperature = temp; |
| @@ -779,9 +779,6 @@ struct il_sensitivity_ranges { · 778 unmodified lines | |||
| 779 | u16 nrg_th_cca; | 779 | u16 nrg_th_cca; |
| 780 | }; | 780 | }; |
| 781 | 781 | ||
| 782 | #define KELVIN_TO_CELSIUS(x) ((x)-273) | ||
| 783 | #define CELSIUS_TO_KELVIN(x) ((x)+273) | ||
| 784 | |||
| 785 | /** | 782 | /** |
| 786 | * struct il_hw_params | 783 | * struct il_hw_params |
| 787 | * @bcast_id: f/w broadcast station ID | 784 | * @bcast_id: f/w broadcast station ID |
| @@ -237,11 +237,6 @@ struct iwl_sensitivity_ranges { · 236 unmodified lines | |||
| 237 | u16 nrg_th_cca; | 237 | u16 nrg_th_cca; |
| 238 | }; | 238 | }; |
| 239 | 239 | ||
| 240 | |||
| 241 | #define KELVIN_TO_CELSIUS(x) ((x)-273) | ||
| 242 | #define CELSIUS_TO_KELVIN(x) ((x)+273) | ||
| 243 | |||
| 244 | |||
| 245 | /****************************************************************************** | 240 | /****************************************************************************** |
| 246 | * | 241 | * |
| 247 | * Functions implemented in core module which are forward declared here | 242 | * Functions implemented in core module which are forward declared here |
| @@ -10,6 +10,8 @@ · 9 unmodified lines | |||
| 10 | * | 10 | * |
| 11 | *****************************************************************************/ | 11 | *****************************************************************************/ |
| 12 | 12 | ||
| 13 | #include <linux/units.h> | ||
| 14 | |||
| 13 | /* | 15 | /* |
| 14 | * DVM device-specific data & functions | 16 | * DVM device-specific data & functions |
| 15 | */ | 17 | */ |
| @@ -345,7 +347,7 @@ static s32 iwl_temp_calib_to_offset(struct iwl_priv *priv) · 329 unmodified lines | |||
| 345 | static void iwl5150_set_ct_threshold(struct iwl_priv *priv) | 347 | static void iwl5150_set_ct_threshold(struct iwl_priv *priv) |
| 346 | { | 348 | { |
| 347 | const s32 volt2temp_coef = IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF; | 349 | const s32 volt2temp_coef = IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF; |
| 348 | s32 threshold = (s32)CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD_LEGACY) - | 350 | s32 threshold = (s32)celsius_to_kelvin(CT_KILL_THRESHOLD_LEGACY) - |
| 349 | iwl_temp_calib_to_offset(priv); | 351 | iwl_temp_calib_to_offset(priv); |
| 350 | 352 | ||
| 351 | priv->hw_params.ct_kill_threshold = threshold * volt2temp_coef; | 353 | priv->hw_params.ct_kill_threshold = threshold * volt2temp_coef; |
| @@ -381,7 +383,7 @@ static void iwl5150_temperature(struct iwl_priv *priv) · 29 unmodified lines | |||
| 381 | vt = le32_to_cpu(priv->statistics.common.temperature); | 383 | vt = le32_to_cpu(priv->statistics.common.temperature); |
| 382 | vt = vt / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF + offset; | 384 | vt = vt / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF + offset; |
| 383 | /* now vt hold the temperature in Kelvin */ | 385 | /* now vt hold the temperature in Kelvin */ |
| 384 | priv->temperature = KELVIN_TO_CELSIUS(vt); | 386 | priv->temperature = kelvin_to_celsius(vt); |
| 385 | iwl_tt_handler(priv); | 387 | iwl_tt_handler(priv); |
| 386 | } | 388 | } |
| 387 | 389 | ||
| @@ -337,13 +337,7 @@ static void pmem_release_disk(void *__pmem) · 336 unmodified lines | |||
| 337 | put_disk(pmem->disk); | 337 | put_disk(pmem->disk); |
| 338 | } | 338 | } |
| 339 | 339 | ||
| 340 | static void pmem_pagemap_page_free(struct page *page) | ||
| 341 | { | ||
| 342 | wake_up_var(&page->_refcount); | ||
| 343 | } | ||
| 344 | |||
| 345 | static const struct dev_pagemap_ops fsdax_pagemap_ops = { | 340 | static const struct dev_pagemap_ops fsdax_pagemap_ops = { |
| 346 | .page_free = pmem_pagemap_page_free, | ||
| 347 | .kill = pmem_pagemap_kill, | 341 | .kill = pmem_pagemap_kill, |
| 348 | .cleanup = pmem_pagemap_cleanup, | 342 | .cleanup = pmem_pagemap_cleanup, |
| 349 | }; | 343 | }; |
| @@ -5,14 +5,11 @@ · 4 unmodified lines | |||
| 5 | */ | 5 | */ |
| 6 | 6 | ||
| 7 | #include <linux/hwmon.h> | 7 | #include <linux/hwmon.h> |
| 8 | #include <linux/units.h> | ||
| 8 | #include <asm/unaligned.h> | 9 | #include <asm/unaligned.h> |
| 9 | 10 | ||
| 10 | #include "nvme.h" | 11 | #include "nvme.h" |
| 11 | 12 | ||
| 12 | /* These macros should be moved to linux/temperature.h */ | ||
| 13 | #define MILLICELSIUS_TO_KELVIN(t) DIV_ROUND_CLOSEST((t) + 273150, 1000) | ||
| 14 | #define KELVIN_TO_MILLICELSIUS(t) ((t) * 1000L - 273150) | ||
| 15 | |||
| 16 | struct nvme_hwmon_data { | 13 | struct nvme_hwmon_data { |
| 17 | struct nvme_ctrl *ctrl; | 14 | struct nvme_ctrl *ctrl; |
| 18 | struct nvme_smart_log log; | 15 | struct nvme_smart_log log; |
| @@ -35,7 +32,7 @@ static int nvme_get_temp_thresh(struct nvme_ctrl *ctrl, int sensor, bool under, · 16 unmodified lines | |||
| 35 | return -EIO; | 32 | return -EIO; |
| 36 | if (ret < 0) | 33 | if (ret < 0) |
| 37 | return ret; | 34 | return ret; |
| 38 | *temp = KELVIN_TO_MILLICELSIUS(status & NVME_TEMP_THRESH_MASK); | 35 | *temp = kelvin_to_millicelsius(status & NVME_TEMP_THRESH_MASK); |
| 39 | 36 | ||
| 40 | return 0; | 37 | return 0; |
| 41 | } | 38 | } |
| @@ -46,7 +43,7 @@ static int nvme_set_temp_thresh(struct nvme_ctrl *ctrl, int sensor, bool under, · 4 unmodified lines | |||
| 46 | unsigned int threshold = sensor << NVME_TEMP_THRESH_SELECT_SHIFT; | 43 | unsigned int threshold = sensor << NVME_TEMP_THRESH_SELECT_SHIFT; |
| 47 | int ret; | 44 | int ret; |
| 48 | 45 | ||
| 49 | temp = MILLICELSIUS_TO_KELVIN(temp); | 46 | temp = millicelsius_to_kelvin(temp); |
| 50 | threshold |= clamp_val(temp, 0, NVME_TEMP_THRESH_MASK); | 47 | threshold |= clamp_val(temp, 0, NVME_TEMP_THRESH_MASK); |
| 51 | 48 | ||
| 52 | if (under) | 49 | if (under) |
| @@ -88,7 +85,7 @@ static int nvme_hwmon_read(struct device *dev, enum hwmon_sensor_types type, · 35 unmodified lines | |||
| 88 | case hwmon_temp_min: | 85 | case hwmon_temp_min: |
| 89 | return nvme_get_temp_thresh(data->ctrl, channel, true, val); | 86 | return nvme_get_temp_thresh(data->ctrl, channel, true, val); |
| 90 | case hwmon_temp_crit: | 87 | case hwmon_temp_crit: |
| 91 | *val = KELVIN_TO_MILLICELSIUS(data->ctrl->cctemp); | 88 | *val = kelvin_to_millicelsius(data->ctrl->cctemp); |
| 92 | return 0; | 89 | return 0; |
| 93 | default: | 90 | default: |
| 94 | break; | 91 | break; |
| @@ -105,7 +102,7 @@ static int nvme_hwmon_read(struct device *dev, enum hwmon_sensor_types type, · 10 unmodified lines | |||
| 105 | temp = get_unaligned_le16(log->temperature); | 102 | temp = get_unaligned_le16(log->temperature); |
| 106 | else | 103 | else |
| 107 | temp = le16_to_cpu(log->temp_sensor[channel - 1]); | 104 | temp = le16_to_cpu(log->temp_sensor[channel - 1]); |
| 108 | *val = KELVIN_TO_MILLICELSIUS(temp); | 105 | *val = kelvin_to_millicelsius(temp); |
| 109 | break; | 106 | break; |
| 110 | case hwmon_temp_alarm: | 107 | case hwmon_temp_alarm: |
| 111 | *val = !!(log->critical_warning & NVME_SMART_CRIT_TEMPERATURE); | 108 | *val = !!(log->critical_warning & NVME_SMART_CRIT_TEMPERATURE); |
| @@ -257,12 +257,12 @@ static int goldfish_pipe_error_convert(int status) · 256 unmodified lines | |||
| 257 | } | 257 | } |
| 258 | } | 258 | } |
| 259 | 259 | ||
| 260 | static int pin_user_pages(unsigned long first_page, | 260 | static int goldfish_pin_pages(unsigned long first_page, |
| 261 | unsigned long last_page, | 261 | unsigned long last_page, |
| 262 | unsigned int last_page_size, | 262 | unsigned int last_page_size, |
| 263 | int is_write, | 263 | int is_write, |
| 264 | struct page *pages[MAX_BUFFERS_PER_COMMAND], | 264 | struct page *pages[MAX_BUFFERS_PER_COMMAND], |
| 265 | unsigned int *iter_last_page_size) | 265 | unsigned int *iter_last_page_size) |
| 266 | { | 266 | { |
| 267 | int ret; | 267 | int ret; |
| 268 | int requested_pages = ((last_page - first_page) >> PAGE_SHIFT) + 1; | 268 | int requested_pages = ((last_page - first_page) >> PAGE_SHIFT) + 1; |
| @@ -274,7 +274,7 @@ static int pin_user_pages(unsigned long first_page, · 5 unmodified lines | |||
| 274 | *iter_last_page_size = last_page_size; | 274 | *iter_last_page_size = last_page_size; |
| 275 | } | 275 | } |
| 276 | 276 | ||
| 277 | ret = get_user_pages_fast(first_page, requested_pages, | 277 | ret = pin_user_pages_fast(first_page, requested_pages, |
| 278 | !is_write ? FOLL_WRITE : 0, | 278 | !is_write ? FOLL_WRITE : 0, |
| 279 | pages); | 279 | pages); |
| 280 | if (ret <= 0) | 280 | if (ret <= 0) |
| @@ -285,18 +285,6 @@ static int pin_user_pages(unsigned long first_page, · 4 unmodified lines | |||
| 285 | return ret; | 285 | return ret; |
| 286 | } | 286 | } |
| 287 | 287 | ||
| 288 | static void release_user_pages(struct page **pages, int pages_count, | ||
| 289 | int is_write, s32 consumed_size) | ||
| 290 | { | ||
| 291 | int i; | ||
| 292 | |||
| 293 | for (i = 0; i < pages_count; i++) { | ||
| 294 | if (!is_write && consumed_size > 0) | ||
| 295 | set_page_dirty(pages[i]); | ||
| 296 | put_page(pages[i]); | ||
| 297 | } | ||
| 298 | } | ||
| 299 | |||
| 300 | /* Populate the call parameters, merging adjacent pages together */ | 288 | /* Populate the call parameters, merging adjacent pages together */ |
| 301 | static void populate_rw_params(struct page **pages, | 289 | static void populate_rw_params(struct page **pages, |
| 302 | int pages_count, | 290 | int pages_count, |
| @@ -354,9 +342,9 @@ static int transfer_max_buffers(struct goldfish_pipe *pipe, · 51 unmodified lines | |||
| 354 | if (mutex_lock_interruptible(&pipe->lock)) | 342 | if (mutex_lock_interruptible(&pipe->lock)) |
| 355 | return -ERESTARTSYS; | 343 | return -ERESTARTSYS; |
| 356 | 344 | ||
| 357 | pages_count = pin_user_pages(first_page, last_page, | 345 | pages_count = goldfish_pin_pages(first_page, last_page, |
| 358 | last_page_size, is_write, | 346 | last_page_size, is_write, |
| 359 | pipe->pages, &iter_last_page_size); | 347 | pipe->pages, &iter_last_page_size); |
| 360 | if (pages_count < 0) { | 348 | if (pages_count < 0) { |
| 361 | mutex_unlock(&pipe->lock); | 349 | mutex_unlock(&pipe->lock); |
| 362 | return pages_count; | 350 | return pages_count; |
| @@ -372,7 +360,8 @@ static int transfer_max_buffers(struct goldfish_pipe *pipe, · 9 unmodified lines | |||
| 372 | 360 | ||
| 373 | *consumed_size = pipe->command_buffer->rw_params.consumed_size; | 361 | *consumed_size = pipe->command_buffer->rw_params.consumed_size; |
| 374 | 362 | ||
| 375 | release_user_pages(pipe->pages, pages_count, is_write, *consumed_size); | 363 | unpin_user_pages_dirty_lock(pipe->pages, pages_count, |
| 364 | !is_write && *consumed_size > 0); | ||
| 376 | 365 | ||
| 377 | mutex_unlock(&pipe->lock); | 366 | mutex_unlock(&pipe->lock); |
| 378 | return 0; | 367 | return 0; |
| @@ -33,9 +33,9 @@ · 32 unmodified lines | |||
| 33 | #include <linux/seq_file.h> | 33 | #include <linux/seq_file.h> |
| 34 | #include <linux/platform_data/x86/asus-wmi.h> | 34 | #include <linux/platform_data/x86/asus-wmi.h> |
| 35 | #include <linux/platform_device.h> | 35 | #include <linux/platform_device.h> |
| 36 | #include <linux/thermal.h> | ||
| 37 | #include <linux/acpi.h> | 36 | #include <linux/acpi.h> |
| 38 | #include <linux/dmi.h> | 37 | #include <linux/dmi.h> |
| 38 | #include <linux/units.h> | ||
| 39 | 39 | ||
| 40 | #include <acpi/battery.h> | 40 | #include <acpi/battery.h> |
| 41 | #include <acpi/video.h> | 41 | #include <acpi/video.h> |
| @@ -1514,9 +1514,8 @@ static ssize_t asus_hwmon_temp1(struct device *dev, · 1472 unmodified lines | |||
| 1514 | if (err < 0) | 1514 | if (err < 0) |
| 1515 | return err; | 1515 | return err; |
| 1516 | 1516 | ||
| 1517 | value = DECI_KELVIN_TO_CELSIUS((value & 0xFFFF)) * 1000; | 1517 | return sprintf(buf, "%ld\n", |
| 1518 | 1518 | deci_kelvin_to_millicelsius(value & 0xFFFF)); | |
| 1519 | return sprintf(buf, "%d\n", value); | ||
| 1520 | } | 1519 | } |
| 1521 | 1520 | ||
| 1522 | /* Fan1 */ | 1521 | /* Fan1 */ |
| @@ -22,6 +22,7 @@ · 21 unmodified lines | |||
| 22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
| 23 | #include <linux/thermal.h> | 23 | #include <linux/thermal.h> |
| 24 | #include <linux/types.h> | 24 | #include <linux/types.h> |
| 25 | #include <linux/units.h> | ||
| 25 | 26 | ||
| 26 | MODULE_AUTHOR("Thomas Sujith"); | 27 | MODULE_AUTHOR("Thomas Sujith"); |
| 27 | MODULE_AUTHOR("Zhang Rui"); | 28 | MODULE_AUTHOR("Zhang Rui"); |
| @@ -302,8 +303,10 @@ static ssize_t aux_show(struct device *dev, struct device_attribute *dev_attr, · 274 unmodified lines | |||
| 302 | int result; | 303 | int result; |
| 303 | 304 | ||
| 304 | result = sensor_get_auxtrip(attr->handle, idx, &value); | 305 | result = sensor_get_auxtrip(attr->handle, idx, &value); |
| 306 | if (result) | ||
| 307 | return result; | ||
| 305 | 308 | ||
| 306 | return result ? result : sprintf(buf, "%lu", DECI_KELVIN_TO_CELSIUS(value)); | 309 | return sprintf(buf, "%lu", deci_kelvin_to_celsius(value)); |
| 307 | } | 310 | } |
| 308 | 311 | ||
| 309 | static ssize_t aux0_show(struct device *dev, | 312 | static ssize_t aux0_show(struct device *dev, |
| @@ -332,8 +335,8 @@ static ssize_t aux_store(struct device *dev, struct device_attribute *dev_attr, · 22 unmodified lines | |||
| 332 | if (value < 0) | 335 | if (value < 0) |
| 333 | return -EINVAL; | 336 | return -EINVAL; |
| 334 | 337 | ||
| 335 | result = sensor_set_auxtrip(attr->handle, idx, | 338 | result = sensor_set_auxtrip(attr->handle, idx, |
| 336 | CELSIUS_TO_DECI_KELVIN(value)); | 339 | celsius_to_deci_kelvin(value)); |
| 337 | return result ? result : count; | 340 | return result ? result : count; |
| 338 | } | 341 | } |
| 339 | 342 | ||
| @@ -21,8 +21,6 @@ · 20 unmodified lines | |||
| 21 | 21 | ||
| 22 | #include "thermal_core.h" | 22 | #include "thermal_core.h" |
| 23 | 23 | ||
| 24 | #define TO_MCELSIUS(c) ((c) * 1000) | ||
| 25 | |||
| 26 | /* Thermal Manager Control and Status Register */ | 24 | /* Thermal Manager Control and Status Register */ |
| 27 | #define PMU_TDC0_SW_RST_MASK (0x1 << 1) | 25 | #define PMU_TDC0_SW_RST_MASK (0x1 << 1) |
| 28 | #define PMU_TM_DISABLE_OFFS 0 | 26 | #define PMU_TM_DISABLE_OFFS 0 |
| @@ -8,6 +8,7 @@ · 7 unmodified lines | |||
| 8 | #include <linux/init.h> | 8 | #include <linux/init.h> |
| 9 | #include <linux/acpi.h> | 9 | #include <linux/acpi.h> |
| 10 | #include <linux/thermal.h> | 10 | #include <linux/thermal.h> |
| 11 | #include <linux/units.h> | ||
| 11 | #include "int340x_thermal_zone.h" | 12 | #include "int340x_thermal_zone.h" |
| 12 | 13 | ||
| 13 | static int int340x_thermal_get_zone_temp(struct thermal_zone_device *zone, | 14 | static int int340x_thermal_get_zone_temp(struct thermal_zone_device *zone, |
| @@ -34,7 +35,7 @@ static int int340x_thermal_get_zone_temp(struct thermal_zone_device *zone, · 20 unmodified lines | |||
| 34 | *temp = (unsigned long)conv_temp * 10; | 35 | *temp = (unsigned long)conv_temp * 10; |
| 35 | } else | 36 | } else |
| 36 | /* _TMP returns the temperature in tenths of degrees Kelvin */ | 37 | /* _TMP returns the temperature in tenths of degrees Kelvin */ |
| 37 | *temp = DECI_KELVIN_TO_MILLICELSIUS(tmp); | 38 | *temp = deci_kelvin_to_millicelsius(tmp); |
| 38 | 39 | ||
| 39 | return 0; | 40 | return 0; |
| 40 | } | 41 | } |
| @@ -116,7 +117,7 @@ static int int340x_thermal_set_trip_temp(struct thermal_zone_device *zone, · 75 unmodified lines | |||
| 116 | 117 | ||
| 117 | snprintf(name, sizeof(name), "PAT%d", trip); | 118 | snprintf(name, sizeof(name), "PAT%d", trip); |
| 118 | status = acpi_execute_simple_method(d->adev->handle, name, | 119 | status = acpi_execute_simple_method(d->adev->handle, name, |
| 119 | MILLICELSIUS_TO_DECI_KELVIN(temp)); | 120 | millicelsius_to_deci_kelvin(temp)); |
| 120 | if (ACPI_FAILURE(status)) | 121 | if (ACPI_FAILURE(status)) |
| 121 | return -EIO; | 122 | return -EIO; |
| 122 | 123 | ||
| @@ -163,7 +164,7 @@ static int int340x_thermal_get_trip_config(acpi_handle handle, char *name, · 40 unmodified lines | |||
| 163 | if (ACPI_FAILURE(status)) | 164 | if (ACPI_FAILURE(status)) |
| 164 | return -EIO; | 165 | return -EIO; |
| 165 | 166 | ||
| 166 | *temp = DECI_KELVIN_TO_MILLICELSIUS(r); | 167 | *temp = deci_kelvin_to_millicelsius(r); |
| 167 | 168 | ||
| 168 | return 0; | 169 | return 0; |
| 169 | } | 170 | } |
| @@ -13,6 +13,7 @@ · 12 unmodified lines | |||
| 13 | #include <linux/pci.h> | 13 | #include <linux/pci.h> |
| 14 | #include <linux/acpi.h> | 14 | #include <linux/acpi.h> |
| 15 | #include <linux/thermal.h> | 15 | #include <linux/thermal.h> |
| 16 | #include <linux/units.h> | ||
| 16 | #include <linux/pm.h> | 17 | #include <linux/pm.h> |
| 17 | 18 | ||
| 18 | /* Intel PCH thermal Device IDs */ | 19 | /* Intel PCH thermal Device IDs */ |
| @@ -93,7 +94,7 @@ static void pch_wpt_add_acpi_psv_trip(struct pch_thermal_device *ptd, · 74 unmodified lines | |||
| 93 | if (ACPI_SUCCESS(status)) { | 94 | if (ACPI_SUCCESS(status)) { |
| 94 | unsigned long trip_temp; | 95 | unsigned long trip_temp; |
| 95 | 96 | ||
| 96 | trip_temp = DECI_KELVIN_TO_MILLICELSIUS(r); | 97 | trip_temp = deci_kelvin_to_millicelsius(r); |
| 97 | if (trip_temp) { | 98 | if (trip_temp) { |
| 98 | ptd->psv_temp = trip_temp; | 99 | ptd->psv_temp = trip_temp; |
| 99 | ptd->psv_trip_id = *nr_trips; | 100 | ptd->psv_trip_id = *nr_trips; |
| @@ -309,9 +309,8 @@ static int put_pfn(unsigned long pfn, int prot) · 308 unmodified lines | |||
| 309 | { | 309 | { |
| 310 | if (!is_invalid_reserved_pfn(pfn)) { | 310 | if (!is_invalid_reserved_pfn(pfn)) { |
| 311 | struct page *page = pfn_to_page(pfn); | 311 | struct page *page = pfn_to_page(pfn); |
| 312 | if (prot & IOMMU_WRITE) | 312 | |
| 313 | SetPageDirty(page); | 313 | unpin_user_pages_dirty_lock(&page, 1, prot & IOMMU_WRITE); |
| 314 | put_page(page); | ||
| 315 | return 1; | 314 | return 1; |
| 316 | } | 315 | } |
| 317 | return 0; | 316 | return 0; |
| @@ -322,7 +321,6 @@ static int vaddr_get_pfn(struct mm_struct *mm, unsigned long vaddr, · 4 unmodified lines | |||
| 322 | { | 321 | { |
| 323 | struct page *page[1]; | 322 | struct page *page[1]; |
| 324 | struct vm_area_struct *vma; | 323 | struct vm_area_struct *vma; |
| 325 | struct vm_area_struct *vmas[1]; | ||
| 326 | unsigned int flags = 0; | 324 | unsigned int flags = 0; |
| 327 | int ret; | 325 | int ret; |
| 328 | 326 | ||
| @@ -330,33 +328,14 @@ static int vaddr_get_pfn(struct mm_struct *mm, unsigned long vaddr, · 1 unmodified line | |||
| 330 | flags |= FOLL_WRITE; | 328 | flags |= FOLL_WRITE; |
| 331 | 329 | ||
| 332 | down_read(&mm->mmap_sem); | 330 | down_read(&mm->mmap_sem); |
| 333 | if (mm == current->mm) { | 331 | ret = pin_user_pages_remote(NULL, mm, vaddr, 1, flags | FOLL_LONGTERM, |
| 334 | ret = get_user_pages(vaddr, 1, flags | FOLL_LONGTERM, page, | 332 | page, NULL, NULL); |
| 335 | vmas); | ||
| 336 | } else { | ||
| 337 | ret = get_user_pages_remote(NULL, mm, vaddr, 1, flags, page, | ||
| 338 | vmas, NULL); | ||
| 339 | /* | ||
| 340 | * The lifetime of a vaddr_get_pfn() page pin is | ||
| 341 | * userspace-controlled. In the fs-dax case this could | ||
| 342 | * lead to indefinite stalls in filesystem operations. | ||
| 343 | * Disallow attempts to pin fs-dax pages via this | ||
| 344 | * interface. | ||
| 345 | */ | ||
| 346 | if (ret > 0 && vma_is_fsdax(vmas[0])) { | ||
| 347 | ret = -EOPNOTSUPP; | ||
| 348 | put_page(page[0]); | ||
| 349 | } | ||
| 350 | } | ||
| 351 | up_read(&mm->mmap_sem); | ||
| 352 | |||
| 353 | if (ret == 1) { | 333 | if (ret == 1) { |
| 354 | *pfn = page_to_pfn(page[0]); | 334 | *pfn = page_to_pfn(page[0]); |
| 355 | return 0; | 335 | ret = 0; |
| 336 | goto done; | ||
| 356 | } | 337 | } |
| 357 | 338 | ||
| 358 | down_read(&mm->mmap_sem); | ||
| 359 | |||
| 360 | vaddr = untagged_addr(vaddr); | 339 | vaddr = untagged_addr(vaddr); |
| 361 | 340 | ||
| 362 | vma = find_vma_intersection(mm, vaddr, vaddr + 1); | 341 | vma = find_vma_intersection(mm, vaddr, vaddr + 1); |
| @@ -366,7 +345,7 @@ static int vaddr_get_pfn(struct mm_struct *mm, unsigned long vaddr, · 3 unmodified lines | |||
| 366 | if (is_invalid_reserved_pfn(*pfn)) | 345 | if (is_invalid_reserved_pfn(*pfn)) |
| 367 | ret = 0; | 346 | ret = 0; |
| 368 | } | 347 | } |
| 369 | 348 | done: | |
| 370 | up_read(&mm->mmap_sem); | 349 | up_read(&mm->mmap_sem); |
| 371 | return ret; | 350 | return ret; |
| 372 | } | 351 | } |
| @@ -97,7 +97,7 @@ static struct linux_binfmt elf_format = { · 96 unmodified lines | |||
| 97 | .min_coredump = ELF_EXEC_PAGESIZE, | 97 | .min_coredump = ELF_EXEC_PAGESIZE, |
| 98 | }; | 98 | }; |
| 99 | 99 | ||
| 100 | #define BAD_ADDR(x) ((unsigned long)(x) >= TASK_SIZE) | 100 | #define BAD_ADDR(x) (unlikely((unsigned long)(x) >= TASK_SIZE)) |
| 101 | 101 | ||
| 102 | static int set_brk(unsigned long start, unsigned long end, int prot) | 102 | static int set_brk(unsigned long start, unsigned long end, int prot) |
| 103 | { | 103 | { |
| @@ -161,9 +161,11 @@ static int padzero(unsigned long elf_bss) · 57 unmodified lines | |||
| 161 | #endif | 161 | #endif |
| 162 | 162 | ||
| 163 | static int | 163 | static int |
| 164 | create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, | 164 | create_elf_tables(struct linux_binprm *bprm, const struct elfhdr *exec, |
| 165 | unsigned long load_addr, unsigned long interp_load_addr) | 165 | unsigned long load_addr, unsigned long interp_load_addr, |
| 166 | unsigned long e_entry) | ||
| 166 | { | 167 | { |
| 168 | struct mm_struct *mm = current->mm; | ||
| 167 | unsigned long p = bprm->p; | 169 | unsigned long p = bprm->p; |
| 168 | int argc = bprm->argc; | 170 | int argc = bprm->argc; |
| 169 | int envc = bprm->envc; | 171 | int envc = bprm->envc; |
| @@ -176,7 +178,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, · 6 unmodified lines | |||
| 176 | unsigned char k_rand_bytes[16]; | 178 | unsigned char k_rand_bytes[16]; |
| 177 | int items; | 179 | int items; |
| 178 | elf_addr_t *elf_info; | 180 | elf_addr_t *elf_info; |
| 179 | int ei_index = 0; | 181 | int ei_index; |
| 180 | const struct cred *cred = current_cred(); | 182 | const struct cred *cred = current_cred(); |
| 181 | struct vm_area_struct *vma; | 183 | struct vm_area_struct *vma; |
| 182 | 184 | ||
| @@ -226,12 +228,12 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, · 43 unmodified lines | |||
| 226 | return -EFAULT; | 228 | return -EFAULT; |
| 227 | 229 | ||
| 228 | /* Create the ELF interpreter info */ | 230 | /* Create the ELF interpreter info */ |
| 229 | elf_info = (elf_addr_t *)current->mm->saved_auxv; | 231 | elf_info = (elf_addr_t *)mm->saved_auxv; |
| 230 | /* update AT_VECTOR_SIZE_BASE if the number of NEW_AUX_ENT() changes */ | 232 | /* update AT_VECTOR_SIZE_BASE if the number of NEW_AUX_ENT() changes */ |
| 231 | #define NEW_AUX_ENT(id, val) \ | 233 | #define NEW_AUX_ENT(id, val) \ |
| 232 | do { \ | 234 | do { \ |
| 233 | elf_info[ei_index++] = id; \ | 235 | *elf_info++ = id; \ |
| 234 | elf_info[ei_index++] = val; \ | 236 | *elf_info++ = val; \ |
| 235 | } while (0) | 237 | } while (0) |
| 236 | 238 | ||
| 237 | #ifdef ARCH_DLINFO | 239 | #ifdef ARCH_DLINFO |
| @@ -251,7 +253,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, · 13 unmodified lines | |||
| 251 | NEW_AUX_ENT(AT_PHNUM, exec->e_phnum); | 253 | NEW_AUX_ENT(AT_PHNUM, exec->e_phnum); |
| 252 | NEW_AUX_ENT(AT_BASE, interp_load_addr); | 254 | NEW_AUX_ENT(AT_BASE, interp_load_addr); |
| 253 | NEW_AUX_ENT(AT_FLAGS, 0); | 255 | NEW_AUX_ENT(AT_FLAGS, 0); |
| 254 | NEW_AUX_ENT(AT_ENTRY, exec->e_entry); | 256 | NEW_AUX_ENT(AT_ENTRY, e_entry); |
| 255 | NEW_AUX_ENT(AT_UID, from_kuid_munged(cred->user_ns, cred->uid)); | 257 | NEW_AUX_ENT(AT_UID, from_kuid_munged(cred->user_ns, cred->uid)); |
| 256 | NEW_AUX_ENT(AT_EUID, from_kuid_munged(cred->user_ns, cred->euid)); | 258 | NEW_AUX_ENT(AT_EUID, from_kuid_munged(cred->user_ns, cred->euid)); |
| 257 | NEW_AUX_ENT(AT_GID, from_kgid_munged(cred->user_ns, cred->gid)); | 259 | NEW_AUX_ENT(AT_GID, from_kgid_munged(cred->user_ns, cred->gid)); |
| @@ -275,12 +277,13 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, · 17 unmodified lines | |||
| 275 | } | 277 | } |
| 276 | #undef NEW_AUX_ENT | 278 | #undef NEW_AUX_ENT |
| 277 | /* AT_NULL is zero; clear the rest too */ | 279 | /* AT_NULL is zero; clear the rest too */ |
| 278 | memset(&elf_info[ei_index], 0, | 280 | memset(elf_info, 0, (char *)mm->saved_auxv + |
| 279 | sizeof current->mm->saved_auxv - ei_index * sizeof elf_info[0]); | 281 | sizeof(mm->saved_auxv) - (char *)elf_info); |
| 280 | 282 | ||
| 281 | /* And advance past the AT_NULL entry. */ | 283 | /* And advance past the AT_NULL entry. */ |
| 282 | ei_index += 2; | 284 | elf_info += 2; |
| 283 | 285 | ||
| 286 | ei_index = elf_info - (elf_addr_t *)mm->saved_auxv; | ||
| 284 | sp = STACK_ADD(p, ei_index); | 287 | sp = STACK_ADD(p, ei_index); |
| 285 | 288 | ||
| 286 | items = (argc + 1) + (envc + 1) + 1; | 289 | items = (argc + 1) + (envc + 1) + 1; |
| @@ -299,7 +302,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, · 12 unmodified lines | |||
| 299 | * Grow the stack manually; some architectures have a limit on how | 302 | * Grow the stack manually; some architectures have a limit on how |
| 300 | * far ahead a user-space access may be in order to grow the stack. | 303 | * far ahead a user-space access may be in order to grow the stack. |
| 301 | */ | 304 | */ |
| 302 | vma = find_extend_vma(current->mm, bprm->p); | 305 | vma = find_extend_vma(mm, bprm->p); |
| 303 | if (!vma) | 306 | if (!vma) |
| 304 | return -EFAULT; | 307 | return -EFAULT; |
| 305 | 308 | ||
| @@ -308,7 +311,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, · 2 unmodified lines | |||
| 308 | return -EFAULT; | 311 | return -EFAULT; |
| 309 | 312 | ||
| 310 | /* Populate list of argv pointers back to argv strings. */ | 313 | /* Populate list of argv pointers back to argv strings. */ |
| 311 | p = current->mm->arg_end = current->mm->arg_start; | 314 | p = mm->arg_end = mm->arg_start; |
| 312 | while (argc-- > 0) { | 315 | while (argc-- > 0) { |
| 313 | size_t len; | 316 | size_t len; |
| 314 | if (__put_user((elf_addr_t)p, sp++)) | 317 | if (__put_user((elf_addr_t)p, sp++)) |
| @@ -320,10 +323,10 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, · 5 unmodified lines | |||
| 320 | } | 323 | } |
| 321 | if (__put_user(0, sp++)) | 324 | if (__put_user(0, sp++)) |
| 322 | return -EFAULT; | 325 | return -EFAULT; |
| 323 | current->mm->arg_end = p; | 326 | mm->arg_end = p; |
| 324 | 327 | ||
| 325 | /* Populate list of envp pointers back to envp strings. */ | 328 | /* Populate list of envp pointers back to envp strings. */ |
| 326 | current->mm->env_end = current->mm->env_start = p; | 329 | mm->env_end = mm->env_start = p; |
| 327 | while (envc-- > 0) { | 330 | while (envc-- > 0) { |
| 328 | size_t len; | 331 | size_t len; |
| 329 | if (__put_user((elf_addr_t)p, sp++)) | 332 | if (__put_user((elf_addr_t)p, sp++)) |
| @@ -335,10 +338,10 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, · 5 unmodified lines | |||
| 335 | } | 338 | } |
| 336 | if (__put_user(0, sp++)) | 339 | if (__put_user(0, sp++)) |
| 337 | return -EFAULT; | 340 | return -EFAULT; |
| 338 | current->mm->env_end = p; | 341 | mm->env_end = p; |
| 339 | 342 | ||
| 340 | /* Put the elf_info on the stack in the right place. */ | 343 | /* Put the elf_info on the stack in the right place. */ |
| 341 | if (copy_to_user(sp, elf_info, ei_index * sizeof(elf_addr_t))) | 344 | if (copy_to_user(sp, mm->saved_auxv, ei_index * sizeof(elf_addr_t))) |
| 342 | return -EFAULT; | 345 | return -EFAULT; |
| 343 | return 0; | 346 | return 0; |
| 344 | } | 347 | } |
| @@ -689,15 +692,17 @@ static int load_elf_binary(struct linux_binprm *bprm) · 344 unmodified lines | |||
| 689 | int bss_prot = 0; | 692 | int bss_prot = 0; |
| 690 | int retval, i; | 693 | int retval, i; |
| 691 | unsigned long elf_entry; | 694 | unsigned long elf_entry; |
| 695 | unsigned long e_entry; | ||
| 692 | unsigned long interp_load_addr = 0; | 696 | unsigned long interp_load_addr = 0; |
| 693 | unsigned long start_code, end_code, start_data, end_data; | 697 | unsigned long start_code, end_code, start_data, end_data; |
| 694 | unsigned long reloc_func_desc __maybe_unused = 0; | 698 | unsigned long reloc_func_desc __maybe_unused = 0; |
| 695 | int executable_stack = EXSTACK_DEFAULT; | 699 | int executable_stack = EXSTACK_DEFAULT; |
| 700 | struct elfhdr *elf_ex = (struct elfhdr *)bprm->buf; | ||
| 696 | struct { | 701 | struct { |
| 697 | struct elfhdr elf_ex; | ||
| 698 | struct elfhdr interp_elf_ex; | 702 | struct elfhdr interp_elf_ex; |
| 699 | } *loc; | 703 | } *loc; |
| 700 | struct arch_elf_state arch_state = INIT_ARCH_ELF_STATE; | 704 | struct arch_elf_state arch_state = INIT_ARCH_ELF_STATE; |
| 705 | struct mm_struct *mm; | ||
| 701 | struct pt_regs *regs; | 706 | struct pt_regs *regs; |
| 702 | 707 | ||
| 703 | loc = kmalloc(sizeof(*loc), GFP_KERNEL); | 708 | loc = kmalloc(sizeof(*loc), GFP_KERNEL); |
| @@ -705,30 +710,27 @@ static int load_elf_binary(struct linux_binprm *bprm) · 1 unmodified line | |||
| 705 | retval = -ENOMEM; | 710 | retval = -ENOMEM; |
| 706 | goto out_ret; | 711 | goto out_ret; |
| 707 | } | 712 | } |
| 708 | |||
| 709 | /* Get the exec-header */ | ||
| 710 | loc->elf_ex = *((struct elfhdr *)bprm->buf); | ||
| 711 | 713 | ||
| 712 | retval = -ENOEXEC; | 714 | retval = -ENOEXEC; |
| 713 | /* First of all, some simple consistency checks */ | 715 | /* First of all, some simple consistency checks */ |
| 714 | if (memcmp(loc->elf_ex.e_ident, ELFMAG, SELFMAG) != 0) | 716 | if (memcmp(elf_ex->e_ident, ELFMAG, SELFMAG) != 0) |
| 715 | goto out; | 717 | goto out; |
| 716 | 718 | ||
| 717 | if (loc->elf_ex.e_type != ET_EXEC && loc->elf_ex.e_type != ET_DYN) | 719 | if (elf_ex->e_type != ET_EXEC && elf_ex->e_type != ET_DYN) |
| 718 | goto out; | 720 | goto out; |
| 719 | if (!elf_check_arch(&loc->elf_ex)) | 721 | if (!elf_check_arch(elf_ex)) |
| 720 | goto out; | 722 | goto out; |
| 721 | if (elf_check_fdpic(&loc->elf_ex)) | 723 | if (elf_check_fdpic(elf_ex)) |
| 722 | goto out; | 724 | goto out; |
| 723 | if (!bprm->file->f_op->mmap) | 725 | if (!bprm->file->f_op->mmap) |
| 724 | goto out; | 726 | goto out; |
| 725 | 727 | ||
| 726 | elf_phdata = load_elf_phdrs(&loc->elf_ex, bprm->file); | 728 | elf_phdata = load_elf_phdrs(elf_ex, bprm->file); |
| 727 | if (!elf_phdata) | 729 | if (!elf_phdata) |
| 728 | goto out; | 730 | goto out; |
| 729 | 731 | ||
| 730 | elf_ppnt = elf_phdata; | 732 | elf_ppnt = elf_phdata; |
| 731 | for (i = 0; i < loc->elf_ex.e_phnum; i++, elf_ppnt++) { | 733 | for (i = 0; i < elf_ex->e_phnum; i++, elf_ppnt++) { |
| 732 | char *elf_interpreter; | 734 | char *elf_interpreter; |
| 733 | 735 | ||
| 734 | if (elf_ppnt->p_type != PT_INTERP) | 736 | if (elf_ppnt->p_type != PT_INTERP) |
| @@ -782,7 +784,7 @@ out_free_interp: · 47 unmodified lines | |||
| 782 | } | 784 | } |
| 783 | 785 | ||
| 784 | elf_ppnt = elf_phdata; | 786 | elf_ppnt = elf_phdata; |
| 785 | for (i = 0; i < loc->elf_ex.e_phnum; i++, elf_ppnt++) | 787 | for (i = 0; i < elf_ex->e_phnum; i++, elf_ppnt++) |
| 786 | switch (elf_ppnt->p_type) { | 788 | switch (elf_ppnt->p_type) { |
| 787 | case PT_GNU_STACK: | 789 | case PT_GNU_STACK: |
| 788 | if (elf_ppnt->p_flags & PF_X) | 790 | if (elf_ppnt->p_flags & PF_X) |
| @@ -792,7 +794,7 @@ out_free_interp: · 3 unmodified lines | |||
| 792 | break; | 794 | break; |
| 793 | 795 | ||
| 794 | case PT_LOPROC ... PT_HIPROC: | 796 | case PT_LOPROC ... PT_HIPROC: |
| 795 | retval = arch_elf_pt_proc(&loc->elf_ex, elf_ppnt, | 797 | retval = arch_elf_pt_proc(elf_ex, elf_ppnt, |
| 796 | bprm->file, false, | 798 | bprm->file, false, |
| 797 | &arch_state); | 799 | &arch_state); |
| 798 | if (retval) | 800 | if (retval) |
| @@ -836,7 +838,7 @@ out_free_interp: · 37 unmodified lines | |||
| 836 | * still possible to return an error to the code that invoked | 838 | * still possible to return an error to the code that invoked |
| 837 | * the exec syscall. | 839 | * the exec syscall. |
| 838 | */ | 840 | */ |
| 839 | retval = arch_check_elf(&loc->elf_ex, | 841 | retval = arch_check_elf(elf_ex, |
| 840 | !!interpreter, &loc->interp_elf_ex, | 842 | !!interpreter, &loc->interp_elf_ex, |
| 841 | &arch_state); | 843 | &arch_state); |
| 842 | if (retval) | 844 | if (retval) |
| @@ -849,8 +851,8 @@ out_free_interp: · 6 unmodified lines | |||
| 849 | 851 | ||
| 850 | /* Do this immediately, since STACK_TOP as used in setup_arg_pages | 852 | /* Do this immediately, since STACK_TOP as used in setup_arg_pages |
| 851 | may depend on the personality. */ | 853 | may depend on the personality. */ |
| 852 | SET_PERSONALITY2(loc->elf_ex, &arch_state); | 854 | SET_PERSONALITY2(*elf_ex, &arch_state); |
| 853 | if (elf_read_implies_exec(loc->elf_ex, executable_stack)) | 855 | if (elf_read_implies_exec(*elf_ex, executable_stack)) |
| 854 | current->personality |= READ_IMPLIES_EXEC; | 856 | current->personality |= READ_IMPLIES_EXEC; |
| 855 | 857 | ||
| 856 | if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) | 858 | if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) |
| @@ -877,7 +879,7 @@ out_free_interp: · 20 unmodified lines | |||
| 877 | /* Now we do a little grungy work by mmapping the ELF image into | 879 | /* Now we do a little grungy work by mmapping the ELF image into |
| 878 | the correct location in memory. */ | 880 | the correct location in memory. */ |
| 879 | for(i = 0, elf_ppnt = elf_phdata; | 881 | for(i = 0, elf_ppnt = elf_phdata; |
| 880 | i < loc->elf_ex.e_phnum; i++, elf_ppnt++) { | 882 | i < elf_ex->e_phnum; i++, elf_ppnt++) { |
| 881 | int elf_prot, elf_flags; | 883 | int elf_prot, elf_flags; |
| 882 | unsigned long k, vaddr; | 884 | unsigned long k, vaddr; |
| 883 | unsigned long total_size = 0; | 885 | unsigned long total_size = 0; |
| @@ -921,9 +923,9 @@ out_free_interp: · 37 unmodified lines | |||
| 921 | * If we are loading ET_EXEC or we have already performed | 923 | * If we are loading ET_EXEC or we have already performed |
| 922 | * the ET_DYN load_addr calculations, proceed normally. | 924 | * the ET_DYN load_addr calculations, proceed normally. |
| 923 | */ | 925 | */ |
| 924 | if (loc->elf_ex.e_type == ET_EXEC || load_addr_set) { | 926 | if (elf_ex->e_type == ET_EXEC || load_addr_set) { |
| 925 | elf_flags |= MAP_FIXED; | 927 | elf_flags |= MAP_FIXED; |
| 926 | } else if (loc->elf_ex.e_type == ET_DYN) { | 928 | } else if (elf_ex->e_type == ET_DYN) { |
| 927 | /* | 929 | /* |
| 928 | * This logic is run once for the first LOAD Program | 930 | * This logic is run once for the first LOAD Program |
| 929 | * Header for ET_DYN binaries to calculate the | 931 | * Header for ET_DYN binaries to calculate the |
| @@ -972,7 +974,7 @@ out_free_interp: · 42 unmodified lines | |||
| 972 | load_bias = ELF_PAGESTART(load_bias - vaddr); | 974 | load_bias = ELF_PAGESTART(load_bias - vaddr); |
| 973 | 975 | ||
| 974 | total_size = total_mapping_size(elf_phdata, | 976 | total_size = total_mapping_size(elf_phdata, |
| 975 | loc->elf_ex.e_phnum); | 977 | elf_ex->e_phnum); |
| 976 | if (!total_size) { | 978 | if (!total_size) { |
| 977 | retval = -EINVAL; | 979 | retval = -EINVAL; |
| 978 | goto out_free_dentry; | 980 | goto out_free_dentry; |
| @@ -990,7 +992,7 @@ out_free_interp: · 11 unmodified lines | |||
| 990 | if (!load_addr_set) { | 992 | if (!load_addr_set) { |
| 991 | load_addr_set = 1; | 993 | load_addr_set = 1; |
| 992 | load_addr = (elf_ppnt->p_vaddr - elf_ppnt->p_offset); | 994 | load_addr = (elf_ppnt->p_vaddr - elf_ppnt->p_offset); |
| 993 | if (loc->elf_ex.e_type == ET_DYN) { | 995 | if (elf_ex->e_type == ET_DYN) { |
| 994 | load_bias += error - | 996 | load_bias += error - |
| 995 | ELF_PAGESTART(load_bias + vaddr); | 997 | ELF_PAGESTART(load_bias + vaddr); |
| 996 | load_addr += load_bias; | 998 | load_addr += load_bias; |
| @@ -998,7 +1000,7 @@ out_free_interp: · 1 unmodified line | |||
| 998 | } | 1000 | } |
| 999 | } | 1001 | } |
| 1000 | k = elf_ppnt->p_vaddr; | 1002 | k = elf_ppnt->p_vaddr; |
| 1001 | if (k < start_code) | 1003 | if ((elf_ppnt->p_flags & PF_X) && k < start_code) |
| 1002 | start_code = k; | 1004 | start_code = k; |
| 1003 | if (start_data < k) | 1005 | if (start_data < k) |
| 1004 | start_data = k; | 1006 | start_data = k; |
| @@ -1031,7 +1033,7 @@ out_free_interp: · 26 unmodified lines | |||
| 1031 | } | 1033 | } |
| 1032 | } | 1034 | } |
| 1033 | 1035 | ||
| 1034 | loc->elf_ex.e_entry += load_bias; | 1036 | e_entry = elf_ex->e_entry + load_bias; |
| 1035 | elf_bss += load_bias; | 1037 | elf_bss += load_bias; |
| 1036 | elf_brk += load_bias; | 1038 | elf_brk += load_bias; |
| 1037 | start_code += load_bias; | 1039 | start_code += load_bias; |
| @@ -1074,7 +1076,7 @@ out_free_interp: · 36 unmodified lines | |||
| 1074 | allow_write_access(interpreter); | 1076 | allow_write_access(interpreter); |
| 1075 | fput(interpreter); | 1077 | fput(interpreter); |
| 1076 | } else { | 1078 | } else { |
| 1077 | elf_entry = loc->elf_ex.e_entry; | 1079 | elf_entry = e_entry; |
| 1078 | if (BAD_ADDR(elf_entry)) { | 1080 | if (BAD_ADDR(elf_entry)) { |
| 1079 | retval = -EINVAL; | 1081 | retval = -EINVAL; |
| 1080 | goto out_free_dentry; | 1082 | goto out_free_dentry; |
| @@ -1092,15 +1094,17 @@ out_free_interp: · 11 unmodified lines | |||
| 1092 | goto out; | 1094 | goto out; |
| 1093 | #endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */ | 1095 | #endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */ |
| 1094 | 1096 | ||
| 1095 | retval = create_elf_tables(bprm, &loc->elf_ex, | 1097 | retval = create_elf_tables(bprm, elf_ex, |
| 1096 | load_addr, interp_load_addr); | 1098 | load_addr, interp_load_addr, e_entry); |
| 1097 | if (retval < 0) | 1099 | if (retval < 0) |
| 1098 | goto out; | 1100 | goto out; |
| 1099 | current->mm->end_code = end_code; | 1101 | |
| 1100 | current->mm->start_code = start_code; | 1102 | mm = current->mm; |
| 1101 | current->mm->start_data = start_data; | 1103 | mm->end_code = end_code; |
| 1102 | current->mm->end_data = end_data; | 1104 | mm->start_code = start_code; |
| 1103 | current->mm->start_stack = bprm->p; | 1105 | mm->start_data = start_data; |
| 1106 | mm->end_data = end_data; | ||
| 1107 | mm->start_stack = bprm->p; | ||
| 1104 | 1108 | ||
| 1105 | if ((current->flags & PF_RANDOMIZE) && (randomize_va_space > 1)) { | 1109 | if ((current->flags & PF_RANDOMIZE) && (randomize_va_space > 1)) { |
| 1106 | /* | 1110 | /* |
| @@ -1111,12 +1115,11 @@ out_free_interp: · 4 unmodified lines | |||
| 1111 | * growing down), and into the unused ELF_ET_DYN_BASE region. | 1115 | * growing down), and into the unused ELF_ET_DYN_BASE region. |
| 1112 | */ | 1116 | */ |
| 1113 | if (IS_ENABLED(CONFIG_ARCH_HAS_ELF_RANDOMIZE) && | 1117 | if (IS_ENABLED(CONFIG_ARCH_HAS_ELF_RANDOMIZE) && |
| 1114 | loc->elf_ex.e_type == ET_DYN && !interpreter) | 1118 | elf_ex->e_type == ET_DYN && !interpreter) { |
| 1115 | current->mm->brk = current->mm->start_brk = | 1119 | mm->brk = mm->start_brk = ELF_ET_DYN_BASE; |
| 1116 | ELF_ET_DYN_BASE; | 1120 | } |
| 1117 | 1121 | ||
| 1118 | current->mm->brk = current->mm->start_brk = | 1122 | mm->brk = mm->start_brk = arch_randomize_brk(mm); |
| 1119 | arch_randomize_brk(current->mm); | ||
| 1120 | #ifdef compat_brk_randomized | 1123 | #ifdef compat_brk_randomized |
| 1121 | current->brk_randomized = 1; | 1124 | current->brk_randomized = 1; |
| 1122 | #endif | 1125 | #endif |
| @@ -1574,6 +1577,7 @@ static void fill_siginfo_note(struct memelfnote *note, user_siginfo_t *csigdata, · 451 unmodified lines | |||
| 1574 | */ | 1577 | */ |
| 1575 | static int fill_files_note(struct memelfnote *note) | 1578 | static int fill_files_note(struct memelfnote *note) |
| 1576 | { | 1579 | { |
| 1580 | struct mm_struct *mm = current->mm; | ||
| 1577 | struct vm_area_struct *vma; | 1581 | struct vm_area_struct *vma; |
| 1578 | unsigned count, size, names_ofs, remaining, n; | 1582 | unsigned count, size, names_ofs, remaining, n; |
| 1579 | user_long_t *data; | 1583 | user_long_t *data; |
| @@ -1581,7 +1585,7 @@ static int fill_files_note(struct memelfnote *note) · 1 unmodified line | |||
| 1581 | char *name_base, *name_curpos; | 1585 | char *name_base, *name_curpos; |
| 1582 | 1586 | ||
| 1583 | /* *Estimated* file count and total data size needed */ | 1587 | /* *Estimated* file count and total data size needed */ |
| 1584 | count = current->mm->map_count; | 1588 | count = mm->map_count; |
| 1585 | if (count > UINT_MAX / 64) | 1589 | if (count > UINT_MAX / 64) |
| 1586 | return -EINVAL; | 1590 | return -EINVAL; |
| 1587 | size = count * 64; | 1591 | size = count * 64; |
| @@ -1591,6 +1595,10 @@ static int fill_files_note(struct memelfnote *note) · 3 unmodified lines | |||
| 1591 | if (size >= MAX_FILE_NOTE_SIZE) /* paranoia check */ | 1595 | if (size >= MAX_FILE_NOTE_SIZE) /* paranoia check */ |
| 1592 | return -EINVAL; | 1596 | return -EINVAL; |
| 1593 | size = round_up(size, PAGE_SIZE); | 1597 | size = round_up(size, PAGE_SIZE); |
| 1598 | /* | ||
| 1599 | * "size" can be 0 here legitimately. | ||
| 1600 | * Let it ENOMEM and omit NT_FILE section which will be empty anyway. | ||
| 1601 | */ | ||
| 1594 | data = kvmalloc(size, GFP_KERNEL); | 1602 | data = kvmalloc(size, GFP_KERNEL); |
| 1595 | if (ZERO_OR_NULL_PTR(data)) | 1603 | if (ZERO_OR_NULL_PTR(data)) |
| 1596 | return -ENOMEM; | 1604 | return -ENOMEM; |
| @@ -1599,7 +1607,7 @@ static int fill_files_note(struct memelfnote *note) · 2 unmodified lines | |||
| 1599 | name_base = name_curpos = ((char *)data) + names_ofs; | 1607 | name_base = name_curpos = ((char *)data) + names_ofs; |
| 1600 | remaining = size - names_ofs; | 1608 | remaining = size - names_ofs; |
| 1601 | count = 0; | 1609 | count = 0; |
| 1602 | for (vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) { | 1610 | for (vma = mm->mmap; vma != NULL; vma = vma->vm_next) { |
| 1603 | struct file *file; | 1611 | struct file *file; |
| 1604 | const char *filename; | 1612 | const char *filename; |
| 1605 | 1613 | ||
| @@ -1633,10 +1641,10 @@ static int fill_files_note(struct memelfnote *note) · 27 unmodified lines | |||
| 1633 | data[0] = count; | 1641 | data[0] = count; |
| 1634 | data[1] = PAGE_SIZE; | 1642 | data[1] = PAGE_SIZE; |
| 1635 | /* | 1643 | /* |
| 1636 | * Count usually is less than current->mm->map_count, | 1644 | * Count usually is less than mm->map_count, |
| 1637 | * we need to move filenames down. | 1645 | * we need to move filenames down. |
| 1638 | */ | 1646 | */ |
| 1639 | n = current->mm->map_count - count; | 1647 | n = mm->map_count - count; |
| 1640 | if (n != 0) { | 1648 | if (n != 0) { |
| 1641 | unsigned shift_bytes = n * 3 * sizeof(data[0]); | 1649 | unsigned shift_bytes = n * 3 * sizeof(data[0]); |
| 1642 | memmove(name_base - shift_bytes, name_base, | 1650 | memmove(name_base - shift_bytes, name_base, |
| @@ -2182,7 +2190,7 @@ static int elf_core_dump(struct coredump_params *cprm) · 539 unmodified lines | |||
| 2182 | int segs, i; | 2190 | int segs, i; |
| 2183 | size_t vma_data_size = 0; | 2191 | size_t vma_data_size = 0; |
| 2184 | struct vm_area_struct *vma, *gate_vma; | 2192 | struct vm_area_struct *vma, *gate_vma; |
| 2185 | struct elfhdr *elf = NULL; | 2193 | struct elfhdr elf; |
| 2186 | loff_t offset = 0, dataoff; | 2194 | loff_t offset = 0, dataoff; |
| 2187 | struct elf_note_info info = { }; | 2195 | struct elf_note_info info = { }; |
| 2188 | struct elf_phdr *phdr4note = NULL; | 2196 | struct elf_phdr *phdr4note = NULL; |
| @@ -2203,10 +2211,6 @@ static int elf_core_dump(struct coredump_params *cprm) · 14 unmodified lines | |||
| 2203 | * exists while dumping the mm->vm_next areas to the core file. | 2211 | * exists while dumping the mm->vm_next areas to the core file. |
| 2204 | */ | 2212 | */ |
| 2205 | 2213 | ||
| 2206 | /* alloc memory for large data structures: too large to be on stack */ | ||
| 2207 | elf = kmalloc(sizeof(*elf), GFP_KERNEL); | ||
| 2208 | if (!elf) | ||
| 2209 | goto out; | ||
| 2210 | /* | 2214 | /* |
| 2211 | * The number of segs are recored into ELF header as 16bit value. | 2215 | * The number of segs are recored into ELF header as 16bit value. |
| 2212 | * Please check DEFAULT_MAX_MAP_COUNT definition when you modify here. | 2216 | * Please check DEFAULT_MAX_MAP_COUNT definition when you modify here. |
| @@ -2230,7 +2234,7 @@ static int elf_core_dump(struct coredump_params *cprm) · 17 unmodified lines | |||
| 2230 | * Collect all the non-memory information about the process for the | 2234 | * Collect all the non-memory information about the process for the |
| 2231 | * notes. This also sets up the file header. | 2235 | * notes. This also sets up the file header. |
| 2232 | */ | 2236 | */ |
| 2233 | if (!fill_note_info(elf, e_phnum, &info, cprm->siginfo, cprm->regs)) | 2237 | if (!fill_note_info(&elf, e_phnum, &info, cprm->siginfo, cprm->regs)) |
| 2234 | goto cleanup; | 2238 | goto cleanup; |
| 2235 | 2239 | ||
| 2236 | has_dumped = 1; | 2240 | has_dumped = 1; |
| @@ -2238,7 +2242,7 @@ static int elf_core_dump(struct coredump_params *cprm) · 1 unmodified line | |||
| 2238 | fs = get_fs(); | 2242 | fs = get_fs(); |
| 2239 | set_fs(KERNEL_DS); | 2243 | set_fs(KERNEL_DS); |
| 2240 | 2244 | ||
| 2241 | offset += sizeof(*elf); /* Elf header */ | 2245 | offset += sizeof(elf); /* Elf header */ |
| 2242 | offset += segs * sizeof(struct elf_phdr); /* Program headers */ | 2246 | offset += segs * sizeof(struct elf_phdr); /* Program headers */ |
| 2243 | 2247 | ||
| 2244 | /* Write notes phdr entry */ | 2248 | /* Write notes phdr entry */ |
| @@ -2257,11 +2261,13 @@ static int elf_core_dump(struct coredump_params *cprm) · 12 unmodified lines | |||
| 2257 | 2261 | ||
| 2258 | dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE); | 2262 | dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE); |
| 2259 | 2263 | ||
| 2260 | if (segs - 1 > ULONG_MAX / sizeof(*vma_filesz)) | 2264 | /* |
| 2261 | goto end_coredump; | 2265 | * Zero vma process will get ZERO_SIZE_PTR here. |
| 2266 | * Let coredump continue for register state at least. | ||
| 2267 | */ | ||
| 2262 | vma_filesz = kvmalloc(array_size(sizeof(*vma_filesz), (segs - 1)), | 2268 | vma_filesz = kvmalloc(array_size(sizeof(*vma_filesz), (segs - 1)), |
| 2263 | GFP_KERNEL); | 2269 | GFP_KERNEL); |
| 2264 | if (ZERO_OR_NULL_PTR(vma_filesz)) | 2270 | if (!vma_filesz) |
| 2265 | goto end_coredump; | 2271 | goto end_coredump; |
| 2266 | 2272 | ||
| 2267 | for (i = 0, vma = first_vma(current, gate_vma); vma != NULL; | 2273 | for (i = 0, vma = first_vma(current, gate_vma); vma != NULL; |
| @@ -2281,12 +2287,12 @@ static int elf_core_dump(struct coredump_params *cprm) · 13 unmodified lines | |||
| 2281 | shdr4extnum = kmalloc(sizeof(*shdr4extnum), GFP_KERNEL); | 2287 | shdr4extnum = kmalloc(sizeof(*shdr4extnum), GFP_KERNEL); |
| 2282 | if (!shdr4extnum) | 2288 | if (!shdr4extnum) |
| 2283 | goto end_coredump; | 2289 | goto end_coredump; |
| 2284 | fill_extnum_info(elf, shdr4extnum, e_shoff, segs); | 2290 | fill_extnum_info(&elf, shdr4extnum, e_shoff, segs); |
| 2285 | } | 2291 | } |
| 2286 | 2292 | ||
| 2287 | offset = dataoff; | 2293 | offset = dataoff; |
| 2288 | 2294 | ||
| 2289 | if (!dump_emit(cprm, elf, sizeof(*elf))) | 2295 | if (!dump_emit(cprm, &elf, sizeof(elf))) |
| 2290 | goto end_coredump; | 2296 | goto end_coredump; |
| 2291 | 2297 | ||
| 2292 | if (!dump_emit(cprm, phdr4note, sizeof(*phdr4note))) | 2298 | if (!dump_emit(cprm, phdr4note, sizeof(*phdr4note))) |
| @@ -2370,8 +2376,6 @@ cleanup: · 77 unmodified lines | |||
| 2370 | kfree(shdr4extnum); | 2376 | kfree(shdr4extnum); |
| 2371 | kvfree(vma_filesz); | 2377 | kvfree(vma_filesz); |
| 2372 | kfree(phdr4note); | 2378 | kfree(phdr4note); |
| 2373 | kfree(elf); | ||
| 2374 | out: | ||
| 2375 | return has_dumped; | 2379 | return has_dumped; |
| 2376 | } | 2380 | } |
| 2377 | 2381 | ||
| @@ -1290,7 +1290,7 @@ int btrfs_decompress_buf2page(const char *buf, unsigned long buf_start, · 1289 unmodified lines | |||
| 1290 | /* copy bytes from the working buffer into the pages */ | 1290 | /* copy bytes from the working buffer into the pages */ |
| 1291 | while (working_bytes > 0) { | 1291 | while (working_bytes > 0) { |
| 1292 | bytes = min_t(unsigned long, bvec.bv_len, | 1292 | bytes = min_t(unsigned long, bvec.bv_len, |
| 1293 | PAGE_SIZE - buf_offset); | 1293 | PAGE_SIZE - (buf_offset % PAGE_SIZE)); |
| 1294 | bytes = min(bytes, working_bytes); | 1294 | bytes = min(bytes, working_bytes); |
| 1295 | 1295 | ||
| 1296 | kaddr = kmap_atomic(bvec.bv_page); | 1296 | kaddr = kmap_atomic(bvec.bv_page); |
| @@ -20,9 +20,13 @@ · 19 unmodified lines | |||
| 20 | #include <linux/refcount.h> | 20 | #include <linux/refcount.h> |
| 21 | #include "compression.h" | 21 | #include "compression.h" |
| 22 | 22 | ||
| 23 | /* workspace buffer size for s390 zlib hardware support */ | ||
| 24 | #define ZLIB_DFLTCC_BUF_SIZE (4 * PAGE_SIZE) | ||
| 25 | |||
| 23 | struct workspace { | 26 | struct workspace { |
| 24 | z_stream strm; | 27 | z_stream strm; |
| 25 | char *buf; | 28 | char *buf; |
| 29 | unsigned int buf_size; | ||
| 26 | struct list_head list; | 30 | struct list_head list; |
| 27 | int level; | 31 | int level; |
| 28 | }; | 32 | }; |
| @@ -61,7 +65,21 @@ struct list_head *zlib_alloc_workspace(unsigned int level) · 32 unmodified lines | |||
| 61 | zlib_inflate_workspacesize()); | 65 | zlib_inflate_workspacesize()); |
| 62 | workspace->strm.workspace = kvmalloc(workspacesize, GFP_KERNEL); | 66 | workspace->strm.workspace = kvmalloc(workspacesize, GFP_KERNEL); |
| 63 | workspace->level = level; | 67 | workspace->level = level; |
| 64 | workspace->buf = kmalloc(PAGE_SIZE, GFP_KERNEL); | 68 | workspace->buf = NULL; |
| 69 | /* | ||
| 70 | * In case of s390 zlib hardware support, allocate lager workspace | ||
| 71 | * buffer. If allocator fails, fall back to a single page buffer. | ||
| 72 | */ | ||
| 73 | if (zlib_deflate_dfltcc_enabled()) { | ||
| 74 | workspace->buf = kmalloc(ZLIB_DFLTCC_BUF_SIZE, | ||
| 75 | __GFP_NOMEMALLOC | __GFP_NORETRY | | ||
| 76 | __GFP_NOWARN | GFP_NOIO); | ||
| 77 | workspace->buf_size = ZLIB_DFLTCC_BUF_SIZE; | ||
| 78 | } | ||
| 79 | if (!workspace->buf) { | ||
| 80 | workspace->buf = kmalloc(PAGE_SIZE, GFP_KERNEL); | ||
| 81 | workspace->buf_size = PAGE_SIZE; | ||
| 82 | } | ||
| 65 | if (!workspace->strm.workspace || !workspace->buf) | 83 | if (!workspace->strm.workspace || !workspace->buf) |
| 66 | goto fail; | 84 | goto fail; |
| 67 | 85 | ||
| @@ -85,6 +103,7 @@ int zlib_compress_pages(struct list_head *ws, struct address_space *mapping, · 17 unmodified lines | |||
| 85 | struct page *in_page = NULL; | 103 | struct page *in_page = NULL; |
| 86 | struct page *out_page = NULL; | 104 | struct page *out_page = NULL; |
| 87 | unsigned long bytes_left; | 105 | unsigned long bytes_left; |
| 106 | unsigned int in_buf_pages; | ||
| 88 | unsigned long len = *total_out; | 107 | unsigned long len = *total_out; |
| 89 | unsigned long nr_dest_pages = *out_pages; | 108 | unsigned long nr_dest_pages = *out_pages; |
| 90 | const unsigned long max_out = nr_dest_pages * PAGE_SIZE; | 109 | const unsigned long max_out = nr_dest_pages * PAGE_SIZE; |
| @@ -102,9 +121,6 @@ int zlib_compress_pages(struct list_head *ws, struct address_space *mapping, · 11 unmodified lines | |||
| 102 | workspace->strm.total_in = 0; | 121 | workspace->strm.total_in = 0; |
| 103 | workspace->strm.total_out = 0; | 122 | workspace->strm.total_out = 0; |
| 104 | 123 | ||
| 105 | in_page = find_get_page(mapping, start >> PAGE_SHIFT); | ||
| 106 | data_in = kmap(in_page); | ||
| 107 | |||
| 108 | out_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM); | 124 | out_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM); |
| 109 | if (out_page == NULL) { | 125 | if (out_page == NULL) { |
| 110 | ret = -ENOMEM; | 126 | ret = -ENOMEM; |
| @@ -114,12 +130,51 @@ int zlib_compress_pages(struct list_head *ws, struct address_space *mapping, · 3 unmodified lines | |||
| 114 | pages[0] = out_page; | 130 | pages[0] = out_page; |
| 115 | nr_pages = 1; | 131 | nr_pages = 1; |
| 116 | 132 | ||
| 117 | workspace->strm.next_in = data_in; | 133 | workspace->strm.next_in = workspace->buf; |
| 134 | workspace->strm.avail_in = 0; | ||
| 118 | workspace->strm.next_out = cpage_out; | 135 | workspace->strm.next_out = cpage_out; |
| 119 | workspace->strm.avail_out = PAGE_SIZE; | 136 | workspace->strm.avail_out = PAGE_SIZE; |
| 120 | workspace->strm.avail_in = min(len, PAGE_SIZE); | ||
| 121 | 137 | ||
| 122 | while (workspace->strm.total_in < len) { | 138 | while (workspace->strm.total_in < len) { |
| 139 | /* | ||
| 140 | * Get next input pages and copy the contents to | ||
| 141 | * the workspace buffer if required. | ||
| 142 | */ | ||
| 143 | if (workspace->strm.avail_in == 0) { | ||
| 144 | bytes_left = len - workspace->strm.total_in; | ||
| 145 | in_buf_pages = min(DIV_ROUND_UP(bytes_left, PAGE_SIZE), | ||
| 146 | workspace->buf_size / PAGE_SIZE); | ||
| 147 | if (in_buf_pages > 1) { | ||
| 148 | int i; | ||
| 149 | |||
| 150 | for (i = 0; i < in_buf_pages; i++) { | ||
| 151 | if (in_page) { | ||
| 152 | kunmap(in_page); | ||
| 153 | put_page(in_page); | ||
| 154 | } | ||
| 155 | in_page = find_get_page(mapping, | ||
| 156 | start >> PAGE_SHIFT); | ||
| 157 | data_in = kmap(in_page); | ||
| 158 | memcpy(workspace->buf + i * PAGE_SIZE, | ||
| 159 | data_in, PAGE_SIZE); | ||
| 160 | start += PAGE_SIZE; | ||
| 161 | } | ||
| 162 | workspace->strm.next_in = workspace->buf; | ||
| 163 | } else { | ||
| 164 | if (in_page) { | ||
| 165 | kunmap(in_page); | ||
| 166 | put_page(in_page); | ||
| 167 | } | ||
| 168 | in_page = find_get_page(mapping, | ||
| 169 | start >> PAGE_SHIFT); | ||
| 170 | data_in = kmap(in_page); | ||
| 171 | start += PAGE_SIZE; | ||
| 172 | workspace->strm.next_in = data_in; | ||
| 173 | } | ||
| 174 | workspace->strm.avail_in = min(bytes_left, | ||
| 175 | (unsigned long) workspace->buf_size); | ||
| 176 | } | ||
| 177 | |||
| 123 | ret = zlib_deflate(&workspace->strm, Z_SYNC_FLUSH); | 178 | ret = zlib_deflate(&workspace->strm, Z_SYNC_FLUSH); |
| 124 | if (ret != Z_OK) { | 179 | if (ret != Z_OK) { |
| 125 | pr_debug("BTRFS: deflate in loop returned %d\n", | 180 | pr_debug("BTRFS: deflate in loop returned %d\n", |
| @@ -161,33 +216,43 @@ int zlib_compress_pages(struct list_head *ws, struct address_space *mapping, · 35 unmodified lines | |||
| 161 | /* we're all done */ | 216 | /* we're all done */ |
| 162 | if (workspace->strm.total_in >= len) | 217 | if (workspace->strm.total_in >= len) |
| 163 | break; | 218 | break; |
| 164 | 219 | if (workspace->strm.total_out > max_out) | |
| 165 | /* we've read in a full page, get a new one */ | 220 | break; |
| 166 | if (workspace->strm.avail_in == 0) { | ||
| 167 | if (workspace->strm.total_out > max_out) | ||
| 168 | break; | ||
| 169 | |||
| 170 | bytes_left = len - workspace->strm.total_in; | ||
| 171 | kunmap(in_page); | ||
| 172 | put_page(in_page); | ||
| 173 | |||
| 174 | start += PAGE_SIZE; | ||
| 175 | in_page = find_get_page(mapping, | ||
| 176 | start >> PAGE_SHIFT); | ||
| 177 | data_in = kmap(in_page); | ||
| 178 | workspace->strm.avail_in = min(bytes_left, | ||
| 179 | PAGE_SIZE); | ||
| 180 | workspace->strm.next_in = data_in; | ||
| 181 | } | ||
| 182 | } | 221 | } |
| 183 | workspace->strm.avail_in = 0; | 222 | workspace->strm.avail_in = 0; |
| 184 | ret = zlib_deflate(&workspace->strm, Z_FINISH); | 223 | /* |
| 185 | zlib_deflateEnd(&workspace->strm); | 224 | * Call deflate with Z_FINISH flush parameter providing more output |
| 186 | 225 | * space but no more input data, until it returns with Z_STREAM_END. | |
| 187 | if (ret != Z_STREAM_END) { | 226 | */ |
| 188 | ret = -EIO; | 227 | while (ret != Z_STREAM_END) { |
| 189 | goto out; | 228 | ret = zlib_deflate(&workspace->strm, Z_FINISH); |
| 229 | if (ret == Z_STREAM_END) | ||
| 230 | break; | ||
| 231 | if (ret != Z_OK && ret != Z_BUF_ERROR) { | ||
| 232 | zlib_deflateEnd(&workspace->strm); | ||
| 233 | ret = -EIO; | ||
| 234 | goto out; | ||
| 235 | } else if (workspace->strm.avail_out == 0) { | ||
| 236 | /* get another page for the stream end */ | ||
| 237 | kunmap(out_page); | ||
| 238 | if (nr_pages == nr_dest_pages) { | ||
| 239 | out_page = NULL; | ||
| 240 | ret = -E2BIG; | ||
| 241 | goto out; | ||
| 242 | } | ||
| 243 | out_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM); | ||
| 244 | if (out_page == NULL) { | ||
| 245 | ret = -ENOMEM; | ||
| 246 | goto out; | ||
| 247 | } | ||
| 248 | cpage_out = kmap(out_page); | ||
| 249 | pages[nr_pages] = out_page; | ||
| 250 | nr_pages++; | ||
| 251 | workspace->strm.avail_out = PAGE_SIZE; | ||
| 252 | workspace->strm.next_out = cpage_out; | ||
| 253 | } | ||
| 190 | } | 254 | } |
| 255 | zlib_deflateEnd(&workspace->strm); | ||
| 191 | 256 | ||
| 192 | if (workspace->strm.total_out >= workspace->strm.total_in) { | 257 | if (workspace->strm.total_out >= workspace->strm.total_in) { |
| 193 | ret = -E2BIG; | 258 | ret = -E2BIG; |
| @@ -231,7 +296,7 @@ int zlib_decompress_bio(struct list_head *ws, struct compressed_bio *cb) · 37 unmodified lines | |||
| 231 | 296 | ||
| 232 | workspace->strm.total_out = 0; | 297 | workspace->strm.total_out = 0; |
| 233 | workspace->strm.next_out = workspace->buf; | 298 | workspace->strm.next_out = workspace->buf; |
| 234 | workspace->strm.avail_out = PAGE_SIZE; | 299 | workspace->strm.avail_out = workspace->buf_size; |
| 235 | 300 | ||
| 236 | /* If it's deflate, and it's got no preset dictionary, then | 301 | /* If it's deflate, and it's got no preset dictionary, then |
| 237 | we can tell zlib to skip the adler32 check. */ | 302 | we can tell zlib to skip the adler32 check. */ |
| @@ -270,7 +335,7 @@ int zlib_decompress_bio(struct list_head *ws, struct compressed_bio *cb) · 32 unmodified lines | |||
| 270 | } | 335 | } |
| 271 | 336 | ||
| 272 | workspace->strm.next_out = workspace->buf; | 337 | workspace->strm.next_out = workspace->buf; |
| 273 | workspace->strm.avail_out = PAGE_SIZE; | 338 | workspace->strm.avail_out = workspace->buf_size; |
| 274 | 339 | ||
| 275 | if (workspace->strm.avail_in == 0) { | 340 | if (workspace->strm.avail_in == 0) { |
| 276 | unsigned long tmp; | 341 | unsigned long tmp; |
| @@ -320,7 +385,7 @@ int zlib_decompress(struct list_head *ws, unsigned char *data_in, · 43 unmodified lines | |||
| 320 | workspace->strm.total_in = 0; | 385 | workspace->strm.total_in = 0; |
| 321 | 386 | ||
| 322 | workspace->strm.next_out = workspace->buf; | 387 | workspace->strm.next_out = workspace->buf; |
| 323 | workspace->strm.avail_out = PAGE_SIZE; | 388 | workspace->strm.avail_out = workspace->buf_size; |
| 324 | workspace->strm.total_out = 0; | 389 | workspace->strm.total_out = 0; |
| 325 | /* If it's deflate, and it's got no preset dictionary, then | 390 | /* If it's deflate, and it's got no preset dictionary, then |
| 326 | we can tell zlib to skip the adler32 check. */ | 391 | we can tell zlib to skip the adler32 check. */ |
| @@ -364,7 +429,7 @@ int zlib_decompress(struct list_head *ws, unsigned char *data_in, · 37 unmodified lines | |||
| 364 | buf_offset = 0; | 429 | buf_offset = 0; |
| 365 | 430 | ||
| 366 | bytes = min(PAGE_SIZE - pg_offset, | 431 | bytes = min(PAGE_SIZE - pg_offset, |
| 367 | PAGE_SIZE - buf_offset); | 432 | PAGE_SIZE - (buf_offset % PAGE_SIZE)); |
| 368 | bytes = min(bytes, bytes_left); | 433 | bytes = min(bytes, bytes_left); |
| 369 | 434 | ||
| 370 | kaddr = kmap_atomic(dest_page); | 435 | kaddr = kmap_atomic(dest_page); |
| @@ -375,7 +440,7 @@ int zlib_decompress(struct list_head *ws, unsigned char *data_in, · 4 unmodified lines | |||
| 375 | bytes_left -= bytes; | 440 | bytes_left -= bytes; |
| 376 | next: | 441 | next: |
| 377 | workspace->strm.next_out = workspace->buf; | 442 | workspace->strm.next_out = workspace->buf; |
| 378 | workspace->strm.avail_out = PAGE_SIZE; | 443 | workspace->strm.avail_out = workspace->buf_size; |
| 379 | } | 444 | } |
| 380 | 445 | ||
| 381 | if (ret != Z_STREAM_END && bytes_left != 0) | 446 | if (ret != Z_STREAM_END && bytes_left != 0) |
| @@ -760,6 +760,11 @@ int setup_arg_pages(struct linux_binprm *bprm, · 759 unmodified lines | |||
| 760 | goto out_unlock; | 760 | goto out_unlock; |
| 761 | BUG_ON(prev != vma); | 761 | BUG_ON(prev != vma); |
| 762 | 762 | ||
| 763 | if (unlikely(vm_flags & VM_EXEC)) { | ||
| 764 | pr_warn_once("process '%pD4' started with executable stack\n", | ||
| 765 | bprm->file); | ||
| 766 | } | ||
| 767 | |||
| 763 | /* Move stack pages down in memory. */ | 768 | /* Move stack pages down in memory. */ |
| 764 | if (stack_shift) { | 769 | if (stack_shift) { |
| 765 | ret = shift_arg_pages(vma, stack_shift); | 770 | ret = shift_arg_pages(vma, stack_shift); |
| @@ -2063,7 +2063,7 @@ void wb_workfn(struct work_struct *work) · 2062 unmodified lines | |||
| 2063 | struct bdi_writeback, dwork); | 2063 | struct bdi_writeback, dwork); |
| 2064 | long pages_written; | 2064 | long pages_written; |
| 2065 | 2065 | ||
| 2066 | set_worker_desc("flush-%s", dev_name(wb->bdi->dev)); | 2066 | set_worker_desc("flush-%s", bdi_dev_name(wb->bdi)); |
| 2067 | current->flags |= PF_SWAPWRITE; | 2067 | current->flags |= PF_SWAPWRITE; |
| 2068 | 2068 | ||
| 2069 | if (likely(!current_is_workqueue_rescuer() || | 2069 | if (likely(!current_is_workqueue_rescuer() || |
| @@ -6005,7 +6005,7 @@ static int io_sqe_buffer_unregister(struct io_ring_ctx *ctx) · 6004 unmodified lines | |||
| 6005 | struct io_mapped_ubuf *imu = &ctx->user_bufs[i]; | 6005 | struct io_mapped_ubuf *imu = &ctx->user_bufs[i]; |
| 6006 | 6006 | ||
| 6007 | for (j = 0; j < imu->nr_bvecs; j++) | 6007 | for (j = 0; j < imu->nr_bvecs; j++) |
| 6008 | put_user_page(imu->bvec[j].bv_page); | 6008 | unpin_user_page(imu->bvec[j].bv_page); |
| 6009 | 6009 | ||
| 6010 | if (ctx->account_mem) | 6010 | if (ctx->account_mem) |
| 6011 | io_unaccount_mem(ctx->user, imu->nr_bvecs); | 6011 | io_unaccount_mem(ctx->user, imu->nr_bvecs); |
| @@ -6126,7 +6126,7 @@ static int io_sqe_buffer_register(struct io_ring_ctx *ctx, void __user *arg, · 114 unmodified lines | |||
| 6126 | 6126 | ||
| 6127 | ret = 0; | 6127 | ret = 0; |
| 6128 | down_read(¤t->mm->mmap_sem); | 6128 | down_read(¤t->mm->mmap_sem); |
| 6129 | pret = get_user_pages(ubuf, nr_pages, | 6129 | pret = pin_user_pages(ubuf, nr_pages, |
| 6130 | FOLL_WRITE | FOLL_LONGTERM, | 6130 | FOLL_WRITE | FOLL_LONGTERM, |
| 6131 | pages, vmas); | 6131 | pages, vmas); |
| 6132 | if (pret == nr_pages) { | 6132 | if (pret == nr_pages) { |
| @@ -6150,7 +6150,7 @@ static int io_sqe_buffer_register(struct io_ring_ctx *ctx, void __user *arg, · 17 unmodified lines | |||
| 6150 | * release any pages we did get | 6150 | * release any pages we did get |
| 6151 | */ | 6151 | */ |
| 6152 | if (pret > 0) | 6152 | if (pret > 0) |
| 6153 | put_user_pages(pages, pret); | 6153 | unpin_user_pages(pages, pret); |
| 6154 | if (ctx->account_mem) | 6154 | if (ctx->account_mem) |
| 6155 | io_unaccount_mem(ctx->user, nr_pages); | 6155 | io_unaccount_mem(ctx->user, nr_pages); |
| 6156 | kvfree(imu->bvec); | 6156 | kvfree(imu->bvec); |
| @@ -73,7 +73,7 @@ static void o2quo_fence_self(void) · 72 unmodified lines | |||
| 73 | "system by restarting ***\n"); | 73 | "system by restarting ***\n"); |
| 74 | emergency_restart(); | 74 | emergency_restart(); |
| 75 | break; | 75 | break; |
| 76 | }; | 76 | } |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | /* Indicate that a timeout occurred on a heartbeat region write. The | 79 | /* Indicate that a timeout occurred on a heartbeat region write. The |
| @@ -1,6 +1,4 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0-only | 1 | # SPDX-License-Identifier: GPL-2.0-only |
| 2 | ccflags-y := -I $(srctree)/$(src)/.. | ||
| 3 | |||
| 4 | obj-$(CONFIG_OCFS2_FS_O2CB) += ocfs2_dlm.o | 2 | obj-$(CONFIG_OCFS2_FS_O2CB) += ocfs2_dlm.o |
| 5 | 3 | ||
| 6 | ocfs2_dlm-objs := dlmdomain.o dlmdebug.o dlmthread.o dlmrecovery.o \ | 4 | ocfs2_dlm-objs := dlmdomain.o dlmdebug.o dlmthread.o dlmrecovery.o \ |
| @@ -23,15 +23,15 @@ · 22 unmodified lines | |||
| 23 | #include <linux/spinlock.h> | 23 | #include <linux/spinlock.h> |
| 24 | 24 | ||
| 25 | 25 | ||
| 26 | #include "cluster/heartbeat.h" | 26 | #include "../cluster/heartbeat.h" |
| 27 | #include "cluster/nodemanager.h" | 27 | #include "../cluster/nodemanager.h" |
| 28 | #include "cluster/tcp.h" | 28 | #include "../cluster/tcp.h" |
| 29 | 29 | ||
| 30 | #include "dlmapi.h" | 30 | #include "dlmapi.h" |
| 31 | #include "dlmcommon.h" | 31 | #include "dlmcommon.h" |
| 32 | 32 | ||
| 33 | #define MLOG_MASK_PREFIX ML_DLM | 33 | #define MLOG_MASK_PREFIX ML_DLM |
| 34 | #include "cluster/masklog.h" | 34 | #include "../cluster/masklog.h" |
| 35 | 35 | ||
| 36 | static void dlm_update_lvb(struct dlm_ctxt *dlm, struct dlm_lock_resource *res, | 36 | static void dlm_update_lvb(struct dlm_ctxt *dlm, struct dlm_lock_resource *res, |
| 37 | struct dlm_lock *lock); | 37 | struct dlm_lock *lock); |
| @@ -688,10 +688,6 @@ struct dlm_begin_reco · 687 unmodified lines | |||
| 688 | __be32 pad2; | 688 | __be32 pad2; |
| 689 | }; | 689 | }; |
| 690 | 690 | ||
| 691 | |||
| 692 | #define BITS_PER_BYTE 8 | ||
| 693 | #define BITS_TO_BYTES(bits) (((bits)+BITS_PER_BYTE-1)/BITS_PER_BYTE) | ||
| 694 | |||
| 695 | struct dlm_query_join_request | 691 | struct dlm_query_join_request |
| 696 | { | 692 | { |
| 697 | u8 node_idx; | 693 | u8 node_idx; |
| @@ -23,9 +23,9 @@ · 22 unmodified lines | |||
| 23 | #include <linux/spinlock.h> | 23 | #include <linux/spinlock.h> |
| 24 | 24 | ||
| 25 | 25 | ||
| 26 | #include "cluster/heartbeat.h" | 26 | #include "../cluster/heartbeat.h" |
| 27 | #include "cluster/nodemanager.h" | 27 | #include "../cluster/nodemanager.h" |
| 28 | #include "cluster/tcp.h" | 28 | #include "../cluster/tcp.h" |
| 29 | 29 | ||
| 30 | #include "dlmapi.h" | 30 | #include "dlmapi.h" |
| 31 | #include "dlmcommon.h" | 31 | #include "dlmcommon.h" |
| @@ -33,7 +33,7 @@ · 1 unmodified line | |||
| 33 | #include "dlmconvert.h" | 33 | #include "dlmconvert.h" |
| 34 | 34 | ||
| 35 | #define MLOG_MASK_PREFIX ML_DLM | 35 | #define MLOG_MASK_PREFIX ML_DLM |
| 36 | #include "cluster/masklog.h" | 36 | #include "../cluster/masklog.h" |
| 37 | 37 | ||
| 38 | /* NOTE: __dlmconvert_master is the only function in here that | 38 | /* NOTE: __dlmconvert_master is the only function in here that |
| 39 | * needs a spinlock held on entry (res->spinlock) and it is the | 39 | * needs a spinlock held on entry (res->spinlock) and it is the |
| @@ -17,9 +17,9 @@ · 16 unmodified lines | |||
| 17 | #include <linux/debugfs.h> | 17 | #include <linux/debugfs.h> |
| 18 | #include <linux/export.h> | 18 | #include <linux/export.h> |
| 19 | 19 | ||
| 20 | #include "cluster/heartbeat.h" | 20 | #include "../cluster/heartbeat.h" |
| 21 | #include "cluster/nodemanager.h" | 21 | #include "../cluster/nodemanager.h" |
| 22 | #include "cluster/tcp.h" | 22 | #include "../cluster/tcp.h" |
| 23 | 23 | ||
| 24 | #include "dlmapi.h" | 24 | #include "dlmapi.h" |
| 25 | #include "dlmcommon.h" | 25 | #include "dlmcommon.h" |
| @@ -27,7 +27,7 @@ · 1 unmodified line | |||
| 27 | #include "dlmdebug.h" | 27 | #include "dlmdebug.h" |
| 28 | 28 | ||
| 29 | #define MLOG_MASK_PREFIX ML_DLM | 29 | #define MLOG_MASK_PREFIX ML_DLM |
| 30 | #include "cluster/masklog.h" | 30 | #include "../cluster/masklog.h" |
| 31 | 31 | ||
| 32 | static int stringify_lockname(const char *lockname, int locklen, char *buf, | 32 | static int stringify_lockname(const char *lockname, int locklen, char *buf, |
| 33 | int len); | 33 | int len); |
| @@ -20,9 +20,9 @@ · 19 unmodified lines | |||
| 20 | #include <linux/debugfs.h> | 20 | #include <linux/debugfs.h> |
| 21 | #include <linux/sched/signal.h> | 21 | #include <linux/sched/signal.h> |
| 22 | 22 | ||
| 23 | #include "cluster/heartbeat.h" | 23 | #include "../cluster/heartbeat.h" |
| 24 | #include "cluster/nodemanager.h" | 24 | #include "../cluster/nodemanager.h" |
| 25 | #include "cluster/tcp.h" | 25 | #include "../cluster/tcp.h" |
| 26 | 26 | ||
| 27 | #include "dlmapi.h" | 27 | #include "dlmapi.h" |
| 28 | #include "dlmcommon.h" | 28 | #include "dlmcommon.h" |
| @@ -30,7 +30,7 @@ · 1 unmodified line | |||
| 30 | #include "dlmdebug.h" | 30 | #include "dlmdebug.h" |
| 31 | 31 | ||
| 32 | #define MLOG_MASK_PREFIX (ML_DLM|ML_DLM_DOMAIN) | 32 | #define MLOG_MASK_PREFIX (ML_DLM|ML_DLM_DOMAIN) |
| 33 | #include "cluster/masklog.h" | 33 | #include "../cluster/masklog.h" |
| 34 | 34 | ||
| 35 | /* | 35 | /* |
| 36 | * ocfs2 node maps are array of long int, which limits to send them freely | 36 | * ocfs2 node maps are array of long int, which limits to send them freely |
| @@ -25,9 +25,9 @@ · 24 unmodified lines | |||
| 25 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
| 26 | 26 | ||
| 27 | 27 | ||
| 28 | #include "cluster/heartbeat.h" | 28 | #include "../cluster/heartbeat.h" |
| 29 | #include "cluster/nodemanager.h" | 29 | #include "../cluster/nodemanager.h" |
| 30 | #include "cluster/tcp.h" | 30 | #include "../cluster/tcp.h" |
| 31 | 31 | ||
| 32 | #include "dlmapi.h" | 32 | #include "dlmapi.h" |
| 33 | #include "dlmcommon.h" | 33 | #include "dlmcommon.h" |
| @@ -35,7 +35,7 @@ · 1 unmodified line | |||
| 35 | #include "dlmconvert.h" | 35 | #include "dlmconvert.h" |
| 36 | 36 | ||
| 37 | #define MLOG_MASK_PREFIX ML_DLM | 37 | #define MLOG_MASK_PREFIX ML_DLM |
| 38 | #include "cluster/masklog.h" | 38 | #include "../cluster/masklog.h" |
| 39 | 39 | ||
| 40 | static struct kmem_cache *dlm_lock_cache; | 40 | static struct kmem_cache *dlm_lock_cache; |
| 41 | 41 | ||
| @@ -25,9 +25,9 @@ · 24 unmodified lines | |||
| 25 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
| 26 | 26 | ||
| 27 | 27 | ||
| 28 | #include "cluster/heartbeat.h" | 28 | #include "../cluster/heartbeat.h" |
| 29 | #include "cluster/nodemanager.h" | 29 | #include "../cluster/nodemanager.h" |
| 30 | #include "cluster/tcp.h" | 30 | #include "../cluster/tcp.h" |
| 31 | 31 | ||
| 32 | #include "dlmapi.h" | 32 | #include "dlmapi.h" |
| 33 | #include "dlmcommon.h" | 33 | #include "dlmcommon.h" |
| @@ -35,7 +35,7 @@ · 1 unmodified line | |||
| 35 | #include "dlmdebug.h" | 35 | #include "dlmdebug.h" |
| 36 | 36 | ||
| 37 | #define MLOG_MASK_PREFIX (ML_DLM|ML_DLM_MASTER) | 37 | #define MLOG_MASK_PREFIX (ML_DLM|ML_DLM_MASTER) |
| 38 | #include "cluster/masklog.h" | 38 | #include "../cluster/masklog.h" |
| 39 | 39 | ||
| 40 | static void dlm_mle_node_down(struct dlm_ctxt *dlm, | 40 | static void dlm_mle_node_down(struct dlm_ctxt *dlm, |
| 41 | struct dlm_master_list_entry *mle, | 41 | struct dlm_master_list_entry *mle, |
| @@ -2554,8 +2554,6 @@ static int dlm_migrate_lockres(struct dlm_ctxt *dlm, · 2512 unmodified lines | |||
| 2554 | if (!dlm_grab(dlm)) | 2554 | if (!dlm_grab(dlm)) |
| 2555 | return -EINVAL; | 2555 | return -EINVAL; |
| 2556 | 2556 | ||
| 2557 | BUG_ON(target == O2NM_MAX_NODES); | ||
| 2558 | |||
| 2559 | name = res->lockname.name; | 2557 | name = res->lockname.name; |
| 2560 | namelen = res->lockname.len; | 2558 | namelen = res->lockname.len; |
| 2561 | 2559 | ||
| @@ -26,16 +26,16 @@ · 25 unmodified lines | |||
| 26 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
| 27 | 27 | ||
| 28 | 28 | ||
| 29 | #include "cluster/heartbeat.h" | 29 | #include "../cluster/heartbeat.h" |
| 30 | #include "cluster/nodemanager.h" | 30 | #include "../cluster/nodemanager.h" |
| 31 | #include "cluster/tcp.h" | 31 | #include "../cluster/tcp.h" |
| 32 | 32 | ||
| 33 | #include "dlmapi.h" | 33 | #include "dlmapi.h" |
| 34 | #include "dlmcommon.h" | 34 | #include "dlmcommon.h" |
| 35 | #include "dlmdomain.h" | 35 | #include "dlmdomain.h" |
| 36 | 36 | ||
| 37 | #define MLOG_MASK_PREFIX (ML_DLM|ML_DLM_RECOVERY) | 37 | #define MLOG_MASK_PREFIX (ML_DLM|ML_DLM_RECOVERY) |
| 38 | #include "cluster/masklog.h" | 38 | #include "../cluster/masklog.h" |
| 39 | 39 | ||
| 40 | static void dlm_do_local_recovery_cleanup(struct dlm_ctxt *dlm, u8 dead_node); | 40 | static void dlm_do_local_recovery_cleanup(struct dlm_ctxt *dlm, u8 dead_node); |
| 41 | 41 | ||
| @@ -1668,7 +1668,7 @@ static int dlm_lockres_master_requery(struct dlm_ctxt *dlm, · 1626 unmodified lines | |||
| 1668 | int dlm_do_master_requery(struct dlm_ctxt *dlm, struct dlm_lock_resource *res, | 1668 | int dlm_do_master_requery(struct dlm_ctxt *dlm, struct dlm_lock_resource *res, |
| 1669 | u8 nodenum, u8 *real_master) | 1669 | u8 nodenum, u8 *real_master) |
| 1670 | { | 1670 | { |
| 1671 | int ret = -EINVAL; | 1671 | int ret; |
| 1672 | struct dlm_master_requery req; | 1672 | struct dlm_master_requery req; |
| 1673 | int status = DLM_LOCK_RES_OWNER_UNKNOWN; | 1673 | int status = DLM_LOCK_RES_OWNER_UNKNOWN; |
| 1674 | 1674 | ||
| @@ -25,16 +25,16 @@ · 24 unmodified lines | |||
| 25 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
| 26 | 26 | ||
| 27 | 27 | ||
| 28 | #include "cluster/heartbeat.h" | 28 | #include "../cluster/heartbeat.h" |
| 29 | #include "cluster/nodemanager.h" | 29 | #include "../cluster/nodemanager.h" |
| 30 | #include "cluster/tcp.h" | 30 | #include "../cluster/tcp.h" |
| 31 | 31 | ||
| 32 | #include "dlmapi.h" | 32 | #include "dlmapi.h" |
| 33 | #include "dlmcommon.h" | 33 | #include "dlmcommon.h" |
| 34 | #include "dlmdomain.h" | 34 | #include "dlmdomain.h" |
| 35 | 35 | ||
| 36 | #define MLOG_MASK_PREFIX (ML_DLM|ML_DLM_THREAD) | 36 | #define MLOG_MASK_PREFIX (ML_DLM|ML_DLM_THREAD) |
| 37 | #include "cluster/masklog.h" | 37 | #include "../cluster/masklog.h" |
| 38 | 38 | ||
| 39 | static int dlm_thread(void *data); | 39 | static int dlm_thread(void *data); |
| 40 | static void dlm_flush_asts(struct dlm_ctxt *dlm); | 40 | static void dlm_flush_asts(struct dlm_ctxt *dlm); |
| @@ -23,15 +23,15 @@ · 22 unmodified lines | |||
| 23 | #include <linux/spinlock.h> | 23 | #include <linux/spinlock.h> |
| 24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
| 25 | 25 | ||
| 26 | #include "cluster/heartbeat.h" | 26 | #include "../cluster/heartbeat.h" |
| 27 | #include "cluster/nodemanager.h" | 27 | #include "../cluster/nodemanager.h" |
| 28 | #include "cluster/tcp.h" | 28 | #include "../cluster/tcp.h" |
| 29 | 29 | ||
| 30 | #include "dlmapi.h" | 30 | #include "dlmapi.h" |
| 31 | #include "dlmcommon.h" | 31 | #include "dlmcommon.h" |
| 32 | 32 | ||
| 33 | #define MLOG_MASK_PREFIX ML_DLM | 33 | #define MLOG_MASK_PREFIX ML_DLM |
| 34 | #include "cluster/masklog.h" | 34 | #include "../cluster/masklog.h" |
| 35 | 35 | ||
| 36 | #define DLM_UNLOCK_FREE_LOCK 0x00000001 | 36 | #define DLM_UNLOCK_FREE_LOCK 0x00000001 |
| 37 | #define DLM_UNLOCK_CALL_AST 0x00000002 | 37 | #define DLM_UNLOCK_CALL_AST 0x00000002 |
| @@ -1,6 +1,4 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0-only | 1 | # SPDX-License-Identifier: GPL-2.0-only |
| 2 | ccflags-y := -I $(srctree)/$(src)/.. | ||
| 3 | |||
| 4 | obj-$(CONFIG_OCFS2_FS) += ocfs2_dlmfs.o | 2 | obj-$(CONFIG_OCFS2_FS) += ocfs2_dlmfs.o |
| 5 | 3 | ||
| 6 | ocfs2_dlmfs-objs := userdlm.o dlmfs.o | 4 | ocfs2_dlmfs-objs := userdlm.o dlmfs.o |
| @@ -33,11 +33,11 @@ · 32 unmodified lines | |||
| 33 | 33 | ||
| 34 | #include <linux/uaccess.h> | 34 | #include <linux/uaccess.h> |
| 35 | 35 | ||
| 36 | #include "stackglue.h" | 36 | #include "../stackglue.h" |
| 37 | #include "userdlm.h" | 37 | #include "userdlm.h" |
| 38 | 38 | ||
| 39 | #define MLOG_MASK_PREFIX ML_DLMFS | 39 | #define MLOG_MASK_PREFIX ML_DLMFS |
| 40 | #include "cluster/masklog.h" | 40 | #include "../cluster/masklog.h" |
| 41 | 41 | ||
| 42 | 42 | ||
| 43 | static const struct super_operations dlmfs_ops; | 43 | static const struct super_operations dlmfs_ops; |
| @@ -21,12 +21,12 @@ · 20 unmodified lines | |||
| 21 | #include <linux/types.h> | 21 | #include <linux/types.h> |
| 22 | #include <linux/crc32.h> | 22 | #include <linux/crc32.h> |
| 23 | 23 | ||
| 24 | #include "ocfs2_lockingver.h" | 24 | #include "../ocfs2_lockingver.h" |
| 25 | #include "stackglue.h" | 25 | #include "../stackglue.h" |
| 26 | #include "userdlm.h" | 26 | #include "userdlm.h" |
| 27 | 27 | ||
| 28 | #define MLOG_MASK_PREFIX ML_DLMFS | 28 | #define MLOG_MASK_PREFIX ML_DLMFS |
| 29 | #include "cluster/masklog.h" | 29 | #include "../cluster/masklog.h" |
| 30 | 30 | ||
| 31 | 31 | ||
| 32 | static inline struct user_lock_res *user_lksb_to_lock_res(struct ocfs2_dlm_lksb *lksb) | 32 | static inline struct user_lock_res *user_lksb_to_lock_res(struct ocfs2_dlm_lksb *lksb) |
| @@ -570,7 +570,7 @@ void ocfs2_inode_lock_res_init(struct ocfs2_lock_res *res, · 569 unmodified lines | |||
| 570 | mlog_bug_on_msg(1, "type: %d\n", type); | 570 | mlog_bug_on_msg(1, "type: %d\n", type); |
| 571 | ops = NULL; /* thanks, gcc */ | 571 | ops = NULL; /* thanks, gcc */ |
| 572 | break; | 572 | break; |
| 573 | }; | 573 | } |
| 574 | 574 | ||
| 575 | ocfs2_build_lock_name(type, OCFS2_I(inode)->ip_blkno, | 575 | ocfs2_build_lock_name(type, OCFS2_I(inode)->ip_blkno, |
| 576 | generation, res->l_name); | 576 | generation, res->l_name); |
| @@ -597,9 +597,11 @@ static inline void ocfs2_update_inode_fsync_trans(handle_t *handle, · 596 unmodified lines | |||
| 597 | { | 597 | { |
| 598 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | 598 | struct ocfs2_inode_info *oi = OCFS2_I(inode); |
| 599 | 599 | ||
| 600 | oi->i_sync_tid = handle->h_transaction->t_tid; | 600 | if (!is_handle_aborted(handle)) { |
| 601 | if (datasync) | 601 | oi->i_sync_tid = handle->h_transaction->t_tid; |
| 602 | oi->i_datasync_tid = handle->h_transaction->t_tid; | 602 | if (datasync) |
| 603 | oi->i_datasync_tid = handle->h_transaction->t_tid; | ||
| 604 | } | ||
| 603 | } | 605 | } |
| 604 | 606 | ||
| 605 | #endif /* OCFS2_JOURNAL_H */ | 607 | #endif /* OCFS2_JOURNAL_H */ |
| @@ -586,8 +586,7 @@ static int __ocfs2_mknod_locked(struct inode *dir, · 585 unmodified lines | |||
| 586 | mlog_errno(status); | 586 | mlog_errno(status); |
| 587 | } | 587 | } |
| 588 | 588 | ||
| 589 | oi->i_sync_tid = handle->h_transaction->t_tid; | 589 | ocfs2_update_inode_fsync_trans(handle, inode, 1); |
| 590 | oi->i_datasync_tid = handle->h_transaction->t_tid; | ||
| 591 | 590 | ||
| 592 | leave: | 591 | leave: |
| 593 | if (status < 0) { | 592 | if (status < 0) { |
| @@ -2240,7 +2240,8 @@ error_out: · 2239 unmodified lines | |||
| 2240 | /* also releases the path */ | 2240 | /* also releases the path */ |
| 2241 | unfix_nodes(&s_ins_balance); | 2241 | unfix_nodes(&s_ins_balance); |
| 2242 | #ifdef REISERQUOTA_DEBUG | 2242 | #ifdef REISERQUOTA_DEBUG |
| 2243 | reiserfs_debug(th->t_super, REISERFS_DEBUG_CODE, | 2243 | if (inode) |
| 2244 | reiserfs_debug(th->t_super, REISERFS_DEBUG_CODE, | ||
| 2244 | "reiserquota insert_item(): freeing %u id=%u type=%c", | 2245 | "reiserquota insert_item(): freeing %u id=%u type=%c", |
| 2245 | quota_bytes, inode->i_uid, head2type(ih)); | 2246 | quota_bytes, inode->i_uid, head2type(ih)); |
| 2246 | #endif | 2247 | #endif |
| @@ -13,6 +13,7 @@ · 12 unmodified lines | |||
| 13 | #include <linux/fs.h> | 13 | #include <linux/fs.h> |
| 14 | #include <linux/sched.h> | 14 | #include <linux/sched.h> |
| 15 | #include <linux/blkdev.h> | 15 | #include <linux/blkdev.h> |
| 16 | #include <linux/device.h> | ||
| 16 | #include <linux/writeback.h> | 17 | #include <linux/writeback.h> |
| 17 | #include <linux/blk-cgroup.h> | 18 | #include <linux/blk-cgroup.h> |
| 18 | #include <linux/backing-dev-defs.h> | 19 | #include <linux/backing-dev-defs.h> |
| @@ -504,4 +505,13 @@ static inline int bdi_rw_congested(struct backing_dev_info *bdi) · 485 unmodified lines | |||
| 504 | (1 << WB_async_congested)); | 505 | (1 << WB_async_congested)); |
| 505 | } | 506 | } |
| 506 | 507 | ||
| 508 | extern const char *bdi_unknown_name; | ||
| 509 | |||
| 510 | static inline const char *bdi_dev_name(struct backing_dev_info *bdi) | ||
| 511 | { | ||
| 512 | if (!bdi || !bdi->dev) | ||
| 513 | return bdi_unknown_name; | ||
| 514 | return dev_name(bdi->dev); | ||
| 515 | } | ||
| 516 | |||
| 507 | #endif /* _LINUX_BACKING_DEV_H */ | 517 | #endif /* _LINUX_BACKING_DEV_H */ |
| @@ -13,6 +13,7 @@ · 12 unmodified lines | |||
| 13 | 13 | ||
| 14 | #define BITS_PER_TYPE(type) (sizeof(type) * BITS_PER_BYTE) | 14 | #define BITS_PER_TYPE(type) (sizeof(type) * BITS_PER_BYTE) |
| 15 | #define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_TYPE(long)) | 15 | #define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_TYPE(long)) |
| 16 | #define BITS_TO_BYTES(nr) DIV_ROUND_UP(nr, BITS_PER_TYPE(char)) | ||
| 16 | 17 | ||
| 17 | extern unsigned int __sw_hweight8(unsigned int w); | 18 | extern unsigned int __sw_hweight8(unsigned int w); |
| 18 | extern unsigned int __sw_hweight16(unsigned int w); | 19 | extern unsigned int __sw_hweight16(unsigned int w); |
| @@ -2737,7 +2737,6 @@ static inline int filemap_fdatawait(struct address_space *mapping) · 2736 unmodified lines | |||
| 2737 | 2737 | ||
| 2738 | extern bool filemap_range_has_page(struct address_space *, loff_t lstart, | 2738 | extern bool filemap_range_has_page(struct address_space *, loff_t lstart, |
| 2739 | loff_t lend); | 2739 | loff_t lend); |
| 2740 | extern int filemap_write_and_wait(struct address_space *mapping); | ||
| 2741 | extern int filemap_write_and_wait_range(struct address_space *mapping, | 2740 | extern int filemap_write_and_wait_range(struct address_space *mapping, |
| 2742 | loff_t lstart, loff_t lend); | 2741 | loff_t lstart, loff_t lend); |
| 2743 | extern int __filemap_fdatawrite_range(struct address_space *mapping, | 2742 | extern int __filemap_fdatawrite_range(struct address_space *mapping, |
| @@ -2747,6 +2746,11 @@ extern int filemap_fdatawrite_range(struct address_space *mapping, · 3 unmodified lines | |||
| 2747 | extern int filemap_check_errors(struct address_space *mapping); | 2746 | extern int filemap_check_errors(struct address_space *mapping); |
| 2748 | extern void __filemap_set_wb_err(struct address_space *mapping, int err); | 2747 | extern void __filemap_set_wb_err(struct address_space *mapping, int err); |
| 2749 | 2748 | ||
| 2749 | static inline int filemap_write_and_wait(struct address_space *mapping) | ||
| 2750 | { | ||
| 2751 | return filemap_write_and_wait_range(mapping, 0, LLONG_MAX); | ||
| 2752 | } | ||
| 2753 | |||
| 2750 | extern int __must_check file_fdatawait_range(struct file *file, loff_t lstart, | 2754 | extern int __must_check file_fdatawait_range(struct file *file, loff_t lstart, |
| 2751 | loff_t lend); | 2755 | loff_t lend); |
| 2752 | extern int __must_check file_check_and_advance_wb_err(struct file *file); | 2756 | extern int __must_check file_check_and_advance_wb_err(struct file *file); |
| @@ -28,6 +28,7 @@ struct io_mapping { · 27 unmodified lines | |||
| 28 | 28 | ||
| 29 | #ifdef CONFIG_HAVE_ATOMIC_IOMAP | 29 | #ifdef CONFIG_HAVE_ATOMIC_IOMAP |
| 30 | 30 | ||
| 31 | #include <linux/pfn.h> | ||
| 31 | #include <asm/iomap.h> | 32 | #include <asm/iomap.h> |
| 32 | /* | 33 | /* |
| 33 | * For small address space machines, mapping large objects | 34 | * For small address space machines, mapping large objects |
| @@ -64,12 +65,10 @@ io_mapping_map_atomic_wc(struct io_mapping *mapping, · 30 unmodified lines | |||
| 64 | unsigned long offset) | 65 | unsigned long offset) |
| 65 | { | 66 | { |
| 66 | resource_size_t phys_addr; | 67 | resource_size_t phys_addr; |
| 67 | unsigned long pfn; | ||
| 68 | 68 | ||
| 69 | BUG_ON(offset >= mapping->size); | 69 | BUG_ON(offset >= mapping->size); |
| 70 | phys_addr = mapping->base + offset; | 70 | phys_addr = mapping->base + offset; |
| 71 | pfn = (unsigned long) (phys_addr >> PAGE_SHIFT); | 71 | return iomap_atomic_prot_pfn(PHYS_PFN(phys_addr), mapping->prot); |
| 72 | return iomap_atomic_prot_pfn(pfn, mapping->prot); | ||
| 73 | } | 72 | } |
| 74 | 73 | ||
| 75 | static inline void | 74 | static inline void |
| @@ -113,6 +113,9 @@ int memblock_add(phys_addr_t base, phys_addr_t size); · 112 unmodified lines | |||
| 113 | int memblock_remove(phys_addr_t base, phys_addr_t size); | 113 | int memblock_remove(phys_addr_t base, phys_addr_t size); |
| 114 | int memblock_free(phys_addr_t base, phys_addr_t size); | 114 | int memblock_free(phys_addr_t base, phys_addr_t size); |
| 115 | int memblock_reserve(phys_addr_t base, phys_addr_t size); | 115 | int memblock_reserve(phys_addr_t base, phys_addr_t size); |
| 116 | #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP | ||
| 117 | int memblock_physmem_add(phys_addr_t base, phys_addr_t size); | ||
| 118 | #endif | ||
| 116 | void memblock_trim_memory(phys_addr_t align); | 119 | void memblock_trim_memory(phys_addr_t align); |
| 117 | bool memblock_overlaps_region(struct memblock_type *type, | 120 | bool memblock_overlaps_region(struct memblock_type *type, |
| 118 | phys_addr_t base, phys_addr_t size); | 121 | phys_addr_t base, phys_addr_t size); |
| @@ -127,10 +130,6 @@ void reset_node_managed_pages(pg_data_t *pgdat); · 8 unmodified lines | |||
| 127 | void reset_all_zones_managed_pages(void); | 130 | void reset_all_zones_managed_pages(void); |
| 128 | 131 | ||
| 129 | /* Low level functions */ | 132 | /* Low level functions */ |
| 130 | int memblock_add_range(struct memblock_type *type, | ||
| 131 | phys_addr_t base, phys_addr_t size, | ||
| 132 | int nid, enum memblock_flags flags); | ||
| 133 | |||
| 134 | void __next_mem_range(u64 *idx, int nid, enum memblock_flags flags, | 133 | void __next_mem_range(u64 *idx, int nid, enum memblock_flags flags, |
| 135 | struct memblock_type *type_a, | 134 | struct memblock_type *type_a, |
| 136 | struct memblock_type *type_b, phys_addr_t *out_start, | 135 | struct memblock_type *type_b, phys_addr_t *out_start, |
| @@ -29,8 +29,6 @@ struct memory_block { · 28 unmodified lines | |||
| 29 | int section_count; /* serialized by mem_sysfs_mutex */ | 29 | int section_count; /* serialized by mem_sysfs_mutex */ |
| 30 | int online_type; /* for passing data to online routine */ | 30 | int online_type; /* for passing data to online routine */ |
| 31 | int phys_device; /* to which fru does this belong? */ | 31 | int phys_device; /* to which fru does this belong? */ |
| 32 | void *hw; /* optional pointer to fw/hw data */ | ||
| 33 | int (*phys_callback)(struct memory_block *); | ||
| 34 | struct device dev; | 32 | struct device dev; |
| 35 | int nid; /* NID for this memory block */ | 33 | int nid; /* NID for this memory block */ |
| 36 | }; | 34 | }; |
| @@ -55,19 +53,6 @@ struct memory_notify { · 18 unmodified lines | |||
| 55 | int status_change_nid; | 53 | int status_change_nid; |
| 56 | }; | 54 | }; |
| 57 | 55 | ||
| 58 | /* | ||
| 59 | * During pageblock isolation, count the number of pages within the | ||
| 60 | * range [start_pfn, start_pfn + nr_pages) which are owned by code | ||
| 61 | * in the notifier chain. | ||
| 62 | */ | ||
| 63 | #define MEM_ISOLATE_COUNT (1<<0) | ||
| 64 | |||
| 65 | struct memory_isolate_notify { | ||
| 66 | unsigned long start_pfn; /* Start of range to check */ | ||
| 67 | unsigned int nr_pages; /* # pages in range to check */ | ||
| 68 | unsigned int pages_found; /* # pages owned found by callbacks */ | ||
| 69 | }; | ||
| 70 | |||
| 71 | struct notifier_block; | 56 | struct notifier_block; |
| 72 | struct mem_section; | 57 | struct mem_section; |
| 73 | 58 | ||
| @@ -94,27 +79,13 @@ static inline int memory_notify(unsigned long val, void *v) · 20 unmodified lines | |||
| 94 | { | 79 | { |
| 95 | return 0; | 80 | return 0; |
| 96 | } | 81 | } |
| 97 | static inline int register_memory_isolate_notifier(struct notifier_block *nb) | ||
| 98 | { | ||
| 99 | return 0; | ||
| 100 | } | ||
| 101 | static inline void unregister_memory_isolate_notifier(struct notifier_block *nb) | ||
| 102 | { | ||
| 103 | } | ||
| 104 | static inline int memory_isolate_notify(unsigned long val, void *v) | ||
| 105 | { | ||
| 106 | return 0; | ||
| 107 | } | ||
| 108 | #else | 82 | #else |
| 109 | extern int register_memory_notifier(struct notifier_block *nb); | 83 | extern int register_memory_notifier(struct notifier_block *nb); |
| 110 | extern void unregister_memory_notifier(struct notifier_block *nb); | 84 | extern void unregister_memory_notifier(struct notifier_block *nb); |
| 111 | extern int register_memory_isolate_notifier(struct notifier_block *nb); | ||
| 112 | extern void unregister_memory_isolate_notifier(struct notifier_block *nb); | ||
| 113 | int create_memory_block_devices(unsigned long start, unsigned long size); | 85 | int create_memory_block_devices(unsigned long start, unsigned long size); |
| 114 | void remove_memory_block_devices(unsigned long start, unsigned long size); | 86 | void remove_memory_block_devices(unsigned long start, unsigned long size); |
| 115 | extern void memory_dev_init(void); | 87 | extern void memory_dev_init(void); |
| 116 | extern int memory_notify(unsigned long val, void *v); | 88 | extern int memory_notify(unsigned long val, void *v); |
| 117 | extern int memory_isolate_notify(unsigned long val, void *v); | ||
| 118 | extern struct memory_block *find_memory_block(struct mem_section *); | 89 | extern struct memory_block *find_memory_block(struct mem_section *); |
| 119 | typedef int (*walk_memory_blocks_func_t)(struct memory_block *, void *); | 90 | typedef int (*walk_memory_blocks_func_t)(struct memory_block *, void *); |
| 120 | extern int walk_memory_blocks(unsigned long start, unsigned long size, | 91 | extern int walk_memory_blocks(unsigned long start, unsigned long size, |
| @@ -94,7 +94,8 @@ extern int zone_grow_free_lists(struct zone *zone, unsigned long new_nr_pages); · 93 unmodified lines | |||
| 94 | extern int zone_grow_waitqueues(struct zone *zone, unsigned long nr_pages); | 94 | extern int zone_grow_waitqueues(struct zone *zone, unsigned long nr_pages); |
| 95 | extern int add_one_highpage(struct page *page, int pfn, int bad_ppro); | 95 | extern int add_one_highpage(struct page *page, int pfn, int bad_ppro); |
| 96 | /* VM interface that may be used by firmware interface */ | 96 | /* VM interface that may be used by firmware interface */ |
| 97 | extern int online_pages(unsigned long, unsigned long, int); | 97 | extern int online_pages(unsigned long pfn, unsigned long nr_pages, |
| 98 | int online_type, int nid); | ||
| 98 | extern int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn, | 99 | extern int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn, |
| 99 | unsigned long *valid_start, unsigned long *valid_end); | 100 | unsigned long *valid_start, unsigned long *valid_end); |
| 100 | extern unsigned long __offline_isolated_pages(unsigned long start_pfn, | 101 | extern unsigned long __offline_isolated_pages(unsigned long start_pfn, |
| @@ -70,11 +70,6 @@ static inline void totalram_pages_add(long count) · 69 unmodified lines | |||
| 70 | atomic_long_add(count, &_totalram_pages); | 70 | atomic_long_add(count, &_totalram_pages); |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | static inline void totalram_pages_set(long val) | ||
| 74 | { | ||
| 75 | atomic_long_set(&_totalram_pages, val); | ||
| 76 | } | ||
| 77 | |||
| 78 | extern void * high_memory; | 73 | extern void * high_memory; |
| 79 | extern int page_cluster; | 74 | extern int page_cluster; |
| 80 | 75 | ||
| @@ -916,10 +911,6 @@ vm_fault_t finish_mkwrite_fault(struct vm_fault *vmf); · 835 unmodified lines | |||
| 916 | 911 | ||
| 917 | #define ZONEID_PGSHIFT (ZONEID_PGOFF * (ZONEID_SHIFT != 0)) | 912 | #define ZONEID_PGSHIFT (ZONEID_PGOFF * (ZONEID_SHIFT != 0)) |
| 918 | 913 | ||
| 919 | #if SECTIONS_WIDTH+NODES_WIDTH+ZONES_WIDTH > BITS_PER_LONG - NR_PAGEFLAGS | ||
| 920 | #error SECTIONS_WIDTH+NODES_WIDTH+ZONES_WIDTH > BITS_PER_LONG - NR_PAGEFLAGS | ||
| 921 | #endif | ||
| 922 | |||
| 923 | #define ZONES_MASK ((1UL << ZONES_WIDTH) - 1) | 914 | #define ZONES_MASK ((1UL << ZONES_WIDTH) - 1) |
| 924 | #define NODES_MASK ((1UL << NODES_WIDTH) - 1) | 915 | #define NODES_MASK ((1UL << NODES_WIDTH) - 1) |
| 925 | #define SECTIONS_MASK ((1UL << SECTIONS_WIDTH) - 1) | 916 | #define SECTIONS_MASK ((1UL << SECTIONS_WIDTH) - 1) |
| @@ -947,9 +938,10 @@ static inline bool is_zone_device_page(const struct page *page) · 21 unmodified lines | |||
| 947 | #endif | 938 | #endif |
| 948 | 939 | ||
| 949 | #ifdef CONFIG_DEV_PAGEMAP_OPS | 940 | #ifdef CONFIG_DEV_PAGEMAP_OPS |
| 950 | void __put_devmap_managed_page(struct page *page); | 941 | void free_devmap_managed_page(struct page *page); |
| 951 | DECLARE_STATIC_KEY_FALSE(devmap_managed_key); | 942 | DECLARE_STATIC_KEY_FALSE(devmap_managed_key); |
| 952 | static inline bool put_devmap_managed_page(struct page *page) | 943 | |
| 944 | static inline bool page_is_devmap_managed(struct page *page) | ||
| 953 | { | 945 | { |
| 954 | if (!static_branch_unlikely(&devmap_managed_key)) | 946 | if (!static_branch_unlikely(&devmap_managed_key)) |
| 955 | return false; | 947 | return false; |
| @@ -958,7 +950,6 @@ static inline bool put_devmap_managed_page(struct page *page) · 2 unmodified lines | |||
| 958 | switch (page->pgmap->type) { | 950 | switch (page->pgmap->type) { |
| 959 | case MEMORY_DEVICE_PRIVATE: | 951 | case MEMORY_DEVICE_PRIVATE: |
| 960 | case MEMORY_DEVICE_FS_DAX: | 952 | case MEMORY_DEVICE_FS_DAX: |
| 961 | __put_devmap_managed_page(page); | ||
| 962 | return true; | 953 | return true; |
| 963 | default: | 954 | default: |
| 964 | break; | 955 | break; |
| @@ -966,11 +957,17 @@ static inline bool put_devmap_managed_page(struct page *page) · 1 unmodified line | |||
| 966 | return false; | 957 | return false; |
| 967 | } | 958 | } |
| 968 | 959 | ||
| 960 | void put_devmap_managed_page(struct page *page); | ||
| 961 | |||
| 969 | #else /* CONFIG_DEV_PAGEMAP_OPS */ | 962 | #else /* CONFIG_DEV_PAGEMAP_OPS */ |
| 970 | static inline bool put_devmap_managed_page(struct page *page) | 963 | static inline bool page_is_devmap_managed(struct page *page) |
| 971 | { | 964 | { |
| 972 | return false; | 965 | return false; |
| 973 | } | 966 | } |
| 967 | |||
| 968 | static inline void put_devmap_managed_page(struct page *page) | ||
| 969 | { | ||
| 970 | } | ||
| 974 | #endif /* CONFIG_DEV_PAGEMAP_OPS */ | 971 | #endif /* CONFIG_DEV_PAGEMAP_OPS */ |
| 975 | 972 | ||
| 976 | static inline bool is_device_private_page(const struct page *page) | 973 | static inline bool is_device_private_page(const struct page *page) |
| @@ -1023,37 +1020,37 @@ static inline void put_page(struct page *page) · 46 unmodified lines | |||
| 1023 | * need to inform the device driver through callback. See | 1020 | * need to inform the device driver through callback. See |
| 1024 | * include/linux/memremap.h and HMM for details. | 1021 | * include/linux/memremap.h and HMM for details. |
| 1025 | */ | 1022 | */ |
| 1026 | if (put_devmap_managed_page(page)) | 1023 | if (page_is_devmap_managed(page)) { |
| 1024 | put_devmap_managed_page(page); | ||
| 1027 | return; | 1025 | return; |
| 1026 | } | ||
| 1028 | 1027 | ||
| 1029 | if (put_page_testzero(page)) | 1028 | if (put_page_testzero(page)) |
| 1030 | __put_page(page); | 1029 | __put_page(page); |
| 1031 | } | 1030 | } |
| 1032 | 1031 | ||
| 1033 | /** | 1032 | /** |
| 1034 | * put_user_page() - release a gup-pinned page | 1033 | * unpin_user_page() - release a gup-pinned page |
| 1035 | * @page: pointer to page to be released | 1034 | * @page: pointer to page to be released |
| 1036 | * | 1035 | * |
| 1037 | * Pages that were pinned via get_user_pages*() must be released via | 1036 | * Pages that were pinned via pin_user_pages*() must be released via either |
| 1038 | * either put_user_page(), or one of the put_user_pages*() routines | 1037 | * unpin_user_page(), or one of the unpin_user_pages*() routines. This is so |
| 1039 | * below. This is so that eventually, pages that are pinned via | 1038 | * that eventually such pages can be separately tracked and uniquely handled. In |
| 1040 | * get_user_pages*() can be separately tracked and uniquely handled. In | 1039 | * particular, interactions with RDMA and filesystems need special handling. |
| 1041 | * particular, interactions with RDMA and filesystems need special | ||
| 1042 | * handling. | ||
| 1043 | * | 1040 | * |
| 1044 | * put_user_page() and put_page() are not interchangeable, despite this early | 1041 | * unpin_user_page() and put_page() are not interchangeable, despite this early |
| 1045 | * implementation that makes them look the same. put_user_page() calls must | 1042 | * implementation that makes them look the same. unpin_user_page() calls must |
| 1046 | * be perfectly matched up with get_user_page() calls. | 1043 | * be perfectly matched up with pin*() calls. |
| 1047 | */ | 1044 | */ |
| 1048 | static inline void put_user_page(struct page *page) | 1045 | static inline void unpin_user_page(struct page *page) |
| 1049 | { | 1046 | { |
| 1050 | put_page(page); | 1047 | put_page(page); |
| 1051 | } | 1048 | } |
| 1052 | 1049 | ||
| 1053 | void put_user_pages_dirty_lock(struct page **pages, unsigned long npages, | 1050 | void unpin_user_pages_dirty_lock(struct page **pages, unsigned long npages, |
| 1054 | bool make_dirty); | 1051 | bool make_dirty); |
| 1055 | 1052 | ||
| 1056 | void put_user_pages(struct page **pages, unsigned long npages); | 1053 | void unpin_user_pages(struct page **pages, unsigned long npages); |
| 1057 | 1054 | ||
| 1058 | #if defined(CONFIG_SPARSEMEM) && !defined(CONFIG_SPARSEMEM_VMEMMAP) | 1055 | #if defined(CONFIG_SPARSEMEM) && !defined(CONFIG_SPARSEMEM_VMEMMAP) |
| 1059 | #define SECTION_IN_PAGE_FLAGS | 1056 | #define SECTION_IN_PAGE_FLAGS |
| @@ -1501,9 +1498,16 @@ long get_user_pages_remote(struct task_struct *tsk, struct mm_struct *mm, · 441 unmodified lines | |||
| 1501 | unsigned long start, unsigned long nr_pages, | 1498 | unsigned long start, unsigned long nr_pages, |
| 1502 | unsigned int gup_flags, struct page **pages, | 1499 | unsigned int gup_flags, struct page **pages, |
| 1503 | struct vm_area_struct **vmas, int *locked); | 1500 | struct vm_area_struct **vmas, int *locked); |
| 1501 | long pin_user_pages_remote(struct task_struct *tsk, struct mm_struct *mm, | ||
| 1502 | unsigned long start, unsigned long nr_pages, | ||
| 1503 | unsigned int gup_flags, struct page **pages, | ||
| 1504 | struct vm_area_struct **vmas, int *locked); | ||
| 1504 | long get_user_pages(unsigned long start, unsigned long nr_pages, | 1505 | long get_user_pages(unsigned long start, unsigned long nr_pages, |
| 1505 | unsigned int gup_flags, struct page **pages, | 1506 | unsigned int gup_flags, struct page **pages, |
| 1506 | struct vm_area_struct **vmas); | 1507 | struct vm_area_struct **vmas); |
| 1508 | long pin_user_pages(unsigned long start, unsigned long nr_pages, | ||
| 1509 | unsigned int gup_flags, struct page **pages, | ||
| 1510 | struct vm_area_struct **vmas); | ||
| 1507 | long get_user_pages_locked(unsigned long start, unsigned long nr_pages, | 1511 | long get_user_pages_locked(unsigned long start, unsigned long nr_pages, |
| 1508 | unsigned int gup_flags, struct page **pages, int *locked); | 1512 | unsigned int gup_flags, struct page **pages, int *locked); |
| 1509 | long get_user_pages_unlocked(unsigned long start, unsigned long nr_pages, | 1513 | long get_user_pages_unlocked(unsigned long start, unsigned long nr_pages, |
| @@ -1511,6 +1515,8 @@ long get_user_pages_unlocked(unsigned long start, unsigned long nr_pages, · 1 unmodified line | |||
| 1511 | 1515 | ||
| 1512 | int get_user_pages_fast(unsigned long start, int nr_pages, | 1516 | int get_user_pages_fast(unsigned long start, int nr_pages, |
| 1513 | unsigned int gup_flags, struct page **pages); | 1517 | unsigned int gup_flags, struct page **pages); |
| 1518 | int pin_user_pages_fast(unsigned long start, int nr_pages, | ||
| 1519 | unsigned int gup_flags, struct page **pages); | ||
| 1514 | 1520 | ||
| 1515 | int account_locked_vm(struct mm_struct *mm, unsigned long pages, bool inc); | 1521 | int account_locked_vm(struct mm_struct *mm, unsigned long pages, bool inc); |
| 1516 | int __account_locked_vm(struct mm_struct *mm, unsigned long pages, bool inc, | 1522 | int __account_locked_vm(struct mm_struct *mm, unsigned long pages, bool inc, |
| @@ -2575,13 +2581,15 @@ struct page *follow_page(struct vm_area_struct *vma, unsigned long address, · 1058 unmodified lines | |||
| 2575 | #define FOLL_ANON 0x8000 /* don't do file mappings */ | 2581 | #define FOLL_ANON 0x8000 /* don't do file mappings */ |
| 2576 | #define FOLL_LONGTERM 0x10000 /* mapping lifetime is indefinite: see below */ | 2582 | #define FOLL_LONGTERM 0x10000 /* mapping lifetime is indefinite: see below */ |
| 2577 | #define FOLL_SPLIT_PMD 0x20000 /* split huge pmd before returning */ | 2583 | #define FOLL_SPLIT_PMD 0x20000 /* split huge pmd before returning */ |
| 2584 | #define FOLL_PIN 0x40000 /* pages must be released via unpin_user_page */ | ||
| 2578 | 2585 | ||
| 2579 | /* | 2586 | /* |
| 2580 | * NOTE on FOLL_LONGTERM: | 2587 | * FOLL_PIN and FOLL_LONGTERM may be used in various combinations with each |
| 2588 | * other. Here is what they mean, and how to use them: | ||
| 2581 | * | 2589 | * |
| 2582 | * FOLL_LONGTERM indicates that the page will be held for an indefinite time | 2590 | * FOLL_LONGTERM indicates that the page will be held for an indefinite time |
| 2583 | * period _often_ under userspace control. This is contrasted with | 2591 | * period _often_ under userspace control. This is in contrast to |
| 2584 | * iov_iter_get_pages() where usages which are transient. | 2592 | * iov_iter_get_pages(), whose usages are transient. |
| 2585 | * | 2593 | * |
| 2586 | * FIXME: For pages which are part of a filesystem, mappings are subject to the | 2594 | * FIXME: For pages which are part of a filesystem, mappings are subject to the |
| 2587 | * lifetime enforced by the filesystem and we need guarantees that longterm | 2595 | * lifetime enforced by the filesystem and we need guarantees that longterm |
| @@ -2596,11 +2604,39 @@ struct page *follow_page(struct vm_area_struct *vma, unsigned long address, · 8 unmodified lines | |||
| 2596 | * Currently only get_user_pages() and get_user_pages_fast() support this flag | 2604 | * Currently only get_user_pages() and get_user_pages_fast() support this flag |
| 2597 | * and calls to get_user_pages_[un]locked are specifically not allowed. This | 2605 | * and calls to get_user_pages_[un]locked are specifically not allowed. This |
| 2598 | * is due to an incompatibility with the FS DAX check and | 2606 | * is due to an incompatibility with the FS DAX check and |
| 2599 | * FAULT_FLAG_ALLOW_RETRY | 2607 | * FAULT_FLAG_ALLOW_RETRY. |
| 2600 | * | 2608 | * |
| 2601 | * In the CMA case: longterm pins in a CMA region would unnecessarily fragment | 2609 | * In the CMA case: long term pins in a CMA region would unnecessarily fragment |
| 2602 | * that region. And so CMA attempts to migrate the page before pinning when | 2610 | * that region. And so, CMA attempts to migrate the page before pinning, when |
| 2603 | * FOLL_LONGTERM is specified. | 2611 | * FOLL_LONGTERM is specified. |
| 2612 | * | ||
| 2613 | * FOLL_PIN indicates that a special kind of tracking (not just page->_refcount, | ||
| 2614 | * but an additional pin counting system) will be invoked. This is intended for | ||
| 2615 | * anything that gets a page reference and then touches page data (for example, | ||
| 2616 | * Direct IO). This lets the filesystem know that some non-file-system entity is | ||
| 2617 | * potentially changing the pages' data. In contrast to FOLL_GET (whose pages | ||
| 2618 | * are released via put_page()), FOLL_PIN pages must be released, ultimately, by | ||
| 2619 | * a call to unpin_user_page(). | ||
| 2620 | * | ||
| 2621 | * FOLL_PIN is similar to FOLL_GET: both of these pin pages. They use different | ||
| 2622 | * and separate refcounting mechanisms, however, and that means that each has | ||
| 2623 | * its own acquire and release mechanisms: | ||
| 2624 | * | ||
| 2625 | * FOLL_GET: get_user_pages*() to acquire, and put_page() to release. | ||
| 2626 | * | ||
| 2627 | * FOLL_PIN: pin_user_pages*() to acquire, and unpin_user_pages to release. | ||
| 2628 | * | ||
| 2629 | * FOLL_PIN and FOLL_GET are mutually exclusive for a given function call. | ||
| 2630 | * (The underlying pages may experience both FOLL_GET-based and FOLL_PIN-based | ||
| 2631 | * calls applied to them, and that's perfectly OK. This is a constraint on the | ||
| 2632 | * callers, not on the pages.) | ||
| 2633 | * | ||
| 2634 | * FOLL_PIN should be set internally by the pin_user_pages*() APIs, never | ||
| 2635 | * directly by the caller. That's in order to help avoid mismatches when | ||
| 2636 | * releasing pages: get_user_pages*() pages must be released via put_page(), | ||
| 2637 | * while pin_user_pages*() pages must be released via unpin_user_page(). | ||
| 2638 | * | ||
| 2639 | * Please see Documentation/vm/pin_user_pages.rst for more information. | ||
| 2604 | */ | 2640 | */ |
| 2605 | 2641 | ||
| 2606 | static inline int vm_fault_to_errno(vm_fault_t vm_fault, int foll_flags) | 2642 | static inline int vm_fault_to_errno(vm_fault_t vm_fault, int foll_flags) |
| @@ -758,7 +758,7 @@ typedef struct pglist_data { · 757 unmodified lines | |||
| 758 | 758 | ||
| 759 | #ifdef CONFIG_NUMA | 759 | #ifdef CONFIG_NUMA |
| 760 | /* | 760 | /* |
| 761 | * zone reclaim becomes active if more unmapped pages exist. | 761 | * node reclaim becomes active if more unmapped pages exist. |
| 762 | */ | 762 | */ |
| 763 | unsigned long min_unmapped_pages; | 763 | unsigned long min_unmapped_pages; |
| 764 | unsigned long min_slab_pages; | 764 | unsigned long min_slab_pages; |
| @@ -33,8 +33,8 @@ static inline bool is_migrate_isolate(int migratetype) · 32 unmodified lines | |||
| 33 | #define MEMORY_OFFLINE 0x1 | 33 | #define MEMORY_OFFLINE 0x1 |
| 34 | #define REPORT_FAILURE 0x2 | 34 | #define REPORT_FAILURE 0x2 |
| 35 | 35 | ||
| 36 | bool has_unmovable_pages(struct zone *zone, struct page *page, int count, | 36 | struct page *has_unmovable_pages(struct zone *zone, struct page *page, |
| 37 | int migratetype, int flags); | 37 | int migratetype, int flags); |
| 38 | void set_pageblock_migratetype(struct page *page, int migratetype); | 38 | void set_pageblock_migratetype(struct page *page, int migratetype); |
| 39 | int move_freepages_block(struct zone *zone, struct page *page, | 39 | int move_freepages_block(struct zone *zone, struct page *page, |
| 40 | int migratetype, int *num_movable); | 40 | int migratetype, int *num_movable); |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | |||
| 7 | # define swab16 __swab16 | 7 | # define swab16 __swab16 |
| 8 | # define swab32 __swab32 | 8 | # define swab32 __swab32 |
| 9 | # define swab64 __swab64 | 9 | # define swab64 __swab64 |
| 10 | # define swab __swab | ||
| 10 | # define swahw32 __swahw32 | 11 | # define swahw32 __swahw32 |
| 11 | # define swahb32 __swahb32 | 12 | # define swahb32 __swahb32 |
| 12 | # define swab16p __swab16p | 13 | # define swab16p __swab16p |
| @@ -32,17 +32,6 @@ · 31 unmodified lines | |||
| 32 | /* use value, which < 0K, to indicate an invalid/uninitialized temperature */ | 32 | /* use value, which < 0K, to indicate an invalid/uninitialized temperature */ |
| 33 | #define THERMAL_TEMP_INVALID -274000 | 33 | #define THERMAL_TEMP_INVALID -274000 |
| 34 | 34 | ||
| 35 | /* Unit conversion macros */ | ||
| 36 | #define DECI_KELVIN_TO_CELSIUS(t) ({ \ | ||
| 37 | long _t = (t); \ | ||
| 38 | ((_t-2732 >= 0) ? (_t-2732+5)/10 : (_t-2732-5)/10); \ | ||
| 39 | }) | ||
| 40 | #define CELSIUS_TO_DECI_KELVIN(t) ((t)*10+2732) | ||
| 41 | #define DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(t, off) (((t) - (off)) * 100) | ||
| 42 | #define DECI_KELVIN_TO_MILLICELSIUS(t) DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(t, 2732) | ||
| 43 | #define MILLICELSIUS_TO_DECI_KELVIN_WITH_OFFSET(t, off) (((t) / 100) + (off)) | ||
| 44 | #define MILLICELSIUS_TO_DECI_KELVIN(t) MILLICELSIUS_TO_DECI_KELVIN_WITH_OFFSET(t, 2732) | ||
| 45 | |||
| 46 | /* Default Thermal Governor */ | 35 | /* Default Thermal Governor */ |
| 47 | #if defined(CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE) | 36 | #if defined(CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE) |
| 48 | #define DEFAULT_THERMAL_GOVERNOR "step_wise" | 37 | #define DEFAULT_THERMAL_GOVERNOR "step_wise" |
| @@ -0,0 +1,84 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | #ifndef _LINUX_UNITS_H | ||
| 3 | #define _LINUX_UNITS_H | ||
| 4 | |||
| 5 | #include <linux/kernel.h> | ||
| 6 | |||
| 7 | #define ABSOLUTE_ZERO_MILLICELSIUS -273150 | ||
| 8 | |||
| 9 | static inline long milli_kelvin_to_millicelsius(long t) | ||
| 10 | { | ||
| 11 | return t + ABSOLUTE_ZERO_MILLICELSIUS; | ||
| 12 | } | ||
| 13 | |||
| 14 | static inline long millicelsius_to_milli_kelvin(long t) | ||
| 15 | { | ||
| 16 | return t - ABSOLUTE_ZERO_MILLICELSIUS; | ||
| 17 | } | ||
| 18 | |||
| 19 | #define MILLIDEGREE_PER_DEGREE 1000 | ||
| 20 | #define MILLIDEGREE_PER_DECIDEGREE 100 | ||
| 21 | |||
| 22 | static inline long kelvin_to_millicelsius(long t) | ||
| 23 | { | ||
| 24 | return milli_kelvin_to_millicelsius(t * MILLIDEGREE_PER_DEGREE); | ||
| 25 | } | ||
| 26 | |||
| 27 | static inline long millicelsius_to_kelvin(long t) | ||
| 28 | { | ||
| 29 | t = millicelsius_to_milli_kelvin(t); | ||
| 30 | |||
| 31 | return DIV_ROUND_CLOSEST(t, MILLIDEGREE_PER_DEGREE); | ||
| 32 | } | ||
| 33 | |||
| 34 | static inline long deci_kelvin_to_celsius(long t) | ||
| 35 | { | ||
| 36 | t = milli_kelvin_to_millicelsius(t * MILLIDEGREE_PER_DECIDEGREE); | ||
| 37 | |||
| 38 | return DIV_ROUND_CLOSEST(t, MILLIDEGREE_PER_DEGREE); | ||
| 39 | } | ||
| 40 | |||
| 41 | static inline long celsius_to_deci_kelvin(long t) | ||
| 42 | { | ||
| 43 | t = millicelsius_to_milli_kelvin(t * MILLIDEGREE_PER_DEGREE); | ||
| 44 | |||
| 45 | return DIV_ROUND_CLOSEST(t, MILLIDEGREE_PER_DECIDEGREE); | ||
| 46 | } | ||
| 47 | |||
| 48 | /** | ||
| 49 | * deci_kelvin_to_millicelsius_with_offset - convert Kelvin to Celsius | ||
| 50 | * @t: temperature value in decidegrees Kelvin | ||
| 51 | * @offset: difference between Kelvin and Celsius in millidegrees | ||
| 52 | * | ||
| 53 | * Return: temperature value in millidegrees Celsius | ||
| 54 | */ | ||
| 55 | static inline long deci_kelvin_to_millicelsius_with_offset(long t, long offset) | ||
| 56 | { | ||
| 57 | return t * MILLIDEGREE_PER_DECIDEGREE - offset; | ||
| 58 | } | ||
| 59 | |||
| 60 | static inline long deci_kelvin_to_millicelsius(long t) | ||
| 61 | { | ||
| 62 | return milli_kelvin_to_millicelsius(t * MILLIDEGREE_PER_DECIDEGREE); | ||
| 63 | } | ||
| 64 | |||
| 65 | static inline long millicelsius_to_deci_kelvin(long t) | ||
| 66 | { | ||
| 67 | t = millicelsius_to_milli_kelvin(t); | ||
| 68 | |||
| 69 | return DIV_ROUND_CLOSEST(t, MILLIDEGREE_PER_DECIDEGREE); | ||
| 70 | } | ||
| 71 | |||
| 72 | static inline long kelvin_to_celsius(long t) | ||
| 73 | { | ||
| 74 | return t + DIV_ROUND_CLOSEST(ABSOLUTE_ZERO_MILLICELSIUS, | ||
| 75 | MILLIDEGREE_PER_DEGREE); | ||
| 76 | } | ||
| 77 | |||
| 78 | static inline long celsius_to_kelvin(long t) | ||
| 79 | { | ||
| 80 | return t - DIV_ROUND_CLOSEST(ABSOLUTE_ZERO_MILLICELSIUS, | ||
| 81 | MILLIDEGREE_PER_DEGREE); | ||
| 82 | } | ||
| 83 | |||
| 84 | #endif /* _LINUX_UNITS_H */ | ||
| @@ -191,6 +191,12 @@ extern int zlib_deflate_workspacesize (int windowBits, int memLevel); · 190 unmodified lines | |||
| 191 | exceed those passed here. | 191 | exceed those passed here. |
| 192 | */ | 192 | */ |
| 193 | 193 | ||
| 194 | extern int zlib_deflate_dfltcc_enabled (void); | ||
| 195 | /* | ||
| 196 | Returns 1 if Deflate-Conversion facility is installed and enabled, | ||
| 197 | otherwise 0. | ||
| 198 | */ | ||
| 199 | |||
| 194 | /* | 200 | /* |
| 195 | extern int deflateInit (z_streamp strm, int level); | 201 | extern int deflateInit (z_streamp strm, int level); |
| 196 | 202 | ||
| @@ -88,8 +88,8 @@ DECLARE_EVENT_CLASS(kmem_alloc_node, · 87 unmodified lines | |||
| 88 | __entry->node = node; | 88 | __entry->node = node; |
| 89 | ), | 89 | ), |
| 90 | 90 | ||
| 91 | TP_printk("call_site=%lx ptr=%p bytes_req=%zu bytes_alloc=%zu gfp_flags=%s node=%d", | 91 | TP_printk("call_site=%pS ptr=%p bytes_req=%zu bytes_alloc=%zu gfp_flags=%s node=%d", |
| 92 | __entry->call_site, | 92 | (void *)__entry->call_site, |
| 93 | __entry->ptr, | 93 | __entry->ptr, |
| 94 | __entry->bytes_req, | 94 | __entry->bytes_req, |
| 95 | __entry->bytes_alloc, | 95 | __entry->bytes_alloc, |
| @@ -67,8 +67,8 @@ DECLARE_EVENT_CLASS(writeback_page_template, · 66 unmodified lines | |||
| 67 | 67 | ||
| 68 | TP_fast_assign( | 68 | TP_fast_assign( |
| 69 | strscpy_pad(__entry->name, | 69 | strscpy_pad(__entry->name, |
| 70 | mapping ? dev_name(inode_to_bdi(mapping->host)->dev) : "(unknown)", | 70 | bdi_dev_name(mapping ? inode_to_bdi(mapping->host) : |
| 71 | 32); | 71 | NULL), 32); |
| 72 | __entry->ino = mapping ? mapping->host->i_ino : 0; | 72 | __entry->ino = mapping ? mapping->host->i_ino : 0; |
| 73 | __entry->index = page->index; | 73 | __entry->index = page->index; |
| 74 | ), | 74 | ), |
| @@ -111,8 +111,7 @@ DECLARE_EVENT_CLASS(writeback_dirty_inode_template, · 36 unmodified lines | |||
| 111 | struct backing_dev_info *bdi = inode_to_bdi(inode); | 111 | struct backing_dev_info *bdi = inode_to_bdi(inode); |
| 112 | 112 | ||
| 113 | /* may be called for files on pseudo FSes w/ unregistered bdi */ | 113 | /* may be called for files on pseudo FSes w/ unregistered bdi */ |
| 114 | strscpy_pad(__entry->name, | 114 | strscpy_pad(__entry->name, bdi_dev_name(bdi), 32); |
| 115 | bdi->dev ? dev_name(bdi->dev) : "(unknown)", 32); | ||
| 116 | __entry->ino = inode->i_ino; | 115 | __entry->ino = inode->i_ino; |
| 117 | __entry->state = inode->i_state; | 116 | __entry->state = inode->i_state; |
| 118 | __entry->flags = flags; | 117 | __entry->flags = flags; |
| @@ -193,7 +192,7 @@ TRACE_EVENT(inode_foreign_history, · 74 unmodified lines | |||
| 193 | ), | 192 | ), |
| 194 | 193 | ||
| 195 | TP_fast_assign( | 194 | TP_fast_assign( |
| 196 | strncpy(__entry->name, dev_name(inode_to_bdi(inode)->dev), 32); | 195 | strncpy(__entry->name, bdi_dev_name(inode_to_bdi(inode)), 32); |
| 197 | __entry->ino = inode->i_ino; | 196 | __entry->ino = inode->i_ino; |
| 198 | __entry->cgroup_ino = __trace_wbc_assign_cgroup(wbc); | 197 | __entry->cgroup_ino = __trace_wbc_assign_cgroup(wbc); |
| 199 | __entry->history = history; | 198 | __entry->history = history; |
| @@ -222,7 +221,7 @@ TRACE_EVENT(inode_switch_wbs, · 22 unmodified lines | |||
| 222 | ), | 221 | ), |
| 223 | 222 | ||
| 224 | TP_fast_assign( | 223 | TP_fast_assign( |
| 225 | strncpy(__entry->name, dev_name(old_wb->bdi->dev), 32); | 224 | strncpy(__entry->name, bdi_dev_name(old_wb->bdi), 32); |
| 226 | __entry->ino = inode->i_ino; | 225 | __entry->ino = inode->i_ino; |
| 227 | __entry->old_cgroup_ino = __trace_wb_assign_cgroup(old_wb); | 226 | __entry->old_cgroup_ino = __trace_wb_assign_cgroup(old_wb); |
| 228 | __entry->new_cgroup_ino = __trace_wb_assign_cgroup(new_wb); | 227 | __entry->new_cgroup_ino = __trace_wb_assign_cgroup(new_wb); |
| @@ -255,7 +254,7 @@ TRACE_EVENT(track_foreign_dirty, · 26 unmodified lines | |||
| 255 | struct address_space *mapping = page_mapping(page); | 254 | struct address_space *mapping = page_mapping(page); |
| 256 | struct inode *inode = mapping ? mapping->host : NULL; | 255 | struct inode *inode = mapping ? mapping->host : NULL; |
| 257 | 256 | ||
| 258 | strncpy(__entry->name, dev_name(wb->bdi->dev), 32); | 257 | strncpy(__entry->name, bdi_dev_name(wb->bdi), 32); |
| 259 | __entry->bdi_id = wb->bdi->id; | 258 | __entry->bdi_id = wb->bdi->id; |
| 260 | __entry->ino = inode ? inode->i_ino : 0; | 259 | __entry->ino = inode ? inode->i_ino : 0; |
| 261 | __entry->memcg_id = wb->memcg_css->id; | 260 | __entry->memcg_id = wb->memcg_css->id; |
| @@ -288,7 +287,7 @@ TRACE_EVENT(flush_foreign, · 26 unmodified lines | |||
| 288 | ), | 287 | ), |
| 289 | 288 | ||
| 290 | TP_fast_assign( | 289 | TP_fast_assign( |
| 291 | strncpy(__entry->name, dev_name(wb->bdi->dev), 32); | 290 | strncpy(__entry->name, bdi_dev_name(wb->bdi), 32); |
| 292 | __entry->cgroup_ino = __trace_wb_assign_cgroup(wb); | 291 | __entry->cgroup_ino = __trace_wb_assign_cgroup(wb); |
| 293 | __entry->frn_bdi_id = frn_bdi_id; | 292 | __entry->frn_bdi_id = frn_bdi_id; |
| 294 | __entry->frn_memcg_id = frn_memcg_id; | 293 | __entry->frn_memcg_id = frn_memcg_id; |
| @@ -318,7 +317,7 @@ DECLARE_EVENT_CLASS(writeback_write_inode_template, · 23 unmodified lines | |||
| 318 | 317 | ||
| 319 | TP_fast_assign( | 318 | TP_fast_assign( |
| 320 | strscpy_pad(__entry->name, | 319 | strscpy_pad(__entry->name, |
| 321 | dev_name(inode_to_bdi(inode)->dev), 32); | 320 | bdi_dev_name(inode_to_bdi(inode)), 32); |
| 322 | __entry->ino = inode->i_ino; | 321 | __entry->ino = inode->i_ino; |
| 323 | __entry->sync_mode = wbc->sync_mode; | 322 | __entry->sync_mode = wbc->sync_mode; |
| 324 | __entry->cgroup_ino = __trace_wbc_assign_cgroup(wbc); | 323 | __entry->cgroup_ino = __trace_wbc_assign_cgroup(wbc); |
| @@ -361,9 +360,7 @@ DECLARE_EVENT_CLASS(writeback_work_class, · 36 unmodified lines | |||
| 361 | __field(ino_t, cgroup_ino) | 360 | __field(ino_t, cgroup_ino) |
| 362 | ), | 361 | ), |
| 363 | TP_fast_assign( | 362 | TP_fast_assign( |
| 364 | strscpy_pad(__entry->name, | 363 | strscpy_pad(__entry->name, bdi_dev_name(wb->bdi), 32); |
| 365 | wb->bdi->dev ? dev_name(wb->bdi->dev) : | ||
| 366 | "(unknown)", 32); | ||
| 367 | __entry->nr_pages = work->nr_pages; | 364 | __entry->nr_pages = work->nr_pages; |
| 368 | __entry->sb_dev = work->sb ? work->sb->s_dev : 0; | 365 | __entry->sb_dev = work->sb ? work->sb->s_dev : 0; |
| 369 | __entry->sync_mode = work->sync_mode; | 366 | __entry->sync_mode = work->sync_mode; |
| @@ -416,7 +413,7 @@ DECLARE_EVENT_CLASS(writeback_class, · 46 unmodified lines | |||
| 416 | __field(ino_t, cgroup_ino) | 413 | __field(ino_t, cgroup_ino) |
| 417 | ), | 414 | ), |
| 418 | TP_fast_assign( | 415 | TP_fast_assign( |
| 419 | strscpy_pad(__entry->name, dev_name(wb->bdi->dev), 32); | 416 | strscpy_pad(__entry->name, bdi_dev_name(wb->bdi), 32); |
| 420 | __entry->cgroup_ino = __trace_wb_assign_cgroup(wb); | 417 | __entry->cgroup_ino = __trace_wb_assign_cgroup(wb); |
| 421 | ), | 418 | ), |
| 422 | TP_printk("bdi %s: cgroup_ino=%lu", | 419 | TP_printk("bdi %s: cgroup_ino=%lu", |
| @@ -438,7 +435,7 @@ TRACE_EVENT(writeback_bdi_register, · 15 unmodified lines | |||
| 438 | __array(char, name, 32) | 435 | __array(char, name, 32) |
| 439 | ), | 436 | ), |
| 440 | TP_fast_assign( | 437 | TP_fast_assign( |
| 441 | strscpy_pad(__entry->name, dev_name(bdi->dev), 32); | 438 | strscpy_pad(__entry->name, bdi_dev_name(bdi), 32); |
| 442 | ), | 439 | ), |
| 443 | TP_printk("bdi %s", | 440 | TP_printk("bdi %s", |
| 444 | __entry->name | 441 | __entry->name |
| @@ -463,7 +460,7 @@ DECLARE_EVENT_CLASS(wbc_class, · 18 unmodified lines | |||
| 463 | ), | 460 | ), |
| 464 | 461 | ||
| 465 | TP_fast_assign( | 462 | TP_fast_assign( |
| 466 | strscpy_pad(__entry->name, dev_name(bdi->dev), 32); | 463 | strscpy_pad(__entry->name, bdi_dev_name(bdi), 32); |
| 467 | __entry->nr_to_write = wbc->nr_to_write; | 464 | __entry->nr_to_write = wbc->nr_to_write; |
| 468 | __entry->pages_skipped = wbc->pages_skipped; | 465 | __entry->pages_skipped = wbc->pages_skipped; |
| 469 | __entry->sync_mode = wbc->sync_mode; | 466 | __entry->sync_mode = wbc->sync_mode; |
| @@ -514,7 +511,7 @@ TRACE_EVENT(writeback_queue_io, · 44 unmodified lines | |||
| 514 | ), | 511 | ), |
| 515 | TP_fast_assign( | 512 | TP_fast_assign( |
| 516 | unsigned long *older_than_this = work->older_than_this; | 513 | unsigned long *older_than_this = work->older_than_this; |
| 517 | strscpy_pad(__entry->name, dev_name(wb->bdi->dev), 32); | 514 | strscpy_pad(__entry->name, bdi_dev_name(wb->bdi), 32); |
| 518 | __entry->older = older_than_this ? *older_than_this : 0; | 515 | __entry->older = older_than_this ? *older_than_this : 0; |
| 519 | __entry->age = older_than_this ? | 516 | __entry->age = older_than_this ? |
| 520 | (jiffies - *older_than_this) * 1000 / HZ : -1; | 517 | (jiffies - *older_than_this) * 1000 / HZ : -1; |
| @@ -600,7 +597,7 @@ TRACE_EVENT(bdi_dirty_ratelimit, · 79 unmodified lines | |||
| 600 | ), | 597 | ), |
| 601 | 598 | ||
| 602 | TP_fast_assign( | 599 | TP_fast_assign( |
| 603 | strscpy_pad(__entry->bdi, dev_name(wb->bdi->dev), 32); | 600 | strscpy_pad(__entry->bdi, bdi_dev_name(wb->bdi), 32); |
| 604 | __entry->write_bw = KBps(wb->write_bandwidth); | 601 | __entry->write_bw = KBps(wb->write_bandwidth); |
| 605 | __entry->avg_write_bw = KBps(wb->avg_write_bandwidth); | 602 | __entry->avg_write_bw = KBps(wb->avg_write_bandwidth); |
| 606 | __entry->dirty_rate = KBps(dirty_rate); | 603 | __entry->dirty_rate = KBps(dirty_rate); |
| @@ -665,7 +662,7 @@ TRACE_EVENT(balance_dirty_pages, · 58 unmodified lines | |||
| 665 | 662 | ||
| 666 | TP_fast_assign( | 663 | TP_fast_assign( |
| 667 | unsigned long freerun = (thresh + bg_thresh) / 2; | 664 | unsigned long freerun = (thresh + bg_thresh) / 2; |
| 668 | strscpy_pad(__entry->bdi, dev_name(wb->bdi->dev), 32); | 665 | strscpy_pad(__entry->bdi, bdi_dev_name(wb->bdi), 32); |
| 669 | 666 | ||
| 670 | __entry->limit = global_wb_domain.dirty_limit; | 667 | __entry->limit = global_wb_domain.dirty_limit; |
| 671 | __entry->setpoint = (global_wb_domain.dirty_limit + | 668 | __entry->setpoint = (global_wb_domain.dirty_limit + |
| @@ -726,7 +723,7 @@ TRACE_EVENT(writeback_sb_inodes_requeue, · 54 unmodified lines | |||
| 726 | 723 | ||
| 727 | TP_fast_assign( | 724 | TP_fast_assign( |
| 728 | strscpy_pad(__entry->name, | 725 | strscpy_pad(__entry->name, |
| 729 | dev_name(inode_to_bdi(inode)->dev), 32); | 726 | bdi_dev_name(inode_to_bdi(inode)), 32); |
| 730 | __entry->ino = inode->i_ino; | 727 | __entry->ino = inode->i_ino; |
| 731 | __entry->state = inode->i_state; | 728 | __entry->state = inode->i_state; |
| 732 | __entry->dirtied_when = inode->dirtied_when; | 729 | __entry->dirtied_when = inode->dirtied_when; |
| @@ -800,7 +797,7 @@ DECLARE_EVENT_CLASS(writeback_single_inode_template, · 67 unmodified lines | |||
| 800 | 797 | ||
| 801 | TP_fast_assign( | 798 | TP_fast_assign( |
| 802 | strscpy_pad(__entry->name, | 799 | strscpy_pad(__entry->name, |
| 803 | dev_name(inode_to_bdi(inode)->dev), 32); | 800 | bdi_dev_name(inode_to_bdi(inode)), 32); |
| 804 | __entry->ino = inode->i_ino; | 801 | __entry->ino = inode->i_ino; |
| 805 | __entry->state = inode->i_state; | 802 | __entry->state = inode->i_state; |
| 806 | __entry->dirtied_when = inode->dirtied_when; | 803 | __entry->dirtied_when = inode->dirtied_when; |
| @@ -4,6 +4,7 @@ · 3 unmodified lines | |||
| 4 | 4 | ||
| 5 | #include <linux/types.h> | 5 | #include <linux/types.h> |
| 6 | #include <linux/compiler.h> | 6 | #include <linux/compiler.h> |
| 7 | #include <asm/bitsperlong.h> | ||
| 7 | #include <asm/swab.h> | 8 | #include <asm/swab.h> |
| 8 | 9 | ||
| 9 | /* | 10 | /* |
| @@ -132,6 +133,15 @@ static inline __attribute_const__ __u32 __fswahb32(__u32 val) · 122 unmodified lines | |||
| 132 | __fswab64(x)) | 133 | __fswab64(x)) |
| 133 | #endif | 134 | #endif |
| 134 | 135 | ||
| 136 | static __always_inline unsigned long __swab(const unsigned long y) | ||
| 137 | { | ||
| 138 | #if BITS_PER_LONG == 64 | ||
| 139 | return __swab64(y); | ||
| 140 | #else /* BITS_PER_LONG == 32 */ | ||
| 141 | return __swab32(y); | ||
| 142 | #endif | ||
| 143 | } | ||
| 144 | |||
| 135 | /** | 145 | /** |
| 136 | * __swahw32 - return a word-swapped 32-bit value | 146 | * __swahw32 - return a word-swapped 32-bit value |
| 137 | * @x: value to wordswap | 147 | * @x: value to wordswap |
| @@ -195,7 +195,7 @@ enum · 194 unmodified lines | |||
| 195 | VM_MIN_UNMAPPED=32, /* Set min percent of unmapped pages */ | 195 | VM_MIN_UNMAPPED=32, /* Set min percent of unmapped pages */ |
| 196 | VM_PANIC_ON_OOM=33, /* panic at out-of-memory */ | 196 | VM_PANIC_ON_OOM=33, /* panic at out-of-memory */ |
| 197 | VM_VDSO_ENABLED=34, /* map VDSO into new processes? */ | 197 | VM_VDSO_ENABLED=34, /* map VDSO into new processes? */ |
| 198 | VM_MIN_SLAB=35, /* Percent pages ignored by zone reclaim */ | 198 | VM_MIN_SLAB=35, /* Percent pages ignored by node reclaim */ |
| 199 | }; | 199 | }; |
| 200 | 200 | ||
| 201 | 201 | ||
| @@ -246,8 +246,7 @@ static int __init loglevel(char *str) · 245 unmodified lines | |||
| 246 | early_param("loglevel", loglevel); | 246 | early_param("loglevel", loglevel); |
| 247 | 247 | ||
| 248 | /* Change NUL term back to "=", to make "param" the whole string. */ | 248 | /* Change NUL term back to "=", to make "param" the whole string. */ |
| 249 | static int __init repair_env_string(char *param, char *val, | 249 | static void __init repair_env_string(char *param, char *val) |
| 250 | const char *unused, void *arg) | ||
| 251 | { | 250 | { |
| 252 | if (val) { | 251 | if (val) { |
| 253 | /* param=val or param="val"? */ | 252 | /* param=val or param="val"? */ |
| @@ -256,11 +255,9 @@ static int __init repair_env_string(char *param, char *val, · 2 unmodified lines | |||
| 256 | else if (val == param+strlen(param)+2) { | 255 | else if (val == param+strlen(param)+2) { |
| 257 | val[-2] = '='; | 256 | val[-2] = '='; |
| 258 | memmove(val-1, val, strlen(val)+1); | 257 | memmove(val-1, val, strlen(val)+1); |
| 259 | val--; | ||
| 260 | } else | 258 | } else |
| 261 | BUG(); | 259 | BUG(); |
| 262 | } | 260 | } |
| 263 | return 0; | ||
| 264 | } | 261 | } |
| 265 | 262 | ||
| 266 | /* Anything after -- gets handed straight to init. */ | 263 | /* Anything after -- gets handed straight to init. */ |
| @@ -272,7 +269,7 @@ static int __init set_init_arg(char *param, char *val, · 5 unmodified lines | |||
| 272 | if (panic_later) | 269 | if (panic_later) |
| 273 | return 0; | 270 | return 0; |
| 274 | 271 | ||
| 275 | repair_env_string(param, val, unused, NULL); | 272 | repair_env_string(param, val); |
| 276 | 273 | ||
| 277 | for (i = 0; argv_init[i]; i++) { | 274 | for (i = 0; argv_init[i]; i++) { |
| 278 | if (i == MAX_INIT_ARGS) { | 275 | if (i == MAX_INIT_ARGS) { |
| @@ -292,14 +289,16 @@ static int __init set_init_arg(char *param, char *val, · 13 unmodified lines | |||
| 292 | static int __init unknown_bootoption(char *param, char *val, | 289 | static int __init unknown_bootoption(char *param, char *val, |
| 293 | const char *unused, void *arg) | 290 | const char *unused, void *arg) |
| 294 | { | 291 | { |
| 295 | repair_env_string(param, val, unused, NULL); | 292 | size_t len = strlen(param); |
| 293 | |||
| 294 | repair_env_string(param, val); | ||
| 296 | 295 | ||
| 297 | /* Handle obsolete-style parameters */ | 296 | /* Handle obsolete-style parameters */ |
| 298 | if (obsolete_checksetup(param)) | 297 | if (obsolete_checksetup(param)) |
| 299 | return 0; | 298 | return 0; |
| 300 | 299 | ||
| 301 | /* Unused module parameter. */ | 300 | /* Unused module parameter. */ |
| 302 | if (strchr(param, '.') && (!val || strchr(param, '.') < val)) | 301 | if (strnchr(param, len, '.')) |
| 303 | return 0; | 302 | return 0; |
| 304 | 303 | ||
| 305 | if (panic_later) | 304 | if (panic_later) |
| @@ -313,7 +312,7 @@ static int __init unknown_bootoption(char *param, char *val, · 7 unmodified lines | |||
| 313 | panic_later = "env"; | 312 | panic_later = "env"; |
| 314 | panic_param = param; | 313 | panic_param = param; |
| 315 | } | 314 | } |
| 316 | if (!strncmp(param, envp_init[i], val - param)) | 315 | if (!strncmp(param, envp_init[i], len+1)) |
| 317 | break; | 316 | break; |
| 318 | } | 317 | } |
| 319 | envp_init[i] = param; | 318 | envp_init[i] = param; |
| @@ -991,6 +990,12 @@ static const char *initcall_level_names[] __initdata = { · 671 unmodified lines | |||
| 991 | "late", | 990 | "late", |
| 992 | }; | 991 | }; |
| 993 | 992 | ||
| 993 | static int __init ignore_unknown_bootoption(char *param, char *val, | ||
| 994 | const char *unused, void *arg) | ||
| 995 | { | ||
| 996 | return 0; | ||
| 997 | } | ||
| 998 | |||
| 994 | static void __init do_initcall_level(int level) | 999 | static void __init do_initcall_level(int level) |
| 995 | { | 1000 | { |
| 996 | initcall_entry_t *fn; | 1001 | initcall_entry_t *fn; |
| @@ -1000,7 +1005,7 @@ static void __init do_initcall_level(int level) · 3 unmodified lines | |||
| 1000 | initcall_command_line, __start___param, | 1005 | initcall_command_line, __start___param, |
| 1001 | __stop___param - __start___param, | 1006 | __stop___param - __start___param, |
| 1002 | level, level, | 1007 | level, level, |
| 1003 | NULL, &repair_env_string); | 1008 | NULL, ignore_unknown_bootoption); |
| 1004 | 1009 | ||
| 1005 | trace_initcall_level(initcall_level_names[level]); | 1010 | trace_initcall_level(initcall_level_names[level]); |
| 1006 | for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++) | 1011 | for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++) |
| @@ -1043,8 +1048,16 @@ static void __init do_pre_smp_initcalls(void) · 36 unmodified lines | |||
| 1043 | 1048 | ||
| 1044 | static int run_init_process(const char *init_filename) | 1049 | static int run_init_process(const char *init_filename) |
| 1045 | { | 1050 | { |
| 1051 | const char *const *p; | ||
| 1052 | |||
| 1046 | argv_init[0] = init_filename; | 1053 | argv_init[0] = init_filename; |
| 1047 | pr_info("Run %s as init process\n", init_filename); | 1054 | pr_info("Run %s as init process\n", init_filename); |
| 1055 | pr_debug(" with arguments:\n"); | ||
| 1056 | for (p = argv_init; *p; p++) | ||
| 1057 | pr_debug(" %s\n", *p); | ||
| 1058 | pr_debug(" with environment:\n"); | ||
| 1059 | for (p = envp_init; *p; p++) | ||
| 1060 | pr_debug(" %s\n", *p); | ||
| 1048 | return do_execve(getname_kernel(init_filename), | 1061 | return do_execve(getname_kernel(init_filename), |
| 1049 | (const char __user *const __user *)argv_init, | 1062 | (const char __user *const __user *)argv_init, |
| 1050 | (const char __user *const __user *)envp_init); | 1063 | (const char __user *const __user *)envp_init); |
| @@ -1091,6 +1104,11 @@ static void mark_readonly(void) · 40 unmodified lines | |||
| 1091 | } else | 1104 | } else |
| 1092 | pr_info("Kernel memory protection disabled.\n"); | 1105 | pr_info("Kernel memory protection disabled.\n"); |
| 1093 | } | 1106 | } |
| 1107 | #elif defined(CONFIG_ARCH_HAS_STRICT_KERNEL_RWX) | ||
| 1108 | static inline void mark_readonly(void) | ||
| 1109 | { | ||
| 1110 | pr_warn("Kernel memory protection not selected by kernel config.\n"); | ||
| 1111 | } | ||
| 1094 | #else | 1112 | #else |
| 1095 | static inline void mark_readonly(void) | 1113 | static inline void mark_readonly(void) |
| 1096 | { | 1114 | { |
| @@ -27,6 +27,7 @@ KCOV_INSTRUMENT_softirq.o := n · 26 unmodified lines | |||
| 27 | # and produce insane amounts of uninteresting coverage. | 27 | # and produce insane amounts of uninteresting coverage. |
| 28 | KCOV_INSTRUMENT_module.o := n | 28 | KCOV_INSTRUMENT_module.o := n |
| 29 | KCOV_INSTRUMENT_extable.o := n | 29 | KCOV_INSTRUMENT_extable.o := n |
| 30 | KCOV_INSTRUMENT_stacktrace.o := n | ||
| 30 | # Don't self-instrument. | 31 | # Don't self-instrument. |
| 31 | KCOV_INSTRUMENT_kcov.o := n | 32 | KCOV_INSTRUMENT_kcov.o := n |
| 32 | KASAN_SANITIZE_kcov.o := n | 33 | KASAN_SANITIZE_kcov.o := n |
| @@ -278,6 +278,13 @@ config ZLIB_DEFLATE · 277 unmodified lines | |||
| 278 | tristate | 278 | tristate |
| 279 | select BITREVERSE | 279 | select BITREVERSE |
| 280 | 280 | ||
| 281 | config ZLIB_DFLTCC | ||
| 282 | def_bool y | ||
| 283 | depends on S390 | ||
| 284 | prompt "Enable s390x DEFLATE CONVERSION CALL support for kernel zlib" | ||
| 285 | help | ||
| 286 | Enable s390x hardware support for zlib in the kernel. | ||
| 287 | |||
| 281 | config LZO_COMPRESS | 288 | config LZO_COMPRESS |
| 282 | tristate | 289 | tristate |
| 283 | 290 | ||
| @@ -16,6 +16,7 @@ KCOV_INSTRUMENT_rbtree.o := n · 15 unmodified lines | |||
| 16 | KCOV_INSTRUMENT_list_debug.o := n | 16 | KCOV_INSTRUMENT_list_debug.o := n |
| 17 | KCOV_INSTRUMENT_debugobjects.o := n | 17 | KCOV_INSTRUMENT_debugobjects.o := n |
| 18 | KCOV_INSTRUMENT_dynamic_debug.o := n | 18 | KCOV_INSTRUMENT_dynamic_debug.o := n |
| 19 | KCOV_INSTRUMENT_fault-inject.o := n | ||
| 19 | 20 | ||
| 20 | # Early boot use of cmdline, don't instrument it | 21 | # Early boot use of cmdline, don't instrument it |
| 21 | ifdef CONFIG_AMD_MEM_ENCRYPT | 22 | ifdef CONFIG_AMD_MEM_ENCRYPT |
| @@ -140,6 +141,7 @@ obj-$(CONFIG_842_COMPRESS) += 842/ · 118 unmodified lines | |||
| 140 | obj-$(CONFIG_842_DECOMPRESS) += 842/ | 141 | obj-$(CONFIG_842_DECOMPRESS) += 842/ |
| 141 | obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate/ | 142 | obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate/ |
| 142 | obj-$(CONFIG_ZLIB_DEFLATE) += zlib_deflate/ | 143 | obj-$(CONFIG_ZLIB_DEFLATE) += zlib_deflate/ |
| 144 | obj-$(CONFIG_ZLIB_DFLTCC) += zlib_dfltcc/ | ||
| 143 | obj-$(CONFIG_REED_SOLOMON) += reed_solomon/ | 145 | obj-$(CONFIG_REED_SOLOMON) += reed_solomon/ |
| 144 | obj-$(CONFIG_BCH) += bch.o | 146 | obj-$(CONFIG_BCH) += bch.o |
| 145 | obj-$(CONFIG_LZO_COMPRESS) += lzo/ | 147 | obj-$(CONFIG_LZO_COMPRESS) += lzo/ |
| @@ -10,6 +10,10 @@ · 9 unmodified lines | |||
| 10 | #include "zlib_inflate/inftrees.c" | 10 | #include "zlib_inflate/inftrees.c" |
| 11 | #include "zlib_inflate/inffast.c" | 11 | #include "zlib_inflate/inffast.c" |
| 12 | #include "zlib_inflate/inflate.c" | 12 | #include "zlib_inflate/inflate.c" |
| 13 | #ifdef CONFIG_ZLIB_DFLTCC | ||
| 14 | #include "zlib_dfltcc/dfltcc.c" | ||
| 15 | #include "zlib_dfltcc/dfltcc_inflate.c" | ||
| 16 | #endif | ||
| 13 | 17 | ||
| 14 | #else /* STATIC */ | 18 | #else /* STATIC */ |
| 15 | /* initramfs et al: linked */ | 19 | /* initramfs et al: linked */ |
| @@ -76,7 +80,12 @@ STATIC int INIT __gunzip(unsigned char *buf, long len, · 60 unmodified lines | |||
| 76 | } | 80 | } |
| 77 | 81 | ||
| 78 | strm->workspace = malloc(flush ? zlib_inflate_workspacesize() : | 82 | strm->workspace = malloc(flush ? zlib_inflate_workspacesize() : |
| 83 | #ifdef CONFIG_ZLIB_DFLTCC | ||
| 84 | /* Always allocate the full workspace for DFLTCC */ | ||
| 85 | zlib_inflate_workspacesize()); | ||
| 86 | #else | ||
| 79 | sizeof(struct inflate_state)); | 87 | sizeof(struct inflate_state)); |
| 88 | #endif | ||
| 80 | if (strm->workspace == NULL) { | 89 | if (strm->workspace == NULL) { |
| 81 | error("Out of memory while allocating workspace"); | 90 | error("Out of memory while allocating workspace"); |
| 82 | goto gunzip_nomem4; | 91 | goto gunzip_nomem4; |
| @@ -123,10 +132,14 @@ STATIC int INIT __gunzip(unsigned char *buf, long len, · 40 unmodified lines | |||
| 123 | 132 | ||
| 124 | rc = zlib_inflateInit2(strm, -MAX_WBITS); | 133 | rc = zlib_inflateInit2(strm, -MAX_WBITS); |
| 125 | 134 | ||
| 135 | #ifdef CONFIG_ZLIB_DFLTCC | ||
| 136 | /* Always keep the window for DFLTCC */ | ||
| 137 | #else | ||
| 126 | if (!flush) { | 138 | if (!flush) { |
| 127 | WS(strm)->inflate_state.wsize = 0; | 139 | WS(strm)->inflate_state.wsize = 0; |
| 128 | WS(strm)->inflate_state.window = NULL; | 140 | WS(strm)->inflate_state.window = NULL; |
| 129 | } | 141 | } |
| 142 | #endif | ||
| 130 | 143 | ||
| 131 | while (rc == Z_OK) { | 144 | while (rc == Z_OK) { |
| 132 | if (strm->avail_in == 0) { | 145 | if (strm->avail_in == 0) { |
| @@ -17,9 +17,9 @@ · 16 unmodified lines | |||
| 17 | #include <linux/export.h> | 17 | #include <linux/export.h> |
| 18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
| 19 | 19 | ||
| 20 | #if !defined(find_next_bit) || !defined(find_next_zero_bit) || \ | 20 | #if !defined(find_next_bit) || !defined(find_next_zero_bit) || \ |
| 21 | !defined(find_next_and_bit) | 21 | !defined(find_next_bit_le) || !defined(find_next_zero_bit_le) || \ |
| 22 | 22 | !defined(find_next_and_bit) | |
| 23 | /* | 23 | /* |
| 24 | * This is a common helper function for find_next_bit, find_next_zero_bit, and | 24 | * This is a common helper function for find_next_bit, find_next_zero_bit, and |
| 25 | * find_next_and_bit. The differences are: | 25 | * find_next_and_bit. The differences are: |
| @@ -27,11 +27,11 @@ · 1 unmodified line | |||
| 27 | * searching it for one bits. | 27 | * searching it for one bits. |
| 28 | * - The optional "addr2", which is anded with "addr1" if present. | 28 | * - The optional "addr2", which is anded with "addr1" if present. |
| 29 | */ | 29 | */ |
| 30 | static inline unsigned long _find_next_bit(const unsigned long *addr1, | 30 | static unsigned long _find_next_bit(const unsigned long *addr1, |
| 31 | const unsigned long *addr2, unsigned long nbits, | 31 | const unsigned long *addr2, unsigned long nbits, |
| 32 | unsigned long start, unsigned long invert) | 32 | unsigned long start, unsigned long invert, unsigned long le) |
| 33 | { | 33 | { |
| 34 | unsigned long tmp; | 34 | unsigned long tmp, mask; |
| 35 | 35 | ||
| 36 | if (unlikely(start >= nbits)) | 36 | if (unlikely(start >= nbits)) |
| 37 | return nbits; | 37 | return nbits; |
| @@ -42,7 +42,12 @@ static inline unsigned long _find_next_bit(const unsigned long *addr1, · 4 unmodified lines | |||
| 42 | tmp ^= invert; | 42 | tmp ^= invert; |
| 43 | 43 | ||
| 44 | /* Handle 1st word. */ | 44 | /* Handle 1st word. */ |
| 45 | tmp &= BITMAP_FIRST_WORD_MASK(start); | 45 | mask = BITMAP_FIRST_WORD_MASK(start); |
| 46 | if (le) | ||
| 47 | mask = swab(mask); | ||
| 48 | |||
| 49 | tmp &= mask; | ||
| 50 | |||
| 46 | start = round_down(start, BITS_PER_LONG); | 51 | start = round_down(start, BITS_PER_LONG); |
| 47 | 52 | ||
| 48 | while (!tmp) { | 53 | while (!tmp) { |
| @@ -56,6 +61,9 @@ static inline unsigned long _find_next_bit(const unsigned long *addr1, · 7 unmodified lines | |||
| 56 | tmp ^= invert; | 61 | tmp ^= invert; |
| 57 | } | 62 | } |
| 58 | 63 | ||
| 64 | if (le) | ||
| 65 | tmp = swab(tmp); | ||
| 66 | |||
| 59 | return min(start + __ffs(tmp), nbits); | 67 | return min(start + __ffs(tmp), nbits); |
| 60 | } | 68 | } |
| 61 | #endif | 69 | #endif |
| @@ -67,7 +75,7 @@ static inline unsigned long _find_next_bit(const unsigned long *addr1, · 5 unmodified lines | |||
| 67 | unsigned long find_next_bit(const unsigned long *addr, unsigned long size, | 75 | unsigned long find_next_bit(const unsigned long *addr, unsigned long size, |
| 68 | unsigned long offset) | 76 | unsigned long offset) |
| 69 | { | 77 | { |
| 70 | return _find_next_bit(addr, NULL, size, offset, 0UL); | 78 | return _find_next_bit(addr, NULL, size, offset, 0UL, 0); |
| 71 | } | 79 | } |
| 72 | EXPORT_SYMBOL(find_next_bit); | 80 | EXPORT_SYMBOL(find_next_bit); |
| 73 | #endif | 81 | #endif |
| @@ -76,7 +84,7 @@ EXPORT_SYMBOL(find_next_bit); · 2 unmodified lines | |||
| 76 | unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, | 84 | unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, |
| 77 | unsigned long offset) | 85 | unsigned long offset) |
| 78 | { | 86 | { |
| 79 | return _find_next_bit(addr, NULL, size, offset, ~0UL); | 87 | return _find_next_bit(addr, NULL, size, offset, ~0UL, 0); |
| 80 | } | 88 | } |
| 81 | EXPORT_SYMBOL(find_next_zero_bit); | 89 | EXPORT_SYMBOL(find_next_zero_bit); |
| 82 | #endif | 90 | #endif |
| @@ -86,7 +94,7 @@ unsigned long find_next_and_bit(const unsigned long *addr1, · 3 unmodified lines | |||
| 86 | const unsigned long *addr2, unsigned long size, | 94 | const unsigned long *addr2, unsigned long size, |
| 87 | unsigned long offset) | 95 | unsigned long offset) |
| 88 | { | 96 | { |
| 89 | return _find_next_bit(addr1, addr2, size, offset, 0UL); | 97 | return _find_next_bit(addr1, addr2, size, offset, 0UL, 0); |
| 90 | } | 98 | } |
| 91 | EXPORT_SYMBOL(find_next_and_bit); | 99 | EXPORT_SYMBOL(find_next_and_bit); |
| 92 | #endif | 100 | #endif |
| @@ -149,57 +157,11 @@ EXPORT_SYMBOL(find_last_bit); · 56 unmodified lines | |||
| 149 | 157 | ||
| 150 | #ifdef __BIG_ENDIAN | 158 | #ifdef __BIG_ENDIAN |
| 151 | 159 | ||
| 152 | /* include/linux/byteorder does not support "unsigned long" type */ | ||
| 153 | static inline unsigned long ext2_swab(const unsigned long y) | ||
| 154 | { | ||
| 155 | #if BITS_PER_LONG == 64 | ||
| 156 | return (unsigned long) __swab64((u64) y); | ||
| 157 | #elif BITS_PER_LONG == 32 | ||
| 158 | return (unsigned long) __swab32((u32) y); | ||
| 159 | #else | ||
| 160 | #error BITS_PER_LONG not defined | ||
| 161 | #endif | ||
| 162 | } | ||
| 163 | |||
| 164 | #if !defined(find_next_bit_le) || !defined(find_next_zero_bit_le) | ||
| 165 | static inline unsigned long _find_next_bit_le(const unsigned long *addr1, | ||
| 166 | const unsigned long *addr2, unsigned long nbits, | ||
| 167 | unsigned long start, unsigned long invert) | ||
| 168 | { | ||
| 169 | unsigned long tmp; | ||
| 170 | |||
| 171 | if (unlikely(start >= nbits)) | ||
| 172 | return nbits; | ||
| 173 | |||
| 174 | tmp = addr1[start / BITS_PER_LONG]; | ||
| 175 | if (addr2) | ||
| 176 | tmp &= addr2[start / BITS_PER_LONG]; | ||
| 177 | tmp ^= invert; | ||
| 178 | |||
| 179 | /* Handle 1st word. */ | ||
| 180 | tmp &= ext2_swab(BITMAP_FIRST_WORD_MASK(start)); | ||
| 181 | start = round_down(start, BITS_PER_LONG); | ||
| 182 | |||
| 183 | while (!tmp) { | ||
| 184 | start += BITS_PER_LONG; | ||
| 185 | if (start >= nbits) | ||
| 186 | return nbits; | ||
| 187 | |||
| 188 | tmp = addr1[start / BITS_PER_LONG]; | ||
| 189 | if (addr2) | ||
| 190 | tmp &= addr2[start / BITS_PER_LONG]; | ||
| 191 | tmp ^= invert; | ||
| 192 | } | ||
| 193 | |||
| 194 | return min(start + __ffs(ext2_swab(tmp)), nbits); | ||
| 195 | } | ||
| 196 | #endif | ||
| 197 | |||
| 198 | #ifndef find_next_zero_bit_le | 160 | #ifndef find_next_zero_bit_le |
| 199 | unsigned long find_next_zero_bit_le(const void *addr, unsigned | 161 | unsigned long find_next_zero_bit_le(const void *addr, unsigned |
| 200 | long size, unsigned long offset) | 162 | long size, unsigned long offset) |
| 201 | { | 163 | { |
| 202 | return _find_next_bit_le(addr, NULL, size, offset, ~0UL); | 164 | return _find_next_bit(addr, NULL, size, offset, ~0UL, 1); |
| 203 | } | 165 | } |
| 204 | EXPORT_SYMBOL(find_next_zero_bit_le); | 166 | EXPORT_SYMBOL(find_next_zero_bit_le); |
| 205 | #endif | 167 | #endif |
| @@ -208,7 +170,7 @@ EXPORT_SYMBOL(find_next_zero_bit_le); · 2 unmodified lines | |||
| 208 | unsigned long find_next_bit_le(const void *addr, unsigned | 170 | unsigned long find_next_bit_le(const void *addr, unsigned |
| 209 | long size, unsigned long offset) | 171 | long size, unsigned long offset) |
| 210 | { | 172 | { |
| 211 | return _find_next_bit_le(addr, NULL, size, offset, 0UL); | 173 | return _find_next_bit(addr, NULL, size, offset, 0UL, 1); |
| 212 | } | 174 | } |
| 213 | EXPORT_SYMBOL(find_next_bit_le); | 175 | EXPORT_SYMBOL(find_next_bit_le); |
| 214 | #endif | 176 | #endif |
| @@ -311,7 +311,7 @@ int __sg_alloc_table(struct sg_table *table, unsigned int nents, · 310 unmodified lines | |||
| 311 | if (prv) | 311 | if (prv) |
| 312 | table->nents = ++table->orig_nents; | 312 | table->nents = ++table->orig_nents; |
| 313 | 313 | ||
| 314 | return -ENOMEM; | 314 | return -ENOMEM; |
| 315 | } | 315 | } |
| 316 | 316 | ||
| 317 | sg_init_table(sg, alloc_size); | 317 | sg_init_table(sg, alloc_size); |
| @@ -275,22 +275,23 @@ static void __init test_copy(void) · 274 unmodified lines | |||
| 275 | static void __init test_replace(void) | 275 | static void __init test_replace(void) |
| 276 | { | 276 | { |
| 277 | unsigned int nbits = 64; | 277 | unsigned int nbits = 64; |
| 278 | unsigned int nlongs = DIV_ROUND_UP(nbits, BITS_PER_LONG); | ||
| 278 | DECLARE_BITMAP(bmap, 1024); | 279 | DECLARE_BITMAP(bmap, 1024); |
| 279 | 280 | ||
| 280 | bitmap_zero(bmap, 1024); | 281 | bitmap_zero(bmap, 1024); |
| 281 | bitmap_replace(bmap, &exp2[0], &exp2[1], exp2_to_exp3_mask, nbits); | 282 | bitmap_replace(bmap, &exp2[0 * nlongs], &exp2[1 * nlongs], exp2_to_exp3_mask, nbits); |
| 282 | expect_eq_bitmap(bmap, exp3_0_1, nbits); | 283 | expect_eq_bitmap(bmap, exp3_0_1, nbits); |
| 283 | 284 | ||
| 284 | bitmap_zero(bmap, 1024); | 285 | bitmap_zero(bmap, 1024); |
| 285 | bitmap_replace(bmap, &exp2[1], &exp2[0], exp2_to_exp3_mask, nbits); | 286 | bitmap_replace(bmap, &exp2[1 * nlongs], &exp2[0 * nlongs], exp2_to_exp3_mask, nbits); |
| 286 | expect_eq_bitmap(bmap, exp3_1_0, nbits); | 287 | expect_eq_bitmap(bmap, exp3_1_0, nbits); |
| 287 | 288 | ||
| 288 | bitmap_fill(bmap, 1024); | 289 | bitmap_fill(bmap, 1024); |
| 289 | bitmap_replace(bmap, &exp2[0], &exp2[1], exp2_to_exp3_mask, nbits); | 290 | bitmap_replace(bmap, &exp2[0 * nlongs], &exp2[1 * nlongs], exp2_to_exp3_mask, nbits); |
| 290 | expect_eq_bitmap(bmap, exp3_0_1, nbits); | 291 | expect_eq_bitmap(bmap, exp3_0_1, nbits); |
| 291 | 292 | ||
| 292 | bitmap_fill(bmap, 1024); | 293 | bitmap_fill(bmap, 1024); |
| 293 | bitmap_replace(bmap, &exp2[1], &exp2[0], exp2_to_exp3_mask, nbits); | 294 | bitmap_replace(bmap, &exp2[1 * nlongs], &exp2[0 * nlongs], exp2_to_exp3_mask, nbits); |
| 294 | expect_eq_bitmap(bmap, exp3_1_0, nbits); | 295 | expect_eq_bitmap(bmap, exp3_1_0, nbits); |
| 295 | } | 296 | } |
| 296 | 297 | ||
| @@ -158,6 +158,7 @@ static noinline void __init kmalloc_oob_krealloc_more(void) · 157 unmodified lines | |||
| 158 | if (!ptr1 || !ptr2) { | 158 | if (!ptr1 || !ptr2) { |
| 159 | pr_err("Allocation failed\n"); | 159 | pr_err("Allocation failed\n"); |
| 160 | kfree(ptr1); | 160 | kfree(ptr1); |
| 161 | kfree(ptr2); | ||
| 161 | return; | 162 | return; |
| 162 | } | 163 | } |
| 163 | 164 | ||
| @@ -52,16 +52,19 @@ · 51 unmodified lines | |||
| 52 | #include <linux/zutil.h> | 52 | #include <linux/zutil.h> |
| 53 | #include "defutil.h" | 53 | #include "defutil.h" |
| 54 | 54 | ||
| 55 | /* architecture-specific bits */ | ||
| 56 | #ifdef CONFIG_ZLIB_DFLTCC | ||
| 57 | # include "../zlib_dfltcc/dfltcc.h" | ||
| 58 | #else | ||
| 59 | #define DEFLATE_RESET_HOOK(strm) do {} while (0) | ||
| 60 | #define DEFLATE_HOOK(strm, flush, bstate) 0 | ||
| 61 | #define DEFLATE_NEED_CHECKSUM(strm) 1 | ||
| 62 | #define DEFLATE_DFLTCC_ENABLED() 0 | ||
| 63 | #endif | ||
| 55 | 64 | ||
| 56 | /* =========================================================================== | 65 | /* =========================================================================== |
| 57 | * Function prototypes. | 66 | * Function prototypes. |
| 58 | */ | 67 | */ |
| 59 | typedef enum { | ||
| 60 | need_more, /* block not completed, need more input or more output */ | ||
| 61 | block_done, /* block flush performed */ | ||
| 62 | finish_started, /* finish started, need only more output at next deflate */ | ||
| 63 | finish_done /* finish done, accept no more input or output */ | ||
| 64 | } block_state; | ||
| 65 | 68 | ||
| 66 | typedef block_state (*compress_func) (deflate_state *s, int flush); | 69 | typedef block_state (*compress_func) (deflate_state *s, int flush); |
| 67 | /* Compression function. Returns the block state after the call. */ | 70 | /* Compression function. Returns the block state after the call. */ |
| @@ -72,7 +75,6 @@ static block_state deflate_fast (deflate_state *s, int flush); · 4 unmodified lines | |||
| 72 | static block_state deflate_slow (deflate_state *s, int flush); | 75 | static block_state deflate_slow (deflate_state *s, int flush); |
| 73 | static void lm_init (deflate_state *s); | 76 | static void lm_init (deflate_state *s); |
| 74 | static void putShortMSB (deflate_state *s, uInt b); | 77 | static void putShortMSB (deflate_state *s, uInt b); |
| 75 | static void flush_pending (z_streamp strm); | ||
| 76 | static int read_buf (z_streamp strm, Byte *buf, unsigned size); | 78 | static int read_buf (z_streamp strm, Byte *buf, unsigned size); |
| 77 | static uInt longest_match (deflate_state *s, IPos cur_match); | 79 | static uInt longest_match (deflate_state *s, IPos cur_match); |
| 78 | 80 | ||
| @@ -98,6 +100,25 @@ static void check_match (deflate_state *s, IPos start, IPos match, · 19 unmodified lines | |||
| 98 | * See deflate.c for comments about the MIN_MATCH+1. | 100 | * See deflate.c for comments about the MIN_MATCH+1. |
| 99 | */ | 101 | */ |
| 100 | 102 | ||
| 103 | /* Workspace to be allocated for deflate processing */ | ||
| 104 | typedef struct deflate_workspace { | ||
| 105 | /* State memory for the deflator */ | ||
| 106 | deflate_state deflate_memory; | ||
| 107 | #ifdef CONFIG_ZLIB_DFLTCC | ||
| 108 | /* State memory for s390 hardware deflate */ | ||
| 109 | struct dfltcc_state dfltcc_memory; | ||
| 110 | #endif | ||
| 111 | Byte *window_memory; | ||
| 112 | Pos *prev_memory; | ||
| 113 | Pos *head_memory; | ||
| 114 | char *overlay_memory; | ||
| 115 | } deflate_workspace; | ||
| 116 | |||
| 117 | #ifdef CONFIG_ZLIB_DFLTCC | ||
| 118 | /* dfltcc_state must be doubleword aligned for DFLTCC call */ | ||
| 119 | static_assert(offsetof(struct deflate_workspace, dfltcc_memory) % 8 == 0); | ||
| 120 | #endif | ||
| 121 | |||
| 101 | /* Values for max_lazy_match, good_match and max_chain_length, depending on | 122 | /* Values for max_lazy_match, good_match and max_chain_length, depending on |
| 102 | * the desired pack level (0..9). The values given below have been tuned to | 123 | * the desired pack level (0..9). The values given below have been tuned to |
| 103 | * exclude worst case performance for pathological files. Better values may be | 124 | * exclude worst case performance for pathological files. Better values may be |
| @@ -207,7 +228,15 @@ int zlib_deflateInit2( · 103 unmodified lines | |||
| 207 | */ | 228 | */ |
| 208 | next = (char *) mem; | 229 | next = (char *) mem; |
| 209 | next += sizeof(*mem); | 230 | next += sizeof(*mem); |
| 231 | #ifdef CONFIG_ZLIB_DFLTCC | ||
| 232 | /* | ||
| 233 | * DFLTCC requires the window to be page aligned. | ||
| 234 | * Thus, we overallocate and take the aligned portion of the buffer. | ||
| 235 | */ | ||
| 236 | mem->window_memory = (Byte *) PTR_ALIGN(next, PAGE_SIZE); | ||
| 237 | #else | ||
| 210 | mem->window_memory = (Byte *) next; | 238 | mem->window_memory = (Byte *) next; |
| 239 | #endif | ||
| 211 | next += zlib_deflate_window_memsize(windowBits); | 240 | next += zlib_deflate_window_memsize(windowBits); |
| 212 | mem->prev_memory = (Pos *) next; | 241 | mem->prev_memory = (Pos *) next; |
| 213 | next += zlib_deflate_prev_memsize(windowBits); | 242 | next += zlib_deflate_prev_memsize(windowBits); |
| @@ -277,6 +306,8 @@ int zlib_deflateReset( · 63 unmodified lines | |||
| 277 | zlib_tr_init(s); | 306 | zlib_tr_init(s); |
| 278 | lm_init(s); | 307 | lm_init(s); |
| 279 | 308 | ||
| 309 | DEFLATE_RESET_HOOK(strm); | ||
| 310 | |||
| 280 | return Z_OK; | 311 | return Z_OK; |
| 281 | } | 312 | } |
| 282 | 313 | ||
| @@ -294,35 +325,6 @@ static void putShortMSB( · 11 unmodified lines | |||
| 294 | put_byte(s, (Byte)(b & 0xff)); | 325 | put_byte(s, (Byte)(b & 0xff)); |
| 295 | } | 326 | } |
| 296 | 327 | ||
| 297 | /* ========================================================================= | ||
| 298 | * Flush as much pending output as possible. All deflate() output goes | ||
| 299 | * through this function so some applications may wish to modify it | ||
| 300 | * to avoid allocating a large strm->next_out buffer and copying into it. | ||
| 301 | * (See also read_buf()). | ||
| 302 | */ | ||
| 303 | static void flush_pending( | ||
| 304 | z_streamp strm | ||
| 305 | ) | ||
| 306 | { | ||
| 307 | deflate_state *s = (deflate_state *) strm->state; | ||
| 308 | unsigned len = s->pending; | ||
| 309 | |||
| 310 | if (len > strm->avail_out) len = strm->avail_out; | ||
| 311 | if (len == 0) return; | ||
| 312 | |||
| 313 | if (strm->next_out != NULL) { | ||
| 314 | memcpy(strm->next_out, s->pending_out, len); | ||
| 315 | strm->next_out += len; | ||
| 316 | } | ||
| 317 | s->pending_out += len; | ||
| 318 | strm->total_out += len; | ||
| 319 | strm->avail_out -= len; | ||
| 320 | s->pending -= len; | ||
| 321 | if (s->pending == 0) { | ||
| 322 | s->pending_out = s->pending_buf; | ||
| 323 | } | ||
| 324 | } | ||
| 325 | |||
| 326 | /* ========================================================================= */ | 328 | /* ========================================================================= */ |
| 327 | int zlib_deflate( | 329 | int zlib_deflate( |
| 328 | z_streamp strm, | 330 | z_streamp strm, |
| @@ -404,7 +406,8 @@ int zlib_deflate( · 75 unmodified lines | |||
| 404 | (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { | 406 | (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { |
| 405 | block_state bstate; | 407 | block_state bstate; |
| 406 | 408 | ||
| 407 | bstate = (*(configuration_table[s->level].func))(s, flush); | 409 | bstate = DEFLATE_HOOK(strm, flush, &bstate) ? bstate : |
| 410 | (*(configuration_table[s->level].func))(s, flush); | ||
| 408 | 411 | ||
| 409 | if (bstate == finish_started || bstate == finish_done) { | 412 | if (bstate == finish_started || bstate == finish_done) { |
| 410 | s->status = FINISH_STATE; | 413 | s->status = FINISH_STATE; |
| @@ -503,7 +506,8 @@ static int read_buf( · 92 unmodified lines | |||
| 503 | 506 | ||
| 504 | strm->avail_in -= len; | 507 | strm->avail_in -= len; |
| 505 | 508 | ||
| 506 | if (!((deflate_state *)(strm->state))->noheader) { | 509 | if (!DEFLATE_NEED_CHECKSUM(strm)) {} |
| 510 | else if (!((deflate_state *)(strm->state))->noheader) { | ||
| 507 | strm->adler = zlib_adler32(strm->adler, strm->next_in, len); | 511 | strm->adler = zlib_adler32(strm->adler, strm->next_in, len); |
| 508 | } | 512 | } |
| 509 | memcpy(buf, strm->next_in, len); | 513 | memcpy(buf, strm->next_in, len); |
| @@ -1135,3 +1139,8 @@ int zlib_deflate_workspacesize(int windowBits, int memLevel) · 625 unmodified lines | |||
| 1135 | + zlib_deflate_head_memsize(memLevel) | 1139 | + zlib_deflate_head_memsize(memLevel) |
| 1136 | + zlib_deflate_overlay_memsize(memLevel); | 1140 | + zlib_deflate_overlay_memsize(memLevel); |
| 1137 | } | 1141 | } |
| 1142 | |||
| 1143 | int zlib_deflate_dfltcc_enabled(void) | ||
| 1144 | { | ||
| 1145 | return DEFLATE_DFLTCC_ENABLED(); | ||
| 1146 | } | ||
| @@ -12,6 +12,7 @@ · 11 unmodified lines | |||
| 12 | #include <linux/zlib.h> | 12 | #include <linux/zlib.h> |
| 13 | 13 | ||
| 14 | EXPORT_SYMBOL(zlib_deflate_workspacesize); | 14 | EXPORT_SYMBOL(zlib_deflate_workspacesize); |
| 15 | EXPORT_SYMBOL(zlib_deflate_dfltcc_enabled); | ||
| 15 | EXPORT_SYMBOL(zlib_deflate); | 16 | EXPORT_SYMBOL(zlib_deflate); |
| 16 | EXPORT_SYMBOL(zlib_deflateInit2); | 17 | EXPORT_SYMBOL(zlib_deflateInit2); |
| 17 | EXPORT_SYMBOL(zlib_deflateEnd); | 18 | EXPORT_SYMBOL(zlib_deflateEnd); |
| @@ -76,11 +76,6 @@ static const uch bl_order[BL_CODES] · 75 unmodified lines | |||
| 76 | * probability, to avoid transmitting the lengths for unused bit length codes. | 76 | * probability, to avoid transmitting the lengths for unused bit length codes. |
| 77 | */ | 77 | */ |
| 78 | 78 | ||
| 79 | #define Buf_size (8 * 2*sizeof(char)) | ||
| 80 | /* Number of bits used within bi_buf. (bi_buf might be implemented on | ||
| 81 | * more than 16 bits on some systems.) | ||
| 82 | */ | ||
| 83 | |||
| 84 | /* =========================================================================== | 79 | /* =========================================================================== |
| 85 | * Local data. These are initialized only once. | 80 | * Local data. These are initialized only once. |
| 86 | */ | 81 | */ |
| @@ -147,7 +142,6 @@ static void send_all_trees (deflate_state *s, int lcodes, int dcodes, · 60 unmodified lines | |||
| 147 | static void compress_block (deflate_state *s, ct_data *ltree, | 142 | static void compress_block (deflate_state *s, ct_data *ltree, |
| 148 | ct_data *dtree); | 143 | ct_data *dtree); |
| 149 | static void set_data_type (deflate_state *s); | 144 | static void set_data_type (deflate_state *s); |
| 150 | static void bi_windup (deflate_state *s); | ||
| 151 | static void bi_flush (deflate_state *s); | 145 | static void bi_flush (deflate_state *s); |
| 152 | static void copy_block (deflate_state *s, char *buf, unsigned len, | 146 | static void copy_block (deflate_state *s, char *buf, unsigned len, |
| 153 | int header); | 147 | int header); |
| @@ -169,54 +163,6 @@ static void copy_block (deflate_state *s, char *buf, unsigned len, · 15 unmodified lines | |||
| 169 | * used. | 163 | * used. |
| 170 | */ | 164 | */ |
| 171 | 165 | ||
| 172 | /* =========================================================================== | ||
| 173 | * Send a value on a given number of bits. | ||
| 174 | * IN assertion: length <= 16 and value fits in length bits. | ||
| 175 | */ | ||
| 176 | #ifdef DEBUG_ZLIB | ||
| 177 | static void send_bits (deflate_state *s, int value, int length); | ||
| 178 | |||
| 179 | static void send_bits( | ||
| 180 | deflate_state *s, | ||
| 181 | int value, /* value to send */ | ||
| 182 | int length /* number of bits */ | ||
| 183 | ) | ||
| 184 | { | ||
| 185 | Tracevv((stderr," l %2d v %4x ", length, value)); | ||
| 186 | Assert(length > 0 && length <= 15, "invalid length"); | ||
| 187 | s->bits_sent += (ulg)length; | ||
| 188 | |||
| 189 | /* If not enough room in bi_buf, use (valid) bits from bi_buf and | ||
| 190 | * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) | ||
| 191 | * unused bits in value. | ||
| 192 | */ | ||
| 193 | if (s->bi_valid > (int)Buf_size - length) { | ||
| 194 | s->bi_buf |= (value << s->bi_valid); | ||
| 195 | put_short(s, s->bi_buf); | ||
| 196 | s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); | ||
| 197 | s->bi_valid += length - Buf_size; | ||
| 198 | } else { | ||
| 199 | s->bi_buf |= value << s->bi_valid; | ||
| 200 | s->bi_valid += length; | ||
| 201 | } | ||
| 202 | } | ||
| 203 | #else /* !DEBUG_ZLIB */ | ||
| 204 | |||
| 205 | #define send_bits(s, value, length) \ | ||
| 206 | { int len = length;\ | ||
| 207 | if (s->bi_valid > (int)Buf_size - len) {\ | ||
| 208 | int val = value;\ | ||
| 209 | s->bi_buf |= (val << s->bi_valid);\ | ||
| 210 | put_short(s, s->bi_buf);\ | ||
| 211 | s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ | ||
| 212 | s->bi_valid += len - Buf_size;\ | ||
| 213 | } else {\ | ||
| 214 | s->bi_buf |= (value) << s->bi_valid;\ | ||
| 215 | s->bi_valid += len;\ | ||
| 216 | }\ | ||
| 217 | } | ||
| 218 | #endif /* DEBUG_ZLIB */ | ||
| 219 | |||
| 220 | /* =========================================================================== | 166 | /* =========================================================================== |
| 221 | * Initialize the various 'constant' tables. In a multi-threaded environment, | 167 | * Initialize the various 'constant' tables. In a multi-threaded environment, |
| 222 | * this function may be called by two threads concurrently, but this is | 168 | * this function may be called by two threads concurrently, but this is |
| @@ -1,5 +1,7 @@ | |||
| 1 | #ifndef DEFUTIL_H | ||
| 2 | #define DEFUTIL_H | ||
| 1 | 3 | ||
| 2 | 4 | #include <linux/zutil.h> | |
| 3 | 5 | ||
| 4 | #define Assert(err, str) | 6 | #define Assert(err, str) |
| 5 | #define Trace(dummy) | 7 | #define Trace(dummy) |
| @@ -238,17 +240,13 @@ typedef struct deflate_state { · 232 unmodified lines | |||
| 238 | 240 | ||
| 239 | } deflate_state; | 241 | } deflate_state; |
| 240 | 242 | ||
| 241 | typedef struct deflate_workspace { | 243 | #ifdef CONFIG_ZLIB_DFLTCC |
| 242 | /* State memory for the deflator */ | 244 | #define zlib_deflate_window_memsize(windowBits) \ |
| 243 | deflate_state deflate_memory; | 245 | (2 * (1 << (windowBits)) * sizeof(Byte) + PAGE_SIZE) |
| 244 | Byte *window_memory; | 246 | #else |
| 245 | Pos *prev_memory; | ||
| 246 | Pos *head_memory; | ||
| 247 | char *overlay_memory; | ||
| 248 | } deflate_workspace; | ||
| 249 | |||
| 250 | #define zlib_deflate_window_memsize(windowBits) \ | 247 | #define zlib_deflate_window_memsize(windowBits) \ |
| 251 | (2 * (1 << (windowBits)) * sizeof(Byte)) | 248 | (2 * (1 << (windowBits)) * sizeof(Byte)) |
| 249 | #endif | ||
| 252 | #define zlib_deflate_prev_memsize(windowBits) \ | 250 | #define zlib_deflate_prev_memsize(windowBits) \ |
| 253 | ((1 << (windowBits)) * sizeof(Pos)) | 251 | ((1 << (windowBits)) * sizeof(Pos)) |
| 254 | #define zlib_deflate_head_memsize(memLevel) \ | 252 | #define zlib_deflate_head_memsize(memLevel) \ |
| @@ -292,6 +290,24 @@ void zlib_tr_stored_type_only (deflate_state *); · 37 unmodified lines | |||
| 292 | put_byte(s, (uch)((ush)(w) >> 8)); \ | 290 | put_byte(s, (uch)((ush)(w) >> 8)); \ |
| 293 | } | 291 | } |
| 294 | 292 | ||
| 293 | /* =========================================================================== | ||
| 294 | * Reverse the first len bits of a code, using straightforward code (a faster | ||
| 295 | * method would use a table) | ||
| 296 | * IN assertion: 1 <= len <= 15 | ||
| 297 | */ | ||
| 298 | static inline unsigned bi_reverse( | ||
| 299 | unsigned code, /* the value to invert */ | ||
| 300 | int len /* its bit length */ | ||
| 301 | ) | ||
| 302 | { | ||
| 303 | register unsigned res = 0; | ||
| 304 | do { | ||
| 305 | res |= code & 1; | ||
| 306 | code >>= 1, res <<= 1; | ||
| 307 | } while (--len > 0); | ||
| 308 | return res >> 1; | ||
| 309 | } | ||
| 310 | |||
| 295 | /* =========================================================================== | 311 | /* =========================================================================== |
| 296 | * Flush the bit buffer, keeping at most 7 bits in it. | 312 | * Flush the bit buffer, keeping at most 7 bits in it. |
| 297 | */ | 313 | */ |
| @@ -325,3 +341,101 @@ static inline void bi_windup(deflate_state *s) · 27 unmodified lines | |||
| 325 | #endif | 341 | #endif |
| 326 | } | 342 | } |
| 327 | 343 | ||
| 344 | typedef enum { | ||
| 345 | need_more, /* block not completed, need more input or more output */ | ||
| 346 | block_done, /* block flush performed */ | ||
| 347 | finish_started, /* finish started, need only more output at next deflate */ | ||
| 348 | finish_done /* finish done, accept no more input or output */ | ||
| 349 | } block_state; | ||
| 350 | |||
| 351 | #define Buf_size (8 * 2*sizeof(char)) | ||
| 352 | /* Number of bits used within bi_buf. (bi_buf might be implemented on | ||
| 353 | * more than 16 bits on some systems.) | ||
| 354 | */ | ||
| 355 | |||
| 356 | /* =========================================================================== | ||
| 357 | * Send a value on a given number of bits. | ||
| 358 | * IN assertion: length <= 16 and value fits in length bits. | ||
| 359 | */ | ||
| 360 | #ifdef DEBUG_ZLIB | ||
| 361 | static void send_bits (deflate_state *s, int value, int length); | ||
| 362 | |||
| 363 | static void send_bits( | ||
| 364 | deflate_state *s, | ||
| 365 | int value, /* value to send */ | ||
| 366 | int length /* number of bits */ | ||
| 367 | ) | ||
| 368 | { | ||
| 369 | Tracevv((stderr," l %2d v %4x ", length, value)); | ||
| 370 | Assert(length > 0 && length <= 15, "invalid length"); | ||
| 371 | s->bits_sent += (ulg)length; | ||
| 372 | |||
| 373 | /* If not enough room in bi_buf, use (valid) bits from bi_buf and | ||
| 374 | * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) | ||
| 375 | * unused bits in value. | ||
| 376 | */ | ||
| 377 | if (s->bi_valid > (int)Buf_size - length) { | ||
| 378 | s->bi_buf |= (value << s->bi_valid); | ||
| 379 | put_short(s, s->bi_buf); | ||
| 380 | s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); | ||
| 381 | s->bi_valid += length - Buf_size; | ||
| 382 | } else { | ||
| 383 | s->bi_buf |= value << s->bi_valid; | ||
| 384 | s->bi_valid += length; | ||
| 385 | } | ||
| 386 | } | ||
| 387 | #else /* !DEBUG_ZLIB */ | ||
| 388 | |||
| 389 | #define send_bits(s, value, length) \ | ||
| 390 | { int len = length;\ | ||
| 391 | if (s->bi_valid > (int)Buf_size - len) {\ | ||
| 392 | int val = value;\ | ||
| 393 | s->bi_buf |= (val << s->bi_valid);\ | ||
| 394 | put_short(s, s->bi_buf);\ | ||
| 395 | s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ | ||
| 396 | s->bi_valid += len - Buf_size;\ | ||
| 397 | } else {\ | ||
| 398 | s->bi_buf |= (value) << s->bi_valid;\ | ||
| 399 | s->bi_valid += len;\ | ||
| 400 | }\ | ||
| 401 | } | ||
| 402 | #endif /* DEBUG_ZLIB */ | ||
| 403 | |||
| 404 | static inline void zlib_tr_send_bits( | ||
| 405 | deflate_state *s, | ||
| 406 | int value, | ||
| 407 | int length | ||
| 408 | ) | ||
| 409 | { | ||
| 410 | send_bits(s, value, length); | ||
| 411 | } | ||
| 412 | |||
| 413 | /* ========================================================================= | ||
| 414 | * Flush as much pending output as possible. All deflate() output goes | ||
| 415 | * through this function so some applications may wish to modify it | ||
| 416 | * to avoid allocating a large strm->next_out buffer and copying into it. | ||
| 417 | * (See also read_buf()). | ||
| 418 | */ | ||
| 419 | static inline void flush_pending( | ||
| 420 | z_streamp strm | ||
| 421 | ) | ||
| 422 | { | ||
| 423 | deflate_state *s = (deflate_state *) strm->state; | ||
| 424 | unsigned len = s->pending; | ||
| 425 | |||
| 426 | if (len > strm->avail_out) len = strm->avail_out; | ||
| 427 | if (len == 0) return; | ||
| 428 | |||
| 429 | if (strm->next_out != NULL) { | ||
| 430 | memcpy(strm->next_out, s->pending_out, len); | ||
| 431 | strm->next_out += len; | ||
| 432 | } | ||
| 433 | s->pending_out += len; | ||
| 434 | strm->total_out += len; | ||
| 435 | strm->avail_out -= len; | ||
| 436 | s->pending -= len; | ||
| 437 | if (s->pending == 0) { | ||
| 438 | s->pending_out = s->pending_buf; | ||
| 439 | } | ||
| 440 | } | ||
| 441 | #endif /* DEFUTIL_H */ | ||
| @@ -0,0 +1,11 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | # | ||
| 3 | # This is a modified version of zlib, which does all memory | ||
| 4 | # allocation ahead of time. | ||
| 5 | # | ||
| 6 | # This is the code for s390 zlib hardware support. | ||
| 7 | # | ||
| 8 | |||
| 9 | obj-$(CONFIG_ZLIB_DFLTCC) += zlib_dfltcc.o | ||
| 10 | |||
| 11 | zlib_dfltcc-objs := dfltcc.o dfltcc_deflate.o dfltcc_inflate.o dfltcc_syms.o | ||
| @@ -0,0 +1,55 @@ | |||
| 1 | // SPDX-License-Identifier: Zlib | ||
| 2 | /* dfltcc.c - SystemZ DEFLATE CONVERSION CALL support. */ | ||
| 3 | |||
| 4 | #include <linux/zutil.h> | ||
| 5 | #include "dfltcc_util.h" | ||
| 6 | #include "dfltcc.h" | ||
| 7 | |||
| 8 | char *oesc_msg( | ||
| 9 | char *buf, | ||
| 10 | int oesc | ||
| 11 | ) | ||
| 12 | { | ||
| 13 | if (oesc == 0x00) | ||
| 14 | return NULL; /* Successful completion */ | ||
| 15 | else { | ||
| 16 | #ifdef STATIC | ||
| 17 | return NULL; /* Ignore for pre-boot decompressor */ | ||
| 18 | #else | ||
| 19 | sprintf(buf, "Operation-Ending-Supplemental Code is 0x%.2X", oesc); | ||
| 20 | return buf; | ||
| 21 | #endif | ||
| 22 | } | ||
| 23 | } | ||
| 24 | |||
| 25 | void dfltcc_reset( | ||
| 26 | z_streamp strm, | ||
| 27 | uInt size | ||
| 28 | ) | ||
| 29 | { | ||
| 30 | struct dfltcc_state *dfltcc_state = | ||
| 31 | (struct dfltcc_state *)((char *)strm->state + size); | ||
| 32 | struct dfltcc_qaf_param *param = | ||
| 33 | (struct dfltcc_qaf_param *)&dfltcc_state->param; | ||
| 34 | |||
| 35 | /* Initialize available functions */ | ||
| 36 | if (is_dfltcc_enabled()) { | ||
| 37 | dfltcc(DFLTCC_QAF, param, NULL, NULL, NULL, NULL, NULL); | ||
| 38 | memmove(&dfltcc_state->af, param, sizeof(dfltcc_state->af)); | ||
| 39 | } else | ||
| 40 | memset(&dfltcc_state->af, 0, sizeof(dfltcc_state->af)); | ||
| 41 | |||
| 42 | /* Initialize parameter block */ | ||
| 43 | memset(&dfltcc_state->param, 0, sizeof(dfltcc_state->param)); | ||
| 44 | dfltcc_state->param.nt = 1; | ||
| 45 | |||
| 46 | /* Initialize tuning parameters */ | ||
| 47 | if (zlib_dfltcc_support == ZLIB_DFLTCC_FULL_DEBUG) | ||
| 48 | dfltcc_state->level_mask = DFLTCC_LEVEL_MASK_DEBUG; | ||
| 49 | else | ||
| 50 | dfltcc_state->level_mask = DFLTCC_LEVEL_MASK; | ||
| 51 | dfltcc_state->block_size = DFLTCC_BLOCK_SIZE; | ||
| 52 | dfltcc_state->block_threshold = DFLTCC_FIRST_FHT_BLOCK_SIZE; | ||
| 53 | dfltcc_state->dht_threshold = DFLTCC_DHT_MIN_SAMPLE_SIZE; | ||
| 54 | dfltcc_state->param.ribm = DFLTCC_RIBM; | ||
| 55 | } | ||
| @@ -0,0 +1,155 @@ | |||
| 1 | // SPDX-License-Identifier: Zlib | ||
| 2 | #ifndef DFLTCC_H | ||
| 3 | #define DFLTCC_H | ||
| 4 | |||
| 5 | #include "../zlib_deflate/defutil.h" | ||
| 6 | #include <asm/facility.h> | ||
| 7 | #include <asm/setup.h> | ||
| 8 | |||
| 9 | /* | ||
| 10 | * Tuning parameters. | ||
| 11 | */ | ||
| 12 | #define DFLTCC_LEVEL_MASK 0x2 /* DFLTCC compression for level 1 only */ | ||
| 13 | #define DFLTCC_LEVEL_MASK_DEBUG 0x3fe /* DFLTCC compression for all levels */ | ||
| 14 | #define DFLTCC_BLOCK_SIZE 1048576 | ||
| 15 | #define DFLTCC_FIRST_FHT_BLOCK_SIZE 4096 | ||
| 16 | #define DFLTCC_DHT_MIN_SAMPLE_SIZE 4096 | ||
| 17 | #define DFLTCC_RIBM 0 | ||
| 18 | |||
| 19 | #define DFLTCC_FACILITY 151 | ||
| 20 | |||
| 21 | /* | ||
| 22 | * Parameter Block for Query Available Functions. | ||
| 23 | */ | ||
| 24 | struct dfltcc_qaf_param { | ||
| 25 | char fns[16]; | ||
| 26 | char reserved1[8]; | ||
| 27 | char fmts[2]; | ||
| 28 | char reserved2[6]; | ||
| 29 | }; | ||
| 30 | |||
| 31 | static_assert(sizeof(struct dfltcc_qaf_param) == 32); | ||
| 32 | |||
| 33 | #define DFLTCC_FMT0 0 | ||
| 34 | |||
| 35 | /* | ||
| 36 | * Parameter Block for Generate Dynamic-Huffman Table, Compress and Expand. | ||
| 37 | */ | ||
| 38 | struct dfltcc_param_v0 { | ||
| 39 | uint16_t pbvn; /* Parameter-Block-Version Number */ | ||
| 40 | uint8_t mvn; /* Model-Version Number */ | ||
| 41 | uint8_t ribm; /* Reserved for IBM use */ | ||
| 42 | unsigned reserved32 : 31; | ||
| 43 | unsigned cf : 1; /* Continuation Flag */ | ||
| 44 | uint8_t reserved64[8]; | ||
| 45 | unsigned nt : 1; /* New Task */ | ||
| 46 | unsigned reserved129 : 1; | ||
| 47 | unsigned cvt : 1; /* Check Value Type */ | ||
| 48 | unsigned reserved131 : 1; | ||
| 49 | unsigned htt : 1; /* Huffman-Table Type */ | ||
| 50 | unsigned bcf : 1; /* Block-Continuation Flag */ | ||
| 51 | unsigned bcc : 1; /* Block Closing Control */ | ||
| 52 | unsigned bhf : 1; /* Block Header Final */ | ||
| 53 | unsigned reserved136 : 1; | ||
| 54 | unsigned reserved137 : 1; | ||
| 55 | unsigned dhtgc : 1; /* DHT Generation Control */ | ||
| 56 | unsigned reserved139 : 5; | ||
| 57 | unsigned reserved144 : 5; | ||
| 58 | unsigned sbb : 3; /* Sub-Byte Boundary */ | ||
| 59 | uint8_t oesc; /* Operation-Ending-Supplemental Code */ | ||
| 60 | unsigned reserved160 : 12; | ||
| 61 | unsigned ifs : 4; /* Incomplete-Function Status */ | ||
| 62 | uint16_t ifl; /* Incomplete-Function Length */ | ||
| 63 | uint8_t reserved192[8]; | ||
| 64 | uint8_t reserved256[8]; | ||
| 65 | uint8_t reserved320[4]; | ||
| 66 | uint16_t hl; /* History Length */ | ||
| 67 | unsigned reserved368 : 1; | ||
| 68 | uint16_t ho : 15; /* History Offset */ | ||
| 69 | uint32_t cv; /* Check Value */ | ||
| 70 | unsigned eobs : 15; /* End-of-block Symbol */ | ||
| 71 | unsigned reserved431: 1; | ||
| 72 | uint8_t eobl : 4; /* End-of-block Length */ | ||
| 73 | unsigned reserved436 : 12; | ||
| 74 | unsigned reserved448 : 4; | ||
| 75 | uint16_t cdhtl : 12; /* Compressed-Dynamic-Huffman Table | ||
| 76 | Length */ | ||
| 77 | uint8_t reserved464[6]; | ||
| 78 | uint8_t cdht[288]; | ||
| 79 | uint8_t reserved[32]; | ||
| 80 | uint8_t csb[1152]; | ||
| 81 | }; | ||
| 82 | |||
| 83 | static_assert(sizeof(struct dfltcc_param_v0) == 1536); | ||
| 84 | |||
| 85 | #define CVT_CRC32 0 | ||
| 86 | #define CVT_ADLER32 1 | ||
| 87 | #define HTT_FIXED 0 | ||
| 88 | #define HTT_DYNAMIC 1 | ||
| 89 | |||
| 90 | /* | ||
| 91 | * Extension of inflate_state and deflate_state for DFLTCC. | ||
| 92 | */ | ||
| 93 | struct dfltcc_state { | ||
| 94 | struct dfltcc_param_v0 param; /* Parameter block */ | ||
| 95 | struct dfltcc_qaf_param af; /* Available functions */ | ||
| 96 | uLong level_mask; /* Levels on which to use DFLTCC */ | ||
| 97 | uLong block_size; /* New block each X bytes */ | ||
| 98 | uLong block_threshold; /* New block after total_in > X */ | ||
| 99 | uLong dht_threshold; /* New block only if avail_in >= X */ | ||
| 100 | char msg[64]; /* Buffer for strm->msg */ | ||
| 101 | }; | ||
| 102 | |||
| 103 | /* Resides right after inflate_state or deflate_state */ | ||
| 104 | #define GET_DFLTCC_STATE(state) ((struct dfltcc_state *)((state) + 1)) | ||
| 105 | |||
| 106 | /* External functions */ | ||
| 107 | int dfltcc_can_deflate(z_streamp strm); | ||
| 108 | int dfltcc_deflate(z_streamp strm, | ||
| 109 | int flush, | ||
| 110 | block_state *result); | ||
| 111 | void dfltcc_reset(z_streamp strm, uInt size); | ||
| 112 | int dfltcc_can_inflate(z_streamp strm); | ||
| 113 | typedef enum { | ||
| 114 | DFLTCC_INFLATE_CONTINUE, | ||
| 115 | DFLTCC_INFLATE_BREAK, | ||
| 116 | DFLTCC_INFLATE_SOFTWARE, | ||
| 117 | } dfltcc_inflate_action; | ||
| 118 | dfltcc_inflate_action dfltcc_inflate(z_streamp strm, | ||
| 119 | int flush, int *ret); | ||
| 120 | static inline int is_dfltcc_enabled(void) | ||
| 121 | { | ||
| 122 | return (zlib_dfltcc_support != ZLIB_DFLTCC_DISABLED && | ||
| 123 | test_facility(DFLTCC_FACILITY)); | ||
| 124 | } | ||
| 125 | |||
| 126 | #define DEFLATE_RESET_HOOK(strm) \ | ||
| 127 | dfltcc_reset((strm), sizeof(deflate_state)) | ||
| 128 | |||
| 129 | #define DEFLATE_HOOK dfltcc_deflate | ||
| 130 | |||
| 131 | #define DEFLATE_NEED_CHECKSUM(strm) (!dfltcc_can_deflate((strm))) | ||
| 132 | |||
| 133 | #define DEFLATE_DFLTCC_ENABLED() is_dfltcc_enabled() | ||
| 134 | |||
| 135 | #define INFLATE_RESET_HOOK(strm) \ | ||
| 136 | dfltcc_reset((strm), sizeof(struct inflate_state)) | ||
| 137 | |||
| 138 | #define INFLATE_TYPEDO_HOOK(strm, flush) \ | ||
| 139 | if (dfltcc_can_inflate((strm))) { \ | ||
| 140 | dfltcc_inflate_action action; \ | ||
| 141 | \ | ||
| 142 | RESTORE(); \ | ||
| 143 | action = dfltcc_inflate((strm), (flush), &ret); \ | ||
| 144 | LOAD(); \ | ||
| 145 | if (action == DFLTCC_INFLATE_CONTINUE) \ | ||
| 146 | break; \ | ||
| 147 | else if (action == DFLTCC_INFLATE_BREAK) \ | ||
| 148 | goto inf_leave; \ | ||
| 149 | } | ||
| 150 | |||
| 151 | #define INFLATE_NEED_CHECKSUM(strm) (!dfltcc_can_inflate((strm))) | ||
| 152 | |||
| 153 | #define INFLATE_NEED_UPDATEWINDOW(strm) (!dfltcc_can_inflate((strm))) | ||
| 154 | |||
| 155 | #endif /* DFLTCC_H */ | ||
| @@ -0,0 +1,279 @@ | |||
| 1 | // SPDX-License-Identifier: Zlib | ||
| 2 | |||
| 3 | #include "../zlib_deflate/defutil.h" | ||
| 4 | #include "dfltcc_util.h" | ||
| 5 | #include "dfltcc.h" | ||
| 6 | #include <asm/setup.h> | ||
| 7 | #include <linux/zutil.h> | ||
| 8 | |||
| 9 | /* | ||
| 10 | * Compress. | ||
| 11 | */ | ||
| 12 | int dfltcc_can_deflate( | ||
| 13 | z_streamp strm | ||
| 14 | ) | ||
| 15 | { | ||
| 16 | deflate_state *state = (deflate_state *)strm->state; | ||
| 17 | struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); | ||
| 18 | |||
| 19 | /* Check for kernel dfltcc command line parameter */ | ||
| 20 | if (zlib_dfltcc_support == ZLIB_DFLTCC_DISABLED || | ||
| 21 | zlib_dfltcc_support == ZLIB_DFLTCC_INFLATE_ONLY) | ||
| 22 | return 0; | ||
| 23 | |||
| 24 | /* Unsupported compression settings */ | ||
| 25 | if (!dfltcc_are_params_ok(state->level, state->w_bits, state->strategy, | ||
| 26 | dfltcc_state->level_mask)) | ||
| 27 | return 0; | ||
| 28 | |||
| 29 | /* Unsupported hardware */ | ||
| 30 | if (!is_bit_set(dfltcc_state->af.fns, DFLTCC_GDHT) || | ||
| 31 | !is_bit_set(dfltcc_state->af.fns, DFLTCC_CMPR) || | ||
| 32 | !is_bit_set(dfltcc_state->af.fmts, DFLTCC_FMT0)) | ||
| 33 | return 0; | ||
| 34 | |||
| 35 | return 1; | ||
| 36 | } | ||
| 37 | |||
| 38 | static void dfltcc_gdht( | ||
| 39 | z_streamp strm | ||
| 40 | ) | ||
| 41 | { | ||
| 42 | deflate_state *state = (deflate_state *)strm->state; | ||
| 43 | struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param; | ||
| 44 | size_t avail_in = avail_in = strm->avail_in; | ||
| 45 | |||
| 46 | dfltcc(DFLTCC_GDHT, | ||
| 47 | param, NULL, NULL, | ||
| 48 | &strm->next_in, &avail_in, NULL); | ||
| 49 | } | ||
| 50 | |||
| 51 | static dfltcc_cc dfltcc_cmpr( | ||
| 52 | z_streamp strm | ||
| 53 | ) | ||
| 54 | { | ||
| 55 | deflate_state *state = (deflate_state *)strm->state; | ||
| 56 | struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param; | ||
| 57 | size_t avail_in = strm->avail_in; | ||
| 58 | size_t avail_out = strm->avail_out; | ||
| 59 | dfltcc_cc cc; | ||
| 60 | |||
| 61 | cc = dfltcc(DFLTCC_CMPR | HBT_CIRCULAR, | ||
| 62 | param, &strm->next_out, &avail_out, | ||
| 63 | &strm->next_in, &avail_in, state->window); | ||
| 64 | strm->total_in += (strm->avail_in - avail_in); | ||
| 65 | strm->total_out += (strm->avail_out - avail_out); | ||
| 66 | strm->avail_in = avail_in; | ||
| 67 | strm->avail_out = avail_out; | ||
| 68 | return cc; | ||
| 69 | } | ||
| 70 | |||
| 71 | static void send_eobs( | ||
| 72 | z_streamp strm, | ||
| 73 | const struct dfltcc_param_v0 *param | ||
| 74 | ) | ||
| 75 | { | ||
| 76 | deflate_state *state = (deflate_state *)strm->state; | ||
| 77 | |||
| 78 | zlib_tr_send_bits( | ||
| 79 | state, | ||
| 80 | bi_reverse(param->eobs >> (15 - param->eobl), param->eobl), | ||
| 81 | param->eobl); | ||
| 82 | flush_pending(strm); | ||
| 83 | if (state->pending != 0) { | ||
| 84 | /* The remaining data is located in pending_out[0:pending]. If someone | ||
| 85 | * calls put_byte() - this might happen in deflate() - the byte will be | ||
| 86 | * placed into pending_buf[pending], which is incorrect. Move the | ||
| 87 | * remaining data to the beginning of pending_buf so that put_byte() is | ||
| 88 | * usable again. | ||
| 89 | */ | ||
| 90 | memmove(state->pending_buf, state->pending_out, state->pending); | ||
| 91 | state->pending_out = state->pending_buf; | ||
| 92 | } | ||
| 93 | #ifdef ZLIB_DEBUG | ||
| 94 | state->compressed_len += param->eobl; | ||
| 95 | #endif | ||
| 96 | } | ||
| 97 | |||
| 98 | int dfltcc_deflate( | ||
| 99 | z_streamp strm, | ||
| 100 | int flush, | ||
| 101 | block_state *result | ||
| 102 | ) | ||
| 103 | { | ||
| 104 | deflate_state *state = (deflate_state *)strm->state; | ||
| 105 | struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); | ||
| 106 | struct dfltcc_param_v0 *param = &dfltcc_state->param; | ||
| 107 | uInt masked_avail_in; | ||
| 108 | dfltcc_cc cc; | ||
| 109 | int need_empty_block; | ||
| 110 | int soft_bcc; | ||
| 111 | int no_flush; | ||
| 112 | |||
| 113 | if (!dfltcc_can_deflate(strm)) | ||
| 114 | return 0; | ||
| 115 | |||
| 116 | again: | ||
| 117 | masked_avail_in = 0; | ||
| 118 | soft_bcc = 0; | ||
| 119 | no_flush = flush == Z_NO_FLUSH; | ||
| 120 | |||
| 121 | /* Trailing empty block. Switch to software, except when Continuation Flag | ||
| 122 | * is set, which means that DFLTCC has buffered some output in the | ||
| 123 | * parameter block and needs to be called again in order to flush it. | ||
| 124 | */ | ||
| 125 | if (flush == Z_FINISH && strm->avail_in == 0 && !param->cf) { | ||
| 126 | if (param->bcf) { | ||
| 127 | /* A block is still open, and the hardware does not support closing | ||
| 128 | * blocks without adding data. Thus, close it manually. | ||
| 129 | */ | ||
| 130 | send_eobs(strm, param); | ||
| 131 | param->bcf = 0; | ||
| 132 | } | ||
| 133 | return 0; | ||
| 134 | } | ||
| 135 | |||
| 136 | if (strm->avail_in == 0 && !param->cf) { | ||
| 137 | *result = need_more; | ||
| 138 | return 1; | ||
| 139 | } | ||
| 140 | |||
| 141 | /* There is an open non-BFINAL block, we are not going to close it just | ||
| 142 | * yet, we have compressed more than DFLTCC_BLOCK_SIZE bytes and we see | ||
| 143 | * more than DFLTCC_DHT_MIN_SAMPLE_SIZE bytes. Open a new block with a new | ||
| 144 | * DHT in order to adapt to a possibly changed input data distribution. | ||
| 145 | */ | ||
| 146 | if (param->bcf && no_flush && | ||
| 147 | strm->total_in > dfltcc_state->block_threshold && | ||
| 148 | strm->avail_in >= dfltcc_state->dht_threshold) { | ||
| 149 | if (param->cf) { | ||
| 150 | /* We need to flush the DFLTCC buffer before writing the | ||
| 151 | * End-of-block Symbol. Mask the input data and proceed as usual. | ||
| 152 | */ | ||
| 153 | masked_avail_in += strm->avail_in; | ||
| 154 | strm->avail_in = 0; | ||
| 155 | no_flush = 0; | ||
| 156 | } else { | ||
| 157 | /* DFLTCC buffer is empty, so we can manually write the | ||
| 158 | * End-of-block Symbol right away. | ||
| 159 | */ | ||
| 160 | send_eobs(strm, param); | ||
| 161 | param->bcf = 0; | ||
| 162 | dfltcc_state->block_threshold = | ||
| 163 | strm->total_in + dfltcc_state->block_size; | ||
| 164 | if (strm->avail_out == 0) { | ||
| 165 | *result = need_more; | ||
| 166 | return 1; | ||
| 167 | } | ||
| 168 | } | ||
| 169 | } | ||
| 170 | |||
| 171 | /* The caller gave us too much data. Pass only one block worth of | ||
| 172 | * uncompressed data to DFLTCC and mask the rest, so that on the next | ||
| 173 | * iteration we start a new block. | ||
| 174 | */ | ||
| 175 | if (no_flush && strm->avail_in > dfltcc_state->block_size) { | ||
| 176 | masked_avail_in += (strm->avail_in - dfltcc_state->block_size); | ||
| 177 | strm->avail_in = dfltcc_state->block_size; | ||
| 178 | } | ||
| 179 | |||
| 180 | /* When we have an open non-BFINAL deflate block and caller indicates that | ||
| 181 | * the stream is ending, we need to close an open deflate block and open a | ||
| 182 | * BFINAL one. | ||
| 183 | */ | ||
| 184 | need_empty_block = flush == Z_FINISH && param->bcf && !param->bhf; | ||
| 185 | |||
| 186 | /* Translate stream to parameter block */ | ||
| 187 | param->cvt = CVT_ADLER32; | ||
| 188 | if (!no_flush) | ||
| 189 | /* We need to close a block. Always do this in software - when there is | ||
| 190 | * no input data, the hardware will not nohor BCC. */ | ||
| 191 | soft_bcc = 1; | ||
| 192 | if (flush == Z_FINISH && !param->bcf) | ||
| 193 | /* We are about to open a BFINAL block, set Block Header Final bit | ||
| 194 | * until the stream ends. | ||
| 195 | */ | ||
| 196 | param->bhf = 1; | ||
| 197 | /* DFLTCC-CMPR will write to next_out, so make sure that buffers with | ||
| 198 | * higher precedence are empty. | ||
| 199 | */ | ||
| 200 | Assert(state->pending == 0, "There must be no pending bytes"); | ||
| 201 | Assert(state->bi_valid < 8, "There must be less than 8 pending bits"); | ||
| 202 | param->sbb = (unsigned int)state->bi_valid; | ||
| 203 | if (param->sbb > 0) | ||
| 204 | *strm->next_out = (Byte)state->bi_buf; | ||
| 205 | if (param->hl) | ||
| 206 | param->nt = 0; /* Honor history */ | ||
| 207 | param->cv = strm->adler; | ||
| 208 | |||
| 209 | /* When opening a block, choose a Huffman-Table Type */ | ||
| 210 | if (!param->bcf) { | ||
| 211 | if (strm->total_in == 0 && dfltcc_state->block_threshold > 0) { | ||
| 212 | param->htt = HTT_FIXED; | ||
| 213 | } | ||
| 214 | else { | ||
| 215 | param->htt = HTT_DYNAMIC; | ||
| 216 | dfltcc_gdht(strm); | ||
| 217 | } | ||
| 218 | } | ||
| 219 | |||
| 220 | /* Deflate */ | ||
| 221 | do { | ||
| 222 | cc = dfltcc_cmpr(strm); | ||
| 223 | if (strm->avail_in < 4096 && masked_avail_in > 0) | ||
| 224 | /* We are about to call DFLTCC with a small input buffer, which is | ||
| 225 | * inefficient. Since there is masked data, there will be at least | ||
| 226 | * one more DFLTCC call, so skip the current one and make the next | ||
| 227 | * one handle more data. | ||
| 228 | */ | ||
| 229 | break; | ||
| 230 | } while (cc == DFLTCC_CC_AGAIN); | ||
| 231 | |||
| 232 | /* Translate parameter block to stream */ | ||
| 233 | strm->msg = oesc_msg(dfltcc_state->msg, param->oesc); | ||
| 234 | state->bi_valid = param->sbb; | ||
| 235 | if (state->bi_valid == 0) | ||
| 236 | state->bi_buf = 0; /* Avoid accessing next_out */ | ||
| 237 | else | ||
| 238 | state->bi_buf = *strm->next_out & ((1 << state->bi_valid) - 1); | ||
| 239 | strm->adler = param->cv; | ||
| 240 | |||
| 241 | /* Unmask the input data */ | ||
| 242 | strm->avail_in += masked_avail_in; | ||
| 243 | masked_avail_in = 0; | ||
| 244 | |||
| 245 | /* If we encounter an error, it means there is a bug in DFLTCC call */ | ||
| 246 | Assert(cc != DFLTCC_CC_OP2_CORRUPT || param->oesc == 0, "BUG"); | ||
| 247 | |||
| 248 | /* Update Block-Continuation Flag. It will be used to check whether to call | ||
| 249 | * GDHT the next time. | ||
| 250 | */ | ||
| 251 | if (cc == DFLTCC_CC_OK) { | ||
| 252 | if (soft_bcc) { | ||
| 253 | send_eobs(strm, param); | ||
| 254 | param->bcf = 0; | ||
| 255 | dfltcc_state->block_threshold = | ||
| 256 | strm->total_in + dfltcc_state->block_size; | ||
| 257 | } else | ||
| 258 | param->bcf = 1; | ||
| 259 | if (flush == Z_FINISH) { | ||
| 260 | if (need_empty_block) | ||
| 261 | /* Make the current deflate() call also close the stream */ | ||
| 262 | return 0; | ||
| 263 | else { | ||
| 264 | bi_windup(state); | ||
| 265 | *result = finish_done; | ||
| 266 | } | ||
| 267 | } else { | ||
| 268 | if (flush == Z_FULL_FLUSH) | ||
| 269 | param->hl = 0; /* Clear history */ | ||
| 270 | *result = flush == Z_NO_FLUSH ? need_more : block_done; | ||
| 271 | } | ||
| 272 | } else { | ||
| 273 | param->bcf = 1; | ||
| 274 | *result = need_more; | ||
| 275 | } | ||
| 276 | if (strm->avail_in != 0 && strm->avail_out != 0) | ||
| 277 | goto again; /* deflate() must use all input or all output */ | ||
| 278 | return 1; | ||
| 279 | } | ||
| @@ -0,0 +1,149 @@ | |||
| 1 | // SPDX-License-Identifier: Zlib | ||
| 2 | |||
| 3 | #include "../zlib_inflate/inflate.h" | ||
| 4 | #include "dfltcc_util.h" | ||
| 5 | #include "dfltcc.h" | ||
| 6 | #include <asm/setup.h> | ||
| 7 | #include <linux/zutil.h> | ||
| 8 | |||
| 9 | /* | ||
| 10 | * Expand. | ||
| 11 | */ | ||
| 12 | int dfltcc_can_inflate( | ||
| 13 | z_streamp strm | ||
| 14 | ) | ||
| 15 | { | ||
| 16 | struct inflate_state *state = (struct inflate_state *)strm->state; | ||
| 17 | struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); | ||
| 18 | |||
| 19 | /* Check for kernel dfltcc command line parameter */ | ||
| 20 | if (zlib_dfltcc_support == ZLIB_DFLTCC_DISABLED || | ||
| 21 | zlib_dfltcc_support == ZLIB_DFLTCC_DEFLATE_ONLY) | ||
| 22 | return 0; | ||
| 23 | |||
| 24 | /* Unsupported compression settings */ | ||
| 25 | if (state->wbits != HB_BITS) | ||
| 26 | return 0; | ||
| 27 | |||
| 28 | /* Unsupported hardware */ | ||
| 29 | return is_bit_set(dfltcc_state->af.fns, DFLTCC_XPND) && | ||
| 30 | is_bit_set(dfltcc_state->af.fmts, DFLTCC_FMT0); | ||
| 31 | } | ||
| 32 | |||
| 33 | static int dfltcc_was_inflate_used( | ||
| 34 | z_streamp strm | ||
| 35 | ) | ||
| 36 | { | ||
| 37 | struct inflate_state *state = (struct inflate_state *)strm->state; | ||
| 38 | struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param; | ||
| 39 | |||
| 40 | return !param->nt; | ||
| 41 | } | ||
| 42 | |||
| 43 | static int dfltcc_inflate_disable( | ||
| 44 | z_streamp strm | ||
| 45 | ) | ||
| 46 | { | ||
| 47 | struct inflate_state *state = (struct inflate_state *)strm->state; | ||
| 48 | struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); | ||
| 49 | |||
| 50 | if (!dfltcc_can_inflate(strm)) | ||
| 51 | return 0; | ||
| 52 | if (dfltcc_was_inflate_used(strm)) | ||
| 53 | /* DFLTCC has already decompressed some data. Since there is not | ||
| 54 | * enough information to resume decompression in software, the call | ||
| 55 | * must fail. | ||
| 56 | */ | ||
| 57 | return 1; | ||
| 58 | /* DFLTCC was not used yet - decompress in software */ | ||
| 59 | memset(&dfltcc_state->af, 0, sizeof(dfltcc_state->af)); | ||
| 60 | return 0; | ||
| 61 | } | ||
| 62 | |||
| 63 | static dfltcc_cc dfltcc_xpnd( | ||
| 64 | z_streamp strm | ||
| 65 | ) | ||
| 66 | { | ||
| 67 | struct inflate_state *state = (struct inflate_state *)strm->state; | ||
| 68 | struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param; | ||
| 69 | size_t avail_in = strm->avail_in; | ||
| 70 | size_t avail_out = strm->avail_out; | ||
| 71 | dfltcc_cc cc; | ||
| 72 | |||
| 73 | cc = dfltcc(DFLTCC_XPND | HBT_CIRCULAR, | ||
| 74 | param, &strm->next_out, &avail_out, | ||
| 75 | &strm->next_in, &avail_in, state->window); | ||
| 76 | strm->avail_in = avail_in; | ||
| 77 | strm->avail_out = avail_out; | ||
| 78 | return cc; | ||
| 79 | } | ||
| 80 | |||
| 81 | dfltcc_inflate_action dfltcc_inflate( | ||
| 82 | z_streamp strm, | ||
| 83 | int flush, | ||
| 84 | int *ret | ||
| 85 | ) | ||
| 86 | { | ||
| 87 | struct inflate_state *state = (struct inflate_state *)strm->state; | ||
| 88 | struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); | ||
| 89 | struct dfltcc_param_v0 *param = &dfltcc_state->param; | ||
| 90 | dfltcc_cc cc; | ||
| 91 | |||
| 92 | if (flush == Z_BLOCK) { | ||
| 93 | /* DFLTCC does not support stopping on block boundaries */ | ||
| 94 | if (dfltcc_inflate_disable(strm)) { | ||
| 95 | *ret = Z_STREAM_ERROR; | ||
| 96 | return DFLTCC_INFLATE_BREAK; | ||
| 97 | } else | ||
| 98 | return DFLTCC_INFLATE_SOFTWARE; | ||
| 99 | } | ||
| 100 | |||
| 101 | if (state->last) { | ||
| 102 | if (state->bits != 0) { | ||
| 103 | strm->next_in++; | ||
| 104 | strm->avail_in--; | ||
| 105 | state->bits = 0; | ||
| 106 | } | ||
| 107 | state->mode = CHECK; | ||
| 108 | return DFLTCC_INFLATE_CONTINUE; | ||
| 109 | } | ||
| 110 | |||
| 111 | if (strm->avail_in == 0 && !param->cf) | ||
| 112 | return DFLTCC_INFLATE_BREAK; | ||
| 113 | |||
| 114 | if (!state->window || state->wsize == 0) { | ||
| 115 | state->mode = MEM; | ||
| 116 | return DFLTCC_INFLATE_CONTINUE; | ||
| 117 | } | ||
| 118 | |||
| 119 | /* Translate stream to parameter block */ | ||
| 120 | param->cvt = CVT_ADLER32; | ||
| 121 | param->sbb = state->bits; | ||
| 122 | param->hl = state->whave; /* Software and hardware history formats match */ | ||
| 123 | param->ho = (state->write - state->whave) & ((1 << HB_BITS) - 1); | ||
| 124 | if (param->hl) | ||
| 125 | param->nt = 0; /* Honor history for the first block */ | ||
| 126 | param->cv = state->flags ? REVERSE(state->check) : state->check; | ||
| 127 | |||
| 128 | /* Inflate */ | ||
| 129 | do { | ||
| 130 | cc = dfltcc_xpnd(strm); | ||
| 131 | } while (cc == DFLTCC_CC_AGAIN); | ||
| 132 | |||
| 133 | /* Translate parameter block to stream */ | ||
| 134 | strm->msg = oesc_msg(dfltcc_state->msg, param->oesc); | ||
| 135 | state->last = cc == DFLTCC_CC_OK; | ||
| 136 | state->bits = param->sbb; | ||
| 137 | state->whave = param->hl; | ||
| 138 | state->write = (param->ho + param->hl) & ((1 << HB_BITS) - 1); | ||
| 139 | state->check = state->flags ? REVERSE(param->cv) : param->cv; | ||
| 140 | if (cc == DFLTCC_CC_OP2_CORRUPT && param->oesc != 0) { | ||
| 141 | /* Report an error if stream is corrupted */ | ||
| 142 | state->mode = BAD; | ||
| 143 | return DFLTCC_INFLATE_CONTINUE; | ||
| 144 | } | ||
| 145 | state->mode = TYPEDO; | ||
| 146 | /* Break if operands are exhausted, otherwise continue looping */ | ||
| 147 | return (cc == DFLTCC_CC_OP1_TOO_SHORT || cc == DFLTCC_CC_OP2_TOO_SHORT) ? | ||
| 148 | DFLTCC_INFLATE_BREAK : DFLTCC_INFLATE_CONTINUE; | ||
| 149 | } | ||
| @@ -0,0 +1,17 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | /* | ||
| 3 | * linux/lib/zlib_dfltcc/dfltcc_syms.c | ||
| 4 | * | ||
| 5 | * Exported symbols for the s390 zlib dfltcc support. | ||
| 6 | * | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <linux/init.h> | ||
| 10 | #include <linux/module.h> | ||
| 11 | #include <linux/zlib.h> | ||
| 12 | #include "dfltcc.h" | ||
| 13 | |||
| 14 | EXPORT_SYMBOL(dfltcc_can_deflate); | ||
| 15 | EXPORT_SYMBOL(dfltcc_deflate); | ||
| 16 | EXPORT_SYMBOL(dfltcc_reset); | ||
| 17 | MODULE_LICENSE("GPL"); | ||
| @@ -0,0 +1,103 @@ | |||
| 1 | // SPDX-License-Identifier: Zlib | ||
| 2 | #ifndef DFLTCC_UTIL_H | ||
| 3 | #define DFLTCC_UTIL_H | ||
| 4 | |||
| 5 | #include <linux/zutil.h> | ||
| 6 | |||
| 7 | /* | ||
| 8 | * C wrapper for the DEFLATE CONVERSION CALL instruction. | ||
| 9 | */ | ||
| 10 | typedef enum { | ||
| 11 | DFLTCC_CC_OK = 0, | ||
| 12 | DFLTCC_CC_OP1_TOO_SHORT = 1, | ||
| 13 | DFLTCC_CC_OP2_TOO_SHORT = 2, | ||
| 14 | DFLTCC_CC_OP2_CORRUPT = 2, | ||
| 15 | DFLTCC_CC_AGAIN = 3, | ||
| 16 | } dfltcc_cc; | ||
| 17 | |||
| 18 | #define DFLTCC_QAF 0 | ||
| 19 | #define DFLTCC_GDHT 1 | ||
| 20 | #define DFLTCC_CMPR 2 | ||
| 21 | #define DFLTCC_XPND 4 | ||
| 22 | #define HBT_CIRCULAR (1 << 7) | ||
| 23 | #define HB_BITS 15 | ||
| 24 | #define HB_SIZE (1 << HB_BITS) | ||
| 25 | |||
| 26 | static inline dfltcc_cc dfltcc( | ||
| 27 | int fn, | ||
| 28 | void *param, | ||
| 29 | Byte **op1, | ||
| 30 | size_t *len1, | ||
| 31 | const Byte **op2, | ||
| 32 | size_t *len2, | ||
| 33 | void *hist | ||
| 34 | ) | ||
| 35 | { | ||
| 36 | Byte *t2 = op1 ? *op1 : NULL; | ||
| 37 | size_t t3 = len1 ? *len1 : 0; | ||
| 38 | const Byte *t4 = op2 ? *op2 : NULL; | ||
| 39 | size_t t5 = len2 ? *len2 : 0; | ||
| 40 | register int r0 __asm__("r0") = fn; | ||
| 41 | register void *r1 __asm__("r1") = param; | ||
| 42 | register Byte *r2 __asm__("r2") = t2; | ||
| 43 | register size_t r3 __asm__("r3") = t3; | ||
| 44 | register const Byte *r4 __asm__("r4") = t4; | ||
| 45 | register size_t r5 __asm__("r5") = t5; | ||
| 46 | int cc; | ||
| 47 | |||
| 48 | __asm__ volatile( | ||
| 49 | ".insn rrf,0xb9390000,%[r2],%[r4],%[hist],0\n" | ||
| 50 | "ipm %[cc]\n" | ||
| 51 | : [r2] "+r" (r2) | ||
| 52 | , [r3] "+r" (r3) | ||
| 53 | , [r4] "+r" (r4) | ||
| 54 | , [r5] "+r" (r5) | ||
| 55 | , [cc] "=r" (cc) | ||
| 56 | : [r0] "r" (r0) | ||
| 57 | , [r1] "r" (r1) | ||
| 58 | , [hist] "r" (hist) | ||
| 59 | : "cc", "memory"); | ||
| 60 | t2 = r2; t3 = r3; t4 = r4; t5 = r5; | ||
| 61 | |||
| 62 | if (op1) | ||
| 63 | *op1 = t2; | ||
| 64 | if (len1) | ||
| 65 | *len1 = t3; | ||
| 66 | if (op2) | ||
| 67 | *op2 = t4; | ||
| 68 | if (len2) | ||
| 69 | *len2 = t5; | ||
| 70 | return (cc >> 28) & 3; | ||
| 71 | } | ||
| 72 | |||
| 73 | static inline int is_bit_set( | ||
| 74 | const char *bits, | ||
| 75 | int n | ||
| 76 | ) | ||
| 77 | { | ||
| 78 | return bits[n / 8] & (1 << (7 - (n % 8))); | ||
| 79 | } | ||
| 80 | |||
| 81 | static inline void turn_bit_off( | ||
| 82 | char *bits, | ||
| 83 | int n | ||
| 84 | ) | ||
| 85 | { | ||
| 86 | bits[n / 8] &= ~(1 << (7 - (n % 8))); | ||
| 87 | } | ||
| 88 | |||
| 89 | static inline int dfltcc_are_params_ok( | ||
| 90 | int level, | ||
| 91 | uInt window_bits, | ||
| 92 | int strategy, | ||
| 93 | uLong level_mask | ||
| 94 | ) | ||
| 95 | { | ||
| 96 | return (level_mask & (1 << level)) != 0 && | ||
| 97 | (window_bits == HB_BITS) && | ||
| 98 | (strategy == Z_DEFAULT_STRATEGY); | ||
| 99 | } | ||
| 100 | |||
| 101 | char *oesc_msg(char *buf, int oesc); | ||
| 102 | |||
| 103 | #endif /* DFLTCC_UTIL_H */ | ||
| @@ -15,6 +15,16 @@ · 14 unmodified lines | |||
| 15 | #include "inffast.h" | 15 | #include "inffast.h" |
| 16 | #include "infutil.h" | 16 | #include "infutil.h" |
| 17 | 17 | ||
| 18 | /* architecture-specific bits */ | ||
| 19 | #ifdef CONFIG_ZLIB_DFLTCC | ||
| 20 | # include "../zlib_dfltcc/dfltcc.h" | ||
| 21 | #else | ||
| 22 | #define INFLATE_RESET_HOOK(strm) do {} while (0) | ||
| 23 | #define INFLATE_TYPEDO_HOOK(strm, flush) do {} while (0) | ||
| 24 | #define INFLATE_NEED_UPDATEWINDOW(strm) 1 | ||
| 25 | #define INFLATE_NEED_CHECKSUM(strm) 1 | ||
| 26 | #endif | ||
| 27 | |||
| 18 | int zlib_inflate_workspacesize(void) | 28 | int zlib_inflate_workspacesize(void) |
| 19 | { | 29 | { |
| 20 | return sizeof(struct inflate_workspace); | 30 | return sizeof(struct inflate_workspace); |
| @@ -42,6 +52,7 @@ int zlib_inflateReset(z_streamp strm) · 21 unmodified lines | |||
| 42 | state->write = 0; | 52 | state->write = 0; |
| 43 | state->whave = 0; | 53 | state->whave = 0; |
| 44 | 54 | ||
| 55 | INFLATE_RESET_HOOK(strm); | ||
| 45 | return Z_OK; | 56 | return Z_OK; |
| 46 | } | 57 | } |
| 47 | 58 | ||
| @@ -66,7 +77,15 @@ int zlib_inflateInit2(z_streamp strm, int windowBits) · 18 unmodified lines | |||
| 66 | return Z_STREAM_ERROR; | 77 | return Z_STREAM_ERROR; |
| 67 | } | 78 | } |
| 68 | state->wbits = (unsigned)windowBits; | 79 | state->wbits = (unsigned)windowBits; |
| 80 | #ifdef CONFIG_ZLIB_DFLTCC | ||
| 81 | /* | ||
| 82 | * DFLTCC requires the window to be page aligned. | ||
| 83 | * Thus, we overallocate and take the aligned portion of the buffer. | ||
| 84 | */ | ||
| 85 | state->window = PTR_ALIGN(&WS(strm)->working_window[0], PAGE_SIZE); | ||
| 86 | #else | ||
| 69 | state->window = &WS(strm)->working_window[0]; | 87 | state->window = &WS(strm)->working_window[0]; |
| 88 | #endif | ||
| 70 | 89 | ||
| 71 | return zlib_inflateReset(strm); | 90 | return zlib_inflateReset(strm); |
| 72 | } | 91 | } |
| @@ -227,11 +246,6 @@ static int zlib_inflateSyncPacket(z_streamp strm) · 154 unmodified lines | |||
| 227 | bits -= bits & 7; \ | 246 | bits -= bits & 7; \ |
| 228 | } while (0) | 247 | } while (0) |
| 229 | 248 | ||
| 230 | /* Reverse the bytes in a 32-bit value */ | ||
| 231 | #define REVERSE(q) \ | ||
| 232 | ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ | ||
| 233 | (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) | ||
| 234 | |||
| 235 | /* | 249 | /* |
| 236 | inflate() uses a state machine to process as much input data and generate as | 250 | inflate() uses a state machine to process as much input data and generate as |
| 237 | much output data as possible before returning. The state machine is | 251 | much output data as possible before returning. The state machine is |
| @@ -395,6 +409,7 @@ int zlib_inflate(z_streamp strm, int flush) · 157 unmodified lines | |||
| 395 | if (flush == Z_BLOCK) goto inf_leave; | 409 | if (flush == Z_BLOCK) goto inf_leave; |
| 396 | /* fall through */ | 410 | /* fall through */ |
| 397 | case TYPEDO: | 411 | case TYPEDO: |
| 412 | INFLATE_TYPEDO_HOOK(strm, flush); | ||
| 398 | if (state->last) { | 413 | if (state->last) { |
| 399 | BYTEBITS(); | 414 | BYTEBITS(); |
| 400 | state->mode = CHECK; | 415 | state->mode = CHECK; |
| @@ -692,7 +707,7 @@ int zlib_inflate(z_streamp strm, int flush) · 291 unmodified lines | |||
| 692 | out -= left; | 707 | out -= left; |
| 693 | strm->total_out += out; | 708 | strm->total_out += out; |
| 694 | state->total += out; | 709 | state->total += out; |
| 695 | if (out) | 710 | if (INFLATE_NEED_CHECKSUM(strm) && out) |
| 696 | strm->adler = state->check = | 711 | strm->adler = state->check = |
| 697 | UPDATE(state->check, put - out, out); | 712 | UPDATE(state->check, put - out, out); |
| 698 | out = left; | 713 | out = left; |
| @@ -726,7 +741,8 @@ int zlib_inflate(z_streamp strm, int flush) · 27 unmodified lines | |||
| 726 | */ | 741 | */ |
| 727 | inf_leave: | 742 | inf_leave: |
| 728 | RESTORE(); | 743 | RESTORE(); |
| 729 | if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) | 744 | if (INFLATE_NEED_UPDATEWINDOW(strm) && |
| 745 | (state->wsize || (state->mode < CHECK && out != strm->avail_out))) | ||
| 730 | zlib_updatewindow(strm, out); | 746 | zlib_updatewindow(strm, out); |
| 731 | 747 | ||
| 732 | in -= strm->avail_in; | 748 | in -= strm->avail_in; |
| @@ -734,7 +750,7 @@ int zlib_inflate(z_streamp strm, int flush) · 1 unmodified line | |||
| 734 | strm->total_in += in; | 750 | strm->total_in += in; |
| 735 | strm->total_out += out; | 751 | strm->total_out += out; |
| 736 | state->total += out; | 752 | state->total += out; |
| 737 | if (state->wrap && out) | 753 | if (INFLATE_NEED_CHECKSUM(strm) && state->wrap && out) |
| 738 | strm->adler = state->check = | 754 | strm->adler = state->check = |
| 739 | UPDATE(state->check, strm->next_out - out, out); | 755 | UPDATE(state->check, strm->next_out - out, out); |
| 740 | 756 | ||
| @@ -11,6 +11,8 @@ · 10 unmodified lines | |||
| 11 | subject to change. Applications should only use zlib.h. | 11 | subject to change. Applications should only use zlib.h. |
| 12 | */ | 12 | */ |
| 13 | 13 | ||
| 14 | #include "inftrees.h" | ||
| 15 | |||
| 14 | /* Possible inflate modes between inflate() calls */ | 16 | /* Possible inflate modes between inflate() calls */ |
| 15 | typedef enum { | 17 | typedef enum { |
| 16 | HEAD, /* i: waiting for magic header */ | 18 | HEAD, /* i: waiting for magic header */ |
| @@ -108,4 +110,10 @@ struct inflate_state { · 91 unmodified lines | |||
| 108 | unsigned short work[288]; /* work area for code table building */ | 110 | unsigned short work[288]; /* work area for code table building */ |
| 109 | code codes[ENOUGH]; /* space for code tables */ | 111 | code codes[ENOUGH]; /* space for code tables */ |
| 110 | }; | 112 | }; |
| 113 | |||
| 114 | /* Reverse the bytes in a 32-bit value */ | ||
| 115 | #define REVERSE(q) \ | ||
| 116 | ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ | ||
| 117 | (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) | ||
| 118 | |||
| 111 | #endif | 119 | #endif |
| @@ -12,14 +12,28 @@ · 11 unmodified lines | |||
| 12 | #define _INFUTIL_H | 12 | #define _INFUTIL_H |
| 13 | 13 | ||
| 14 | #include <linux/zlib.h> | 14 | #include <linux/zlib.h> |
| 15 | #ifdef CONFIG_ZLIB_DFLTCC | ||
| 16 | #include "../zlib_dfltcc/dfltcc.h" | ||
| 17 | #include <asm/page.h> | ||
| 18 | #endif | ||
| 15 | 19 | ||
| 16 | /* memory allocation for inflation */ | 20 | /* memory allocation for inflation */ |
| 17 | 21 | ||
| 18 | struct inflate_workspace { | 22 | struct inflate_workspace { |
| 19 | struct inflate_state inflate_state; | 23 | struct inflate_state inflate_state; |
| 20 | unsigned char working_window[1 << MAX_WBITS]; | 24 | #ifdef CONFIG_ZLIB_DFLTCC |
| 25 | struct dfltcc_state dfltcc_state; | ||
| 26 | unsigned char working_window[(1 << MAX_WBITS) + PAGE_SIZE]; | ||
| 27 | #else | ||
| 28 | unsigned char working_window[(1 << MAX_WBITS)]; | ||
| 29 | #endif | ||
| 21 | }; | 30 | }; |
| 22 | 31 | ||
| 23 | #define WS(z) ((struct inflate_workspace *)(z->workspace)) | 32 | #ifdef CONFIG_ZLIB_DFLTCC |
| 33 | /* dfltcc_state must be doubleword aligned for DFLTCC call */ | ||
| 34 | static_assert(offsetof(struct inflate_workspace, dfltcc_state) % 8 == 0); | ||
| 35 | #endif | ||
| 36 | |||
| 37 | #define WS(strm) ((struct inflate_workspace *)(strm->workspace)) | ||
| 24 | 38 | ||
| 25 | #endif | 39 | #endif |
| @@ -20,6 +20,7 @@ KCOV_INSTRUMENT_kmemleak.o := n · 19 unmodified lines | |||
| 20 | KCOV_INSTRUMENT_memcontrol.o := n | 20 | KCOV_INSTRUMENT_memcontrol.o := n |
| 21 | KCOV_INSTRUMENT_mmzone.o := n | 21 | KCOV_INSTRUMENT_mmzone.o := n |
| 22 | KCOV_INSTRUMENT_vmstat.o := n | 22 | KCOV_INSTRUMENT_vmstat.o := n |
| 23 | KCOV_INSTRUMENT_failslab.o := n | ||
| 23 | 24 | ||
| 24 | CFLAGS_init-mm.o += $(call cc-disable-warning, override-init) | 25 | CFLAGS_init-mm.o += $(call cc-disable-warning, override-init) |
| 25 | CFLAGS_init-mm.o += $(call cc-disable-warning, initializer-overrides) | 26 | CFLAGS_init-mm.o += $(call cc-disable-warning, initializer-overrides) |
| @@ -21,6 +21,7 @@ struct backing_dev_info noop_backing_dev_info = { · 20 unmodified lines | |||
| 21 | EXPORT_SYMBOL_GPL(noop_backing_dev_info); | 21 | EXPORT_SYMBOL_GPL(noop_backing_dev_info); |
| 22 | 22 | ||
| 23 | static struct class *bdi_class; | 23 | static struct class *bdi_class; |
| 24 | const char *bdi_unknown_name = "(unknown)"; | ||
| 24 | 25 | ||
| 25 | /* | 26 | /* |
| 26 | * bdi_lock protects bdi_tree and updates to bdi_list. bdi_list has RCU | 27 | * bdi_lock protects bdi_tree and updates to bdi_list. bdi_list has RCU |
| @@ -46,7 +46,15 @@ void __dump_page(struct page *page, const char *reason) · 45 unmodified lines | |||
| 46 | { | 46 | { |
| 47 | struct address_space *mapping; | 47 | struct address_space *mapping; |
| 48 | bool page_poisoned = PagePoisoned(page); | 48 | bool page_poisoned = PagePoisoned(page); |
| 49 | /* | ||
| 50 | * Accessing the pageblock without the zone lock. It could change to | ||
| 51 | * "isolate" again in the meantime, but since we are just dumping the | ||
| 52 | * state for debugging, it should be fine to accept a bit of | ||
| 53 | * inaccuracy here due to racing. | ||
| 54 | */ | ||
| 55 | bool page_cma = is_migrate_cma_page(page); | ||
| 49 | int mapcount; | 56 | int mapcount; |
| 57 | char *type = ""; | ||
| 50 | 58 | ||
| 51 | /* | 59 | /* |
| 52 | * If struct page is poisoned don't access Page*() functions as that | 60 | * If struct page is poisoned don't access Page*() functions as that |
| @@ -78,9 +86,9 @@ void __dump_page(struct page *page, const char *reason) · 25 unmodified lines | |||
| 78 | page, page_ref_count(page), mapcount, | 86 | page, page_ref_count(page), mapcount, |
| 79 | page->mapping, page_to_pgoff(page)); | 87 | page->mapping, page_to_pgoff(page)); |
| 80 | if (PageKsm(page)) | 88 | if (PageKsm(page)) |
| 81 | pr_warn("ksm flags: %#lx(%pGp)\n", page->flags, &page->flags); | 89 | type = "ksm "; |
| 82 | else if (PageAnon(page)) | 90 | else if (PageAnon(page)) |
| 83 | pr_warn("anon flags: %#lx(%pGp)\n", page->flags, &page->flags); | 91 | type = "anon "; |
| 84 | else if (mapping) { | 92 | else if (mapping) { |
| 85 | if (mapping->host && mapping->host->i_dentry.first) { | 93 | if (mapping->host && mapping->host->i_dentry.first) { |
| 86 | struct dentry *dentry; | 94 | struct dentry *dentry; |
| @@ -88,10 +96,12 @@ void __dump_page(struct page *page, const char *reason) · 1 unmodified line | |||
| 88 | pr_warn("%ps name:\"%pd\"\n", mapping->a_ops, dentry); | 96 | pr_warn("%ps name:\"%pd\"\n", mapping->a_ops, dentry); |
| 89 | } else | 97 | } else |
| 90 | pr_warn("%ps\n", mapping->a_ops); | 98 | pr_warn("%ps\n", mapping->a_ops); |
| 91 | pr_warn("flags: %#lx(%pGp)\n", page->flags, &page->flags); | ||
| 92 | } | 99 | } |
| 93 | BUILD_BUG_ON(ARRAY_SIZE(pageflag_names) != __NR_PAGEFLAGS + 1); | 100 | BUILD_BUG_ON(ARRAY_SIZE(pageflag_names) != __NR_PAGEFLAGS + 1); |
| 94 | 101 | ||
| 102 | pr_warn("%sflags: %#lx(%pGp)%s\n", type, page->flags, &page->flags, | ||
| 103 | page_cma ? " CMA" : ""); | ||
| 104 | |||
| 95 | hex_only: | 105 | hex_only: |
| 96 | print_hex_dump(KERN_WARNING, "raw: ", DUMP_PREFIX_NONE, 32, | 106 | print_hex_dump(KERN_WARNING, "raw: ", DUMP_PREFIX_NONE, 32, |
| 97 | sizeof(unsigned long), page, | 107 | sizeof(unsigned long), page, |
| @@ -121,8 +121,8 @@ __early_ioremap(resource_size_t phys_addr, unsigned long size, pgprot_t prot) · 120 unmodified lines | |||
| 121 | } | 121 | } |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | if (WARN(slot < 0, "%s(%08llx, %08lx) not found slot\n", | 124 | if (WARN(slot < 0, "%s(%pa, %08lx) not found slot\n", |
| 125 | __func__, (u64)phys_addr, size)) | 125 | __func__, &phys_addr, size)) |
| 126 | return NULL; | 126 | return NULL; |
| 127 | 127 | ||
| 128 | /* Don't allow wraparound or zero size */ | 128 | /* Don't allow wraparound or zero size */ |
| @@ -158,8 +158,8 @@ __early_ioremap(resource_size_t phys_addr, unsigned long size, pgprot_t prot) · 29 unmodified lines | |||
| 158 | --idx; | 158 | --idx; |
| 159 | --nrpages; | 159 | --nrpages; |
| 160 | } | 160 | } |
| 161 | WARN(early_ioremap_debug, "%s(%08llx, %08lx) [%d] => %08lx + %08lx\n", | 161 | WARN(early_ioremap_debug, "%s(%pa, %08lx) [%d] => %08lx + %08lx\n", |
| 162 | __func__, (u64)phys_addr, size, slot, offset, slot_virt[slot]); | 162 | __func__, &phys_addr, size, slot, offset, slot_virt[slot]); |
| 163 | 163 | ||
| 164 | prev_map[slot] = (void __iomem *)(offset + slot_virt[slot]); | 164 | prev_map[slot] = (void __iomem *)(offset + slot_virt[slot]); |
| 165 | return prev_map[slot]; | 165 | return prev_map[slot]; |
| @@ -632,33 +632,6 @@ static bool mapping_needs_writeback(struct address_space *mapping) · 631 unmodified lines | |||
| 632 | return mapping->nrpages; | 632 | return mapping->nrpages; |
| 633 | } | 633 | } |
| 634 | 634 | ||
| 635 | int filemap_write_and_wait(struct address_space *mapping) | ||
| 636 | { | ||
| 637 | int err = 0; | ||
| 638 | |||
| 639 | if (mapping_needs_writeback(mapping)) { | ||
| 640 | err = filemap_fdatawrite(mapping); | ||
| 641 | /* | ||
| 642 | * Even if the above returned error, the pages may be | ||
| 643 | * written partially (e.g. -ENOSPC), so we wait for it. | ||
| 644 | * But the -EIO is special case, it may indicate the worst | ||
| 645 | * thing (e.g. bug) happened, so we avoid waiting for it. | ||
| 646 | */ | ||
| 647 | if (err != -EIO) { | ||
| 648 | int err2 = filemap_fdatawait(mapping); | ||
| 649 | if (!err) | ||
| 650 | err = err2; | ||
| 651 | } else { | ||
| 652 | /* Clear any previously stored errors */ | ||
| 653 | filemap_check_errors(mapping); | ||
| 654 | } | ||
| 655 | } else { | ||
| 656 | err = filemap_check_errors(mapping); | ||
| 657 | } | ||
| 658 | return err; | ||
| 659 | } | ||
| 660 | EXPORT_SYMBOL(filemap_write_and_wait); | ||
| 661 | |||
| 662 | /** | 635 | /** |
| 663 | * filemap_write_and_wait_range - write out & wait on a file range | 636 | * filemap_write_and_wait_range - write out & wait on a file range |
| 664 | * @mapping: the address_space for the pages | 637 | * @mapping: the address_space for the pages |
| @@ -680,7 +653,12 @@ int filemap_write_and_wait_range(struct address_space *mapping, · 15 unmodified lines | |||
| 680 | if (mapping_needs_writeback(mapping)) { | 653 | if (mapping_needs_writeback(mapping)) { |
| 681 | err = __filemap_fdatawrite_range(mapping, lstart, lend, | 654 | err = __filemap_fdatawrite_range(mapping, lstart, lend, |
| 682 | WB_SYNC_ALL); | 655 | WB_SYNC_ALL); |
| 683 | /* See comment of filemap_write_and_wait() */ | 656 | /* |
| 657 | * Even if the above returned error, the pages may be | ||
| 658 | * written partially (e.g. -ENOSPC), so we wait for it. | ||
| 659 | * But the -EIO is special case, it may indicate the worst | ||
| 660 | * thing (e.g. bug) happened, so we avoid waiting for it. | ||
| 661 | */ | ||
| 684 | if (err != -EIO) { | 662 | if (err != -EIO) { |
| 685 | int err2 = filemap_fdatawait_range(mapping, | 663 | int err2 = filemap_fdatawait_range(mapping, |
| 686 | lstart, lend); | 664 | lstart, lend); |
| @@ -29,8 +29,23 @@ struct follow_page_context { · 28 unmodified lines | |||
| 29 | unsigned int page_mask; | 29 | unsigned int page_mask; |
| 30 | }; | 30 | }; |
| 31 | 31 | ||
| 32 | /* | ||
| 33 | * Return the compound head page with ref appropriately incremented, | ||
| 34 | * or NULL if that failed. | ||
| 35 | */ | ||
| 36 | static inline struct page *try_get_compound_head(struct page *page, int refs) | ||
| 37 | { | ||
| 38 | struct page *head = compound_head(page); | ||
| 39 | |||
| 40 | if (WARN_ON_ONCE(page_ref_count(head) < 0)) | ||
| 41 | return NULL; | ||
| 42 | if (unlikely(!page_cache_add_speculative(head, refs))) | ||
| 43 | return NULL; | ||
| 44 | return head; | ||
| 45 | } | ||
| 46 | |||
| 32 | /** | 47 | /** |
| 33 | * put_user_pages_dirty_lock() - release and optionally dirty gup-pinned pages | 48 | * unpin_user_pages_dirty_lock() - release and optionally dirty gup-pinned pages |
| 34 | * @pages: array of pages to be maybe marked dirty, and definitely released. | 49 | * @pages: array of pages to be maybe marked dirty, and definitely released. |
| 35 | * @npages: number of pages in the @pages array. | 50 | * @npages: number of pages in the @pages array. |
| 36 | * @make_dirty: whether to mark the pages dirty | 51 | * @make_dirty: whether to mark the pages dirty |
| @@ -40,19 +55,19 @@ struct follow_page_context { · 3 unmodified lines | |||
| 40 | * | 55 | * |
| 41 | * For each page in the @pages array, make that page (or its head page, if a | 56 | * For each page in the @pages array, make that page (or its head page, if a |
| 42 | * compound page) dirty, if @make_dirty is true, and if the page was previously | 57 | * compound page) dirty, if @make_dirty is true, and if the page was previously |
| 43 | * listed as clean. In any case, releases all pages using put_user_page(), | 58 | * listed as clean. In any case, releases all pages using unpin_user_page(), |
| 44 | * possibly via put_user_pages(), for the non-dirty case. | 59 | * possibly via unpin_user_pages(), for the non-dirty case. |
| 45 | * | 60 | * |
| 46 | * Please see the put_user_page() documentation for details. | 61 | * Please see the unpin_user_page() documentation for details. |
| 47 | * | 62 | * |
| 48 | * set_page_dirty_lock() is used internally. If instead, set_page_dirty() is | 63 | * set_page_dirty_lock() is used internally. If instead, set_page_dirty() is |
| 49 | * required, then the caller should a) verify that this is really correct, | 64 | * required, then the caller should a) verify that this is really correct, |
| 50 | * because _lock() is usually required, and b) hand code it: | 65 | * because _lock() is usually required, and b) hand code it: |
| 51 | * set_page_dirty_lock(), put_user_page(). | 66 | * set_page_dirty_lock(), unpin_user_page(). |
| 52 | * | 67 | * |
| 53 | */ | 68 | */ |
| 54 | void put_user_pages_dirty_lock(struct page **pages, unsigned long npages, | 69 | void unpin_user_pages_dirty_lock(struct page **pages, unsigned long npages, |
| 55 | bool make_dirty) | 70 | bool make_dirty) |
| 56 | { | 71 | { |
| 57 | unsigned long index; | 72 | unsigned long index; |
| 58 | 73 | ||
| @@ -63,7 +78,7 @@ void put_user_pages_dirty_lock(struct page **pages, unsigned long npages, · 4 unmodified lines | |||
| 63 | */ | 78 | */ |
| 64 | 79 | ||
| 65 | if (!make_dirty) { | 80 | if (!make_dirty) { |
| 66 | put_user_pages(pages, npages); | 81 | unpin_user_pages(pages, npages); |
| 67 | return; | 82 | return; |
| 68 | } | 83 | } |
| 69 | 84 | ||
| @@ -91,21 +106,21 @@ void put_user_pages_dirty_lock(struct page **pages, unsigned long npages, · 21 unmodified lines | |||
| 91 | */ | 106 | */ |
| 92 | if (!PageDirty(page)) | 107 | if (!PageDirty(page)) |
| 93 | set_page_dirty_lock(page); | 108 | set_page_dirty_lock(page); |
| 94 | put_user_page(page); | 109 | unpin_user_page(page); |
| 95 | } | 110 | } |
| 96 | } | 111 | } |
| 97 | EXPORT_SYMBOL(put_user_pages_dirty_lock); | 112 | EXPORT_SYMBOL(unpin_user_pages_dirty_lock); |
| 98 | 113 | ||
| 99 | /** | 114 | /** |
| 100 | * put_user_pages() - release an array of gup-pinned pages. | 115 | * unpin_user_pages() - release an array of gup-pinned pages. |
| 101 | * @pages: array of pages to be marked dirty and released. | 116 | * @pages: array of pages to be marked dirty and released. |
| 102 | * @npages: number of pages in the @pages array. | 117 | * @npages: number of pages in the @pages array. |
| 103 | * | 118 | * |
| 104 | * For each page in the @pages array, release the page using put_user_page(). | 119 | * For each page in the @pages array, release the page using unpin_user_page(). |
| 105 | * | 120 | * |
| 106 | * Please see the put_user_page() documentation for details. | 121 | * Please see the unpin_user_page() documentation for details. |
| 107 | */ | 122 | */ |
| 108 | void put_user_pages(struct page **pages, unsigned long npages) | 123 | void unpin_user_pages(struct page **pages, unsigned long npages) |
| 109 | { | 124 | { |
| 110 | unsigned long index; | 125 | unsigned long index; |
| 111 | 126 | ||
| @@ -115,9 +130,9 @@ void put_user_pages(struct page **pages, unsigned long npages) · 3 unmodified lines | |||
| 115 | * single operation to the head page should suffice. | 130 | * single operation to the head page should suffice. |
| 116 | */ | 131 | */ |
| 117 | for (index = 0; index < npages; index++) | 132 | for (index = 0; index < npages; index++) |
| 118 | put_user_page(pages[index]); | 133 | unpin_user_page(pages[index]); |
| 119 | } | 134 | } |
| 120 | EXPORT_SYMBOL(put_user_pages); | 135 | EXPORT_SYMBOL(unpin_user_pages); |
| 121 | 136 | ||
| 122 | #ifdef CONFIG_MMU | 137 | #ifdef CONFIG_MMU |
| 123 | static struct page *no_page_table(struct vm_area_struct *vma, | 138 | static struct page *no_page_table(struct vm_area_struct *vma, |
| @@ -179,6 +194,10 @@ static struct page *follow_page_pte(struct vm_area_struct *vma, · 55 unmodified lines | |||
| 179 | spinlock_t *ptl; | 194 | spinlock_t *ptl; |
| 180 | pte_t *ptep, pte; | 195 | pte_t *ptep, pte; |
| 181 | 196 | ||
| 197 | /* FOLL_GET and FOLL_PIN are mutually exclusive. */ | ||
| 198 | if (WARN_ON_ONCE((flags & (FOLL_PIN | FOLL_GET)) == | ||
| 199 | (FOLL_PIN | FOLL_GET))) | ||
| 200 | return ERR_PTR(-EINVAL); | ||
| 182 | retry: | 201 | retry: |
| 183 | if (unlikely(pmd_bad(*pmd))) | 202 | if (unlikely(pmd_bad(*pmd))) |
| 184 | return no_page_table(vma, flags); | 203 | return no_page_table(vma, flags); |
| @@ -323,7 +342,7 @@ static struct page *follow_pmd_mask(struct vm_area_struct *vma, · 138 unmodified lines | |||
| 323 | pmdval = READ_ONCE(*pmd); | 342 | pmdval = READ_ONCE(*pmd); |
| 324 | if (pmd_none(pmdval)) | 343 | if (pmd_none(pmdval)) |
| 325 | return no_page_table(vma, flags); | 344 | return no_page_table(vma, flags); |
| 326 | if (pmd_huge(pmdval) && vma->vm_flags & VM_HUGETLB) { | 345 | if (pmd_huge(pmdval) && is_vm_hugetlb_page(vma)) { |
| 327 | page = follow_huge_pmd(mm, address, pmd, flags); | 346 | page = follow_huge_pmd(mm, address, pmd, flags); |
| 328 | if (page) | 347 | if (page) |
| 329 | return page; | 348 | return page; |
| @@ -433,7 +452,7 @@ static struct page *follow_pud_mask(struct vm_area_struct *vma, · 103 unmodified lines | |||
| 433 | pud = pud_offset(p4dp, address); | 452 | pud = pud_offset(p4dp, address); |
| 434 | if (pud_none(*pud)) | 453 | if (pud_none(*pud)) |
| 435 | return no_page_table(vma, flags); | 454 | return no_page_table(vma, flags); |
| 436 | if (pud_huge(*pud) && vma->vm_flags & VM_HUGETLB) { | 455 | if (pud_huge(*pud) && is_vm_hugetlb_page(vma)) { |
| 437 | page = follow_huge_pud(mm, address, pud, flags); | 456 | page = follow_huge_pud(mm, address, pud, flags); |
| 438 | if (page) | 457 | if (page) |
| 439 | return page; | 458 | return page; |
| @@ -796,7 +815,7 @@ static long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, · 356 unmodified lines | |||
| 796 | 815 | ||
| 797 | start = untagged_addr(start); | 816 | start = untagged_addr(start); |
| 798 | 817 | ||
| 799 | VM_BUG_ON(!!pages != !!(gup_flags & FOLL_GET)); | 818 | VM_BUG_ON(!!pages != !!(gup_flags & (FOLL_GET | FOLL_PIN))); |
| 800 | 819 | ||
| 801 | /* | 820 | /* |
| 802 | * If FOLL_FORCE is set then do not force a full fault as the hinting | 821 | * If FOLL_FORCE is set then do not force a full fault as the hinting |
| @@ -1020,7 +1039,16 @@ static __always_inline long __get_user_pages_locked(struct task_struct *tsk, · 217 unmodified lines | |||
| 1020 | BUG_ON(*locked != 1); | 1039 | BUG_ON(*locked != 1); |
| 1021 | } | 1040 | } |
| 1022 | 1041 | ||
| 1023 | if (pages) | 1042 | /* |
| 1043 | * FOLL_PIN and FOLL_GET are mutually exclusive. Traditional behavior | ||
| 1044 | * is to set FOLL_GET if the caller wants pages[] filled in (but has | ||
| 1045 | * carelessly failed to specify FOLL_GET), so keep doing that, but only | ||
| 1046 | * for FOLL_GET, not for the newer FOLL_PIN. | ||
| 1047 | * | ||
| 1048 | * FOLL_PIN always expects pages to be non-null, but no need to assert | ||
| 1049 | * that here, as any failures will be obvious enough. | ||
| 1050 | */ | ||
| 1051 | if (pages && !(flags & FOLL_PIN)) | ||
| 1024 | flags |= FOLL_GET; | 1052 | flags |= FOLL_GET; |
| 1025 | 1053 | ||
| 1026 | pages_done = 0; | 1054 | pages_done = 0; |
| @@ -1096,88 +1124,6 @@ static __always_inline long __get_user_pages_locked(struct task_struct *tsk, · 69 unmodified lines | |||
| 1096 | return pages_done; | 1124 | return pages_done; |
| 1097 | } | 1125 | } |
| 1098 | 1126 | ||
| 1099 | /* | ||
| 1100 | * get_user_pages_remote() - pin user pages in memory | ||
| 1101 | * @tsk: the task_struct to use for page fault accounting, or | ||
| 1102 | * NULL if faults are not to be recorded. | ||
| 1103 | * @mm: mm_struct of target mm | ||
| 1104 | * @start: starting user address | ||
| 1105 | * @nr_pages: number of pages from start to pin | ||
| 1106 | * @gup_flags: flags modifying lookup behaviour | ||
| 1107 | * @pages: array that receives pointers to the pages pinned. | ||
| 1108 | * Should be at least nr_pages long. Or NULL, if caller | ||
| 1109 | * only intends to ensure the pages are faulted in. | ||
| 1110 | * @vmas: array of pointers to vmas corresponding to each page. | ||
| 1111 | * Or NULL if the caller does not require them. | ||
| 1112 | * @locked: pointer to lock flag indicating whether lock is held and | ||
| 1113 | * subsequently whether VM_FAULT_RETRY functionality can be | ||
| 1114 | * utilised. Lock must initially be held. | ||
| 1115 | * | ||
| 1116 | * Returns either number of pages pinned (which may be less than the | ||
| 1117 | * number requested), or an error. Details about the return value: | ||
| 1118 | * | ||
| 1119 | * -- If nr_pages is 0, returns 0. | ||
| 1120 | * -- If nr_pages is >0, but no pages were pinned, returns -errno. | ||
| 1121 | * -- If nr_pages is >0, and some pages were pinned, returns the number of | ||
| 1122 | * pages pinned. Again, this may be less than nr_pages. | ||
| 1123 | * | ||
| 1124 | * The caller is responsible for releasing returned @pages, via put_page(). | ||
| 1125 | * | ||
| 1126 | * @vmas are valid only as long as mmap_sem is held. | ||
| 1127 | * | ||
| 1128 | * Must be called with mmap_sem held for read or write. | ||
| 1129 | * | ||
| 1130 | * get_user_pages walks a process's page tables and takes a reference to | ||
| 1131 | * each struct page that each user address corresponds to at a given | ||
| 1132 | * instant. That is, it takes the page that would be accessed if a user | ||
| 1133 | * thread accesses the given user virtual address at that instant. | ||
| 1134 | * | ||
| 1135 | * This does not guarantee that the page exists in the user mappings when | ||
| 1136 | * get_user_pages returns, and there may even be a completely different | ||
| 1137 | * page there in some cases (eg. if mmapped pagecache has been invalidated | ||
| 1138 | * and subsequently re faulted). However it does guarantee that the page | ||
| 1139 | * won't be freed completely. And mostly callers simply care that the page | ||
| 1140 | * contains data that was valid *at some point in time*. Typically, an IO | ||
| 1141 | * or similar operation cannot guarantee anything stronger anyway because | ||
| 1142 | * locks can't be held over the syscall boundary. | ||
| 1143 | * | ||
| 1144 | * If gup_flags & FOLL_WRITE == 0, the page must not be written to. If the page | ||
| 1145 | * is written to, set_page_dirty (or set_page_dirty_lock, as appropriate) must | ||
| 1146 | * be called after the page is finished with, and before put_page is called. | ||
| 1147 | * | ||
| 1148 | * get_user_pages is typically used for fewer-copy IO operations, to get a | ||
| 1149 | * handle on the memory by some means other than accesses via the user virtual | ||
| 1150 | * addresses. The pages may be submitted for DMA to devices or accessed via | ||
| 1151 | * their kernel linear mapping (via the kmap APIs). Care should be taken to | ||
| 1152 | * use the correct cache flushing APIs. | ||
| 1153 | * | ||
| 1154 | * See also get_user_pages_fast, for performance critical applications. | ||
| 1155 | * | ||
| 1156 | * get_user_pages should be phased out in favor of | ||
| 1157 | * get_user_pages_locked|unlocked or get_user_pages_fast. Nothing | ||
| 1158 | * should use get_user_pages because it cannot pass | ||
| 1159 | * FAULT_FLAG_ALLOW_RETRY to handle_mm_fault. | ||
| 1160 | */ | ||
| 1161 | long get_user_pages_remote(struct task_struct *tsk, struct mm_struct *mm, | ||
| 1162 | unsigned long start, unsigned long nr_pages, | ||
| 1163 | unsigned int gup_flags, struct page **pages, | ||
| 1164 | struct vm_area_struct **vmas, int *locked) | ||
| 1165 | { | ||
| 1166 | /* | ||
| 1167 | * FIXME: Current FOLL_LONGTERM behavior is incompatible with | ||
| 1168 | * FAULT_FLAG_ALLOW_RETRY because of the FS DAX check requirement on | ||
| 1169 | * vmas. As there are no users of this flag in this call we simply | ||
| 1170 | * disallow this option for now. | ||
| 1171 | */ | ||
| 1172 | if (WARN_ON_ONCE(gup_flags & FOLL_LONGTERM)) | ||
| 1173 | return -EINVAL; | ||
| 1174 | |||
| 1175 | return __get_user_pages_locked(tsk, mm, start, nr_pages, pages, vmas, | ||
| 1176 | locked, | ||
| 1177 | gup_flags | FOLL_TOUCH | FOLL_REMOTE); | ||
| 1178 | } | ||
| 1179 | EXPORT_SYMBOL(get_user_pages_remote); | ||
| 1180 | |||
| 1181 | /** | 1127 | /** |
| 1182 | * populate_vma_page_range() - populate a range of pages in the vma. | 1128 | * populate_vma_page_range() - populate a range of pages in the vma. |
| 1183 | * @vma: target vma | 1129 | * @vma: target vma |
| @@ -1611,6 +1557,116 @@ static __always_inline long __gup_longterm_locked(struct task_struct *tsk, · 427 unmodified lines | |||
| 1611 | } | 1557 | } |
| 1612 | #endif /* CONFIG_FS_DAX || CONFIG_CMA */ | 1558 | #endif /* CONFIG_FS_DAX || CONFIG_CMA */ |
| 1613 | 1559 | ||
| 1560 | /* | ||
| 1561 | * get_user_pages_remote() - pin user pages in memory | ||
| 1562 | * @tsk: the task_struct to use for page fault accounting, or | ||
| 1563 | * NULL if faults are not to be recorded. | ||
| 1564 | * @mm: mm_struct of target mm | ||
| 1565 | * @start: starting user address | ||
| 1566 | * @nr_pages: number of pages from start to pin | ||
| 1567 | * @gup_flags: flags modifying lookup behaviour | ||
| 1568 | * @pages: array that receives pointers to the pages pinned. | ||
| 1569 | * Should be at least nr_pages long. Or NULL, if caller | ||
| 1570 | * only intends to ensure the pages are faulted in. | ||
| 1571 | * @vmas: array of pointers to vmas corresponding to each page. | ||
| 1572 | * Or NULL if the caller does not require them. | ||
| 1573 | * @locked: pointer to lock flag indicating whether lock is held and | ||
| 1574 | * subsequently whether VM_FAULT_RETRY functionality can be | ||
| 1575 | * utilised. Lock must initially be held. | ||
| 1576 | * | ||
| 1577 | * Returns either number of pages pinned (which may be less than the | ||
| 1578 | * number requested), or an error. Details about the return value: | ||
| 1579 | * | ||
| 1580 | * -- If nr_pages is 0, returns 0. | ||
| 1581 | * -- If nr_pages is >0, but no pages were pinned, returns -errno. | ||
| 1582 | * -- If nr_pages is >0, and some pages were pinned, returns the number of | ||
| 1583 | * pages pinned. Again, this may be less than nr_pages. | ||
| 1584 | * | ||
| 1585 | * The caller is responsible for releasing returned @pages, via put_page(). | ||
| 1586 | * | ||
| 1587 | * @vmas are valid only as long as mmap_sem is held. | ||
| 1588 | * | ||
| 1589 | * Must be called with mmap_sem held for read or write. | ||
| 1590 | * | ||
| 1591 | * get_user_pages walks a process's page tables and takes a reference to | ||
| 1592 | * each struct page that each user address corresponds to at a given | ||
| 1593 | * instant. That is, it takes the page that would be accessed if a user | ||
| 1594 | * thread accesses the given user virtual address at that instant. | ||
| 1595 | * | ||
| 1596 | * This does not guarantee that the page exists in the user mappings when | ||
| 1597 | * get_user_pages returns, and there may even be a completely different | ||
| 1598 | * page there in some cases (eg. if mmapped pagecache has been invalidated | ||
| 1599 | * and subsequently re faulted). However it does guarantee that the page | ||
| 1600 | * won't be freed completely. And mostly callers simply care that the page | ||
| 1601 | * contains data that was valid *at some point in time*. Typically, an IO | ||
| 1602 | * or similar operation cannot guarantee anything stronger anyway because | ||
| 1603 | * locks can't be held over the syscall boundary. | ||
| 1604 | * | ||
| 1605 | * If gup_flags & FOLL_WRITE == 0, the page must not be written to. If the page | ||
| 1606 | * is written to, set_page_dirty (or set_page_dirty_lock, as appropriate) must | ||
| 1607 | * be called after the page is finished with, and before put_page is called. | ||
| 1608 | * | ||
| 1609 | * get_user_pages is typically used for fewer-copy IO operations, to get a | ||
| 1610 | * handle on the memory by some means other than accesses via the user virtual | ||
| 1611 | * addresses. The pages may be submitted for DMA to devices or accessed via | ||
| 1612 | * their kernel linear mapping (via the kmap APIs). Care should be taken to | ||
| 1613 | * use the correct cache flushing APIs. | ||
| 1614 | * | ||
| 1615 | * See also get_user_pages_fast, for performance critical applications. | ||
| 1616 | * | ||
| 1617 | * get_user_pages should be phased out in favor of | ||
| 1618 | * get_user_pages_locked|unlocked or get_user_pages_fast. Nothing | ||
| 1619 | * should use get_user_pages because it cannot pass | ||
| 1620 | * FAULT_FLAG_ALLOW_RETRY to handle_mm_fault. | ||
| 1621 | */ | ||
| 1622 | #ifdef CONFIG_MMU | ||
| 1623 | long get_user_pages_remote(struct task_struct *tsk, struct mm_struct *mm, | ||
| 1624 | unsigned long start, unsigned long nr_pages, | ||
| 1625 | unsigned int gup_flags, struct page **pages, | ||
| 1626 | struct vm_area_struct **vmas, int *locked) | ||
| 1627 | { | ||
| 1628 | /* | ||
| 1629 | * FOLL_PIN must only be set internally by the pin_user_pages*() APIs, | ||
| 1630 | * never directly by the caller, so enforce that with an assertion: | ||
| 1631 | */ | ||
| 1632 | if (WARN_ON_ONCE(gup_flags & FOLL_PIN)) | ||
| 1633 | return -EINVAL; | ||
| 1634 | |||
| 1635 | /* | ||
| 1636 | * Parts of FOLL_LONGTERM behavior are incompatible with | ||
| 1637 | * FAULT_FLAG_ALLOW_RETRY because of the FS DAX check requirement on | ||
| 1638 | * vmas. However, this only comes up if locked is set, and there are | ||
| 1639 | * callers that do request FOLL_LONGTERM, but do not set locked. So, | ||
| 1640 | * allow what we can. | ||
| 1641 | */ | ||
| 1642 | if (gup_flags & FOLL_LONGTERM) { | ||
| 1643 | if (WARN_ON_ONCE(locked)) | ||
| 1644 | return -EINVAL; | ||
| 1645 | /* | ||
| 1646 | * This will check the vmas (even if our vmas arg is NULL) | ||
| 1647 | * and return -ENOTSUPP if DAX isn't allowed in this case: | ||
| 1648 | */ | ||
| 1649 | return __gup_longterm_locked(tsk, mm, start, nr_pages, pages, | ||
| 1650 | vmas, gup_flags | FOLL_TOUCH | | ||
| 1651 | FOLL_REMOTE); | ||
| 1652 | } | ||
| 1653 | |||
| 1654 | return __get_user_pages_locked(tsk, mm, start, nr_pages, pages, vmas, | ||
| 1655 | locked, | ||
| 1656 | gup_flags | FOLL_TOUCH | FOLL_REMOTE); | ||
| 1657 | } | ||
| 1658 | EXPORT_SYMBOL(get_user_pages_remote); | ||
| 1659 | |||
| 1660 | #else /* CONFIG_MMU */ | ||
| 1661 | long get_user_pages_remote(struct task_struct *tsk, struct mm_struct *mm, | ||
| 1662 | unsigned long start, unsigned long nr_pages, | ||
| 1663 | unsigned int gup_flags, struct page **pages, | ||
| 1664 | struct vm_area_struct **vmas, int *locked) | ||
| 1665 | { | ||
| 1666 | return 0; | ||
| 1667 | } | ||
| 1668 | #endif /* !CONFIG_MMU */ | ||
| 1669 | |||
| 1614 | /* | 1670 | /* |
| 1615 | * This is the same as get_user_pages_remote(), just with a | 1671 | * This is the same as get_user_pages_remote(), just with a |
| 1616 | * less-flexible calling convention where we assume that the task | 1672 | * less-flexible calling convention where we assume that the task |
| @@ -1622,6 +1678,13 @@ long get_user_pages(unsigned long start, unsigned long nr_pages, · 5 unmodified lines | |||
| 1622 | unsigned int gup_flags, struct page **pages, | 1678 | unsigned int gup_flags, struct page **pages, |
| 1623 | struct vm_area_struct **vmas) | 1679 | struct vm_area_struct **vmas) |
| 1624 | { | 1680 | { |
| 1681 | /* | ||
| 1682 | * FOLL_PIN must only be set internally by the pin_user_pages*() APIs, | ||
| 1683 | * never directly by the caller, so enforce that with an assertion: | ||
| 1684 | */ | ||
| 1685 | if (WARN_ON_ONCE(gup_flags & FOLL_PIN)) | ||
| 1686 | return -EINVAL; | ||
| 1687 | |||
| 1625 | return __gup_longterm_locked(current, current->mm, start, nr_pages, | 1688 | return __gup_longterm_locked(current, current->mm, start, nr_pages, |
| 1626 | pages, vmas, gup_flags | FOLL_TOUCH); | 1689 | pages, vmas, gup_flags | FOLL_TOUCH); |
| 1627 | } | 1690 | } |
| @@ -1807,20 +1870,6 @@ static void __maybe_unused undo_dev_pagemap(int *nr, int nr_start, · 179 unmodified lines | |||
| 1807 | } | 1870 | } |
| 1808 | } | 1871 | } |
| 1809 | 1872 | ||
| 1810 | /* | ||
| 1811 | * Return the compund head page with ref appropriately incremented, | ||
| 1812 | * or NULL if that failed. | ||
| 1813 | */ | ||
| 1814 | static inline struct page *try_get_compound_head(struct page *page, int refs) | ||
| 1815 | { | ||
| 1816 | struct page *head = compound_head(page); | ||
| 1817 | if (WARN_ON_ONCE(page_ref_count(head) < 0)) | ||
| 1818 | return NULL; | ||
| 1819 | if (unlikely(!page_cache_add_speculative(head, refs))) | ||
| 1820 | return NULL; | ||
| 1821 | return head; | ||
| 1822 | } | ||
| 1823 | |||
| 1824 | #ifdef CONFIG_ARCH_HAS_PTE_SPECIAL | 1873 | #ifdef CONFIG_ARCH_HAS_PTE_SPECIAL |
| 1825 | static int gup_pte_range(pmd_t pmd, unsigned long addr, unsigned long end, | 1874 | static int gup_pte_range(pmd_t pmd, unsigned long addr, unsigned long end, |
| 1826 | unsigned int flags, struct page **pages, int *nr) | 1875 | unsigned int flags, struct page **pages, int *nr) |
| @@ -1978,6 +2027,29 @@ static int __gup_device_huge_pud(pud_t pud, pud_t *pudp, unsigned long addr, · 151 unmodified lines | |||
| 1978 | } | 2027 | } |
| 1979 | #endif | 2028 | #endif |
| 1980 | 2029 | ||
| 2030 | static int record_subpages(struct page *page, unsigned long addr, | ||
| 2031 | unsigned long end, struct page **pages) | ||
| 2032 | { | ||
| 2033 | int nr; | ||
| 2034 | |||
| 2035 | for (nr = 0; addr != end; addr += PAGE_SIZE) | ||
| 2036 | pages[nr++] = page++; | ||
| 2037 | |||
| 2038 | return nr; | ||
| 2039 | } | ||
| 2040 | |||
| 2041 | static void put_compound_head(struct page *page, int refs) | ||
| 2042 | { | ||
| 2043 | VM_BUG_ON_PAGE(page_ref_count(page) < refs, page); | ||
| 2044 | /* | ||
| 2045 | * Calling put_page() for each ref is unnecessarily slow. Only the last | ||
| 2046 | * ref needs a put_page(). | ||
| 2047 | */ | ||
| 2048 | if (refs > 1) | ||
| 2049 | page_ref_sub(page, refs - 1); | ||
| 2050 | put_page(page); | ||
| 2051 | } | ||
| 2052 | |||
| 1981 | #ifdef CONFIG_ARCH_HAS_HUGEPD | 2053 | #ifdef CONFIG_ARCH_HAS_HUGEPD |
| 1982 | static unsigned long hugepte_addr_end(unsigned long addr, unsigned long end, | 2054 | static unsigned long hugepte_addr_end(unsigned long addr, unsigned long end, |
| 1983 | unsigned long sz) | 2055 | unsigned long sz) |
| @@ -2007,32 +2079,20 @@ static int gup_hugepte(pte_t *ptep, unsigned long sz, unsigned long addr, · 23 unmodified lines | |||
| 2007 | /* hugepages are never "special" */ | 2079 | /* hugepages are never "special" */ |
| 2008 | VM_BUG_ON(!pfn_valid(pte_pfn(pte))); | 2080 | VM_BUG_ON(!pfn_valid(pte_pfn(pte))); |
| 2009 | 2081 | ||
| 2010 | refs = 0; | ||
| 2011 | head = pte_page(pte); | 2082 | head = pte_page(pte); |
| 2012 | |||
| 2013 | page = head + ((addr & (sz-1)) >> PAGE_SHIFT); | 2083 | page = head + ((addr & (sz-1)) >> PAGE_SHIFT); |
| 2014 | do { | 2084 | refs = record_subpages(page, addr, end, pages + *nr); |
| 2015 | VM_BUG_ON(compound_head(page) != head); | ||
| 2016 | pages[*nr] = page; | ||
| 2017 | (*nr)++; | ||
| 2018 | page++; | ||
| 2019 | refs++; | ||
| 2020 | } while (addr += PAGE_SIZE, addr != end); | ||
| 2021 | 2085 | ||
| 2022 | head = try_get_compound_head(head, refs); | 2086 | head = try_get_compound_head(head, refs); |
| 2023 | if (!head) { | 2087 | if (!head) |
| 2024 | *nr -= refs; | ||
| 2025 | return 0; | 2088 | return 0; |
| 2026 | } | ||
| 2027 | 2089 | ||
| 2028 | if (unlikely(pte_val(pte) != pte_val(*ptep))) { | 2090 | if (unlikely(pte_val(pte) != pte_val(*ptep))) { |
| 2029 | /* Could be optimized better */ | 2091 | put_compound_head(head, refs); |
| 2030 | *nr -= refs; | ||
| 2031 | while (refs--) | ||
| 2032 | put_page(head); | ||
| 2033 | return 0; | 2092 | return 0; |
| 2034 | } | 2093 | } |
| 2035 | 2094 | ||
| 2095 | *nr += refs; | ||
| 2036 | SetPageReferenced(head); | 2096 | SetPageReferenced(head); |
| 2037 | return 1; | 2097 | return 1; |
| 2038 | } | 2098 | } |
| @@ -2079,28 +2139,19 @@ static int gup_huge_pmd(pmd_t orig, pmd_t *pmdp, unsigned long addr, · 40 unmodified lines | |||
| 2079 | return __gup_device_huge_pmd(orig, pmdp, addr, end, pages, nr); | 2139 | return __gup_device_huge_pmd(orig, pmdp, addr, end, pages, nr); |
| 2080 | } | 2140 | } |
| 2081 | 2141 | ||
| 2082 | refs = 0; | ||
| 2083 | page = pmd_page(orig) + ((addr & ~PMD_MASK) >> PAGE_SHIFT); | 2142 | page = pmd_page(orig) + ((addr & ~PMD_MASK) >> PAGE_SHIFT); |
| 2084 | do { | 2143 | refs = record_subpages(page, addr, end, pages + *nr); |
| 2085 | pages[*nr] = page; | ||
| 2086 | (*nr)++; | ||
| 2087 | page++; | ||
| 2088 | refs++; | ||
| 2089 | } while (addr += PAGE_SIZE, addr != end); | ||
| 2090 | 2144 | ||
| 2091 | head = try_get_compound_head(pmd_page(orig), refs); | 2145 | head = try_get_compound_head(pmd_page(orig), refs); |
| 2092 | if (!head) { | 2146 | if (!head) |
| 2093 | *nr -= refs; | ||
| 2094 | return 0; | 2147 | return 0; |
| 2095 | } | ||
| 2096 | 2148 | ||
| 2097 | if (unlikely(pmd_val(orig) != pmd_val(*pmdp))) { | 2149 | if (unlikely(pmd_val(orig) != pmd_val(*pmdp))) { |
| 2098 | *nr -= refs; | 2150 | put_compound_head(head, refs); |
| 2099 | while (refs--) | ||
| 2100 | put_page(head); | ||
| 2101 | return 0; | 2151 | return 0; |
| 2102 | } | 2152 | } |
| 2103 | 2153 | ||
| 2154 | *nr += refs; | ||
| 2104 | SetPageReferenced(head); | 2155 | SetPageReferenced(head); |
| 2105 | return 1; | 2156 | return 1; |
| 2106 | } | 2157 | } |
| @@ -2120,28 +2171,19 @@ static int gup_huge_pud(pud_t orig, pud_t *pudp, unsigned long addr, · 13 unmodified lines | |||
| 2120 | return __gup_device_huge_pud(orig, pudp, addr, end, pages, nr); | 2171 | return __gup_device_huge_pud(orig, pudp, addr, end, pages, nr); |
| 2121 | } | 2172 | } |
| 2122 | 2173 | ||
| 2123 | refs = 0; | ||
| 2124 | page = pud_page(orig) + ((addr & ~PUD_MASK) >> PAGE_SHIFT); | 2174 | page = pud_page(orig) + ((addr & ~PUD_MASK) >> PAGE_SHIFT); |
| 2125 | do { | 2175 | refs = record_subpages(page, addr, end, pages + *nr); |
| 2126 | pages[*nr] = page; | ||
| 2127 | (*nr)++; | ||
| 2128 | page++; | ||
| 2129 | refs++; | ||
| 2130 | } while (addr += PAGE_SIZE, addr != end); | ||
| 2131 | 2176 | ||
| 2132 | head = try_get_compound_head(pud_page(orig), refs); | 2177 | head = try_get_compound_head(pud_page(orig), refs); |
| 2133 | if (!head) { | 2178 | if (!head) |
| 2134 | *nr -= refs; | ||
| 2135 | return 0; | 2179 | return 0; |
| 2136 | } | ||
| 2137 | 2180 | ||
| 2138 | if (unlikely(pud_val(orig) != pud_val(*pudp))) { | 2181 | if (unlikely(pud_val(orig) != pud_val(*pudp))) { |
| 2139 | *nr -= refs; | 2182 | put_compound_head(head, refs); |
| 2140 | while (refs--) | ||
| 2141 | put_page(head); | ||
| 2142 | return 0; | 2183 | return 0; |
| 2143 | } | 2184 | } |
| 2144 | 2185 | ||
| 2186 | *nr += refs; | ||
| 2145 | SetPageReferenced(head); | 2187 | SetPageReferenced(head); |
| 2146 | return 1; | 2188 | return 1; |
| 2147 | } | 2189 | } |
| @@ -2157,28 +2199,20 @@ static int gup_huge_pgd(pgd_t orig, pgd_t *pgdp, unsigned long addr, · 9 unmodified lines | |||
| 2157 | return 0; | 2199 | return 0; |
| 2158 | 2200 | ||
| 2159 | BUILD_BUG_ON(pgd_devmap(orig)); | 2201 | BUILD_BUG_ON(pgd_devmap(orig)); |
| 2160 | refs = 0; | 2202 | |
| 2161 | page = pgd_page(orig) + ((addr & ~PGDIR_MASK) >> PAGE_SHIFT); | 2203 | page = pgd_page(orig) + ((addr & ~PGDIR_MASK) >> PAGE_SHIFT); |
| 2162 | do { | 2204 | refs = record_subpages(page, addr, end, pages + *nr); |
| 2163 | pages[*nr] = page; | ||
| 2164 | (*nr)++; | ||
| 2165 | page++; | ||
| 2166 | refs++; | ||
| 2167 | } while (addr += PAGE_SIZE, addr != end); | ||
| 2168 | 2205 | ||
| 2169 | head = try_get_compound_head(pgd_page(orig), refs); | 2206 | head = try_get_compound_head(pgd_page(orig), refs); |
| 2170 | if (!head) { | 2207 | if (!head) |
| 2171 | *nr -= refs; | ||
| 2172 | return 0; | 2208 | return 0; |
| 2173 | } | ||
| 2174 | 2209 | ||
| 2175 | if (unlikely(pgd_val(orig) != pgd_val(*pgdp))) { | 2210 | if (unlikely(pgd_val(orig) != pgd_val(*pgdp))) { |
| 2176 | *nr -= refs; | 2211 | put_compound_head(head, refs); |
| 2177 | while (refs--) | ||
| 2178 | put_page(head); | ||
| 2179 | return 0; | 2212 | return 0; |
| 2180 | } | 2213 | } |
| 2181 | 2214 | ||
| 2215 | *nr += refs; | ||
| 2182 | SetPageReferenced(head); | 2216 | SetPageReferenced(head); |
| 2183 | return 1; | 2217 | return 1; |
| 2184 | } | 2218 | } |
| @@ -2237,7 +2271,7 @@ static int gup_pud_range(p4d_t p4d, unsigned long addr, unsigned long end, · 52 unmodified lines | |||
| 2237 | pud_t pud = READ_ONCE(*pudp); | 2271 | pud_t pud = READ_ONCE(*pudp); |
| 2238 | 2272 | ||
| 2239 | next = pud_addr_end(addr, end); | 2273 | next = pud_addr_end(addr, end); |
| 2240 | if (pud_none(pud)) | 2274 | if (unlikely(!pud_present(pud))) |
| 2241 | return 0; | 2275 | return 0; |
| 2242 | if (unlikely(pud_huge(pud))) { | 2276 | if (unlikely(pud_huge(pud))) { |
| 2243 | if (!gup_huge_pud(pud, pudp, addr, next, flags, | 2277 | if (!gup_huge_pud(pud, pudp, addr, next, flags, |
| @@ -2393,29 +2427,15 @@ static int __gup_longterm_unlocked(unsigned long start, int nr_pages, · 149 unmodified lines | |||
| 2393 | return ret; | 2427 | return ret; |
| 2394 | } | 2428 | } |
| 2395 | 2429 | ||
| 2396 | /** | 2430 | static int internal_get_user_pages_fast(unsigned long start, int nr_pages, |
| 2397 | * get_user_pages_fast() - pin user pages in memory | 2431 | unsigned int gup_flags, |
| 2398 | * @start: starting user address | 2432 | struct page **pages) |
| 2399 | * @nr_pages: number of pages from start to pin | ||
| 2400 | * @gup_flags: flags modifying pin behaviour | ||
| 2401 | * @pages: array that receives pointers to the pages pinned. | ||
| 2402 | * Should be at least nr_pages long. | ||
| 2403 | * | ||
| 2404 | * Attempt to pin user pages in memory without taking mm->mmap_sem. | ||
| 2405 | * If not successful, it will fall back to taking the lock and | ||
| 2406 | * calling get_user_pages(). | ||
| 2407 | * | ||
| 2408 | * Returns number of pages pinned. This may be fewer than the number | ||
| 2409 | * requested. If nr_pages is 0 or negative, returns 0. If no pages | ||
| 2410 | * were pinned, returns -errno. | ||
| 2411 | */ | ||
| 2412 | int get_user_pages_fast(unsigned long start, int nr_pages, | ||
| 2413 | unsigned int gup_flags, struct page **pages) | ||
| 2414 | { | 2433 | { |
| 2415 | unsigned long addr, len, end; | 2434 | unsigned long addr, len, end; |
| 2416 | int nr = 0, ret = 0; | 2435 | int nr = 0, ret = 0; |
| 2417 | 2436 | ||
| 2418 | if (WARN_ON_ONCE(gup_flags & ~(FOLL_WRITE | FOLL_LONGTERM))) | 2437 | if (WARN_ON_ONCE(gup_flags & ~(FOLL_WRITE | FOLL_LONGTERM | |
| 2438 | FOLL_FORCE | FOLL_PIN))) | ||
| 2419 | return -EINVAL; | 2439 | return -EINVAL; |
| 2420 | 2440 | ||
| 2421 | start = untagged_addr(start) & PAGE_MASK; | 2441 | start = untagged_addr(start) & PAGE_MASK; |
| @@ -2455,4 +2475,103 @@ int get_user_pages_fast(unsigned long start, int nr_pages, · 33 unmodified lines | |||
| 2455 | 2475 | ||
| 2456 | return ret; | 2476 | return ret; |
| 2457 | } | 2477 | } |
| 2478 | |||
| 2479 | /** | ||
| 2480 | * get_user_pages_fast() - pin user pages in memory | ||
| 2481 | * @start: starting user address | ||
| 2482 | * @nr_pages: number of pages from start to pin | ||
| 2483 | * @gup_flags: flags modifying pin behaviour | ||
| 2484 | * @pages: array that receives pointers to the pages pinned. | ||
| 2485 | * Should be at least nr_pages long. | ||
| 2486 | * | ||
| 2487 | * Attempt to pin user pages in memory without taking mm->mmap_sem. | ||
| 2488 | * If not successful, it will fall back to taking the lock and | ||
| 2489 | * calling get_user_pages(). | ||
| 2490 | * | ||
| 2491 | * Returns number of pages pinned. This may be fewer than the number requested. | ||
| 2492 | * If nr_pages is 0 or negative, returns 0. If no pages were pinned, returns | ||
| 2493 | * -errno. | ||
| 2494 | */ | ||
| 2495 | int get_user_pages_fast(unsigned long start, int nr_pages, | ||
| 2496 | unsigned int gup_flags, struct page **pages) | ||
| 2497 | { | ||
| 2498 | /* | ||
| 2499 | * FOLL_PIN must only be set internally by the pin_user_pages*() APIs, | ||
| 2500 | * never directly by the caller, so enforce that: | ||
| 2501 | */ | ||
| 2502 | if (WARN_ON_ONCE(gup_flags & FOLL_PIN)) | ||
| 2503 | return -EINVAL; | ||
| 2504 | |||
| 2505 | return internal_get_user_pages_fast(start, nr_pages, gup_flags, pages); | ||
| 2506 | } | ||
| 2458 | EXPORT_SYMBOL_GPL(get_user_pages_fast); | 2507 | EXPORT_SYMBOL_GPL(get_user_pages_fast); |
| 2508 | |||
| 2509 | /** | ||
| 2510 | * pin_user_pages_fast() - pin user pages in memory without taking locks | ||
| 2511 | * | ||
| 2512 | * For now, this is a placeholder function, until various call sites are | ||
| 2513 | * converted to use the correct get_user_pages*() or pin_user_pages*() API. So, | ||
| 2514 | * this is identical to get_user_pages_fast(). | ||
| 2515 | * | ||
| 2516 | * This is intended for Case 1 (DIO) in Documentation/vm/pin_user_pages.rst. It | ||
| 2517 | * is NOT intended for Case 2 (RDMA: long-term pins). | ||
| 2518 | */ | ||
| 2519 | int pin_user_pages_fast(unsigned long start, int nr_pages, | ||
| 2520 | unsigned int gup_flags, struct page **pages) | ||
| 2521 | { | ||
| 2522 | /* | ||
| 2523 | * This is a placeholder, until the pin functionality is activated. | ||
| 2524 | * Until then, just behave like the corresponding get_user_pages*() | ||
| 2525 | * routine. | ||
| 2526 | */ | ||
| 2527 | return get_user_pages_fast(start, nr_pages, gup_flags, pages); | ||
| 2528 | } | ||
| 2529 | EXPORT_SYMBOL_GPL(pin_user_pages_fast); | ||
| 2530 | |||
| 2531 | /** | ||
| 2532 | * pin_user_pages_remote() - pin pages of a remote process (task != current) | ||
| 2533 | * | ||
| 2534 | * For now, this is a placeholder function, until various call sites are | ||
| 2535 | * converted to use the correct get_user_pages*() or pin_user_pages*() API. So, | ||
| 2536 | * this is identical to get_user_pages_remote(). | ||
| 2537 | * | ||
| 2538 | * This is intended for Case 1 (DIO) in Documentation/vm/pin_user_pages.rst. It | ||
| 2539 | * is NOT intended for Case 2 (RDMA: long-term pins). | ||
| 2540 | */ | ||
| 2541 | long pin_user_pages_remote(struct task_struct *tsk, struct mm_struct *mm, | ||
| 2542 | unsigned long start, unsigned long nr_pages, | ||
| 2543 | unsigned int gup_flags, struct page **pages, | ||
| 2544 | struct vm_area_struct **vmas, int *locked) | ||
| 2545 | { | ||
| 2546 | /* | ||
| 2547 | * This is a placeholder, until the pin functionality is activated. | ||
| 2548 | * Until then, just behave like the corresponding get_user_pages*() | ||
| 2549 | * routine. | ||
| 2550 | */ | ||
| 2551 | return get_user_pages_remote(tsk, mm, start, nr_pages, gup_flags, pages, | ||
| 2552 | vmas, locked); | ||
| 2553 | } | ||
| 2554 | EXPORT_SYMBOL(pin_user_pages_remote); | ||
| 2555 | |||
| 2556 | /** | ||
| 2557 | * pin_user_pages() - pin user pages in memory for use by other devices | ||
| 2558 | * | ||
| 2559 | * For now, this is a placeholder function, until various call sites are | ||
| 2560 | * converted to use the correct get_user_pages*() or pin_user_pages*() API. So, | ||
| 2561 | * this is identical to get_user_pages(). | ||
| 2562 | * | ||
| 2563 | * This is intended for Case 1 (DIO) in Documentation/vm/pin_user_pages.rst. It | ||
| 2564 | * is NOT intended for Case 2 (RDMA: long-term pins). | ||
| 2565 | */ | ||
| 2566 | long pin_user_pages(unsigned long start, unsigned long nr_pages, | ||
| 2567 | unsigned int gup_flags, struct page **pages, | ||
| 2568 | struct vm_area_struct **vmas) | ||
| 2569 | { | ||
| 2570 | /* | ||
| 2571 | * This is a placeholder, until the pin functionality is activated. | ||
| 2572 | * Until then, just behave like the corresponding get_user_pages*() | ||
| 2573 | * routine. | ||
| 2574 | */ | ||
| 2575 | return get_user_pages(start, nr_pages, gup_flags, pages, vmas); | ||
| 2576 | } | ||
| 2577 | EXPORT_SYMBOL(pin_user_pages); | ||
| @@ -49,18 +49,21 @@ static int __gup_benchmark_ioctl(unsigned int cmd, · 48 unmodified lines | |||
| 49 | nr = (next - addr) / PAGE_SIZE; | 49 | nr = (next - addr) / PAGE_SIZE; |
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | /* Filter out most gup flags: only allow a tiny subset here: */ | ||
| 53 | gup->flags &= FOLL_WRITE; | ||
| 54 | |||
| 52 | switch (cmd) { | 55 | switch (cmd) { |
| 53 | case GUP_FAST_BENCHMARK: | 56 | case GUP_FAST_BENCHMARK: |
| 54 | nr = get_user_pages_fast(addr, nr, gup->flags & 1, | 57 | nr = get_user_pages_fast(addr, nr, gup->flags, |
| 55 | pages + i); | 58 | pages + i); |
| 56 | break; | 59 | break; |
| 57 | case GUP_LONGTERM_BENCHMARK: | 60 | case GUP_LONGTERM_BENCHMARK: |
| 58 | nr = get_user_pages(addr, nr, | 61 | nr = get_user_pages(addr, nr, |
| 59 | (gup->flags & 1) | FOLL_LONGTERM, | 62 | gup->flags | FOLL_LONGTERM, |
| 60 | pages + i, NULL); | 63 | pages + i, NULL); |
| 61 | break; | 64 | break; |
| 62 | case GUP_BENCHMARK: | 65 | case GUP_BENCHMARK: |
| 63 | nr = get_user_pages(addr, nr, gup->flags & 1, pages + i, | 66 | nr = get_user_pages(addr, nr, gup->flags, pages + i, |
| 64 | NULL); | 67 | NULL); |
| 65 | break; | 68 | break; |
| 66 | default: | 69 | default: |
| @@ -177,16 +177,13 @@ static ssize_t enabled_store(struct kobject *kobj, · 176 unmodified lines | |||
| 177 | { | 177 | { |
| 178 | ssize_t ret = count; | 178 | ssize_t ret = count; |
| 179 | 179 | ||
| 180 | if (!memcmp("always", buf, | 180 | if (sysfs_streq(buf, "always")) { |
| 181 | min(sizeof("always")-1, count))) { | ||
| 182 | clear_bit(TRANSPARENT_HUGEPAGE_REQ_MADV_FLAG, &transparent_hugepage_flags); | 181 | clear_bit(TRANSPARENT_HUGEPAGE_REQ_MADV_FLAG, &transparent_hugepage_flags); |
| 183 | set_bit(TRANSPARENT_HUGEPAGE_FLAG, &transparent_hugepage_flags); | 182 | set_bit(TRANSPARENT_HUGEPAGE_FLAG, &transparent_hugepage_flags); |
| 184 | } else if (!memcmp("madvise", buf, | 183 | } else if (sysfs_streq(buf, "madvise")) { |
| 185 | min(sizeof("madvise")-1, count))) { | ||
| 186 | clear_bit(TRANSPARENT_HUGEPAGE_FLAG, &transparent_hugepage_flags); | 184 | clear_bit(TRANSPARENT_HUGEPAGE_FLAG, &transparent_hugepage_flags); |
| 187 | set_bit(TRANSPARENT_HUGEPAGE_REQ_MADV_FLAG, &transparent_hugepage_flags); | 185 | set_bit(TRANSPARENT_HUGEPAGE_REQ_MADV_FLAG, &transparent_hugepage_flags); |
| 188 | } else if (!memcmp("never", buf, | 186 | } else if (sysfs_streq(buf, "never")) { |
| 189 | min(sizeof("never")-1, count))) { | ||
| 190 | clear_bit(TRANSPARENT_HUGEPAGE_FLAG, &transparent_hugepage_flags); | 187 | clear_bit(TRANSPARENT_HUGEPAGE_FLAG, &transparent_hugepage_flags); |
| 191 | clear_bit(TRANSPARENT_HUGEPAGE_REQ_MADV_FLAG, &transparent_hugepage_flags); | 188 | clear_bit(TRANSPARENT_HUGEPAGE_REQ_MADV_FLAG, &transparent_hugepage_flags); |
| 192 | } else | 189 | } else |
| @@ -250,32 +247,27 @@ static ssize_t defrag_store(struct kobject *kobj, · 57 unmodified lines | |||
| 250 | struct kobj_attribute *attr, | 247 | struct kobj_attribute *attr, |
| 251 | const char *buf, size_t count) | 248 | const char *buf, size_t count) |
| 252 | { | 249 | { |
| 253 | if (!memcmp("always", buf, | 250 | if (sysfs_streq(buf, "always")) { |
| 254 | min(sizeof("always")-1, count))) { | ||
| 255 | clear_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_FLAG, &transparent_hugepage_flags); | 251 | clear_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_FLAG, &transparent_hugepage_flags); |
| 256 | clear_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_OR_MADV_FLAG, &transparent_hugepage_flags); | 252 | clear_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_OR_MADV_FLAG, &transparent_hugepage_flags); |
| 257 | clear_bit(TRANSPARENT_HUGEPAGE_DEFRAG_REQ_MADV_FLAG, &transparent_hugepage_flags); | 253 | clear_bit(TRANSPARENT_HUGEPAGE_DEFRAG_REQ_MADV_FLAG, &transparent_hugepage_flags); |
| 258 | set_bit(TRANSPARENT_HUGEPAGE_DEFRAG_DIRECT_FLAG, &transparent_hugepage_flags); | 254 | set_bit(TRANSPARENT_HUGEPAGE_DEFRAG_DIRECT_FLAG, &transparent_hugepage_flags); |
| 259 | } else if (!memcmp("defer+madvise", buf, | 255 | } else if (sysfs_streq(buf, "defer+madvise")) { |
| 260 | min(sizeof("defer+madvise")-1, count))) { | ||
| 261 | clear_bit(TRANSPARENT_HUGEPAGE_DEFRAG_DIRECT_FLAG, &transparent_hugepage_flags); | 256 | clear_bit(TRANSPARENT_HUGEPAGE_DEFRAG_DIRECT_FLAG, &transparent_hugepage_flags); |
| 262 | clear_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_FLAG, &transparent_hugepage_flags); | 257 | clear_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_FLAG, &transparent_hugepage_flags); |
| 263 | clear_bit(TRANSPARENT_HUGEPAGE_DEFRAG_REQ_MADV_FLAG, &transparent_hugepage_flags); | 258 | clear_bit(TRANSPARENT_HUGEPAGE_DEFRAG_REQ_MADV_FLAG, &transparent_hugepage_flags); |
| 264 | set_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_OR_MADV_FLAG, &transparent_hugepage_flags); | 259 | set_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_OR_MADV_FLAG, &transparent_hugepage_flags); |
| 265 | } else if (!memcmp("defer", buf, | 260 | } else if (sysfs_streq(buf, "defer")) { |
| 266 | min(sizeof("defer")-1, count))) { | ||
| 267 | clear_bit(TRANSPARENT_HUGEPAGE_DEFRAG_DIRECT_FLAG, &transparent_hugepage_flags); | 261 | clear_bit(TRANSPARENT_HUGEPAGE_DEFRAG_DIRECT_FLAG, &transparent_hugepage_flags); |
| 268 | clear_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_OR_MADV_FLAG, &transparent_hugepage_flags); | 262 | clear_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_OR_MADV_FLAG, &transparent_hugepage_flags); |
| 269 | clear_bit(TRANSPARENT_HUGEPAGE_DEFRAG_REQ_MADV_FLAG, &transparent_hugepage_flags); | 263 | clear_bit(TRANSPARENT_HUGEPAGE_DEFRAG_REQ_MADV_FLAG, &transparent_hugepage_flags); |
| 270 | set_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_FLAG, &transparent_hugepage_flags); | 264 | set_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_FLAG, &transparent_hugepage_flags); |
| 271 | } else if (!memcmp("madvise", buf, | 265 | } else if (sysfs_streq(buf, "madvise")) { |
| 272 | min(sizeof("madvise")-1, count))) { | ||
| 273 | clear_bit(TRANSPARENT_HUGEPAGE_DEFRAG_DIRECT_FLAG, &transparent_hugepage_flags); | 266 | clear_bit(TRANSPARENT_HUGEPAGE_DEFRAG_DIRECT_FLAG, &transparent_hugepage_flags); |
| 274 | clear_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_FLAG, &transparent_hugepage_flags); | 267 | clear_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_FLAG, &transparent_hugepage_flags); |
| 275 | clear_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_OR_MADV_FLAG, &transparent_hugepage_flags); | 268 | clear_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_OR_MADV_FLAG, &transparent_hugepage_flags); |
| 276 | set_bit(TRANSPARENT_HUGEPAGE_DEFRAG_REQ_MADV_FLAG, &transparent_hugepage_flags); | 269 | set_bit(TRANSPARENT_HUGEPAGE_DEFRAG_REQ_MADV_FLAG, &transparent_hugepage_flags); |
| 277 | } else if (!memcmp("never", buf, | 270 | } else if (sysfs_streq(buf, "never")) { |
| 278 | min(sizeof("never")-1, count))) { | ||
| 279 | clear_bit(TRANSPARENT_HUGEPAGE_DEFRAG_DIRECT_FLAG, &transparent_hugepage_flags); | 271 | clear_bit(TRANSPARENT_HUGEPAGE_DEFRAG_DIRECT_FLAG, &transparent_hugepage_flags); |
| 280 | clear_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_FLAG, &transparent_hugepage_flags); | 272 | clear_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_FLAG, &transparent_hugepage_flags); |
| 281 | clear_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_OR_MADV_FLAG, &transparent_hugepage_flags); | 273 | clear_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_OR_MADV_FLAG, &transparent_hugepage_flags); |
| @@ -2715,7 +2707,7 @@ int split_huge_page_to_list(struct page *page, struct list_head *list) · 2433 unmodified lines | |||
| 2715 | { | 2707 | { |
| 2716 | struct page *head = compound_head(page); | 2708 | struct page *head = compound_head(page); |
| 2717 | struct pglist_data *pgdata = NODE_DATA(page_to_nid(head)); | 2709 | struct pglist_data *pgdata = NODE_DATA(page_to_nid(head)); |
| 2718 | struct deferred_split *ds_queue = get_deferred_split_queue(page); | 2710 | struct deferred_split *ds_queue = get_deferred_split_queue(head); |
| 2719 | struct anon_vma *anon_vma = NULL; | 2711 | struct anon_vma *anon_vma = NULL; |
| 2720 | struct address_space *mapping = NULL; | 2712 | struct address_space *mapping = NULL; |
| 2721 | int count, mapcount, extra_pins, ret; | 2713 | int count, mapcount, extra_pins, ret; |
| @@ -2723,11 +2715,11 @@ int split_huge_page_to_list(struct page *page, struct list_head *list) · 1 unmodified line | |||
| 2723 | unsigned long flags; | 2715 | unsigned long flags; |
| 2724 | pgoff_t end; | 2716 | pgoff_t end; |
| 2725 | 2717 | ||
| 2726 | VM_BUG_ON_PAGE(is_huge_zero_page(page), page); | 2718 | VM_BUG_ON_PAGE(is_huge_zero_page(head), head); |
| 2727 | VM_BUG_ON_PAGE(!PageLocked(page), page); | 2719 | VM_BUG_ON_PAGE(!PageLocked(head), head); |
| 2728 | VM_BUG_ON_PAGE(!PageCompound(page), page); | 2720 | VM_BUG_ON_PAGE(!PageCompound(head), head); |
| 2729 | 2721 | ||
| 2730 | if (PageWriteback(page)) | 2722 | if (PageWriteback(head)) |
| 2731 | return -EBUSY; | 2723 | return -EBUSY; |
| 2732 | 2724 | ||
| 2733 | if (PageAnon(head)) { | 2725 | if (PageAnon(head)) { |
| @@ -2778,7 +2770,7 @@ int split_huge_page_to_list(struct page *page, struct list_head *list) · 44 unmodified lines | |||
| 2778 | goto out_unlock; | 2770 | goto out_unlock; |
| 2779 | } | 2771 | } |
| 2780 | 2772 | ||
| 2781 | mlocked = PageMlocked(page); | 2773 | mlocked = PageMlocked(head); |
| 2782 | unmap_page(head); | 2774 | unmap_page(head); |
| 2783 | VM_BUG_ON_PAGE(compound_mapcount(head), head); | 2775 | VM_BUG_ON_PAGE(compound_mapcount(head), head); |
| 2784 | 2776 | ||
| @@ -2810,14 +2802,14 @@ int split_huge_page_to_list(struct page *page, struct list_head *list) · 25 unmodified lines | |||
| 2810 | ds_queue->split_queue_len--; | 2802 | ds_queue->split_queue_len--; |
| 2811 | list_del(page_deferred_list(head)); | 2803 | list_del(page_deferred_list(head)); |
| 2812 | } | 2804 | } |
| 2805 | spin_unlock(&ds_queue->split_queue_lock); | ||
| 2813 | if (mapping) { | 2806 | if (mapping) { |
| 2814 | if (PageSwapBacked(page)) | 2807 | if (PageSwapBacked(head)) |
| 2815 | __dec_node_page_state(page, NR_SHMEM_THPS); | 2808 | __dec_node_page_state(head, NR_SHMEM_THPS); |
| 2816 | else | 2809 | else |
| 2817 | __dec_node_page_state(page, NR_FILE_THPS); | 2810 | __dec_node_page_state(head, NR_FILE_THPS); |
| 2818 | } | 2811 | } |
| 2819 | 2812 | ||
| 2820 | spin_unlock(&ds_queue->split_queue_lock); | ||
| 2821 | __split_huge_page(page, list, end, flags); | 2813 | __split_huge_page(page, list, end, flags); |
| 2822 | if (PageSwapCache(head)) { | 2814 | if (PageSwapCache(head)) { |
| 2823 | swp_entry_t entry = { .val = page_private(head) }; | 2815 | swp_entry_t entry = { .val = page_private(head) }; |
| @@ -13,7 +13,7 @@ · 12 unmodified lines | |||
| 13 | * | 13 | * |
| 14 | * The following locks and mutexes are used by kmemleak: | 14 | * The following locks and mutexes are used by kmemleak: |
| 15 | * | 15 | * |
| 16 | * - kmemleak_lock (rwlock): protects the object_list modifications and | 16 | * - kmemleak_lock (raw_spinlock_t): protects the object_list modifications and |
| 17 | * accesses to the object_tree_root. The object_list is the main list | 17 | * accesses to the object_tree_root. The object_list is the main list |
| 18 | * holding the metadata (struct kmemleak_object) for the allocated memory | 18 | * holding the metadata (struct kmemleak_object) for the allocated memory |
| 19 | * blocks. The object_tree_root is a red black tree used to look-up | 19 | * blocks. The object_tree_root is a red black tree used to look-up |
| @@ -22,13 +22,13 @@ · 2 unmodified lines | |||
| 22 | * object_tree_root in the create_object() function called from the | 22 | * object_tree_root in the create_object() function called from the |
| 23 | * kmemleak_alloc() callback and removed in delete_object() called from the | 23 | * kmemleak_alloc() callback and removed in delete_object() called from the |
| 24 | * kmemleak_free() callback | 24 | * kmemleak_free() callback |
| 25 | * - kmemleak_object.lock (spinlock): protects a kmemleak_object. Accesses to | 25 | * - kmemleak_object.lock (raw_spinlock_t): protects a kmemleak_object. |
| 26 | * the metadata (e.g. count) are protected by this lock. Note that some | 26 | * Accesses to the metadata (e.g. count) are protected by this lock. Note |
| 27 | * members of this structure may be protected by other means (atomic or | 27 | * that some members of this structure may be protected by other means |
| 28 | * kmemleak_lock). This lock is also held when scanning the corresponding | 28 | * (atomic or kmemleak_lock). This lock is also held when scanning the |
| 29 | * memory block to avoid the kernel freeing it via the kmemleak_free() | 29 | * corresponding memory block to avoid the kernel freeing it via the |
| 30 | * callback. This is less heavyweight than holding a global lock like | 30 | * kmemleak_free() callback. This is less heavyweight than holding a global |
| 31 | * kmemleak_lock during scanning | 31 | * lock like kmemleak_lock during scanning. |
| 32 | * - scan_mutex (mutex): ensures that only one thread may scan the memory for | 32 | * - scan_mutex (mutex): ensures that only one thread may scan the memory for |
| 33 | * unreferenced objects at a time. The gray_list contains the objects which | 33 | * unreferenced objects at a time. The gray_list contains the objects which |
| 34 | * are already referenced or marked as false positives and need to be | 34 | * are already referenced or marked as false positives and need to be |
| @@ -135,7 +135,7 @@ struct kmemleak_scan_area { · 100 unmodified lines | |||
| 135 | * (use_count) and freed using the RCU mechanism. | 135 | * (use_count) and freed using the RCU mechanism. |
| 136 | */ | 136 | */ |
| 137 | struct kmemleak_object { | 137 | struct kmemleak_object { |
| 138 | spinlock_t lock; | 138 | raw_spinlock_t lock; |
| 139 | unsigned int flags; /* object status flags */ | 139 | unsigned int flags; /* object status flags */ |
| 140 | struct list_head object_list; | 140 | struct list_head object_list; |
| 141 | struct list_head gray_list; | 141 | struct list_head gray_list; |
| @@ -191,8 +191,8 @@ static int mem_pool_free_count = ARRAY_SIZE(mem_pool); · 49 unmodified lines | |||
| 191 | static LIST_HEAD(mem_pool_free_list); | 191 | static LIST_HEAD(mem_pool_free_list); |
| 192 | /* search tree for object boundaries */ | 192 | /* search tree for object boundaries */ |
| 193 | static struct rb_root object_tree_root = RB_ROOT; | 193 | static struct rb_root object_tree_root = RB_ROOT; |
| 194 | /* rw_lock protecting the access to object_list and object_tree_root */ | 194 | /* protecting the access to object_list and object_tree_root */ |
| 195 | static DEFINE_RWLOCK(kmemleak_lock); | 195 | static DEFINE_RAW_SPINLOCK(kmemleak_lock); |
| 196 | 196 | ||
| 197 | /* allocation caches for kmemleak internal data */ | 197 | /* allocation caches for kmemleak internal data */ |
| 198 | static struct kmem_cache *object_cache; | 198 | static struct kmem_cache *object_cache; |
| @@ -426,7 +426,7 @@ static struct kmemleak_object *mem_pool_alloc(gfp_t gfp) · 227 unmodified lines | |||
| 426 | } | 426 | } |
| 427 | 427 | ||
| 428 | /* slab allocation failed, try the memory pool */ | 428 | /* slab allocation failed, try the memory pool */ |
| 429 | write_lock_irqsave(&kmemleak_lock, flags); | 429 | raw_spin_lock_irqsave(&kmemleak_lock, flags); |
| 430 | object = list_first_entry_or_null(&mem_pool_free_list, | 430 | object = list_first_entry_or_null(&mem_pool_free_list, |
| 431 | typeof(*object), object_list); | 431 | typeof(*object), object_list); |
| 432 | if (object) | 432 | if (object) |
| @@ -435,7 +435,7 @@ static struct kmemleak_object *mem_pool_alloc(gfp_t gfp) · 2 unmodified lines | |||
| 435 | object = &mem_pool[--mem_pool_free_count]; | 435 | object = &mem_pool[--mem_pool_free_count]; |
| 436 | else | 436 | else |
| 437 | pr_warn_once("Memory pool empty, consider increasing CONFIG_DEBUG_KMEMLEAK_MEM_POOL_SIZE\n"); | 437 | pr_warn_once("Memory pool empty, consider increasing CONFIG_DEBUG_KMEMLEAK_MEM_POOL_SIZE\n"); |
| 438 | write_unlock_irqrestore(&kmemleak_lock, flags); | 438 | raw_spin_unlock_irqrestore(&kmemleak_lock, flags); |
| 439 | 439 | ||
| 440 | return object; | 440 | return object; |
| 441 | } | 441 | } |
| @@ -453,9 +453,9 @@ static void mem_pool_free(struct kmemleak_object *object) · 11 unmodified lines | |||
| 453 | } | 453 | } |
| 454 | 454 | ||
| 455 | /* add the object to the memory pool free list */ | 455 | /* add the object to the memory pool free list */ |
| 456 | write_lock_irqsave(&kmemleak_lock, flags); | 456 | raw_spin_lock_irqsave(&kmemleak_lock, flags); |
| 457 | list_add(&object->object_list, &mem_pool_free_list); | 457 | list_add(&object->object_list, &mem_pool_free_list); |
| 458 | write_unlock_irqrestore(&kmemleak_lock, flags); | 458 | raw_spin_unlock_irqrestore(&kmemleak_lock, flags); |
| 459 | } | 459 | } |
| 460 | 460 | ||
| 461 | /* | 461 | /* |
| @@ -514,9 +514,9 @@ static struct kmemleak_object *find_and_get_object(unsigned long ptr, int alias) · 52 unmodified lines | |||
| 514 | struct kmemleak_object *object; | 514 | struct kmemleak_object *object; |
| 515 | 515 | ||
| 516 | rcu_read_lock(); | 516 | rcu_read_lock(); |
| 517 | read_lock_irqsave(&kmemleak_lock, flags); | 517 | raw_spin_lock_irqsave(&kmemleak_lock, flags); |
| 518 | object = lookup_object(ptr, alias); | 518 | object = lookup_object(ptr, alias); |
| 519 | read_unlock_irqrestore(&kmemleak_lock, flags); | 519 | raw_spin_unlock_irqrestore(&kmemleak_lock, flags); |
| 520 | 520 | ||
| 521 | /* check whether the object is still available */ | 521 | /* check whether the object is still available */ |
| 522 | if (object && !get_object(object)) | 522 | if (object && !get_object(object)) |
| @@ -546,11 +546,11 @@ static struct kmemleak_object *find_and_remove_object(unsigned long ptr, int ali · 23 unmodified lines | |||
| 546 | unsigned long flags; | 546 | unsigned long flags; |
| 547 | struct kmemleak_object *object; | 547 | struct kmemleak_object *object; |
| 548 | 548 | ||
| 549 | write_lock_irqsave(&kmemleak_lock, flags); | 549 | raw_spin_lock_irqsave(&kmemleak_lock, flags); |
| 550 | object = lookup_object(ptr, alias); | 550 | object = lookup_object(ptr, alias); |
| 551 | if (object) | 551 | if (object) |
| 552 | __remove_object(object); | 552 | __remove_object(object); |
| 553 | write_unlock_irqrestore(&kmemleak_lock, flags); | 553 | raw_spin_unlock_irqrestore(&kmemleak_lock, flags); |
| 554 | 554 | ||
| 555 | return object; | 555 | return object; |
| 556 | } | 556 | } |
| @@ -585,7 +585,7 @@ static struct kmemleak_object *create_object(unsigned long ptr, size_t size, · 28 unmodified lines | |||
| 585 | INIT_LIST_HEAD(&object->object_list); | 585 | INIT_LIST_HEAD(&object->object_list); |
| 586 | INIT_LIST_HEAD(&object->gray_list); | 586 | INIT_LIST_HEAD(&object->gray_list); |
| 587 | INIT_HLIST_HEAD(&object->area_list); | 587 | INIT_HLIST_HEAD(&object->area_list); |
| 588 | spin_lock_init(&object->lock); | 588 | raw_spin_lock_init(&object->lock); |
| 589 | atomic_set(&object->use_count, 1); | 589 | atomic_set(&object->use_count, 1); |
| 590 | object->flags = OBJECT_ALLOCATED; | 590 | object->flags = OBJECT_ALLOCATED; |
| 591 | object->pointer = ptr; | 591 | object->pointer = ptr; |
| @@ -617,7 +617,7 @@ static struct kmemleak_object *create_object(unsigned long ptr, size_t size, · 25 unmodified lines | |||
| 617 | /* kernel backtrace */ | 617 | /* kernel backtrace */ |
| 618 | object->trace_len = __save_stack_trace(object->trace); | 618 | object->trace_len = __save_stack_trace(object->trace); |
| 619 | 619 | ||
| 620 | write_lock_irqsave(&kmemleak_lock, flags); | 620 | raw_spin_lock_irqsave(&kmemleak_lock, flags); |
| 621 | 621 | ||
| 622 | untagged_ptr = (unsigned long)kasan_reset_tag((void *)ptr); | 622 | untagged_ptr = (unsigned long)kasan_reset_tag((void *)ptr); |
| 623 | min_addr = min(min_addr, untagged_ptr); | 623 | min_addr = min(min_addr, untagged_ptr); |
| @@ -649,7 +649,7 @@ static struct kmemleak_object *create_object(unsigned long ptr, size_t size, · 25 unmodified lines | |||
| 649 | 649 | ||
| 650 | list_add_tail_rcu(&object->object_list, &object_list); | 650 | list_add_tail_rcu(&object->object_list, &object_list); |
| 651 | out: | 651 | out: |
| 652 | write_unlock_irqrestore(&kmemleak_lock, flags); | 652 | raw_spin_unlock_irqrestore(&kmemleak_lock, flags); |
| 653 | return object; | 653 | return object; |
| 654 | } | 654 | } |
| 655 | 655 | ||
| @@ -667,9 +667,9 @@ static void __delete_object(struct kmemleak_object *object) · 11 unmodified lines | |||
| 667 | * Locking here also ensures that the corresponding memory block | 667 | * Locking here also ensures that the corresponding memory block |
| 668 | * cannot be freed when it is being scanned. | 668 | * cannot be freed when it is being scanned. |
| 669 | */ | 669 | */ |
| 670 | spin_lock_irqsave(&object->lock, flags); | 670 | raw_spin_lock_irqsave(&object->lock, flags); |
| 671 | object->flags &= ~OBJECT_ALLOCATED; | 671 | object->flags &= ~OBJECT_ALLOCATED; |
| 672 | spin_unlock_irqrestore(&object->lock, flags); | 672 | raw_spin_unlock_irqrestore(&object->lock, flags); |
| 673 | put_object(object); | 673 | put_object(object); |
| 674 | } | 674 | } |
| 675 | 675 | ||
| @@ -739,9 +739,9 @@ static void paint_it(struct kmemleak_object *object, int color) · 63 unmodified lines | |||
| 739 | { | 739 | { |
| 740 | unsigned long flags; | 740 | unsigned long flags; |
| 741 | 741 | ||
| 742 | spin_lock_irqsave(&object->lock, flags); | 742 | raw_spin_lock_irqsave(&object->lock, flags); |
| 743 | __paint_it(object, color); | 743 | __paint_it(object, color); |
| 744 | spin_unlock_irqrestore(&object->lock, flags); | 744 | raw_spin_unlock_irqrestore(&object->lock, flags); |
| 745 | } | 745 | } |
| 746 | 746 | ||
| 747 | static void paint_ptr(unsigned long ptr, int color) | 747 | static void paint_ptr(unsigned long ptr, int color) |
| @@ -798,7 +798,7 @@ static void add_scan_area(unsigned long ptr, size_t size, gfp_t gfp) · 50 unmodified lines | |||
| 798 | if (scan_area_cache) | 798 | if (scan_area_cache) |
| 799 | area = kmem_cache_alloc(scan_area_cache, gfp_kmemleak_mask(gfp)); | 799 | area = kmem_cache_alloc(scan_area_cache, gfp_kmemleak_mask(gfp)); |
| 800 | 800 | ||
| 801 | spin_lock_irqsave(&object->lock, flags); | 801 | raw_spin_lock_irqsave(&object->lock, flags); |
| 802 | if (!area) { | 802 | if (!area) { |
| 803 | pr_warn_once("Cannot allocate a scan area, scanning the full object\n"); | 803 | pr_warn_once("Cannot allocate a scan area, scanning the full object\n"); |
| 804 | /* mark the object for full scan to avoid false positives */ | 804 | /* mark the object for full scan to avoid false positives */ |
| @@ -820,7 +820,7 @@ static void add_scan_area(unsigned long ptr, size_t size, gfp_t gfp) · 15 unmodified lines | |||
| 820 | 820 | ||
| 821 | hlist_add_head(&area->node, &object->area_list); | 821 | hlist_add_head(&area->node, &object->area_list); |
| 822 | out_unlock: | 822 | out_unlock: |
| 823 | spin_unlock_irqrestore(&object->lock, flags); | 823 | raw_spin_unlock_irqrestore(&object->lock, flags); |
| 824 | put_object(object); | 824 | put_object(object); |
| 825 | } | 825 | } |
| 826 | 826 | ||
| @@ -842,9 +842,9 @@ static void object_set_excess_ref(unsigned long ptr, unsigned long excess_ref) · 15 unmodified lines | |||
| 842 | return; | 842 | return; |
| 843 | } | 843 | } |
| 844 | 844 | ||
| 845 | spin_lock_irqsave(&object->lock, flags); | 845 | raw_spin_lock_irqsave(&object->lock, flags); |
| 846 | object->excess_ref = excess_ref; | 846 | object->excess_ref = excess_ref; |
| 847 | spin_unlock_irqrestore(&object->lock, flags); | 847 | raw_spin_unlock_irqrestore(&object->lock, flags); |
| 848 | put_object(object); | 848 | put_object(object); |
| 849 | } | 849 | } |
| 850 | 850 | ||
| @@ -864,9 +864,9 @@ static void object_no_scan(unsigned long ptr) · 13 unmodified lines | |||
| 864 | return; | 864 | return; |
| 865 | } | 865 | } |
| 866 | 866 | ||
| 867 | spin_lock_irqsave(&object->lock, flags); | 867 | raw_spin_lock_irqsave(&object->lock, flags); |
| 868 | object->flags |= OBJECT_NO_SCAN; | 868 | object->flags |= OBJECT_NO_SCAN; |
| 869 | spin_unlock_irqrestore(&object->lock, flags); | 869 | raw_spin_unlock_irqrestore(&object->lock, flags); |
| 870 | put_object(object); | 870 | put_object(object); |
| 871 | } | 871 | } |
| 872 | 872 | ||
| @@ -1026,9 +1026,9 @@ void __ref kmemleak_update_trace(const void *ptr) · 153 unmodified lines | |||
| 1026 | return; | 1026 | return; |
| 1027 | } | 1027 | } |
| 1028 | 1028 | ||
| 1029 | spin_lock_irqsave(&object->lock, flags); | 1029 | raw_spin_lock_irqsave(&object->lock, flags); |
| 1030 | object->trace_len = __save_stack_trace(object->trace); | 1030 | object->trace_len = __save_stack_trace(object->trace); |
| 1031 | spin_unlock_irqrestore(&object->lock, flags); | 1031 | raw_spin_unlock_irqrestore(&object->lock, flags); |
| 1032 | 1032 | ||
| 1033 | put_object(object); | 1033 | put_object(object); |
| 1034 | } | 1034 | } |
| @@ -1233,7 +1233,7 @@ static void scan_block(void *_start, void *_end, · 198 unmodified lines | |||
| 1233 | unsigned long flags; | 1233 | unsigned long flags; |
| 1234 | unsigned long untagged_ptr; | 1234 | unsigned long untagged_ptr; |
| 1235 | 1235 | ||
| 1236 | read_lock_irqsave(&kmemleak_lock, flags); | 1236 | raw_spin_lock_irqsave(&kmemleak_lock, flags); |
| 1237 | for (ptr = start; ptr < end; ptr++) { | 1237 | for (ptr = start; ptr < end; ptr++) { |
| 1238 | struct kmemleak_object *object; | 1238 | struct kmemleak_object *object; |
| 1239 | unsigned long pointer; | 1239 | unsigned long pointer; |
| @@ -1268,7 +1268,7 @@ static void scan_block(void *_start, void *_end, · 28 unmodified lines | |||
| 1268 | * previously acquired in scan_object(). These locks are | 1268 | * previously acquired in scan_object(). These locks are |
| 1269 | * enclosed by scan_mutex. | 1269 | * enclosed by scan_mutex. |
| 1270 | */ | 1270 | */ |
| 1271 | spin_lock_nested(&object->lock, SINGLE_DEPTH_NESTING); | 1271 | raw_spin_lock_nested(&object->lock, SINGLE_DEPTH_NESTING); |
| 1272 | /* only pass surplus references (object already gray) */ | 1272 | /* only pass surplus references (object already gray) */ |
| 1273 | if (color_gray(object)) { | 1273 | if (color_gray(object)) { |
| 1274 | excess_ref = object->excess_ref; | 1274 | excess_ref = object->excess_ref; |
| @@ -1277,7 +1277,7 @@ static void scan_block(void *_start, void *_end, · 2 unmodified lines | |||
| 1277 | excess_ref = 0; | 1277 | excess_ref = 0; |
| 1278 | update_refs(object); | 1278 | update_refs(object); |
| 1279 | } | 1279 | } |
| 1280 | spin_unlock(&object->lock); | 1280 | raw_spin_unlock(&object->lock); |
| 1281 | 1281 | ||
| 1282 | if (excess_ref) { | 1282 | if (excess_ref) { |
| 1283 | object = lookup_object(excess_ref, 0); | 1283 | object = lookup_object(excess_ref, 0); |
| @@ -1286,12 +1286,12 @@ static void scan_block(void *_start, void *_end, · 2 unmodified lines | |||
| 1286 | if (object == scanned) | 1286 | if (object == scanned) |
| 1287 | /* circular reference, ignore */ | 1287 | /* circular reference, ignore */ |
| 1288 | continue; | 1288 | continue; |
| 1289 | spin_lock_nested(&object->lock, SINGLE_DEPTH_NESTING); | 1289 | raw_spin_lock_nested(&object->lock, SINGLE_DEPTH_NESTING); |
| 1290 | update_refs(object); | 1290 | update_refs(object); |
| 1291 | spin_unlock(&object->lock); | 1291 | raw_spin_unlock(&object->lock); |
| 1292 | } | 1292 | } |
| 1293 | } | 1293 | } |
| 1294 | read_unlock_irqrestore(&kmemleak_lock, flags); | 1294 | raw_spin_unlock_irqrestore(&kmemleak_lock, flags); |
| 1295 | } | 1295 | } |
| 1296 | 1296 | ||
| 1297 | /* | 1297 | /* |
| @@ -1324,7 +1324,7 @@ static void scan_object(struct kmemleak_object *object) · 26 unmodified lines | |||
| 1324 | * Once the object->lock is acquired, the corresponding memory block | 1324 | * Once the object->lock is acquired, the corresponding memory block |
| 1325 | * cannot be freed (the same lock is acquired in delete_object). | 1325 | * cannot be freed (the same lock is acquired in delete_object). |
| 1326 | */ | 1326 | */ |
| 1327 | spin_lock_irqsave(&object->lock, flags); | 1327 | raw_spin_lock_irqsave(&object->lock, flags); |
| 1328 | if (object->flags & OBJECT_NO_SCAN) | 1328 | if (object->flags & OBJECT_NO_SCAN) |
| 1329 | goto out; | 1329 | goto out; |
| 1330 | if (!(object->flags & OBJECT_ALLOCATED)) | 1330 | if (!(object->flags & OBJECT_ALLOCATED)) |
| @@ -1344,9 +1344,9 @@ static void scan_object(struct kmemleak_object *object) · 13 unmodified lines | |||
| 1344 | if (start >= end) | 1344 | if (start >= end) |
| 1345 | break; | 1345 | break; |
| 1346 | 1346 | ||
| 1347 | spin_unlock_irqrestore(&object->lock, flags); | 1347 | raw_spin_unlock_irqrestore(&object->lock, flags); |
| 1348 | cond_resched(); | 1348 | cond_resched(); |
| 1349 | spin_lock_irqsave(&object->lock, flags); | 1349 | raw_spin_lock_irqsave(&object->lock, flags); |
| 1350 | } while (object->flags & OBJECT_ALLOCATED); | 1350 | } while (object->flags & OBJECT_ALLOCATED); |
| 1351 | } else | 1351 | } else |
| 1352 | hlist_for_each_entry(area, &object->area_list, node) | 1352 | hlist_for_each_entry(area, &object->area_list, node) |
| @@ -1354,7 +1354,7 @@ static void scan_object(struct kmemleak_object *object) · 1 unmodified line | |||
| 1354 | (void *)(area->start + area->size), | 1354 | (void *)(area->start + area->size), |
| 1355 | object); | 1355 | object); |
| 1356 | out: | 1356 | out: |
| 1357 | spin_unlock_irqrestore(&object->lock, flags); | 1357 | raw_spin_unlock_irqrestore(&object->lock, flags); |
| 1358 | } | 1358 | } |
| 1359 | 1359 | ||
| 1360 | /* | 1360 | /* |
| @@ -1407,7 +1407,7 @@ static void kmemleak_scan(void) · 46 unmodified lines | |||
| 1407 | /* prepare the kmemleak_object's */ | 1407 | /* prepare the kmemleak_object's */ |
| 1408 | rcu_read_lock(); | 1408 | rcu_read_lock(); |
| 1409 | list_for_each_entry_rcu(object, &object_list, object_list) { | 1409 | list_for_each_entry_rcu(object, &object_list, object_list) { |
| 1410 | spin_lock_irqsave(&object->lock, flags); | 1410 | raw_spin_lock_irqsave(&object->lock, flags); |
| 1411 | #ifdef DEBUG | 1411 | #ifdef DEBUG |
| 1412 | /* | 1412 | /* |
| 1413 | * With a few exceptions there should be a maximum of | 1413 | * With a few exceptions there should be a maximum of |
| @@ -1424,7 +1424,7 @@ static void kmemleak_scan(void) · 10 unmodified lines | |||
| 1424 | if (color_gray(object) && get_object(object)) | 1424 | if (color_gray(object) && get_object(object)) |
| 1425 | list_add_tail(&object->gray_list, &gray_list); | 1425 | list_add_tail(&object->gray_list, &gray_list); |
| 1426 | 1426 | ||
| 1427 | spin_unlock_irqrestore(&object->lock, flags); | 1427 | raw_spin_unlock_irqrestore(&object->lock, flags); |
| 1428 | } | 1428 | } |
| 1429 | rcu_read_unlock(); | 1429 | rcu_read_unlock(); |
| 1430 | 1430 | ||
| @@ -1492,14 +1492,14 @@ static void kmemleak_scan(void) · 61 unmodified lines | |||
| 1492 | */ | 1492 | */ |
| 1493 | rcu_read_lock(); | 1493 | rcu_read_lock(); |
| 1494 | list_for_each_entry_rcu(object, &object_list, object_list) { | 1494 | list_for_each_entry_rcu(object, &object_list, object_list) { |
| 1495 | spin_lock_irqsave(&object->lock, flags); | 1495 | raw_spin_lock_irqsave(&object->lock, flags); |
| 1496 | if (color_white(object) && (object->flags & OBJECT_ALLOCATED) | 1496 | if (color_white(object) && (object->flags & OBJECT_ALLOCATED) |
| 1497 | && update_checksum(object) && get_object(object)) { | 1497 | && update_checksum(object) && get_object(object)) { |
| 1498 | /* color it gray temporarily */ | 1498 | /* color it gray temporarily */ |
| 1499 | object->count = object->min_count; | 1499 | object->count = object->min_count; |
| 1500 | list_add_tail(&object->gray_list, &gray_list); | 1500 | list_add_tail(&object->gray_list, &gray_list); |
| 1501 | } | 1501 | } |
| 1502 | spin_unlock_irqrestore(&object->lock, flags); | 1502 | raw_spin_unlock_irqrestore(&object->lock, flags); |
| 1503 | } | 1503 | } |
| 1504 | rcu_read_unlock(); | 1504 | rcu_read_unlock(); |
| 1505 | 1505 | ||
| @@ -1519,7 +1519,7 @@ static void kmemleak_scan(void) · 13 unmodified lines | |||
| 1519 | */ | 1519 | */ |
| 1520 | rcu_read_lock(); | 1520 | rcu_read_lock(); |
| 1521 | list_for_each_entry_rcu(object, &object_list, object_list) { | 1521 | list_for_each_entry_rcu(object, &object_list, object_list) { |
| 1522 | spin_lock_irqsave(&object->lock, flags); | 1522 | raw_spin_lock_irqsave(&object->lock, flags); |
| 1523 | if (unreferenced_object(object) && | 1523 | if (unreferenced_object(object) && |
| 1524 | !(object->flags & OBJECT_REPORTED)) { | 1524 | !(object->flags & OBJECT_REPORTED)) { |
| 1525 | object->flags |= OBJECT_REPORTED; | 1525 | object->flags |= OBJECT_REPORTED; |
| @@ -1529,7 +1529,7 @@ static void kmemleak_scan(void) · 3 unmodified lines | |||
| 1529 | 1529 | ||
| 1530 | new_leaks++; | 1530 | new_leaks++; |
| 1531 | } | 1531 | } |
| 1532 | spin_unlock_irqrestore(&object->lock, flags); | 1532 | raw_spin_unlock_irqrestore(&object->lock, flags); |
| 1533 | } | 1533 | } |
| 1534 | rcu_read_unlock(); | 1534 | rcu_read_unlock(); |
| 1535 | 1535 | ||
| @@ -1681,10 +1681,10 @@ static int kmemleak_seq_show(struct seq_file *seq, void *v) · 145 unmodified lines | |||
| 1681 | struct kmemleak_object *object = v; | 1681 | struct kmemleak_object *object = v; |
| 1682 | unsigned long flags; | 1682 | unsigned long flags; |
| 1683 | 1683 | ||
| 1684 | spin_lock_irqsave(&object->lock, flags); | 1684 | raw_spin_lock_irqsave(&object->lock, flags); |
| 1685 | if ((object->flags & OBJECT_REPORTED) && unreferenced_object(object)) | 1685 | if ((object->flags & OBJECT_REPORTED) && unreferenced_object(object)) |
| 1686 | print_unreferenced(seq, object); | 1686 | print_unreferenced(seq, object); |
| 1687 | spin_unlock_irqrestore(&object->lock, flags); | 1687 | raw_spin_unlock_irqrestore(&object->lock, flags); |
| 1688 | return 0; | 1688 | return 0; |
| 1689 | } | 1689 | } |
| 1690 | 1690 | ||
| @@ -1714,9 +1714,9 @@ static int dump_str_object_info(const char *str) · 23 unmodified lines | |||
| 1714 | return -EINVAL; | 1714 | return -EINVAL; |
| 1715 | } | 1715 | } |
| 1716 | 1716 | ||
| 1717 | spin_lock_irqsave(&object->lock, flags); | 1717 | raw_spin_lock_irqsave(&object->lock, flags); |
| 1718 | dump_object_info(object); | 1718 | dump_object_info(object); |
| 1719 | spin_unlock_irqrestore(&object->lock, flags); | 1719 | raw_spin_unlock_irqrestore(&object->lock, flags); |
| 1720 | 1720 | ||
| 1721 | put_object(object); | 1721 | put_object(object); |
| 1722 | return 0; | 1722 | return 0; |
| @@ -1735,11 +1735,11 @@ static void kmemleak_clear(void) · 12 unmodified lines | |||
| 1735 | 1735 | ||
| 1736 | rcu_read_lock(); | 1736 | rcu_read_lock(); |
| 1737 | list_for_each_entry_rcu(object, &object_list, object_list) { | 1737 | list_for_each_entry_rcu(object, &object_list, object_list) { |
| 1738 | spin_lock_irqsave(&object->lock, flags); | 1738 | raw_spin_lock_irqsave(&object->lock, flags); |
| 1739 | if ((object->flags & OBJECT_REPORTED) && | 1739 | if ((object->flags & OBJECT_REPORTED) && |
| 1740 | unreferenced_object(object)) | 1740 | unreferenced_object(object)) |
| 1741 | __paint_it(object, KMEMLEAK_GREY); | 1741 | __paint_it(object, KMEMLEAK_GREY); |
| 1742 | spin_unlock_irqrestore(&object->lock, flags); | 1742 | raw_spin_unlock_irqrestore(&object->lock, flags); |
| 1743 | } | 1743 | } |
| 1744 | rcu_read_unlock(); | 1744 | rcu_read_unlock(); |
| 1745 | 1745 | ||
| @@ -575,7 +575,7 @@ static void __init_memblock memblock_insert_region(struct memblock_type *type, · 574 unmodified lines | |||
| 575 | * Return: | 575 | * Return: |
| 576 | * 0 on success, -errno on failure. | 576 | * 0 on success, -errno on failure. |
| 577 | */ | 577 | */ |
| 578 | int __init_memblock memblock_add_range(struct memblock_type *type, | 578 | static int __init_memblock memblock_add_range(struct memblock_type *type, |
| 579 | phys_addr_t base, phys_addr_t size, | 579 | phys_addr_t base, phys_addr_t size, |
| 580 | int nid, enum memblock_flags flags) | 580 | int nid, enum memblock_flags flags) |
| 581 | { | 581 | { |
| @@ -694,7 +694,7 @@ int __init_memblock memblock_add(phys_addr_t base, phys_addr_t size) · 112 unmodified lines | |||
| 694 | { | 694 | { |
| 695 | phys_addr_t end = base + size - 1; | 695 | phys_addr_t end = base + size - 1; |
| 696 | 696 | ||
| 697 | memblock_dbg("memblock_add: [%pa-%pa] %pS\n", | 697 | memblock_dbg("%s: [%pa-%pa] %pS\n", __func__, |
| 698 | &base, &end, (void *)_RET_IP_); | 698 | &base, &end, (void *)_RET_IP_); |
| 699 | 699 | ||
| 700 | return memblock_add_range(&memblock.memory, base, size, MAX_NUMNODES, 0); | 700 | return memblock_add_range(&memblock.memory, base, size, MAX_NUMNODES, 0); |
| @@ -795,7 +795,7 @@ int __init_memblock memblock_remove(phys_addr_t base, phys_addr_t size) · 94 unmodified lines | |||
| 795 | { | 795 | { |
| 796 | phys_addr_t end = base + size - 1; | 796 | phys_addr_t end = base + size - 1; |
| 797 | 797 | ||
| 798 | memblock_dbg("memblock_remove: [%pa-%pa] %pS\n", | 798 | memblock_dbg("%s: [%pa-%pa] %pS\n", __func__, |
| 799 | &base, &end, (void *)_RET_IP_); | 799 | &base, &end, (void *)_RET_IP_); |
| 800 | 800 | ||
| 801 | return memblock_remove_range(&memblock.memory, base, size); | 801 | return memblock_remove_range(&memblock.memory, base, size); |
| @@ -813,7 +813,7 @@ int __init_memblock memblock_free(phys_addr_t base, phys_addr_t size) · 11 unmodified lines | |||
| 813 | { | 813 | { |
| 814 | phys_addr_t end = base + size - 1; | 814 | phys_addr_t end = base + size - 1; |
| 815 | 815 | ||
| 816 | memblock_dbg(" memblock_free: [%pa-%pa] %pS\n", | 816 | memblock_dbg("%s: [%pa-%pa] %pS\n", __func__, |
| 817 | &base, &end, (void *)_RET_IP_); | 817 | &base, &end, (void *)_RET_IP_); |
| 818 | 818 | ||
| 819 | kmemleak_free_part_phys(base, size); | 819 | kmemleak_free_part_phys(base, size); |
| @@ -824,12 +824,24 @@ int __init_memblock memblock_reserve(phys_addr_t base, phys_addr_t size) · 4 unmodified lines | |||
| 824 | { | 824 | { |
| 825 | phys_addr_t end = base + size - 1; | 825 | phys_addr_t end = base + size - 1; |
| 826 | 826 | ||
| 827 | memblock_dbg("memblock_reserve: [%pa-%pa] %pS\n", | 827 | memblock_dbg("%s: [%pa-%pa] %pS\n", __func__, |
| 828 | &base, &end, (void *)_RET_IP_); | 828 | &base, &end, (void *)_RET_IP_); |
| 829 | 829 | ||
| 830 | return memblock_add_range(&memblock.reserved, base, size, MAX_NUMNODES, 0); | 830 | return memblock_add_range(&memblock.reserved, base, size, MAX_NUMNODES, 0); |
| 831 | } | 831 | } |
| 832 | 832 | ||
| 833 | #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP | ||
| 834 | int __init_memblock memblock_physmem_add(phys_addr_t base, phys_addr_t size) | ||
| 835 | { | ||
| 836 | phys_addr_t end = base + size - 1; | ||
| 837 | |||
| 838 | memblock_dbg("%s: [%pa-%pa] %pS\n", __func__, | ||
| 839 | &base, &end, (void *)_RET_IP_); | ||
| 840 | |||
| 841 | return memblock_add_range(&memblock.physmem, base, size, MAX_NUMNODES, 0); | ||
| 842 | } | ||
| 843 | #endif | ||
| 844 | |||
| 833 | /** | 845 | /** |
| 834 | * memblock_setclr_flag - set or clear flag for a memory region | 846 | * memblock_setclr_flag - set or clear flag for a memory region |
| 835 | * @base: base address of the region | 847 | * @base: base address of the region |
| @@ -5340,14 +5340,6 @@ static int mem_cgroup_move_account(struct page *page, · 5339 unmodified lines | |||
| 5340 | __mod_lruvec_state(to_vec, NR_WRITEBACK, nr_pages); | 5340 | __mod_lruvec_state(to_vec, NR_WRITEBACK, nr_pages); |
| 5341 | } | 5341 | } |
| 5342 | 5342 | ||
| 5343 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | ||
| 5344 | if (compound && !list_empty(page_deferred_list(page))) { | ||
| 5345 | spin_lock(&from->deferred_split_queue.split_queue_lock); | ||
| 5346 | list_del_init(page_deferred_list(page)); | ||
| 5347 | from->deferred_split_queue.split_queue_len--; | ||
| 5348 | spin_unlock(&from->deferred_split_queue.split_queue_lock); | ||
| 5349 | } | ||
| 5350 | #endif | ||
| 5351 | /* | 5343 | /* |
| 5352 | * It is safe to change page->mem_cgroup here because the page | 5344 | * It is safe to change page->mem_cgroup here because the page |
| 5353 | * is referenced, charged, and isolated - we can't race with | 5345 | * is referenced, charged, and isolated - we can't race with |
| @@ -5357,16 +5349,6 @@ static int mem_cgroup_move_account(struct page *page, · 3 unmodified lines | |||
| 5357 | /* caller should have done css_get */ | 5349 | /* caller should have done css_get */ |
| 5358 | page->mem_cgroup = to; | 5350 | page->mem_cgroup = to; |
| 5359 | 5351 | ||
| 5360 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | ||
| 5361 | if (compound && list_empty(page_deferred_list(page))) { | ||
| 5362 | spin_lock(&to->deferred_split_queue.split_queue_lock); | ||
| 5363 | list_add_tail(page_deferred_list(page), | ||
| 5364 | &to->deferred_split_queue.split_queue); | ||
| 5365 | to->deferred_split_queue.split_queue_len++; | ||
| 5366 | spin_unlock(&to->deferred_split_queue.split_queue_lock); | ||
| 5367 | } | ||
| 5368 | #endif | ||
| 5369 | |||
| 5370 | spin_unlock_irqrestore(&from->move_lock, flags); | 5352 | spin_unlock_irqrestore(&from->move_lock, flags); |
| 5371 | 5353 | ||
| 5372 | ret = 0; | 5354 | ret = 0; |
| @@ -6651,7 +6633,6 @@ void mem_cgroup_migrate(struct page *oldpage, struct page *newpage) · 1278 unmodified lines | |||
| 6651 | { | 6633 | { |
| 6652 | struct mem_cgroup *memcg; | 6634 | struct mem_cgroup *memcg; |
| 6653 | unsigned int nr_pages; | 6635 | unsigned int nr_pages; |
| 6654 | bool compound; | ||
| 6655 | unsigned long flags; | 6636 | unsigned long flags; |
| 6656 | 6637 | ||
| 6657 | VM_BUG_ON_PAGE(!PageLocked(oldpage), oldpage); | 6638 | VM_BUG_ON_PAGE(!PageLocked(oldpage), oldpage); |
| @@ -6673,8 +6654,7 @@ void mem_cgroup_migrate(struct page *oldpage, struct page *newpage) · 15 unmodified lines | |||
| 6673 | return; | 6654 | return; |
| 6674 | 6655 | ||
| 6675 | /* Force-charge the new page. The old one will be freed soon */ | 6656 | /* Force-charge the new page. The old one will be freed soon */ |
| 6676 | compound = PageTransHuge(newpage); | 6657 | nr_pages = hpage_nr_pages(newpage); |
| 6677 | nr_pages = compound ? hpage_nr_pages(newpage) : 1; | ||
| 6678 | 6658 | ||
| 6679 | page_counter_charge(&memcg->memory, nr_pages); | 6659 | page_counter_charge(&memcg->memory, nr_pages); |
| 6680 | if (do_memsw_account()) | 6660 | if (do_memsw_account()) |
| @@ -6684,7 +6664,8 @@ void mem_cgroup_migrate(struct page *oldpage, struct page *newpage) · 3 unmodified lines | |||
| 6684 | commit_charge(newpage, memcg, false); | 6664 | commit_charge(newpage, memcg, false); |
| 6685 | 6665 | ||
| 6686 | local_irq_save(flags); | 6666 | local_irq_save(flags); |
| 6687 | mem_cgroup_charge_statistics(memcg, newpage, compound, nr_pages); | 6667 | mem_cgroup_charge_statistics(memcg, newpage, PageTransHuge(newpage), |
| 6668 | nr_pages); | ||
| 6688 | memcg_check_events(memcg, newpage); | 6669 | memcg_check_events(memcg, newpage); |
| 6689 | local_irq_restore(flags); | 6670 | local_irq_restore(flags); |
| 6690 | } | 6671 | } |
| @@ -783,27 +783,18 @@ struct zone * zone_for_pfn_range(int online_type, int nid, unsigned start_pfn, · 782 unmodified lines | |||
| 783 | return default_zone_for_pfn(nid, start_pfn, nr_pages); | 783 | return default_zone_for_pfn(nid, start_pfn, nr_pages); |
| 784 | } | 784 | } |
| 785 | 785 | ||
| 786 | int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_type) | 786 | int __ref online_pages(unsigned long pfn, unsigned long nr_pages, |
| 787 | int online_type, int nid) | ||
| 787 | { | 788 | { |
| 788 | unsigned long flags; | 789 | unsigned long flags; |
| 789 | unsigned long onlined_pages = 0; | 790 | unsigned long onlined_pages = 0; |
| 790 | struct zone *zone; | 791 | struct zone *zone; |
| 791 | int need_zonelists_rebuild = 0; | 792 | int need_zonelists_rebuild = 0; |
| 792 | int nid; | ||
| 793 | int ret; | 793 | int ret; |
| 794 | struct memory_notify arg; | 794 | struct memory_notify arg; |
| 795 | struct memory_block *mem; | ||
| 796 | 795 | ||
| 797 | mem_hotplug_begin(); | 796 | mem_hotplug_begin(); |
| 798 | 797 | ||
| 799 | /* | ||
| 800 | * We can't use pfn_to_nid() because nid might be stored in struct page | ||
| 801 | * which is not yet initialized. Instead, we find nid from memory block. | ||
| 802 | */ | ||
| 803 | mem = find_memory_block(__pfn_to_section(pfn)); | ||
| 804 | nid = mem->nid; | ||
| 805 | put_device(&mem->dev); | ||
| 806 | |||
| 807 | /* associate pfn range with the zone */ | 798 | /* associate pfn range with the zone */ |
| 808 | zone = zone_for_pfn_range(online_type, nid, pfn, nr_pages); | 799 | zone = zone_for_pfn_range(online_type, nid, pfn, nr_pages); |
| 809 | move_pfn_range_to_zone(zone, pfn, nr_pages, NULL); | 800 | move_pfn_range_to_zone(zone, pfn, nr_pages, NULL); |
| @@ -1182,7 +1173,7 @@ static bool is_pageblock_removable_nolock(unsigned long pfn) · 372 unmodified lines | |||
| 1182 | if (!zone_spans_pfn(zone, pfn)) | 1173 | if (!zone_spans_pfn(zone, pfn)) |
| 1183 | return false; | 1174 | return false; |
| 1184 | 1175 | ||
| 1185 | return !has_unmovable_pages(zone, page, 0, MIGRATE_MOVABLE, | 1176 | return !has_unmovable_pages(zone, page, MIGRATE_MOVABLE, |
| 1186 | MEMORY_OFFLINE); | 1177 | MEMORY_OFFLINE); |
| 1187 | } | 1178 | } |
| 1188 | 1179 | ||
| @@ -1764,8 +1755,6 @@ static int __ref try_remove_memory(int nid, u64 start, u64 size) · 575 unmodified lines | |||
| 1764 | 1755 | ||
| 1765 | BUG_ON(check_hotplug_memory_range(start, size)); | 1756 | BUG_ON(check_hotplug_memory_range(start, size)); |
| 1766 | 1757 | ||
| 1767 | mem_hotplug_begin(); | ||
| 1768 | |||
| 1769 | /* | 1758 | /* |
| 1770 | * All memory blocks must be offlined before removing memory. Check | 1759 | * All memory blocks must be offlined before removing memory. Check |
| 1771 | * whether all memory blocks in question are offline and return error | 1760 | * whether all memory blocks in question are offline and return error |
| @@ -1778,9 +1767,14 @@ static int __ref try_remove_memory(int nid, u64 start, u64 size) · 6 unmodified lines | |||
| 1778 | /* remove memmap entry */ | 1767 | /* remove memmap entry */ |
| 1779 | firmware_map_remove(start, start + size, "System RAM"); | 1768 | firmware_map_remove(start, start + size, "System RAM"); |
| 1780 | 1769 | ||
| 1781 | /* remove memory block devices before removing memory */ | 1770 | /* |
| 1771 | * Memory block device removal under the device_hotplug_lock is | ||
| 1772 | * a barrier against racing online attempts. | ||
| 1773 | */ | ||
| 1782 | remove_memory_block_devices(start, size); | 1774 | remove_memory_block_devices(start, size); |
| 1783 | 1775 | ||
| 1776 | mem_hotplug_begin(); | ||
| 1777 | |||
| 1784 | arch_remove_memory(nid, start, size, NULL); | 1778 | arch_remove_memory(nid, start, size, NULL); |
| 1785 | memblock_free(start, size); | 1779 | memblock_free(start, size); |
| 1786 | memblock_remove(start, size); | 1780 | memblock_remove(start, size); |
| @@ -2821,6 +2821,9 @@ int mpol_parse_str(char *str, struct mempolicy **mpol) · 2820 unmodified lines | |||
| 2821 | char *flags = strchr(str, '='); | 2821 | char *flags = strchr(str, '='); |
| 2822 | int err = 1, mode; | 2822 | int err = 1, mode; |
| 2823 | 2823 | ||
| 2824 | if (flags) | ||
| 2825 | *flags++ = '\0'; /* terminate mode string */ | ||
| 2826 | |||
| 2824 | if (nodelist) { | 2827 | if (nodelist) { |
| 2825 | /* NUL-terminate mode or flags string */ | 2828 | /* NUL-terminate mode or flags string */ |
| 2826 | *nodelist++ = '\0'; | 2829 | *nodelist++ = '\0'; |
| @@ -2831,9 +2834,6 @@ int mpol_parse_str(char *str, struct mempolicy **mpol) · 4 unmodified lines | |||
| 2831 | } else | 2834 | } else |
| 2832 | nodes_clear(nodes); | 2835 | nodes_clear(nodes); |
| 2833 | 2836 | ||
| 2834 | if (flags) | ||
| 2835 | *flags++ = '\0'; /* terminate mode string */ | ||
| 2836 | |||
| 2837 | mode = match_string(policy_modes, MPOL_MAX, str); | 2837 | mode = match_string(policy_modes, MPOL_MAX, str); |
| 2838 | if (mode < 0) | 2838 | if (mode < 0) |
| 2839 | goto out; | 2839 | goto out; |
| @@ -27,7 +27,8 @@ static void devmap_managed_enable_put(void) · 26 unmodified lines | |||
| 27 | 27 | ||
| 28 | static int devmap_managed_enable_get(struct dev_pagemap *pgmap) | 28 | static int devmap_managed_enable_get(struct dev_pagemap *pgmap) |
| 29 | { | 29 | { |
| 30 | if (!pgmap->ops || !pgmap->ops->page_free) { | 30 | if (pgmap->type == MEMORY_DEVICE_PRIVATE && |
| 31 | (!pgmap->ops || !pgmap->ops->page_free)) { | ||
| 31 | WARN(1, "Missing page_free method\n"); | 32 | WARN(1, "Missing page_free method\n"); |
| 32 | return -EINVAL; | 33 | return -EINVAL; |
| 33 | } | 34 | } |
| @@ -410,48 +411,42 @@ struct dev_pagemap *get_dev_pagemap(unsigned long pfn, · 376 unmodified lines | |||
| 410 | EXPORT_SYMBOL_GPL(get_dev_pagemap); | 411 | EXPORT_SYMBOL_GPL(get_dev_pagemap); |
| 411 | 412 | ||
| 412 | #ifdef CONFIG_DEV_PAGEMAP_OPS | 413 | #ifdef CONFIG_DEV_PAGEMAP_OPS |
| 413 | void __put_devmap_managed_page(struct page *page) | 414 | void free_devmap_managed_page(struct page *page) |
| 414 | { | 415 | { |
| 415 | int count = page_ref_dec_return(page); | 416 | /* notify page idle for dax */ |
| 416 | 417 | if (!is_device_private_page(page)) { | |
| 417 | /* | 418 | wake_up_var(&page->_refcount); |
| 418 | * If refcount is 1 then page is freed and refcount is stable as nobody | 419 | return; |
| 419 | * holds a reference on the page. | 420 | } |
| 420 | */ | ||
| 421 | if (count == 1) { | ||
| 422 | /* Clear Active bit in case of parallel mark_page_accessed */ | ||
| 423 | __ClearPageActive(page); | ||
| 424 | __ClearPageWaiters(page); | ||
| 425 | 421 | ||
| 426 | mem_cgroup_uncharge(page); | 422 | /* Clear Active bit in case of parallel mark_page_accessed */ |
| 423 | __ClearPageActive(page); | ||
| 424 | __ClearPageWaiters(page); | ||
| 427 | 425 | ||
| 428 | /* | 426 | mem_cgroup_uncharge(page); |
| 429 | * When a device_private page is freed, the page->mapping field | ||
| 430 | * may still contain a (stale) mapping value. For example, the | ||
| 431 | * lower bits of page->mapping may still identify the page as | ||
| 432 | * an anonymous page. Ultimately, this entire field is just | ||
| 433 | * stale and wrong, and it will cause errors if not cleared. | ||
| 434 | * One example is: | ||
| 435 | * | ||
| 436 | * migrate_vma_pages() | ||
| 437 | * migrate_vma_insert_page() | ||
| 438 | * page_add_new_anon_rmap() | ||
| 439 | * __page_set_anon_rmap() | ||
| 440 | * ...checks page->mapping, via PageAnon(page) call, | ||
| 441 | * and incorrectly concludes that the page is an | ||
| 442 | * anonymous page. Therefore, it incorrectly, | ||
| 443 | * silently fails to set up the new anon rmap. | ||
| 444 | * | ||
| 445 | * For other types of ZONE_DEVICE pages, migration is either | ||
| 446 | * handled differently or not done at all, so there is no need | ||
| 447 | * to clear page->mapping. | ||
| 448 | */ | ||
| 449 | if (is_device_private_page(page)) | ||
| 450 | page->mapping = NULL; | ||
| 451 | 427 | ||
| 452 | page->pgmap->ops->page_free(page); | 428 | /* |
| 453 | } else if (!count) | 429 | * When a device_private page is freed, the page->mapping field |
| 454 | __put_page(page); | 430 | * may still contain a (stale) mapping value. For example, the |
| 431 | * lower bits of page->mapping may still identify the page as an | ||
| 432 | * anonymous page. Ultimately, this entire field is just stale | ||
| 433 | * and wrong, and it will cause errors if not cleared. One | ||
| 434 | * example is: | ||
| 435 | * | ||
| 436 | * migrate_vma_pages() | ||
| 437 | * migrate_vma_insert_page() | ||
| 438 | * page_add_new_anon_rmap() | ||
| 439 | * __page_set_anon_rmap() | ||
| 440 | * ...checks page->mapping, via PageAnon(page) call, | ||
| 441 | * and incorrectly concludes that the page is an | ||
| 442 | * anonymous page. Therefore, it incorrectly, | ||
| 443 | * silently fails to set up the new anon rmap. | ||
| 444 | * | ||
| 445 | * For other types of ZONE_DEVICE pages, migration is either | ||
| 446 | * handled differently or not done at all, so there is no need | ||
| 447 | * to clear page->mapping. | ||
| 448 | */ | ||
| 449 | page->mapping = NULL; | ||
| 450 | page->pgmap->ops->page_free(page); | ||
| 455 | } | 451 | } |
| 456 | EXPORT_SYMBOL(__put_devmap_managed_page); | ||
| 457 | #endif /* CONFIG_DEV_PAGEMAP_OPS */ | 452 | #endif /* CONFIG_DEV_PAGEMAP_OPS */ |
| @@ -48,6 +48,7 @@ · 47 unmodified lines | |||
| 48 | #include <linux/page_owner.h> | 48 | #include <linux/page_owner.h> |
| 49 | #include <linux/sched/mm.h> | 49 | #include <linux/sched/mm.h> |
| 50 | #include <linux/ptrace.h> | 50 | #include <linux/ptrace.h> |
| 51 | #include <linux/oom.h> | ||
| 51 | 52 | ||
| 52 | #include <asm/tlbflush.h> | 53 | #include <asm/tlbflush.h> |
| 53 | 54 | ||
| @@ -986,7 +987,7 @@ static int move_to_new_page(struct page *newpage, struct page *page, · 932 unmodified lines | |||
| 986 | } | 987 | } |
| 987 | 988 | ||
| 988 | /* | 989 | /* |
| 989 | * Anonymous and movable page->mapping will be cleard by | 990 | * Anonymous and movable page->mapping will be cleared by |
| 990 | * free_pages_prepare so don't reset it here for keeping | 991 | * free_pages_prepare so don't reset it here for keeping |
| 991 | * the type to work PageAnon, for example. | 992 | * the type to work PageAnon, for example. |
| 992 | */ | 993 | */ |
| @@ -1199,8 +1200,7 @@ out: · 206 unmodified lines | |||
| 1199 | /* | 1200 | /* |
| 1200 | * A page that has been migrated has all references | 1201 | * A page that has been migrated has all references |
| 1201 | * removed and will be freed. A page that has not been | 1202 | * removed and will be freed. A page that has not been |
| 1202 | * migrated will have kepts its references and be | 1203 | * migrated will have kept its references and be restored. |
| 1203 | * restored. | ||
| 1204 | */ | 1204 | */ |
| 1205 | list_del(&page->lru); | 1205 | list_del(&page->lru); |
| 1206 | 1206 | ||
| @@ -1627,8 +1627,19 @@ static int do_pages_move(struct mm_struct *mm, nodemask_t task_nodes, · 420 unmodified lines | |||
| 1627 | start = i; | 1627 | start = i; |
| 1628 | } else if (node != current_node) { | 1628 | } else if (node != current_node) { |
| 1629 | err = do_move_pages_to_node(mm, &pagelist, current_node); | 1629 | err = do_move_pages_to_node(mm, &pagelist, current_node); |
| 1630 | if (err) | 1630 | if (err) { |
| 1631 | /* | ||
| 1632 | * Positive err means the number of failed | ||
| 1633 | * pages to migrate. Since we are going to | ||
| 1634 | * abort and return the number of non-migrated | ||
| 1635 | * pages, so need to incude the rest of the | ||
| 1636 | * nr_pages that have not been attempted as | ||
| 1637 | * well. | ||
| 1638 | */ | ||
| 1639 | if (err > 0) | ||
| 1640 | err += nr_pages - i - 1; | ||
| 1631 | goto out; | 1641 | goto out; |
| 1642 | } | ||
| 1632 | err = store_status(status, start, current_node, i - start); | 1643 | err = store_status(status, start, current_node, i - start); |
| 1633 | if (err) | 1644 | if (err) |
| 1634 | goto out; | 1645 | goto out; |
| @@ -1659,8 +1670,11 @@ static int do_pages_move(struct mm_struct *mm, nodemask_t task_nodes, · 24 unmodified lines | |||
| 1659 | goto out_flush; | 1670 | goto out_flush; |
| 1660 | 1671 | ||
| 1661 | err = do_move_pages_to_node(mm, &pagelist, current_node); | 1672 | err = do_move_pages_to_node(mm, &pagelist, current_node); |
| 1662 | if (err) | 1673 | if (err) { |
| 1674 | if (err > 0) | ||
| 1675 | err += nr_pages - i - 1; | ||
| 1663 | goto out; | 1676 | goto out; |
| 1677 | } | ||
| 1664 | if (i > start) { | 1678 | if (i > start) { |
| 1665 | err = store_status(status, start, current_node, i - start); | 1679 | err = store_status(status, start, current_node, i - start); |
| 1666 | if (err) | 1680 | if (err) |
| @@ -1674,9 +1688,16 @@ out_flush: · 7 unmodified lines | |||
| 1674 | 1688 | ||
| 1675 | /* Make sure we do not overwrite the existing error */ | 1689 | /* Make sure we do not overwrite the existing error */ |
| 1676 | err1 = do_move_pages_to_node(mm, &pagelist, current_node); | 1690 | err1 = do_move_pages_to_node(mm, &pagelist, current_node); |
| 1691 | /* | ||
| 1692 | * Don't have to report non-attempted pages here since: | ||
| 1693 | * - If the above loop is done gracefully all pages have been | ||
| 1694 | * attempted. | ||
| 1695 | * - If the above loop is aborted it means a fatal error | ||
| 1696 | * happened, should return ret. | ||
| 1697 | */ | ||
| 1677 | if (!err1) | 1698 | if (!err1) |
| 1678 | err1 = store_status(status, start, current_node, i - start); | 1699 | err1 = store_status(status, start, current_node, i - start); |
| 1679 | if (!err) | 1700 | if (err >= 0) |
| 1680 | err = err1; | 1701 | err = err1; |
| 1681 | out: | 1702 | out: |
| 1682 | return err; | 1703 | return err; |
| @@ -2135,7 +2156,7 @@ static int migrate_vma_collect_hole(unsigned long start, · 452 unmodified lines | |||
| 2135 | struct migrate_vma *migrate = walk->private; | 2156 | struct migrate_vma *migrate = walk->private; |
| 2136 | unsigned long addr; | 2157 | unsigned long addr; |
| 2137 | 2158 | ||
| 2138 | for (addr = start & PAGE_MASK; addr < end; addr += PAGE_SIZE) { | 2159 | for (addr = start; addr < end; addr += PAGE_SIZE) { |
| 2139 | migrate->src[migrate->npages] = MIGRATE_PFN_MIGRATE; | 2160 | migrate->src[migrate->npages] = MIGRATE_PFN_MIGRATE; |
| 2140 | migrate->dst[migrate->npages] = 0; | 2161 | migrate->dst[migrate->npages] = 0; |
| 2141 | migrate->npages++; | 2162 | migrate->npages++; |
| @@ -2152,7 +2173,7 @@ static int migrate_vma_collect_skip(unsigned long start, · 10 unmodified lines | |||
| 2152 | struct migrate_vma *migrate = walk->private; | 2173 | struct migrate_vma *migrate = walk->private; |
| 2153 | unsigned long addr; | 2174 | unsigned long addr; |
| 2154 | 2175 | ||
| 2155 | for (addr = start & PAGE_MASK; addr < end; addr += PAGE_SIZE) { | 2176 | for (addr = start; addr < end; addr += PAGE_SIZE) { |
| 2156 | migrate->dst[migrate->npages] = 0; | 2177 | migrate->dst[migrate->npages] = 0; |
| 2157 | migrate->src[migrate->npages++] = 0; | 2178 | migrate->src[migrate->npages++] = 0; |
| 2158 | } | 2179 | } |
| @@ -2675,6 +2696,14 @@ int migrate_vma_setup(struct migrate_vma *args) · 516 unmodified lines | |||
| 2675 | } | 2696 | } |
| 2676 | EXPORT_SYMBOL(migrate_vma_setup); | 2697 | EXPORT_SYMBOL(migrate_vma_setup); |
| 2677 | 2698 | ||
| 2699 | /* | ||
| 2700 | * This code closely matches the code in: | ||
| 2701 | * __handle_mm_fault() | ||
| 2702 | * handle_pte_fault() | ||
| 2703 | * do_anonymous_page() | ||
| 2704 | * to map in an anonymous zero page but the struct page will be a ZONE_DEVICE | ||
| 2705 | * private page. | ||
| 2706 | */ | ||
| 2678 | static void migrate_vma_insert_page(struct migrate_vma *migrate, | 2707 | static void migrate_vma_insert_page(struct migrate_vma *migrate, |
| 2679 | unsigned long addr, | 2708 | unsigned long addr, |
| 2680 | struct page *page, | 2709 | struct page *page, |
| @@ -2755,30 +2784,24 @@ static void migrate_vma_insert_page(struct migrate_vma *migrate, · 74 unmodified lines | |||
| 2755 | 2784 | ||
| 2756 | ptep = pte_offset_map_lock(mm, pmdp, addr, &ptl); | 2785 | ptep = pte_offset_map_lock(mm, pmdp, addr, &ptl); |
| 2757 | 2786 | ||
| 2787 | if (check_stable_address_space(mm)) | ||
| 2788 | goto unlock_abort; | ||
| 2789 | |||
| 2758 | if (pte_present(*ptep)) { | 2790 | if (pte_present(*ptep)) { |
| 2759 | unsigned long pfn = pte_pfn(*ptep); | 2791 | unsigned long pfn = pte_pfn(*ptep); |
| 2760 | 2792 | ||
| 2761 | if (!is_zero_pfn(pfn)) { | 2793 | if (!is_zero_pfn(pfn)) |
| 2762 | pte_unmap_unlock(ptep, ptl); | 2794 | goto unlock_abort; |
| 2763 | mem_cgroup_cancel_charge(page, memcg, false); | ||
| 2764 | goto abort; | ||
| 2765 | } | ||
| 2766 | flush = true; | 2795 | flush = true; |
| 2767 | } else if (!pte_none(*ptep)) { | 2796 | } else if (!pte_none(*ptep)) |
| 2768 | pte_unmap_unlock(ptep, ptl); | 2797 | goto unlock_abort; |
| 2769 | mem_cgroup_cancel_charge(page, memcg, false); | ||
| 2770 | goto abort; | ||
| 2771 | } | ||
| 2772 | 2798 | ||
| 2773 | /* | 2799 | /* |
| 2774 | * Check for usefaultfd but do not deliver the fault. Instead, | 2800 | * Check for userfaultfd but do not deliver the fault. Instead, |
| 2775 | * just back off. | 2801 | * just back off. |
| 2776 | */ | 2802 | */ |
| 2777 | if (userfaultfd_missing(vma)) { | 2803 | if (userfaultfd_missing(vma)) |
| 2778 | pte_unmap_unlock(ptep, ptl); | 2804 | goto unlock_abort; |
| 2779 | mem_cgroup_cancel_charge(page, memcg, false); | ||
| 2780 | goto abort; | ||
| 2781 | } | ||
| 2782 | 2805 | ||
| 2783 | inc_mm_counter(mm, MM_ANONPAGES); | 2806 | inc_mm_counter(mm, MM_ANONPAGES); |
| 2784 | page_add_new_anon_rmap(page, vma, addr, false); | 2807 | page_add_new_anon_rmap(page, vma, addr, false); |
| @@ -2802,6 +2825,9 @@ static void migrate_vma_insert_page(struct migrate_vma *migrate, · 17 unmodified lines | |||
| 2802 | *src = MIGRATE_PFN_MIGRATE; | 2825 | *src = MIGRATE_PFN_MIGRATE; |
| 2803 | return; | 2826 | return; |
| 2804 | 2827 | ||
| 2828 | unlock_abort: | ||
| 2829 | pte_unmap_unlock(ptep, ptl); | ||
| 2830 | mem_cgroup_cancel_charge(page, memcg, false); | ||
| 2805 | abort: | 2831 | abort: |
| 2806 | *src &= ~MIGRATE_PFN_MIGRATE; | 2832 | *src &= ~MIGRATE_PFN_MIGRATE; |
| 2807 | } | 2833 | } |
| @@ -2834,9 +2860,8 @@ void migrate_vma_pages(struct migrate_vma *migrate) · 26 unmodified lines | |||
| 2834 | } | 2860 | } |
| 2835 | 2861 | ||
| 2836 | if (!page) { | 2862 | if (!page) { |
| 2837 | if (!(migrate->src[i] & MIGRATE_PFN_MIGRATE)) { | 2863 | if (!(migrate->src[i] & MIGRATE_PFN_MIGRATE)) |
| 2838 | continue; | 2864 | continue; |
| 2839 | } | ||
| 2840 | if (!notified) { | 2865 | if (!notified) { |
| 2841 | notified = true; | 2866 | notified = true; |
| 2842 | 2867 | ||
| @@ -1270,26 +1270,22 @@ static struct anon_vma *reusable_anon_vma(struct vm_area_struct *old, struct vm_ · 1269 unmodified lines | |||
| 1270 | */ | 1270 | */ |
| 1271 | struct anon_vma *find_mergeable_anon_vma(struct vm_area_struct *vma) | 1271 | struct anon_vma *find_mergeable_anon_vma(struct vm_area_struct *vma) |
| 1272 | { | 1272 | { |
| 1273 | struct anon_vma *anon_vma; | 1273 | struct anon_vma *anon_vma = NULL; |
| 1274 | struct vm_area_struct *near; | 1274 | |
| 1275 | 1275 | /* Try next first. */ | |
| 1276 | near = vma->vm_next; | 1276 | if (vma->vm_next) { |
| 1277 | if (!near) | 1277 | anon_vma = reusable_anon_vma(vma->vm_next, vma, vma->vm_next); |
| 1278 | goto try_prev; | 1278 | if (anon_vma) |
| 1279 | 1279 | return anon_vma; | |
| 1280 | anon_vma = reusable_anon_vma(near, vma, near); | 1280 | } |
| 1281 | if (anon_vma) | 1281 | |
| 1282 | return anon_vma; | 1282 | /* Try prev next. */ |
| 1283 | try_prev: | 1283 | if (vma->vm_prev) |
| 1284 | near = vma->vm_prev; | 1284 | anon_vma = reusable_anon_vma(vma->vm_prev, vma->vm_prev, vma); |
| 1285 | if (!near) | 1285 | |
| 1286 | goto none; | ||
| 1287 | |||
| 1288 | anon_vma = reusable_anon_vma(near, near, vma); | ||
| 1289 | if (anon_vma) | ||
| 1290 | return anon_vma; | ||
| 1291 | none: | ||
| 1292 | /* | 1286 | /* |
| 1287 | * We might reach here with anon_vma == NULL if we can't find | ||
| 1288 | * any reusable anon_vma. | ||
| 1293 | * There's no absolute need to look only at touching neighbours: | 1289 | * There's no absolute need to look only at touching neighbours: |
| 1294 | * we could search further afield for "compatible" anon_vmas. | 1290 | * we could search further afield for "compatible" anon_vmas. |
| 1295 | * But it would probably just be a waste of time searching, | 1291 | * But it would probably just be a waste of time searching, |
| @@ -1297,7 +1293,7 @@ none: · 1 unmodified line | |||
| 1297 | * We're trying to allow mprotect remerging later on, | 1293 | * We're trying to allow mprotect remerging later on, |
| 1298 | * not trying to minimize memory used for anon_vmas. | 1294 | * not trying to minimize memory used for anon_vmas. |
| 1299 | */ | 1295 | */ |
| 1300 | return NULL; | 1296 | return anon_vma; |
| 1301 | } | 1297 | } |
| 1302 | 1298 | ||
| 1303 | /* | 1299 | /* |
| @@ -26,6 +26,7 @@ · 25 unmodified lines | |||
| 26 | #include <linux/sched/mm.h> | 26 | #include <linux/sched/mm.h> |
| 27 | #include <linux/sched/coredump.h> | 27 | #include <linux/sched/coredump.h> |
| 28 | #include <linux/sched/task.h> | 28 | #include <linux/sched/task.h> |
| 29 | #include <linux/sched/debug.h> | ||
| 29 | #include <linux/swap.h> | 30 | #include <linux/swap.h> |
| 30 | #include <linux/timex.h> | 31 | #include <linux/timex.h> |
| 31 | #include <linux/jiffies.h> | 32 | #include <linux/jiffies.h> |
| @@ -620,6 +621,7 @@ static void oom_reap_task(struct task_struct *tsk) · 588 unmodified lines | |||
| 620 | 621 | ||
| 621 | pr_info("oom_reaper: unable to reap pid:%d (%s)\n", | 622 | pr_info("oom_reaper: unable to reap pid:%d (%s)\n", |
| 622 | task_pid_nr(tsk), tsk->comm); | 623 | task_pid_nr(tsk), tsk->comm); |
| 624 | sched_show_task(tsk); | ||
| 623 | debug_show_all_locks(); | 625 | debug_show_all_locks(); |
| 624 | 626 | ||
| 625 | done: | 627 | done: |
| @@ -5848,6 +5848,30 @@ overlap_memmap_init(unsigned long zone, unsigned long *pfn) · 5847 unmodified lines | |||
| 5848 | return false; | 5848 | return false; |
| 5849 | } | 5849 | } |
| 5850 | 5850 | ||
| 5851 | #ifdef CONFIG_SPARSEMEM | ||
| 5852 | /* Skip PFNs that belong to non-present sections */ | ||
| 5853 | static inline __meminit unsigned long next_pfn(unsigned long pfn) | ||
| 5854 | { | ||
| 5855 | unsigned long section_nr; | ||
| 5856 | |||
| 5857 | section_nr = pfn_to_section_nr(++pfn); | ||
| 5858 | if (present_section_nr(section_nr)) | ||
| 5859 | return pfn; | ||
| 5860 | |||
| 5861 | while (++section_nr <= __highest_present_section_nr) { | ||
| 5862 | if (present_section_nr(section_nr)) | ||
| 5863 | return section_nr_to_pfn(section_nr); | ||
| 5864 | } | ||
| 5865 | |||
| 5866 | return -1; | ||
| 5867 | } | ||
| 5868 | #else | ||
| 5869 | static inline __meminit unsigned long next_pfn(unsigned long pfn) | ||
| 5870 | { | ||
| 5871 | return pfn++; | ||
| 5872 | } | ||
| 5873 | #endif | ||
| 5874 | |||
| 5851 | /* | 5875 | /* |
| 5852 | * Initially all pages are reserved - free ones are freed | 5876 | * Initially all pages are reserved - free ones are freed |
| 5853 | * up by memblock_free_all() once the early boot process is | 5877 | * up by memblock_free_all() once the early boot process is |
| @@ -5887,8 +5911,10 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone, · 33 unmodified lines | |||
| 5887 | * function. They do not exist on hotplugged memory. | 5911 | * function. They do not exist on hotplugged memory. |
| 5888 | */ | 5912 | */ |
| 5889 | if (context == MEMMAP_EARLY) { | 5913 | if (context == MEMMAP_EARLY) { |
| 5890 | if (!early_pfn_valid(pfn)) | 5914 | if (!early_pfn_valid(pfn)) { |
| 5915 | pfn = next_pfn(pfn) - 1; | ||
| 5891 | continue; | 5916 | continue; |
| 5917 | } | ||
| 5892 | if (!early_pfn_in_nid(pfn, nid)) | 5918 | if (!early_pfn_in_nid(pfn, nid)) |
| 5893 | continue; | 5919 | continue; |
| 5894 | if (overlap_memmap_init(zone, &pfn)) | 5920 | if (overlap_memmap_init(zone, &pfn)) |
| @@ -8154,20 +8180,22 @@ void *__init alloc_large_system_hash(const char *tablename, · 2259 unmodified lines | |||
| 8154 | 8180 | ||
| 8155 | /* | 8181 | /* |
| 8156 | * This function checks whether pageblock includes unmovable pages or not. | 8182 | * This function checks whether pageblock includes unmovable pages or not. |
| 8157 | * If @count is not zero, it is okay to include less @count unmovable pages | ||
| 8158 | * | 8183 | * |
| 8159 | * PageLRU check without isolation or lru_lock could race so that | 8184 | * PageLRU check without isolation or lru_lock could race so that |
| 8160 | * MIGRATE_MOVABLE block might include unmovable pages. And __PageMovable | 8185 | * MIGRATE_MOVABLE block might include unmovable pages. And __PageMovable |
| 8161 | * check without lock_page also may miss some movable non-lru pages at | 8186 | * check without lock_page also may miss some movable non-lru pages at |
| 8162 | * race condition. So you can't expect this function should be exact. | 8187 | * race condition. So you can't expect this function should be exact. |
| 8188 | * | ||
| 8189 | * Returns a page without holding a reference. If the caller wants to | ||
| 8190 | * dereference that page (e.g., dumping), it has to make sure that that it | ||
| 8191 | * cannot get removed (e.g., via memory unplug) concurrently. | ||
| 8192 | * | ||
| 8163 | */ | 8193 | */ |
| 8164 | bool has_unmovable_pages(struct zone *zone, struct page *page, int count, | 8194 | struct page *has_unmovable_pages(struct zone *zone, struct page *page, |
| 8165 | int migratetype, int flags) | 8195 | int migratetype, int flags) |
| 8166 | { | 8196 | { |
| 8167 | unsigned long found; | ||
| 8168 | unsigned long iter = 0; | 8197 | unsigned long iter = 0; |
| 8169 | unsigned long pfn = page_to_pfn(page); | 8198 | unsigned long pfn = page_to_pfn(page); |
| 8170 | const char *reason = "unmovable page"; | ||
| 8171 | 8199 | ||
| 8172 | /* | 8200 | /* |
| 8173 | * TODO we could make this much more efficient by not checking every | 8201 | * TODO we could make this much more efficient by not checking every |
| @@ -8184,22 +8212,19 @@ bool has_unmovable_pages(struct zone *zone, struct page *page, int count, · 10 unmodified lines | |||
| 8184 | * so consider them movable here. | 8212 | * so consider them movable here. |
| 8185 | */ | 8213 | */ |
| 8186 | if (is_migrate_cma(migratetype)) | 8214 | if (is_migrate_cma(migratetype)) |
| 8187 | return false; | 8215 | return NULL; |
| 8188 | 8216 | ||
| 8189 | reason = "CMA page"; | 8217 | return page; |
| 8190 | goto unmovable; | ||
| 8191 | } | 8218 | } |
| 8192 | 8219 | ||
| 8193 | for (found = 0; iter < pageblock_nr_pages; iter++) { | 8220 | for (; iter < pageblock_nr_pages; iter++) { |
| 8194 | unsigned long check = pfn + iter; | 8221 | if (!pfn_valid_within(pfn + iter)) |
| 8195 | |||
| 8196 | if (!pfn_valid_within(check)) | ||
| 8197 | continue; | 8222 | continue; |
| 8198 | 8223 | ||
| 8199 | page = pfn_to_page(check); | 8224 | page = pfn_to_page(pfn + iter); |
| 8200 | 8225 | ||
| 8201 | if (PageReserved(page)) | 8226 | if (PageReserved(page)) |
| 8202 | goto unmovable; | 8227 | return page; |
| 8203 | 8228 | ||
| 8204 | /* | 8229 | /* |
| 8205 | * If the zone is movable and we have ruled out all reserved | 8230 | * If the zone is movable and we have ruled out all reserved |
| @@ -8219,7 +8244,7 @@ bool has_unmovable_pages(struct zone *zone, struct page *page, int count, · 13 unmodified lines | |||
| 8219 | unsigned int skip_pages; | 8244 | unsigned int skip_pages; |
| 8220 | 8245 | ||
| 8221 | if (!hugepage_migration_supported(page_hstate(head))) | 8246 | if (!hugepage_migration_supported(page_hstate(head))) |
| 8222 | goto unmovable; | 8247 | return page; |
| 8223 | 8248 | ||
| 8224 | skip_pages = compound_nr(head) - (page - head); | 8249 | skip_pages = compound_nr(head) - (page - head); |
| 8225 | iter += skip_pages - 1; | 8250 | iter += skip_pages - 1; |
| @@ -8245,11 +8270,9 @@ bool has_unmovable_pages(struct zone *zone, struct page *page, int count, · 19 unmodified lines | |||
| 8245 | if ((flags & MEMORY_OFFLINE) && PageHWPoison(page)) | 8270 | if ((flags & MEMORY_OFFLINE) && PageHWPoison(page)) |
| 8246 | continue; | 8271 | continue; |
| 8247 | 8272 | ||
| 8248 | if (__PageMovable(page)) | 8273 | if (__PageMovable(page) || PageLRU(page)) |
| 8249 | continue; | 8274 | continue; |
| 8250 | 8275 | ||
| 8251 | if (!PageLRU(page)) | ||
| 8252 | found++; | ||
| 8253 | /* | 8276 | /* |
| 8254 | * If there are RECLAIMABLE pages, we need to check | 8277 | * If there are RECLAIMABLE pages, we need to check |
| 8255 | * it. But now, memory offline itself doesn't call | 8278 | * it. But now, memory offline itself doesn't call |
| @@ -8263,15 +8286,9 @@ bool has_unmovable_pages(struct zone *zone, struct page *page, int count, · 7 unmodified lines | |||
| 8263 | * is set to both of a memory hole page and a _used_ kernel | 8286 | * is set to both of a memory hole page and a _used_ kernel |
| 8264 | * page at boot. | 8287 | * page at boot. |
| 8265 | */ | 8288 | */ |
| 8266 | if (found > count) | 8289 | return page; |
| 8267 | goto unmovable; | ||
| 8268 | } | 8290 | } |
| 8269 | return false; | 8291 | return NULL; |
| 8270 | unmovable: | ||
| 8271 | WARN_ON_ONCE(zone_idx(zone) == ZONE_MOVABLE); | ||
| 8272 | if (flags & REPORT_FAILURE) | ||
| 8273 | dump_page(pfn_to_page(pfn + iter), reason); | ||
| 8274 | return true; | ||
| 8275 | } | 8292 | } |
| 8276 | 8293 | ||
| 8277 | #ifdef CONFIG_CONTIG_ALLOC | 8294 | #ifdef CONFIG_CONTIG_ALLOC |
| @@ -8675,10 +8692,6 @@ __offline_isolated_pages(unsigned long start_pfn, unsigned long end_pfn) · 397 unmodified lines | |||
| 8675 | BUG_ON(!PageBuddy(page)); | 8692 | BUG_ON(!PageBuddy(page)); |
| 8676 | order = page_order(page); | 8693 | order = page_order(page); |
| 8677 | offlined_pages += 1 << order; | 8694 | offlined_pages += 1 << order; |
| 8678 | #ifdef CONFIG_DEBUG_VM | ||
| 8679 | pr_info("remove from free list %lx %d %lx\n", | ||
| 8680 | pfn, 1 << order, end_pfn); | ||
| 8681 | #endif | ||
| 8682 | del_page_from_free_area(page, &zone->free_area[order]); | 8695 | del_page_from_free_area(page, &zone->free_area[order]); |
| 8683 | pfn += (1 << order); | 8696 | pfn += (1 << order); |
| 8684 | } | 8697 | } |
| @@ -17,10 +17,9 @@ · 16 unmodified lines | |||
| 17 | 17 | ||
| 18 | static int set_migratetype_isolate(struct page *page, int migratetype, int isol_flags) | 18 | static int set_migratetype_isolate(struct page *page, int migratetype, int isol_flags) |
| 19 | { | 19 | { |
| 20 | struct page *unmovable = NULL; | ||
| 20 | struct zone *zone; | 21 | struct zone *zone; |
| 21 | unsigned long flags, pfn; | 22 | unsigned long flags; |
| 22 | struct memory_isolate_notify arg; | ||
| 23 | int notifier_ret; | ||
| 24 | int ret = -EBUSY; | 23 | int ret = -EBUSY; |
| 25 | 24 | ||
| 26 | zone = page_zone(page); | 25 | zone = page_zone(page); |
| @@ -35,41 +34,12 @@ static int set_migratetype_isolate(struct page *page, int migratetype, int isol_ · 8 unmodified lines | |||
| 35 | if (is_migrate_isolate_page(page)) | 34 | if (is_migrate_isolate_page(page)) |
| 36 | goto out; | 35 | goto out; |
| 37 | 36 | ||
| 38 | pfn = page_to_pfn(page); | ||
| 39 | arg.start_pfn = pfn; | ||
| 40 | arg.nr_pages = pageblock_nr_pages; | ||
| 41 | arg.pages_found = 0; | ||
| 42 | |||
| 43 | /* | ||
| 44 | * It may be possible to isolate a pageblock even if the | ||
| 45 | * migratetype is not MIGRATE_MOVABLE. The memory isolation | ||
| 46 | * notifier chain is used by balloon drivers to return the | ||
| 47 | * number of pages in a range that are held by the balloon | ||
| 48 | * driver to shrink memory. If all the pages are accounted for | ||
| 49 | * by balloons, are free, or on the LRU, isolation can continue. | ||
| 50 | * Later, for example, when memory hotplug notifier runs, these | ||
| 51 | * pages reported as "can be isolated" should be isolated(freed) | ||
| 52 | * by the balloon driver through the memory notifier chain. | ||
| 53 | */ | ||
| 54 | notifier_ret = memory_isolate_notify(MEM_ISOLATE_COUNT, &arg); | ||
| 55 | notifier_ret = notifier_to_errno(notifier_ret); | ||
| 56 | if (notifier_ret) | ||
| 57 | goto out; | ||
| 58 | /* | 37 | /* |
| 59 | * FIXME: Now, memory hotplug doesn't call shrink_slab() by itself. | 38 | * FIXME: Now, memory hotplug doesn't call shrink_slab() by itself. |
| 60 | * We just check MOVABLE pages. | 39 | * We just check MOVABLE pages. |
| 61 | */ | 40 | */ |
| 62 | if (!has_unmovable_pages(zone, page, arg.pages_found, migratetype, | 41 | unmovable = has_unmovable_pages(zone, page, migratetype, isol_flags); |
| 63 | isol_flags)) | 42 | if (!unmovable) { |
| 64 | ret = 0; | ||
| 65 | |||
| 66 | /* | ||
| 67 | * immobile means "not-on-lru" pages. If immobile is larger than | ||
| 68 | * removable-by-driver pages reported by notifier, we'll fail. | ||
| 69 | */ | ||
| 70 | |||
| 71 | out: | ||
| 72 | if (!ret) { | ||
| 73 | unsigned long nr_pages; | 43 | unsigned long nr_pages; |
| 74 | int mt = get_pageblock_migratetype(page); | 44 | int mt = get_pageblock_migratetype(page); |
| 75 | 45 | ||
| @@ -79,11 +49,24 @@ out: · 3 unmodified lines | |||
| 79 | NULL); | 49 | NULL); |
| 80 | 50 | ||
| 81 | __mod_zone_freepage_state(zone, -nr_pages, mt); | 51 | __mod_zone_freepage_state(zone, -nr_pages, mt); |
| 52 | ret = 0; | ||
| 82 | } | 53 | } |
| 83 | 54 | ||
| 55 | out: | ||
| 84 | spin_unlock_irqrestore(&zone->lock, flags); | 56 | spin_unlock_irqrestore(&zone->lock, flags); |
| 85 | if (!ret) | 57 | if (!ret) { |
| 86 | drain_all_pages(zone); | 58 | drain_all_pages(zone); |
| 59 | } else { | ||
| 60 | WARN_ON_ONCE(zone_idx(zone) == ZONE_MOVABLE); | ||
| 61 | |||
| 62 | if ((isol_flags & REPORT_FAILURE) && unmovable) | ||
| 63 | /* | ||
| 64 | * printk() with zone->lock held will likely trigger a | ||
| 65 | * lockdep splat, so defer it here. | ||
| 66 | */ | ||
| 67 | dump_page(unmovable, "unmovable page"); | ||
| 68 | } | ||
| 69 | |||
| 87 | return ret; | 70 | return ret; |
| 88 | } | 71 | } |
| 89 | 72 | ||
| @@ -52,12 +52,16 @@ static bool map_pte(struct page_vma_mapped_walk *pvmw) · 51 unmodified lines | |||
| 52 | return true; | 52 | return true; |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | static inline bool pfn_in_hpage(struct page *hpage, unsigned long pfn) | 55 | static inline bool pfn_is_match(struct page *page, unsigned long pfn) |
| 56 | { | 56 | { |
| 57 | unsigned long hpage_pfn = page_to_pfn(hpage); | 57 | unsigned long page_pfn = page_to_pfn(page); |
| 58 | |||
| 59 | /* normal page and hugetlbfs page */ | ||
| 60 | if (!PageTransCompound(page) || PageHuge(page)) | ||
| 61 | return page_pfn == pfn; | ||
| 58 | 62 | ||
| 59 | /* THP can be referenced by any subpage */ | 63 | /* THP can be referenced by any subpage */ |
| 60 | return pfn >= hpage_pfn && pfn - hpage_pfn < hpage_nr_pages(hpage); | 64 | return pfn >= page_pfn && pfn - page_pfn < hpage_nr_pages(page); |
| 61 | } | 65 | } |
| 62 | 66 | ||
| 63 | /** | 67 | /** |
| @@ -108,7 +112,7 @@ static bool check_pte(struct page_vma_mapped_walk *pvmw) · 44 unmodified lines | |||
| 108 | pfn = pte_pfn(*pvmw->pte); | 112 | pfn = pte_pfn(*pvmw->pte); |
| 109 | } | 113 | } |
| 110 | 114 | ||
| 111 | return pfn_in_hpage(pvmw->page, pfn); | 115 | return pfn_is_match(pvmw->page, pfn); |
| 112 | } | 116 | } |
| 113 | 117 | ||
| 114 | /** | 118 | /** |
| @@ -42,12 +42,11 @@ static int process_vm_rw_pages(struct page **pages, · 41 unmodified lines | |||
| 42 | if (copy > len) | 42 | if (copy > len) |
| 43 | copy = len; | 43 | copy = len; |
| 44 | 44 | ||
| 45 | if (vm_write) { | 45 | if (vm_write) |
| 46 | copied = copy_page_from_iter(page, offset, copy, iter); | 46 | copied = copy_page_from_iter(page, offset, copy, iter); |
| 47 | set_page_dirty_lock(page); | 47 | else |
| 48 | } else { | ||
| 49 | copied = copy_page_to_iter(page, offset, copy, iter); | 48 | copied = copy_page_to_iter(page, offset, copy, iter); |
| 50 | } | 49 | |
| 51 | len -= copied; | 50 | len -= copied; |
| 52 | if (copied < copy && iov_iter_count(iter)) | 51 | if (copied < copy && iov_iter_count(iter)) |
| 53 | return -EFAULT; | 52 | return -EFAULT; |
| @@ -96,7 +95,7 @@ static int process_vm_rw_single_vec(unsigned long addr, · 42 unmodified lines | |||
| 96 | flags |= FOLL_WRITE; | 95 | flags |= FOLL_WRITE; |
| 97 | 96 | ||
| 98 | while (!rc && nr_pages && iov_iter_count(iter)) { | 97 | while (!rc && nr_pages && iov_iter_count(iter)) { |
| 99 | int pages = min(nr_pages, max_pages_per_loop); | 98 | int pinned_pages = min(nr_pages, max_pages_per_loop); |
| 100 | int locked = 1; | 99 | int locked = 1; |
| 101 | size_t bytes; | 100 | size_t bytes; |
| 102 | 101 | ||
| @@ -106,14 +105,15 @@ static int process_vm_rw_single_vec(unsigned long addr, · 3 unmodified lines | |||
| 106 | * current/current->mm | 105 | * current/current->mm |
| 107 | */ | 106 | */ |
| 108 | down_read(&mm->mmap_sem); | 107 | down_read(&mm->mmap_sem); |
| 109 | pages = get_user_pages_remote(task, mm, pa, pages, flags, | 108 | pinned_pages = pin_user_pages_remote(task, mm, pa, pinned_pages, |
| 110 | process_pages, NULL, &locked); | 109 | flags, process_pages, |
| 110 | NULL, &locked); | ||
| 111 | if (locked) | 111 | if (locked) |
| 112 | up_read(&mm->mmap_sem); | 112 | up_read(&mm->mmap_sem); |
| 113 | if (pages <= 0) | 113 | if (pinned_pages <= 0) |
| 114 | return -EFAULT; | 114 | return -EFAULT; |
| 115 | 115 | ||
| 116 | bytes = pages * PAGE_SIZE - start_offset; | 116 | bytes = pinned_pages * PAGE_SIZE - start_offset; |
| 117 | if (bytes > len) | 117 | if (bytes > len) |
| 118 | bytes = len; | 118 | bytes = len; |
| 119 | 119 | ||
| @@ -122,10 +122,12 @@ static int process_vm_rw_single_vec(unsigned long addr, · 2 unmodified lines | |||
| 122 | vm_write); | 122 | vm_write); |
| 123 | len -= bytes; | 123 | len -= bytes; |
| 124 | start_offset = 0; | 124 | start_offset = 0; |
| 125 | nr_pages -= pages; | 125 | nr_pages -= pinned_pages; |
| 126 | pa += pages * PAGE_SIZE; | 126 | pa += pinned_pages * PAGE_SIZE; |
| 127 | while (pages) | 127 | |
| 128 | put_page(process_pages[--pages]); | 128 | /* If vm_write is set, the pages need to be made dirty: */ |
| 129 | unpin_user_pages_dirty_lock(process_pages, pinned_pages, | ||
| 130 | vm_write); | ||
| 129 | } | 131 | } |
| 130 | 132 | ||
| 131 | return rc; | 133 | return rc; |
| @@ -439,19 +439,38 @@ static inline bool cmpxchg_double_slab(struct kmem_cache *s, struct page *page, · 438 unmodified lines | |||
| 439 | } | 439 | } |
| 440 | 440 | ||
| 441 | #ifdef CONFIG_SLUB_DEBUG | 441 | #ifdef CONFIG_SLUB_DEBUG |
| 442 | static unsigned long object_map[BITS_TO_LONGS(MAX_OBJS_PER_PAGE)]; | ||
| 443 | static DEFINE_SPINLOCK(object_map_lock); | ||
| 444 | |||
| 442 | /* | 445 | /* |
| 443 | * Determine a map of object in use on a page. | 446 | * Determine a map of object in use on a page. |
| 444 | * | 447 | * |
| 445 | * Node listlock must be held to guarantee that the page does | 448 | * Node listlock must be held to guarantee that the page does |
| 446 | * not vanish from under us. | 449 | * not vanish from under us. |
| 447 | */ | 450 | */ |
| 448 | static void get_map(struct kmem_cache *s, struct page *page, unsigned long *map) | 451 | static unsigned long *get_map(struct kmem_cache *s, struct page *page) |
| 449 | { | 452 | { |
| 450 | void *p; | 453 | void *p; |
| 451 | void *addr = page_address(page); | 454 | void *addr = page_address(page); |
| 452 | 455 | ||
| 456 | VM_BUG_ON(!irqs_disabled()); | ||
| 457 | |||
| 458 | spin_lock(&object_map_lock); | ||
| 459 | |||
| 460 | bitmap_zero(object_map, page->objects); | ||
| 461 | |||
| 453 | for (p = page->freelist; p; p = get_freepointer(s, p)) | 462 | for (p = page->freelist; p; p = get_freepointer(s, p)) |
| 454 | set_bit(slab_index(p, s, addr), map); | 463 | set_bit(slab_index(p, s, addr), object_map); |
| 464 | |||
| 465 | return object_map; | ||
| 466 | } | ||
| 467 | |||
| 468 | static void put_map(unsigned long *map) | ||
| 469 | { | ||
| 470 | VM_BUG_ON(map != object_map); | ||
| 471 | lockdep_assert_held(&object_map_lock); | ||
| 472 | |||
| 473 | spin_unlock(&object_map_lock); | ||
| 455 | } | 474 | } |
| 456 | 475 | ||
| 457 | static inline unsigned int size_from_object(struct kmem_cache *s) | 476 | static inline unsigned int size_from_object(struct kmem_cache *s) |
| @@ -3675,13 +3694,12 @@ static void list_slab_objects(struct kmem_cache *s, struct page *page, · 3217 unmodified lines | |||
| 3675 | #ifdef CONFIG_SLUB_DEBUG | 3694 | #ifdef CONFIG_SLUB_DEBUG |
| 3676 | void *addr = page_address(page); | 3695 | void *addr = page_address(page); |
| 3677 | void *p; | 3696 | void *p; |
| 3678 | unsigned long *map = bitmap_zalloc(page->objects, GFP_ATOMIC); | 3697 | unsigned long *map; |
| 3679 | if (!map) | 3698 | |
| 3680 | return; | ||
| 3681 | slab_err(s, page, text, s->name); | 3699 | slab_err(s, page, text, s->name); |
| 3682 | slab_lock(page); | 3700 | slab_lock(page); |
| 3683 | 3701 | ||
| 3684 | get_map(s, page, map); | 3702 | map = get_map(s, page); |
| 3685 | for_each_object(p, s, addr, page->objects) { | 3703 | for_each_object(p, s, addr, page->objects) { |
| 3686 | 3704 | ||
| 3687 | if (!test_bit(slab_index(p, s, addr), map)) { | 3705 | if (!test_bit(slab_index(p, s, addr), map)) { |
| @@ -3689,8 +3707,9 @@ static void list_slab_objects(struct kmem_cache *s, struct page *page, · 1 unmodified line | |||
| 3689 | print_tracking(s, p); | 3707 | print_tracking(s, p); |
| 3690 | } | 3708 | } |
| 3691 | } | 3709 | } |
| 3710 | put_map(map); | ||
| 3711 | |||
| 3692 | slab_unlock(page); | 3712 | slab_unlock(page); |
| 3693 | bitmap_free(map); | ||
| 3694 | #endif | 3713 | #endif |
| 3695 | } | 3714 | } |
| 3696 | 3715 | ||
| @@ -4384,19 +4403,19 @@ static int count_total(struct page *page) · 687 unmodified lines | |||
| 4384 | #endif | 4403 | #endif |
| 4385 | 4404 | ||
| 4386 | #ifdef CONFIG_SLUB_DEBUG | 4405 | #ifdef CONFIG_SLUB_DEBUG |
| 4387 | static void validate_slab(struct kmem_cache *s, struct page *page, | 4406 | static void validate_slab(struct kmem_cache *s, struct page *page) |
| 4388 | unsigned long *map) | ||
| 4389 | { | 4407 | { |
| 4390 | void *p; | 4408 | void *p; |
| 4391 | void *addr = page_address(page); | 4409 | void *addr = page_address(page); |
| 4410 | unsigned long *map; | ||
| 4411 | |||
| 4412 | slab_lock(page); | ||
| 4392 | 4413 | ||
| 4393 | if (!check_slab(s, page) || !on_freelist(s, page, NULL)) | 4414 | if (!check_slab(s, page) || !on_freelist(s, page, NULL)) |
| 4394 | return; | 4415 | goto unlock; |
| 4395 | 4416 | ||
| 4396 | /* Now we know that a valid freelist exists */ | 4417 | /* Now we know that a valid freelist exists */ |
| 4397 | bitmap_zero(map, page->objects); | 4418 | map = get_map(s, page); |
| 4398 | |||
| 4399 | get_map(s, page, map); | ||
| 4400 | for_each_object(p, s, addr, page->objects) { | 4419 | for_each_object(p, s, addr, page->objects) { |
| 4401 | u8 val = test_bit(slab_index(p, s, addr), map) ? | 4420 | u8 val = test_bit(slab_index(p, s, addr), map) ? |
| 4402 | SLUB_RED_INACTIVE : SLUB_RED_ACTIVE; | 4421 | SLUB_RED_INACTIVE : SLUB_RED_ACTIVE; |
| @@ -4404,18 +4423,13 @@ static void validate_slab(struct kmem_cache *s, struct page *page, · 1 unmodified line | |||
| 4404 | if (!check_object(s, page, p, val)) | 4423 | if (!check_object(s, page, p, val)) |
| 4405 | break; | 4424 | break; |
| 4406 | } | 4425 | } |
| 4407 | } | 4426 | put_map(map); |
| 4408 | 4427 | unlock: | |
| 4409 | static void validate_slab_slab(struct kmem_cache *s, struct page *page, | ||
| 4410 | unsigned long *map) | ||
| 4411 | { | ||
| 4412 | slab_lock(page); | ||
| 4413 | validate_slab(s, page, map); | ||
| 4414 | slab_unlock(page); | 4428 | slab_unlock(page); |
| 4415 | } | 4429 | } |
| 4416 | 4430 | ||
| 4417 | static int validate_slab_node(struct kmem_cache *s, | 4431 | static int validate_slab_node(struct kmem_cache *s, |
| 4418 | struct kmem_cache_node *n, unsigned long *map) | 4432 | struct kmem_cache_node *n) |
| 4419 | { | 4433 | { |
| 4420 | unsigned long count = 0; | 4434 | unsigned long count = 0; |
| 4421 | struct page *page; | 4435 | struct page *page; |
| @@ -4424,7 +4438,7 @@ static int validate_slab_node(struct kmem_cache *s, · 2 unmodified lines | |||
| 4424 | spin_lock_irqsave(&n->list_lock, flags); | 4438 | spin_lock_irqsave(&n->list_lock, flags); |
| 4425 | 4439 | ||
| 4426 | list_for_each_entry(page, &n->partial, slab_list) { | 4440 | list_for_each_entry(page, &n->partial, slab_list) { |
| 4427 | validate_slab_slab(s, page, map); | 4441 | validate_slab(s, page); |
| 4428 | count++; | 4442 | count++; |
| 4429 | } | 4443 | } |
| 4430 | if (count != n->nr_partial) | 4444 | if (count != n->nr_partial) |
| @@ -4435,7 +4449,7 @@ static int validate_slab_node(struct kmem_cache *s, · 4 unmodified lines | |||
| 4435 | goto out; | 4449 | goto out; |
| 4436 | 4450 | ||
| 4437 | list_for_each_entry(page, &n->full, slab_list) { | 4451 | list_for_each_entry(page, &n->full, slab_list) { |
| 4438 | validate_slab_slab(s, page, map); | 4452 | validate_slab(s, page); |
| 4439 | count++; | 4453 | count++; |
| 4440 | } | 4454 | } |
| 4441 | if (count != atomic_long_read(&n->nr_slabs)) | 4455 | if (count != atomic_long_read(&n->nr_slabs)) |
| @@ -4452,15 +4466,11 @@ static long validate_slab_cache(struct kmem_cache *s) · 10 unmodified lines | |||
| 4452 | int node; | 4466 | int node; |
| 4453 | unsigned long count = 0; | 4467 | unsigned long count = 0; |
| 4454 | struct kmem_cache_node *n; | 4468 | struct kmem_cache_node *n; |
| 4455 | unsigned long *map = bitmap_alloc(oo_objects(s->max), GFP_KERNEL); | ||
| 4456 | |||
| 4457 | if (!map) | ||
| 4458 | return -ENOMEM; | ||
| 4459 | 4469 | ||
| 4460 | flush_all(s); | 4470 | flush_all(s); |
| 4461 | for_each_kmem_cache_node(s, node, n) | 4471 | for_each_kmem_cache_node(s, node, n) |
| 4462 | count += validate_slab_node(s, n, map); | 4472 | count += validate_slab_node(s, n); |
| 4463 | bitmap_free(map); | 4473 | |
| 4464 | return count; | 4474 | return count; |
| 4465 | } | 4475 | } |
| 4466 | /* | 4476 | /* |
| @@ -4590,18 +4600,17 @@ static int add_location(struct loc_track *t, struct kmem_cache *s, · 123 unmodified lines | |||
| 4590 | } | 4600 | } |
| 4591 | 4601 | ||
| 4592 | static void process_slab(struct loc_track *t, struct kmem_cache *s, | 4602 | static void process_slab(struct loc_track *t, struct kmem_cache *s, |
| 4593 | struct page *page, enum track_item alloc, | 4603 | struct page *page, enum track_item alloc) |
| 4594 | unsigned long *map) | ||
| 4595 | { | 4604 | { |
| 4596 | void *addr = page_address(page); | 4605 | void *addr = page_address(page); |
| 4597 | void *p; | 4606 | void *p; |
| 4607 | unsigned long *map; | ||
| 4598 | 4608 | ||
| 4599 | bitmap_zero(map, page->objects); | 4609 | map = get_map(s, page); |
| 4600 | get_map(s, page, map); | ||
| 4601 | |||
| 4602 | for_each_object(p, s, addr, page->objects) | 4610 | for_each_object(p, s, addr, page->objects) |
| 4603 | if (!test_bit(slab_index(p, s, addr), map)) | 4611 | if (!test_bit(slab_index(p, s, addr), map)) |
| 4604 | add_location(t, s, get_track(s, p, alloc)); | 4612 | add_location(t, s, get_track(s, p, alloc)); |
| 4613 | put_map(map); | ||
| 4605 | } | 4614 | } |
| 4606 | 4615 | ||
| 4607 | static int list_locations(struct kmem_cache *s, char *buf, | 4616 | static int list_locations(struct kmem_cache *s, char *buf, |
| @@ -4612,11 +4621,9 @@ static int list_locations(struct kmem_cache *s, char *buf, · 4 unmodified lines | |||
| 4612 | struct loc_track t = { 0, 0, NULL }; | 4621 | struct loc_track t = { 0, 0, NULL }; |
| 4613 | int node; | 4622 | int node; |
| 4614 | struct kmem_cache_node *n; | 4623 | struct kmem_cache_node *n; |
| 4615 | unsigned long *map = bitmap_alloc(oo_objects(s->max), GFP_KERNEL); | ||
| 4616 | 4624 | ||
| 4617 | if (!map || !alloc_loc_track(&t, PAGE_SIZE / sizeof(struct location), | 4625 | if (!alloc_loc_track(&t, PAGE_SIZE / sizeof(struct location), |
| 4618 | GFP_KERNEL)) { | 4626 | GFP_KERNEL)) { |
| 4619 | bitmap_free(map); | ||
| 4620 | return sprintf(buf, "Out of memory\n"); | 4627 | return sprintf(buf, "Out of memory\n"); |
| 4621 | } | 4628 | } |
| 4622 | /* Push back cpu slabs */ | 4629 | /* Push back cpu slabs */ |
| @@ -4631,9 +4638,9 @@ static int list_locations(struct kmem_cache *s, char *buf, · 8 unmodified lines | |||
| 4631 | 4638 | ||
| 4632 | spin_lock_irqsave(&n->list_lock, flags); | 4639 | spin_lock_irqsave(&n->list_lock, flags); |
| 4633 | list_for_each_entry(page, &n->partial, slab_list) | 4640 | list_for_each_entry(page, &n->partial, slab_list) |
| 4634 | process_slab(&t, s, page, alloc, map); | 4641 | process_slab(&t, s, page, alloc); |
| 4635 | list_for_each_entry(page, &n->full, slab_list) | 4642 | list_for_each_entry(page, &n->full, slab_list) |
| 4636 | process_slab(&t, s, page, alloc, map); | 4643 | process_slab(&t, s, page, alloc); |
| 4637 | spin_unlock_irqrestore(&n->list_lock, flags); | 4644 | spin_unlock_irqrestore(&n->list_lock, flags); |
| 4638 | } | 4645 | } |
| 4639 | 4646 | ||
| @@ -4682,7 +4689,6 @@ static int list_locations(struct kmem_cache *s, char *buf, · 42 unmodified lines | |||
| 4682 | } | 4689 | } |
| 4683 | 4690 | ||
| 4684 | free_loc_track(&t); | 4691 | free_loc_track(&t); |
| 4685 | bitmap_free(map); | ||
| 4686 | if (!t.count) | 4692 | if (!t.count) |
| 4687 | len += sprintf(buf, "No data\n"); | 4693 | len += sprintf(buf, "No data\n"); |
| 4688 | return len; | 4694 | return len; |
| @@ -789,7 +789,7 @@ static void section_deactivate(unsigned long pfn, unsigned long nr_pages, · 788 unmodified lines | |||
| 789 | ms->usage = NULL; | 789 | ms->usage = NULL; |
| 790 | } | 790 | } |
| 791 | memmap = sparse_decode_mem_map(ms->section_mem_map, section_nr); | 791 | memmap = sparse_decode_mem_map(ms->section_mem_map, section_nr); |
| 792 | ms->section_mem_map = sparse_encode_mem_map(NULL, section_nr); | 792 | ms->section_mem_map = (unsigned long)NULL; |
| 793 | } | 793 | } |
| 794 | 794 | ||
| 795 | if (section_is_early && memmap) | 795 | if (section_is_early && memmap) |
| @@ -813,8 +813,10 @@ void release_pages(struct page **pages, int nr) · 812 unmodified lines | |||
| 813 | * processing, and instead, expect a call to | 813 | * processing, and instead, expect a call to |
| 814 | * put_page_testzero(). | 814 | * put_page_testzero(). |
| 815 | */ | 815 | */ |
| 816 | if (put_devmap_managed_page(page)) | 816 | if (page_is_devmap_managed(page)) { |
| 817 | put_devmap_managed_page(page); | ||
| 817 | continue; | 818 | continue; |
| 819 | } | ||
| 818 | } | 820 | } |
| 819 | 821 | ||
| 820 | page = compound_head(page); | 822 | page = compound_head(page); |
| @@ -1102,3 +1104,26 @@ void __init swap_setup(void) · 281 unmodified lines | |||
| 1102 | * _really_ don't want to cluster much more | 1104 | * _really_ don't want to cluster much more |
| 1103 | */ | 1105 | */ |
| 1104 | } | 1106 | } |
| 1107 | |||
| 1108 | #ifdef CONFIG_DEV_PAGEMAP_OPS | ||
| 1109 | void put_devmap_managed_page(struct page *page) | ||
| 1110 | { | ||
| 1111 | int count; | ||
| 1112 | |||
| 1113 | if (WARN_ON_ONCE(!page_is_devmap_managed(page))) | ||
| 1114 | return; | ||
| 1115 | |||
| 1116 | count = page_ref_dec_return(page); | ||
| 1117 | |||
| 1118 | /* | ||
| 1119 | * devmap page refcounts are 1-based, rather than 0-based: if | ||
| 1120 | * refcount is 1, then the page is free and the refcount is | ||
| 1121 | * stable because nobody holds a reference on the page. | ||
| 1122 | */ | ||
| 1123 | if (count == 1) | ||
| 1124 | free_devmap_managed_page(page); | ||
| 1125 | else if (!count) | ||
| 1126 | __put_page(page); | ||
| 1127 | } | ||
| 1128 | EXPORT_SYMBOL(put_devmap_managed_page); | ||
| 1129 | #endif | ||
| @@ -2737,10 +2737,10 @@ static void *swap_next(struct seq_file *swap, void *v, loff_t *pos) · 2736 unmodified lines | |||
| 2737 | else | 2737 | else |
| 2738 | type = si->type + 1; | 2738 | type = si->type + 1; |
| 2739 | 2739 | ||
| 2740 | ++(*pos); | ||
| 2740 | for (; (si = swap_type_to_swap_info(type)); type++) { | 2741 | for (; (si = swap_type_to_swap_info(type)); type++) { |
| 2741 | if (!(si->flags & SWP_USED) || !si->swap_map) | 2742 | if (!(si->flags & SWP_USED) || !si->swap_map) |
| 2742 | continue; | 2743 | continue; |
| 2743 | ++*pos; | ||
| 2744 | return si; | 2744 | return si; |
| 2745 | } | 2745 | } |
| 2746 | 2746 | ||
| @@ -146,20 +146,6 @@ struct scan_control { · 145 unmodified lines | |||
| 146 | struct reclaim_state reclaim_state; | 146 | struct reclaim_state reclaim_state; |
| 147 | }; | 147 | }; |
| 148 | 148 | ||
| 149 | #ifdef ARCH_HAS_PREFETCH | ||
| 150 | #define prefetch_prev_lru_page(_page, _base, _field) \ | ||
| 151 | do { \ | ||
| 152 | if ((_page)->lru.prev != _base) { \ | ||
| 153 | struct page *prev; \ | ||
| 154 | \ | ||
| 155 | prev = lru_to_page(&(_page->lru)); \ | ||
| 156 | prefetch(&prev->_field); \ | ||
| 157 | } \ | ||
| 158 | } while (0) | ||
| 159 | #else | ||
| 160 | #define prefetch_prev_lru_page(_page, _base, _field) do { } while (0) | ||
| 161 | #endif | ||
| 162 | |||
| 163 | #ifdef ARCH_HAS_PREFETCHW | 149 | #ifdef ARCH_HAS_PREFETCHW |
| 164 | #define prefetchw_prev_lru_page(_page, _base, _field) \ | 150 | #define prefetchw_prev_lru_page(_page, _base, _field) \ |
| 165 | do { \ | 151 | do { \ |
| @@ -2695,7 +2681,7 @@ static void shrink_node_memcgs(pg_data_t *pgdat, struct scan_control *sc) · 2529 unmodified lines | |||
| 2695 | } while ((memcg = mem_cgroup_iter(target_memcg, memcg, NULL))); | 2681 | } while ((memcg = mem_cgroup_iter(target_memcg, memcg, NULL))); |
| 2696 | } | 2682 | } |
| 2697 | 2683 | ||
| 2698 | static bool shrink_node(pg_data_t *pgdat, struct scan_control *sc) | 2684 | static void shrink_node(pg_data_t *pgdat, struct scan_control *sc) |
| 2699 | { | 2685 | { |
| 2700 | struct reclaim_state *reclaim_state = current->reclaim_state; | 2686 | struct reclaim_state *reclaim_state = current->reclaim_state; |
| 2701 | unsigned long nr_reclaimed, nr_scanned; | 2687 | unsigned long nr_reclaimed, nr_scanned; |
| @@ -2874,8 +2860,6 @@ again: · 172 unmodified lines | |||
| 2874 | */ | 2860 | */ |
| 2875 | if (reclaimable) | 2861 | if (reclaimable) |
| 2876 | pgdat->kswapd_failures = 0; | 2862 | pgdat->kswapd_failures = 0; |
| 2877 | |||
| 2878 | return reclaimable; | ||
| 2879 | } | 2863 | } |
| 2880 | 2864 | ||
| 2881 | /* | 2865 | /* |
| @@ -4126,10 +4110,8 @@ module_init(kswapd_init) · 1244 unmodified lines | |||
| 4126 | */ | 4110 | */ |
| 4127 | int node_reclaim_mode __read_mostly; | 4111 | int node_reclaim_mode __read_mostly; |
| 4128 | 4112 | ||
| 4129 | #define RECLAIM_OFF 0 | 4113 | #define RECLAIM_WRITE (1<<0) /* Writeout pages during reclaim */ |
| 4130 | #define RECLAIM_ZONE (1<<0) /* Run shrink_inactive_list on the zone */ | 4114 | #define RECLAIM_UNMAP (1<<1) /* Unmap pages during reclaim */ |
| 4131 | #define RECLAIM_WRITE (1<<1) /* Writeout pages during reclaim */ | ||
| 4132 | #define RECLAIM_UNMAP (1<<2) /* Unmap pages during reclaim */ | ||
| 4133 | 4115 | ||
| 4134 | /* | 4116 | /* |
| 4135 | * Priority for NODE_RECLAIM. This determines the fraction of pages | 4117 | * Priority for NODE_RECLAIM. This determines the fraction of pages |
| @@ -32,6 +32,7 @@ · 31 unmodified lines | |||
| 32 | #include <linux/swapops.h> | 32 | #include <linux/swapops.h> |
| 33 | #include <linux/writeback.h> | 33 | #include <linux/writeback.h> |
| 34 | #include <linux/pagemap.h> | 34 | #include <linux/pagemap.h> |
| 35 | #include <linux/workqueue.h> | ||
| 35 | 36 | ||
| 36 | /********************************* | 37 | /********************************* |
| 37 | * statistics | 38 | * statistics |
| @@ -65,6 +66,11 @@ static u64 zswap_reject_kmemcache_fail; · 27 unmodified lines | |||
| 65 | /* Duplicate store was encountered (rare) */ | 66 | /* Duplicate store was encountered (rare) */ |
| 66 | static u64 zswap_duplicate_entry; | 67 | static u64 zswap_duplicate_entry; |
| 67 | 68 | ||
| 69 | /* Shrinker work queue */ | ||
| 70 | static struct workqueue_struct *shrink_wq; | ||
| 71 | /* Pool limit was hit, we need to calm down */ | ||
| 72 | static bool zswap_pool_reached_full; | ||
| 73 | |||
| 68 | /********************************* | 74 | /********************************* |
| 69 | * tunables | 75 | * tunables |
| 70 | **********************************/ | 76 | **********************************/ |
| @@ -109,6 +115,11 @@ module_param_cb(zpool, &zswap_zpool_param_ops, &zswap_zpool_type, 0644); · 38 unmodified lines | |||
| 109 | static unsigned int zswap_max_pool_percent = 20; | 115 | static unsigned int zswap_max_pool_percent = 20; |
| 110 | module_param_named(max_pool_percent, zswap_max_pool_percent, uint, 0644); | 116 | module_param_named(max_pool_percent, zswap_max_pool_percent, uint, 0644); |
| 111 | 117 | ||
| 118 | /* The threshold for accepting new pages after the max_pool_percent was hit */ | ||
| 119 | static unsigned int zswap_accept_thr_percent = 90; /* of max pool size */ | ||
| 120 | module_param_named(accept_threshold_percent, zswap_accept_thr_percent, | ||
| 121 | uint, 0644); | ||
| 122 | |||
| 112 | /* Enable/disable handling same-value filled pages (enabled by default) */ | 123 | /* Enable/disable handling same-value filled pages (enabled by default) */ |
| 113 | static bool zswap_same_filled_pages_enabled = true; | 124 | static bool zswap_same_filled_pages_enabled = true; |
| 114 | module_param_named(same_filled_pages_enabled, zswap_same_filled_pages_enabled, | 125 | module_param_named(same_filled_pages_enabled, zswap_same_filled_pages_enabled, |
| @@ -123,7 +134,8 @@ struct zswap_pool { · 8 unmodified lines | |||
| 123 | struct crypto_comp * __percpu *tfm; | 134 | struct crypto_comp * __percpu *tfm; |
| 124 | struct kref kref; | 135 | struct kref kref; |
| 125 | struct list_head list; | 136 | struct list_head list; |
| 126 | struct work_struct work; | 137 | struct work_struct release_work; |
| 138 | struct work_struct shrink_work; | ||
| 127 | struct hlist_node node; | 139 | struct hlist_node node; |
| 128 | char tfm_name[CRYPTO_MAX_ALG_NAME]; | 140 | char tfm_name[CRYPTO_MAX_ALG_NAME]; |
| 129 | }; | 141 | }; |
| @@ -214,6 +226,13 @@ static bool zswap_is_full(void) · 84 unmodified lines | |||
| 214 | DIV_ROUND_UP(zswap_pool_total_size, PAGE_SIZE); | 226 | DIV_ROUND_UP(zswap_pool_total_size, PAGE_SIZE); |
| 215 | } | 227 | } |
| 216 | 228 | ||
| 229 | static bool zswap_can_accept(void) | ||
| 230 | { | ||
| 231 | return totalram_pages() * zswap_accept_thr_percent / 100 * | ||
| 232 | zswap_max_pool_percent / 100 > | ||
| 233 | DIV_ROUND_UP(zswap_pool_total_size, PAGE_SIZE); | ||
| 234 | } | ||
| 235 | |||
| 217 | static void zswap_update_total_size(void) | 236 | static void zswap_update_total_size(void) |
| 218 | { | 237 | { |
| 219 | struct zswap_pool *pool; | 238 | struct zswap_pool *pool; |
| @@ -501,6 +520,16 @@ static struct zswap_pool *zswap_pool_find_get(char *type, char *compressor) · 281 unmodified lines | |||
| 501 | return NULL; | 520 | return NULL; |
| 502 | } | 521 | } |
| 503 | 522 | ||
| 523 | static void shrink_worker(struct work_struct *w) | ||
| 524 | { | ||
| 525 | struct zswap_pool *pool = container_of(w, typeof(*pool), | ||
| 526 | shrink_work); | ||
| 527 | |||
| 528 | if (zpool_shrink(pool->zpool, 1, NULL)) | ||
| 529 | zswap_reject_reclaim_fail++; | ||
| 530 | zswap_pool_put(pool); | ||
| 531 | } | ||
| 532 | |||
| 504 | static struct zswap_pool *zswap_pool_create(char *type, char *compressor) | 533 | static struct zswap_pool *zswap_pool_create(char *type, char *compressor) |
| 505 | { | 534 | { |
| 506 | struct zswap_pool *pool; | 535 | struct zswap_pool *pool; |
| @@ -551,6 +580,7 @@ static struct zswap_pool *zswap_pool_create(char *type, char *compressor) · 44 unmodified lines | |||
| 551 | */ | 580 | */ |
| 552 | kref_init(&pool->kref); | 581 | kref_init(&pool->kref); |
| 553 | INIT_LIST_HEAD(&pool->list); | 582 | INIT_LIST_HEAD(&pool->list); |
| 583 | INIT_WORK(&pool->shrink_work, shrink_worker); | ||
| 554 | 584 | ||
| 555 | zswap_pool_debug("created", pool); | 585 | zswap_pool_debug("created", pool); |
| 556 | 586 | ||
| @@ -624,7 +654,8 @@ static int __must_check zswap_pool_get(struct zswap_pool *pool) · 67 unmodified lines | |||
| 624 | 654 | ||
| 625 | static void __zswap_pool_release(struct work_struct *work) | 655 | static void __zswap_pool_release(struct work_struct *work) |
| 626 | { | 656 | { |
| 627 | struct zswap_pool *pool = container_of(work, typeof(*pool), work); | 657 | struct zswap_pool *pool = container_of(work, typeof(*pool), |
| 658 | release_work); | ||
| 628 | 659 | ||
| 629 | synchronize_rcu(); | 660 | synchronize_rcu(); |
| 630 | 661 | ||
| @@ -647,8 +678,8 @@ static void __zswap_pool_empty(struct kref *kref) · 16 unmodified lines | |||
| 647 | 678 | ||
| 648 | list_del_rcu(&pool->list); | 679 | list_del_rcu(&pool->list); |
| 649 | 680 | ||
| 650 | INIT_WORK(&pool->work, __zswap_pool_release); | 681 | INIT_WORK(&pool->release_work, __zswap_pool_release); |
| 651 | schedule_work(&pool->work); | 682 | schedule_work(&pool->release_work); |
| 652 | 683 | ||
| 653 | spin_unlock(&zswap_pools_lock); | 684 | spin_unlock(&zswap_pools_lock); |
| 654 | } | 685 | } |
| @@ -942,22 +973,6 @@ end: · 287 unmodified lines | |||
| 942 | return ret; | 973 | return ret; |
| 943 | } | 974 | } |
| 944 | 975 | ||
| 945 | static int zswap_shrink(void) | ||
| 946 | { | ||
| 947 | struct zswap_pool *pool; | ||
| 948 | int ret; | ||
| 949 | |||
| 950 | pool = zswap_pool_last_get(); | ||
| 951 | if (!pool) | ||
| 952 | return -ENOENT; | ||
| 953 | |||
| 954 | ret = zpool_shrink(pool->zpool, 1, NULL); | ||
| 955 | |||
| 956 | zswap_pool_put(pool); | ||
| 957 | |||
| 958 | return ret; | ||
| 959 | } | ||
| 960 | |||
| 961 | static int zswap_is_page_same_filled(void *ptr, unsigned long *value) | 976 | static int zswap_is_page_same_filled(void *ptr, unsigned long *value) |
| 962 | { | 977 | { |
| 963 | unsigned int pos; | 978 | unsigned int pos; |
| @@ -1011,21 +1026,23 @@ static int zswap_frontswap_store(unsigned type, pgoff_t offset, · 47 unmodified lines | |||
| 1011 | 1026 | ||
| 1012 | /* reclaim space if needed */ | 1027 | /* reclaim space if needed */ |
| 1013 | if (zswap_is_full()) { | 1028 | if (zswap_is_full()) { |
| 1029 | struct zswap_pool *pool; | ||
| 1030 | |||
| 1014 | zswap_pool_limit_hit++; | 1031 | zswap_pool_limit_hit++; |
| 1015 | if (zswap_shrink()) { | 1032 | zswap_pool_reached_full = true; |
| 1016 | zswap_reject_reclaim_fail++; | 1033 | pool = zswap_pool_last_get(); |
| 1017 | ret = -ENOMEM; | 1034 | if (pool) |
| 1018 | goto reject; | 1035 | queue_work(shrink_wq, &pool->shrink_work); |
| 1019 | } | 1036 | ret = -ENOMEM; |
| 1037 | goto reject; | ||
| 1038 | } | ||
| 1020 | 1039 | ||
| 1021 | /* A second zswap_is_full() check after | 1040 | if (zswap_pool_reached_full) { |
| 1022 | * zswap_shrink() to make sure it's now | 1041 | if (!zswap_can_accept()) { |
| 1023 | * under the max_pool_percent | ||
| 1024 | */ | ||
| 1025 | if (zswap_is_full()) { | ||
| 1026 | ret = -ENOMEM; | 1042 | ret = -ENOMEM; |
| 1027 | goto reject; | 1043 | goto reject; |
| 1028 | } | 1044 | } else |
| 1045 | zswap_pool_reached_full = false; | ||
| 1029 | } | 1046 | } |
| 1030 | 1047 | ||
| 1031 | /* allocate entry */ | 1048 | /* allocate entry */ |
| @@ -1332,11 +1349,18 @@ static int __init init_zswap(void) · 300 unmodified lines | |||
| 1332 | zswap_enabled = false; | 1349 | zswap_enabled = false; |
| 1333 | } | 1350 | } |
| 1334 | 1351 | ||
| 1352 | shrink_wq = create_workqueue("zswap-shrink"); | ||
| 1353 | if (!shrink_wq) | ||
| 1354 | goto fallback_fail; | ||
| 1355 | |||
| 1335 | frontswap_register_ops(&zswap_frontswap_ops); | 1356 | frontswap_register_ops(&zswap_frontswap_ops); |
| 1336 | if (zswap_debugfs_init()) | 1357 | if (zswap_debugfs_init()) |
| 1337 | pr_warn("debugfs initialization failed\n"); | 1358 | pr_warn("debugfs initialization failed\n"); |
| 1338 | return 0; | 1359 | return 0; |
| 1339 | 1360 | ||
| 1361 | fallback_fail: | ||
| 1362 | if (pool) | ||
| 1363 | zswap_pool_destroy(pool); | ||
| 1340 | hp_fail: | 1364 | hp_fail: |
| 1341 | cpuhp_remove_state(CPUHP_MM_ZSWP_MEM_PREPARE); | 1365 | cpuhp_remove_state(CPUHP_MM_ZSWP_MEM_PREPARE); |
| 1342 | dstmem_fail: | 1366 | dstmem_fail: |
| @@ -212,7 +212,7 @@ static int xdp_umem_map_pages(struct xdp_umem *umem) · 211 unmodified lines | |||
| 212 | 212 | ||
| 213 | static void xdp_umem_unpin_pages(struct xdp_umem *umem) | 213 | static void xdp_umem_unpin_pages(struct xdp_umem *umem) |
| 214 | { | 214 | { |
| 215 | put_user_pages_dirty_lock(umem->pgs, umem->npgs, true); | 215 | unpin_user_pages_dirty_lock(umem->pgs, umem->npgs, true); |
| 216 | 216 | ||
| 217 | kfree(umem->pgs); | 217 | kfree(umem->pgs); |
| 218 | umem->pgs = NULL; | 218 | umem->pgs = NULL; |
| @@ -291,7 +291,7 @@ static int xdp_umem_pin_pages(struct xdp_umem *umem) · 72 unmodified lines | |||
| 291 | return -ENOMEM; | 291 | return -ENOMEM; |
| 292 | 292 | ||
| 293 | down_read(¤t->mm->mmap_sem); | 293 | down_read(¤t->mm->mmap_sem); |
| 294 | npgs = get_user_pages(umem->address, umem->npgs, | 294 | npgs = pin_user_pages(umem->address, umem->npgs, |
| 295 | gup_flags | FOLL_LONGTERM, &umem->pgs[0], NULL); | 295 | gup_flags | FOLL_LONGTERM, &umem->pgs[0], NULL); |
| 296 | up_read(¤t->mm->mmap_sem); | 296 | up_read(¤t->mm->mmap_sem); |
| 297 | 297 | ||
| @@ -39,6 +39,8 @@ accout||account · 38 unmodified lines | |||
| 39 | accquire||acquire | 39 | accquire||acquire |
| 40 | accquired||acquired | 40 | accquired||acquired |
| 41 | accross||across | 41 | accross||across |
| 42 | accumalate||accumulate | ||
| 43 | accumalator||accumulator | ||
| 42 | acessable||accessible | 44 | acessable||accessible |
| 43 | acess||access | 45 | acess||access |
| 44 | acessing||accessing | 46 | acessing||accessing |
| @@ -106,6 +108,7 @@ alogrithm||algorithm · 61 unmodified lines | |||
| 106 | alot||a lot | 108 | alot||a lot |
| 107 | alow||allow | 109 | alow||allow |
| 108 | alows||allows | 110 | alows||allows |
| 111 | alreay||already | ||
| 109 | alredy||already | 112 | alredy||already |
| 110 | altough||although | 113 | altough||although |
| 111 | alue||value | 114 | alue||value |
| @@ -241,6 +244,7 @@ calender||calendar · 129 unmodified lines | |||
| 241 | calescing||coalescing | 244 | calescing||coalescing |
| 242 | calle||called | 245 | calle||called |
| 243 | callibration||calibration | 246 | callibration||calibration |
| 247 | callled||called | ||
| 244 | calucate||calculate | 248 | calucate||calculate |
| 245 | calulate||calculate | 249 | calulate||calculate |
| 246 | cancelation||cancellation | 250 | cancelation||cancellation |
| @@ -311,6 +315,7 @@ compaibility||compatibility · 64 unmodified lines | |||
| 311 | comparsion||comparison | 315 | comparsion||comparison |
| 312 | compatability||compatibility | 316 | compatability||compatibility |
| 313 | compatable||compatible | 317 | compatable||compatible |
| 318 | compatibililty||compatibility | ||
| 314 | compatibiliy||compatibility | 319 | compatibiliy||compatibility |
| 315 | compatibilty||compatibility | 320 | compatibilty||compatibility |
| 316 | compatiblity||compatibility | 321 | compatiblity||compatibility |
| @@ -330,6 +335,7 @@ comunication||communication · 13 unmodified lines | |||
| 330 | conbination||combination | 335 | conbination||combination |
| 331 | conditionaly||conditionally | 336 | conditionaly||conditionally |
| 332 | conditon||condition | 337 | conditon||condition |
| 338 | condtion||condition | ||
| 333 | conected||connected | 339 | conected||connected |
| 334 | conector||connector | 340 | conector||connector |
| 335 | connecetd||connected | 341 | connecetd||connected |
| @@ -388,6 +394,8 @@ dafault||default · 52 unmodified lines | |||
| 388 | deafult||default | 394 | deafult||default |
| 389 | deamon||daemon | 395 | deamon||daemon |
| 390 | debouce||debounce | 396 | debouce||debounce |
| 397 | decendant||descendant | ||
| 398 | decendants||descendants | ||
| 391 | decompres||decompress | 399 | decompres||decompress |
| 392 | decsribed||described | 400 | decsribed||described |
| 393 | decription||description | 401 | decription||description |
| @@ -411,11 +419,13 @@ delare||declare · 17 unmodified lines | |||
| 411 | delares||declares | 419 | delares||declares |
| 412 | delaring||declaring | 420 | delaring||declaring |
| 413 | delemiter||delimiter | 421 | delemiter||delimiter |
| 422 | delievered||delivered | ||
| 414 | demodualtor||demodulator | 423 | demodualtor||demodulator |
| 415 | demension||dimension | 424 | demension||dimension |
| 416 | dependancies||dependencies | 425 | dependancies||dependencies |
| 417 | dependancy||dependency | 426 | dependancy||dependency |
| 418 | dependant||dependent | 427 | dependant||dependent |
| 428 | dependend||dependent | ||
| 419 | depreacted||deprecated | 429 | depreacted||deprecated |
| 420 | depreacte||deprecate | 430 | depreacte||deprecate |
| 421 | desactivate||deactivate | 431 | desactivate||deactivate |
| @@ -791,6 +801,7 @@ ireelevant||irrelevant · 369 unmodified lines | |||
| 791 | irrelevent||irrelevant | 801 | irrelevent||irrelevant |
| 792 | isnt||isn't | 802 | isnt||isn't |
| 793 | isssue||issue | 803 | isssue||issue |
| 804 | issus||issues | ||
| 794 | iternations||iterations | 805 | iternations||iterations |
| 795 | itertation||iteration | 806 | itertation||iteration |
| 796 | itslef||itself | 807 | itslef||itself |
| @@ -995,6 +1006,7 @@ peice||piece · 198 unmodified lines | |||
| 995 | pendantic||pedantic | 1006 | pendantic||pedantic |
| 996 | peprocessor||preprocessor | 1007 | peprocessor||preprocessor |
| 997 | perfoming||performing | 1008 | perfoming||performing |
| 1009 | perfomring||performing | ||
| 998 | peripherial||peripheral | 1010 | peripherial||peripheral |
| 999 | permissons||permissions | 1011 | permissons||permissions |
| 1000 | peroid||period | 1012 | peroid||period |
| @@ -1166,6 +1178,8 @@ retreive||retrieve · 165 unmodified lines | |||
| 1166 | retreiving||retrieving | 1178 | retreiving||retrieving |
| 1167 | retrive||retrieve | 1179 | retrive||retrieve |
| 1168 | retrived||retrieved | 1180 | retrived||retrieved |
| 1181 | retrun||return | ||
| 1182 | retun||return | ||
| 1169 | retuned||returned | 1183 | retuned||returned |
| 1170 | reudce||reduce | 1184 | reudce||reduce |
| 1171 | reuest||request | 1185 | reuest||request |
| @@ -18,6 +18,9 @@ · 17 unmodified lines | |||
| 18 | #define GUP_LONGTERM_BENCHMARK _IOWR('g', 2, struct gup_benchmark) | 18 | #define GUP_LONGTERM_BENCHMARK _IOWR('g', 2, struct gup_benchmark) |
| 19 | #define GUP_BENCHMARK _IOWR('g', 3, struct gup_benchmark) | 19 | #define GUP_BENCHMARK _IOWR('g', 3, struct gup_benchmark) |
| 20 | 20 | ||
| 21 | /* Just the flags we need, copied from mm.h: */ | ||
| 22 | #define FOLL_WRITE 0x01 /* check pte is writable */ | ||
| 23 | |||
| 21 | struct gup_benchmark { | 24 | struct gup_benchmark { |
| 22 | __u64 get_delta_usec; | 25 | __u64 get_delta_usec; |
| 23 | __u64 put_delta_usec; | 26 | __u64 put_delta_usec; |
| @@ -85,7 +88,8 @@ int main(int argc, char **argv) · 61 unmodified lines | |||
| 85 | } | 88 | } |
| 86 | 89 | ||
| 87 | gup.nr_pages_per_call = nr_pages; | 90 | gup.nr_pages_per_call = nr_pages; |
| 88 | gup.flags = write; | 91 | if (write) |
| 92 | gup.flags |= FOLL_WRITE; | ||
| 89 | 93 | ||
| 90 | fd = open("/sys/kernel/debug/gup_benchmark", O_RDWR); | 94 | fd = open("/sys/kernel/debug/gup_benchmark", O_RDWR); |
| 91 | if (fd == -1) | 95 | if (fd == -1) |
| @@ -720,11 +720,11 @@ static void slab_debug(struct slabinfo *s) · 719 unmodified lines | |||
| 720 | return; | 720 | return; |
| 721 | 721 | ||
| 722 | if (sanity && !s->sanity_checks) { | 722 | if (sanity && !s->sanity_checks) { |
| 723 | set_obj(s, "sanity", 1); | 723 | set_obj(s, "sanity_checks", 1); |
| 724 | } | 724 | } |
| 725 | if (!sanity && s->sanity_checks) { | 725 | if (!sanity && s->sanity_checks) { |
| 726 | if (slab_empty(s)) | 726 | if (slab_empty(s)) |
| 727 | set_obj(s, "sanity", 0); | 727 | set_obj(s, "sanity_checks", 0); |
| 728 | else | 728 | else |
| 729 | fprintf(stderr, "%s not empty cannot disable sanity checks\n", s->name); | 729 | fprintf(stderr, "%s not empty cannot disable sanity checks\n", s->name); |
| 730 | } | 730 | } |