diff options
348 files changed, 10189 insertions, 3536 deletions
| @@ -1381,6 +1381,9 @@ S: 17 rue Danton | |||
| 1381 | S: F - 94270 Le Kremlin-Bicêtre | 1381 | S: F - 94270 Le Kremlin-Bicêtre |
| 1382 | S: France | 1382 | S: France |
| 1383 | 1383 | ||
| 1384 | N: Jack Hammer | ||
| 1385 | D: IBM ServeRAID RAID (ips) driver maintenance | ||
| 1386 | |||
| 1384 | N: Greg Hankins | 1387 | N: Greg Hankins |
| 1385 | E: gregh@cc.gatech.edu | 1388 | E: gregh@cc.gatech.edu |
| 1386 | D: fixed keyboard driver to separate LED and locking status | 1389 | D: fixed keyboard driver to separate LED and locking status |
| @@ -1691,6 +1694,10 @@ S: Reading | |||
| 1691 | S: RG6 2NU | 1694 | S: RG6 2NU |
| 1692 | S: United Kingdom | 1695 | S: United Kingdom |
| 1693 | 1696 | ||
| 1697 | N: Dave Jeffery | ||
| 1698 | E: dhjeffery@gmail.com | ||
| 1699 | D: SCSI hacks and IBM ServeRAID RAID driver maintenance | ||
| 1700 | |||
| 1694 | N: Jakub Jelinek | 1701 | N: Jakub Jelinek |
| 1695 | E: jakub@redhat.com | 1702 | E: jakub@redhat.com |
| 1696 | W: http://sunsite.mff.cuni.cz/~jj | 1703 | W: http://sunsite.mff.cuni.cz/~jj |
diff --git a/Documentation/ABI/testing/sysfs-fs-nilfs2 b/Documentation/ABI/testing/sysfs-fs-nilfs2 new file mode 100644 index 000000000000..304ba84a973a --- /dev/null +++ b/Documentation/ABI/testing/sysfs-fs-nilfs2 | |||
| @@ -0,0 +1,269 @@ | |||
| 1 | |||
| 2 | What: /sys/fs/nilfs2/features/revision | ||
| 3 | Date: April 2014 | ||
| 4 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 5 | Description: | ||
| 6 | Show current revision of NILFS file system driver. | ||
| 7 | This value informs about file system revision that | ||
| 8 | driver is ready to support. | ||
| 9 | |||
| 10 | What: /sys/fs/nilfs2/features/README | ||
| 11 | Date: April 2014 | ||
| 12 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 13 | Description: | ||
| 14 | Describe attributes of /sys/fs/nilfs2/features group. | ||
| 15 | |||
| 16 | What: /sys/fs/nilfs2/<device>/revision | ||
| 17 | Date: April 2014 | ||
| 18 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 19 | Description: | ||
| 20 | Show NILFS file system revision on volume. | ||
| 21 | This value informs about metadata structures' | ||
| 22 | revision on mounted volume. | ||
| 23 | |||
| 24 | What: /sys/fs/nilfs2/<device>/blocksize | ||
| 25 | Date: April 2014 | ||
| 26 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 27 | Description: | ||
| 28 | Show volume's block size in bytes. | ||
| 29 | |||
| 30 | What: /sys/fs/nilfs2/<device>/device_size | ||
| 31 | Date: April 2014 | ||
| 32 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 33 | Description: | ||
| 34 | Show volume size in bytes. | ||
| 35 | |||
| 36 | What: /sys/fs/nilfs2/<device>/free_blocks | ||
| 37 | Date: April 2014 | ||
| 38 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 39 | Description: | ||
| 40 | Show count of free blocks on volume. | ||
| 41 | |||
| 42 | What: /sys/fs/nilfs2/<device>/uuid | ||
| 43 | Date: April 2014 | ||
| 44 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 45 | Description: | ||
| 46 | Show volume's UUID (Universally Unique Identifier). | ||
| 47 | |||
| 48 | What: /sys/fs/nilfs2/<device>/volume_name | ||
| 49 | Date: April 2014 | ||
| 50 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 51 | Description: | ||
| 52 | Show volume's label. | ||
| 53 | |||
| 54 | What: /sys/fs/nilfs2/<device>/README | ||
| 55 | Date: April 2014 | ||
| 56 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 57 | Description: | ||
| 58 | Describe attributes of /sys/fs/nilfs2/<device> group. | ||
| 59 | |||
| 60 | What: /sys/fs/nilfs2/<device>/superblock/sb_write_time | ||
| 61 | Date: April 2014 | ||
| 62 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 63 | Description: | ||
| 64 | Show last write time of super block in human-readable | ||
| 65 | format. | ||
| 66 | |||
| 67 | What: /sys/fs/nilfs2/<device>/superblock/sb_write_time_secs | ||
| 68 | Date: April 2014 | ||
| 69 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 70 | Description: | ||
| 71 | Show last write time of super block in seconds. | ||
| 72 | |||
| 73 | What: /sys/fs/nilfs2/<device>/superblock/sb_write_count | ||
| 74 | Date: April 2014 | ||
| 75 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 76 | Description: | ||
| 77 | Show current write count of super block. | ||
| 78 | |||
| 79 | What: /sys/fs/nilfs2/<device>/superblock/sb_update_frequency | ||
| 80 | Date: April 2014 | ||
| 81 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 82 | Description: | ||
| 83 | Show/Set interval of periodical update of superblock | ||
| 84 | (in seconds). | ||
| 85 | |||
| 86 | What: /sys/fs/nilfs2/<device>/superblock/README | ||
| 87 | Date: April 2014 | ||
| 88 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 89 | Description: | ||
| 90 | Describe attributes of /sys/fs/nilfs2/<device>/superblock | ||
| 91 | group. | ||
| 92 | |||
| 93 | What: /sys/fs/nilfs2/<device>/segctor/last_pseg_block | ||
| 94 | Date: April 2014 | ||
| 95 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 96 | Description: | ||
| 97 | Show start block number of the latest segment. | ||
| 98 | |||
| 99 | What: /sys/fs/nilfs2/<device>/segctor/last_seg_sequence | ||
| 100 | Date: April 2014 | ||
| 101 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 102 | Description: | ||
| 103 | Show sequence value of the latest segment. | ||
| 104 | |||
| 105 | What: /sys/fs/nilfs2/<device>/segctor/last_seg_checkpoint | ||
| 106 | Date: April 2014 | ||
| 107 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 108 | Description: | ||
| 109 | Show checkpoint number of the latest segment. | ||
| 110 | |||
| 111 | What: /sys/fs/nilfs2/<device>/segctor/current_seg_sequence | ||
| 112 | Date: April 2014 | ||
| 113 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 114 | Description: | ||
| 115 | Show segment sequence counter. | ||
| 116 | |||
| 117 | What: /sys/fs/nilfs2/<device>/segctor/current_last_full_seg | ||
| 118 | Date: April 2014 | ||
| 119 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 120 | Description: | ||
| 121 | Show index number of the latest full segment. | ||
| 122 | |||
| 123 | What: /sys/fs/nilfs2/<device>/segctor/next_full_seg | ||
| 124 | Date: April 2014 | ||
| 125 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 126 | Description: | ||
| 127 | Show index number of the full segment index | ||
| 128 | to be used next. | ||
| 129 | |||
| 130 | What: /sys/fs/nilfs2/<device>/segctor/next_pseg_offset | ||
| 131 | Date: April 2014 | ||
| 132 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 133 | Description: | ||
| 134 | Show offset of next partial segment in the current | ||
| 135 | full segment. | ||
| 136 | |||
| 137 | What: /sys/fs/nilfs2/<device>/segctor/next_checkpoint | ||
| 138 | Date: April 2014 | ||
| 139 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 140 | Description: | ||
| 141 | Show next checkpoint number. | ||
| 142 | |||
| 143 | What: /sys/fs/nilfs2/<device>/segctor/last_seg_write_time | ||
| 144 | Date: April 2014 | ||
| 145 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 146 | Description: | ||
| 147 | Show write time of the last segment in | ||
| 148 | human-readable format. | ||
| 149 | |||
| 150 | What: /sys/fs/nilfs2/<device>/segctor/last_seg_write_time_secs | ||
| 151 | Date: April 2014 | ||
| 152 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 153 | Description: | ||
| 154 | Show write time of the last segment in seconds. | ||
| 155 | |||
| 156 | What: /sys/fs/nilfs2/<device>/segctor/last_nongc_write_time | ||
| 157 | Date: April 2014 | ||
| 158 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 159 | Description: | ||
| 160 | Show write time of the last segment not for cleaner | ||
| 161 | operation in human-readable format. | ||
| 162 | |||
| 163 | What: /sys/fs/nilfs2/<device>/segctor/last_nongc_write_time_secs | ||
| 164 | Date: April 2014 | ||
| 165 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 166 | Description: | ||
| 167 | Show write time of the last segment not for cleaner | ||
| 168 | operation in seconds. | ||
| 169 | |||
| 170 | What: /sys/fs/nilfs2/<device>/segctor/dirty_data_blocks_count | ||
| 171 | Date: April 2014 | ||
| 172 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 173 | Description: | ||
| 174 | Show number of dirty data blocks. | ||
| 175 | |||
| 176 | What: /sys/fs/nilfs2/<device>/segctor/README | ||
| 177 | Date: April 2014 | ||
| 178 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 179 | Description: | ||
| 180 | Describe attributes of /sys/fs/nilfs2/<device>/segctor | ||
| 181 | group. | ||
| 182 | |||
| 183 | What: /sys/fs/nilfs2/<device>/segments/segments_number | ||
| 184 | Date: April 2014 | ||
| 185 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 186 | Description: | ||
| 187 | Show number of segments on a volume. | ||
| 188 | |||
| 189 | What: /sys/fs/nilfs2/<device>/segments/blocks_per_segment | ||
| 190 | Date: April 2014 | ||
| 191 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 192 | Description: | ||
| 193 | Show number of blocks in segment. | ||
| 194 | |||
| 195 | What: /sys/fs/nilfs2/<device>/segments/clean_segments | ||
| 196 | Date: April 2014 | ||
| 197 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 198 | Description: | ||
| 199 | Show count of clean segments. | ||
| 200 | |||
| 201 | What: /sys/fs/nilfs2/<device>/segments/dirty_segments | ||
| 202 | Date: April 2014 | ||
| 203 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 204 | Description: | ||
| 205 | Show count of dirty segments. | ||
| 206 | |||
| 207 | What: /sys/fs/nilfs2/<device>/segments/README | ||
| 208 | Date: April 2014 | ||
| 209 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 210 | Description: | ||
| 211 | Describe attributes of /sys/fs/nilfs2/<device>/segments | ||
| 212 | group. | ||
| 213 | |||
| 214 | What: /sys/fs/nilfs2/<device>/checkpoints/checkpoints_number | ||
| 215 | Date: April 2014 | ||
| 216 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 217 | Description: | ||
| 218 | Show number of checkpoints on volume. | ||
| 219 | |||
| 220 | What: /sys/fs/nilfs2/<device>/checkpoints/snapshots_number | ||
| 221 | Date: April 2014 | ||
| 222 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 223 | Description: | ||
| 224 | Show number of snapshots on volume. | ||
| 225 | |||
| 226 | What: /sys/fs/nilfs2/<device>/checkpoints/last_seg_checkpoint | ||
| 227 | Date: April 2014 | ||
| 228 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 229 | Description: | ||
| 230 | Show checkpoint number of the latest segment. | ||
| 231 | |||
| 232 | What: /sys/fs/nilfs2/<device>/checkpoints/next_checkpoint | ||
| 233 | Date: April 2014 | ||
| 234 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 235 | Description: | ||
| 236 | Show next checkpoint number. | ||
| 237 | |||
| 238 | What: /sys/fs/nilfs2/<device>/checkpoints/README | ||
| 239 | Date: April 2014 | ||
| 240 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 241 | Description: | ||
| 242 | Describe attributes of /sys/fs/nilfs2/<device>/checkpoints | ||
| 243 | group. | ||
| 244 | |||
| 245 | What: /sys/fs/nilfs2/<device>/mounted_snapshots/README | ||
| 246 | Date: April 2014 | ||
| 247 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 248 | Description: | ||
| 249 | Describe content of /sys/fs/nilfs2/<device>/mounted_snapshots | ||
| 250 | group. | ||
| 251 | |||
| 252 | What: /sys/fs/nilfs2/<device>/mounted_snapshots/<id>/inodes_count | ||
| 253 | Date: April 2014 | ||
| 254 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 255 | Description: | ||
| 256 | Show number of inodes for snapshot. | ||
| 257 | |||
| 258 | What: /sys/fs/nilfs2/<device>/mounted_snapshots/<id>/blocks_count | ||
| 259 | Date: April 2014 | ||
| 260 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 261 | Description: | ||
| 262 | Show number of blocks for snapshot. | ||
| 263 | |||
| 264 | What: /sys/fs/nilfs2/<device>/mounted_snapshots/<id>/README | ||
| 265 | Date: April 2014 | ||
| 266 | Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> | ||
| 267 | Description: | ||
| 268 | Describe attributes of /sys/fs/nilfs2/<device>/mounted_snapshots/<id> | ||
| 269 | group. | ||
diff --git a/Documentation/cgroups/memcg_test.txt b/Documentation/cgroups/memcg_test.txt index 80ac454704b8..8870b0212150 100644 --- a/Documentation/cgroups/memcg_test.txt +++ b/Documentation/cgroups/memcg_test.txt | |||
| @@ -24,64 +24,27 @@ Please note that implementation details can be changed. | |||
| 24 | 24 | ||
| 25 | a page/swp_entry may be charged (usage += PAGE_SIZE) at | 25 | a page/swp_entry may be charged (usage += PAGE_SIZE) at |
| 26 | 26 | ||
| 27 | mem_cgroup_charge_anon() | 27 | mem_cgroup_try_charge() |
| 28 | Called at new page fault and Copy-On-Write. | ||
| 29 | |||
| 30 | mem_cgroup_try_charge_swapin() | ||
| 31 | Called at do_swap_page() (page fault on swap entry) and swapoff. | ||
| 32 | Followed by charge-commit-cancel protocol. (With swap accounting) | ||
| 33 | At commit, a charge recorded in swap_cgroup is removed. | ||
| 34 | |||
| 35 | mem_cgroup_charge_file() | ||
| 36 | Called at add_to_page_cache() | ||
| 37 | |||
| 38 | mem_cgroup_cache_charge_swapin() | ||
| 39 | Called at shmem's swapin. | ||
| 40 | |||
| 41 | mem_cgroup_prepare_migration() | ||
| 42 | Called before migration. "extra" charge is done and followed by | ||
| 43 | charge-commit-cancel protocol. | ||
| 44 | At commit, charge against oldpage or newpage will be committed. | ||
| 45 | 28 | ||
| 46 | 2. Uncharge | 29 | 2. Uncharge |
| 47 | a page/swp_entry may be uncharged (usage -= PAGE_SIZE) by | 30 | a page/swp_entry may be uncharged (usage -= PAGE_SIZE) by |
| 48 | 31 | ||
| 49 | mem_cgroup_uncharge_page() | 32 | mem_cgroup_uncharge() |
| 50 | Called when an anonymous page is fully unmapped. I.e., mapcount goes | 33 | Called when a page's refcount goes down to 0. |
| 51 | to 0. If the page is SwapCache, uncharge is delayed until | ||
| 52 | mem_cgroup_uncharge_swapcache(). | ||
| 53 | |||
| 54 | mem_cgroup_uncharge_cache_page() | ||
| 55 | Called when a page-cache is deleted from radix-tree. If the page is | ||
| 56 | SwapCache, uncharge is delayed until mem_cgroup_uncharge_swapcache(). | ||
| 57 | |||
| 58 | mem_cgroup_uncharge_swapcache() | ||
| 59 | Called when SwapCache is removed from radix-tree. The charge itself | ||
| 60 | is moved to swap_cgroup. (If mem+swap controller is disabled, no | ||
| 61 | charge to swap occurs.) | ||
| 62 | 34 | ||
| 63 | mem_cgroup_uncharge_swap() | 35 | mem_cgroup_uncharge_swap() |
| 64 | Called when swp_entry's refcnt goes down to 0. A charge against swap | 36 | Called when swp_entry's refcnt goes down to 0. A charge against swap |
| 65 | disappears. | 37 | disappears. |
| 66 | 38 | ||
| 67 | mem_cgroup_end_migration(old, new) | ||
| 68 | At success of migration old is uncharged (if necessary), a charge | ||
| 69 | to new page is committed. At failure, charge to old page is committed. | ||
| 70 | |||
| 71 | 3. charge-commit-cancel | 39 | 3. charge-commit-cancel |
| 72 | In some case, we can't know this "charge" is valid or not at charging | 40 | Memcg pages are charged in two steps: |
| 73 | (because of races). | 41 | mem_cgroup_try_charge() |
| 74 | To handle such case, there are charge-commit-cancel functions. | 42 | mem_cgroup_commit_charge() or mem_cgroup_cancel_charge() |
| 75 | mem_cgroup_try_charge_XXX | ||
| 76 | mem_cgroup_commit_charge_XXX | ||
| 77 | mem_cgroup_cancel_charge_XXX | ||
| 78 | these are used in swap-in and migration. | ||
| 79 | 43 | ||
| 80 | At try_charge(), there are no flags to say "this page is charged". | 44 | At try_charge(), there are no flags to say "this page is charged". |
| 81 | at this point, usage += PAGE_SIZE. | 45 | at this point, usage += PAGE_SIZE. |
| 82 | 46 | ||
| 83 | At commit(), the function checks the page should be charged or not | 47 | At commit(), the page is associated with the memcg. |
| 84 | and set flags or avoid charging.(usage -= PAGE_SIZE) | ||
| 85 | 48 | ||
| 86 | At cancel(), simply usage -= PAGE_SIZE. | 49 | At cancel(), simply usage -= PAGE_SIZE. |
| 87 | 50 | ||
| @@ -91,18 +54,6 @@ Under below explanation, we assume CONFIG_MEM_RES_CTRL_SWAP=y. | |||
| 91 | Anonymous page is newly allocated at | 54 | Anonymous page is newly allocated at |
| 92 | - page fault into MAP_ANONYMOUS mapping. | 55 | - page fault into MAP_ANONYMOUS mapping. |
| 93 | - Copy-On-Write. | 56 | - Copy-On-Write. |
| 94 | It is charged right after it's allocated before doing any page table | ||
| 95 | related operations. Of course, it's uncharged when another page is used | ||
| 96 | for the fault address. | ||
| 97 | |||
| 98 | At freeing anonymous page (by exit() or munmap()), zap_pte() is called | ||
| 99 | and pages for ptes are freed one by one.(see mm/memory.c). Uncharges | ||
| 100 | are done at page_remove_rmap() when page_mapcount() goes down to 0. | ||
| 101 | |||
| 102 | Another page freeing is by page-reclaim (vmscan.c) and anonymous | ||
| 103 | pages are swapped out. In this case, the page is marked as | ||
| 104 | PageSwapCache(). uncharge() routine doesn't uncharge the page marked | ||
| 105 | as SwapCache(). It's delayed until __delete_from_swap_cache(). | ||
| 106 | 57 | ||
| 107 | 4.1 Swap-in. | 58 | 4.1 Swap-in. |
| 108 | At swap-in, the page is taken from swap-cache. There are 2 cases. | 59 | At swap-in, the page is taken from swap-cache. There are 2 cases. |
| @@ -111,41 +62,6 @@ Under below explanation, we assume CONFIG_MEM_RES_CTRL_SWAP=y. | |||
| 111 | (b) If the SwapCache has been mapped by processes, it has been | 62 | (b) If the SwapCache has been mapped by processes, it has been |
| 112 | charged already. | 63 | charged already. |
| 113 | 64 | ||
| 114 | This swap-in is one of the most complicated work. In do_swap_page(), | ||
| 115 | following events occur when pte is unchanged. | ||
| 116 | |||
| 117 | (1) the page (SwapCache) is looked up. | ||
| 118 | (2) lock_page() | ||
| 119 | (3) try_charge_swapin() | ||
| 120 | (4) reuse_swap_page() (may call delete_swap_cache()) | ||
| 121 | (5) commit_charge_swapin() | ||
| 122 | (6) swap_free(). | ||
| 123 | |||
| 124 | Considering following situation for example. | ||
| 125 | |||
| 126 | (A) The page has not been charged before (2) and reuse_swap_page() | ||
| 127 | doesn't call delete_from_swap_cache(). | ||
| 128 | (B) The page has not been charged before (2) and reuse_swap_page() | ||
| 129 | calls delete_from_swap_cache(). | ||
| 130 | (C) The page has been charged before (2) and reuse_swap_page() doesn't | ||
| 131 | call delete_from_swap_cache(). | ||
| 132 | (D) The page has been charged before (2) and reuse_swap_page() calls | ||
| 133 | delete_from_swap_cache(). | ||
| 134 | |||
| 135 | memory.usage/memsw.usage changes to this page/swp_entry will be | ||
| 136 | Case (A) (B) (C) (D) | ||
| 137 | Event | ||
| 138 | Before (2) 0/ 1 0/ 1 1/ 1 1/ 1 | ||
| 139 | =========================================== | ||
| 140 | (3) +1/+1 +1/+1 +1/+1 +1/+1 | ||
| 141 | (4) - 0/ 0 - -1/ 0 | ||
| 142 | (5) 0/-1 0/ 0 -1/-1 0/ 0 | ||
| 143 | (6) - 0/-1 - 0/-1 | ||
| 144 | =========================================== | ||
| 145 | Result 1/ 1 1/ 1 1/ 1 1/ 1 | ||
| 146 | |||
| 147 | In any cases, charges to this page should be 1/ 1. | ||
| 148 | |||
| 149 | 4.2 Swap-out. | 65 | 4.2 Swap-out. |
| 150 | At swap-out, typical state transition is below. | 66 | At swap-out, typical state transition is below. |
| 151 | 67 | ||
| @@ -158,28 +74,20 @@ Under below explanation, we assume CONFIG_MEM_RES_CTRL_SWAP=y. | |||
| 158 | swp_entry's refcnt -= 1. | 74 | swp_entry's refcnt -= 1. |
| 159 | 75 | ||
| 160 | 76 | ||
| 161 | At (b), the page is marked as SwapCache and not uncharged. | ||
| 162 | At (d), the page is removed from SwapCache and a charge in page_cgroup | ||
| 163 | is moved to swap_cgroup. | ||
| 164 | |||
| 165 | Finally, at task exit, | 77 | Finally, at task exit, |
| 166 | (e) zap_pte() is called and swp_entry's refcnt -=1 -> 0. | 78 | (e) zap_pte() is called and swp_entry's refcnt -=1 -> 0. |
| 167 | Here, a charge in swap_cgroup disappears. | ||
| 168 | 79 | ||
| 169 | 5. Page Cache | 80 | 5. Page Cache |
| 170 | Page Cache is charged at | 81 | Page Cache is charged at |
| 171 | - add_to_page_cache_locked(). | 82 | - add_to_page_cache_locked(). |
| 172 | 83 | ||
| 173 | uncharged at | ||
| 174 | - __remove_from_page_cache(). | ||
| 175 | |||
| 176 | The logic is very clear. (About migration, see below) | 84 | The logic is very clear. (About migration, see below) |
| 177 | Note: __remove_from_page_cache() is called by remove_from_page_cache() | 85 | Note: __remove_from_page_cache() is called by remove_from_page_cache() |
| 178 | and __remove_mapping(). | 86 | and __remove_mapping(). |
| 179 | 87 | ||
| 180 | 6. Shmem(tmpfs) Page Cache | 88 | 6. Shmem(tmpfs) Page Cache |
| 181 | Memcg's charge/uncharge have special handlers of shmem. The best way | 89 | The best way to understand shmem's page state transition is to read |
| 182 | to understand shmem's page state transition is to read mm/shmem.c. | 90 | mm/shmem.c. |
| 183 | But brief explanation of the behavior of memcg around shmem will be | 91 | But brief explanation of the behavior of memcg around shmem will be |
| 184 | helpful to understand the logic. | 92 | helpful to understand the logic. |
| 185 | 93 | ||
| @@ -192,56 +100,10 @@ Under below explanation, we assume CONFIG_MEM_RES_CTRL_SWAP=y. | |||
| 192 | It's charged when... | 100 | It's charged when... |
| 193 | - A new page is added to shmem's radix-tree. | 101 | - A new page is added to shmem's radix-tree. |
| 194 | - A swp page is read. (move a charge from swap_cgroup to page_cgroup) | 102 | - A swp page is read. (move a charge from swap_cgroup to page_cgroup) |
| 195 | It's uncharged when | ||
| 196 | - A page is removed from radix-tree and not SwapCache. | ||
| 197 | - When SwapCache is removed, a charge is moved to swap_cgroup. | ||
| 198 | - When swp_entry's refcnt goes down to 0, a charge in swap_cgroup | ||
| 199 | disappears. | ||
| 200 | 103 | ||
| 201 | 7. Page Migration | 104 | 7. Page Migration |
| 202 | One of the most complicated functions is page-migration-handler. | 105 | |
| 203 | Memcg has 2 routines. Assume that we are migrating a page's contents | 106 | mem_cgroup_migrate() |
| 204 | from OLDPAGE to NEWPAGE. | ||
| 205 | |||
| 206 | Usual migration logic is.. | ||
| 207 | (a) remove the page from LRU. | ||
| 208 | (b) allocate NEWPAGE (migration target) | ||
| 209 | (c) lock by lock_page(). | ||
| 210 | (d) unmap all mappings. | ||
| 211 | (e-1) If necessary, replace entry in radix-tree. | ||
| 212 | (e-2) move contents of a page. | ||
| 213 | (f) map all mappings again. | ||
| 214 | (g) pushback the page to LRU. | ||
| 215 | (-) OLDPAGE will be freed. | ||
| 216 | |||
| 217 | Before (g), memcg should complete all necessary charge/uncharge to | ||
| 218 | NEWPAGE/OLDPAGE. | ||
| 219 | |||
| 220 | The point is.... | ||
| 221 | - If OLDPAGE is anonymous, all charges will be dropped at (d) because | ||
| 222 | try_to_unmap() drops all mapcount and the page will not be | ||
| 223 | SwapCache. | ||
| 224 | |||
| 225 | - If OLDPAGE is SwapCache, charges will be kept at (g) because | ||
| 226 | __delete_from_swap_cache() isn't called at (e-1) | ||
| 227 | |||
| 228 | - If OLDPAGE is page-cache, charges will be kept at (g) because | ||
| 229 | remove_from_swap_cache() isn't called at (e-1) | ||
| 230 | |||
| 231 | memcg provides following hooks. | ||
| 232 | |||
| 233 | - mem_cgroup_prepare_migration(OLDPAGE) | ||
| 234 | Called after (b) to account a charge (usage += PAGE_SIZE) against | ||
| 235 | memcg which OLDPAGE belongs to. | ||
| 236 | |||
| 237 | - mem_cgroup_end_migration(OLDPAGE, NEWPAGE) | ||
| 238 | Called after (f) before (g). | ||
| 239 | If OLDPAGE is used, commit OLDPAGE again. If OLDPAGE is already | ||
| 240 | charged, a charge by prepare_migration() is automatically canceled. | ||
| 241 | If NEWPAGE is used, commit NEWPAGE and uncharge OLDPAGE. | ||
| 242 | |||
| 243 | But zap_pte() (by exit or munmap) can be called while migration, | ||
| 244 | we have to check if OLDPAGE/NEWPAGE is a valid page after commit(). | ||
| 245 | 107 | ||
| 246 | 8. LRU | 108 | 8. LRU |
| 247 | Each memcg has its own private LRU. Now, its handling is under global | 109 | Each memcg has its own private LRU. Now, its handling is under global |
diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt index 37803eb5521e..6af570ec53b4 100644 --- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt +++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt | |||
| @@ -70,6 +70,7 @@ nuvoton,npct501 i2c trusted platform module (TPM) | |||
| 70 | nxp,pca9556 Octal SMBus and I2C registered interface | 70 | nxp,pca9556 Octal SMBus and I2C registered interface |
| 71 | nxp,pca9557 8-bit I2C-bus and SMBus I/O port with reset | 71 | nxp,pca9557 8-bit I2C-bus and SMBus I/O port with reset |
| 72 | nxp,pcf8563 Real-time clock/calendar | 72 | nxp,pcf8563 Real-time clock/calendar |
| 73 | nxp,pcf85063 Tiny Real-Time Clock | ||
| 73 | ovti,ov5642 OV5642: Color CMOS QSXGA (5-megapixel) Image Sensor with OmniBSI and Embedded TrueFocus | 74 | ovti,ov5642 OV5642: Color CMOS QSXGA (5-megapixel) Image Sensor with OmniBSI and Embedded TrueFocus |
| 74 | pericom,pt7c4338 Real-time Clock Module | 75 | pericom,pt7c4338 Real-time Clock Module |
| 75 | plx,pex8648 48-Lane, 12-Port PCI Express Gen 2 (5.0 GT/s) Switch | 76 | plx,pex8648 48-Lane, 12-Port PCI Express Gen 2 (5.0 GT/s) Switch |
diff --git a/Documentation/oops-tracing.txt b/Documentation/oops-tracing.txt index e3155995ddd8..beefb9f82902 100644 --- a/Documentation/oops-tracing.txt +++ b/Documentation/oops-tracing.txt | |||
| @@ -268,6 +268,8 @@ characters, each representing a particular tainted value. | |||
| 268 | 14: 'E' if an unsigned module has been loaded in a kernel supporting | 268 | 14: 'E' if an unsigned module has been loaded in a kernel supporting |
| 269 | module signature. | 269 | module signature. |
| 270 | 270 | ||
| 271 | 15: 'L' if a soft lockup has previously occurred on the system. | ||
| 272 | |||
| 271 | The primary reason for the 'Tainted: ' string is to tell kernel | 273 | The primary reason for the 'Tainted: ' string is to tell kernel |
| 272 | debuggers if this is a clean kernel or if anything unusual has | 274 | debuggers if this is a clean kernel or if anything unusual has |
| 273 | occurred. Tainting is permanent: even if an offending module is | 275 | occurred. Tainting is permanent: even if an offending module is |
diff --git a/Documentation/rapidio/tsi721.txt b/Documentation/rapidio/tsi721.txt index 335f3c6087dc..626052f403bb 100644 --- a/Documentation/rapidio/tsi721.txt +++ b/Documentation/rapidio/tsi721.txt | |||
| @@ -20,13 +20,26 @@ II. Known problems | |||
| 20 | 20 | ||
| 21 | None. | 21 | None. |
| 22 | 22 | ||
| 23 | III. To do | 23 | III. DMA Engine Support |
| 24 | 24 | ||
| 25 | Add DMA data transfers (non-messaging). | 25 | Tsi721 mport driver supports DMA data transfers between local system memory and |
| 26 | Add inbound region (SRIO-to-PCIe) mapping. | 26 | remote RapidIO devices. This functionality is implemented according to SLAVE |
| 27 | mode API defined by common Linux kernel DMA Engine framework. | ||
| 28 | |||
| 29 | Depending on system requirements RapidIO DMA operations can be included/excluded | ||
| 30 | by setting CONFIG_RAPIDIO_DMA_ENGINE option. Tsi721 miniport driver uses seven | ||
| 31 | out of eight available BDMA channels to support DMA data transfers. | ||
| 32 | One BDMA channel is reserved for generation of maintenance read/write requests. | ||
| 33 | |||
| 34 | If Tsi721 mport driver have been built with RAPIDIO_DMA_ENGINE support included, | ||
| 35 | this driver will accept DMA-specific module parameter: | ||
| 36 | "dma_desc_per_channel" - defines number of hardware buffer descriptors used by | ||
| 37 | each BDMA channel of Tsi721 (by default - 128). | ||
| 27 | 38 | ||
| 28 | IV. Version History | 39 | IV. Version History |
| 29 | 40 | ||
| 41 | 1.1.0 - DMA operations re-worked to support data scatter/gather lists larger | ||
| 42 | than hardware buffer descriptors ring. | ||
| 30 | 1.0.0 - Initial driver release. | 43 | 1.0.0 - Initial driver release. |
| 31 | 44 | ||
| 32 | V. License | 45 | V. License |
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt index c14374e71775..f79eb9666379 100644 --- a/Documentation/sysctl/kernel.txt +++ b/Documentation/sysctl/kernel.txt | |||
| @@ -826,6 +826,7 @@ can be ORed together: | |||
| 826 | 4096 - An out-of-tree module has been loaded. | 826 | 4096 - An out-of-tree module has been loaded. |
| 827 | 8192 - An unsigned module has been loaded in a kernel supporting module | 827 | 8192 - An unsigned module has been loaded in a kernel supporting module |
| 828 | signature. | 828 | signature. |
| 829 | 16384 - A soft lockup has previously occurred on the system. | ||
| 829 | 830 | ||
| 830 | ============================================================== | 831 | ============================================================== |
| 831 | 832 | ||
diff --git a/MAINTAINERS b/MAINTAINERS index e065c3881626..30873e781dfa 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -597,7 +597,7 @@ AMD GEODE CS5536 USB DEVICE CONTROLLER DRIVER | |||
| 597 | M: Thomas Dahlmann <dahlmann.thomas@arcor.de> | 597 | M: Thomas Dahlmann <dahlmann.thomas@arcor.de> |
| 598 | L: linux-geode@lists.infradead.org (moderated for non-subscribers) | 598 | L: linux-geode@lists.infradead.org (moderated for non-subscribers) |
| 599 | S: Supported | 599 | S: Supported |
| 600 | F: drivers/usb/gadget/amd5536udc.* | 600 | F: drivers/usb/gadget/udc/amd5536udc.* |
| 601 | 601 | ||
| 602 | AMD GEODE PROCESSOR/CHIPSET SUPPORT | 602 | AMD GEODE PROCESSOR/CHIPSET SUPPORT |
| 603 | P: Andres Salomon <dilinger@queued.net> | 603 | P: Andres Salomon <dilinger@queued.net> |
| @@ -621,7 +621,7 @@ AMD MICROCODE UPDATE SUPPORT | |||
| 621 | M: Andreas Herrmann <herrmann.der.user@googlemail.com> | 621 | M: Andreas Herrmann <herrmann.der.user@googlemail.com> |
| 622 | L: amd64-microcode@amd64.org | 622 | L: amd64-microcode@amd64.org |
| 623 | S: Maintained | 623 | S: Maintained |
| 624 | F: arch/x86/kernel/microcode_amd.c | 624 | F: arch/x86/kernel/cpu/microcode/amd* |
| 625 | 625 | ||
| 626 | AMD XGBE DRIVER | 626 | AMD XGBE DRIVER |
| 627 | M: Tom Lendacky <thomas.lendacky@amd.com> | 627 | M: Tom Lendacky <thomas.lendacky@amd.com> |
| @@ -911,7 +911,7 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | |||
| 911 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/baohua/linux.git | 911 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/baohua/linux.git |
| 912 | S: Maintained | 912 | S: Maintained |
| 913 | F: arch/arm/mach-prima2/ | 913 | F: arch/arm/mach-prima2/ |
| 914 | F: drivers/clk/clk-prima2.c | 914 | F: drivers/clk/sirf/ |
| 915 | F: drivers/clocksource/timer-prima2.c | 915 | F: drivers/clocksource/timer-prima2.c |
| 916 | F: drivers/clocksource/timer-marco.c | 916 | F: drivers/clocksource/timer-marco.c |
| 917 | N: [^a-z]sirf | 917 | N: [^a-z]sirf |
| @@ -1164,6 +1164,7 @@ M: Linus Walleij <linus.walleij@linaro.org> | |||
| 1164 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | 1164 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 1165 | S: Maintained | 1165 | S: Maintained |
| 1166 | F: arch/arm/mach-nomadik/ | 1166 | F: arch/arm/mach-nomadik/ |
| 1167 | F: drivers/pinctrl/nomadik/ | ||
| 1167 | F: drivers/i2c/busses/i2c-nomadik.c | 1168 | F: drivers/i2c/busses/i2c-nomadik.c |
| 1168 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-nomadik.git | 1169 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-nomadik.git |
| 1169 | 1170 | ||
| @@ -1185,8 +1186,7 @@ F: drivers/mmc/host/msm_sdcc.h | |||
| 1185 | F: drivers/tty/serial/msm_serial.h | 1186 | F: drivers/tty/serial/msm_serial.h |
| 1186 | F: drivers/tty/serial/msm_serial.c | 1187 | F: drivers/tty/serial/msm_serial.c |
| 1187 | F: drivers/*/pm8???-* | 1188 | F: drivers/*/pm8???-* |
| 1188 | F: drivers/mfd/ssbi/ | 1189 | F: drivers/mfd/ssbi.c |
| 1189 | F: include/linux/mfd/pm8xxx/ | ||
| 1190 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/davidb/linux-msm.git | 1190 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/davidb/linux-msm.git |
| 1191 | S: Maintained | 1191 | S: Maintained |
| 1192 | 1192 | ||
| @@ -1443,7 +1443,8 @@ F: drivers/mfd/abx500* | |||
| 1443 | F: drivers/mfd/ab8500* | 1443 | F: drivers/mfd/ab8500* |
| 1444 | F: drivers/mfd/dbx500* | 1444 | F: drivers/mfd/dbx500* |
| 1445 | F: drivers/mfd/db8500* | 1445 | F: drivers/mfd/db8500* |
| 1446 | F: drivers/pinctrl/pinctrl-nomadik* | 1446 | F: drivers/pinctrl/nomadik/pinctrl-ab* |
| 1447 | F: drivers/pinctrl/nomadik/pinctrl-nomadik* | ||
| 1447 | F: drivers/rtc/rtc-ab8500.c | 1448 | F: drivers/rtc/rtc-ab8500.c |
| 1448 | F: drivers/rtc/rtc-pl031.c | 1449 | F: drivers/rtc/rtc-pl031.c |
| 1449 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git | 1450 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git |
| @@ -1699,7 +1700,7 @@ ATMEL USBA UDC DRIVER | |||
| 1699 | M: Nicolas Ferre <nicolas.ferre@atmel.com> | 1700 | M: Nicolas Ferre <nicolas.ferre@atmel.com> |
| 1700 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | 1701 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 1701 | S: Supported | 1702 | S: Supported |
| 1702 | F: drivers/usb/gadget/atmel_usba_udc.* | 1703 | F: drivers/usb/gadget/udc/atmel_usba_udc.* |
| 1703 | 1704 | ||
| 1704 | ATMEL WIRELESS DRIVER | 1705 | ATMEL WIRELESS DRIVER |
| 1705 | M: Simon Kelley <simon@thekelleys.org.uk> | 1706 | M: Simon Kelley <simon@thekelleys.org.uk> |
| @@ -1991,7 +1992,7 @@ F: arch/arm/boot/dts/bcm113* | |||
| 1991 | F: arch/arm/boot/dts/bcm216* | 1992 | F: arch/arm/boot/dts/bcm216* |
| 1992 | F: arch/arm/boot/dts/bcm281* | 1993 | F: arch/arm/boot/dts/bcm281* |
| 1993 | F: arch/arm/configs/bcm_defconfig | 1994 | F: arch/arm/configs/bcm_defconfig |
| 1994 | F: drivers/mmc/host/sdhci_bcm_kona.c | 1995 | F: drivers/mmc/host/sdhci-bcm-kona.c |
| 1995 | F: drivers/clocksource/bcm_kona_timer.c | 1996 | F: drivers/clocksource/bcm_kona_timer.c |
| 1996 | 1997 | ||
| 1997 | BROADCOM BCM2835 ARM ARCHICTURE | 1998 | BROADCOM BCM2835 ARM ARCHICTURE |
| @@ -2341,12 +2342,6 @@ L: netdev@vger.kernel.org | |||
| 2341 | S: Maintained | 2342 | S: Maintained |
| 2342 | F: drivers/net/ethernet/cirrus/ep93xx_eth.c | 2343 | F: drivers/net/ethernet/cirrus/ep93xx_eth.c |
| 2343 | 2344 | ||
| 2344 | CIRRUS LOGIC EP93XX OHCI USB HOST DRIVER | ||
| 2345 | M: Lennert Buytenhek <kernel@wantstofly.org> | ||
| 2346 | L: linux-usb@vger.kernel.org | ||
| 2347 | S: Maintained | ||
| 2348 | F: drivers/usb/host/ohci-ep93xx.c | ||
| 2349 | |||
| 2350 | CIRRUS LOGIC AUDIO CODEC DRIVERS | 2345 | CIRRUS LOGIC AUDIO CODEC DRIVERS |
| 2351 | M: Brian Austin <brian.austin@cirrus.com> | 2346 | M: Brian Austin <brian.austin@cirrus.com> |
| 2352 | M: Paul Handrigan <Paul.Handrigan@cirrus.com> | 2347 | M: Paul Handrigan <Paul.Handrigan@cirrus.com> |
| @@ -2431,7 +2426,7 @@ W: http://linux-cifs.samba.org/ | |||
| 2431 | Q: http://patchwork.ozlabs.org/project/linux-cifs-client/list/ | 2426 | Q: http://patchwork.ozlabs.org/project/linux-cifs-client/list/ |
| 2432 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6.git | 2427 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6.git |
| 2433 | S: Supported | 2428 | S: Supported |
| 2434 | F: Documentation/filesystems/cifs.txt | 2429 | F: Documentation/filesystems/cifs/ |
| 2435 | F: fs/cifs/ | 2430 | F: fs/cifs/ |
| 2436 | 2431 | ||
| 2437 | COMPACTPCI HOTPLUG CORE | 2432 | COMPACTPCI HOTPLUG CORE |
| @@ -2966,7 +2961,9 @@ L: linux-media@vger.kernel.org | |||
| 2966 | L: dri-devel@lists.freedesktop.org | 2961 | L: dri-devel@lists.freedesktop.org |
| 2967 | L: linaro-mm-sig@lists.linaro.org | 2962 | L: linaro-mm-sig@lists.linaro.org |
| 2968 | F: drivers/dma-buf/ | 2963 | F: drivers/dma-buf/ |
| 2969 | F: include/linux/dma-buf* include/linux/reservation.h include/linux/*fence.h | 2964 | F: include/linux/dma-buf* |
| 2965 | F: include/linux/reservation.h | ||
| 2966 | F: include/linux/*fence.h | ||
| 2970 | F: Documentation/dma-buf-sharing.txt | 2967 | F: Documentation/dma-buf-sharing.txt |
| 2971 | T: git git://git.linaro.org/people/sumitsemwal/linux-dma-buf.git | 2968 | T: git git://git.linaro.org/people/sumitsemwal/linux-dma-buf.git |
| 2972 | 2969 | ||
| @@ -3061,7 +3058,6 @@ L: dri-devel@lists.freedesktop.org | |||
| 3061 | T: git git://people.freedesktop.org/~agd5f/linux | 3058 | T: git git://people.freedesktop.org/~agd5f/linux |
| 3062 | S: Supported | 3059 | S: Supported |
| 3063 | F: drivers/gpu/drm/radeon/ | 3060 | F: drivers/gpu/drm/radeon/ |
| 3064 | F: include/drm/radeon* | ||
| 3065 | F: include/uapi/drm/radeon* | 3061 | F: include/uapi/drm/radeon* |
| 3066 | 3062 | ||
| 3067 | DRM PANEL DRIVERS | 3063 | DRM PANEL DRIVERS |
| @@ -3255,26 +3251,12 @@ T: git git://linuxtv.org/anttip/media_tree.git | |||
| 3255 | S: Maintained | 3251 | S: Maintained |
| 3256 | F: drivers/media/tuners/e4000* | 3252 | F: drivers/media/tuners/e4000* |
| 3257 | 3253 | ||
| 3258 | EATA-DMA SCSI DRIVER | ||
| 3259 | M: Michael Neuffer <mike@i-Connect.Net> | ||
| 3260 | L: linux-eata@i-connect.net | ||
| 3261 | L: linux-scsi@vger.kernel.org | ||
| 3262 | S: Maintained | ||
| 3263 | F: drivers/scsi/eata* | ||
| 3264 | |||
| 3265 | EATA ISA/EISA/PCI SCSI DRIVER | 3254 | EATA ISA/EISA/PCI SCSI DRIVER |
| 3266 | M: Dario Ballabio <ballabio_dario@emc.com> | 3255 | M: Dario Ballabio <ballabio_dario@emc.com> |
| 3267 | L: linux-scsi@vger.kernel.org | 3256 | L: linux-scsi@vger.kernel.org |
| 3268 | S: Maintained | 3257 | S: Maintained |
| 3269 | F: drivers/scsi/eata.c | 3258 | F: drivers/scsi/eata.c |
| 3270 | 3259 | ||
| 3271 | EATA-PIO SCSI DRIVER | ||
| 3272 | M: Michael Neuffer <mike@i-Connect.Net> | ||
| 3273 | L: linux-eata@i-connect.net | ||
| 3274 | L: linux-scsi@vger.kernel.org | ||
| 3275 | S: Maintained | ||
| 3276 | F: drivers/scsi/eata_pio.* | ||
| 3277 | |||
| 3278 | EC100 MEDIA DRIVER | 3260 | EC100 MEDIA DRIVER |
| 3279 | M: Antti Palosaari <crope@iki.fi> | 3261 | M: Antti Palosaari <crope@iki.fi> |
| 3280 | L: linux-media@vger.kernel.org | 3262 | L: linux-media@vger.kernel.org |
| @@ -3449,7 +3431,7 @@ M: Matt Fleming <matt.fleming@intel.com> | |||
| 3449 | L: linux-efi@vger.kernel.org | 3431 | L: linux-efi@vger.kernel.org |
| 3450 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi.git | 3432 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi.git |
| 3451 | S: Maintained | 3433 | S: Maintained |
| 3452 | F: Documentation/x86/efi-stub.txt | 3434 | F: Documentation/efi-stub.txt |
| 3453 | F: arch/ia64/kernel/efi.c | 3435 | F: arch/ia64/kernel/efi.c |
| 3454 | F: arch/x86/boot/compressed/eboot.[ch] | 3436 | F: arch/x86/boot/compressed/eboot.[ch] |
| 3455 | F: arch/x86/include/asm/efi.h | 3437 | F: arch/x86/include/asm/efi.h |
| @@ -3836,7 +3818,7 @@ M: Li Yang <leoli@freescale.com> | |||
| 3836 | L: linux-usb@vger.kernel.org | 3818 | L: linux-usb@vger.kernel.org |
| 3837 | L: linuxppc-dev@lists.ozlabs.org | 3819 | L: linuxppc-dev@lists.ozlabs.org |
| 3838 | S: Maintained | 3820 | S: Maintained |
| 3839 | F: drivers/usb/gadget/fsl* | 3821 | F: drivers/usb/gadget/udc/fsl* |
| 3840 | 3822 | ||
| 3841 | FREESCALE QUICC ENGINE UCC ETHERNET DRIVER | 3823 | FREESCALE QUICC ENGINE UCC ETHERNET DRIVER |
| 3842 | M: Li Yang <leoli@freescale.com> | 3824 | M: Li Yang <leoli@freescale.com> |
| @@ -4525,10 +4507,7 @@ S: Supported | |||
| 4525 | F: drivers/scsi/ibmvscsi/ibmvfc* | 4507 | F: drivers/scsi/ibmvscsi/ibmvfc* |
| 4526 | 4508 | ||
| 4527 | IBM ServeRAID RAID DRIVER | 4509 | IBM ServeRAID RAID DRIVER |
| 4528 | P: Jack Hammer | 4510 | S: Orphan |
| 4529 | M: Dave Jeffery <ipslinux@adaptec.com> | ||
| 4530 | W: http://www.developer.ibm.com/welcome/netfinity/serveraid.html | ||
| 4531 | S: Supported | ||
| 4532 | F: drivers/scsi/ips.* | 4511 | F: drivers/scsi/ips.* |
| 4533 | 4512 | ||
| 4534 | ICH LPC AND GPIO DRIVER | 4513 | ICH LPC AND GPIO DRIVER |
| @@ -4725,8 +4704,8 @@ F: drivers/platform/x86/intel_menlow.c | |||
| 4725 | INTEL IA32 MICROCODE UPDATE SUPPORT | 4704 | INTEL IA32 MICROCODE UPDATE SUPPORT |
| 4726 | M: Tigran Aivazian <tigran@aivazian.fsnet.co.uk> | 4705 | M: Tigran Aivazian <tigran@aivazian.fsnet.co.uk> |
| 4727 | S: Maintained | 4706 | S: Maintained |
| 4728 | F: arch/x86/kernel/microcode_core.c | 4707 | F: arch/x86/kernel/cpu/microcode/core* |
| 4729 | F: arch/x86/kernel/microcode_intel.c | 4708 | F: arch/x86/kernel/cpu/microcode/intel* |
| 4730 | 4709 | ||
| 4731 | INTEL I/OAT DMA DRIVER | 4710 | INTEL I/OAT DMA DRIVER |
| 4732 | M: Dan Williams <dan.j.williams@intel.com> | 4711 | M: Dan Williams <dan.j.williams@intel.com> |
| @@ -5185,7 +5164,6 @@ L: linux-nfs@vger.kernel.org | |||
| 5185 | W: http://nfs.sourceforge.net/ | 5164 | W: http://nfs.sourceforge.net/ |
| 5186 | S: Supported | 5165 | S: Supported |
| 5187 | F: fs/nfsd/ | 5166 | F: fs/nfsd/ |
| 5188 | F: include/linux/nfsd/ | ||
| 5189 | F: include/uapi/linux/nfsd/ | 5167 | F: include/uapi/linux/nfsd/ |
| 5190 | F: fs/lockd/ | 5168 | F: fs/lockd/ |
| 5191 | F: fs/nfs_common/ | 5169 | F: fs/nfs_common/ |
| @@ -5906,7 +5884,6 @@ F: drivers/clocksource/metag_generic.c | |||
| 5906 | F: drivers/irqchip/irq-metag.c | 5884 | F: drivers/irqchip/irq-metag.c |
| 5907 | F: drivers/irqchip/irq-metag-ext.c | 5885 | F: drivers/irqchip/irq-metag-ext.c |
| 5908 | F: drivers/tty/metag_da.c | 5886 | F: drivers/tty/metag_da.c |
| 5909 | F: fs/imgdafs/ | ||
| 5910 | 5887 | ||
| 5911 | MICROBLAZE ARCHITECTURE | 5888 | MICROBLAZE ARCHITECTURE |
| 5912 | M: Michal Simek <monstr@monstr.eu> | 5889 | M: Michal Simek <monstr@monstr.eu> |
| @@ -6997,9 +6974,9 @@ M: Jamie Iles <jamie@jamieiles.com> | |||
| 6997 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | 6974 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 6998 | T: git git://github.com/jamieiles/linux-2.6-ji.git | 6975 | T: git git://github.com/jamieiles/linux-2.6-ji.git |
| 6999 | S: Supported | 6976 | S: Supported |
| 6977 | F: arch/arm/boot/dts/picoxcell* | ||
| 7000 | F: arch/arm/mach-picoxcell/ | 6978 | F: arch/arm/mach-picoxcell/ |
| 7001 | F: drivers/*/picoxcell* | 6979 | F: drivers/crypto/picoxcell* |
| 7002 | F: drivers/*/*/picoxcell* | ||
| 7003 | 6980 | ||
| 7004 | PIN CONTROL SUBSYSTEM | 6981 | PIN CONTROL SUBSYSTEM |
| 7005 | M: Linus Walleij <linus.walleij@linaro.org> | 6982 | M: Linus Walleij <linus.walleij@linaro.org> |
| @@ -7224,7 +7201,7 @@ F: drivers/ptp/* | |||
| 7224 | F: include/linux/ptp_cl* | 7201 | F: include/linux/ptp_cl* |
| 7225 | 7202 | ||
| 7226 | PTRACE SUPPORT | 7203 | PTRACE SUPPORT |
| 7227 | M: Roland McGrath <roland@redhat.com> | 7204 | M: Roland McGrath <roland@hack.frob.com> |
| 7228 | M: Oleg Nesterov <oleg@redhat.com> | 7205 | M: Oleg Nesterov <oleg@redhat.com> |
| 7229 | S: Maintained | 7206 | S: Maintained |
| 7230 | F: include/asm-generic/syscall.h | 7207 | F: include/asm-generic/syscall.h |
| @@ -7274,7 +7251,7 @@ S: Maintained | |||
| 7274 | F: arch/arm/mach-pxa/ | 7251 | F: arch/arm/mach-pxa/ |
| 7275 | F: drivers/pcmcia/pxa2xx* | 7252 | F: drivers/pcmcia/pxa2xx* |
| 7276 | F: drivers/spi/spi-pxa2xx* | 7253 | F: drivers/spi/spi-pxa2xx* |
| 7277 | F: drivers/usb/gadget/pxa2* | 7254 | F: drivers/usb/gadget/udc/pxa2* |
| 7278 | F: include/sound/pxa2xx-lib.h | 7255 | F: include/sound/pxa2xx-lib.h |
| 7279 | F: sound/arm/pxa* | 7256 | F: sound/arm/pxa* |
| 7280 | F: sound/soc/pxa/ | 7257 | F: sound/soc/pxa/ |
| @@ -7283,7 +7260,7 @@ PXA3xx NAND FLASH DRIVER | |||
| 7283 | M: Ezequiel Garcia <ezequiel.garcia@free-electrons.com> | 7260 | M: Ezequiel Garcia <ezequiel.garcia@free-electrons.com> |
| 7284 | L: linux-mtd@lists.infradead.org | 7261 | L: linux-mtd@lists.infradead.org |
| 7285 | S: Maintained | 7262 | S: Maintained |
| 7286 | F: drivers/mtd/nand/pxa3xx-nand.c | 7263 | F: drivers/mtd/nand/pxa3xx_nand.c |
| 7287 | 7264 | ||
| 7288 | MMP SUPPORT | 7265 | MMP SUPPORT |
| 7289 | M: Eric Miao <eric.y.miao@gmail.com> | 7266 | M: Eric Miao <eric.y.miao@gmail.com> |
| @@ -9628,8 +9605,8 @@ USB WEBCAM GADGET | |||
| 9628 | M: Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 9605 | M: Laurent Pinchart <laurent.pinchart@ideasonboard.com> |
| 9629 | L: linux-usb@vger.kernel.org | 9606 | L: linux-usb@vger.kernel.org |
| 9630 | S: Maintained | 9607 | S: Maintained |
| 9631 | F: drivers/usb/gadget/*uvc*.c | 9608 | F: drivers/usb/gadget/function/*uvc*.c |
| 9632 | F: drivers/usb/gadget/webcam.c | 9609 | F: drivers/usb/gadget/legacy/webcam.c |
| 9633 | 9610 | ||
| 9634 | USB WIRELESS RNDIS DRIVER (rndis_wlan) | 9611 | USB WIRELESS RNDIS DRIVER (rndis_wlan) |
| 9635 | M: Jussi Kivilinna <jussi.kivilinna@iki.fi> | 9612 | M: Jussi Kivilinna <jussi.kivilinna@iki.fi> |
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild index 96e54bed5088..e858aa0ad8af 100644 --- a/arch/alpha/include/asm/Kbuild +++ b/arch/alpha/include/asm/Kbuild | |||
| @@ -6,4 +6,5 @@ generic-y += exec.h | |||
| 6 | generic-y += hash.h | 6 | generic-y += hash.h |
| 7 | generic-y += mcs_spinlock.h | 7 | generic-y += mcs_spinlock.h |
| 8 | generic-y += preempt.h | 8 | generic-y += preempt.h |
| 9 | generic-y += scatterlist.h | ||
| 9 | generic-y += trace_clock.h | 10 | generic-y += trace_clock.h |
diff --git a/arch/alpha/include/asm/scatterlist.h b/arch/alpha/include/asm/scatterlist.h deleted file mode 100644 index 017d7471c3c4..000000000000 --- a/arch/alpha/include/asm/scatterlist.h +++ /dev/null | |||
| @@ -1,6 +0,0 @@ | |||
| 1 | #ifndef _ALPHA_SCATTERLIST_H | ||
| 2 | #define _ALPHA_SCATTERLIST_H | ||
| 3 | |||
| 4 | #include <asm-generic/scatterlist.h> | ||
| 5 | |||
| 6 | #endif /* !(_ALPHA_SCATTERLIST_H) */ | ||
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 916cedbd7a67..c49a775937db 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
| @@ -83,6 +83,7 @@ config ARM | |||
| 83 | <http://www.arm.linux.org.uk/>. | 83 | <http://www.arm.linux.org.uk/>. |
| 84 | 84 | ||
| 85 | config ARM_HAS_SG_CHAIN | 85 | config ARM_HAS_SG_CHAIN |
| 86 | select ARCH_HAS_SG_CHAIN | ||
| 86 | bool | 87 | bool |
| 87 | 88 | ||
| 88 | config NEED_SG_DMA_LENGTH | 89 | config NEED_SG_DMA_LENGTH |
| @@ -1982,6 +1983,8 @@ config XIP_PHYS_ADDR | |||
| 1982 | config KEXEC | 1983 | config KEXEC |
| 1983 | bool "Kexec system call (EXPERIMENTAL)" | 1984 | bool "Kexec system call (EXPERIMENTAL)" |
| 1984 | depends on (!SMP || PM_SLEEP_SMP) | 1985 | depends on (!SMP || PM_SLEEP_SMP) |
| 1986 | select CRYPTO | ||
| 1987 | select CRYPTO_SHA256 | ||
| 1985 | help | 1988 | help |
| 1986 | kexec is a system call that implements the ability to shutdown your | 1989 | kexec is a system call that implements the ability to shutdown your |
| 1987 | current kernel, and to start another kernel. It is like a reboot | 1990 | current kernel, and to start another kernel. It is like a reboot |
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild index f5a357601983..70cd84eb7fda 100644 --- a/arch/arm/include/asm/Kbuild +++ b/arch/arm/include/asm/Kbuild | |||
| @@ -22,6 +22,7 @@ generic-y += poll.h | |||
| 22 | generic-y += preempt.h | 22 | generic-y += preempt.h |
| 23 | generic-y += resource.h | 23 | generic-y += resource.h |
| 24 | generic-y += rwsem.h | 24 | generic-y += rwsem.h |
| 25 | generic-y += scatterlist.h | ||
| 25 | generic-y += sections.h | 26 | generic-y += sections.h |
| 26 | generic-y += segment.h | 27 | generic-y += segment.h |
| 27 | generic-y += sembuf.h | 28 | generic-y += sembuf.h |
diff --git a/arch/arm/include/asm/scatterlist.h b/arch/arm/include/asm/scatterlist.h deleted file mode 100644 index cefdb8f898a1..000000000000 --- a/arch/arm/include/asm/scatterlist.h +++ /dev/null | |||
| @@ -1,12 +0,0 @@ | |||
| 1 | #ifndef _ASMARM_SCATTERLIST_H | ||
| 2 | #define _ASMARM_SCATTERLIST_H | ||
| 3 | |||
| 4 | #ifdef CONFIG_ARM_HAS_SG_CHAIN | ||
| 5 | #define ARCH_HAS_SG_CHAIN | ||
| 6 | #endif | ||
| 7 | |||
| 8 | #include <asm/memory.h> | ||
| 9 | #include <asm/types.h> | ||
| 10 | #include <asm-generic/scatterlist.h> | ||
| 11 | |||
| 12 | #endif /* _ASMARM_SCATTERLIST_H */ | ||
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c index 7da48bc42bbf..70b904c010c6 100644 --- a/arch/arm/mach-omap2/board-omap3touchbook.c +++ b/arch/arm/mach-omap2/board-omap3touchbook.c | |||
| @@ -336,7 +336,7 @@ static int __init early_touchbook_revision(char *p) | |||
| 336 | if (!p) | 336 | if (!p) |
| 337 | return 0; | 337 | return 0; |
| 338 | 338 | ||
| 339 | return strict_strtoul(p, 10, &touchbook_revision); | 339 | return kstrtoul(p, 10, &touchbook_revision); |
| 340 | } | 340 | } |
| 341 | early_param("tbr", early_touchbook_revision); | 341 | early_param("tbr", early_touchbook_revision); |
| 342 | 342 | ||
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c index f62f7537d899..ac8a249779f2 100644 --- a/arch/arm/mach-omap2/mux.c +++ b/arch/arm/mach-omap2/mux.c | |||
| @@ -681,29 +681,19 @@ static ssize_t omap_mux_dbg_signal_write(struct file *file, | |||
| 681 | const char __user *user_buf, | 681 | const char __user *user_buf, |
| 682 | size_t count, loff_t *ppos) | 682 | size_t count, loff_t *ppos) |
| 683 | { | 683 | { |
| 684 | char buf[OMAP_MUX_MAX_ARG_CHAR]; | ||
| 685 | struct seq_file *seqf; | 684 | struct seq_file *seqf; |
| 686 | struct omap_mux *m; | 685 | struct omap_mux *m; |
| 687 | unsigned long val; | 686 | u16 val; |
| 688 | int buf_size, ret; | 687 | int ret; |
| 689 | struct omap_mux_partition *partition; | 688 | struct omap_mux_partition *partition; |
| 690 | 689 | ||
| 691 | if (count > OMAP_MUX_MAX_ARG_CHAR) | 690 | if (count > OMAP_MUX_MAX_ARG_CHAR) |
| 692 | return -EINVAL; | 691 | return -EINVAL; |
| 693 | 692 | ||
| 694 | memset(buf, 0, sizeof(buf)); | 693 | ret = kstrtou16_from_user(user_buf, count, 0x10, &val); |
| 695 | buf_size = min(count, sizeof(buf) - 1); | ||
| 696 | |||
| 697 | if (copy_from_user(buf, user_buf, buf_size)) | ||
| 698 | return -EFAULT; | ||
| 699 | |||
| 700 | ret = strict_strtoul(buf, 0x10, &val); | ||
| 701 | if (ret < 0) | 694 | if (ret < 0) |
| 702 | return ret; | 695 | return ret; |
| 703 | 696 | ||
| 704 | if (val > 0xffff) | ||
| 705 | return -EINVAL; | ||
| 706 | |||
| 707 | seqf = file->private_data; | 697 | seqf = file->private_data; |
| 708 | m = seqf->private; | 698 | m = seqf->private; |
| 709 | 699 | ||
| @@ -711,7 +701,7 @@ static ssize_t omap_mux_dbg_signal_write(struct file *file, | |||
| 711 | if (!partition) | 701 | if (!partition) |
| 712 | return -ENODEV; | 702 | return -ENODEV; |
| 713 | 703 | ||
| 714 | omap_mux_write(partition, (u16)val, m->reg_offset); | 704 | omap_mux_write(partition, val, m->reg_offset); |
| 715 | *ppos += count; | 705 | *ppos += count; |
| 716 | 706 | ||
| 717 | return count; | 707 | return count; |
| @@ -917,14 +907,14 @@ static void __init omap_mux_set_cmdline_signals(void) | |||
| 917 | 907 | ||
| 918 | while ((token = strsep(&next_opt, ",")) != NULL) { | 908 | while ((token = strsep(&next_opt, ",")) != NULL) { |
| 919 | char *keyval, *name; | 909 | char *keyval, *name; |
| 920 | unsigned long val; | 910 | u16 val; |
| 921 | 911 | ||
| 922 | keyval = token; | 912 | keyval = token; |
| 923 | name = strsep(&keyval, "="); | 913 | name = strsep(&keyval, "="); |
| 924 | if (name) { | 914 | if (name) { |
| 925 | int res; | 915 | int res; |
| 926 | 916 | ||
| 927 | res = strict_strtoul(keyval, 0x10, &val); | 917 | res = kstrtou16(keyval, 0x10, &val); |
| 928 | if (res < 0) | 918 | if (res < 0) |
| 929 | continue; | 919 | continue; |
| 930 | 920 | ||
diff --git a/arch/arm/mach-pxa/balloon3.c b/arch/arm/mach-pxa/balloon3.c index 43596e0ed051..d897292712eb 100644 --- a/arch/arm/mach-pxa/balloon3.c +++ b/arch/arm/mach-pxa/balloon3.c | |||
| @@ -90,7 +90,7 @@ int __init parse_balloon3_features(char *arg) | |||
| 90 | if (!arg) | 90 | if (!arg) |
| 91 | return 0; | 91 | return 0; |
| 92 | 92 | ||
| 93 | return strict_strtoul(arg, 0, &balloon3_features_present); | 93 | return kstrtoul(arg, 0, &balloon3_features_present); |
| 94 | } | 94 | } |
| 95 | early_param("balloon3_features", parse_balloon3_features); | 95 | early_param("balloon3_features", parse_balloon3_features); |
| 96 | 96 | ||
diff --git a/arch/arm/mach-pxa/viper.c b/arch/arm/mach-pxa/viper.c index 41f27f667ca8..de3b08073fe7 100644 --- a/arch/arm/mach-pxa/viper.c +++ b/arch/arm/mach-pxa/viper.c | |||
| @@ -769,7 +769,7 @@ static unsigned long viper_tpm; | |||
| 769 | 769 | ||
| 770 | static int __init viper_tpm_setup(char *str) | 770 | static int __init viper_tpm_setup(char *str) |
| 771 | { | 771 | { |
| 772 | return strict_strtoul(str, 10, &viper_tpm) >= 0; | 772 | return kstrtoul(str, 10, &viper_tpm) >= 0; |
| 773 | } | 773 | } |
| 774 | 774 | ||
| 775 | __setup("tpm=", viper_tpm_setup); | 775 | __setup("tpm=", viper_tpm_setup); |
diff --git a/arch/arm/mach-s3c24xx/mach-jive.c b/arch/arm/mach-s3c24xx/mach-jive.c index e647b47244a9..7804d3c6991b 100644 --- a/arch/arm/mach-s3c24xx/mach-jive.c +++ b/arch/arm/mach-s3c24xx/mach-jive.c | |||
| @@ -242,7 +242,7 @@ static int __init jive_mtdset(char *options) | |||
| 242 | if (options == NULL || options[0] == '\0') | 242 | if (options == NULL || options[0] == '\0') |
| 243 | return 0; | 243 | return 0; |
| 244 | 244 | ||
| 245 | if (strict_strtoul(options, 10, &set)) { | 245 | if (kstrtoul(options, 10, &set)) { |
| 246 | printk(KERN_ERR "failed to parse mtdset=%s\n", options); | 246 | printk(KERN_ERR "failed to parse mtdset=%s\n", options); |
| 247 | return 0; | 247 | return 0; |
| 248 | } | 248 | } |
diff --git a/arch/arm/mach-w90x900/cpu.c b/arch/arm/mach-w90x900/cpu.c index b1eabaad50a5..213230ee57d1 100644 --- a/arch/arm/mach-w90x900/cpu.c +++ b/arch/arm/mach-w90x900/cpu.c | |||
| @@ -178,7 +178,8 @@ static int __init nuc900_set_cpufreq(char *str) | |||
| 178 | if (!*str) | 178 | if (!*str) |
| 179 | return 0; | 179 | return 0; |
| 180 | 180 | ||
| 181 | strict_strtoul(str, 0, &cpufreq); | 181 | if (kstrtoul(str, 0, &cpufreq)) |
| 182 | return 0; | ||
| 182 | 183 | ||
| 183 | nuc900_clock_source(NULL, "ext"); | 184 | nuc900_clock_source(NULL, "ext"); |
| 184 | 185 | ||
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index b0f9c9db9590..fd4e81a4e1ce 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | config ARM64 | 1 | config ARM64 |
| 2 | def_bool y | 2 | def_bool y |
| 3 | select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE | 3 | select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE |
| 4 | select ARCH_HAS_SG_CHAIN | ||
| 4 | select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST | 5 | select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST |
| 5 | select ARCH_USE_CMPXCHG_LOCKREF | 6 | select ARCH_USE_CMPXCHG_LOCKREF |
| 6 | select ARCH_SUPPORTS_ATOMIC_RMW | 7 | select ARCH_SUPPORTS_ATOMIC_RMW |
diff --git a/arch/arm64/include/asm/page.h b/arch/arm64/include/asm/page.h index 7a3f462133b0..22b16232bd60 100644 --- a/arch/arm64/include/asm/page.h +++ b/arch/arm64/include/asm/page.h | |||
| @@ -28,9 +28,6 @@ | |||
| 28 | #define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT) | 28 | #define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT) |
| 29 | #define PAGE_MASK (~(PAGE_SIZE-1)) | 29 | #define PAGE_MASK (~(PAGE_SIZE-1)) |
| 30 | 30 | ||
| 31 | /* We do define AT_SYSINFO_EHDR but don't use the gate mechanism */ | ||
| 32 | #define __HAVE_ARCH_GATE_AREA 1 | ||
| 33 | |||
| 34 | /* | 31 | /* |
| 35 | * The idmap and swapper page tables need some space reserved in the kernel | 32 | * The idmap and swapper page tables need some space reserved in the kernel |
| 36 | * image. Both require pgd, pud (4 levels only) and pmd tables to (section) | 33 | * image. Both require pgd, pud (4 levels only) and pmd tables to (section) |
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c index a81a446a5786..32aeea083d93 100644 --- a/arch/arm64/kernel/vdso.c +++ b/arch/arm64/kernel/vdso.c | |||
| @@ -195,25 +195,6 @@ up_fail: | |||
| 195 | } | 195 | } |
| 196 | 196 | ||
| 197 | /* | 197 | /* |
| 198 | * We define AT_SYSINFO_EHDR, so we need these function stubs to keep | ||
| 199 | * Linux happy. | ||
| 200 | */ | ||
| 201 | int in_gate_area_no_mm(unsigned long addr) | ||
| 202 | { | ||
| 203 | return 0; | ||
| 204 | } | ||
| 205 | |||
| 206 | int in_gate_area(struct mm_struct *mm, unsigned long addr) | ||
| 207 | { | ||
| 208 | return 0; | ||
| 209 | } | ||
| 210 | |||
| 211 | struct vm_area_struct *get_gate_vma(struct mm_struct *mm) | ||
| 212 | { | ||
| 213 | return NULL; | ||
| 214 | } | ||
| 215 | |||
| 216 | /* | ||
| 217 | * Update the vDSO data page to keep in sync with kernel timekeeping. | 198 | * Update the vDSO data page to keep in sync with kernel timekeeping. |
| 218 | */ | 199 | */ |
| 219 | void update_vsyscall(struct timekeeper *tk) | 200 | void update_vsyscall(struct timekeeper *tk) |
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild index afff5105909d..31742dfadff9 100644 --- a/arch/cris/include/asm/Kbuild +++ b/arch/cris/include/asm/Kbuild | |||
| @@ -13,6 +13,7 @@ generic-y += linkage.h | |||
| 13 | generic-y += mcs_spinlock.h | 13 | generic-y += mcs_spinlock.h |
| 14 | generic-y += module.h | 14 | generic-y += module.h |
| 15 | generic-y += preempt.h | 15 | generic-y += preempt.h |
| 16 | generic-y += scatterlist.h | ||
| 16 | generic-y += trace_clock.h | 17 | generic-y += trace_clock.h |
| 17 | generic-y += vga.h | 18 | generic-y += vga.h |
| 18 | generic-y += xor.h | 19 | generic-y += xor.h |
diff --git a/arch/cris/include/asm/scatterlist.h b/arch/cris/include/asm/scatterlist.h deleted file mode 100644 index f11f8f40ec4a..000000000000 --- a/arch/cris/include/asm/scatterlist.h +++ /dev/null | |||
| @@ -1,6 +0,0 @@ | |||
| 1 | #ifndef __ASM_CRIS_SCATTERLIST_H | ||
| 2 | #define __ASM_CRIS_SCATTERLIST_H | ||
| 3 | |||
| 4 | #include <asm-generic/scatterlist.h> | ||
| 5 | |||
| 6 | #endif /* !(__ASM_CRIS_SCATTERLIST_H) */ | ||
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild index 87b95eb8aee5..5b73921b6e9d 100644 --- a/arch/frv/include/asm/Kbuild +++ b/arch/frv/include/asm/Kbuild | |||
| @@ -5,4 +5,5 @@ generic-y += exec.h | |||
| 5 | generic-y += hash.h | 5 | generic-y += hash.h |
| 6 | generic-y += mcs_spinlock.h | 6 | generic-y += mcs_spinlock.h |
| 7 | generic-y += preempt.h | 7 | generic-y += preempt.h |
| 8 | generic-y += scatterlist.h | ||
| 8 | generic-y += trace_clock.h | 9 | generic-y += trace_clock.h |
diff --git a/arch/frv/include/asm/scatterlist.h b/arch/frv/include/asm/scatterlist.h deleted file mode 100644 index 0e5eb3018468..000000000000 --- a/arch/frv/include/asm/scatterlist.h +++ /dev/null | |||
| @@ -1,6 +0,0 @@ | |||
| 1 | #ifndef _ASM_SCATTERLIST_H | ||
| 2 | #define _ASM_SCATTERLIST_H | ||
| 3 | |||
| 4 | #include <asm-generic/scatterlist.h> | ||
| 5 | |||
| 6 | #endif /* !_ASM_SCATTERLIST_H */ | ||
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 44a6915ab13d..64aefb76bd69 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig | |||
| @@ -28,6 +28,7 @@ config IA64 | |||
| 28 | select HAVE_MEMBLOCK | 28 | select HAVE_MEMBLOCK |
| 29 | select HAVE_MEMBLOCK_NODE_MAP | 29 | select HAVE_MEMBLOCK_NODE_MAP |
| 30 | select HAVE_VIRT_CPU_ACCOUNTING | 30 | select HAVE_VIRT_CPU_ACCOUNTING |
| 31 | select ARCH_HAS_SG_CHAIN | ||
| 31 | select VIRT_TO_BUS | 32 | select VIRT_TO_BUS |
| 32 | select ARCH_DISCARD_MEMBLOCK | 33 | select ARCH_DISCARD_MEMBLOCK |
| 33 | select GENERIC_IRQ_PROBE | 34 | select GENERIC_IRQ_PROBE |
| @@ -548,6 +549,8 @@ source "drivers/sn/Kconfig" | |||
| 548 | config KEXEC | 549 | config KEXEC |
| 549 | bool "kexec system call" | 550 | bool "kexec system call" |
| 550 | depends on !IA64_HP_SIM && (!SMP || HOTPLUG_CPU) | 551 | depends on !IA64_HP_SIM && (!SMP || HOTPLUG_CPU) |
| 552 | select CRYPTO | ||
| 553 | select CRYPTO_SHA256 | ||
| 551 | help | 554 | help |
| 552 | kexec is a system call that implements the ability to shutdown your | 555 | kexec is a system call that implements the ability to shutdown your |
| 553 | current kernel, and to start another kernel. It is like a reboot | 556 | current kernel, and to start another kernel. It is like a reboot |
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild index 0da4aa2602ae..e8317d2d6c8d 100644 --- a/arch/ia64/include/asm/Kbuild +++ b/arch/ia64/include/asm/Kbuild | |||
| @@ -5,5 +5,6 @@ generic-y += hash.h | |||
| 5 | generic-y += kvm_para.h | 5 | generic-y += kvm_para.h |
| 6 | generic-y += mcs_spinlock.h | 6 | generic-y += mcs_spinlock.h |
| 7 | generic-y += preempt.h | 7 | generic-y += preempt.h |
| 8 | generic-y += scatterlist.h | ||
| 8 | generic-y += trace_clock.h | 9 | generic-y += trace_clock.h |
| 9 | generic-y += vtime.h | 10 | generic-y += vtime.h |
diff --git a/arch/ia64/include/asm/page.h b/arch/ia64/include/asm/page.h index f1e1b2e3cdb3..1f1bf144fe62 100644 --- a/arch/ia64/include/asm/page.h +++ b/arch/ia64/include/asm/page.h | |||
| @@ -231,4 +231,6 @@ get_order (unsigned long size) | |||
| 231 | #define PERCPU_ADDR (-PERCPU_PAGE_SIZE) | 231 | #define PERCPU_ADDR (-PERCPU_PAGE_SIZE) |
| 232 | #define LOAD_OFFSET (KERNEL_START - KERNEL_TR_PAGE_SIZE) | 232 | #define LOAD_OFFSET (KERNEL_START - KERNEL_TR_PAGE_SIZE) |
| 233 | 233 | ||
| 234 | #define __HAVE_ARCH_GATE_AREA 1 | ||
| 235 | |||
| 234 | #endif /* _ASM_IA64_PAGE_H */ | 236 | #endif /* _ASM_IA64_PAGE_H */ |
diff --git a/arch/ia64/include/asm/scatterlist.h b/arch/ia64/include/asm/scatterlist.h deleted file mode 100644 index 08fd93bff1db..000000000000 --- a/arch/ia64/include/asm/scatterlist.h +++ /dev/null | |||
| @@ -1,7 +0,0 @@ | |||
| 1 | #ifndef _ASM_IA64_SCATTERLIST_H | ||
| 2 | #define _ASM_IA64_SCATTERLIST_H | ||
| 3 | |||
| 4 | #include <asm-generic/scatterlist.h> | ||
| 5 | #define ARCH_HAS_SG_CHAIN | ||
| 6 | |||
| 7 | #endif /* _ASM_IA64_SCATTERLIST_H */ | ||
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c index 3e71ef85e439..9a0104a38cd3 100644 --- a/arch/ia64/kernel/time.c +++ b/arch/ia64/kernel/time.c | |||
| @@ -384,21 +384,6 @@ static struct irqaction timer_irqaction = { | |||
| 384 | .name = "timer" | 384 | .name = "timer" |
| 385 | }; | 385 | }; |
| 386 | 386 | ||
| 387 | static struct platform_device rtc_efi_dev = { | ||
| 388 | .name = "rtc-efi", | ||
| 389 | .id = -1, | ||
| 390 | }; | ||
| 391 | |||
| 392 | static int __init rtc_init(void) | ||
| 393 | { | ||
| 394 | if (platform_device_register(&rtc_efi_dev) < 0) | ||
| 395 | printk(KERN_ERR "unable to register rtc device...\n"); | ||
| 396 | |||
| 397 | /* not necessarily an error */ | ||
| 398 | return 0; | ||
| 399 | } | ||
| 400 | module_init(rtc_init); | ||
| 401 | |||
| 402 | void read_persistent_clock(struct timespec *ts) | 387 | void read_persistent_clock(struct timespec *ts) |
| 403 | { | 388 | { |
| 404 | efi_gettimeofday(ts); | 389 | efi_gettimeofday(ts); |
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index 892d43e32f3b..6b3345758d3e 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c | |||
| @@ -278,6 +278,37 @@ setup_gate (void) | |||
| 278 | ia64_patch_gate(); | 278 | ia64_patch_gate(); |
| 279 | } | 279 | } |
| 280 | 280 | ||
| 281 | static struct vm_area_struct gate_vma; | ||
| 282 | |||
| 283 | static int __init gate_vma_init(void) | ||
| 284 | { | ||
| 285 | gate_vma.vm_mm = NULL; | ||
| 286 | gate_vma.vm_start = FIXADDR_USER_START; | ||
| 287 | gate_vma.vm_end = FIXADDR_USER_END; | ||
| 288 | gate_vma.vm_flags = VM_READ | VM_MAYREAD | VM_EXEC | VM_MAYEXEC; | ||
| 289 | gate_vma.vm_page_prot = __P101; | ||
| 290 | |||
| 291 | return 0; | ||
| 292 | } | ||
| 293 | __initcall(gate_vma_init); | ||
| 294 | |||
| 295 | struct vm_area_struct *get_gate_vma(struct mm_struct *mm) | ||
| 296 | { | ||
| 297 | return &gate_vma; | ||
| 298 | } | ||
| 299 | |||
| 300 | int in_gate_area_no_mm(unsigned long addr) | ||
| 301 | { | ||
| 302 | if ((addr >= FIXADDR_USER_START) && (addr < FIXADDR_USER_END)) | ||
| 303 | return 1; | ||
| 304 | return 0; | ||
| 305 | } | ||
| 306 | |||
| 307 | int in_gate_area(struct mm_struct *mm, unsigned long addr) | ||
| 308 | { | ||
| 309 | return in_gate_area_no_mm(addr); | ||
| 310 | } | ||
| 311 | |||
| 281 | void ia64_mmu_init(void *my_cpu_data) | 312 | void ia64_mmu_init(void *my_cpu_data) |
| 282 | { | 313 | { |
| 283 | unsigned long pta, impl_va_bits; | 314 | unsigned long pta, impl_va_bits; |
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild index 67779a74b62d..accc10a3dc78 100644 --- a/arch/m32r/include/asm/Kbuild +++ b/arch/m32r/include/asm/Kbuild | |||
| @@ -6,4 +6,5 @@ generic-y += hash.h | |||
| 6 | generic-y += mcs_spinlock.h | 6 | generic-y += mcs_spinlock.h |
| 7 | generic-y += module.h | 7 | generic-y += module.h |
| 8 | generic-y += preempt.h | 8 | generic-y += preempt.h |
| 9 | generic-y += scatterlist.h | ||
| 9 | generic-y += trace_clock.h | 10 | generic-y += trace_clock.h |
diff --git a/arch/m32r/include/asm/scatterlist.h b/arch/m32r/include/asm/scatterlist.h deleted file mode 100644 index 7370b8b6243e..000000000000 --- a/arch/m32r/include/asm/scatterlist.h +++ /dev/null | |||
| @@ -1,6 +0,0 @@ | |||
| 1 | #ifndef _ASM_M32R_SCATTERLIST_H | ||
| 2 | #define _ASM_M32R_SCATTERLIST_H | ||
| 3 | |||
| 4 | #include <asm-generic/scatterlist.h> | ||
| 5 | |||
| 6 | #endif /* _ASM_M32R_SCATTERLIST_H */ | ||
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index 87b7c7581b1d..3ff8c9a25335 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig | |||
| @@ -91,6 +91,8 @@ config MMU_SUN3 | |||
| 91 | config KEXEC | 91 | config KEXEC |
| 92 | bool "kexec system call" | 92 | bool "kexec system call" |
| 93 | depends on M68KCLASSIC | 93 | depends on M68KCLASSIC |
| 94 | select CRYPTO | ||
| 95 | select CRYPTO_SHA256 | ||
| 94 | help | 96 | help |
| 95 | kexec is a system call that implements the ability to shutdown your | 97 | kexec is a system call that implements the ability to shutdown your |
| 96 | current kernel, and to start another kernel. It is like a reboot | 98 | current kernel, and to start another kernel. It is like a reboot |
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild index 35b3ecaf25d5..27a3acda6c19 100644 --- a/arch/microblaze/include/asm/Kbuild +++ b/arch/microblaze/include/asm/Kbuild | |||
| @@ -7,5 +7,6 @@ generic-y += exec.h | |||
| 7 | generic-y += hash.h | 7 | generic-y += hash.h |
| 8 | generic-y += mcs_spinlock.h | 8 | generic-y += mcs_spinlock.h |
| 9 | generic-y += preempt.h | 9 | generic-y += preempt.h |
| 10 | generic-y += scatterlist.h | ||
| 10 | generic-y += syscalls.h | 11 | generic-y += syscalls.h |
| 11 | generic-y += trace_clock.h | 12 | generic-y += trace_clock.h |
diff --git a/arch/microblaze/include/asm/scatterlist.h b/arch/microblaze/include/asm/scatterlist.h deleted file mode 100644 index 35d786fe93ae..000000000000 --- a/arch/microblaze/include/asm/scatterlist.h +++ /dev/null | |||
| @@ -1 +0,0 @@ | |||
| 1 | #include <asm-generic/scatterlist.h> | ||
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 900c7e5333b6..df51e78a72cc 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig | |||
| @@ -2396,6 +2396,8 @@ source "kernel/Kconfig.preempt" | |||
| 2396 | 2396 | ||
| 2397 | config KEXEC | 2397 | config KEXEC |
| 2398 | bool "Kexec system call" | 2398 | bool "Kexec system call" |
| 2399 | select CRYPTO | ||
| 2400 | select CRYPTO_SHA256 | ||
| 2399 | help | 2401 | help |
| 2400 | kexec is a system call that implements the ability to shutdown your | 2402 | kexec is a system call that implements the ability to shutdown your |
| 2401 | current kernel, and to start another kernel. It is like a reboot | 2403 | current kernel, and to start another kernel. It is like a reboot |
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild index 654d5ba6e310..ecbd6676bd33 100644 --- a/arch/mn10300/include/asm/Kbuild +++ b/arch/mn10300/include/asm/Kbuild | |||
| @@ -6,4 +6,5 @@ generic-y += exec.h | |||
| 6 | generic-y += hash.h | 6 | generic-y += hash.h |
| 7 | generic-y += mcs_spinlock.h | 7 | generic-y += mcs_spinlock.h |
| 8 | generic-y += preempt.h | 8 | generic-y += preempt.h |
| 9 | generic-y += scatterlist.h | ||
| 9 | generic-y += trace_clock.h | 10 | generic-y += trace_clock.h |
diff --git a/arch/mn10300/include/asm/scatterlist.h b/arch/mn10300/include/asm/scatterlist.h deleted file mode 100644 index 7baa4006008a..000000000000 --- a/arch/mn10300/include/asm/scatterlist.h +++ /dev/null | |||
| @@ -1,16 +0,0 @@ | |||
| 1 | /* MN10300 Scatterlist definitions | ||
| 2 | * | ||
| 3 | * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd. | ||
| 4 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public Licence | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the Licence, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | #ifndef _ASM_SCATTERLIST_H | ||
| 12 | #define _ASM_SCATTERLIST_H | ||
| 13 | |||
| 14 | #include <asm-generic/scatterlist.h> | ||
| 15 | |||
| 16 | #endif /* _ASM_SCATTERLIST_H */ | ||
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 80b94b0add1f..a577609f8ed6 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
| @@ -111,6 +111,7 @@ config PPC | |||
| 111 | select HAVE_DMA_API_DEBUG | 111 | select HAVE_DMA_API_DEBUG |
| 112 | select HAVE_OPROFILE | 112 | select HAVE_OPROFILE |
| 113 | select HAVE_DEBUG_KMEMLEAK | 113 | select HAVE_DEBUG_KMEMLEAK |
| 114 | select ARCH_HAS_SG_CHAIN | ||
| 114 | select GENERIC_ATOMIC64 if PPC32 | 115 | select GENERIC_ATOMIC64 if PPC32 |
| 115 | select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE | 116 | select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE |
| 116 | select HAVE_PERF_EVENTS | 117 | select HAVE_PERF_EVENTS |
| @@ -398,6 +399,8 @@ config PPC64_SUPPORTS_MEMORY_FAILURE | |||
| 398 | config KEXEC | 399 | config KEXEC |
| 399 | bool "kexec system call" | 400 | bool "kexec system call" |
| 400 | depends on (PPC_BOOK3S || FSL_BOOKE || (44x && !SMP)) | 401 | depends on (PPC_BOOK3S || FSL_BOOKE || (44x && !SMP)) |
| 402 | select CRYPTO | ||
| 403 | select CRYPTO_SHA256 | ||
| 401 | help | 404 | help |
| 402 | kexec is a system call that implements the ability to shutdown your | 405 | kexec is a system call that implements the ability to shutdown your |
| 403 | current kernel, and to start another kernel. It is like a reboot | 406 | current kernel, and to start another kernel. It is like a reboot |
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild index 3fb1bc432f4f..7f23f162ce9c 100644 --- a/arch/powerpc/include/asm/Kbuild +++ b/arch/powerpc/include/asm/Kbuild | |||
| @@ -4,5 +4,6 @@ generic-y += hash.h | |||
| 4 | generic-y += mcs_spinlock.h | 4 | generic-y += mcs_spinlock.h |
| 5 | generic-y += preempt.h | 5 | generic-y += preempt.h |
| 6 | generic-y += rwsem.h | 6 | generic-y += rwsem.h |
| 7 | generic-y += scatterlist.h | ||
| 7 | generic-y += trace_clock.h | 8 | generic-y += trace_clock.h |
| 8 | generic-y += vtime.h | 9 | generic-y += vtime.h |
diff --git a/arch/powerpc/include/asm/page.h b/arch/powerpc/include/asm/page.h index 32e4e212b9c1..26fe1ae15212 100644 --- a/arch/powerpc/include/asm/page.h +++ b/arch/powerpc/include/asm/page.h | |||
| @@ -48,9 +48,6 @@ extern unsigned int HPAGE_SHIFT; | |||
| 48 | #define HUGE_MAX_HSTATE (MMU_PAGE_COUNT-1) | 48 | #define HUGE_MAX_HSTATE (MMU_PAGE_COUNT-1) |
| 49 | #endif | 49 | #endif |
| 50 | 50 | ||
| 51 | /* We do define AT_SYSINFO_EHDR but don't use the gate mechanism */ | ||
| 52 | #define __HAVE_ARCH_GATE_AREA 1 | ||
| 53 | |||
| 54 | /* | 51 | /* |
| 55 | * Subtle: (1 << PAGE_SHIFT) is an int, not an unsigned long. So if we | 52 | * Subtle: (1 << PAGE_SHIFT) is an int, not an unsigned long. So if we |
| 56 | * assign PAGE_MASK to a larger type it gets extended the way we want | 53 | * assign PAGE_MASK to a larger type it gets extended the way we want |
diff --git a/arch/powerpc/include/asm/scatterlist.h b/arch/powerpc/include/asm/scatterlist.h deleted file mode 100644 index de1f620bd5c9..000000000000 --- a/arch/powerpc/include/asm/scatterlist.h +++ /dev/null | |||
| @@ -1,17 +0,0 @@ | |||
| 1 | #ifndef _ASM_POWERPC_SCATTERLIST_H | ||
| 2 | #define _ASM_POWERPC_SCATTERLIST_H | ||
| 3 | /* | ||
| 4 | * Copyright (C) 2001 PPC64 Team, IBM Corp | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the License, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <asm/dma.h> | ||
| 13 | #include <asm-generic/scatterlist.h> | ||
| 14 | |||
| 15 | #define ARCH_HAS_SG_CHAIN | ||
| 16 | |||
| 17 | #endif /* _ASM_POWERPC_SCATTERLIST_H */ | ||
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index d0225572faa1..75d62d63fe68 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
| @@ -149,13 +149,13 @@ static void check_smt_enabled(void) | |||
| 149 | else if (!strcmp(smt_enabled_cmdline, "off")) | 149 | else if (!strcmp(smt_enabled_cmdline, "off")) |
| 150 | smt_enabled_at_boot = 0; | 150 | smt_enabled_at_boot = 0; |
| 151 | else { | 151 | else { |
| 152 | long smt; | 152 | int smt; |
| 153 | int rc; | 153 | int rc; |
| 154 | 154 | ||
| 155 | rc = strict_strtol(smt_enabled_cmdline, 10, &smt); | 155 | rc = kstrtoint(smt_enabled_cmdline, 10, &smt); |
| 156 | if (!rc) | 156 | if (!rc) |
| 157 | smt_enabled_at_boot = | 157 | smt_enabled_at_boot = |
| 158 | min(threads_per_core, (int)smt); | 158 | min(threads_per_core, smt); |
| 159 | } | 159 | } |
| 160 | } else { | 160 | } else { |
| 161 | dn = of_find_node_by_path("/options"); | 161 | dn = of_find_node_by_path("/options"); |
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index ce74c335a6a4..f174351842cf 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c | |||
| @@ -840,19 +840,3 @@ static int __init vdso_init(void) | |||
| 840 | return 0; | 840 | return 0; |
| 841 | } | 841 | } |
| 842 | arch_initcall(vdso_init); | 842 | arch_initcall(vdso_init); |
| 843 | |||
| 844 | int in_gate_area_no_mm(unsigned long addr) | ||
| 845 | { | ||
| 846 | return 0; | ||
| 847 | } | ||
| 848 | |||
| 849 | int in_gate_area(struct mm_struct *mm, unsigned long addr) | ||
| 850 | { | ||
| 851 | return 0; | ||
| 852 | } | ||
| 853 | |||
| 854 | struct vm_area_struct *get_gate_vma(struct mm_struct *mm) | ||
| 855 | { | ||
| 856 | return NULL; | ||
| 857 | } | ||
| 858 | |||
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index 904c66128fae..5bfdab9047be 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c | |||
| @@ -977,7 +977,7 @@ static ssize_t viodev_cmo_desired_set(struct device *dev, | |||
| 977 | size_t new_desired; | 977 | size_t new_desired; |
| 978 | int ret; | 978 | int ret; |
| 979 | 979 | ||
| 980 | ret = strict_strtoul(buf, 10, &new_desired); | 980 | ret = kstrtoul(buf, 10, &new_desired); |
| 981 | if (ret) | 981 | if (ret) |
| 982 | return ret; | 982 | return ret; |
| 983 | 983 | ||
diff --git a/arch/powerpc/mm/dma-noncoherent.c b/arch/powerpc/mm/dma-noncoherent.c index 7b6c10750179..d85e86aac7fb 100644 --- a/arch/powerpc/mm/dma-noncoherent.c +++ b/arch/powerpc/mm/dma-noncoherent.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #include <linux/export.h> | 33 | #include <linux/export.h> |
| 34 | 34 | ||
| 35 | #include <asm/tlbflush.h> | 35 | #include <asm/tlbflush.h> |
| 36 | #include <asm/dma.h> | ||
| 36 | 37 | ||
| 37 | #include "mmu_decl.h" | 38 | #include "mmu_decl.h" |
| 38 | 39 | ||
diff --git a/arch/powerpc/platforms/44x/warp.c b/arch/powerpc/platforms/44x/warp.c index 534574a97ec9..3a104284b338 100644 --- a/arch/powerpc/platforms/44x/warp.c +++ b/arch/powerpc/platforms/44x/warp.c | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | #include <asm/time.h> | 25 | #include <asm/time.h> |
| 26 | #include <asm/uic.h> | 26 | #include <asm/uic.h> |
| 27 | #include <asm/ppc4xx.h> | 27 | #include <asm/ppc4xx.h> |
| 28 | #include <asm/dma.h> | ||
| 28 | 29 | ||
| 29 | 30 | ||
| 30 | static __initdata struct of_device_id warp_of_bus[] = { | 31 | static __initdata struct of_device_id warp_of_bus[] = { |
diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c index 6e19b0ad5d26..3feffde9128d 100644 --- a/arch/powerpc/platforms/52xx/efika.c +++ b/arch/powerpc/platforms/52xx/efika.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <generated/utsrelease.h> | 13 | #include <generated/utsrelease.h> |
| 14 | #include <linux/pci.h> | 14 | #include <linux/pci.h> |
| 15 | #include <linux/of.h> | 15 | #include <linux/of.h> |
| 16 | #include <asm/dma.h> | ||
| 16 | #include <asm/prom.h> | 17 | #include <asm/prom.h> |
| 17 | #include <asm/time.h> | 18 | #include <asm/time.h> |
| 18 | #include <asm/machdep.h> | 19 | #include <asm/machdep.h> |
diff --git a/arch/powerpc/platforms/amigaone/setup.c b/arch/powerpc/platforms/amigaone/setup.c index 03aabc0e16ac..2fe12046279e 100644 --- a/arch/powerpc/platforms/amigaone/setup.c +++ b/arch/powerpc/platforms/amigaone/setup.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <asm/i8259.h> | 24 | #include <asm/i8259.h> |
| 25 | #include <asm/time.h> | 25 | #include <asm/time.h> |
| 26 | #include <asm/udbg.h> | 26 | #include <asm/udbg.h> |
| 27 | #include <asm/dma.h> | ||
| 27 | 28 | ||
| 28 | extern void __flush_disable_L1(void); | 29 | extern void __flush_disable_L1(void); |
| 29 | 30 | ||
diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c index 2d0b4d68a40a..a2450b8a50a5 100644 --- a/arch/powerpc/platforms/pseries/dlpar.c +++ b/arch/powerpc/platforms/pseries/dlpar.c | |||
| @@ -400,10 +400,10 @@ out: | |||
| 400 | static ssize_t dlpar_cpu_probe(const char *buf, size_t count) | 400 | static ssize_t dlpar_cpu_probe(const char *buf, size_t count) |
| 401 | { | 401 | { |
| 402 | struct device_node *dn, *parent; | 402 | struct device_node *dn, *parent; |
| 403 | unsigned long drc_index; | 403 | u32 drc_index; |
| 404 | int rc; | 404 | int rc; |
| 405 | 405 | ||
| 406 | rc = strict_strtoul(buf, 0, &drc_index); | 406 | rc = kstrtou32(buf, 0, &drc_index); |
| 407 | if (rc) | 407 | if (rc) |
| 408 | return -EINVAL; | 408 | return -EINVAL; |
| 409 | 409 | ||
diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c index d146fef038b8..e7cb6d4a871a 100644 --- a/arch/powerpc/platforms/pseries/mobility.c +++ b/arch/powerpc/platforms/pseries/mobility.c | |||
| @@ -320,7 +320,7 @@ static ssize_t migrate_store(struct class *class, struct class_attribute *attr, | |||
| 320 | u64 streamid; | 320 | u64 streamid; |
| 321 | int rc; | 321 | int rc; |
| 322 | 322 | ||
| 323 | rc = strict_strtoull(buf, 0, &streamid); | 323 | rc = kstrtou64(buf, 0, &streamid); |
| 324 | if (rc) | 324 | if (rc) |
| 325 | return rc; | 325 | return rc; |
| 326 | 326 | ||
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 8ca60f8d5683..ab39ceb89ecf 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig | |||
| @@ -48,6 +48,8 @@ config ARCH_SUPPORTS_DEBUG_PAGEALLOC | |||
| 48 | 48 | ||
| 49 | config KEXEC | 49 | config KEXEC |
| 50 | def_bool y | 50 | def_bool y |
| 51 | select CRYPTO | ||
| 52 | select CRYPTO_SHA256 | ||
| 51 | 53 | ||
| 52 | config AUDIT_ARCH | 54 | config AUDIT_ARCH |
| 53 | def_bool y | 55 | def_bool y |
| @@ -145,6 +147,7 @@ config S390 | |||
| 145 | select TTY | 147 | select TTY |
| 146 | select VIRT_CPU_ACCOUNTING | 148 | select VIRT_CPU_ACCOUNTING |
| 147 | select VIRT_TO_BUS | 149 | select VIRT_TO_BUS |
| 150 | select ARCH_HAS_SG_CHAIN | ||
| 148 | 151 | ||
| 149 | config SCHED_OMIT_FRAME_POINTER | 152 | config SCHED_OMIT_FRAME_POINTER |
| 150 | def_bool y | 153 | def_bool y |
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild index 57892a8a9055..b3fea0722ff1 100644 --- a/arch/s390/include/asm/Kbuild +++ b/arch/s390/include/asm/Kbuild | |||
| @@ -4,4 +4,5 @@ generic-y += clkdev.h | |||
| 4 | generic-y += hash.h | 4 | generic-y += hash.h |
| 5 | generic-y += mcs_spinlock.h | 5 | generic-y += mcs_spinlock.h |
| 6 | generic-y += preempt.h | 6 | generic-y += preempt.h |
| 7 | generic-y += scatterlist.h | ||
| 7 | generic-y += trace_clock.h | 8 | generic-y += trace_clock.h |
diff --git a/arch/s390/include/asm/page.h b/arch/s390/include/asm/page.h index 114258eeaacd..7b2ac6e44166 100644 --- a/arch/s390/include/asm/page.h +++ b/arch/s390/include/asm/page.h | |||
| @@ -162,6 +162,4 @@ static inline int devmem_is_allowed(unsigned long pfn) | |||
| 162 | #include <asm-generic/memory_model.h> | 162 | #include <asm-generic/memory_model.h> |
| 163 | #include <asm-generic/getorder.h> | 163 | #include <asm-generic/getorder.h> |
| 164 | 164 | ||
| 165 | #define __HAVE_ARCH_GATE_AREA 1 | ||
| 166 | |||
| 167 | #endif /* _S390_PAGE_H */ | 165 | #endif /* _S390_PAGE_H */ |
diff --git a/arch/s390/include/asm/scatterlist.h b/arch/s390/include/asm/scatterlist.h deleted file mode 100644 index 6d45ef6c12a7..000000000000 --- a/arch/s390/include/asm/scatterlist.h +++ /dev/null | |||
| @@ -1,3 +0,0 @@ | |||
| 1 | #include <asm-generic/scatterlist.h> | ||
| 2 | |||
| 3 | #define ARCH_HAS_SG_CHAIN | ||
diff --git a/arch/s390/kernel/vdso.c b/arch/s390/kernel/vdso.c index 613649096783..0bbb7e027c5a 100644 --- a/arch/s390/kernel/vdso.c +++ b/arch/s390/kernel/vdso.c | |||
| @@ -316,18 +316,3 @@ static int __init vdso_init(void) | |||
| 316 | return 0; | 316 | return 0; |
| 317 | } | 317 | } |
| 318 | early_initcall(vdso_init); | 318 | early_initcall(vdso_init); |
| 319 | |||
| 320 | int in_gate_area_no_mm(unsigned long addr) | ||
| 321 | { | ||
| 322 | return 0; | ||
| 323 | } | ||
| 324 | |||
| 325 | int in_gate_area(struct mm_struct *mm, unsigned long addr) | ||
| 326 | { | ||
| 327 | return 0; | ||
| 328 | } | ||
| 329 | |||
| 330 | struct vm_area_struct *get_gate_vma(struct mm_struct *mm) | ||
| 331 | { | ||
| 332 | return NULL; | ||
| 333 | } | ||
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild index 2f947aba4bd4..aad209199f7e 100644 --- a/arch/score/include/asm/Kbuild +++ b/arch/score/include/asm/Kbuild | |||
| @@ -8,5 +8,6 @@ generic-y += cputime.h | |||
| 8 | generic-y += hash.h | 8 | generic-y += hash.h |
| 9 | generic-y += mcs_spinlock.h | 9 | generic-y += mcs_spinlock.h |
| 10 | generic-y += preempt.h | 10 | generic-y += preempt.h |
| 11 | generic-y += scatterlist.h | ||
| 11 | generic-y += trace_clock.h | 12 | generic-y += trace_clock.h |
| 12 | generic-y += xor.h | 13 | generic-y += xor.h |
diff --git a/arch/score/include/asm/scatterlist.h b/arch/score/include/asm/scatterlist.h deleted file mode 100644 index 9f533b8362c7..000000000000 --- a/arch/score/include/asm/scatterlist.h +++ /dev/null | |||
| @@ -1,6 +0,0 @@ | |||
| 1 | #ifndef _ASM_SCORE_SCATTERLIST_H | ||
| 2 | #define _ASM_SCORE_SCATTERLIST_H | ||
| 3 | |||
| 4 | #include <asm-generic/scatterlist.h> | ||
| 5 | |||
| 6 | #endif /* _ASM_SCORE_SCATTERLIST_H */ | ||
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index aa2df3eaeb29..453fa5c09550 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig | |||
| @@ -595,6 +595,8 @@ source kernel/Kconfig.hz | |||
| 595 | config KEXEC | 595 | config KEXEC |
| 596 | bool "kexec system call (EXPERIMENTAL)" | 596 | bool "kexec system call (EXPERIMENTAL)" |
| 597 | depends on SUPERH32 && MMU | 597 | depends on SUPERH32 && MMU |
| 598 | select CRYPTO | ||
| 599 | select CRYPTO_SHA256 | ||
| 598 | help | 600 | help |
| 599 | kexec is a system call that implements the ability to shutdown your | 601 | kexec is a system call that implements the ability to shutdown your |
| 600 | current kernel, and to start another kernel. It is like a reboot | 602 | current kernel, and to start another kernel. It is like a reboot |
diff --git a/arch/sh/include/asm/page.h b/arch/sh/include/asm/page.h index 15d970328f71..fe20d14ae051 100644 --- a/arch/sh/include/asm/page.h +++ b/arch/sh/include/asm/page.h | |||
| @@ -186,11 +186,6 @@ typedef struct page *pgtable_t; | |||
| 186 | #include <asm-generic/memory_model.h> | 186 | #include <asm-generic/memory_model.h> |
| 187 | #include <asm-generic/getorder.h> | 187 | #include <asm-generic/getorder.h> |
| 188 | 188 | ||
| 189 | /* vDSO support */ | ||
| 190 | #ifdef CONFIG_VSYSCALL | ||
| 191 | #define __HAVE_ARCH_GATE_AREA | ||
| 192 | #endif | ||
| 193 | |||
| 194 | /* | 189 | /* |
| 195 | * Some drivers need to perform DMA into kmalloc'ed buffers | 190 | * Some drivers need to perform DMA into kmalloc'ed buffers |
| 196 | * and so we have to increase the kmalloc minalign for this. | 191 | * and so we have to increase the kmalloc minalign for this. |
diff --git a/arch/sh/kernel/vsyscall/vsyscall.c b/arch/sh/kernel/vsyscall/vsyscall.c index 5ca579720a09..ea2aa1393b87 100644 --- a/arch/sh/kernel/vsyscall/vsyscall.c +++ b/arch/sh/kernel/vsyscall/vsyscall.c | |||
| @@ -92,18 +92,3 @@ const char *arch_vma_name(struct vm_area_struct *vma) | |||
| 92 | 92 | ||
| 93 | return NULL; | 93 | return NULL; |
| 94 | } | 94 | } |
| 95 | |||
| 96 | struct vm_area_struct *get_gate_vma(struct mm_struct *mm) | ||
| 97 | { | ||
| 98 | return NULL; | ||
| 99 | } | ||
| 100 | |||
| 101 | int in_gate_area(struct mm_struct *mm, unsigned long address) | ||
| 102 | { | ||
| 103 | return 0; | ||
| 104 | } | ||
| 105 | |||
| 106 | int in_gate_area_no_mm(unsigned long address) | ||
| 107 | { | ||
| 108 | return 0; | ||
| 109 | } | ||
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 4692c90936f1..a537816613f9 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig | |||
| @@ -42,6 +42,7 @@ config SPARC | |||
| 42 | select MODULES_USE_ELF_RELA | 42 | select MODULES_USE_ELF_RELA |
| 43 | select ODD_RT_SIGACTION | 43 | select ODD_RT_SIGACTION |
| 44 | select OLD_SIGSUSPEND | 44 | select OLD_SIGSUSPEND |
| 45 | select ARCH_HAS_SG_CHAIN | ||
| 45 | 46 | ||
| 46 | config SPARC32 | 47 | config SPARC32 |
| 47 | def_bool !64BIT | 48 | def_bool !64BIT |
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild index a45821818003..cdd1b447bb6c 100644 --- a/arch/sparc/include/asm/Kbuild +++ b/arch/sparc/include/asm/Kbuild | |||
| @@ -15,6 +15,7 @@ generic-y += mcs_spinlock.h | |||
| 15 | generic-y += module.h | 15 | generic-y += module.h |
| 16 | generic-y += mutex.h | 16 | generic-y += mutex.h |
| 17 | generic-y += preempt.h | 17 | generic-y += preempt.h |
| 18 | generic-y += scatterlist.h | ||
| 18 | generic-y += serial.h | 19 | generic-y += serial.h |
| 19 | generic-y += trace_clock.h | 20 | generic-y += trace_clock.h |
| 20 | generic-y += types.h | 21 | generic-y += types.h |
diff --git a/arch/sparc/include/asm/scatterlist.h b/arch/sparc/include/asm/scatterlist.h deleted file mode 100644 index 92bb638313f8..000000000000 --- a/arch/sparc/include/asm/scatterlist.h +++ /dev/null | |||
| @@ -1,8 +0,0 @@ | |||
| 1 | #ifndef _SPARC_SCATTERLIST_H | ||
| 2 | #define _SPARC_SCATTERLIST_H | ||
| 3 | |||
| 4 | #include <asm-generic/scatterlist.h> | ||
| 5 | |||
| 6 | #define ARCH_HAS_SG_CHAIN | ||
| 7 | |||
| 8 | #endif /* !(_SPARC_SCATTERLIST_H) */ | ||
diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig index 7fcd492adbfc..a3ffe2dd4832 100644 --- a/arch/tile/Kconfig +++ b/arch/tile/Kconfig | |||
| @@ -191,6 +191,8 @@ source "kernel/Kconfig.hz" | |||
| 191 | 191 | ||
| 192 | config KEXEC | 192 | config KEXEC |
| 193 | bool "kexec system call" | 193 | bool "kexec system call" |
| 194 | select CRYPTO | ||
| 195 | select CRYPTO_SHA256 | ||
| 194 | ---help--- | 196 | ---help--- |
| 195 | kexec is a system call that implements the ability to shutdown your | 197 | kexec is a system call that implements the ability to shutdown your |
| 196 | current kernel, and to start another kernel. It is like a reboot | 198 | current kernel, and to start another kernel. It is like a reboot |
diff --git a/arch/tile/include/asm/hardwall.h b/arch/tile/include/asm/hardwall.h index 2f572b6b7bc2..44d2765bde2b 100644 --- a/arch/tile/include/asm/hardwall.h +++ b/arch/tile/include/asm/hardwall.h | |||
| @@ -23,7 +23,7 @@ | |||
| 23 | struct proc_dir_entry; | 23 | struct proc_dir_entry; |
| 24 | #ifdef CONFIG_HARDWALL | 24 | #ifdef CONFIG_HARDWALL |
| 25 | void proc_tile_hardwall_init(struct proc_dir_entry *root); | 25 | void proc_tile_hardwall_init(struct proc_dir_entry *root); |
| 26 | int proc_pid_hardwall(struct task_struct *task, char *buffer); | 26 | int proc_pid_hardwall(struct seq_file *m, struct pid_namespace *ns, struct pid *pid, struct task_struct *task); |
| 27 | #else | 27 | #else |
| 28 | static inline void proc_tile_hardwall_init(struct proc_dir_entry *root) {} | 28 | static inline void proc_tile_hardwall_init(struct proc_dir_entry *root) {} |
| 29 | #endif | 29 | #endif |
diff --git a/arch/tile/include/asm/page.h b/arch/tile/include/asm/page.h index 672768008618..a213a8d84a95 100644 --- a/arch/tile/include/asm/page.h +++ b/arch/tile/include/asm/page.h | |||
| @@ -39,12 +39,6 @@ | |||
| 39 | #define HPAGE_MASK (~(HPAGE_SIZE - 1)) | 39 | #define HPAGE_MASK (~(HPAGE_SIZE - 1)) |
| 40 | 40 | ||
| 41 | /* | 41 | /* |
| 42 | * We do define AT_SYSINFO_EHDR to support vDSO, | ||
| 43 | * but don't use the gate mechanism. | ||
| 44 | */ | ||
| 45 | #define __HAVE_ARCH_GATE_AREA 1 | ||
| 46 | |||
| 47 | /* | ||
| 48 | * If the Kconfig doesn't specify, set a maximum zone order that | 42 | * If the Kconfig doesn't specify, set a maximum zone order that |
| 49 | * is enough so that we can create huge pages from small pages given | 43 | * is enough so that we can create huge pages from small pages given |
| 50 | * the respective sizes of the two page types. See <linux/mmzone.h>. | 44 | * the respective sizes of the two page types. See <linux/mmzone.h>. |
diff --git a/arch/tile/kernel/hardwall.c b/arch/tile/kernel/hardwall.c index 531f4c365351..aca6000bca75 100644 --- a/arch/tile/kernel/hardwall.c +++ b/arch/tile/kernel/hardwall.c | |||
| @@ -947,15 +947,15 @@ static void hardwall_remove_proc(struct hardwall_info *info) | |||
| 947 | remove_proc_entry(buf, info->type->proc_dir); | 947 | remove_proc_entry(buf, info->type->proc_dir); |
| 948 | } | 948 | } |
| 949 | 949 | ||
| 950 | int proc_pid_hardwall(struct task_struct *task, char *buffer) | 950 | int proc_pid_hardwall(struct seq_file *m, struct pid_namespace *ns, |
| 951 | struct pid *pid, struct task_struct *task) | ||
| 951 | { | 952 | { |
| 952 | int i; | 953 | int i; |
| 953 | int n = 0; | 954 | int n = 0; |
| 954 | for (i = 0; i < HARDWALL_TYPES; ++i) { | 955 | for (i = 0; i < HARDWALL_TYPES; ++i) { |
| 955 | struct hardwall_info *info = task->thread.hardwall[i].info; | 956 | struct hardwall_info *info = task->thread.hardwall[i].info; |
| 956 | if (info) | 957 | if (info) |
| 957 | n += sprintf(&buffer[n], "%s: %d\n", | 958 | seq_printf(m, "%s: %d\n", info->type->name, info->id); |
| 958 | info->type->name, info->id); | ||
| 959 | } | 959 | } |
| 960 | return n; | 960 | return n; |
| 961 | } | 961 | } |
diff --git a/arch/tile/kernel/vdso.c b/arch/tile/kernel/vdso.c index 1533af24106e..5bc51d7dfdcb 100644 --- a/arch/tile/kernel/vdso.c +++ b/arch/tile/kernel/vdso.c | |||
| @@ -121,21 +121,6 @@ const char *arch_vma_name(struct vm_area_struct *vma) | |||
| 121 | return NULL; | 121 | return NULL; |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | struct vm_area_struct *get_gate_vma(struct mm_struct *mm) | ||
| 125 | { | ||
| 126 | return NULL; | ||
| 127 | } | ||
| 128 | |||
| 129 | int in_gate_area(struct mm_struct *mm, unsigned long address) | ||
| 130 | { | ||
| 131 | return 0; | ||
| 132 | } | ||
| 133 | |||
| 134 | int in_gate_area_no_mm(unsigned long address) | ||
| 135 | { | ||
| 136 | return 0; | ||
| 137 | } | ||
| 138 | |||
| 139 | int setup_vdso_pages(void) | 124 | int setup_vdso_pages(void) |
| 140 | { | 125 | { |
| 141 | struct page **pagelist; | 126 | struct page **pagelist; |
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild index a5e4b6068213..7bd64aa2e94a 100644 --- a/arch/um/include/asm/Kbuild +++ b/arch/um/include/asm/Kbuild | |||
| @@ -21,6 +21,7 @@ generic-y += param.h | |||
| 21 | generic-y += pci.h | 21 | generic-y += pci.h |
| 22 | generic-y += percpu.h | 22 | generic-y += percpu.h |
| 23 | generic-y += preempt.h | 23 | generic-y += preempt.h |
| 24 | generic-y += scatterlist.h | ||
| 24 | generic-y += sections.h | 25 | generic-y += sections.h |
| 25 | generic-y += switch_to.h | 26 | generic-y += switch_to.h |
| 26 | generic-y += topology.h | 27 | generic-y += topology.h |
diff --git a/arch/um/include/asm/page.h b/arch/um/include/asm/page.h index 5ff53d9185f7..71c5d132062a 100644 --- a/arch/um/include/asm/page.h +++ b/arch/um/include/asm/page.h | |||
| @@ -119,4 +119,9 @@ extern unsigned long uml_physmem; | |||
| 119 | #include <asm-generic/getorder.h> | 119 | #include <asm-generic/getorder.h> |
| 120 | 120 | ||
| 121 | #endif /* __ASSEMBLY__ */ | 121 | #endif /* __ASSEMBLY__ */ |
| 122 | |||
| 123 | #ifdef CONFIG_X86_32 | ||
| 124 | #define __HAVE_ARCH_GATE_AREA 1 | ||
| 125 | #endif | ||
| 126 | |||
| 122 | #endif /* __UM_PAGE_H */ | 127 | #endif /* __UM_PAGE_H */ |
diff --git a/arch/x86/Kbuild b/arch/x86/Kbuild index e5287d8517aa..61b6d51866f8 100644 --- a/arch/x86/Kbuild +++ b/arch/x86/Kbuild | |||
| @@ -16,3 +16,7 @@ obj-$(CONFIG_IA32_EMULATION) += ia32/ | |||
| 16 | 16 | ||
| 17 | obj-y += platform/ | 17 | obj-y += platform/ |
| 18 | obj-y += net/ | 18 | obj-y += net/ |
| 19 | |||
| 20 | ifeq ($(CONFIG_X86_64),y) | ||
| 21 | obj-$(CONFIG_KEXEC) += purgatory/ | ||
| 22 | endif | ||
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index bf2405053af5..4aafd322e21e 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
| @@ -96,6 +96,7 @@ config X86 | |||
| 96 | select IRQ_FORCED_THREADING | 96 | select IRQ_FORCED_THREADING |
| 97 | select HAVE_BPF_JIT if X86_64 | 97 | select HAVE_BPF_JIT if X86_64 |
| 98 | select HAVE_ARCH_TRANSPARENT_HUGEPAGE | 98 | select HAVE_ARCH_TRANSPARENT_HUGEPAGE |
| 99 | select ARCH_HAS_SG_CHAIN | ||
| 99 | select CLKEVT_I8253 | 100 | select CLKEVT_I8253 |
| 100 | select ARCH_HAVE_NMI_SAFE_CMPXCHG | 101 | select ARCH_HAVE_NMI_SAFE_CMPXCHG |
| 101 | select GENERIC_IOMAP | 102 | select GENERIC_IOMAP |
| @@ -1581,6 +1582,9 @@ source kernel/Kconfig.hz | |||
| 1581 | 1582 | ||
| 1582 | config KEXEC | 1583 | config KEXEC |
| 1583 | bool "kexec system call" | 1584 | bool "kexec system call" |
| 1585 | select BUILD_BIN2C | ||
| 1586 | select CRYPTO | ||
| 1587 | select CRYPTO_SHA256 | ||
| 1584 | ---help--- | 1588 | ---help--- |
| 1585 | kexec is a system call that implements the ability to shutdown your | 1589 | kexec is a system call that implements the ability to shutdown your |
| 1586 | current kernel, and to start another kernel. It is like a reboot | 1590 | current kernel, and to start another kernel. It is like a reboot |
| @@ -1595,6 +1599,28 @@ config KEXEC | |||
| 1595 | interface is strongly in flux, so no good recommendation can be | 1599 | interface is strongly in flux, so no good recommendation can be |
| 1596 | made. | 1600 | made. |
| 1597 | 1601 | ||
| 1602 | config KEXEC_VERIFY_SIG | ||
| 1603 | bool "Verify kernel signature during kexec_file_load() syscall" | ||
| 1604 | depends on KEXEC | ||
| 1605 | ---help--- | ||
| 1606 | This option makes kernel signature verification mandatory for | ||
| 1607 | kexec_file_load() syscall. If kernel is signature can not be | ||
| 1608 | verified, kexec_file_load() will fail. | ||
| 1609 | |||
| 1610 | This option enforces signature verification at generic level. | ||
| 1611 | One needs to enable signature verification for type of kernel | ||
| 1612 | image being loaded to make sure it works. For example, enable | ||
| 1613 | bzImage signature verification option to be able to load and | ||
| 1614 | verify signatures of bzImage. Otherwise kernel loading will fail. | ||
| 1615 | |||
| 1616 | config KEXEC_BZIMAGE_VERIFY_SIG | ||
| 1617 | bool "Enable bzImage signature verification support" | ||
| 1618 | depends on KEXEC_VERIFY_SIG | ||
| 1619 | depends on SIGNED_PE_FILE_VERIFICATION | ||
| 1620 | select SYSTEM_TRUSTED_KEYRING | ||
| 1621 | ---help--- | ||
| 1622 | Enable bzImage signature verification support. | ||
| 1623 | |||
| 1598 | config CRASH_DUMP | 1624 | config CRASH_DUMP |
| 1599 | bool "kernel crash dumps" | 1625 | bool "kernel crash dumps" |
| 1600 | depends on X86_64 || (X86_32 && HIGHMEM) | 1626 | depends on X86_64 || (X86_32 && HIGHMEM) |
diff --git a/arch/x86/Makefile b/arch/x86/Makefile index c65fd9650467..c1aa36887843 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile | |||
| @@ -183,6 +183,14 @@ archscripts: scripts_basic | |||
| 183 | archheaders: | 183 | archheaders: |
| 184 | $(Q)$(MAKE) $(build)=arch/x86/syscalls all | 184 | $(Q)$(MAKE) $(build)=arch/x86/syscalls all |
| 185 | 185 | ||
| 186 | archprepare: | ||
| 187 | ifeq ($(CONFIG_KEXEC),y) | ||
| 188 | # Build only for 64bit. No loaders for 32bit yet. | ||
| 189 | ifeq ($(CONFIG_X86_64),y) | ||
| 190 | $(Q)$(MAKE) $(build)=arch/x86/purgatory arch/x86/purgatory/kexec-purgatory.c | ||
| 191 | endif | ||
| 192 | endif | ||
| 193 | |||
| 186 | ### | 194 | ### |
| 187 | # Kernel objects | 195 | # Kernel objects |
| 188 | 196 | ||
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild index 3ca9762e1649..3bf000fab0ae 100644 --- a/arch/x86/include/asm/Kbuild +++ b/arch/x86/include/asm/Kbuild | |||
| @@ -5,6 +5,7 @@ genhdr-y += unistd_64.h | |||
| 5 | genhdr-y += unistd_x32.h | 5 | genhdr-y += unistd_x32.h |
| 6 | 6 | ||
| 7 | generic-y += clkdev.h | 7 | generic-y += clkdev.h |
| 8 | generic-y += early_ioremap.h | ||
| 9 | generic-y += cputime.h | 8 | generic-y += cputime.h |
| 9 | generic-y += early_ioremap.h | ||
| 10 | generic-y += mcs_spinlock.h | 10 | generic-y += mcs_spinlock.h |
| 11 | generic-y += scatterlist.h | ||
diff --git a/arch/x86/include/asm/crash.h b/arch/x86/include/asm/crash.h new file mode 100644 index 000000000000..f498411f2500 --- /dev/null +++ b/arch/x86/include/asm/crash.h | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | #ifndef _ASM_X86_CRASH_H | ||
| 2 | #define _ASM_X86_CRASH_H | ||
| 3 | |||
| 4 | int crash_load_segments(struct kimage *image); | ||
| 5 | int crash_copy_backup_region(struct kimage *image); | ||
| 6 | int crash_setup_memmap_entries(struct kimage *image, | ||
| 7 | struct boot_params *params); | ||
| 8 | |||
| 9 | #endif /* _ASM_X86_CRASH_H */ | ||
diff --git a/arch/x86/include/asm/kexec-bzimage64.h b/arch/x86/include/asm/kexec-bzimage64.h new file mode 100644 index 000000000000..d1b5d194e31d --- /dev/null +++ b/arch/x86/include/asm/kexec-bzimage64.h | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | #ifndef _ASM_KEXEC_BZIMAGE64_H | ||
| 2 | #define _ASM_KEXEC_BZIMAGE64_H | ||
| 3 | |||
| 4 | extern struct kexec_file_ops kexec_bzImage64_ops; | ||
| 5 | |||
| 6 | #endif /* _ASM_KEXE_BZIMAGE64_H */ | ||
diff --git a/arch/x86/include/asm/kexec.h b/arch/x86/include/asm/kexec.h index 17483a492f18..d2434c1cad05 100644 --- a/arch/x86/include/asm/kexec.h +++ b/arch/x86/include/asm/kexec.h | |||
| @@ -23,6 +23,9 @@ | |||
| 23 | 23 | ||
| 24 | #include <asm/page.h> | 24 | #include <asm/page.h> |
| 25 | #include <asm/ptrace.h> | 25 | #include <asm/ptrace.h> |
| 26 | #include <asm/bootparam.h> | ||
| 27 | |||
| 28 | struct kimage; | ||
| 26 | 29 | ||
| 27 | /* | 30 | /* |
| 28 | * KEXEC_SOURCE_MEMORY_LIMIT maximum page get_free_page can return. | 31 | * KEXEC_SOURCE_MEMORY_LIMIT maximum page get_free_page can return. |
| @@ -61,6 +64,10 @@ | |||
| 61 | # define KEXEC_ARCH KEXEC_ARCH_X86_64 | 64 | # define KEXEC_ARCH KEXEC_ARCH_X86_64 |
| 62 | #endif | 65 | #endif |
| 63 | 66 | ||
| 67 | /* Memory to backup during crash kdump */ | ||
| 68 | #define KEXEC_BACKUP_SRC_START (0UL) | ||
| 69 | #define KEXEC_BACKUP_SRC_END (640 * 1024UL) /* 640K */ | ||
| 70 | |||
| 64 | /* | 71 | /* |
| 65 | * CPU does not save ss and sp on stack if execution is already | 72 | * CPU does not save ss and sp on stack if execution is already |
| 66 | * running in kernel mode at the time of NMI occurrence. This code | 73 | * running in kernel mode at the time of NMI occurrence. This code |
| @@ -160,6 +167,44 @@ struct kimage_arch { | |||
| 160 | pud_t *pud; | 167 | pud_t *pud; |
| 161 | pmd_t *pmd; | 168 | pmd_t *pmd; |
| 162 | pte_t *pte; | 169 | pte_t *pte; |
| 170 | /* Details of backup region */ | ||
| 171 | unsigned long backup_src_start; | ||
| 172 | unsigned long backup_src_sz; | ||
| 173 | |||
| 174 | /* Physical address of backup segment */ | ||
| 175 | unsigned long backup_load_addr; | ||
| 176 | |||
| 177 | /* Core ELF header buffer */ | ||
| 178 | void *elf_headers; | ||
| 179 | unsigned long elf_headers_sz; | ||
| 180 | unsigned long elf_load_addr; | ||
| 181 | }; | ||
| 182 | #endif /* CONFIG_X86_32 */ | ||
| 183 | |||
| 184 | #ifdef CONFIG_X86_64 | ||
| 185 | /* | ||
| 186 | * Number of elements and order of elements in this structure should match | ||
| 187 | * with the ones in arch/x86/purgatory/entry64.S. If you make a change here | ||
| 188 | * make an appropriate change in purgatory too. | ||
| 189 | */ | ||
| 190 | struct kexec_entry64_regs { | ||
| 191 | uint64_t rax; | ||
| 192 | uint64_t rcx; | ||
| 193 | uint64_t rdx; | ||
| 194 | uint64_t rbx; | ||
| 195 | uint64_t rsp; | ||
| 196 | uint64_t rbp; | ||
| 197 | uint64_t rsi; | ||
| 198 | uint64_t rdi; | ||
| 199 | uint64_t r8; | ||
| 200 | uint64_t r9; | ||
| 201 | uint64_t r10; | ||
| 202 | uint64_t r11; | ||
| 203 | uint64_t r12; | ||
| 204 | uint64_t r13; | ||
| 205 | uint64_t r14; | ||
| 206 | uint64_t r15; | ||
| 207 | uint64_t rip; | ||
| 163 | }; | 208 | }; |
| 164 | #endif | 209 | #endif |
| 165 | 210 | ||
diff --git a/arch/x86/include/asm/page.h b/arch/x86/include/asm/page.h index 775873d3be55..802dde30c928 100644 --- a/arch/x86/include/asm/page.h +++ b/arch/x86/include/asm/page.h | |||
| @@ -70,7 +70,6 @@ extern bool __virt_addr_valid(unsigned long kaddr); | |||
| 70 | #include <asm-generic/memory_model.h> | 70 | #include <asm-generic/memory_model.h> |
| 71 | #include <asm-generic/getorder.h> | 71 | #include <asm-generic/getorder.h> |
| 72 | 72 | ||
| 73 | #define __HAVE_ARCH_GATE_AREA 1 | ||
| 74 | #define HAVE_ARCH_HUGETLB_UNMAPPED_AREA | 73 | #define HAVE_ARCH_HUGETLB_UNMAPPED_AREA |
| 75 | 74 | ||
| 76 | #endif /* __KERNEL__ */ | 75 | #endif /* __KERNEL__ */ |
diff --git a/arch/x86/include/asm/page_64.h b/arch/x86/include/asm/page_64.h index 0f1ddee6a0ce..f408caf73430 100644 --- a/arch/x86/include/asm/page_64.h +++ b/arch/x86/include/asm/page_64.h | |||
| @@ -39,4 +39,6 @@ void copy_page(void *to, void *from); | |||
| 39 | 39 | ||
| 40 | #endif /* !__ASSEMBLY__ */ | 40 | #endif /* !__ASSEMBLY__ */ |
| 41 | 41 | ||
| 42 | #define __HAVE_ARCH_GATE_AREA 1 | ||
| 43 | |||
| 42 | #endif /* _ASM_X86_PAGE_64_H */ | 44 | #endif /* _ASM_X86_PAGE_64_H */ |
diff --git a/arch/x86/include/asm/scatterlist.h b/arch/x86/include/asm/scatterlist.h deleted file mode 100644 index 4240878b9d76..000000000000 --- a/arch/x86/include/asm/scatterlist.h +++ /dev/null | |||
| @@ -1,8 +0,0 @@ | |||
| 1 | #ifndef _ASM_X86_SCATTERLIST_H | ||
| 2 | #define _ASM_X86_SCATTERLIST_H | ||
| 3 | |||
| 4 | #include <asm-generic/scatterlist.h> | ||
| 5 | |||
| 6 | #define ARCH_HAS_SG_CHAIN | ||
| 7 | |||
| 8 | #endif /* _ASM_X86_SCATTERLIST_H */ | ||
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index bde3993624f1..b5ea75c4a4b4 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile | |||
| @@ -118,4 +118,5 @@ ifeq ($(CONFIG_X86_64),y) | |||
| 118 | 118 | ||
| 119 | obj-$(CONFIG_PCI_MMCONFIG) += mmconf-fam10h_64.o | 119 | obj-$(CONFIG_PCI_MMCONFIG) += mmconf-fam10h_64.o |
| 120 | obj-y += vsmp_64.o | 120 | obj-y += vsmp_64.o |
| 121 | obj-$(CONFIG_KEXEC) += kexec-bzimage64.o | ||
| 121 | endif | 122 | endif |
diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index 9c8f7394c612..c7035073dfc1 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c | |||
| @@ -461,7 +461,7 @@ static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf, | |||
| 461 | 461 | ||
| 462 | cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map)); | 462 | cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map)); |
| 463 | 463 | ||
| 464 | if (strict_strtoul(buf, 10, &val) < 0) | 464 | if (kstrtoul(buf, 10, &val) < 0) |
| 465 | return -EINVAL; | 465 | return -EINVAL; |
| 466 | 466 | ||
| 467 | err = amd_set_l3_disable_slot(this_leaf->base.nb, cpu, slot, val); | 467 | err = amd_set_l3_disable_slot(this_leaf->base.nb, cpu, slot, val); |
| @@ -511,7 +511,7 @@ store_subcaches(struct _cpuid4_info *this_leaf, const char *buf, size_t count, | |||
| 511 | if (!this_leaf->base.nb || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING)) | 511 | if (!this_leaf->base.nb || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING)) |
| 512 | return -EINVAL; | 512 | return -EINVAL; |
| 513 | 513 | ||
| 514 | if (strict_strtoul(buf, 16, &val) < 0) | 514 | if (kstrtoul(buf, 16, &val) < 0) |
| 515 | return -EINVAL; | 515 | return -EINVAL; |
| 516 | 516 | ||
| 517 | if (amd_set_subcaches(cpu, val)) | 517 | if (amd_set_subcaches(cpu, val)) |
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 4fc57975acc1..bd9ccda8087f 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c | |||
| @@ -2136,7 +2136,7 @@ static ssize_t set_bank(struct device *s, struct device_attribute *attr, | |||
| 2136 | { | 2136 | { |
| 2137 | u64 new; | 2137 | u64 new; |
| 2138 | 2138 | ||
| 2139 | if (strict_strtoull(buf, 0, &new) < 0) | 2139 | if (kstrtou64(buf, 0, &new) < 0) |
| 2140 | return -EINVAL; | 2140 | return -EINVAL; |
| 2141 | 2141 | ||
| 2142 | attr_to_bank(attr)->ctl = new; | 2142 | attr_to_bank(attr)->ctl = new; |
| @@ -2174,7 +2174,7 @@ static ssize_t set_ignore_ce(struct device *s, | |||
| 2174 | { | 2174 | { |
| 2175 | u64 new; | 2175 | u64 new; |
| 2176 | 2176 | ||
| 2177 | if (strict_strtoull(buf, 0, &new) < 0) | 2177 | if (kstrtou64(buf, 0, &new) < 0) |
| 2178 | return -EINVAL; | 2178 | return -EINVAL; |
| 2179 | 2179 | ||
| 2180 | if (mca_cfg.ignore_ce ^ !!new) { | 2180 | if (mca_cfg.ignore_ce ^ !!new) { |
| @@ -2198,7 +2198,7 @@ static ssize_t set_cmci_disabled(struct device *s, | |||
| 2198 | { | 2198 | { |
| 2199 | u64 new; | 2199 | u64 new; |
| 2200 | 2200 | ||
| 2201 | if (strict_strtoull(buf, 0, &new) < 0) | 2201 | if (kstrtou64(buf, 0, &new) < 0) |
| 2202 | return -EINVAL; | 2202 | return -EINVAL; |
| 2203 | 2203 | ||
| 2204 | if (mca_cfg.cmci_disabled ^ !!new) { | 2204 | if (mca_cfg.cmci_disabled ^ !!new) { |
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index 603df4f74640..1e49f8f41276 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c | |||
| @@ -353,7 +353,7 @@ store_interrupt_enable(struct threshold_block *b, const char *buf, size_t size) | |||
| 353 | if (!b->interrupt_capable) | 353 | if (!b->interrupt_capable) |
| 354 | return -EINVAL; | 354 | return -EINVAL; |
| 355 | 355 | ||
| 356 | if (strict_strtoul(buf, 0, &new) < 0) | 356 | if (kstrtoul(buf, 0, &new) < 0) |
| 357 | return -EINVAL; | 357 | return -EINVAL; |
| 358 | 358 | ||
| 359 | b->interrupt_enable = !!new; | 359 | b->interrupt_enable = !!new; |
| @@ -372,7 +372,7 @@ store_threshold_limit(struct threshold_block *b, const char *buf, size_t size) | |||
| 372 | struct thresh_restart tr; | 372 | struct thresh_restart tr; |
| 373 | unsigned long new; | 373 | unsigned long new; |
| 374 | 374 | ||
| 375 | if (strict_strtoul(buf, 0, &new) < 0) | 375 | if (kstrtoul(buf, 0, &new) < 0) |
| 376 | return -EINVAL; | 376 | return -EINVAL; |
| 377 | 377 | ||
| 378 | if (new > THRESHOLD_MAX) | 378 | if (new > THRESHOLD_MAX) |
diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c index 507de8066594..0553a34fa0df 100644 --- a/arch/x86/kernel/crash.c +++ b/arch/x86/kernel/crash.c | |||
| @@ -4,9 +4,14 @@ | |||
| 4 | * Created by: Hariprasad Nellitheertha (hari@in.ibm.com) | 4 | * Created by: Hariprasad Nellitheertha (hari@in.ibm.com) |
| 5 | * | 5 | * |
| 6 | * Copyright (C) IBM Corporation, 2004. All rights reserved. | 6 | * Copyright (C) IBM Corporation, 2004. All rights reserved. |
| 7 | * Copyright (C) Red Hat Inc., 2014. All rights reserved. | ||
| 8 | * Authors: | ||
| 9 | * Vivek Goyal <vgoyal@redhat.com> | ||
| 7 | * | 10 | * |
| 8 | */ | 11 | */ |
| 9 | 12 | ||
| 13 | #define pr_fmt(fmt) "kexec: " fmt | ||
| 14 | |||
| 10 | #include <linux/types.h> | 15 | #include <linux/types.h> |
| 11 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
| 12 | #include <linux/smp.h> | 17 | #include <linux/smp.h> |
| @@ -16,6 +21,7 @@ | |||
| 16 | #include <linux/elf.h> | 21 | #include <linux/elf.h> |
| 17 | #include <linux/elfcore.h> | 22 | #include <linux/elfcore.h> |
| 18 | #include <linux/module.h> | 23 | #include <linux/module.h> |
| 24 | #include <linux/slab.h> | ||
| 19 | 25 | ||
| 20 | #include <asm/processor.h> | 26 | #include <asm/processor.h> |
| 21 | #include <asm/hardirq.h> | 27 | #include <asm/hardirq.h> |
| @@ -28,6 +34,45 @@ | |||
| 28 | #include <asm/reboot.h> | 34 | #include <asm/reboot.h> |
| 29 | #include <asm/virtext.h> | 35 | #include <asm/virtext.h> |
| 30 | 36 | ||
| 37 | /* Alignment required for elf header segment */ | ||
| 38 | #define ELF_CORE_HEADER_ALIGN 4096 | ||
| 39 | |||
| 40 | /* This primarily represents number of split ranges due to exclusion */ | ||
| 41 | #define CRASH_MAX_RANGES 16 | ||
| 42 | |||
| 43 | struct crash_mem_range { | ||
| 44 | u64 start, end; | ||
| 45 | }; | ||
| 46 | |||
| 47 | struct crash_mem { | ||
| 48 | unsigned int nr_ranges; | ||
| 49 | struct crash_mem_range ranges[CRASH_MAX_RANGES]; | ||
| 50 | }; | ||
| 51 | |||
| 52 | /* Misc data about ram ranges needed to prepare elf headers */ | ||
| 53 | struct crash_elf_data { | ||
| 54 | struct kimage *image; | ||
| 55 | /* | ||
| 56 | * Total number of ram ranges we have after various adjustments for | ||
| 57 | * GART, crash reserved region etc. | ||
| 58 | */ | ||
| 59 | unsigned int max_nr_ranges; | ||
| 60 | unsigned long gart_start, gart_end; | ||
| 61 | |||
| 62 | /* Pointer to elf header */ | ||
| 63 | void *ehdr; | ||
| 64 | /* Pointer to next phdr */ | ||
| 65 | void *bufp; | ||
| 66 | struct crash_mem mem; | ||
| 67 | }; | ||
| 68 | |||
| 69 | /* Used while preparing memory map entries for second kernel */ | ||
| 70 | struct crash_memmap_data { | ||
| 71 | struct boot_params *params; | ||
| 72 | /* Type of memory */ | ||
| 73 | unsigned int type; | ||
| 74 | }; | ||
| 75 | |||
| 31 | int in_crash_kexec; | 76 | int in_crash_kexec; |
| 32 | 77 | ||
| 33 | /* | 78 | /* |
| @@ -39,6 +84,7 @@ int in_crash_kexec; | |||
| 39 | */ | 84 | */ |
| 40 | crash_vmclear_fn __rcu *crash_vmclear_loaded_vmcss = NULL; | 85 | crash_vmclear_fn __rcu *crash_vmclear_loaded_vmcss = NULL; |
| 41 | EXPORT_SYMBOL_GPL(crash_vmclear_loaded_vmcss); | 86 | EXPORT_SYMBOL_GPL(crash_vmclear_loaded_vmcss); |
| 87 | unsigned long crash_zero_bytes; | ||
| 42 | 88 | ||
| 43 | static inline void cpu_crash_vmclear_loaded_vmcss(void) | 89 | static inline void cpu_crash_vmclear_loaded_vmcss(void) |
| 44 | { | 90 | { |
| @@ -135,3 +181,520 @@ void native_machine_crash_shutdown(struct pt_regs *regs) | |||
| 135 | #endif | 181 | #endif |
| 136 | crash_save_cpu(regs, safe_smp_processor_id()); | 182 | crash_save_cpu(regs, safe_smp_processor_id()); |
| 137 | } | 183 | } |
| 184 | |||
| 185 | #ifdef CONFIG_X86_64 | ||
| 186 | |||
| 187 | static int get_nr_ram_ranges_callback(unsigned long start_pfn, | ||
| 188 | unsigned long nr_pfn, void *arg) | ||
| 189 | { | ||
| 190 | int *nr_ranges = arg; | ||
| 191 | |||
| 192 | (*nr_ranges)++; | ||
| 193 | return 0; | ||
| 194 | } | ||
| 195 | |||
| 196 | static int get_gart_ranges_callback(u64 start, u64 end, void *arg) | ||
| 197 | { | ||
| 198 | struct crash_elf_data *ced = arg; | ||
| 199 | |||
| 200 | ced->gart_start = start; | ||
| 201 | ced->gart_end = end; | ||
| 202 | |||
| 203 | /* Not expecting more than 1 gart aperture */ | ||
| 204 | return 1; | ||
| 205 | } | ||
| 206 | |||
| 207 | |||
| 208 | /* Gather all the required information to prepare elf headers for ram regions */ | ||
| 209 | static void fill_up_crash_elf_data(struct crash_elf_data *ced, | ||
| 210 | struct kimage *image) | ||
| 211 | { | ||
| 212 | unsigned int nr_ranges = 0; | ||
| 213 | |||
| 214 | ced->image = image; | ||
| 215 | |||
| 216 | walk_system_ram_range(0, -1, &nr_ranges, | ||
| 217 | get_nr_ram_ranges_callback); | ||
| 218 | |||
| 219 | ced->max_nr_ranges = nr_ranges; | ||
| 220 | |||
| 221 | /* | ||
| 222 | * We don't create ELF headers for GART aperture as an attempt | ||
| 223 | * to dump this memory in second kernel leads to hang/crash. | ||
| 224 | * If gart aperture is present, one needs to exclude that region | ||
| 225 | * and that could lead to need of extra phdr. | ||
| 226 | */ | ||
| 227 | walk_iomem_res("GART", IORESOURCE_MEM, 0, -1, | ||
| 228 | ced, get_gart_ranges_callback); | ||
| 229 | |||
| 230 | /* | ||
| 231 | * If we have gart region, excluding that could potentially split | ||
| 232 | * a memory range, resulting in extra header. Account for that. | ||
| 233 | */ | ||
| 234 | if (ced->gart_end) | ||
| 235 | ced->max_nr_ranges++; | ||
| 236 | |||
| 237 | /* Exclusion of crash region could split memory ranges */ | ||
| 238 | ced->max_nr_ranges++; | ||
| 239 | |||
| 240 | /* If crashk_low_res is not 0, another range split possible */ | ||
| 241 | if (crashk_low_res.end != 0) | ||
| 242 | ced->max_nr_ranges++; | ||
| 243 | } | ||
| 244 | |||
| 245 | static int exclude_mem_range(struct crash_mem *mem, | ||
| 246 | unsigned long long mstart, unsigned long long mend) | ||
| 247 | { | ||
| 248 | int i, j; | ||
| 249 | unsigned long long start, end; | ||
| 250 | struct crash_mem_range temp_range = {0, 0}; | ||
| 251 | |||
| 252 | for (i = 0; i < mem->nr_ranges; i++) { | ||
| 253 | start = mem->ranges[i].start; | ||
| 254 | end = mem->ranges[i].end; | ||
| 255 | |||
| 256 | if (mstart > end || mend < start) | ||
| 257 | continue; | ||
| 258 | |||
| 259 | /* Truncate any area outside of range */ | ||
| 260 | if (mstart < start) | ||
| 261 | mstart = start; | ||
| 262 | if (mend > end) | ||
| 263 | mend = end; | ||
| 264 | |||
| 265 | /* Found completely overlapping range */ | ||
| 266 | if (mstart == start && mend == end) { | ||
| 267 | mem->ranges[i].start = 0; | ||
| 268 | mem->ranges[i].end = 0; | ||
| 269 | if (i < mem->nr_ranges - 1) { | ||
| 270 | /* Shift rest of the ranges to left */ | ||
| 271 | for (j = i; j < mem->nr_ranges - 1; j++) { | ||
| 272 | mem->ranges[j].start = | ||
| 273 | mem->ranges[j+1].start; | ||
| 274 | mem->ranges[j].end = | ||
| 275 | mem->ranges[j+1].end; | ||
| 276 | } | ||
| 277 | } | ||
| 278 | mem->nr_ranges--; | ||
| 279 | return 0; | ||
| 280 | } | ||
| 281 | |||
| 282 | if (mstart > start && mend < end) { | ||
| 283 | /* Split original range */ | ||
| 284 | mem->ranges[i].end = mstart - 1; | ||
| 285 | temp_range.start = mend + 1; | ||
| 286 | temp_range.end = end; | ||
| 287 | } else if (mstart != start) | ||
| 288 | mem->ranges[i].end = mstart - 1; | ||
| 289 | else | ||
| 290 | mem->ranges[i].start = mend + 1; | ||
| 291 | break; | ||
| 292 | } | ||
| 293 | |||
| 294 | /* If a split happend, add the split to array */ | ||
| 295 | if (!temp_range.end) | ||
| 296 | return 0; | ||
| 297 | |||
| 298 | /* Split happened */ | ||
| 299 | if (i == CRASH_MAX_RANGES - 1) { | ||
| 300 | pr_err("Too many crash ranges after split\n"); | ||
| 301 | return -ENOMEM; | ||
| 302 | } | ||
| 303 | |||
| 304 | /* Location where new range should go */ | ||
| 305 | j = i + 1; | ||
| 306 | if (j < mem->nr_ranges) { | ||
| 307 | /* Move over all ranges one slot towards the end */ | ||
| 308 | for (i = mem->nr_ranges - 1; i >= j; i--) | ||
| 309 | mem->ranges[i + 1] = mem->ranges[i]; | ||
| 310 | } | ||
| 311 | |||
| 312 | mem->ranges[j].start = temp_range.start; | ||
| 313 | mem->ranges[j].end = temp_range.end; | ||
| 314 | mem->nr_ranges++; | ||
| 315 | return 0; | ||
| 316 | } | ||
| 317 | |||
| 318 | /* | ||
| 319 | * Look for any unwanted ranges between mstart, mend and remove them. This | ||
| 320 | * might lead to split and split ranges are put in ced->mem.ranges[] array | ||
| 321 | */ | ||
| 322 | static int elf_header_exclude_ranges(struct crash_elf_data *ced, | ||
| 323 | unsigned long long mstart, unsigned long long mend) | ||
| 324 | { | ||
| 325 | struct crash_mem *cmem = &ced->mem; | ||
| 326 | int ret = 0; | ||
| 327 | |||
| 328 | memset(cmem->ranges, 0, sizeof(cmem->ranges)); | ||
| 329 | |||
| 330 | cmem->ranges[0].start = mstart; | ||
| 331 | cmem->ranges[0].end = mend; | ||
| 332 | cmem->nr_ranges = 1; | ||
| 333 | |||
| 334 | /* Exclude crashkernel region */ | ||
| 335 | ret = exclude_mem_range(cmem, crashk_res.start, crashk_res.end); | ||
| 336 | if (ret) | ||
| 337 | return ret; | ||
| 338 | |||
| 339 | ret = exclude_mem_range(cmem, crashk_low_res.start, crashk_low_res.end); | ||
| 340 | if (ret) | ||
| 341 | return ret; | ||
| 342 | |||
| 343 | /* Exclude GART region */ | ||
| 344 | if (ced->gart_end) { | ||
| 345 | ret = exclude_mem_range(cmem, ced->gart_start, ced->gart_end); | ||
| 346 | if (ret) | ||
| 347 | return ret; | ||
| 348 | } | ||
| 349 | |||
| 350 | return ret; | ||
| 351 | } | ||
| 352 | |||
| 353 | static int prepare_elf64_ram_headers_callback(u64 start, u64 end, void *arg) | ||
| 354 | { | ||
| 355 | struct crash_elf_data *ced = arg; | ||
| 356 | Elf64_Ehdr *ehdr; | ||
| 357 | Elf64_Phdr *phdr; | ||
| 358 | unsigned long mstart, mend; | ||
| 359 | struct kimage *image = ced->image; | ||
| 360 | struct crash_mem *cmem; | ||
| 361 | int ret, i; | ||
| 362 | |||
| 363 | ehdr = ced->ehdr; | ||
| 364 | |||
| 365 | /* Exclude unwanted mem ranges */ | ||
| 366 | ret = elf_header_exclude_ranges(ced, start, end); | ||
| 367 | if (ret) | ||
| 368 | return ret; | ||
| 369 | |||
| 370 | /* Go through all the ranges in ced->mem.ranges[] and prepare phdr */ | ||
| 371 | cmem = &ced->mem; | ||
| 372 | |||
| 373 | for (i = 0; i < cmem->nr_ranges; i++) { | ||
| 374 | mstart = cmem->ranges[i].start; | ||
| 375 | mend = cmem->ranges[i].end; | ||
| 376 | |||
| 377 | phdr = ced->bufp; | ||
| 378 | ced->bufp += sizeof(Elf64_Phdr); | ||
| 379 | |||
| 380 | phdr->p_type = PT_LOAD; | ||
| 381 | phdr->p_flags = PF_R|PF_W|PF_X; | ||
| 382 | phdr->p_offset = mstart; | ||
| 383 | |||
| 384 | /* | ||
| 385 | * If a range matches backup region, adjust offset to backup | ||
| 386 | * segment. | ||
| 387 | */ | ||
| 388 | if (mstart == image->arch.backup_src_start && | ||
| 389 | (mend - mstart + 1) == image->arch.backup_src_sz) | ||
| 390 | phdr->p_offset = image->arch.backup_load_addr; | ||
| 391 | |||
| 392 | phdr->p_paddr = mstart; | ||
| 393 | phdr->p_vaddr = (unsigned long long) __va(mstart); | ||
| 394 | phdr->p_filesz = phdr->p_memsz = mend - mstart + 1; | ||
| 395 | phdr->p_align = 0; | ||
| 396 | ehdr->e_phnum++; | ||
| 397 | pr_debug("Crash PT_LOAD elf header. phdr=%p vaddr=0x%llx, paddr=0x%llx, sz=0x%llx e_phnum=%d p_offset=0x%llx\n", | ||
| 398 | phdr, phdr->p_vaddr, phdr->p_paddr, phdr->p_filesz, | ||
| 399 | ehdr->e_phnum, phdr->p_offset); | ||
| 400 | } | ||
| 401 | |||
| 402 | return ret; | ||
| 403 | } | ||
| 404 | |||
| 405 | static int prepare_elf64_headers(struct crash_elf_data *ced, | ||
| 406 | void **addr, unsigned long *sz) | ||
| 407 | { | ||
| 408 | Elf64_Ehdr *ehdr; | ||
| 409 | Elf64_Phdr *phdr; | ||
| 410 | unsigned long nr_cpus = num_possible_cpus(), nr_phdr, elf_sz; | ||
| 411 | unsigned char *buf, *bufp; | ||
| 412 | unsigned int cpu; | ||
| 413 | unsigned long long notes_addr; | ||
| 414 | int ret; | ||
| 415 | |||
| 416 | /* extra phdr for vmcoreinfo elf note */ | ||
| 417 | nr_phdr = nr_cpus + 1; | ||
| 418 | nr_phdr += ced->max_nr_ranges; | ||
| 419 | |||
| 420 | /* | ||
| 421 | * kexec-tools creates an extra PT_LOAD phdr for kernel text mapping | ||
| 422 | * area on x86_64 (ffffffff80000000 - ffffffffa0000000). | ||
| 423 | * I think this is required by tools like gdb. So same physical | ||
| 424 | * memory will be mapped in two elf headers. One will contain kernel | ||
| 425 | * text virtual addresses and other will have __va(physical) addresses. | ||
| 426 | */ | ||
| 427 | |||
| 428 | nr_phdr++; | ||
| 429 | elf_sz = sizeof(Elf64_Ehdr) + nr_phdr * sizeof(Elf64_Phdr); | ||
| 430 | elf_sz = ALIGN(elf_sz, ELF_CORE_HEADER_ALIGN); | ||
| 431 | |||
| 432 | buf = vzalloc(elf_sz); | ||
| 433 | if (!buf) | ||
| 434 | return -ENOMEM; | ||
| 435 | |||
| 436 | bufp = buf; | ||
| 437 | ehdr = (Elf64_Ehdr *)bufp; | ||
| 438 | bufp += sizeof(Elf64_Ehdr); | ||
| 439 | memcpy(ehdr->e_ident, ELFMAG, SELFMAG); | ||
| 440 | ehdr->e_ident[EI_CLASS] = ELFCLASS64; | ||
| 441 | ehdr->e_ident[EI_DATA] = ELFDATA2LSB; | ||
| 442 | ehdr->e_ident[EI_VERSION] = EV_CURRENT; | ||
| 443 | ehdr->e_ident[EI_OSABI] = ELF_OSABI; | ||
| 444 | memset(ehdr->e_ident + EI_PAD, 0, EI_NIDENT - EI_PAD); | ||
| 445 | ehdr->e_type = ET_CORE; | ||
| 446 | ehdr->e_machine = ELF_ARCH; | ||
| 447 | ehdr->e_version = EV_CURRENT; | ||
| 448 | ehdr->e_phoff = sizeof(Elf64_Ehdr); | ||
| 449 | ehdr->e_ehsize = sizeof(Elf64_Ehdr); | ||
| 450 | ehdr->e_phentsize = sizeof(Elf64_Phdr); | ||
| 451 | |||
| 452 | /* Prepare one phdr of type PT_NOTE for each present cpu */ | ||
| 453 | for_each_present_cpu(cpu) { | ||
| 454 | phdr = (Elf64_Phdr *)bufp; | ||
| 455 | bufp += sizeof(Elf64_Phdr); | ||
| 456 | phdr->p_type = PT_NOTE; | ||
| 457 | notes_addr = per_cpu_ptr_to_phys(per_cpu_ptr(crash_notes, cpu)); | ||
| 458 | phdr->p_offset = phdr->p_paddr = notes_addr; | ||
| 459 | phdr->p_filesz = phdr->p_memsz = sizeof(note_buf_t); | ||
| 460 | (ehdr->e_phnum)++; | ||
| 461 | } | ||
| 462 | |||
| 463 | /* Prepare one PT_NOTE header for vmcoreinfo */ | ||
| 464 | phdr = (Elf64_Phdr *)bufp; | ||
| 465 | bufp += sizeof(Elf64_Phdr); | ||
| 466 | phdr->p_type = PT_NOTE; | ||
| 467 | phdr->p_offset = phdr->p_paddr = paddr_vmcoreinfo_note(); | ||
| 468 | phdr->p_filesz = phdr->p_memsz = sizeof(vmcoreinfo_note); | ||
| 469 | (ehdr->e_phnum)++; | ||
| 470 | |||
| 471 | #ifdef CONFIG_X86_64 | ||
| 472 | /* Prepare PT_LOAD type program header for kernel text region */ | ||
| 473 | phdr = (Elf64_Phdr *)bufp; | ||
| 474 | bufp += sizeof(Elf64_Phdr); | ||
| 475 | phdr->p_type = PT_LOAD; | ||
| 476 | phdr->p_flags = PF_R|PF_W|PF_X; | ||
| 477 | phdr->p_vaddr = (Elf64_Addr)_text; | ||
| 478 | phdr->p_filesz = phdr->p_memsz = _end - _text; | ||
| 479 | phdr->p_offset = phdr->p_paddr = __pa_symbol(_text); | ||
| 480 | (ehdr->e_phnum)++; | ||
| 481 | #endif | ||
| 482 | |||
| 483 | /* Prepare PT_LOAD headers for system ram chunks. */ | ||
| 484 | ced->ehdr = ehdr; | ||
| 485 | ced->bufp = bufp; | ||
| 486 | ret = walk_system_ram_res(0, -1, ced, | ||
| 487 | prepare_elf64_ram_headers_callback); | ||
| 488 | if (ret < 0) | ||
| 489 | return ret; | ||
| 490 | |||
| 491 | *addr = buf; | ||
| 492 | *sz = elf_sz; | ||
| 493 | return 0; | ||
| 494 | } | ||
| 495 | |||
| 496 | /* Prepare elf headers. Return addr and size */ | ||
| 497 | static int prepare_elf_headers(struct kimage *image, void **addr, | ||
| 498 | unsigned long *sz) | ||
| 499 | { | ||
| 500 | struct crash_elf_data *ced; | ||
| 501 | int ret; | ||
| 502 | |||
| 503 | ced = kzalloc(sizeof(*ced), GFP_KERNEL); | ||
| 504 | if (!ced) | ||
| 505 | return -ENOMEM; | ||
| 506 | |||
| 507 | fill_up_crash_elf_data(ced, image); | ||
| 508 | |||
| 509 | /* By default prepare 64bit headers */ | ||
| 510 | ret = prepare_elf64_headers(ced, addr, sz); | ||
| 511 | kfree(ced); | ||
| 512 | return ret; | ||
| 513 | } | ||
| 514 | |||
| 515 | static int add_e820_entry(struct boot_params *params, struct e820entry *entry) | ||
| 516 | { | ||
| 517 | unsigned int nr_e820_entries; | ||
| 518 | |||
| 519 | nr_e820_entries = params->e820_entries; | ||
| 520 | if (nr_e820_entries >= E820MAX) | ||
| 521 | return 1; | ||
| 522 | |||
| 523 | memcpy(¶ms->e820_map[nr_e820_entries], entry, | ||
| 524 | sizeof(struct e820entry)); | ||
| 525 | params->e820_entries++; | ||
| 526 | return 0; | ||
| 527 | } | ||
| 528 | |||
| 529 | static int memmap_entry_callback(u64 start, u64 end, void *arg) | ||
| 530 | { | ||
| 531 | struct crash_memmap_data *cmd = arg; | ||
| 532 | struct boot_params *params = cmd->params; | ||
| 533 | struct e820entry ei; | ||
| 534 | |||
| 535 | ei.addr = start; | ||
| 536 | ei.size = end - start + 1; | ||
| 537 | ei.type = cmd->type; | ||
| 538 | add_e820_entry(params, &ei); | ||
| 539 | |||
| 540 | return 0; | ||
| 541 | } | ||
| 542 | |||
| 543 | static int memmap_exclude_ranges(struct kimage *image, struct crash_mem *cmem, | ||
| 544 | unsigned long long mstart, | ||
| 545 | unsigned long long mend) | ||
| 546 | { | ||
| 547 | unsigned long start, end; | ||
| 548 | int ret = 0; | ||
| 549 | |||
| 550 | cmem->ranges[0].start = mstart; | ||
| 551 | cmem->ranges[0].end = mend; | ||
| 552 | cmem->nr_ranges = 1; | ||
| 553 | |||
| 554 | /* Exclude Backup region */ | ||
| 555 | start = image->arch.backup_load_addr; | ||
| 556 | end = start + image->arch.backup_src_sz - 1; | ||
| 557 | ret = exclude_mem_range(cmem, start, end); | ||
| 558 | if (ret) | ||
| 559 | return ret; | ||
| 560 | |||
| 561 | /* Exclude elf header region */ | ||
| 562 | start = image->arch.elf_load_addr; | ||
| 563 | end = start + image->arch.elf_headers_sz - 1; | ||
| 564 | return exclude_mem_range(cmem, start, end); | ||
| 565 | } | ||
| 566 | |||
| 567 | /* Prepare memory map for crash dump kernel */ | ||
| 568 | int crash_setup_memmap_entries(struct kimage *image, struct boot_params *params) | ||
| 569 | { | ||
| 570 | int i, ret = 0; | ||
| 571 | unsigned long flags; | ||
| 572 | struct e820entry ei; | ||
| 573 | struct crash_memmap_data cmd; | ||
| 574 | struct crash_mem *cmem; | ||
| 575 | |||
| 576 | cmem = vzalloc(sizeof(struct crash_mem)); | ||
| 577 | if (!cmem) | ||
| 578 | return -ENOMEM; | ||
| 579 | |||
| 580 | memset(&cmd, 0, sizeof(struct crash_memmap_data)); | ||
| 581 | cmd.params = params; | ||
| 582 | |||
| 583 | /* Add first 640K segment */ | ||
| 584 | ei.addr = image->arch.backup_src_start; | ||
| 585 | ei.size = image->arch.backup_src_sz; | ||
| 586 | ei.type = E820_RAM; | ||
| 587 | add_e820_entry(params, &ei); | ||
| 588 | |||
| 589 | /* Add ACPI tables */ | ||
| 590 | cmd.type = E820_ACPI; | ||
| 591 | flags = IORESOURCE_MEM | IORESOURCE_BUSY; | ||
| 592 | walk_iomem_res("ACPI Tables", flags, 0, -1, &cmd, | ||
| 593 | memmap_entry_callback); | ||
| 594 | |||
| 595 | /* Add ACPI Non-volatile Storage */ | ||
| 596 | cmd.type = E820_NVS; | ||
| 597 | walk_iomem_res("ACPI Non-volatile Storage", flags, 0, -1, &cmd, | ||
| 598 | memmap_entry_callback); | ||
| 599 | |||
| 600 | /* Add crashk_low_res region */ | ||
| 601 | if (crashk_low_res.end) { | ||
| 602 | ei.addr = crashk_low_res.start; | ||
| 603 | ei.size = crashk_low_res.end - crashk_low_res.start + 1; | ||
| 604 | ei.type = E820_RAM; | ||
| 605 | add_e820_entry(params, &ei); | ||
| 606 | } | ||
| 607 | |||
| 608 | /* Exclude some ranges from crashk_res and add rest to memmap */ | ||
| 609 | ret = memmap_exclude_ranges(image, cmem, crashk_res.start, | ||
| 610 | crashk_res.end); | ||
| 611 | if (ret) | ||
| 612 | goto out; | ||
| 613 | |||
| 614 | for (i = 0; i < cmem->nr_ranges; i++) { | ||
| 615 | ei.size = cmem->ranges[i].end - cmem->ranges[i].start + 1; | ||
| 616 | |||
| 617 | /* If entry is less than a page, skip it */ | ||
| 618 | if (ei.size < PAGE_SIZE) | ||
| 619 | continue; | ||
| 620 | ei.addr = cmem->ranges[i].start; | ||
| 621 | ei.type = E820_RAM; | ||
| 622 | add_e820_entry(params, &ei); | ||
| 623 | } | ||
| 624 | |||
| 625 | out: | ||
| 626 | vfree(cmem); | ||
| 627 | return ret; | ||
| 628 | } | ||
| 629 | |||
| 630 | static int determine_backup_region(u64 start, u64 end, void *arg) | ||
| 631 | { | ||
| 632 | struct kimage *image = arg; | ||
| 633 | |||
| 634 | image->arch.backup_src_start = start; | ||
| 635 | image->arch.backup_src_sz = end - start + 1; | ||
| 636 | |||
| 637 | /* Expecting only one range for backup region */ | ||
| 638 | return 1; | ||
| 639 | } | ||
| 640 | |||
| 641 | int crash_load_segments(struct kimage *image) | ||
| 642 | { | ||
| 643 | unsigned long src_start, src_sz, elf_sz; | ||
| 644 | void *elf_addr; | ||
| 645 | int ret; | ||
| 646 | |||
| 647 | /* | ||
| 648 | * Determine and load a segment for backup area. First 640K RAM | ||
| 649 | * region is backup source | ||
| 650 | */ | ||
| 651 | |||
| 652 | ret = walk_system_ram_res(KEXEC_BACKUP_SRC_START, KEXEC_BACKUP_SRC_END, | ||
| 653 | image, determine_backup_region); | ||
| 654 | |||
| 655 | /* Zero or postive return values are ok */ | ||
| 656 | if (ret < 0) | ||
| 657 | return ret; | ||
| 658 | |||
| 659 | src_start = image->arch.backup_src_start; | ||
| 660 | src_sz = image->arch.backup_src_sz; | ||
| 661 | |||
| 662 | /* Add backup segment. */ | ||
| 663 | if (src_sz) { | ||
| 664 | /* | ||
| 665 | * Ideally there is no source for backup segment. This is | ||
| 666 | * copied in purgatory after crash. Just add a zero filled | ||
| 667 | * segment for now to make sure checksum logic works fine. | ||
| 668 | */ | ||
| 669 | ret = kexec_add_buffer(image, (char *)&crash_zero_bytes, | ||
| 670 | sizeof(crash_zero_bytes), src_sz, | ||
| 671 | PAGE_SIZE, 0, -1, 0, | ||
| 672 | &image->arch.backup_load_addr); | ||
| 673 | if (ret) | ||
| 674 | return ret; | ||
| 675 | pr_debug("Loaded backup region at 0x%lx backup_start=0x%lx memsz=0x%lx\n", | ||
| 676 | image->arch.backup_load_addr, src_start, src_sz); | ||
| 677 | } | ||
| 678 | |||
| 679 | /* Prepare elf headers and add a segment */ | ||
| 680 | ret = prepare_elf_headers(image, &elf_addr, &elf_sz); | ||
| 681 | if (ret) | ||
| 682 | return ret; | ||
| 683 | |||
| 684 | image->arch.elf_headers = elf_addr; | ||
| 685 | image->arch.elf_headers_sz = elf_sz; | ||
| 686 | |||
| 687 | ret = kexec_add_buffer(image, (char *)elf_addr, elf_sz, elf_sz, | ||
| 688 | ELF_CORE_HEADER_ALIGN, 0, -1, 0, | ||
| 689 | &image->arch.elf_load_addr); | ||
| 690 | if (ret) { | ||
| 691 | vfree((void *)image->arch.elf_headers); | ||
| 692 | return ret; | ||
| 693 | } | ||
| 694 | pr_debug("Loaded ELF headers at 0x%lx bufsz=0x%lx memsz=0x%lx\n", | ||
| 695 | image->arch.elf_load_addr, elf_sz, elf_sz); | ||
| 696 | |||
| 697 | return ret; | ||
| 698 | } | ||
| 699 | |||
| 700 | #endif /* CONFIG_X86_64 */ | ||
diff --git a/arch/x86/kernel/kexec-bzimage64.c b/arch/x86/kernel/kexec-bzimage64.c new file mode 100644 index 000000000000..9642b9b33655 --- /dev/null +++ b/arch/x86/kernel/kexec-bzimage64.c | |||
| @@ -0,0 +1,553 @@ | |||
| 1 | /* | ||
| 2 | * Kexec bzImage loader | ||
| 3 | * | ||
| 4 | * Copyright (C) 2014 Red Hat Inc. | ||
| 5 | * Authors: | ||
| 6 | * Vivek Goyal <vgoyal@redhat.com> | ||
| 7 | * | ||
| 8 | * This source code is licensed under the GNU General Public License, | ||
| 9 | * Version 2. See the file COPYING for more details. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #define pr_fmt(fmt) "kexec-bzImage64: " fmt | ||
| 13 | |||
| 14 | #include <linux/string.h> | ||
| 15 | #include <linux/printk.h> | ||
| 16 | #include <linux/errno.h> | ||
| 17 | #include <linux/slab.h> | ||
| 18 | #include <linux/kexec.h> | ||
| 19 | #include <linux/kernel.h> | ||
| 20 | #include <linux/mm.h> | ||
| 21 | #include <linux/efi.h> | ||
| 22 | #include <linux/verify_pefile.h> | ||
| 23 | #include <keys/system_keyring.h> | ||
| 24 | |||
| 25 | #include <asm/bootparam.h> | ||
| 26 | #include <asm/setup.h> | ||
| 27 | #include <asm/crash.h> | ||
| 28 | #include <asm/efi.h> | ||
| 29 | |||
| 30 | #define MAX_ELFCOREHDR_STR_LEN 30 /* elfcorehdr=0x<64bit-value> */ | ||
| 31 | |||
| 32 | /* | ||
| 33 | * Defines lowest physical address for various segments. Not sure where | ||
| 34 | * exactly these limits came from. Current bzimage64 loader in kexec-tools | ||
| 35 | * uses these so I am retaining it. It can be changed over time as we gain | ||
| 36 | * more insight. | ||
| 37 | */ | ||
| 38 | #define MIN_PURGATORY_ADDR 0x3000 | ||
| 39 | #define MIN_BOOTPARAM_ADDR 0x3000 | ||
| 40 | #define MIN_KERNEL_LOAD_ADDR 0x100000 | ||
| 41 | #define MIN_INITRD_LOAD_ADDR 0x1000000 | ||
| 42 | |||
| 43 | /* | ||
| 44 | * This is a place holder for all boot loader specific data structure which | ||
| 45 | * gets allocated in one call but gets freed much later during cleanup | ||
| 46 | * time. Right now there is only one field but it can grow as need be. | ||
| 47 | */ | ||
| 48 | struct bzimage64_data { | ||
| 49 | /* | ||
| 50 | * Temporary buffer to hold bootparams buffer. This should be | ||
| 51 | * freed once the bootparam segment has been loaded. | ||
| 52 | */ | ||
| 53 | void *bootparams_buf; | ||
| 54 | }; | ||
| 55 | |||
| 56 | static int setup_initrd(struct boot_params *params, | ||
| 57 | unsigned long initrd_load_addr, unsigned long initrd_len) | ||
| 58 | { | ||
| 59 | params->hdr.ramdisk_image = initrd_load_addr & 0xffffffffUL; | ||
| 60 | params->hdr.ramdisk_size = initrd_len & 0xffffffffUL; | ||
| 61 | |||
| 62 | params->ext_ramdisk_image = initrd_load_addr >> 32; | ||
| 63 | params->ext_ramdisk_size = initrd_len >> 32; | ||
| 64 | |||
| 65 | return 0; | ||
| 66 | } | ||
| 67 | |||
| 68 | static int setup_cmdline(struct kimage *image, struct boot_params *params, | ||
| 69 | unsigned long bootparams_load_addr, | ||
| 70 | unsigned long cmdline_offset, char *cmdline, | ||
| 71 | unsigned long cmdline_len) | ||
| 72 | { | ||
| 73 | char *cmdline_ptr = ((char *)params) + cmdline_offset; | ||
| 74 | unsigned long cmdline_ptr_phys, len; | ||
| 75 | uint32_t cmdline_low_32, cmdline_ext_32; | ||
| 76 | |||
| 77 | memcpy(cmdline_ptr, cmdline, cmdline_len); | ||
| 78 | if (image->type == KEXEC_TYPE_CRASH) { | ||
| 79 | len = sprintf(cmdline_ptr + cmdline_len - 1, | ||
| 80 | " elfcorehdr=0x%lx", image->arch.elf_load_addr); | ||
| 81 | cmdline_len += len; | ||
| 82 | } | ||
| 83 | cmdline_ptr[cmdline_len - 1] = '\0'; | ||
| 84 | |||
| 85 | pr_debug("Final command line is: %s\n", cmdline_ptr); | ||
| 86 | cmdline_ptr_phys = bootparams_load_addr + cmdline_offset; | ||
| 87 | cmdline_low_32 = cmdline_ptr_phys & 0xffffffffUL; | ||
| 88 | cmdline_ext_32 = cmdline_ptr_phys >> 32; | ||
| 89 | |||
| 90 | params->hdr.cmd_line_ptr = cmdline_low_32; | ||
| 91 | if (cmdline_ext_32) | ||
| 92 | params->ext_cmd_line_ptr = cmdline_ext_32; | ||
| 93 | |||
| 94 | return 0; | ||
| 95 | } | ||
| 96 | |||
| 97 | static int setup_e820_entries(struct boot_params *params) | ||
| 98 | { | ||
| 99 | unsigned int nr_e820_entries; | ||
| 100 | |||
| 101 | nr_e820_entries = e820_saved.nr_map; | ||
| 102 | |||
| 103 | /* TODO: Pass entries more than E820MAX in bootparams setup data */ | ||
| 104 | if (nr_e820_entries > E820MAX) | ||
| 105 | nr_e820_entries = E820MAX; | ||
| 106 | |||
| 107 | params->e820_entries = nr_e820_entries; | ||
| 108 | memcpy(¶ms->e820_map, &e820_saved.map, | ||
| 109 | nr_e820_entries * sizeof(struct e820entry)); | ||
| 110 | |||
| 111 | return 0; | ||
| 112 | } | ||
| 113 | |||
| 114 | #ifdef CONFIG_EFI | ||
| 115 | static int setup_efi_info_memmap(struct boot_params *params, | ||
| 116 | unsigned long params_load_addr, | ||
| 117 | unsigned int efi_map_offset, | ||
| 118 | unsigned int efi_map_sz) | ||
| 119 | { | ||
| 120 | void *efi_map = (void *)params + efi_map_offset; | ||
| 121 | unsigned long efi_map_phys_addr = params_load_addr + efi_map_offset; | ||
| 122 | struct efi_info *ei = ¶ms->efi_info; | ||
| 123 | |||
| 124 | if (!efi_map_sz) | ||
| 125 | return 0; | ||
| 126 | |||
| 127 | efi_runtime_map_copy(efi_map, efi_map_sz); | ||
| 128 | |||
| 129 | ei->efi_memmap = efi_map_phys_addr & 0xffffffff; | ||
| 130 | ei->efi_memmap_hi = efi_map_phys_addr >> 32; | ||
| 131 | ei->efi_memmap_size = efi_map_sz; | ||
| 132 | |||
| 133 | return 0; | ||
| 134 | } | ||
| 135 | |||
| 136 | static int | ||
| 137 | prepare_add_efi_setup_data(struct boot_params *params, | ||
| 138 | unsigned long params_load_addr, | ||
| 139 | unsigned int efi_setup_data_offset) | ||
| 140 | { | ||
| 141 | unsigned long setup_data_phys; | ||
| 142 | struct setup_data *sd = (void *)params + efi_setup_data_offset; | ||
| 143 | struct efi_setup_data *esd = (void *)sd + sizeof(struct setup_data); | ||
| 144 | |||
| 145 | esd->fw_vendor = efi.fw_vendor; | ||
| 146 | esd->runtime = efi.runtime; | ||
| 147 | esd->tables = efi.config_table; | ||
| 148 | esd->smbios = efi.smbios; | ||
| 149 | |||
| 150 | sd->type = SETUP_EFI; | ||
| 151 | sd->len = sizeof(struct efi_setup_data); | ||
| 152 | |||
| 153 | /* Add setup data */ | ||
| 154 | setup_data_phys = params_load_addr + efi_setup_data_offset; | ||
| 155 | sd->next = params->hdr.setup_data; | ||
| 156 | params->hdr.setup_data = setup_data_phys; | ||
| 157 | |||
| 158 | return 0; | ||
| 159 | } | ||
| 160 | |||
| 161 | static int | ||
| 162 | setup_efi_state(struct boot_params *params, unsigned long params_load_addr, | ||
| 163 | unsigned int efi_map_offset, unsigned int efi_map_sz, | ||
| 164 | unsigned int efi_setup_data_offset) | ||
| 165 | { | ||
| 166 | struct efi_info *current_ei = &boot_params.efi_info; | ||
| 167 | struct efi_info *ei = ¶ms->efi_info; | ||
| 168 | |||
| 169 | if (!current_ei->efi_memmap_size) | ||
| 170 | return 0; | ||
| 171 | |||
| 172 | /* | ||
| 173 | * If 1:1 mapping is not enabled, second kernel can not setup EFI | ||
| 174 | * and use EFI run time services. User space will have to pass | ||
| 175 | * acpi_rsdp=<addr> on kernel command line to make second kernel boot | ||
| 176 | * without efi. | ||
| 177 | */ | ||
| 178 | if (efi_enabled(EFI_OLD_MEMMAP)) | ||
| 179 | return 0; | ||
| 180 | |||
| 181 | ei->efi_loader_signature = current_ei->efi_loader_signature; | ||
| 182 | ei->efi_systab = current_ei->efi_systab; | ||
| 183 | ei->efi_systab_hi = current_ei->efi_systab_hi; | ||
| 184 | |||
| 185 | ei->efi_memdesc_version = current_ei->efi_memdesc_version; | ||
| 186 | ei->efi_memdesc_size = efi_get_runtime_map_desc_size(); | ||
| 187 | |||
| 188 | setup_efi_info_memmap(params, params_load_addr, efi_map_offset, | ||
| 189 | efi_map_sz); | ||
| 190 | prepare_add_efi_setup_data(params, params_load_addr, | ||
| 191 | efi_setup_data_offset); | ||
| 192 | return 0; | ||
| 193 | } | ||
| 194 | #endif /* CONFIG_EFI */ | ||
| 195 | |||
| 196 | static int | ||
| 197 | setup_boot_parameters(struct kimage *image, struct boot_params *params, | ||
| 198 | unsigned long params_load_addr, | ||
| 199 | unsigned int efi_map_offset, unsigned int efi_map_sz, | ||
| 200 | unsigned int efi_setup_data_offset) | ||
| 201 | { | ||
| 202 | unsigned int nr_e820_entries; | ||
| 203 | unsigned long long mem_k, start, end; | ||
| 204 | int i, ret = 0; | ||
| 205 | |||
| 206 | /* Get subarch from existing bootparams */ | ||
| 207 | params->hdr.hardware_subarch = boot_params.hdr.hardware_subarch; | ||
| 208 | |||
| 209 | /* Copying screen_info will do? */ | ||
| 210 | memcpy(¶ms->screen_info, &boot_params.screen_info, | ||
| 211 | sizeof(struct screen_info)); | ||
| 212 | |||
| 213 | /* Fill in memsize later */ | ||
| 214 | params->screen_info.ext_mem_k = 0; | ||
| 215 | params->alt_mem_k = 0; | ||
| 216 | |||
| 217 | /* Default APM info */ | ||
| 218 | memset(¶ms->apm_bios_info, 0, sizeof(params->apm_bios_info)); | ||
| 219 | |||
| 220 | /* Default drive info */ | ||
| 221 | memset(¶ms->hd0_info, 0, sizeof(params->hd0_info)); | ||
| 222 | memset(¶ms->hd1_info, 0, sizeof(params->hd1_info)); | ||
| 223 | |||
| 224 | /* Default sysdesc table */ | ||
| 225 | params->sys_desc_table.length = 0; | ||
| 226 | |||
| 227 | if (image->type == KEXEC_TYPE_CRASH) { | ||
| 228 | ret = crash_setup_memmap_entries(image, params); | ||
| 229 | if (ret) | ||
| 230 | return ret; | ||
| 231 | } else | ||
| 232 | setup_e820_entries(params); | ||
| 233 | |||
| 234 | nr_e820_entries = params->e820_entries; | ||
| 235 | |||
| 236 | for (i = 0; i < nr_e820_entries; i++) { | ||
| 237 | if (params->e820_map[i].type != E820_RAM) | ||
| 238 | continue; | ||
| 239 | start = params->e820_map[i].addr; | ||
| 240 | end = params->e820_map[i].addr + params->e820_map[i].size - 1; | ||
| 241 | |||
| 242 | if ((start <= 0x100000) && end > 0x100000) { | ||
| 243 | mem_k = (end >> 10) - (0x100000 >> 10); | ||
| 244 | params->screen_info.ext_mem_k = mem_k; | ||
| 245 | params->alt_mem_k = mem_k; | ||
| 246 | if (mem_k > 0xfc00) | ||
| 247 | params->screen_info.ext_mem_k = 0xfc00; /* 64M*/ | ||
| 248 | if (mem_k > 0xffffffff) | ||
| 249 | params->alt_mem_k = 0xffffffff; | ||
| 250 | } | ||
| 251 | } | ||
| 252 | |||
| 253 | #ifdef CONFIG_EFI | ||
| 254 | /* Setup EFI state */ | ||
| 255 | setup_efi_state(params, params_load_addr, efi_map_offset, efi_map_sz, | ||
| 256 | efi_setup_data_offset); | ||
| 257 | #endif | ||
| 258 | |||
| 259 | /* Setup EDD info */ | ||
| 260 | memcpy(params->eddbuf, boot_params.eddbuf, | ||
| 261 | EDDMAXNR * sizeof(struct edd_info)); | ||
| 262 | params->eddbuf_entries = boot_params.eddbuf_entries; | ||
| 263 | |||
| 264 | memcpy(params->edd_mbr_sig_buffer, boot_params.edd_mbr_sig_buffer, | ||
| 265 | EDD_MBR_SIG_MAX * sizeof(unsigned int)); | ||
| 266 | |||
| 267 | return ret; | ||
| 268 | } | ||
| 269 | |||
| 270 | int bzImage64_probe(const char *buf, unsigned long len) | ||
| 271 | { | ||
| 272 | int ret = -ENOEXEC; | ||
| 273 | struct setup_header *header; | ||
| 274 | |||
| 275 | /* kernel should be atleast two sectors long */ | ||
| 276 | if (len < 2 * 512) { | ||
| 277 | pr_err("File is too short to be a bzImage\n"); | ||
| 278 | return ret; | ||
| 279 | } | ||
| 280 | |||
| 281 | header = (struct setup_header *)(buf + offsetof(struct boot_params, hdr)); | ||
| 282 | if (memcmp((char *)&header->header, "HdrS", 4) != 0) { | ||
| 283 | pr_err("Not a bzImage\n"); | ||
| 284 | return ret; | ||
| 285 | } | ||
| 286 | |||
| 287 | if (header->boot_flag != 0xAA55) { | ||
| 288 | pr_err("No x86 boot sector present\n"); | ||
| 289 | return ret; | ||
| 290 | } | ||
| 291 | |||
| 292 | if (header->version < 0x020C) { | ||
| 293 | pr_err("Must be at least protocol version 2.12\n"); | ||
| 294 | return ret; | ||
| 295 | } | ||
| 296 | |||
| 297 | if (!(header->loadflags & LOADED_HIGH)) { | ||
| 298 | pr_err("zImage not a bzImage\n"); | ||
| 299 | return ret; | ||
| 300 | } | ||
| 301 | |||
| 302 | if (!(header->xloadflags & XLF_KERNEL_64)) { | ||
| 303 | pr_err("Not a bzImage64. XLF_KERNEL_64 is not set.\n"); | ||
| 304 | return ret; | ||
| 305 | } | ||
| 306 | |||
| 307 | if (!(header->xloadflags & XLF_CAN_BE_LOADED_ABOVE_4G)) { | ||
| 308 | pr_err("XLF_CAN_BE_LOADED_ABOVE_4G is not set.\n"); | ||
| 309 | return ret; | ||
| 310 | } | ||
| 311 | |||
| 312 | /* | ||
| 313 | * Can't handle 32bit EFI as it does not allow loading kernel | ||
| 314 | * above 4G. This should be handled by 32bit bzImage loader | ||
| 315 | */ | ||
| 316 | if (efi_enabled(EFI_RUNTIME_SERVICES) && !efi_enabled(EFI_64BIT)) { | ||
| 317 | pr_debug("EFI is 32 bit. Can't load kernel above 4G.\n"); | ||
| 318 | return ret; | ||
| 319 | } | ||
| 320 | |||
| 321 | /* I've got a bzImage */ | ||
| 322 | pr_debug("It's a relocatable bzImage64\n"); | ||
| 323 | ret = 0; | ||
| 324 | |||
| 325 | return ret; | ||
| 326 | } | ||
| 327 | |||
| 328 | void *bzImage64_load(struct kimage *image, char *kernel, | ||
| 329 | unsigned long kernel_len, char *initrd, | ||
| 330 | unsigned long initrd_len, char *cmdline, | ||
| 331 | unsigned long cmdline_len) | ||
| 332 | { | ||
| 333 | |||
| 334 | struct setup_header *header; | ||
| 335 | int setup_sects, kern16_size, ret = 0; | ||
| 336 | unsigned long setup_header_size, params_cmdline_sz, params_misc_sz; | ||
| 337 | struct boot_params *params; | ||
| 338 | unsigned long bootparam_load_addr, kernel_load_addr, initrd_load_addr; | ||
| 339 | unsigned long purgatory_load_addr; | ||
| 340 | unsigned long kernel_bufsz, kernel_memsz, kernel_align; | ||
| 341 | char *kernel_buf; | ||
| 342 | struct bzimage64_data *ldata; | ||
| 343 | struct kexec_entry64_regs regs64; | ||
| 344 | void *stack; | ||
| 345 | unsigned int setup_hdr_offset = offsetof(struct boot_params, hdr); | ||
| 346 | unsigned int efi_map_offset, efi_map_sz, efi_setup_data_offset; | ||
| 347 | |||
| 348 | header = (struct setup_header *)(kernel + setup_hdr_offset); | ||
| 349 | setup_sects = header->setup_sects; | ||
| 350 | if (setup_sects == 0) | ||
| 351 | setup_sects = 4; | ||
| 352 | |||
| 353 | kern16_size = (setup_sects + 1) * 512; | ||
| 354 | if (kernel_len < kern16_size) { | ||
| 355 | pr_err("bzImage truncated\n"); | ||
| 356 | return ERR_PTR(-ENOEXEC); | ||
| 357 | } | ||
| 358 | |||
| 359 | if (cmdline_len > header->cmdline_size) { | ||
| 360 | pr_err("Kernel command line too long\n"); | ||
| 361 | return ERR_PTR(-EINVAL); | ||
| 362 | } | ||
| 363 | |||
| 364 | /* | ||
| 365 | * In case of crash dump, we will append elfcorehdr=<addr> to | ||
| 366 | * command line. Make sure it does not overflow | ||
| 367 | */ | ||
| 368 | if (cmdline_len + MAX_ELFCOREHDR_STR_LEN > header->cmdline_size) { | ||
| 369 | pr_debug("Appending elfcorehdr=<addr> to command line exceeds maximum allowed length\n"); | ||
| 370 | return ERR_PTR(-EINVAL); | ||
| 371 | } | ||
| 372 | |||
| 373 | /* Allocate and load backup region */ | ||
| 374 | if (image->type == KEXEC_TYPE_CRASH) { | ||
| 375 | ret = crash_load_segments(image); | ||
| 376 | if (ret) | ||
| 377 | return ERR_PTR(ret); | ||
| 378 | } | ||
| 379 | |||
| 380 | /* | ||
| 381 | * Load purgatory. For 64bit entry point, purgatory code can be | ||
| 382 | * anywhere. | ||
| 383 | */ | ||
| 384 | ret = kexec_load_purgatory(image, MIN_PURGATORY_ADDR, ULONG_MAX, 1, | ||
| 385 | &purgatory_load_addr); | ||
| 386 | if (ret) { | ||
| 387 | pr_err("Loading purgatory failed\n"); | ||
| 388 | return ERR_PTR(ret); | ||
| 389 | } | ||
| 390 | |||
| 391 | pr_debug("Loaded purgatory at 0x%lx\n", purgatory_load_addr); | ||
| 392 | |||
| 393 | |||
| 394 | /* | ||
| 395 | * Load Bootparams and cmdline and space for efi stuff. | ||
| 396 | * | ||
| 397 | * Allocate memory together for multiple data structures so | ||
| 398 | * that they all can go in single area/segment and we don't | ||
| 399 | * have to create separate segment for each. Keeps things | ||
| 400 | * little bit simple | ||
| 401 | */ | ||
| 402 | efi_map_sz = efi_get_runtime_map_size(); | ||
| 403 | efi_map_sz = ALIGN(efi_map_sz, 16); | ||
| 404 | params_cmdline_sz = sizeof(struct boot_params) + cmdline_len + | ||
| 405 | MAX_ELFCOREHDR_STR_LEN; | ||
| 406 | params_cmdline_sz = ALIGN(params_cmdline_sz, 16); | ||
| 407 | params_misc_sz = params_cmdline_sz + efi_map_sz + | ||
| 408 | sizeof(struct setup_data) + | ||
| 409 | sizeof(struct efi_setup_data); | ||
| 410 | |||
| 411 | params = kzalloc(params_misc_sz, GFP_KERNEL); | ||
| 412 | if (!params) | ||
| 413 | return ERR_PTR(-ENOMEM); | ||
| 414 | efi_map_offset = params_cmdline_sz; | ||
| 415 | efi_setup_data_offset = efi_map_offset + efi_map_sz; | ||
| 416 | |||
| 417 | /* Copy setup header onto bootparams. Documentation/x86/boot.txt */ | ||
| 418 | setup_header_size = 0x0202 + kernel[0x0201] - setup_hdr_offset; | ||
| 419 | |||
| 420 | /* Is there a limit on setup header size? */ | ||
| 421 | memcpy(¶ms->hdr, (kernel + setup_hdr_offset), setup_header_size); | ||
| 422 | |||
| 423 | ret = kexec_add_buffer(image, (char *)params, params_misc_sz, | ||
| 424 | params_misc_sz, 16, MIN_BOOTPARAM_ADDR, | ||
| 425 | ULONG_MAX, 1, &bootparam_load_addr); | ||
| 426 | if (ret) | ||
| 427 | goto out_free_params; | ||
| 428 | pr_debug("Loaded boot_param, command line and misc at 0x%lx bufsz=0x%lx memsz=0x%lx\n", | ||
| 429 | bootparam_load_addr, params_misc_sz, params_misc_sz); | ||
| 430 | |||
| 431 | /* Load kernel */ | ||
| 432 | kernel_buf = kernel + kern16_size; | ||
| 433 | kernel_bufsz = kernel_len - kern16_size; | ||
| 434 | kernel_memsz = PAGE_ALIGN(header->init_size); | ||
| 435 | kernel_align = header->kernel_alignment; | ||
| 436 | |||
| 437 | ret = kexec_add_buffer(image, kernel_buf, | ||
| 438 | kernel_bufsz, kernel_memsz, kernel_align, | ||
| 439 | MIN_KERNEL_LOAD_ADDR, ULONG_MAX, 1, | ||
| 440 | &kernel_load_addr); | ||
| 441 | if (ret) | ||
| 442 | goto out_free_params; | ||
| 443 | |||
| 444 | pr_debug("Loaded 64bit kernel at 0x%lx bufsz=0x%lx memsz=0x%lx\n", | ||
| 445 | kernel_load_addr, kernel_memsz, kernel_memsz); | ||
| 446 | |||
| 447 | /* Load initrd high */ | ||
| 448 | if (initrd) { | ||
| 449 | ret = kexec_add_buffer(image, initrd, initrd_len, initrd_len, | ||
| 450 | PAGE_SIZE, MIN_INITRD_LOAD_ADDR, | ||
| 451 | ULONG_MAX, 1, &initrd_load_addr); | ||
| 452 | if (ret) | ||
| 453 | goto out_free_params; | ||
| 454 | |||
| 455 | pr_debug("Loaded initrd at 0x%lx bufsz=0x%lx memsz=0x%lx\n", | ||
| 456 | initrd_load_addr, initrd_len, initrd_len); | ||
| 457 | |||
| 458 | setup_initrd(params, initrd_load_addr, initrd_len); | ||
| 459 | } | ||
| 460 | |||
| 461 | setup_cmdline(image, params, bootparam_load_addr, | ||
| 462 | sizeof(struct boot_params), cmdline, cmdline_len); | ||
| 463 | |||
| 464 | /* bootloader info. Do we need a separate ID for kexec kernel loader? */ | ||
| 465 | params->hdr.type_of_loader = 0x0D << 4; | ||
| 466 | params->hdr.loadflags = 0; | ||
| 467 | |||
| 468 | /* Setup purgatory regs for entry */ | ||
| 469 | ret = kexec_purgatory_get_set_symbol(image, "entry64_regs", ®s64, | ||
| 470 | sizeof(regs64), 1); | ||
| 471 | if (ret) | ||
| 472 | goto out_free_params; | ||
| 473 | |||
| 474 | regs64.rbx = 0; /* Bootstrap Processor */ | ||
| 475 | regs64.rsi = bootparam_load_addr; | ||
| 476 | regs64.rip = kernel_load_addr + 0x200; | ||
| 477 | stack = kexec_purgatory_get_symbol_addr(image, "stack_end"); | ||
| 478 | if (IS_ERR(stack)) { | ||
| 479 | pr_err("Could not find address of symbol stack_end\n"); | ||
| 480 | ret = -EINVAL; | ||
| 481 | goto out_free_params; | ||
| 482 | } | ||
| 483 | |||
| 484 | regs64.rsp = (unsigned long)stack; | ||
| 485 | ret = kexec_purgatory_get_set_symbol(image, "entry64_regs", ®s64, | ||
| 486 | sizeof(regs64), 0); | ||
| 487 | if (ret) | ||
| 488 | goto out_free_params; | ||
| 489 | |||
| 490 | ret = setup_boot_parameters(image, params, bootparam_load_addr, | ||
| 491 | efi_map_offset, efi_map_sz, | ||
| 492 | efi_setup_data_offset); | ||
| 493 | if (ret) | ||
| 494 | goto out_free_params; | ||
| 495 | |||
| 496 | /* Allocate loader specific data */ | ||
| 497 | ldata = kzalloc(sizeof(struct bzimage64_data), GFP_KERNEL); | ||
| 498 | if (!ldata) { | ||
| 499 | ret = -ENOMEM; | ||
| 500 | goto out_free_params; | ||
| 501 | } | ||
| 502 | |||
| 503 | /* | ||
| 504 | * Store pointer to params so that it could be freed after loading | ||
| 505 | * params segment has been loaded and contents have been copied | ||
| 506 | * somewhere else. | ||
| 507 | */ | ||
| 508 | ldata->bootparams_buf = params; | ||
| 509 | return ldata; | ||
| 510 | |||
| 511 | out_free_params: | ||
| 512 | kfree(params); | ||
| 513 | return ERR_PTR(ret); | ||
| 514 | } | ||
| 515 | |||
| 516 | /* This cleanup function is called after various segments have been loaded */ | ||
| 517 | int bzImage64_cleanup(void *loader_data) | ||
| 518 | { | ||
| 519 | struct bzimage64_data *ldata = loader_data; | ||
| 520 | |||
| 521 | if (!ldata) | ||
| 522 | return 0; | ||
| 523 | |||
| 524 | kfree(ldata->bootparams_buf); | ||
| 525 | ldata->bootparams_buf = NULL; | ||
| 526 | |||
| 527 | return 0; | ||
| 528 | } | ||
| 529 | |||
| 530 | #ifdef CONFIG_KEXEC_BZIMAGE_VERIFY_SIG | ||
| 531 | int bzImage64_verify_sig(const char *kernel, unsigned long kernel_len) | ||
| 532 | { | ||
| 533 | bool trusted; | ||
| 534 | int ret; | ||
| 535 | |||
| 536 | ret = verify_pefile_signature(kernel, kernel_len, | ||
| 537 | system_trusted_keyring, &trusted); | ||
| 538 | if (ret < 0) | ||
| 539 | return ret; | ||
| 540 | if (!trusted) | ||
| 541 | return -EKEYREJECTED; | ||
| 542 | return 0; | ||
| 543 | } | ||
| 544 | #endif | ||
| 545 | |||
| 546 | struct kexec_file_ops kexec_bzImage64_ops = { | ||
| 547 | .probe = bzImage64_probe, | ||
| 548 | .load = bzImage64_load, | ||
| 549 | .cleanup = bzImage64_cleanup, | ||
| 550 | #ifdef CONFIG_KEXEC_BZIMAGE_VERIFY_SIG | ||
| 551 | .verify_sig = bzImage64_verify_sig, | ||
| 552 | #endif | ||
| 553 | }; | ||
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c index 679cef0791cd..8b04018e5d1f 100644 --- a/arch/x86/kernel/machine_kexec_64.c +++ b/arch/x86/kernel/machine_kexec_64.c | |||
| @@ -6,6 +6,8 @@ | |||
| 6 | * Version 2. See the file COPYING for more details. | 6 | * Version 2. See the file COPYING for more details. |
| 7 | */ | 7 | */ |
| 8 | 8 | ||
| 9 | #define pr_fmt(fmt) "kexec: " fmt | ||
| 10 | |||
| 9 | #include <linux/mm.h> | 11 | #include <linux/mm.h> |
| 10 | #include <linux/kexec.h> | 12 | #include <linux/kexec.h> |
| 11 | #include <linux/string.h> | 13 | #include <linux/string.h> |
| @@ -21,6 +23,11 @@ | |||
| 21 | #include <asm/tlbflush.h> | 23 | #include <asm/tlbflush.h> |
| 22 | #include <asm/mmu_context.h> | 24 | #include <asm/mmu_context.h> |
| 23 | #include <asm/debugreg.h> | 25 | #include <asm/debugreg.h> |
| 26 | #include <asm/kexec-bzimage64.h> | ||
| 27 | |||
| 28 | static struct kexec_file_ops *kexec_file_loaders[] = { | ||
| 29 | &kexec_bzImage64_ops, | ||
| 30 | }; | ||
| 24 | 31 | ||
| 25 | static void free_transition_pgtable(struct kimage *image) | 32 | static void free_transition_pgtable(struct kimage *image) |
| 26 | { | 33 | { |
| @@ -171,6 +178,38 @@ static void load_segments(void) | |||
| 171 | ); | 178 | ); |
| 172 | } | 179 | } |
| 173 | 180 | ||
| 181 | /* Update purgatory as needed after various image segments have been prepared */ | ||
| 182 | static int arch_update_purgatory(struct kimage *image) | ||
| 183 | { | ||
| 184 | int ret = 0; | ||
| 185 | |||
| 186 | if (!image->file_mode) | ||
| 187 | return 0; | ||
| 188 | |||
| 189 | /* Setup copying of backup region */ | ||
| 190 | if (image->type == KEXEC_TYPE_CRASH) { | ||
| 191 | ret = kexec_purgatory_get_set_symbol(image, "backup_dest", | ||
| 192 | &image->arch.backup_load_addr, | ||
| 193 | sizeof(image->arch.backup_load_addr), 0); | ||
| 194 | if (ret) | ||
| 195 | return ret; | ||
| 196 | |||
| 197 | ret = kexec_purgatory_get_set_symbol(image, "backup_src", | ||
| 198 | &image->arch.backup_src_start, | ||
| 199 | sizeof(image->arch.backup_src_start), 0); | ||
| 200 | if (ret) | ||
| 201 | return ret; | ||
| 202 | |||
| 203 | ret = kexec_purgatory_get_set_symbol(image, "backup_sz", | ||
| 204 | &image->arch.backup_src_sz, | ||
| 205 | sizeof(image->arch.backup_src_sz), 0); | ||
| 206 | if (ret) | ||
| 207 | return ret; | ||
| 208 | } | ||
| 209 | |||
| 210 | return ret; | ||
| 211 | } | ||
| 212 | |||
| 174 | int machine_kexec_prepare(struct kimage *image) | 213 | int machine_kexec_prepare(struct kimage *image) |
| 175 | { | 214 | { |
| 176 | unsigned long start_pgtable; | 215 | unsigned long start_pgtable; |
| @@ -184,6 +223,11 @@ int machine_kexec_prepare(struct kimage *image) | |||
| 184 | if (result) | 223 | if (result) |
| 185 | return result; | 224 | return result; |
| 186 | 225 | ||
| 226 | /* update purgatory as needed */ | ||
| 227 | result = arch_update_purgatory(image); | ||
| 228 | if (result) | ||
| 229 | return result; | ||
| 230 | |||
| 187 | return 0; | 231 | return 0; |
| 188 | } | 232 | } |
| 189 | 233 | ||
| @@ -283,3 +327,198 @@ void arch_crash_save_vmcoreinfo(void) | |||
| 283 | (unsigned long)&_text - __START_KERNEL); | 327 | (unsigned long)&_text - __START_KERNEL); |
| 284 | } | 328 | } |
| 285 | 329 | ||
| 330 | /* arch-dependent functionality related to kexec file-based syscall */ | ||
| 331 | |||
| 332 | int arch_kexec_kernel_image_probe(struct kimage *image, void *buf, | ||
| 333 | unsigned long buf_len) | ||
| 334 | { | ||
| 335 | int i, ret = -ENOEXEC; | ||
| 336 | struct kexec_file_ops *fops; | ||
| 337 | |||
| 338 | for (i = 0; i < ARRAY_SIZE(kexec_file_loaders); i++) { | ||
| 339 | fops = kexec_file_loaders[i]; | ||
| 340 | if (!fops || !fops->probe) | ||
| 341 | continue; | ||
| 342 | |||
| 343 | ret = fops->probe(buf, buf_len); | ||
| 344 | if (!ret) { | ||
| 345 | image->fops = fops; | ||
| 346 | return ret; | ||
| 347 | } | ||
| 348 | } | ||
| 349 | |||
| 350 | return ret; | ||
| 351 | } | ||
| 352 | |||
| 353 | void *arch_kexec_kernel_image_load(struct kimage *image) | ||
| 354 | { | ||
| 355 | vfree(image->arch.elf_headers); | ||
| 356 | image->arch.elf_headers = NULL; | ||
| 357 | |||
| 358 | if (!image->fops || !image->fops->load) | ||
| 359 | return ERR_PTR(-ENOEXEC); | ||
| 360 | |||
| 361 | return image->fops->load(image, image->kernel_buf, | ||
| 362 | image->kernel_buf_len, image->initrd_buf, | ||
| 363 | image->initrd_buf_len, image->cmdline_buf, | ||
| 364 | image->cmdline_buf_len); | ||
| 365 | } | ||
| 366 | |||
| 367 | int arch_kimage_file_post_load_cleanup(struct kimage *image) | ||
| 368 | { | ||
| 369 | if (!image->fops || !image->fops->cleanup) | ||
| 370 | return 0; | ||
| 371 | |||
| 372 | return image->fops->cleanup(image->image_loader_data); | ||
| 373 | } | ||
| 374 | |||
| 375 | int arch_kexec_kernel_verify_sig(struct kimage *image, void *kernel, | ||
| 376 | unsigned long kernel_len) | ||
| 377 | { | ||
| 378 | if (!image->fops || !image->fops->verify_sig) { | ||
| 379 | pr_debug("kernel loader does not support signature verification."); | ||
| 380 | return -EKEYREJECTED; | ||
| 381 | } | ||
| 382 | |||
| 383 | return image->fops->verify_sig(kernel, kernel_len); | ||
| 384 | } | ||
| 385 | |||
| 386 | /* | ||
| 387 | * Apply purgatory relocations. | ||
| 388 | * | ||
| 389 | * ehdr: Pointer to elf headers | ||
| 390 | * sechdrs: Pointer to section headers. | ||
| 391 | * relsec: section index of SHT_RELA section. | ||
| 392 | * | ||
| 393 | * TODO: Some of the code belongs to generic code. Move that in kexec.c. | ||
| 394 | */ | ||
| 395 | int arch_kexec_apply_relocations_add(const Elf64_Ehdr *ehdr, | ||
| 396 | Elf64_Shdr *sechdrs, unsigned int relsec) | ||
| 397 | { | ||
| 398 | unsigned int i; | ||
| 399 | Elf64_Rela *rel; | ||
| 400 | Elf64_Sym *sym; | ||
| 401 | void *location; | ||
| 402 | Elf64_Shdr *section, *symtabsec; | ||
| 403 | unsigned long address, sec_base, value; | ||
| 404 | const char *strtab, *name, *shstrtab; | ||
| 405 | |||
| 406 | /* | ||
| 407 | * ->sh_offset has been modified to keep the pointer to section | ||
| 408 | * contents in memory | ||
| 409 | */ | ||
| 410 | rel = (void *)sechdrs[relsec].sh_offset; | ||
| 411 | |||
| 412 | /* Section to which relocations apply */ | ||
| 413 | section = &sechdrs[sechdrs[relsec].sh_info]; | ||
| 414 | |||
| 415 | pr_debug("Applying relocate section %u to %u\n", relsec, | ||
| 416 | sechdrs[relsec].sh_info); | ||
| 417 | |||
| 418 | /* Associated symbol table */ | ||
| 419 | symtabsec = &sechdrs[sechdrs[relsec].sh_link]; | ||
| 420 | |||
| 421 | /* String table */ | ||
| 422 | if (symtabsec->sh_link >= ehdr->e_shnum) { | ||
| 423 | /* Invalid strtab section number */ | ||
| 424 | pr_err("Invalid string table section index %d\n", | ||
| 425 | symtabsec->sh_link); | ||
| 426 | return -ENOEXEC; | ||
| 427 | } | ||
| 428 | |||
| 429 | strtab = (char *)sechdrs[symtabsec->sh_link].sh_offset; | ||
| 430 | |||
| 431 | /* section header string table */ | ||
| 432 | shstrtab = (char *)sechdrs[ehdr->e_shstrndx].sh_offset; | ||
| 433 | |||
| 434 | for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { | ||
| 435 | |||
| 436 | /* | ||
| 437 | * rel[i].r_offset contains byte offset from beginning | ||
| 438 | * of section to the storage unit affected. | ||
| 439 | * | ||
| 440 | * This is location to update (->sh_offset). This is temporary | ||
| 441 | * buffer where section is currently loaded. This will finally | ||
| 442 | * be loaded to a different address later, pointed to by | ||
| 443 | * ->sh_addr. kexec takes care of moving it | ||
| 444 | * (kexec_load_segment()). | ||
| 445 | */ | ||
| 446 | location = (void *)(section->sh_offset + rel[i].r_offset); | ||
| 447 | |||
| 448 | /* Final address of the location */ | ||
| 449 | address = section->sh_addr + rel[i].r_offset; | ||
| 450 | |||
| 451 | /* | ||
| 452 | * rel[i].r_info contains information about symbol table index | ||
| 453 | * w.r.t which relocation must be made and type of relocation | ||
| 454 | * to apply. ELF64_R_SYM() and ELF64_R_TYPE() macros get | ||
| 455 | * these respectively. | ||
| 456 | */ | ||
| 457 | sym = (Elf64_Sym *)symtabsec->sh_offset + | ||
| 458 | ELF64_R_SYM(rel[i].r_info); | ||
| 459 | |||
| 460 | if (sym->st_name) | ||
| 461 | name = strtab + sym->st_name; | ||
| 462 | else | ||
| 463 | name = shstrtab + sechdrs[sym->st_shndx].sh_name; | ||
| 464 | |||
| 465 | pr_debug("Symbol: %s info: %02x shndx: %02x value=%llx size: %llx\n", | ||
| 466 | name, sym->st_info, sym->st_shndx, sym->st_value, | ||
| 467 | sym->st_size); | ||
| 468 | |||
| 469 | if (sym->st_shndx == SHN_UNDEF) { | ||
| 470 | pr_err("Undefined symbol: %s\n", name); | ||
| 471 | return -ENOEXEC; | ||
| 472 | } | ||
| 473 | |||
| 474 | if (sym->st_shndx == SHN_COMMON) { | ||
| 475 | pr_err("symbol '%s' in common section\n", name); | ||
| 476 | return -ENOEXEC; | ||
| 477 | } | ||
| 478 | |||
| 479 | if (sym->st_shndx == SHN_ABS) | ||
| 480 | sec_base = 0; | ||
| 481 | else if (sym->st_shndx >= ehdr->e_shnum) { | ||
| 482 | pr_err("Invalid section %d for symbol %s\n", | ||
| 483 | sym->st_shndx, name); | ||
| 484 | return -ENOEXEC; | ||
| 485 | } else | ||
| 486 | sec_base = sechdrs[sym->st_shndx].sh_addr; | ||
| 487 | |||
| 488 | value = sym->st_value; | ||
| 489 | value += sec_base; | ||
| 490 | value += rel[i].r_addend; | ||
| 491 | |||
| 492 | switch (ELF64_R_TYPE(rel[i].r_info)) { | ||
| 493 | case R_X86_64_NONE: | ||
| 494 | break; | ||
| 495 | case R_X86_64_64: | ||
| 496 | *(u64 *)location = value; | ||
| 497 | break; | ||
| 498 | case R_X86_64_32: | ||
| 499 | *(u32 *)location = value; | ||
| 500 | if (value != *(u32 *)location) | ||
| 501 | goto overflow; | ||
| 502 | break; | ||
| 503 | case R_X86_64_32S: | ||
| 504 | *(s32 *)location = value; | ||
| 505 | if ((s64)value != *(s32 *)location) | ||
| 506 | goto overflow; | ||
| 507 | break; | ||
| 508 | case R_X86_64_PC32: | ||
| 509 | value -= (u64)address; | ||
| 510 | *(u32 *)location = value; | ||
| 511 | break; | ||
| 512 | default: | ||
| 513 | pr_err("Unknown rela relocation: %llu\n", | ||
| 514 | ELF64_R_TYPE(rel[i].r_info)); | ||
| 515 | return -ENOEXEC; | ||
| 516 | } | ||
| 517 | } | ||
| 518 | return 0; | ||
| 519 | |||
| 520 | overflow: | ||
| 521 | pr_err("Overflow in relocation type %d value 0x%lx\n", | ||
| 522 | (int)ELF64_R_TYPE(rel[i].r_info), value); | ||
| 523 | return -ENOEXEC; | ||
| 524 | } | ||
diff --git a/arch/x86/kvm/mmu_audit.c b/arch/x86/kvm/mmu_audit.c index 1185fe7a7f47..9ade5cfb5a4c 100644 --- a/arch/x86/kvm/mmu_audit.c +++ b/arch/x86/kvm/mmu_audit.c | |||
| @@ -273,7 +273,7 @@ static int mmu_audit_set(const char *val, const struct kernel_param *kp) | |||
| 273 | int ret; | 273 | int ret; |
| 274 | unsigned long enable; | 274 | unsigned long enable; |
| 275 | 275 | ||
| 276 | ret = strict_strtoul(val, 10, &enable); | 276 | ret = kstrtoul(val, 10, &enable); |
| 277 | if (ret < 0) | 277 | if (ret < 0) |
| 278 | return -EINVAL; | 278 | return -EINVAL; |
| 279 | 279 | ||
diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c index ed161c6e278b..3968d67d366b 100644 --- a/arch/x86/platform/uv/tlb_uv.c +++ b/arch/x86/platform/uv/tlb_uv.c | |||
| @@ -1479,7 +1479,7 @@ static ssize_t ptc_proc_write(struct file *file, const char __user *user, | |||
| 1479 | return count; | 1479 | return count; |
| 1480 | } | 1480 | } |
| 1481 | 1481 | ||
| 1482 | if (strict_strtol(optstr, 10, &input_arg) < 0) { | 1482 | if (kstrtol(optstr, 10, &input_arg) < 0) { |
| 1483 | printk(KERN_DEBUG "%s is invalid\n", optstr); | 1483 | printk(KERN_DEBUG "%s is invalid\n", optstr); |
| 1484 | return -EINVAL; | 1484 | return -EINVAL; |
| 1485 | } | 1485 | } |
diff --git a/arch/x86/purgatory/Makefile b/arch/x86/purgatory/Makefile new file mode 100644 index 000000000000..7fde9ee438a4 --- /dev/null +++ b/arch/x86/purgatory/Makefile | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | purgatory-y := purgatory.o stack.o setup-x86_$(BITS).o sha256.o entry64.o string.o | ||
| 2 | |||
| 3 | targets += $(purgatory-y) | ||
| 4 | PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y)) | ||
| 5 | |||
| 6 | LDFLAGS_purgatory.ro := -e purgatory_start -r --no-undefined -nostdlib -z nodefaultlib | ||
| 7 | targets += purgatory.ro | ||
| 8 | |||
| 9 | # Default KBUILD_CFLAGS can have -pg option set when FTRACE is enabled. That | ||
| 10 | # in turn leaves some undefined symbols like __fentry__ in purgatory and not | ||
| 11 | # sure how to relocate those. Like kexec-tools, use custom flags. | ||
| 12 | |||
| 13 | KBUILD_CFLAGS := -fno-strict-aliasing -Wall -Wstrict-prototypes -fno-zero-initialized-in-bss -fno-builtin -ffreestanding -c -MD -Os -mcmodel=large | ||
| 14 | |||
| 15 | $(obj)/purgatory.ro: $(PURGATORY_OBJS) FORCE | ||
| 16 | $(call if_changed,ld) | ||
| 17 | |||
| 18 | targets += kexec-purgatory.c | ||
| 19 | |||
| 20 | quiet_cmd_bin2c = BIN2C $@ | ||
| 21 | cmd_bin2c = cat $(obj)/purgatory.ro | $(objtree)/scripts/basic/bin2c kexec_purgatory > $(obj)/kexec-purgatory.c | ||
| 22 | |||
| 23 | $(obj)/kexec-purgatory.c: $(obj)/purgatory.ro FORCE | ||
| 24 | $(call if_changed,bin2c) | ||
| 25 | |||
| 26 | |||
| 27 | # No loaders for 32bits yet. | ||
| 28 | ifeq ($(CONFIG_X86_64),y) | ||
| 29 | obj-$(CONFIG_KEXEC) += kexec-purgatory.o | ||
| 30 | endif | ||
diff --git a/arch/x86/purgatory/entry64.S b/arch/x86/purgatory/entry64.S new file mode 100644 index 000000000000..d1a4291d3568 --- /dev/null +++ b/arch/x86/purgatory/entry64.S | |||
| @@ -0,0 +1,101 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2003,2004 Eric Biederman (ebiederm@xmission.com) | ||
| 3 | * Copyright (C) 2014 Red Hat Inc. | ||
| 4 | |||
| 5 | * Author(s): Vivek Goyal <vgoyal@redhat.com> | ||
| 6 | * | ||
| 7 | * This code has been taken from kexec-tools. | ||
| 8 | * | ||
| 9 | * This source code is licensed under the GNU General Public License, | ||
| 10 | * Version 2. See the file COPYING for more details. | ||
| 11 | */ | ||
| 12 | |||
| 13 | .text | ||
| 14 | .balign 16 | ||
| 15 | .code64 | ||
| 16 | .globl entry64, entry64_regs | ||
| 17 | |||
| 18 | |||
| 19 | entry64: | ||
| 20 | /* Setup a gdt that should be preserved */ | ||
| 21 | lgdt gdt(%rip) | ||
| 22 | |||
| 23 | /* load the data segments */ | ||
| 24 | movl $0x18, %eax /* data segment */ | ||
| 25 | movl %eax, %ds | ||
| 26 | movl %eax, %es | ||
| 27 | movl %eax, %ss | ||
| 28 | movl %eax, %fs | ||
| 29 | movl %eax, %gs | ||
| 30 | |||
| 31 | /* Setup new stack */ | ||
| 32 | leaq stack_init(%rip), %rsp | ||
| 33 | pushq $0x10 /* CS */ | ||
| 34 | leaq new_cs_exit(%rip), %rax | ||
| 35 | pushq %rax | ||
| 36 | lretq | ||
| 37 | new_cs_exit: | ||
| 38 | |||
| 39 | /* Load the registers */ | ||
| 40 | movq rax(%rip), %rax | ||
| 41 | movq rbx(%rip), %rbx | ||
| 42 | movq rcx(%rip), %rcx | ||
| 43 | movq rdx(%rip), %rdx | ||
| 44 | movq rsi(%rip), %rsi | ||
| 45 | movq rdi(%rip), %rdi | ||
| 46 | movq rsp(%rip), %rsp | ||
| 47 | movq rbp(%rip), %rbp | ||
| 48 | movq r8(%rip), %r8 | ||
| 49 | movq r9(%rip), %r9 | ||
| 50 | movq r10(%rip), %r10 | ||
| 51 | movq r11(%rip), %r11 | ||
| 52 | movq r12(%rip), %r12 | ||
| 53 | movq r13(%rip), %r13 | ||
| 54 | movq r14(%rip), %r14 | ||
| 55 | movq r15(%rip), %r15 | ||
| 56 | |||
| 57 | /* Jump to the new code... */ | ||
| 58 | jmpq *rip(%rip) | ||
| 59 | |||
| 60 | .section ".rodata" | ||
| 61 | .balign 4 | ||
| 62 | entry64_regs: | ||
| 63 | rax: .quad 0x0 | ||
| 64 | rcx: .quad 0x0 | ||
| 65 | rdx: .quad 0x0 | ||
| 66 | rbx: .quad 0x0 | ||
| 67 | rsp: .quad 0x0 | ||
| 68 | rbp: .quad 0x0 | ||
| 69 | rsi: .quad 0x0 | ||
| 70 | rdi: .quad 0x0 | ||
| 71 | r8: .quad 0x0 | ||
| 72 | r9: .quad 0x0 | ||
| 73 | r10: .quad 0x0 | ||
| 74 | r11: .quad 0x0 | ||
| 75 | r12: .quad 0x0 | ||
| 76 | r13: .quad 0x0 | ||
| 77 | r14: .quad 0x0 | ||
| 78 | r15: .quad 0x0 | ||
| 79 | rip: .quad 0x0 | ||
| 80 | .size entry64_regs, . - entry64_regs | ||
| 81 | |||
| 82 | /* GDT */ | ||
| 83 | .section ".rodata" | ||
| 84 | .balign 16 | ||
| 85 | gdt: | ||
| 86 | /* 0x00 unusable segment | ||
| 87 | * 0x08 unused | ||
| 88 | * so use them as gdt ptr | ||
| 89 | */ | ||
| 90 | .word gdt_end - gdt - 1 | ||
| 91 | .quad gdt | ||
| 92 | .word 0, 0, 0 | ||
| 93 | |||
| 94 | /* 0x10 4GB flat code segment */ | ||
| 95 | .word 0xFFFF, 0x0000, 0x9A00, 0x00AF | ||
| 96 | |||
| 97 | /* 0x18 4GB flat data segment */ | ||
| 98 | .word 0xFFFF, 0x0000, 0x9200, 0x00CF | ||
| 99 | gdt_end: | ||
| 100 | stack: .quad 0, 0 | ||
| 101 | stack_init: | ||
diff --git a/arch/x86/purgatory/purgatory.c b/arch/x86/purgatory/purgatory.c new file mode 100644 index 000000000000..25e068ba3382 --- /dev/null +++ b/arch/x86/purgatory/purgatory.c | |||
| @@ -0,0 +1,72 @@ | |||
| 1 | /* | ||
| 2 | * purgatory: Runs between two kernels | ||
| 3 | * | ||
| 4 | * Copyright (C) 2014 Red Hat Inc. | ||
| 5 | * | ||
| 6 | * Author: | ||
| 7 | * Vivek Goyal <vgoyal@redhat.com> | ||
| 8 | * | ||
| 9 | * This source code is licensed under the GNU General Public License, | ||
| 10 | * Version 2. See the file COPYING for more details. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include "sha256.h" | ||
| 14 | #include "../boot/string.h" | ||
| 15 | |||
| 16 | struct sha_region { | ||
| 17 | unsigned long start; | ||
| 18 | unsigned long len; | ||
| 19 | }; | ||
| 20 | |||
| 21 | unsigned long backup_dest = 0; | ||
| 22 | unsigned long backup_src = 0; | ||
| 23 | unsigned long backup_sz = 0; | ||
| 24 | |||
| 25 | u8 sha256_digest[SHA256_DIGEST_SIZE] = { 0 }; | ||
| 26 | |||
| 27 | struct sha_region sha_regions[16] = {}; | ||
| 28 | |||
| 29 | /* | ||
| 30 | * On x86, second kernel requries first 640K of memory to boot. Copy | ||
| 31 | * first 640K to a backup region in reserved memory range so that second | ||
| 32 | * kernel can use first 640K. | ||
| 33 | */ | ||
| 34 | static int copy_backup_region(void) | ||
| 35 | { | ||
| 36 | if (backup_dest) | ||
| 37 | memcpy((void *)backup_dest, (void *)backup_src, backup_sz); | ||
| 38 | |||
| 39 | return 0; | ||
| 40 | } | ||
| 41 | |||
| 42 | int verify_sha256_digest(void) | ||
| 43 | { | ||
| 44 | struct sha_region *ptr, *end; | ||
| 45 | u8 digest[SHA256_DIGEST_SIZE]; | ||
| 46 | struct sha256_state sctx; | ||
| 47 | |||
| 48 | sha256_init(&sctx); | ||
| 49 | end = &sha_regions[sizeof(sha_regions)/sizeof(sha_regions[0])]; | ||
| 50 | for (ptr = sha_regions; ptr < end; ptr++) | ||
| 51 | sha256_update(&sctx, (uint8_t *)(ptr->start), ptr->len); | ||
| 52 | |||
| 53 | sha256_final(&sctx, digest); | ||
| 54 | |||
| 55 | if (memcmp(digest, sha256_digest, sizeof(digest))) | ||
| 56 | return 1; | ||
| 57 | |||
| 58 | return 0; | ||
| 59 | } | ||
| 60 | |||
| 61 | void purgatory(void) | ||
| 62 | { | ||
| 63 | int ret; | ||
| 64 | |||
| 65 | ret = verify_sha256_digest(); | ||
| 66 | if (ret) { | ||
| 67 | /* loop forever */ | ||
| 68 | for (;;) | ||
| 69 | ; | ||
| 70 | } | ||
| 71 | copy_backup_region(); | ||
| 72 | } | ||
diff --git a/arch/x86/purgatory/setup-x86_64.S b/arch/x86/purgatory/setup-x86_64.S new file mode 100644 index 000000000000..fe3c91ba1bd0 --- /dev/null +++ b/arch/x86/purgatory/setup-x86_64.S | |||
| @@ -0,0 +1,58 @@ | |||
| 1 | /* | ||
| 2 | * purgatory: setup code | ||
| 3 | * | ||
| 4 | * Copyright (C) 2003,2004 Eric Biederman (ebiederm@xmission.com) | ||
| 5 | * Copyright (C) 2014 Red Hat Inc. | ||
| 6 | * | ||
| 7 | * This code has been taken from kexec-tools. | ||
| 8 | * | ||
| 9 | * This source code is licensed under the GNU General Public License, | ||
| 10 | * Version 2. See the file COPYING for more details. | ||
| 11 | */ | ||
| 12 | |||
| 13 | .text | ||
| 14 | .globl purgatory_start | ||
| 15 | .balign 16 | ||
| 16 | purgatory_start: | ||
| 17 | .code64 | ||
| 18 | |||
| 19 | /* Load a gdt so I know what the segment registers are */ | ||
| 20 | lgdt gdt(%rip) | ||
| 21 | |||
| 22 | /* load the data segments */ | ||
| 23 | movl $0x18, %eax /* data segment */ | ||
| 24 | movl %eax, %ds | ||
| 25 | movl %eax, %es | ||
| 26 | movl %eax, %ss | ||
| 27 | movl %eax, %fs | ||
| 28 | movl %eax, %gs | ||
| 29 | |||
| 30 | /* Setup a stack */ | ||
| 31 | leaq lstack_end(%rip), %rsp | ||
| 32 | |||
| 33 | /* Call the C code */ | ||
| 34 | call purgatory | ||
| 35 | jmp entry64 | ||
| 36 | |||
| 37 | .section ".rodata" | ||
| 38 | .balign 16 | ||
| 39 | gdt: /* 0x00 unusable segment | ||
| 40 | * 0x08 unused | ||
| 41 | * so use them as the gdt ptr | ||
| 42 | */ | ||
| 43 | .word gdt_end - gdt - 1 | ||
| 44 | .quad gdt | ||
| 45 | .word 0, 0, 0 | ||
| 46 | |||
| 47 | /* 0x10 4GB flat code segment */ | ||
| 48 | .word 0xFFFF, 0x0000, 0x9A00, 0x00AF | ||
| 49 | |||
| 50 | /* 0x18 4GB flat data segment */ | ||
| 51 | .word 0xFFFF, 0x0000, 0x9200, 0x00CF | ||
| 52 | gdt_end: | ||
| 53 | |||
| 54 | .bss | ||
| 55 | .balign 4096 | ||
| 56 | lstack: | ||
| 57 | .skip 4096 | ||
| 58 | lstack_end: | ||
diff --git a/arch/x86/purgatory/sha256.c b/arch/x86/purgatory/sha256.c new file mode 100644 index 000000000000..548ca675a14a --- /dev/null +++ b/arch/x86/purgatory/sha256.c | |||
| @@ -0,0 +1,283 @@ | |||
| 1 | /* | ||
| 2 | * SHA-256, as specified in | ||
| 3 | * http://csrc.nist.gov/groups/STM/cavp/documents/shs/sha256-384-512.pdf | ||
| 4 | * | ||
| 5 | * SHA-256 code by Jean-Luc Cooke <jlcooke@certainkey.com>. | ||
| 6 | * | ||
| 7 | * Copyright (c) Jean-Luc Cooke <jlcooke@certainkey.com> | ||
| 8 | * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk> | ||
| 9 | * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> | ||
| 10 | * Copyright (c) 2014 Red Hat Inc. | ||
| 11 | * | ||
| 12 | * This program is free software; you can redistribute it and/or modify it | ||
| 13 | * under the terms of the GNU General Public License as published by the Free | ||
| 14 | * Software Foundation; either version 2 of the License, or (at your option) | ||
| 15 | * any later version. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <linux/bitops.h> | ||
| 19 | #include <asm/byteorder.h> | ||
| 20 | #include "sha256.h" | ||
| 21 | #include "../boot/string.h" | ||
| 22 | |||
| 23 | static inline u32 Ch(u32 x, u32 y, u32 z) | ||
| 24 | { | ||
| 25 | return z ^ (x & (y ^ z)); | ||
| 26 | } | ||
| 27 | |||
| 28 | static inline u32 Maj(u32 x, u32 y, u32 z) | ||
| 29 | { | ||
| 30 | return (x & y) | (z & (x | y)); | ||
| 31 | } | ||
| 32 | |||
| 33 | #define e0(x) (ror32(x, 2) ^ ror32(x, 13) ^ ror32(x, 22)) | ||
| 34 | #define e1(x) (ror32(x, 6) ^ ror32(x, 11) ^ ror32(x, 25)) | ||
| 35 | #define s0(x) (ror32(x, 7) ^ ror32(x, 18) ^ (x >> 3)) | ||
| 36 | #define s1(x) (ror32(x, 17) ^ ror32(x, 19) ^ (x >> 10)) | ||
| 37 | |||
| 38 | static inline void LOAD_OP(int I, u32 *W, const u8 *input) | ||
| 39 | { | ||
| 40 | W[I] = __be32_to_cpu(((__be32 *)(input))[I]); | ||
| 41 | } | ||
| 42 | |||
| 43 | static inline void BLEND_OP(int I, u32 *W) | ||
| 44 | { | ||
| 45 | W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16]; | ||
| 46 | } | ||
| 47 | |||
| 48 | static void sha256_transform(u32 *state, const u8 *input) | ||
| 49 | { | ||
| 50 | u32 a, b, c, d, e, f, g, h, t1, t2; | ||
| 51 | u32 W[64]; | ||
| 52 | int i; | ||
| 53 | |||
| 54 | /* load the input */ | ||
| 55 | for (i = 0; i < 16; i++) | ||
| 56 | LOAD_OP(i, W, input); | ||
| 57 | |||
| 58 | /* now blend */ | ||
| 59 | for (i = 16; i < 64; i++) | ||
| 60 | BLEND_OP(i, W); | ||
| 61 | |||
| 62 | /* load the state into our registers */ | ||
| 63 | a = state[0]; b = state[1]; c = state[2]; d = state[3]; | ||
| 64 | e = state[4]; f = state[5]; g = state[6]; h = state[7]; | ||
| 65 | |||
| 66 | /* now iterate */ | ||
| 67 | t1 = h + e1(e) + Ch(e, f, g) + 0x428a2f98 + W[0]; | ||
| 68 | t2 = e0(a) + Maj(a, b, c); d += t1; h = t1 + t2; | ||
| 69 | t1 = g + e1(d) + Ch(d, e, f) + 0x71374491 + W[1]; | ||
| 70 | t2 = e0(h) + Maj(h, a, b); c += t1; g = t1 + t2; | ||
| 71 | t1 = f + e1(c) + Ch(c, d, e) + 0xb5c0fbcf + W[2]; | ||
| 72 | t2 = e0(g) + Maj(g, h, a); b += t1; f = t1 + t2; | ||
| 73 | t1 = e + e1(b) + Ch(b, c, d) + 0xe9b5dba5 + W[3]; | ||
| 74 | t2 = e0(f) + Maj(f, g, h); a += t1; e = t1 + t2; | ||
| 75 | t1 = d + e1(a) + Ch(a, b, c) + 0x3956c25b + W[4]; | ||
| 76 | t2 = e0(e) + Maj(e, f, g); h += t1; d = t1 + t2; | ||
| 77 | t1 = c + e1(h) + Ch(h, a, b) + 0x59f111f1 + W[5]; | ||
| 78 | t2 = e0(d) + Maj(d, e, f); g += t1; c = t1 + t2; | ||
| 79 | t1 = b + e1(g) + Ch(g, h, a) + 0x923f82a4 + W[6]; | ||
| 80 | t2 = e0(c) + Maj(c, d, e); f += t1; b = t1 + t2; | ||
| 81 | t1 = a + e1(f) + Ch(f, g, h) + 0xab1c5ed5 + W[7]; | ||
| 82 | t2 = e0(b) + Maj(b, c, d); e += t1; a = t1 + t2; | ||
| 83 | |||
| 84 | t1 = h + e1(e) + Ch(e, f, g) + 0xd807aa98 + W[8]; | ||
| 85 | t2 = e0(a) + Maj(a, b, c); d += t1; h = t1 + t2; | ||
| 86 | t1 = g + e1(d) + Ch(d, e, f) + 0x12835b01 + W[9]; | ||
| 87 | t2 = e0(h) + Maj(h, a, b); c += t1; g = t1 + t2; | ||
| 88 | t1 = f + e1(c) + Ch(c, d, e) + 0x243185be + W[10]; | ||
| 89 | t2 = e0(g) + Maj(g, h, a); b += t1; f = t1 + t2; | ||
| 90 | t1 = e + e1(b) + Ch(b, c, d) + 0x550c7dc3 + W[11]; | ||
| 91 | t2 = e0(f) + Maj(f, g, h); a += t1; e = t1 + t2; | ||
| 92 | t1 = d + e1(a) + Ch(a, b, c) + 0x72be5d74 + W[12]; | ||
| 93 | t2 = e0(e) + Maj(e, f, g); h += t1; d = t1 + t2; | ||
| 94 | t1 = c + e1(h) + Ch(h, a, b) + 0x80deb1fe + W[13]; | ||
| 95 | t2 = e0(d) + Maj(d, e, f); g += t1; c = t1 + t2; | ||
| 96 | t1 = b + e1(g) + Ch(g, h, a) + 0x9bdc06a7 + W[14]; | ||
| 97 | t2 = e0(c) + Maj(c, d, e); f += t1; b = t1 + t2; | ||
| 98 | t1 = a + e1(f) + Ch(f, g, h) + 0xc19bf174 + W[15]; | ||
| 99 | t2 = e0(b) + Maj(b, c, d); e += t1; a = t1+t2; | ||
| 100 | |||
| 101 | t1 = h + e1(e) + Ch(e, f, g) + 0xe49b69c1 + W[16]; | ||
| 102 | t2 = e0(a) + Maj(a, b, c); d += t1; h = t1+t2; | ||
| 103 | t1 = g + e1(d) + Ch(d, e, f) + 0xefbe4786 + W[17]; | ||
| 104 | t2 = e0(h) + Maj(h, a, b); c += t1; g = t1+t2; | ||
| 105 | t1 = f + e1(c) + Ch(c, d, e) + 0x0fc19dc6 + W[18]; | ||
| 106 | t2 = e0(g) + Maj(g, h, a); b += t1; f = t1+t2; | ||
| 107 | t1 = e + e1(b) + Ch(b, c, d) + 0x240ca1cc + W[19]; | ||
| 108 | t2 = e0(f) + Maj(f, g, h); a += t1; e = t1+t2; | ||
| 109 | t1 = d + e1(a) + Ch(a, b, c) + 0x2de92c6f + W[20]; | ||
| 110 | t2 = e0(e) + Maj(e, f, g); h += t1; d = t1+t2; | ||
| 111 | t1 = c + e1(h) + Ch(h, a, b) + 0x4a7484aa + W[21]; | ||
| 112 | t2 = e0(d) + Maj(d, e, f); g += t1; c = t1+t2; | ||
| 113 | t1 = b + e1(g) + Ch(g, h, a) + 0x5cb0a9dc + W[22]; | ||
| 114 | t2 = e0(c) + Maj(c, d, e); f += t1; b = t1+t2; | ||
| 115 | t1 = a + e1(f) + Ch(f, g, h) + 0x76f988da + W[23]; | ||
| 116 | t2 = e0(b) + Maj(b, c, d); e += t1; a = t1+t2; | ||
| 117 | |||
| 118 | t1 = h + e1(e) + Ch(e, f, g) + 0x983e5152 + W[24]; | ||
| 119 | t2 = e0(a) + Maj(a, b, c); d += t1; h = t1+t2; | ||
| 120 | t1 = g + e1(d) + Ch(d, e, f) + 0xa831c66d + W[25]; | ||
| 121 | t2 = e0(h) + Maj(h, a, b); c += t1; g = t1+t2; | ||
| 122 | t1 = f + e1(c) + Ch(c, d, e) + 0xb00327c8 + W[26]; | ||
| 123 | t2 = e0(g) + Maj(g, h, a); b += t1; f = t1+t2; | ||
| 124 | t1 = e + e1(b) + Ch(b, c, d) + 0xbf597fc7 + W[27]; | ||
| 125 | t2 = e0(f) + Maj(f, g, h); a += t1; e = t1+t2; | ||
| 126 | t1 = d + e1(a) + Ch(a, b, c) + 0xc6e00bf3 + W[28]; | ||
| 127 | t2 = e0(e) + Maj(e, f, g); h += t1; d = t1+t2; | ||
| 128 | t1 = c + e1(h) + Ch(h, a, b) + 0xd5a79147 + W[29]; | ||
| 129 | t2 = e0(d) + Maj(d, e, f); g += t1; c = t1+t2; | ||
| 130 | t1 = b + e1(g) + Ch(g, h, a) + 0x06ca6351 + W[30]; | ||
| 131 | t2 = e0(c) + Maj(c, d, e); f += t1; b = t1+t2; | ||
| 132 | t1 = a + e1(f) + Ch(f, g, h) + 0x14292967 + W[31]; | ||
| 133 | t2 = e0(b) + Maj(b, c, d); e += t1; a = t1+t2; | ||
| 134 | |||
| 135 | t1 = h + e1(e) + Ch(e, f, g) + 0x27b70a85 + W[32]; | ||
| 136 | t2 = e0(a) + Maj(a, b, c); d += t1; h = t1+t2; | ||
| 137 | t1 = g + e1(d) + Ch(d, e, f) + 0x2e1b2138 + W[33]; | ||
| 138 | t2 = e0(h) + Maj(h, a, b); c += t1; g = t1+t2; | ||
| 139 | t1 = f + e1(c) + Ch(c, d, e) + 0x4d2c6dfc + W[34]; | ||
| 140 | t2 = e0(g) + Maj(g, h, a); b += t1; f = t1+t2; | ||
| 141 | t1 = e + e1(b) + Ch(b, c, d) + 0x53380d13 + W[35]; | ||
| 142 | t2 = e0(f) + Maj(f, g, h); a += t1; e = t1+t2; | ||
| 143 | t1 = d + e1(a) + Ch(a, b, c) + 0x650a7354 + W[36]; | ||
| 144 | t2 = e0(e) + Maj(e, f, g); h += t1; d = t1+t2; | ||
| 145 | t1 = c + e1(h) + Ch(h, a, b) + 0x766a0abb + W[37]; | ||
| 146 | t2 = e0(d) + Maj(d, e, f); g += t1; c = t1+t2; | ||
| 147 | t1 = b + e1(g) + Ch(g, h, a) + 0x81c2c92e + W[38]; | ||
| 148 | t2 = e0(c) + Maj(c, d, e); f += t1; b = t1+t2; | ||
| 149 | t1 = a + e1(f) + Ch(f, g, h) + 0x92722c85 + W[39]; | ||
| 150 | t2 = e0(b) + Maj(b, c, d); e += t1; a = t1+t2; | ||
| 151 | |||
| 152 | t1 = h + e1(e) + Ch(e, f, g) + 0xa2bfe8a1 + W[40]; | ||
| 153 | t2 = e0(a) + Maj(a, b, c); d += t1; h = t1+t2; | ||
| 154 | t1 = g + e1(d) + Ch(d, e, f) + 0xa81a664b + W[41]; | ||
| 155 | t2 = e0(h) + Maj(h, a, b); c += t1; g = t1+t2; | ||
| 156 | t1 = f + e1(c) + Ch(c, d, e) + 0xc24b8b70 + W[42]; | ||
| 157 | t2 = e0(g) + Maj(g, h, a); b += t1; f = t1+t2; | ||
| 158 | t1 = e + e1(b) + Ch(b, c, d) + 0xc76c51a3 + W[43]; | ||
| 159 | t2 = e0(f) + Maj(f, g, h); a += t1; e = t1+t2; | ||
| 160 | t1 = d + e1(a) + Ch(a, b, c) + 0xd192e819 + W[44]; | ||
| 161 | t2 = e0(e) + Maj(e, f, g); h += t1; d = t1+t2; | ||
| 162 | t1 = c + e1(h) + Ch(h, a, b) + 0xd6990624 + W[45]; | ||
| 163 | t2 = e0(d) + Maj(d, e, f); g += t1; c = t1+t2; | ||
| 164 | t1 = b + e1(g) + Ch(g, h, a) + 0xf40e3585 + W[46]; | ||
| 165 | t2 = e0(c) + Maj(c, d, e); f += t1; b = t1+t2; | ||
| 166 | t1 = a + e1(f) + Ch(f, g, h) + 0x106aa070 + W[47]; | ||
| 167 | t2 = e0(b) + Maj(b, c, d); e += t1; a = t1+t2; | ||
| 168 | |||
| 169 | t1 = h + e1(e) + Ch(e, f, g) + 0x19a4c116 + W[48]; | ||
| 170 | t2 = e0(a) + Maj(a, b, c); d += t1; h = t1+t2; | ||
| 171 | t1 = g + e1(d) + Ch(d, e, f) + 0x1e376c08 + W[49]; | ||
| 172 | t2 = e0(h) + Maj(h, a, b); c += t1; g = t1+t2; | ||
| 173 | t1 = f + e1(c) + Ch(c, d, e) + 0x2748774c + W[50]; | ||
| 174 | t2 = e0(g) + Maj(g, h, a); b += t1; f = t1+t2; | ||
| 175 | t1 = e + e1(b) + Ch(b, c, d) + 0x34b0bcb5 + W[51]; | ||
| 176 | t2 = e0(f) + Maj(f, g, h); a += t1; e = t1+t2; | ||
| 177 | t1 = d + e1(a) + Ch(a, b, c) + 0x391c0cb3 + W[52]; | ||
| 178 | t2 = e0(e) + Maj(e, f, g); h += t1; d = t1+t2; | ||
| 179 | t1 = c + e1(h) + Ch(h, a, b) + 0x4ed8aa4a + W[53]; | ||
| 180 | t2 = e0(d) + Maj(d, e, f); g += t1; c = t1+t2; | ||
| 181 | t1 = b + e1(g) + Ch(g, h, a) + 0x5b9cca4f + W[54]; | ||
| 182 | t2 = e0(c) + Maj(c, d, e); f += t1; b = t1+t2; | ||
| 183 | t1 = a + e1(f) + Ch(f, g, h) + 0x682e6ff3 + W[55]; | ||
| 184 | t2 = e0(b) + Maj(b, c, d); e += t1; a = t1+t2; | ||
| 185 | |||
| 186 | t1 = h + e1(e) + Ch(e, f, g) + 0x748f82ee + W[56]; | ||
| 187 | t2 = e0(a) + Maj(a, b, c); d += t1; h = t1+t2; | ||
| 188 | t1 = g + e1(d) + Ch(d, e, f) + 0x78a5636f + W[57]; | ||
| 189 | t2 = e0(h) + Maj(h, a, b); c += t1; g = t1+t2; | ||
| 190 | t1 = f + e1(c) + Ch(c, d, e) + 0x84c87814 + W[58]; | ||
| 191 | t2 = e0(g) + Maj(g, h, a); b += t1; f = t1+t2; | ||
| 192 | t1 = e + e1(b) + Ch(b, c, d) + 0x8cc70208 + W[59]; | ||
| 193 | t2 = e0(f) + Maj(f, g, h); a += t1; e = t1+t2; | ||
| 194 | t1 = d + e1(a) + Ch(a, b, c) + 0x90befffa + W[60]; | ||
| 195 | t2 = e0(e) + Maj(e, f, g); h += t1; d = t1+t2; | ||
| 196 | t1 = c + e1(h) + Ch(h, a, b) + 0xa4506ceb + W[61]; | ||
| 197 | t2 = e0(d) + Maj(d, e, f); g += t1; c = t1+t2; | ||
| 198 | t1 = b + e1(g) + Ch(g, h, a) + 0xbef9a3f7 + W[62]; | ||
| 199 | t2 = e0(c) + Maj(c, d, e); f += t1; b = t1+t2; | ||
| 200 | t1 = a + e1(f) + Ch(f, g, h) + 0xc67178f2 + W[63]; | ||
| 201 | t2 = e0(b) + Maj(b, c, d); e += t1; a = t1+t2; | ||
| 202 | |||
| 203 | state[0] += a; state[1] += b; state[2] += c; state[3] += d; | ||
| 204 | state[4] += e; state[5] += f; state[6] += g; state[7] += h; | ||
| 205 | |||
| 206 | /* clear any sensitive info... */ | ||
| 207 | a = b = c = d = e = f = g = h = t1 = t2 = 0; | ||
| 208 | memset(W, 0, 64 * sizeof(u32)); | ||
| 209 | } | ||
| 210 | |||
| 211 | int sha256_init(struct sha256_state *sctx) | ||
| 212 | { | ||
| 213 | sctx->state[0] = SHA256_H0; | ||
| 214 | sctx->state[1] = SHA256_H1; | ||
| 215 | sctx->state[2] = SHA256_H2; | ||
| 216 | sctx->state[3] = SHA256_H3; | ||
| 217 | sctx->state[4] = SHA256_H4; | ||
| 218 | sctx->state[5] = SHA256_H5; | ||
| 219 | sctx->state[6] = SHA256_H6; | ||
| 220 | sctx->state[7] = SHA256_H7; | ||
| 221 | sctx->count = 0; | ||
| 222 | |||
| 223 | return 0; | ||
| 224 | } | ||
| 225 | |||
| 226 | int sha256_update(struct sha256_state *sctx, const u8 *data, unsigned int len) | ||
| 227 | { | ||
| 228 | unsigned int partial, done; | ||
| 229 | const u8 *src; | ||
| 230 | |||
| 231 | partial = sctx->count & 0x3f; | ||
| 232 | sctx->count += len; | ||
| 233 | done = 0; | ||
| 234 | src = data; | ||
| 235 | |||
| 236 | if ((partial + len) > 63) { | ||
| 237 | if (partial) { | ||
| 238 | done = -partial; | ||
| 239 | memcpy(sctx->buf + partial, data, done + 64); | ||
| 240 | src = sctx->buf; | ||
| 241 | } | ||
| 242 | |||
| 243 | do { | ||
| 244 | sha256_transform(sctx->state, src); | ||
| 245 | done += 64; | ||
| 246 | src = data + done; | ||
| 247 | } while (done + 63 < len); | ||
| 248 | |||
| 249 | partial = 0; | ||
| 250 | } | ||
| 251 | memcpy(sctx->buf + partial, src, len - done); | ||
| 252 | |||
| 253 | return 0; | ||
| 254 | } | ||
| 255 | |||
| 256 | int sha256_final(struct sha256_state *sctx, u8 *out) | ||
| 257 | { | ||
| 258 | __be32 *dst = (__be32 *)out; | ||
| 259 | __be64 bits; | ||
| 260 | unsigned int index, pad_len; | ||
| 261 | int i; | ||
| 262 | static const u8 padding[64] = { 0x80, }; | ||
| 263 | |||
| 264 | /* Save number of bits */ | ||
| 265 | bits = cpu_to_be64(sctx->count << 3); | ||
| 266 | |||
| 267 | /* Pad out to 56 mod 64. */ | ||
| 268 | index = sctx->count & 0x3f; | ||
| 269 | pad_len = (index < 56) ? (56 - index) : ((64+56) - index); | ||
| 270 | sha256_update(sctx, padding, pad_len); | ||
| 271 | |||
| 272 | /* Append length (before padding) */ | ||
| 273 | sha256_update(sctx, (const u8 *)&bits, sizeof(bits)); | ||
| 274 | |||
| 275 | /* Store state in digest */ | ||
| 276 | for (i = 0; i < 8; i++) | ||
| 277 | dst[i] = cpu_to_be32(sctx->state[i]); | ||
| 278 | |||
| 279 | /* Zeroize sensitive information. */ | ||
| 280 | memset(sctx, 0, sizeof(*sctx)); | ||
| 281 | |||
| 282 | return 0; | ||
| 283 | } | ||
diff --git a/arch/x86/purgatory/sha256.h b/arch/x86/purgatory/sha256.h new file mode 100644 index 000000000000..bd15a4127735 --- /dev/null +++ b/arch/x86/purgatory/sha256.h | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2014 Red Hat Inc. | ||
| 3 | * | ||
| 4 | * Author: Vivek Goyal <vgoyal@redhat.com> | ||
| 5 | * | ||
| 6 | * This source code is licensed under the GNU General Public License, | ||
| 7 | * Version 2. See the file COPYING for more details. | ||
| 8 | */ | ||
| 9 | |||
| 10 | #ifndef SHA256_H | ||
| 11 | #define SHA256_H | ||
| 12 | |||
| 13 | |||
| 14 | #include <linux/types.h> | ||
| 15 | #include <crypto/sha.h> | ||
| 16 | |||
| 17 | extern int sha256_init(struct sha256_state *sctx); | ||
| 18 | extern int sha256_update(struct sha256_state *sctx, const u8 *input, | ||
| 19 | unsigned int length); | ||
| 20 | extern int sha256_final(struct sha256_state *sctx, u8 *hash); | ||
| 21 | |||
| 22 | #endif /* SHA256_H */ | ||
diff --git a/arch/x86/purgatory/stack.S b/arch/x86/purgatory/stack.S new file mode 100644 index 000000000000..3cefba1fefc8 --- /dev/null +++ b/arch/x86/purgatory/stack.S | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | /* | ||
| 2 | * purgatory: stack | ||
| 3 | * | ||
| 4 | * Copyright (C) 2014 Red Hat Inc. | ||
| 5 | * | ||
| 6 | * This source code is licensed under the GNU General Public License, | ||
| 7 | * Version 2. See the file COPYING for more details. | ||
| 8 | */ | ||
| 9 | |||
| 10 | /* A stack for the loaded kernel. | ||
| 11 | * Seperate and in the data section so it can be prepopulated. | ||
| 12 | */ | ||
| 13 | .data | ||
| 14 | .balign 4096 | ||
| 15 | .globl stack, stack_end | ||
| 16 | |||
| 17 | stack: | ||
| 18 | .skip 4096 | ||
| 19 | stack_end: | ||
diff --git a/arch/x86/purgatory/string.c b/arch/x86/purgatory/string.c new file mode 100644 index 000000000000..d886b1fa36f0 --- /dev/null +++ b/arch/x86/purgatory/string.c | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | /* | ||
| 2 | * Simple string functions. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2014 Red Hat Inc. | ||
| 5 | * | ||
| 6 | * Author: | ||
| 7 | * Vivek Goyal <vgoyal@redhat.com> | ||
| 8 | * | ||
| 9 | * This source code is licensed under the GNU General Public License, | ||
| 10 | * Version 2. See the file COPYING for more details. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include "../boot/string.c" | ||
diff --git a/arch/x86/syscalls/syscall_32.tbl b/arch/x86/syscalls/syscall_32.tbl index d1b4a119d4a5..028b78168d85 100644 --- a/arch/x86/syscalls/syscall_32.tbl +++ b/arch/x86/syscalls/syscall_32.tbl | |||
| @@ -362,3 +362,4 @@ | |||
| 362 | 353 i386 renameat2 sys_renameat2 | 362 | 353 i386 renameat2 sys_renameat2 |
| 363 | 354 i386 seccomp sys_seccomp | 363 | 354 i386 seccomp sys_seccomp |
| 364 | 355 i386 getrandom sys_getrandom | 364 | 355 i386 getrandom sys_getrandom |
| 365 | 356 i386 memfd_create sys_memfd_create | ||
diff --git a/arch/x86/syscalls/syscall_64.tbl b/arch/x86/syscalls/syscall_64.tbl index 252c804bb1aa..35dd922727b9 100644 --- a/arch/x86/syscalls/syscall_64.tbl +++ b/arch/x86/syscalls/syscall_64.tbl | |||
| @@ -325,6 +325,8 @@ | |||
| 325 | 316 common renameat2 sys_renameat2 | 325 | 316 common renameat2 sys_renameat2 |
| 326 | 317 common seccomp sys_seccomp | 326 | 317 common seccomp sys_seccomp |
| 327 | 318 common getrandom sys_getrandom | 327 | 318 common getrandom sys_getrandom |
| 328 | 319 common memfd_create sys_memfd_create | ||
| 329 | 320 common kexec_file_load sys_kexec_file_load | ||
| 328 | 330 | ||
| 329 | # | 331 | # |
| 330 | # x32-specific system call numbers start at 512 to avoid cache impact | 332 | # x32-specific system call numbers start at 512 to avoid cache impact |
diff --git a/arch/x86/um/asm/elf.h b/arch/x86/um/asm/elf.h index 0feee2fd5077..25a1022dd793 100644 --- a/arch/x86/um/asm/elf.h +++ b/arch/x86/um/asm/elf.h | |||
| @@ -216,6 +216,5 @@ extern long elf_aux_hwcap; | |||
| 216 | #define ELF_HWCAP (elf_aux_hwcap) | 216 | #define ELF_HWCAP (elf_aux_hwcap) |
| 217 | 217 | ||
| 218 | #define SET_PERSONALITY(ex) do ; while(0) | 218 | #define SET_PERSONALITY(ex) do ; while(0) |
| 219 | #define __HAVE_ARCH_GATE_AREA 1 | ||
| 220 | 219 | ||
| 221 | #endif | 220 | #endif |
diff --git a/arch/x86/um/mem_64.c b/arch/x86/um/mem_64.c index c6492e75797b..f8fecaddcc0d 100644 --- a/arch/x86/um/mem_64.c +++ b/arch/x86/um/mem_64.c | |||
| @@ -9,18 +9,3 @@ const char *arch_vma_name(struct vm_area_struct *vma) | |||
| 9 | 9 | ||
| 10 | return NULL; | 10 | return NULL; |
| 11 | } | 11 | } |
| 12 | |||
| 13 | struct vm_area_struct *get_gate_vma(struct mm_struct *mm) | ||
| 14 | { | ||
| 15 | return NULL; | ||
| 16 | } | ||
| 17 | |||
| 18 | int in_gate_area(struct mm_struct *mm, unsigned long addr) | ||
| 19 | { | ||
| 20 | return 0; | ||
| 21 | } | ||
| 22 | |||
| 23 | int in_gate_area_no_mm(unsigned long addr) | ||
| 24 | { | ||
| 25 | return 0; | ||
| 26 | } | ||
diff --git a/arch/x86/vdso/vdso32-setup.c b/arch/x86/vdso/vdso32-setup.c index e4f7781ee162..e904c270573b 100644 --- a/arch/x86/vdso/vdso32-setup.c +++ b/arch/x86/vdso/vdso32-setup.c | |||
| @@ -115,23 +115,6 @@ static __init int ia32_binfmt_init(void) | |||
| 115 | return 0; | 115 | return 0; |
| 116 | } | 116 | } |
| 117 | __initcall(ia32_binfmt_init); | 117 | __initcall(ia32_binfmt_init); |
| 118 | #endif | 118 | #endif /* CONFIG_SYSCTL */ |
| 119 | |||
| 120 | #else /* CONFIG_X86_32 */ | ||
| 121 | |||
| 122 | struct vm_area_struct *get_gate_vma(struct mm_struct *mm) | ||
| 123 | { | ||
| 124 | return NULL; | ||
| 125 | } | ||
| 126 | |||
| 127 | int in_gate_area(struct mm_struct *mm, unsigned long addr) | ||
| 128 | { | ||
| 129 | return 0; | ||
| 130 | } | ||
| 131 | |||
| 132 | int in_gate_area_no_mm(unsigned long addr) | ||
| 133 | { | ||
| 134 | return 0; | ||
| 135 | } | ||
| 136 | 119 | ||
| 137 | #endif /* CONFIG_X86_64 */ | 120 | #endif /* CONFIG_X86_64 */ |
diff --git a/crypto/zlib.c b/crypto/zlib.c index 06b62e5cdcc7..c9ee681d57fd 100644 --- a/crypto/zlib.c +++ b/crypto/zlib.c | |||
| @@ -168,7 +168,7 @@ static int zlib_compress_update(struct crypto_pcomp *tfm, | |||
| 168 | } | 168 | } |
| 169 | 169 | ||
| 170 | ret = req->avail_out - stream->avail_out; | 170 | ret = req->avail_out - stream->avail_out; |
| 171 | pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n", | 171 | pr_debug("avail_in %lu, avail_out %lu (consumed %lu, produced %u)\n", |
| 172 | stream->avail_in, stream->avail_out, | 172 | stream->avail_in, stream->avail_out, |
| 173 | req->avail_in - stream->avail_in, ret); | 173 | req->avail_in - stream->avail_in, ret); |
| 174 | req->next_in = stream->next_in; | 174 | req->next_in = stream->next_in; |
| @@ -198,7 +198,7 @@ static int zlib_compress_final(struct crypto_pcomp *tfm, | |||
| 198 | } | 198 | } |
| 199 | 199 | ||
| 200 | ret = req->avail_out - stream->avail_out; | 200 | ret = req->avail_out - stream->avail_out; |
| 201 | pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n", | 201 | pr_debug("avail_in %lu, avail_out %lu (consumed %lu, produced %u)\n", |
| 202 | stream->avail_in, stream->avail_out, | 202 | stream->avail_in, stream->avail_out, |
| 203 | req->avail_in - stream->avail_in, ret); | 203 | req->avail_in - stream->avail_in, ret); |
| 204 | req->next_in = stream->next_in; | 204 | req->next_in = stream->next_in; |
| @@ -283,7 +283,7 @@ static int zlib_decompress_update(struct crypto_pcomp *tfm, | |||
| 283 | } | 283 | } |
| 284 | 284 | ||
| 285 | ret = req->avail_out - stream->avail_out; | 285 | ret = req->avail_out - stream->avail_out; |
| 286 | pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n", | 286 | pr_debug("avail_in %lu, avail_out %lu (consumed %lu, produced %u)\n", |
| 287 | stream->avail_in, stream->avail_out, | 287 | stream->avail_in, stream->avail_out, |
| 288 | req->avail_in - stream->avail_in, ret); | 288 | req->avail_in - stream->avail_in, ret); |
| 289 | req->next_in = stream->next_in; | 289 | req->next_in = stream->next_in; |
| @@ -331,7 +331,7 @@ static int zlib_decompress_final(struct crypto_pcomp *tfm, | |||
| 331 | } | 331 | } |
| 332 | 332 | ||
| 333 | ret = req->avail_out - stream->avail_out; | 333 | ret = req->avail_out - stream->avail_out; |
| 334 | pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n", | 334 | pr_debug("avail_in %lu, avail_out %lu (consumed %lu, produced %u)\n", |
| 335 | stream->avail_in, stream->avail_out, | 335 | stream->avail_in, stream->avail_out, |
| 336 | req->avail_in - stream->avail_in, ret); | 336 | req->avail_in - stream->avail_in, ret); |
| 337 | req->next_in = stream->next_in; | 337 | req->next_in = stream->next_in; |
diff --git a/drivers/atm/he.c b/drivers/atm/he.c index aa6be2698669..c39702bc279d 100644 --- a/drivers/atm/he.c +++ b/drivers/atm/he.c | |||
| @@ -533,14 +533,13 @@ static void he_init_tx_lbfp(struct he_dev *he_dev) | |||
| 533 | 533 | ||
| 534 | static int he_init_tpdrq(struct he_dev *he_dev) | 534 | static int he_init_tpdrq(struct he_dev *he_dev) |
| 535 | { | 535 | { |
| 536 | he_dev->tpdrq_base = pci_alloc_consistent(he_dev->pci_dev, | 536 | he_dev->tpdrq_base = pci_zalloc_consistent(he_dev->pci_dev, |
| 537 | CONFIG_TPDRQ_SIZE * sizeof(struct he_tpdrq), &he_dev->tpdrq_phys); | 537 | CONFIG_TPDRQ_SIZE * sizeof(struct he_tpdrq), |
| 538 | &he_dev->tpdrq_phys); | ||
| 538 | if (he_dev->tpdrq_base == NULL) { | 539 | if (he_dev->tpdrq_base == NULL) { |
| 539 | hprintk("failed to alloc tpdrq\n"); | 540 | hprintk("failed to alloc tpdrq\n"); |
| 540 | return -ENOMEM; | 541 | return -ENOMEM; |
| 541 | } | 542 | } |
| 542 | memset(he_dev->tpdrq_base, 0, | ||
| 543 | CONFIG_TPDRQ_SIZE * sizeof(struct he_tpdrq)); | ||
| 544 | 543 | ||
| 545 | he_dev->tpdrq_tail = he_dev->tpdrq_base; | 544 | he_dev->tpdrq_tail = he_dev->tpdrq_base; |
| 546 | he_dev->tpdrq_head = he_dev->tpdrq_base; | 545 | he_dev->tpdrq_head = he_dev->tpdrq_base; |
| @@ -804,13 +803,13 @@ static int he_init_group(struct he_dev *he_dev, int group) | |||
| 804 | goto out_free_rbpl_virt; | 803 | goto out_free_rbpl_virt; |
| 805 | } | 804 | } |
| 806 | 805 | ||
| 807 | he_dev->rbpl_base = pci_alloc_consistent(he_dev->pci_dev, | 806 | he_dev->rbpl_base = pci_zalloc_consistent(he_dev->pci_dev, |
| 808 | CONFIG_RBPL_SIZE * sizeof(struct he_rbp), &he_dev->rbpl_phys); | 807 | CONFIG_RBPL_SIZE * sizeof(struct he_rbp), |
| 808 | &he_dev->rbpl_phys); | ||
| 809 | if (he_dev->rbpl_base == NULL) { | 809 | if (he_dev->rbpl_base == NULL) { |
| 810 | hprintk("failed to alloc rbpl_base\n"); | 810 | hprintk("failed to alloc rbpl_base\n"); |
| 811 | goto out_destroy_rbpl_pool; | 811 | goto out_destroy_rbpl_pool; |
| 812 | } | 812 | } |
| 813 | memset(he_dev->rbpl_base, 0, CONFIG_RBPL_SIZE * sizeof(struct he_rbp)); | ||
| 814 | 813 | ||
| 815 | INIT_LIST_HEAD(&he_dev->rbpl_outstanding); | 814 | INIT_LIST_HEAD(&he_dev->rbpl_outstanding); |
| 816 | 815 | ||
| @@ -843,13 +842,13 @@ static int he_init_group(struct he_dev *he_dev, int group) | |||
| 843 | 842 | ||
| 844 | /* rx buffer ready queue */ | 843 | /* rx buffer ready queue */ |
| 845 | 844 | ||
| 846 | he_dev->rbrq_base = pci_alloc_consistent(he_dev->pci_dev, | 845 | he_dev->rbrq_base = pci_zalloc_consistent(he_dev->pci_dev, |
| 847 | CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), &he_dev->rbrq_phys); | 846 | CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), |
| 847 | &he_dev->rbrq_phys); | ||
| 848 | if (he_dev->rbrq_base == NULL) { | 848 | if (he_dev->rbrq_base == NULL) { |
| 849 | hprintk("failed to allocate rbrq\n"); | 849 | hprintk("failed to allocate rbrq\n"); |
| 850 | goto out_free_rbpl; | 850 | goto out_free_rbpl; |
| 851 | } | 851 | } |
| 852 | memset(he_dev->rbrq_base, 0, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq)); | ||
| 853 | 852 | ||
| 854 | he_dev->rbrq_head = he_dev->rbrq_base; | 853 | he_dev->rbrq_head = he_dev->rbrq_base; |
| 855 | he_writel(he_dev, he_dev->rbrq_phys, G0_RBRQ_ST + (group * 16)); | 854 | he_writel(he_dev, he_dev->rbrq_phys, G0_RBRQ_ST + (group * 16)); |
| @@ -867,13 +866,13 @@ static int he_init_group(struct he_dev *he_dev, int group) | |||
| 867 | 866 | ||
| 868 | /* tx buffer ready queue */ | 867 | /* tx buffer ready queue */ |
| 869 | 868 | ||
| 870 | he_dev->tbrq_base = pci_alloc_consistent(he_dev->pci_dev, | 869 | he_dev->tbrq_base = pci_zalloc_consistent(he_dev->pci_dev, |
| 871 | CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), &he_dev->tbrq_phys); | 870 | CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), |
| 871 | &he_dev->tbrq_phys); | ||
| 872 | if (he_dev->tbrq_base == NULL) { | 872 | if (he_dev->tbrq_base == NULL) { |
| 873 | hprintk("failed to allocate tbrq\n"); | 873 | hprintk("failed to allocate tbrq\n"); |
| 874 | goto out_free_rbpq_base; | 874 | goto out_free_rbpq_base; |
| 875 | } | 875 | } |
| 876 | memset(he_dev->tbrq_base, 0, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq)); | ||
| 877 | 876 | ||
| 878 | he_dev->tbrq_head = he_dev->tbrq_base; | 877 | he_dev->tbrq_head = he_dev->tbrq_base; |
| 879 | 878 | ||
| @@ -1460,13 +1459,13 @@ static int he_start(struct atm_dev *dev) | |||
| 1460 | 1459 | ||
| 1461 | /* host status page */ | 1460 | /* host status page */ |
| 1462 | 1461 | ||
| 1463 | he_dev->hsp = pci_alloc_consistent(he_dev->pci_dev, | 1462 | he_dev->hsp = pci_zalloc_consistent(he_dev->pci_dev, |
| 1464 | sizeof(struct he_hsp), &he_dev->hsp_phys); | 1463 | sizeof(struct he_hsp), |
| 1464 | &he_dev->hsp_phys); | ||
| 1465 | if (he_dev->hsp == NULL) { | 1465 | if (he_dev->hsp == NULL) { |
| 1466 | hprintk("failed to allocate host status page\n"); | 1466 | hprintk("failed to allocate host status page\n"); |
| 1467 | return -ENOMEM; | 1467 | return -ENOMEM; |
| 1468 | } | 1468 | } |
| 1469 | memset(he_dev->hsp, 0, sizeof(struct he_hsp)); | ||
| 1470 | he_writel(he_dev, he_dev->hsp_phys, HSP_BA); | 1469 | he_writel(he_dev, he_dev->hsp_phys, HSP_BA); |
| 1471 | 1470 | ||
| 1472 | /* initialize framer */ | 1471 | /* initialize framer */ |
diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c index b621f56a36be..2b24ed056728 100644 --- a/drivers/atm/idt77252.c +++ b/drivers/atm/idt77252.c | |||
| @@ -641,13 +641,11 @@ alloc_scq(struct idt77252_dev *card, int class) | |||
| 641 | scq = kzalloc(sizeof(struct scq_info), GFP_KERNEL); | 641 | scq = kzalloc(sizeof(struct scq_info), GFP_KERNEL); |
| 642 | if (!scq) | 642 | if (!scq) |
| 643 | return NULL; | 643 | return NULL; |
| 644 | scq->base = pci_alloc_consistent(card->pcidev, SCQ_SIZE, | 644 | scq->base = pci_zalloc_consistent(card->pcidev, SCQ_SIZE, &scq->paddr); |
| 645 | &scq->paddr); | ||
| 646 | if (scq->base == NULL) { | 645 | if (scq->base == NULL) { |
| 647 | kfree(scq); | 646 | kfree(scq); |
| 648 | return NULL; | 647 | return NULL; |
| 649 | } | 648 | } |
| 650 | memset(scq->base, 0, SCQ_SIZE); | ||
| 651 | 649 | ||
| 652 | scq->next = scq->base; | 650 | scq->next = scq->base; |
| 653 | scq->last = scq->base + (SCQ_ENTRIES - 1); | 651 | scq->last = scq->base + (SCQ_ENTRIES - 1); |
| @@ -972,13 +970,12 @@ init_rsq(struct idt77252_dev *card) | |||
| 972 | { | 970 | { |
| 973 | struct rsq_entry *rsqe; | 971 | struct rsq_entry *rsqe; |
| 974 | 972 | ||
| 975 | card->rsq.base = pci_alloc_consistent(card->pcidev, RSQSIZE, | 973 | card->rsq.base = pci_zalloc_consistent(card->pcidev, RSQSIZE, |
| 976 | &card->rsq.paddr); | 974 | &card->rsq.paddr); |
| 977 | if (card->rsq.base == NULL) { | 975 | if (card->rsq.base == NULL) { |
| 978 | printk("%s: can't allocate RSQ.\n", card->name); | 976 | printk("%s: can't allocate RSQ.\n", card->name); |
| 979 | return -1; | 977 | return -1; |
| 980 | } | 978 | } |
| 981 | memset(card->rsq.base, 0, RSQSIZE); | ||
| 982 | 979 | ||
| 983 | card->rsq.last = card->rsq.base + RSQ_NUM_ENTRIES - 1; | 980 | card->rsq.last = card->rsq.base + RSQ_NUM_ENTRIES - 1; |
| 984 | card->rsq.next = card->rsq.last; | 981 | card->rsq.next = card->rsq.last; |
| @@ -3400,14 +3397,14 @@ static int init_card(struct atm_dev *dev) | |||
| 3400 | writel(0, SAR_REG_GP); | 3397 | writel(0, SAR_REG_GP); |
| 3401 | 3398 | ||
| 3402 | /* Initialize RAW Cell Handle Register */ | 3399 | /* Initialize RAW Cell Handle Register */ |
| 3403 | card->raw_cell_hnd = pci_alloc_consistent(card->pcidev, 2 * sizeof(u32), | 3400 | card->raw_cell_hnd = pci_zalloc_consistent(card->pcidev, |
| 3404 | &card->raw_cell_paddr); | 3401 | 2 * sizeof(u32), |
| 3402 | &card->raw_cell_paddr); | ||
| 3405 | if (!card->raw_cell_hnd) { | 3403 | if (!card->raw_cell_hnd) { |
| 3406 | printk("%s: memory allocation failure.\n", card->name); | 3404 | printk("%s: memory allocation failure.\n", card->name); |
| 3407 | deinit_card(card); | 3405 | deinit_card(card); |
| 3408 | return -1; | 3406 | return -1; |
| 3409 | } | 3407 | } |
| 3410 | memset(card->raw_cell_hnd, 0, 2 * sizeof(u32)); | ||
| 3411 | writel(card->raw_cell_paddr, SAR_REG_RAWHND); | 3408 | writel(card->raw_cell_paddr, SAR_REG_RAWHND); |
| 3412 | IPRINTK("%s: raw cell handle is at 0x%p.\n", card->name, | 3409 | IPRINTK("%s: raw cell handle is at 0x%p.\n", card->name, |
| 3413 | card->raw_cell_hnd); | 3410 | card->raw_cell_hnd); |
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c index 125d84505738..811e11c82f32 100644 --- a/drivers/block/DAC960.c +++ b/drivers/block/DAC960.c | |||
| @@ -6741,11 +6741,11 @@ static long DAC960_gam_ioctl(struct file *file, unsigned int Request, | |||
| 6741 | ErrorCode = -ENOMEM; | 6741 | ErrorCode = -ENOMEM; |
| 6742 | if (DataTransferLength > 0) | 6742 | if (DataTransferLength > 0) |
| 6743 | { | 6743 | { |
| 6744 | DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice, | 6744 | DataTransferBuffer = pci_zalloc_consistent(Controller->PCIDevice, |
| 6745 | DataTransferLength, &DataTransferBufferDMA); | 6745 | DataTransferLength, |
| 6746 | &DataTransferBufferDMA); | ||
| 6746 | if (DataTransferBuffer == NULL) | 6747 | if (DataTransferBuffer == NULL) |
| 6747 | break; | 6748 | break; |
| 6748 | memset(DataTransferBuffer, 0, DataTransferLength); | ||
| 6749 | } | 6749 | } |
| 6750 | else if (DataTransferLength < 0) | 6750 | else if (DataTransferLength < 0) |
| 6751 | { | 6751 | { |
| @@ -6877,11 +6877,11 @@ static long DAC960_gam_ioctl(struct file *file, unsigned int Request, | |||
| 6877 | ErrorCode = -ENOMEM; | 6877 | ErrorCode = -ENOMEM; |
| 6878 | if (DataTransferLength > 0) | 6878 | if (DataTransferLength > 0) |
| 6879 | { | 6879 | { |
| 6880 | DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice, | 6880 | DataTransferBuffer = pci_zalloc_consistent(Controller->PCIDevice, |
| 6881 | DataTransferLength, &DataTransferBufferDMA); | 6881 | DataTransferLength, |
| 6882 | &DataTransferBufferDMA); | ||
| 6882 | if (DataTransferBuffer == NULL) | 6883 | if (DataTransferBuffer == NULL) |
| 6883 | break; | 6884 | break; |
| 6884 | memset(DataTransferBuffer, 0, DataTransferLength); | ||
| 6885 | } | 6885 | } |
| 6886 | else if (DataTransferLength < 0) | 6886 | else if (DataTransferLength < 0) |
| 6887 | { | 6887 | { |
| @@ -6899,14 +6899,14 @@ static long DAC960_gam_ioctl(struct file *file, unsigned int Request, | |||
| 6899 | RequestSenseLength = UserCommand.RequestSenseLength; | 6899 | RequestSenseLength = UserCommand.RequestSenseLength; |
| 6900 | if (RequestSenseLength > 0) | 6900 | if (RequestSenseLength > 0) |
| 6901 | { | 6901 | { |
| 6902 | RequestSenseBuffer = pci_alloc_consistent(Controller->PCIDevice, | 6902 | RequestSenseBuffer = pci_zalloc_consistent(Controller->PCIDevice, |
| 6903 | RequestSenseLength, &RequestSenseBufferDMA); | 6903 | RequestSenseLength, |
| 6904 | &RequestSenseBufferDMA); | ||
| 6904 | if (RequestSenseBuffer == NULL) | 6905 | if (RequestSenseBuffer == NULL) |
| 6905 | { | 6906 | { |
| 6906 | ErrorCode = -ENOMEM; | 6907 | ErrorCode = -ENOMEM; |
| 6907 | goto Failure2; | 6908 | goto Failure2; |
| 6908 | } | 6909 | } |
| 6909 | memset(RequestSenseBuffer, 0, RequestSenseLength); | ||
| 6910 | } | 6910 | } |
| 6911 | spin_lock_irqsave(&Controller->queue_lock, flags); | 6911 | spin_lock_irqsave(&Controller->queue_lock, flags); |
| 6912 | while ((Command = DAC960_AllocateCommand(Controller)) == NULL) | 6912 | while ((Command = DAC960_AllocateCommand(Controller)) == NULL) |
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 4595c22f33f7..ff20f192b0f6 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
| @@ -1014,24 +1014,21 @@ static CommandList_struct *cmd_special_alloc(ctlr_info_t *h) | |||
| 1014 | u64bit temp64; | 1014 | u64bit temp64; |
| 1015 | dma_addr_t cmd_dma_handle, err_dma_handle; | 1015 | dma_addr_t cmd_dma_handle, err_dma_handle; |
| 1016 | 1016 | ||
| 1017 | c = (CommandList_struct *) pci_alloc_consistent(h->pdev, | 1017 | c = pci_zalloc_consistent(h->pdev, sizeof(CommandList_struct), |
| 1018 | sizeof(CommandList_struct), &cmd_dma_handle); | 1018 | &cmd_dma_handle); |
| 1019 | if (c == NULL) | 1019 | if (c == NULL) |
| 1020 | return NULL; | 1020 | return NULL; |
| 1021 | memset(c, 0, sizeof(CommandList_struct)); | ||
| 1022 | 1021 | ||
| 1023 | c->cmdindex = -1; | 1022 | c->cmdindex = -1; |
| 1024 | 1023 | ||
| 1025 | c->err_info = (ErrorInfo_struct *) | 1024 | c->err_info = pci_zalloc_consistent(h->pdev, sizeof(ErrorInfo_struct), |
| 1026 | pci_alloc_consistent(h->pdev, sizeof(ErrorInfo_struct), | 1025 | &err_dma_handle); |
| 1027 | &err_dma_handle); | ||
| 1028 | 1026 | ||
| 1029 | if (c->err_info == NULL) { | 1027 | if (c->err_info == NULL) { |
| 1030 | pci_free_consistent(h->pdev, | 1028 | pci_free_consistent(h->pdev, |
| 1031 | sizeof(CommandList_struct), c, cmd_dma_handle); | 1029 | sizeof(CommandList_struct), c, cmd_dma_handle); |
| 1032 | return NULL; | 1030 | return NULL; |
| 1033 | } | 1031 | } |
| 1034 | memset(c->err_info, 0, sizeof(ErrorInfo_struct)); | ||
| 1035 | 1032 | ||
| 1036 | INIT_LIST_HEAD(&c->list); | 1033 | INIT_LIST_HEAD(&c->list); |
| 1037 | c->busaddr = (__u32) cmd_dma_handle; | 1034 | c->busaddr = (__u32) cmd_dma_handle; |
diff --git a/drivers/block/skd_main.c b/drivers/block/skd_main.c index 608532d3f8c9..f0a089df85cc 100644 --- a/drivers/block/skd_main.c +++ b/drivers/block/skd_main.c | |||
| @@ -4112,16 +4112,14 @@ static int skd_cons_skcomp(struct skd_device *skdev) | |||
| 4112 | skdev->name, __func__, __LINE__, | 4112 | skdev->name, __func__, __LINE__, |
| 4113 | nbytes, SKD_N_COMPLETION_ENTRY); | 4113 | nbytes, SKD_N_COMPLETION_ENTRY); |
| 4114 | 4114 | ||
| 4115 | skcomp = pci_alloc_consistent(skdev->pdev, nbytes, | 4115 | skcomp = pci_zalloc_consistent(skdev->pdev, nbytes, |
| 4116 | &skdev->cq_dma_address); | 4116 | &skdev->cq_dma_address); |
| 4117 | 4117 | ||
| 4118 | if (skcomp == NULL) { | 4118 | if (skcomp == NULL) { |
| 4119 | rc = -ENOMEM; | 4119 | rc = -ENOMEM; |
| 4120 | goto err_out; | 4120 | goto err_out; |
| 4121 | } | 4121 | } |
| 4122 | 4122 | ||
| 4123 | memset(skcomp, 0, nbytes); | ||
| 4124 | |||
| 4125 | skdev->skcomp_table = skcomp; | 4123 | skdev->skcomp_table = skcomp; |
| 4126 | skdev->skerr_table = (struct fit_comp_error_info *)((char *)skcomp + | 4124 | skdev->skerr_table = (struct fit_comp_error_info *)((char *)skcomp + |
| 4127 | sizeof(*skcomp) * | 4125 | sizeof(*skcomp) * |
| @@ -4304,15 +4302,14 @@ static int skd_cons_skspcl(struct skd_device *skdev) | |||
| 4304 | 4302 | ||
| 4305 | nbytes = SKD_N_SPECIAL_FITMSG_BYTES; | 4303 | nbytes = SKD_N_SPECIAL_FITMSG_BYTES; |
| 4306 | 4304 | ||
| 4307 | skspcl->msg_buf = pci_alloc_consistent(skdev->pdev, nbytes, | 4305 | skspcl->msg_buf = |
| 4308 | &skspcl->mb_dma_address); | 4306 | pci_zalloc_consistent(skdev->pdev, nbytes, |
| 4307 | &skspcl->mb_dma_address); | ||
| 4309 | if (skspcl->msg_buf == NULL) { | 4308 | if (skspcl->msg_buf == NULL) { |
| 4310 | rc = -ENOMEM; | 4309 | rc = -ENOMEM; |
| 4311 | goto err_out; | 4310 | goto err_out; |
| 4312 | } | 4311 | } |
| 4313 | 4312 | ||
| 4314 | memset(skspcl->msg_buf, 0, nbytes); | ||
| 4315 | |||
| 4316 | skspcl->req.sg = kzalloc(sizeof(struct scatterlist) * | 4313 | skspcl->req.sg = kzalloc(sizeof(struct scatterlist) * |
| 4317 | SKD_N_SG_PER_SPECIAL, GFP_KERNEL); | 4314 | SKD_N_SG_PER_SPECIAL, GFP_KERNEL); |
| 4318 | if (skspcl->req.sg == NULL) { | 4315 | if (skspcl->req.sg == NULL) { |
| @@ -4353,25 +4350,21 @@ static int skd_cons_sksb(struct skd_device *skdev) | |||
| 4353 | 4350 | ||
| 4354 | nbytes = SKD_N_INTERNAL_BYTES; | 4351 | nbytes = SKD_N_INTERNAL_BYTES; |
| 4355 | 4352 | ||
| 4356 | skspcl->data_buf = pci_alloc_consistent(skdev->pdev, nbytes, | 4353 | skspcl->data_buf = pci_zalloc_consistent(skdev->pdev, nbytes, |
| 4357 | &skspcl->db_dma_address); | 4354 | &skspcl->db_dma_address); |
| 4358 | if (skspcl->data_buf == NULL) { | 4355 | if (skspcl->data_buf == NULL) { |
| 4359 | rc = -ENOMEM; | 4356 | rc = -ENOMEM; |
| 4360 | goto err_out; | 4357 | goto err_out; |
| 4361 | } | 4358 | } |
| 4362 | 4359 | ||
| 4363 | memset(skspcl->data_buf, 0, nbytes); | ||
| 4364 | |||
| 4365 | nbytes = SKD_N_SPECIAL_FITMSG_BYTES; | 4360 | nbytes = SKD_N_SPECIAL_FITMSG_BYTES; |
| 4366 | skspcl->msg_buf = pci_alloc_consistent(skdev->pdev, nbytes, | 4361 | skspcl->msg_buf = pci_zalloc_consistent(skdev->pdev, nbytes, |
| 4367 | &skspcl->mb_dma_address); | 4362 | &skspcl->mb_dma_address); |
| 4368 | if (skspcl->msg_buf == NULL) { | 4363 | if (skspcl->msg_buf == NULL) { |
| 4369 | rc = -ENOMEM; | 4364 | rc = -ENOMEM; |
| 4370 | goto err_out; | 4365 | goto err_out; |
| 4371 | } | 4366 | } |
| 4372 | 4367 | ||
| 4373 | memset(skspcl->msg_buf, 0, nbytes); | ||
| 4374 | |||
| 4375 | skspcl->req.sksg_list = skd_cons_sg_list(skdev, 1, | 4368 | skspcl->req.sksg_list = skd_cons_sg_list(skdev, 1, |
| 4376 | &skspcl->req.sksg_dma_address); | 4369 | &skspcl->req.sksg_dma_address); |
| 4377 | if (skspcl->req.sksg_list == NULL) { | 4370 | if (skspcl->req.sksg_list == NULL) { |
diff --git a/drivers/crypto/hifn_795x.c b/drivers/crypto/hifn_795x.c index 12fea3e22348..8d2a7728434d 100644 --- a/drivers/crypto/hifn_795x.c +++ b/drivers/crypto/hifn_795x.c | |||
| @@ -2617,14 +2617,13 @@ static int hifn_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 2617 | } | 2617 | } |
| 2618 | } | 2618 | } |
| 2619 | 2619 | ||
| 2620 | dev->desc_virt = pci_alloc_consistent(pdev, sizeof(struct hifn_dma), | 2620 | dev->desc_virt = pci_zalloc_consistent(pdev, sizeof(struct hifn_dma), |
| 2621 | &dev->desc_dma); | 2621 | &dev->desc_dma); |
| 2622 | if (!dev->desc_virt) { | 2622 | if (!dev->desc_virt) { |
| 2623 | dprintk("Failed to allocate descriptor rings.\n"); | 2623 | dprintk("Failed to allocate descriptor rings.\n"); |
| 2624 | err = -ENOMEM; | 2624 | err = -ENOMEM; |
| 2625 | goto err_out_unmap_bars; | 2625 | goto err_out_unmap_bars; |
| 2626 | } | 2626 | } |
| 2627 | memset(dev->desc_virt, 0, sizeof(struct hifn_dma)); | ||
| 2628 | 2627 | ||
| 2629 | dev->pdev = pdev; | 2628 | dev->pdev = pdev; |
| 2630 | dev->irq = pdev->irq; | 2629 | dev->irq = pdev->irq; |
diff --git a/drivers/firmware/efi/runtime-map.c b/drivers/firmware/efi/runtime-map.c index 97cdd16a2169..018c29a26615 100644 --- a/drivers/firmware/efi/runtime-map.c +++ b/drivers/firmware/efi/runtime-map.c | |||
| @@ -138,6 +138,27 @@ add_sysfs_runtime_map_entry(struct kobject *kobj, int nr) | |||
| 138 | return entry; | 138 | return entry; |
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | int efi_get_runtime_map_size(void) | ||
| 142 | { | ||
| 143 | return nr_efi_runtime_map * efi_memdesc_size; | ||
| 144 | } | ||
| 145 | |||
| 146 | int efi_get_runtime_map_desc_size(void) | ||
| 147 | { | ||
| 148 | return efi_memdesc_size; | ||
| 149 | } | ||
| 150 | |||
| 151 | int efi_runtime_map_copy(void *buf, size_t bufsz) | ||
| 152 | { | ||
| 153 | size_t sz = efi_get_runtime_map_size(); | ||
| 154 | |||
| 155 | if (sz > bufsz) | ||
| 156 | sz = bufsz; | ||
| 157 | |||
| 158 | memcpy(buf, efi_runtime_map, sz); | ||
| 159 | return 0; | ||
| 160 | } | ||
| 161 | |||
| 141 | void efi_runtime_map_setup(void *map, int nr_entries, u32 desc_size) | 162 | void efi_runtime_map_setup(void *map, int nr_entries, u32 desc_size) |
| 142 | { | 163 | { |
| 143 | efi_runtime_map = map; | 164 | efi_runtime_map = map; |
diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c index e88bac1d781f..bae897de9468 100644 --- a/drivers/gpu/drm/i810/i810_dma.c +++ b/drivers/gpu/drm/i810/i810_dma.c | |||
| @@ -393,15 +393,14 @@ static int i810_dma_initialize(struct drm_device *dev, | |||
| 393 | 393 | ||
| 394 | /* Program Hardware Status Page */ | 394 | /* Program Hardware Status Page */ |
| 395 | dev_priv->hw_status_page = | 395 | dev_priv->hw_status_page = |
| 396 | pci_alloc_consistent(dev->pdev, PAGE_SIZE, | 396 | pci_zalloc_consistent(dev->pdev, PAGE_SIZE, |
| 397 | &dev_priv->dma_status_page); | 397 | &dev_priv->dma_status_page); |
| 398 | if (!dev_priv->hw_status_page) { | 398 | if (!dev_priv->hw_status_page) { |
| 399 | dev->dev_private = (void *)dev_priv; | 399 | dev->dev_private = (void *)dev_priv; |
| 400 | i810_dma_cleanup(dev); | 400 | i810_dma_cleanup(dev); |
| 401 | DRM_ERROR("Can not allocate hardware status page\n"); | 401 | DRM_ERROR("Can not allocate hardware status page\n"); |
| 402 | return -ENOMEM; | 402 | return -ENOMEM; |
| 403 | } | 403 | } |
| 404 | memset(dev_priv->hw_status_page, 0, PAGE_SIZE); | ||
| 405 | DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page); | 404 | DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page); |
| 406 | 405 | ||
| 407 | I810_WRITE(0x02080, dev_priv->dma_status_page); | 406 | I810_WRITE(0x02080, dev_priv->dma_status_page); |
diff --git a/drivers/infiniband/hw/amso1100/c2.c b/drivers/infiniband/hw/amso1100/c2.c index 00400c352c1a..766a71ccefed 100644 --- a/drivers/infiniband/hw/amso1100/c2.c +++ b/drivers/infiniband/hw/amso1100/c2.c | |||
| @@ -604,16 +604,14 @@ static int c2_up(struct net_device *netdev) | |||
| 604 | tx_size = c2_port->tx_ring.count * sizeof(struct c2_tx_desc); | 604 | tx_size = c2_port->tx_ring.count * sizeof(struct c2_tx_desc); |
| 605 | 605 | ||
| 606 | c2_port->mem_size = tx_size + rx_size; | 606 | c2_port->mem_size = tx_size + rx_size; |
| 607 | c2_port->mem = pci_alloc_consistent(c2dev->pcidev, c2_port->mem_size, | 607 | c2_port->mem = pci_zalloc_consistent(c2dev->pcidev, c2_port->mem_size, |
| 608 | &c2_port->dma); | 608 | &c2_port->dma); |
| 609 | if (c2_port->mem == NULL) { | 609 | if (c2_port->mem == NULL) { |
| 610 | pr_debug("Unable to allocate memory for " | 610 | pr_debug("Unable to allocate memory for " |
| 611 | "host descriptor rings\n"); | 611 | "host descriptor rings\n"); |
| 612 | return -ENOMEM; | 612 | return -ENOMEM; |
| 613 | } | 613 | } |
| 614 | 614 | ||
| 615 | memset(c2_port->mem, 0, c2_port->mem_size); | ||
| 616 | |||
| 617 | /* Create the Rx host descriptor ring */ | 615 | /* Create the Rx host descriptor ring */ |
| 618 | if ((ret = | 616 | if ((ret = |
| 619 | c2_rx_ring_alloc(&c2_port->rx_ring, c2_port->mem, c2_port->dma, | 617 | c2_rx_ring_alloc(&c2_port->rx_ring, c2_port->mem, c2_port->dma, |
diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c index 90200245c5eb..02120d340d50 100644 --- a/drivers/infiniband/hw/nes/nes_hw.c +++ b/drivers/infiniband/hw/nes/nes_hw.c | |||
| @@ -1003,13 +1003,13 @@ int nes_init_cqp(struct nes_device *nesdev) | |||
| 1003 | (sizeof(struct nes_hw_aeqe) * nesadapter->max_qp) + | 1003 | (sizeof(struct nes_hw_aeqe) * nesadapter->max_qp) + |
| 1004 | sizeof(struct nes_hw_cqp_qp_context); | 1004 | sizeof(struct nes_hw_cqp_qp_context); |
| 1005 | 1005 | ||
| 1006 | nesdev->cqp_vbase = pci_alloc_consistent(nesdev->pcidev, nesdev->cqp_mem_size, | 1006 | nesdev->cqp_vbase = pci_zalloc_consistent(nesdev->pcidev, |
| 1007 | &nesdev->cqp_pbase); | 1007 | nesdev->cqp_mem_size, |
| 1008 | &nesdev->cqp_pbase); | ||
| 1008 | if (!nesdev->cqp_vbase) { | 1009 | if (!nesdev->cqp_vbase) { |
| 1009 | nes_debug(NES_DBG_INIT, "Unable to allocate memory for host descriptor rings\n"); | 1010 | nes_debug(NES_DBG_INIT, "Unable to allocate memory for host descriptor rings\n"); |
| 1010 | return -ENOMEM; | 1011 | return -ENOMEM; |
| 1011 | } | 1012 | } |
| 1012 | memset(nesdev->cqp_vbase, 0, nesdev->cqp_mem_size); | ||
| 1013 | 1013 | ||
| 1014 | /* Allocate a twice the number of CQP requests as the SQ size */ | 1014 | /* Allocate a twice the number of CQP requests as the SQ size */ |
| 1015 | nesdev->nes_cqp_requests = kzalloc(sizeof(struct nes_cqp_request) * | 1015 | nesdev->nes_cqp_requests = kzalloc(sizeof(struct nes_cqp_request) * |
| @@ -1691,13 +1691,13 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev) | |||
| 1691 | (NES_NIC_WQ_SIZE * 2 * sizeof(struct nes_hw_nic_cqe)) + | 1691 | (NES_NIC_WQ_SIZE * 2 * sizeof(struct nes_hw_nic_cqe)) + |
| 1692 | sizeof(struct nes_hw_nic_qp_context); | 1692 | sizeof(struct nes_hw_nic_qp_context); |
| 1693 | 1693 | ||
| 1694 | nesvnic->nic_vbase = pci_alloc_consistent(nesdev->pcidev, nesvnic->nic_mem_size, | 1694 | nesvnic->nic_vbase = pci_zalloc_consistent(nesdev->pcidev, |
| 1695 | &nesvnic->nic_pbase); | 1695 | nesvnic->nic_mem_size, |
| 1696 | &nesvnic->nic_pbase); | ||
| 1696 | if (!nesvnic->nic_vbase) { | 1697 | if (!nesvnic->nic_vbase) { |
| 1697 | nes_debug(NES_DBG_INIT, "Unable to allocate memory for NIC host descriptor rings\n"); | 1698 | nes_debug(NES_DBG_INIT, "Unable to allocate memory for NIC host descriptor rings\n"); |
| 1698 | return -ENOMEM; | 1699 | return -ENOMEM; |
| 1699 | } | 1700 | } |
| 1700 | memset(nesvnic->nic_vbase, 0, nesvnic->nic_mem_size); | ||
| 1701 | nes_debug(NES_DBG_INIT, "Allocated NIC QP structures at %p (phys = %016lX), size = %u.\n", | 1701 | nes_debug(NES_DBG_INIT, "Allocated NIC QP structures at %p (phys = %016lX), size = %u.\n", |
| 1702 | nesvnic->nic_vbase, (unsigned long)nesvnic->nic_pbase, nesvnic->nic_mem_size); | 1702 | nesvnic->nic_vbase, (unsigned long)nesvnic->nic_pbase, nesvnic->nic_mem_size); |
| 1703 | 1703 | ||
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c index 218dd3574285..fef067c959fc 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.c +++ b/drivers/infiniband/hw/nes/nes_verbs.c | |||
| @@ -1616,8 +1616,8 @@ static struct ib_cq *nes_create_cq(struct ib_device *ibdev, int entries, | |||
| 1616 | entries, nescq->cq_mem_size, nescq->hw_cq.cq_number); | 1616 | entries, nescq->cq_mem_size, nescq->hw_cq.cq_number); |
| 1617 | 1617 | ||
| 1618 | /* allocate the physical buffer space */ | 1618 | /* allocate the physical buffer space */ |
| 1619 | mem = pci_alloc_consistent(nesdev->pcidev, nescq->cq_mem_size, | 1619 | mem = pci_zalloc_consistent(nesdev->pcidev, nescq->cq_mem_size, |
| 1620 | &nescq->hw_cq.cq_pbase); | 1620 | &nescq->hw_cq.cq_pbase); |
| 1621 | if (!mem) { | 1621 | if (!mem) { |
| 1622 | printk(KERN_ERR PFX "Unable to allocate pci memory for cq\n"); | 1622 | printk(KERN_ERR PFX "Unable to allocate pci memory for cq\n"); |
| 1623 | nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num); | 1623 | nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num); |
| @@ -1625,7 +1625,6 @@ static struct ib_cq *nes_create_cq(struct ib_device *ibdev, int entries, | |||
| 1625 | return ERR_PTR(-ENOMEM); | 1625 | return ERR_PTR(-ENOMEM); |
| 1626 | } | 1626 | } |
| 1627 | 1627 | ||
| 1628 | memset(mem, 0, nescq->cq_mem_size); | ||
| 1629 | nescq->hw_cq.cq_vbase = mem; | 1628 | nescq->hw_cq.cq_vbase = mem; |
| 1630 | nescq->hw_cq.cq_head = 0; | 1629 | nescq->hw_cq.cq_head = 0; |
| 1631 | nes_debug(NES_DBG_CQ, "CQ%u virtual address @ %p, phys = 0x%08X\n", | 1630 | nes_debug(NES_DBG_CQ, "CQ%u virtual address @ %p, phys = 0x%08X\n", |
diff --git a/drivers/media/common/saa7146/saa7146_core.c b/drivers/media/common/saa7146/saa7146_core.c index 34b0d0ddeef3..97afee672d07 100644 --- a/drivers/media/common/saa7146/saa7146_core.c +++ b/drivers/media/common/saa7146/saa7146_core.c | |||
| @@ -421,23 +421,20 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent | |||
| 421 | err = -ENOMEM; | 421 | err = -ENOMEM; |
| 422 | 422 | ||
| 423 | /* get memory for various stuff */ | 423 | /* get memory for various stuff */ |
| 424 | dev->d_rps0.cpu_addr = pci_alloc_consistent(pci, SAA7146_RPS_MEM, | 424 | dev->d_rps0.cpu_addr = pci_zalloc_consistent(pci, SAA7146_RPS_MEM, |
| 425 | &dev->d_rps0.dma_handle); | 425 | &dev->d_rps0.dma_handle); |
| 426 | if (!dev->d_rps0.cpu_addr) | 426 | if (!dev->d_rps0.cpu_addr) |
| 427 | goto err_free_irq; | 427 | goto err_free_irq; |
| 428 | memset(dev->d_rps0.cpu_addr, 0x0, SAA7146_RPS_MEM); | ||
| 429 | 428 | ||
| 430 | dev->d_rps1.cpu_addr = pci_alloc_consistent(pci, SAA7146_RPS_MEM, | 429 | dev->d_rps1.cpu_addr = pci_zalloc_consistent(pci, SAA7146_RPS_MEM, |
| 431 | &dev->d_rps1.dma_handle); | 430 | &dev->d_rps1.dma_handle); |
| 432 | if (!dev->d_rps1.cpu_addr) | 431 | if (!dev->d_rps1.cpu_addr) |
| 433 | goto err_free_rps0; | 432 | goto err_free_rps0; |
| 434 | memset(dev->d_rps1.cpu_addr, 0x0, SAA7146_RPS_MEM); | ||
| 435 | 433 | ||
| 436 | dev->d_i2c.cpu_addr = pci_alloc_consistent(pci, SAA7146_RPS_MEM, | 434 | dev->d_i2c.cpu_addr = pci_zalloc_consistent(pci, SAA7146_RPS_MEM, |
| 437 | &dev->d_i2c.dma_handle); | 435 | &dev->d_i2c.dma_handle); |
| 438 | if (!dev->d_i2c.cpu_addr) | 436 | if (!dev->d_i2c.cpu_addr) |
| 439 | goto err_free_rps1; | 437 | goto err_free_rps1; |
| 440 | memset(dev->d_i2c.cpu_addr, 0x0, SAA7146_RPS_MEM); | ||
| 441 | 438 | ||
| 442 | /* the rest + print status message */ | 439 | /* the rest + print status message */ |
| 443 | 440 | ||
diff --git a/drivers/media/common/saa7146/saa7146_fops.c b/drivers/media/common/saa7146/saa7146_fops.c index d9e1d6395ed9..6c47f3fe9b0f 100644 --- a/drivers/media/common/saa7146/saa7146_fops.c +++ b/drivers/media/common/saa7146/saa7146_fops.c | |||
| @@ -520,14 +520,15 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv) | |||
| 520 | configuration data) */ | 520 | configuration data) */ |
| 521 | dev->ext_vv_data = ext_vv; | 521 | dev->ext_vv_data = ext_vv; |
| 522 | 522 | ||
| 523 | vv->d_clipping.cpu_addr = pci_alloc_consistent(dev->pci, SAA7146_CLIPPING_MEM, &vv->d_clipping.dma_handle); | 523 | vv->d_clipping.cpu_addr = |
| 524 | pci_zalloc_consistent(dev->pci, SAA7146_CLIPPING_MEM, | ||
| 525 | &vv->d_clipping.dma_handle); | ||
| 524 | if( NULL == vv->d_clipping.cpu_addr ) { | 526 | if( NULL == vv->d_clipping.cpu_addr ) { |
| 525 | ERR("out of memory. aborting.\n"); | 527 | ERR("out of memory. aborting.\n"); |
| 526 | kfree(vv); | 528 | kfree(vv); |
| 527 | v4l2_ctrl_handler_free(hdl); | 529 | v4l2_ctrl_handler_free(hdl); |
| 528 | return -1; | 530 | return -1; |
| 529 | } | 531 | } |
| 530 | memset(vv->d_clipping.cpu_addr, 0x0, SAA7146_CLIPPING_MEM); | ||
| 531 | 532 | ||
| 532 | saa7146_video_uops.init(dev,vv); | 533 | saa7146_video_uops.init(dev,vv); |
| 533 | if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE) | 534 | if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE) |
diff --git a/drivers/media/pci/bt8xx/bt878.c b/drivers/media/pci/bt8xx/bt878.c index d0c281f41a0a..11765835d7b2 100644 --- a/drivers/media/pci/bt8xx/bt878.c +++ b/drivers/media/pci/bt8xx/bt878.c | |||
| @@ -101,28 +101,20 @@ static int bt878_mem_alloc(struct bt878 *bt) | |||
| 101 | if (!bt->buf_cpu) { | 101 | if (!bt->buf_cpu) { |
| 102 | bt->buf_size = 128 * 1024; | 102 | bt->buf_size = 128 * 1024; |
| 103 | 103 | ||
| 104 | bt->buf_cpu = | 104 | bt->buf_cpu = pci_zalloc_consistent(bt->dev, bt->buf_size, |
| 105 | pci_alloc_consistent(bt->dev, bt->buf_size, | 105 | &bt->buf_dma); |
| 106 | &bt->buf_dma); | ||
| 107 | |||
| 108 | if (!bt->buf_cpu) | 106 | if (!bt->buf_cpu) |
| 109 | return -ENOMEM; | 107 | return -ENOMEM; |
| 110 | |||
| 111 | memset(bt->buf_cpu, 0, bt->buf_size); | ||
| 112 | } | 108 | } |
| 113 | 109 | ||
| 114 | if (!bt->risc_cpu) { | 110 | if (!bt->risc_cpu) { |
| 115 | bt->risc_size = PAGE_SIZE; | 111 | bt->risc_size = PAGE_SIZE; |
| 116 | bt->risc_cpu = | 112 | bt->risc_cpu = pci_zalloc_consistent(bt->dev, bt->risc_size, |
| 117 | pci_alloc_consistent(bt->dev, bt->risc_size, | 113 | &bt->risc_dma); |
| 118 | &bt->risc_dma); | ||
| 119 | |||
| 120 | if (!bt->risc_cpu) { | 114 | if (!bt->risc_cpu) { |
| 121 | bt878_mem_free(bt); | 115 | bt878_mem_free(bt); |
| 122 | return -ENOMEM; | 116 | return -ENOMEM; |
| 123 | } | 117 | } |
| 124 | |||
| 125 | memset(bt->risc_cpu, 0, bt->risc_size); | ||
| 126 | } | 118 | } |
| 127 | 119 | ||
| 128 | return 0; | 120 | return 0; |
diff --git a/drivers/media/pci/ngene/ngene-core.c b/drivers/media/pci/ngene/ngene-core.c index 826228c3800e..4930b55fd5f4 100644 --- a/drivers/media/pci/ngene/ngene-core.c +++ b/drivers/media/pci/ngene/ngene-core.c | |||
| @@ -1075,12 +1075,11 @@ static int AllocCommonBuffers(struct ngene *dev) | |||
| 1075 | dev->ngenetohost = dev->FWInterfaceBuffer + 256; | 1075 | dev->ngenetohost = dev->FWInterfaceBuffer + 256; |
| 1076 | dev->EventBuffer = dev->FWInterfaceBuffer + 512; | 1076 | dev->EventBuffer = dev->FWInterfaceBuffer + 512; |
| 1077 | 1077 | ||
| 1078 | dev->OverflowBuffer = pci_alloc_consistent(dev->pci_dev, | 1078 | dev->OverflowBuffer = pci_zalloc_consistent(dev->pci_dev, |
| 1079 | OVERFLOW_BUFFER_SIZE, | 1079 | OVERFLOW_BUFFER_SIZE, |
| 1080 | &dev->PAOverflowBuffer); | 1080 | &dev->PAOverflowBuffer); |
| 1081 | if (!dev->OverflowBuffer) | 1081 | if (!dev->OverflowBuffer) |
| 1082 | return -ENOMEM; | 1082 | return -ENOMEM; |
| 1083 | memset(dev->OverflowBuffer, 0, OVERFLOW_BUFFER_SIZE); | ||
| 1084 | 1083 | ||
| 1085 | for (i = STREAM_VIDEOIN1; i < MAX_STREAM; i++) { | 1084 | for (i = STREAM_VIDEOIN1; i < MAX_STREAM; i++) { |
| 1086 | int type = dev->card_info->io_type[i]; | 1085 | int type = dev->card_info->io_type[i]; |
diff --git a/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c index f166ffc9800a..cef7a00099ea 100644 --- a/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c +++ b/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c | |||
| @@ -803,11 +803,9 @@ static int ttusb_alloc_iso_urbs(struct ttusb *ttusb) | |||
| 803 | { | 803 | { |
| 804 | int i; | 804 | int i; |
| 805 | 805 | ||
| 806 | ttusb->iso_buffer = pci_alloc_consistent(NULL, | 806 | ttusb->iso_buffer = pci_zalloc_consistent(NULL, |
| 807 | ISO_FRAME_SIZE * | 807 | ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF * ISO_BUF_COUNT, |
| 808 | FRAMES_PER_ISO_BUF * | 808 | &ttusb->iso_dma_handle); |
| 809 | ISO_BUF_COUNT, | ||
| 810 | &ttusb->iso_dma_handle); | ||
| 811 | 809 | ||
| 812 | if (!ttusb->iso_buffer) { | 810 | if (!ttusb->iso_buffer) { |
| 813 | dprintk("%s: pci_alloc_consistent - not enough memory\n", | 811 | dprintk("%s: pci_alloc_consistent - not enough memory\n", |
| @@ -815,9 +813,6 @@ static int ttusb_alloc_iso_urbs(struct ttusb *ttusb) | |||
| 815 | return -ENOMEM; | 813 | return -ENOMEM; |
| 816 | } | 814 | } |
| 817 | 815 | ||
| 818 | memset(ttusb->iso_buffer, 0, | ||
| 819 | ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF * ISO_BUF_COUNT); | ||
| 820 | |||
| 821 | for (i = 0; i < ISO_BUF_COUNT; i++) { | 816 | for (i = 0; i < ISO_BUF_COUNT; i++) { |
| 822 | struct urb *urb; | 817 | struct urb *urb; |
| 823 | 818 | ||
diff --git a/drivers/media/usb/ttusb-dec/ttusb_dec.c b/drivers/media/usb/ttusb-dec/ttusb_dec.c index 29724af9b9ab..15ab584cf265 100644 --- a/drivers/media/usb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/usb/ttusb-dec/ttusb_dec.c | |||
| @@ -1151,11 +1151,9 @@ static int ttusb_dec_alloc_iso_urbs(struct ttusb_dec *dec) | |||
| 1151 | 1151 | ||
| 1152 | dprintk("%s\n", __func__); | 1152 | dprintk("%s\n", __func__); |
| 1153 | 1153 | ||
| 1154 | dec->iso_buffer = pci_alloc_consistent(NULL, | 1154 | dec->iso_buffer = pci_zalloc_consistent(NULL, |
| 1155 | ISO_FRAME_SIZE * | 1155 | ISO_FRAME_SIZE * (FRAMES_PER_ISO_BUF * ISO_BUF_COUNT), |
| 1156 | (FRAMES_PER_ISO_BUF * | 1156 | &dec->iso_dma_handle); |
| 1157 | ISO_BUF_COUNT), | ||
| 1158 | &dec->iso_dma_handle); | ||
| 1159 | 1157 | ||
| 1160 | if (!dec->iso_buffer) { | 1158 | if (!dec->iso_buffer) { |
| 1161 | dprintk("%s: pci_alloc_consistent - not enough memory\n", | 1159 | dprintk("%s: pci_alloc_consistent - not enough memory\n", |
| @@ -1163,9 +1161,6 @@ static int ttusb_dec_alloc_iso_urbs(struct ttusb_dec *dec) | |||
| 1163 | return -ENOMEM; | 1161 | return -ENOMEM; |
| 1164 | } | 1162 | } |
| 1165 | 1163 | ||
| 1166 | memset(dec->iso_buffer, 0, | ||
| 1167 | ISO_FRAME_SIZE * (FRAMES_PER_ISO_BUF * ISO_BUF_COUNT)); | ||
| 1168 | |||
| 1169 | for (i = 0; i < ISO_BUF_COUNT; i++) { | 1164 | for (i = 0; i < ISO_BUF_COUNT; i++) { |
| 1170 | struct urb *urb; | 1165 | struct urb *urb; |
| 1171 | 1166 | ||
diff --git a/drivers/net/ethernet/amd/pcnet32.c b/drivers/net/ethernet/amd/pcnet32.c index e7cc9174e364..4a8fdc4721d5 100644 --- a/drivers/net/ethernet/amd/pcnet32.c +++ b/drivers/net/ethernet/amd/pcnet32.c | |||
| @@ -481,37 +481,32 @@ static void pcnet32_realloc_tx_ring(struct net_device *dev, | |||
| 481 | dma_addr_t *new_dma_addr_list; | 481 | dma_addr_t *new_dma_addr_list; |
| 482 | struct pcnet32_tx_head *new_tx_ring; | 482 | struct pcnet32_tx_head *new_tx_ring; |
| 483 | struct sk_buff **new_skb_list; | 483 | struct sk_buff **new_skb_list; |
| 484 | unsigned int entries = BIT(size); | ||
| 484 | 485 | ||
| 485 | pcnet32_purge_tx_ring(dev); | 486 | pcnet32_purge_tx_ring(dev); |
| 486 | 487 | ||
| 487 | new_tx_ring = pci_alloc_consistent(lp->pci_dev, | 488 | new_tx_ring = |
| 488 | sizeof(struct pcnet32_tx_head) * | 489 | pci_zalloc_consistent(lp->pci_dev, |
| 489 | (1 << size), | 490 | sizeof(struct pcnet32_tx_head) * entries, |
| 490 | &new_ring_dma_addr); | 491 | &new_ring_dma_addr); |
| 491 | if (new_tx_ring == NULL) { | 492 | if (new_tx_ring == NULL) |
| 492 | netif_err(lp, drv, dev, "Consistent memory allocation failed\n"); | ||
| 493 | return; | 493 | return; |
| 494 | } | ||
| 495 | memset(new_tx_ring, 0, sizeof(struct pcnet32_tx_head) * (1 << size)); | ||
| 496 | 494 | ||
| 497 | new_dma_addr_list = kcalloc(1 << size, sizeof(dma_addr_t), | 495 | new_dma_addr_list = kcalloc(entries, sizeof(dma_addr_t), GFP_ATOMIC); |
| 498 | GFP_ATOMIC); | ||
| 499 | if (!new_dma_addr_list) | 496 | if (!new_dma_addr_list) |
| 500 | goto free_new_tx_ring; | 497 | goto free_new_tx_ring; |
| 501 | 498 | ||
| 502 | new_skb_list = kcalloc(1 << size, sizeof(struct sk_buff *), | 499 | new_skb_list = kcalloc(entries, sizeof(struct sk_buff *), GFP_ATOMIC); |
| 503 | GFP_ATOMIC); | ||
| 504 | if (!new_skb_list) | 500 | if (!new_skb_list) |
| 505 | goto free_new_lists; | 501 | goto free_new_lists; |
| 506 | 502 | ||
| 507 | kfree(lp->tx_skbuff); | 503 | kfree(lp->tx_skbuff); |
| 508 | kfree(lp->tx_dma_addr); | 504 | kfree(lp->tx_dma_addr); |
| 509 | pci_free_consistent(lp->pci_dev, | 505 | pci_free_consistent(lp->pci_dev, |
| 510 | sizeof(struct pcnet32_tx_head) * | 506 | sizeof(struct pcnet32_tx_head) * lp->tx_ring_size, |
| 511 | lp->tx_ring_size, lp->tx_ring, | 507 | lp->tx_ring, lp->tx_ring_dma_addr); |
| 512 | lp->tx_ring_dma_addr); | ||
| 513 | 508 | ||
| 514 | lp->tx_ring_size = (1 << size); | 509 | lp->tx_ring_size = entries; |
| 515 | lp->tx_mod_mask = lp->tx_ring_size - 1; | 510 | lp->tx_mod_mask = lp->tx_ring_size - 1; |
| 516 | lp->tx_len_bits = (size << 12); | 511 | lp->tx_len_bits = (size << 12); |
| 517 | lp->tx_ring = new_tx_ring; | 512 | lp->tx_ring = new_tx_ring; |
| @@ -524,8 +519,7 @@ free_new_lists: | |||
| 524 | kfree(new_dma_addr_list); | 519 | kfree(new_dma_addr_list); |
| 525 | free_new_tx_ring: | 520 | free_new_tx_ring: |
| 526 | pci_free_consistent(lp->pci_dev, | 521 | pci_free_consistent(lp->pci_dev, |
| 527 | sizeof(struct pcnet32_tx_head) * | 522 | sizeof(struct pcnet32_tx_head) * entries, |
| 528 | (1 << size), | ||
| 529 | new_tx_ring, | 523 | new_tx_ring, |
| 530 | new_ring_dma_addr); | 524 | new_ring_dma_addr); |
| 531 | } | 525 | } |
| @@ -549,17 +543,14 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev, | |||
| 549 | struct pcnet32_rx_head *new_rx_ring; | 543 | struct pcnet32_rx_head *new_rx_ring; |
| 550 | struct sk_buff **new_skb_list; | 544 | struct sk_buff **new_skb_list; |
| 551 | int new, overlap; | 545 | int new, overlap; |
| 552 | unsigned int entries = 1 << size; | 546 | unsigned int entries = BIT(size); |
| 553 | 547 | ||
| 554 | new_rx_ring = pci_alloc_consistent(lp->pci_dev, | 548 | new_rx_ring = |
| 555 | sizeof(struct pcnet32_rx_head) * | 549 | pci_zalloc_consistent(lp->pci_dev, |
| 556 | entries, | 550 | sizeof(struct pcnet32_rx_head) * entries, |
| 557 | &new_ring_dma_addr); | 551 | &new_ring_dma_addr); |
| 558 | if (new_rx_ring == NULL) { | 552 | if (new_rx_ring == NULL) |
| 559 | netif_err(lp, drv, dev, "Consistent memory allocation failed\n"); | ||
| 560 | return; | 553 | return; |
| 561 | } | ||
| 562 | memset(new_rx_ring, 0, sizeof(struct pcnet32_rx_head) * entries); | ||
| 563 | 554 | ||
| 564 | new_dma_addr_list = kcalloc(entries, sizeof(dma_addr_t), GFP_ATOMIC); | 555 | new_dma_addr_list = kcalloc(entries, sizeof(dma_addr_t), GFP_ATOMIC); |
| 565 | if (!new_dma_addr_list) | 556 | if (!new_dma_addr_list) |
diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c index 4345332533ad..316e0c3fe048 100644 --- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c +++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c | |||
| @@ -831,17 +831,14 @@ static int atl1e_setup_ring_resources(struct atl1e_adapter *adapter) | |||
| 831 | /* real ring DMA buffer */ | 831 | /* real ring DMA buffer */ |
| 832 | 832 | ||
| 833 | size = adapter->ring_size; | 833 | size = adapter->ring_size; |
| 834 | adapter->ring_vir_addr = pci_alloc_consistent(pdev, | 834 | adapter->ring_vir_addr = pci_zalloc_consistent(pdev, adapter->ring_size, |
| 835 | adapter->ring_size, &adapter->ring_dma); | 835 | &adapter->ring_dma); |
| 836 | |||
| 837 | if (adapter->ring_vir_addr == NULL) { | 836 | if (adapter->ring_vir_addr == NULL) { |
| 838 | netdev_err(adapter->netdev, | 837 | netdev_err(adapter->netdev, |
| 839 | "pci_alloc_consistent failed, size = D%d\n", size); | 838 | "pci_alloc_consistent failed, size = D%d\n", size); |
| 840 | return -ENOMEM; | 839 | return -ENOMEM; |
| 841 | } | 840 | } |
| 842 | 841 | ||
| 843 | memset(adapter->ring_vir_addr, 0, adapter->ring_size); | ||
| 844 | |||
| 845 | rx_page_desc = rx_ring->rx_page_desc; | 842 | rx_page_desc = rx_ring->rx_page_desc; |
| 846 | 843 | ||
| 847 | /* Init TPD Ring */ | 844 | /* Init TPD Ring */ |
diff --git a/drivers/net/ethernet/cisco/enic/vnic_dev.c b/drivers/net/ethernet/cisco/enic/vnic_dev.c index 5abc496bcf29..37472ce4fac3 100644 --- a/drivers/net/ethernet/cisco/enic/vnic_dev.c +++ b/drivers/net/ethernet/cisco/enic/vnic_dev.c | |||
| @@ -432,14 +432,12 @@ int vnic_dev_fw_info(struct vnic_dev *vdev, | |||
| 432 | int err = 0; | 432 | int err = 0; |
| 433 | 433 | ||
| 434 | if (!vdev->fw_info) { | 434 | if (!vdev->fw_info) { |
| 435 | vdev->fw_info = pci_alloc_consistent(vdev->pdev, | 435 | vdev->fw_info = pci_zalloc_consistent(vdev->pdev, |
| 436 | sizeof(struct vnic_devcmd_fw_info), | 436 | sizeof(struct vnic_devcmd_fw_info), |
| 437 | &vdev->fw_info_pa); | 437 | &vdev->fw_info_pa); |
| 438 | if (!vdev->fw_info) | 438 | if (!vdev->fw_info) |
| 439 | return -ENOMEM; | 439 | return -ENOMEM; |
| 440 | 440 | ||
| 441 | memset(vdev->fw_info, 0, sizeof(struct vnic_devcmd_fw_info)); | ||
| 442 | |||
| 443 | a0 = vdev->fw_info_pa; | 441 | a0 = vdev->fw_info_pa; |
| 444 | a1 = sizeof(struct vnic_devcmd_fw_info); | 442 | a1 = sizeof(struct vnic_devcmd_fw_info); |
| 445 | 443 | ||
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index 69693384b58c..59915144aabb 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c | |||
| @@ -1622,11 +1622,10 @@ static int sky2_alloc_buffers(struct sky2_port *sky2) | |||
| 1622 | if (!sky2->tx_ring) | 1622 | if (!sky2->tx_ring) |
| 1623 | goto nomem; | 1623 | goto nomem; |
| 1624 | 1624 | ||
| 1625 | sky2->rx_le = pci_alloc_consistent(hw->pdev, RX_LE_BYTES, | 1625 | sky2->rx_le = pci_zalloc_consistent(hw->pdev, RX_LE_BYTES, |
| 1626 | &sky2->rx_le_map); | 1626 | &sky2->rx_le_map); |
| 1627 | if (!sky2->rx_le) | 1627 | if (!sky2->rx_le) |
| 1628 | goto nomem; | 1628 | goto nomem; |
| 1629 | memset(sky2->rx_le, 0, RX_LE_BYTES); | ||
| 1630 | 1629 | ||
| 1631 | sky2->rx_ring = kcalloc(sky2->rx_pending, sizeof(struct rx_ring_info), | 1630 | sky2->rx_ring = kcalloc(sky2->rx_pending, sizeof(struct rx_ring_info), |
| 1632 | GFP_KERNEL); | 1631 | GFP_KERNEL); |
diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c index 064a48d0c368..cd5f106306d9 100644 --- a/drivers/net/ethernet/micrel/ksz884x.c +++ b/drivers/net/ethernet/micrel/ksz884x.c | |||
| @@ -4409,14 +4409,13 @@ static int ksz_alloc_desc(struct dev_info *adapter) | |||
| 4409 | DESC_ALIGNMENT; | 4409 | DESC_ALIGNMENT; |
| 4410 | 4410 | ||
| 4411 | adapter->desc_pool.alloc_virt = | 4411 | adapter->desc_pool.alloc_virt = |
| 4412 | pci_alloc_consistent( | 4412 | pci_zalloc_consistent(adapter->pdev, |
| 4413 | adapter->pdev, adapter->desc_pool.alloc_size, | 4413 | adapter->desc_pool.alloc_size, |
| 4414 | &adapter->desc_pool.dma_addr); | 4414 | &adapter->desc_pool.dma_addr); |
| 4415 | if (adapter->desc_pool.alloc_virt == NULL) { | 4415 | if (adapter->desc_pool.alloc_virt == NULL) { |
| 4416 | adapter->desc_pool.alloc_size = 0; | 4416 | adapter->desc_pool.alloc_size = 0; |
| 4417 | return 1; | 4417 | return 1; |
| 4418 | } | 4418 | } |
| 4419 | memset(adapter->desc_pool.alloc_virt, 0, adapter->desc_pool.alloc_size); | ||
| 4420 | 4419 | ||
| 4421 | /* Align to the next cache line boundary. */ | 4420 | /* Align to the next cache line boundary. */ |
| 4422 | offset = (((ulong) adapter->desc_pool.alloc_virt % DESC_ALIGNMENT) ? | 4421 | offset = (((ulong) adapter->desc_pool.alloc_virt % DESC_ALIGNMENT) ? |
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c index 6f6be57f4690..b8d5270359cd 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c | |||
| @@ -129,14 +129,12 @@ netxen_get_minidump_template(struct netxen_adapter *adapter) | |||
| 129 | return NX_RCODE_INVALID_ARGS; | 129 | return NX_RCODE_INVALID_ARGS; |
| 130 | } | 130 | } |
| 131 | 131 | ||
| 132 | addr = pci_alloc_consistent(adapter->pdev, size, &md_template_addr); | 132 | addr = pci_zalloc_consistent(adapter->pdev, size, &md_template_addr); |
| 133 | |||
| 134 | if (!addr) { | 133 | if (!addr) { |
| 135 | dev_err(&adapter->pdev->dev, "Unable to allocate dmable memory for template.\n"); | 134 | dev_err(&adapter->pdev->dev, "Unable to allocate dmable memory for template.\n"); |
| 136 | return -ENOMEM; | 135 | return -ENOMEM; |
| 137 | } | 136 | } |
| 138 | 137 | ||
| 139 | memset(addr, 0, size); | ||
| 140 | memset(&cmd, 0, sizeof(cmd)); | 138 | memset(&cmd, 0, sizeof(cmd)); |
| 141 | memset(&cmd.rsp, 1, sizeof(struct _cdrp_cmd)); | 139 | memset(&cmd.rsp, 1, sizeof(struct _cdrp_cmd)); |
| 142 | cmd.req.cmd = NX_CDRP_CMD_GET_TEMP_HDR; | 140 | cmd.req.cmd = NX_CDRP_CMD_GET_TEMP_HDR; |
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c index b40050e03a56..d836ace52277 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c +++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c | |||
| @@ -2727,23 +2727,22 @@ static void ql_free_shadow_space(struct ql_adapter *qdev) | |||
| 2727 | static int ql_alloc_shadow_space(struct ql_adapter *qdev) | 2727 | static int ql_alloc_shadow_space(struct ql_adapter *qdev) |
| 2728 | { | 2728 | { |
| 2729 | qdev->rx_ring_shadow_reg_area = | 2729 | qdev->rx_ring_shadow_reg_area = |
| 2730 | pci_alloc_consistent(qdev->pdev, | 2730 | pci_zalloc_consistent(qdev->pdev, PAGE_SIZE, |
| 2731 | PAGE_SIZE, &qdev->rx_ring_shadow_reg_dma); | 2731 | &qdev->rx_ring_shadow_reg_dma); |
| 2732 | if (qdev->rx_ring_shadow_reg_area == NULL) { | 2732 | if (qdev->rx_ring_shadow_reg_area == NULL) { |
| 2733 | netif_err(qdev, ifup, qdev->ndev, | 2733 | netif_err(qdev, ifup, qdev->ndev, |
| 2734 | "Allocation of RX shadow space failed.\n"); | 2734 | "Allocation of RX shadow space failed.\n"); |
| 2735 | return -ENOMEM; | 2735 | return -ENOMEM; |
| 2736 | } | 2736 | } |
| 2737 | memset(qdev->rx_ring_shadow_reg_area, 0, PAGE_SIZE); | 2737 | |
| 2738 | qdev->tx_ring_shadow_reg_area = | 2738 | qdev->tx_ring_shadow_reg_area = |
| 2739 | pci_alloc_consistent(qdev->pdev, PAGE_SIZE, | 2739 | pci_zalloc_consistent(qdev->pdev, PAGE_SIZE, |
| 2740 | &qdev->tx_ring_shadow_reg_dma); | 2740 | &qdev->tx_ring_shadow_reg_dma); |
| 2741 | if (qdev->tx_ring_shadow_reg_area == NULL) { | 2741 | if (qdev->tx_ring_shadow_reg_area == NULL) { |
| 2742 | netif_err(qdev, ifup, qdev->ndev, | 2742 | netif_err(qdev, ifup, qdev->ndev, |
| 2743 | "Allocation of TX shadow space failed.\n"); | 2743 | "Allocation of TX shadow space failed.\n"); |
| 2744 | goto err_wqp_sh_area; | 2744 | goto err_wqp_sh_area; |
| 2745 | } | 2745 | } |
| 2746 | memset(qdev->tx_ring_shadow_reg_area, 0, PAGE_SIZE); | ||
| 2747 | return 0; | 2746 | return 0; |
| 2748 | 2747 | ||
| 2749 | err_wqp_sh_area: | 2748 | err_wqp_sh_area: |
diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c index 485006604bbc..58ef59469dd0 100644 --- a/drivers/net/irda/vlsi_ir.c +++ b/drivers/net/irda/vlsi_ir.c | |||
| @@ -485,13 +485,13 @@ static int vlsi_create_hwif(vlsi_irda_dev_t *idev) | |||
| 485 | idev->virtaddr = NULL; | 485 | idev->virtaddr = NULL; |
| 486 | idev->busaddr = 0; | 486 | idev->busaddr = 0; |
| 487 | 487 | ||
| 488 | ringarea = pci_alloc_consistent(idev->pdev, HW_RING_AREA_SIZE, &idev->busaddr); | 488 | ringarea = pci_zalloc_consistent(idev->pdev, HW_RING_AREA_SIZE, |
| 489 | &idev->busaddr); | ||
| 489 | if (!ringarea) { | 490 | if (!ringarea) { |
| 490 | IRDA_ERROR("%s: insufficient memory for descriptor rings\n", | 491 | IRDA_ERROR("%s: insufficient memory for descriptor rings\n", |
| 491 | __func__); | 492 | __func__); |
| 492 | goto out; | 493 | goto out; |
| 493 | } | 494 | } |
| 494 | memset(ringarea, 0, HW_RING_AREA_SIZE); | ||
| 495 | 495 | ||
| 496 | hwmap = (struct ring_descr_hw *)ringarea; | 496 | hwmap = (struct ring_descr_hw *)ringarea; |
| 497 | idev->rx_ring = vlsi_alloc_ring(idev->pdev, hwmap, ringsize[1], | 497 | idev->rx_ring = vlsi_alloc_ring(idev->pdev, hwmap, ringsize[1], |
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index dfc6dfc56d52..1ab8e500fb77 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c | |||
| @@ -3449,8 +3449,9 @@ static int ipw2100_msg_allocate(struct ipw2100_priv *priv) | |||
| 3449 | return -ENOMEM; | 3449 | return -ENOMEM; |
| 3450 | 3450 | ||
| 3451 | for (i = 0; i < IPW_COMMAND_POOL_SIZE; i++) { | 3451 | for (i = 0; i < IPW_COMMAND_POOL_SIZE; i++) { |
| 3452 | v = pci_alloc_consistent(priv->pci_dev, | 3452 | v = pci_zalloc_consistent(priv->pci_dev, |
| 3453 | sizeof(struct ipw2100_cmd_header), &p); | 3453 | sizeof(struct ipw2100_cmd_header), |
| 3454 | &p); | ||
| 3454 | if (!v) { | 3455 | if (!v) { |
| 3455 | printk(KERN_ERR DRV_NAME ": " | 3456 | printk(KERN_ERR DRV_NAME ": " |
| 3456 | "%s: PCI alloc failed for msg " | 3457 | "%s: PCI alloc failed for msg " |
| @@ -3459,8 +3460,6 @@ static int ipw2100_msg_allocate(struct ipw2100_priv *priv) | |||
| 3459 | break; | 3460 | break; |
| 3460 | } | 3461 | } |
| 3461 | 3462 | ||
| 3462 | memset(v, 0, sizeof(struct ipw2100_cmd_header)); | ||
| 3463 | |||
| 3464 | priv->msg_buffers[i].type = COMMAND; | 3463 | priv->msg_buffers[i].type = COMMAND; |
| 3465 | priv->msg_buffers[i].info.c_struct.cmd = | 3464 | priv->msg_buffers[i].info.c_struct.cmd = |
| 3466 | (struct ipw2100_cmd_header *)v; | 3465 | (struct ipw2100_cmd_header *)v; |
| @@ -4336,16 +4335,12 @@ static int status_queue_allocate(struct ipw2100_priv *priv, int entries) | |||
| 4336 | IPW_DEBUG_INFO("enter\n"); | 4335 | IPW_DEBUG_INFO("enter\n"); |
| 4337 | 4336 | ||
| 4338 | q->size = entries * sizeof(struct ipw2100_status); | 4337 | q->size = entries * sizeof(struct ipw2100_status); |
| 4339 | q->drv = | 4338 | q->drv = pci_zalloc_consistent(priv->pci_dev, q->size, &q->nic); |
| 4340 | (struct ipw2100_status *)pci_alloc_consistent(priv->pci_dev, | ||
| 4341 | q->size, &q->nic); | ||
| 4342 | if (!q->drv) { | 4339 | if (!q->drv) { |
| 4343 | IPW_DEBUG_WARNING("Can not allocate status queue.\n"); | 4340 | IPW_DEBUG_WARNING("Can not allocate status queue.\n"); |
| 4344 | return -ENOMEM; | 4341 | return -ENOMEM; |
| 4345 | } | 4342 | } |
| 4346 | 4343 | ||
| 4347 | memset(q->drv, 0, q->size); | ||
| 4348 | |||
| 4349 | IPW_DEBUG_INFO("exit\n"); | 4344 | IPW_DEBUG_INFO("exit\n"); |
| 4350 | 4345 | ||
| 4351 | return 0; | 4346 | return 0; |
| @@ -4374,13 +4369,12 @@ static int bd_queue_allocate(struct ipw2100_priv *priv, | |||
| 4374 | 4369 | ||
| 4375 | q->entries = entries; | 4370 | q->entries = entries; |
| 4376 | q->size = entries * sizeof(struct ipw2100_bd); | 4371 | q->size = entries * sizeof(struct ipw2100_bd); |
| 4377 | q->drv = pci_alloc_consistent(priv->pci_dev, q->size, &q->nic); | 4372 | q->drv = pci_zalloc_consistent(priv->pci_dev, q->size, &q->nic); |
| 4378 | if (!q->drv) { | 4373 | if (!q->drv) { |
| 4379 | IPW_DEBUG_INFO | 4374 | IPW_DEBUG_INFO |
| 4380 | ("can't allocate shared memory for buffer descriptors\n"); | 4375 | ("can't allocate shared memory for buffer descriptors\n"); |
| 4381 | return -ENOMEM; | 4376 | return -ENOMEM; |
| 4382 | } | 4377 | } |
| 4383 | memset(q->drv, 0, q->size); | ||
| 4384 | 4378 | ||
| 4385 | IPW_DEBUG_INFO("exit\n"); | 4379 | IPW_DEBUG_INFO("exit\n"); |
| 4386 | 4380 | ||
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 9a3d4d6724f7..fc6cb215e761 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c | |||
| @@ -1159,12 +1159,11 @@ static int mwl8k_rxq_init(struct ieee80211_hw *hw, int index) | |||
| 1159 | 1159 | ||
| 1160 | size = MWL8K_RX_DESCS * priv->rxd_ops->rxd_size; | 1160 | size = MWL8K_RX_DESCS * priv->rxd_ops->rxd_size; |
| 1161 | 1161 | ||
| 1162 | rxq->rxd = pci_alloc_consistent(priv->pdev, size, &rxq->rxd_dma); | 1162 | rxq->rxd = pci_zalloc_consistent(priv->pdev, size, &rxq->rxd_dma); |
| 1163 | if (rxq->rxd == NULL) { | 1163 | if (rxq->rxd == NULL) { |
| 1164 | wiphy_err(hw->wiphy, "failed to alloc RX descriptors\n"); | 1164 | wiphy_err(hw->wiphy, "failed to alloc RX descriptors\n"); |
| 1165 | return -ENOMEM; | 1165 | return -ENOMEM; |
| 1166 | } | 1166 | } |
| 1167 | memset(rxq->rxd, 0, size); | ||
| 1168 | 1167 | ||
| 1169 | rxq->buf = kcalloc(MWL8K_RX_DESCS, sizeof(*rxq->buf), GFP_KERNEL); | 1168 | rxq->buf = kcalloc(MWL8K_RX_DESCS, sizeof(*rxq->buf), GFP_KERNEL); |
| 1170 | if (rxq->buf == NULL) { | 1169 | if (rxq->buf == NULL) { |
| @@ -1451,12 +1450,11 @@ static int mwl8k_txq_init(struct ieee80211_hw *hw, int index) | |||
| 1451 | 1450 | ||
| 1452 | size = MWL8K_TX_DESCS * sizeof(struct mwl8k_tx_desc); | 1451 | size = MWL8K_TX_DESCS * sizeof(struct mwl8k_tx_desc); |
| 1453 | 1452 | ||
| 1454 | txq->txd = pci_alloc_consistent(priv->pdev, size, &txq->txd_dma); | 1453 | txq->txd = pci_zalloc_consistent(priv->pdev, size, &txq->txd_dma); |
| 1455 | if (txq->txd == NULL) { | 1454 | if (txq->txd == NULL) { |
| 1456 | wiphy_err(hw->wiphy, "failed to alloc TX descriptors\n"); | 1455 | wiphy_err(hw->wiphy, "failed to alloc TX descriptors\n"); |
| 1457 | return -ENOMEM; | 1456 | return -ENOMEM; |
| 1458 | } | 1457 | } |
| 1459 | memset(txq->txd, 0, size); | ||
| 1460 | 1458 | ||
| 1461 | txq->skb = kcalloc(MWL8K_TX_DESCS, sizeof(*txq->skb), GFP_KERNEL); | 1459 | txq->skb = kcalloc(MWL8K_TX_DESCS, sizeof(*txq->skb), GFP_KERNEL); |
| 1462 | if (txq->skb == NULL) { | 1460 | if (txq->skb == NULL) { |
diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c index 4b904f708184..fcc45e5bf50a 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180/dev.c | |||
| @@ -972,16 +972,13 @@ static int rtl8180_init_rx_ring(struct ieee80211_hw *dev) | |||
| 972 | else | 972 | else |
| 973 | priv->rx_ring_sz = sizeof(struct rtl8180_rx_desc); | 973 | priv->rx_ring_sz = sizeof(struct rtl8180_rx_desc); |
| 974 | 974 | ||
| 975 | priv->rx_ring = pci_alloc_consistent(priv->pdev, | 975 | priv->rx_ring = pci_zalloc_consistent(priv->pdev, priv->rx_ring_sz * 32, |
| 976 | priv->rx_ring_sz * 32, | 976 | &priv->rx_ring_dma); |
| 977 | &priv->rx_ring_dma); | ||
| 978 | |||
| 979 | if (!priv->rx_ring || (unsigned long)priv->rx_ring & 0xFF) { | 977 | if (!priv->rx_ring || (unsigned long)priv->rx_ring & 0xFF) { |
| 980 | wiphy_err(dev->wiphy, "Cannot allocate RX ring\n"); | 978 | wiphy_err(dev->wiphy, "Cannot allocate RX ring\n"); |
| 981 | return -ENOMEM; | 979 | return -ENOMEM; |
| 982 | } | 980 | } |
| 983 | 981 | ||
| 984 | memset(priv->rx_ring, 0, priv->rx_ring_sz * 32); | ||
| 985 | priv->rx_idx = 0; | 982 | priv->rx_idx = 0; |
| 986 | 983 | ||
| 987 | for (i = 0; i < 32; i++) { | 984 | for (i = 0; i < 32; i++) { |
| @@ -1040,14 +1037,14 @@ static int rtl8180_init_tx_ring(struct ieee80211_hw *dev, | |||
| 1040 | dma_addr_t dma; | 1037 | dma_addr_t dma; |
| 1041 | int i; | 1038 | int i; |
| 1042 | 1039 | ||
| 1043 | ring = pci_alloc_consistent(priv->pdev, sizeof(*ring) * entries, &dma); | 1040 | ring = pci_zalloc_consistent(priv->pdev, sizeof(*ring) * entries, |
| 1041 | &dma); | ||
| 1044 | if (!ring || (unsigned long)ring & 0xFF) { | 1042 | if (!ring || (unsigned long)ring & 0xFF) { |
| 1045 | wiphy_err(dev->wiphy, "Cannot allocate TX ring (prio = %d)\n", | 1043 | wiphy_err(dev->wiphy, "Cannot allocate TX ring (prio = %d)\n", |
| 1046 | prio); | 1044 | prio); |
| 1047 | return -ENOMEM; | 1045 | return -ENOMEM; |
| 1048 | } | 1046 | } |
| 1049 | 1047 | ||
| 1050 | memset(ring, 0, sizeof(*ring)*entries); | ||
| 1051 | priv->tx_ring[prio].desc = ring; | 1048 | priv->tx_ring[prio].desc = ring; |
| 1052 | priv->tx_ring[prio].dma = dma; | 1049 | priv->tx_ring[prio].dma = dma; |
| 1053 | priv->tx_ring[prio].idx = 0; | 1050 | priv->tx_ring[prio].idx = 0; |
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index dae55257f0e8..67d1ee6edcad 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c | |||
| @@ -1092,16 +1092,14 @@ static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw, | |||
| 1092 | u32 nextdescaddress; | 1092 | u32 nextdescaddress; |
| 1093 | int i; | 1093 | int i; |
| 1094 | 1094 | ||
| 1095 | ring = pci_alloc_consistent(rtlpci->pdev, | 1095 | ring = pci_zalloc_consistent(rtlpci->pdev, sizeof(*ring) * entries, |
| 1096 | sizeof(*ring) * entries, &dma); | 1096 | &dma); |
| 1097 | |||
| 1098 | if (!ring || (unsigned long)ring & 0xFF) { | 1097 | if (!ring || (unsigned long)ring & 0xFF) { |
| 1099 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | 1098 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, |
| 1100 | "Cannot allocate TX ring (prio = %d)\n", prio); | 1099 | "Cannot allocate TX ring (prio = %d)\n", prio); |
| 1101 | return -ENOMEM; | 1100 | return -ENOMEM; |
| 1102 | } | 1101 | } |
| 1103 | 1102 | ||
| 1104 | memset(ring, 0, sizeof(*ring) * entries); | ||
| 1105 | rtlpci->tx_ring[prio].desc = ring; | 1103 | rtlpci->tx_ring[prio].desc = ring; |
| 1106 | rtlpci->tx_ring[prio].dma = dma; | 1104 | rtlpci->tx_ring[prio].dma = dma; |
| 1107 | rtlpci->tx_ring[prio].idx = 0; | 1105 | rtlpci->tx_ring[prio].idx = 0; |
| @@ -1139,10 +1137,9 @@ static int _rtl_pci_init_rx_ring(struct ieee80211_hw *hw) | |||
| 1139 | for (rx_queue_idx = 0; rx_queue_idx < RTL_PCI_MAX_RX_QUEUE; | 1137 | for (rx_queue_idx = 0; rx_queue_idx < RTL_PCI_MAX_RX_QUEUE; |
| 1140 | rx_queue_idx++) { | 1138 | rx_queue_idx++) { |
| 1141 | rtlpci->rx_ring[rx_queue_idx].desc = | 1139 | rtlpci->rx_ring[rx_queue_idx].desc = |
| 1142 | pci_alloc_consistent(rtlpci->pdev, | 1140 | pci_zalloc_consistent(rtlpci->pdev, |
| 1143 | sizeof(*rtlpci->rx_ring[rx_queue_idx]. | 1141 | sizeof(*rtlpci->rx_ring[rx_queue_idx].desc) * rtlpci->rxringcount, |
| 1144 | desc) * rtlpci->rxringcount, | 1142 | &rtlpci->rx_ring[rx_queue_idx].dma); |
| 1145 | &rtlpci->rx_ring[rx_queue_idx].dma); | ||
| 1146 | 1143 | ||
| 1147 | if (!rtlpci->rx_ring[rx_queue_idx].desc || | 1144 | if (!rtlpci->rx_ring[rx_queue_idx].desc || |
| 1148 | (unsigned long)rtlpci->rx_ring[rx_queue_idx].desc & 0xFF) { | 1145 | (unsigned long)rtlpci->rx_ring[rx_queue_idx].desc & 0xFF) { |
| @@ -1151,10 +1148,6 @@ static int _rtl_pci_init_rx_ring(struct ieee80211_hw *hw) | |||
| 1151 | return -ENOMEM; | 1148 | return -ENOMEM; |
| 1152 | } | 1149 | } |
| 1153 | 1150 | ||
| 1154 | memset(rtlpci->rx_ring[rx_queue_idx].desc, 0, | ||
| 1155 | sizeof(*rtlpci->rx_ring[rx_queue_idx].desc) * | ||
| 1156 | rtlpci->rxringcount); | ||
| 1157 | |||
| 1158 | rtlpci->rx_ring[rx_queue_idx].idx = 0; | 1151 | rtlpci->rx_ring[rx_queue_idx].idx = 0; |
| 1159 | 1152 | ||
| 1160 | /* If amsdu_8k is disabled, set buffersize to 4096. This | 1153 | /* If amsdu_8k is disabled, set buffersize to 4096. This |
diff --git a/drivers/parport/parport_ip32.c b/drivers/parport/parport_ip32.c index c864f82bd37d..30e981be14c2 100644 --- a/drivers/parport/parport_ip32.c +++ b/drivers/parport/parport_ip32.c | |||
| @@ -2204,7 +2204,7 @@ static int __init parport_ip32_init(void) | |||
| 2204 | { | 2204 | { |
| 2205 | pr_info(PPIP32 "SGI IP32 built-in parallel port driver v0.6\n"); | 2205 | pr_info(PPIP32 "SGI IP32 built-in parallel port driver v0.6\n"); |
| 2206 | this_port = parport_ip32_probe_port(); | 2206 | this_port = parport_ip32_probe_port(); |
| 2207 | return IS_ERR(this_port) ? PTR_ERR(this_port) : 0; | 2207 | return PTR_ERR_OR_ZERO(this_port); |
| 2208 | } | 2208 | } |
| 2209 | 2209 | ||
| 2210 | /** | 2210 | /** |
diff --git a/drivers/rapidio/devices/tsi721.h b/drivers/rapidio/devices/tsi721.h index 0305675270ee..a7b42680a06a 100644 --- a/drivers/rapidio/devices/tsi721.h +++ b/drivers/rapidio/devices/tsi721.h | |||
| @@ -644,27 +644,26 @@ enum tsi721_smsg_int_flag { | |||
| 644 | 644 | ||
| 645 | #ifdef CONFIG_RAPIDIO_DMA_ENGINE | 645 | #ifdef CONFIG_RAPIDIO_DMA_ENGINE |
| 646 | 646 | ||
| 647 | #define TSI721_BDMA_BD_RING_SZ 128 | ||
| 648 | #define TSI721_BDMA_MAX_BCOUNT (TSI721_DMAD_BCOUNT1 + 1) | 647 | #define TSI721_BDMA_MAX_BCOUNT (TSI721_DMAD_BCOUNT1 + 1) |
| 649 | 648 | ||
| 650 | struct tsi721_tx_desc { | 649 | struct tsi721_tx_desc { |
| 651 | struct dma_async_tx_descriptor txd; | 650 | struct dma_async_tx_descriptor txd; |
| 652 | struct tsi721_dma_desc *hw_desc; | ||
| 653 | u16 destid; | 651 | u16 destid; |
| 654 | /* low 64-bits of 66-bit RIO address */ | 652 | /* low 64-bits of 66-bit RIO address */ |
| 655 | u64 rio_addr; | 653 | u64 rio_addr; |
| 656 | /* upper 2-bits of 66-bit RIO address */ | 654 | /* upper 2-bits of 66-bit RIO address */ |
| 657 | u8 rio_addr_u; | 655 | u8 rio_addr_u; |
| 658 | u32 bcount; | 656 | enum dma_rtype rtype; |
| 659 | bool interrupt; | ||
| 660 | struct list_head desc_node; | 657 | struct list_head desc_node; |
| 661 | struct list_head tx_list; | 658 | struct scatterlist *sg; |
| 659 | unsigned int sg_len; | ||
| 660 | enum dma_status status; | ||
| 662 | }; | 661 | }; |
| 663 | 662 | ||
| 664 | struct tsi721_bdma_chan { | 663 | struct tsi721_bdma_chan { |
| 665 | int id; | 664 | int id; |
| 666 | void __iomem *regs; | 665 | void __iomem *regs; |
| 667 | int bd_num; /* number of buffer descriptors */ | 666 | int bd_num; /* number of HW buffer descriptors */ |
| 668 | void *bd_base; /* start of DMA descriptors */ | 667 | void *bd_base; /* start of DMA descriptors */ |
| 669 | dma_addr_t bd_phys; | 668 | dma_addr_t bd_phys; |
| 670 | void *sts_base; /* start of DMA BD status FIFO */ | 669 | void *sts_base; /* start of DMA BD status FIFO */ |
| @@ -680,7 +679,6 @@ struct tsi721_bdma_chan { | |||
| 680 | struct list_head active_list; | 679 | struct list_head active_list; |
| 681 | struct list_head queue; | 680 | struct list_head queue; |
| 682 | struct list_head free_list; | 681 | struct list_head free_list; |
| 683 | dma_cookie_t completed_cookie; | ||
| 684 | struct tasklet_struct tasklet; | 682 | struct tasklet_struct tasklet; |
| 685 | bool active; | 683 | bool active; |
| 686 | }; | 684 | }; |
diff --git a/drivers/rapidio/devices/tsi721_dma.c b/drivers/rapidio/devices/tsi721_dma.c index 44341dc5b148..f64c5decb747 100644 --- a/drivers/rapidio/devices/tsi721_dma.c +++ b/drivers/rapidio/devices/tsi721_dma.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * DMA Engine support for Tsi721 PCIExpress-to-SRIO bridge | 2 | * DMA Engine support for Tsi721 PCIExpress-to-SRIO bridge |
| 3 | * | 3 | * |
| 4 | * Copyright 2011 Integrated Device Technology, Inc. | 4 | * Copyright (c) 2011-2014 Integrated Device Technology, Inc. |
| 5 | * Alexandre Bounine <alexandre.bounine@idt.com> | 5 | * Alexandre Bounine <alexandre.bounine@idt.com> |
| 6 | * | 6 | * |
| 7 | * This program is free software; you can redistribute it and/or modify it | 7 | * This program is free software; you can redistribute it and/or modify it |
| @@ -14,9 +14,8 @@ | |||
| 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| 15 | * more details. | 15 | * more details. |
| 16 | * | 16 | * |
| 17 | * You should have received a copy of the GNU General Public License along with | 17 | * The full GNU General Public License is included in this distribution in the |
| 18 | * this program; if not, write to the Free Software Foundation, Inc., 59 | 18 | * file called COPYING. |
| 19 | * Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
| 20 | */ | 19 | */ |
| 21 | 20 | ||
| 22 | #include <linux/io.h> | 21 | #include <linux/io.h> |
| @@ -32,9 +31,22 @@ | |||
| 32 | #include <linux/interrupt.h> | 31 | #include <linux/interrupt.h> |
| 33 | #include <linux/kfifo.h> | 32 | #include <linux/kfifo.h> |
| 34 | #include <linux/delay.h> | 33 | #include <linux/delay.h> |
| 34 | #include "../../dma/dmaengine.h" | ||
| 35 | 35 | ||
| 36 | #include "tsi721.h" | 36 | #include "tsi721.h" |
| 37 | 37 | ||
| 38 | #define TSI721_DMA_TX_QUEUE_SZ 16 /* number of transaction descriptors */ | ||
| 39 | |||
| 40 | #ifdef CONFIG_PCI_MSI | ||
| 41 | static irqreturn_t tsi721_bdma_msix(int irq, void *ptr); | ||
| 42 | #endif | ||
| 43 | static int tsi721_submit_sg(struct tsi721_tx_desc *desc); | ||
| 44 | |||
| 45 | static unsigned int dma_desc_per_channel = 128; | ||
| 46 | module_param(dma_desc_per_channel, uint, S_IWUSR | S_IRUGO); | ||
| 47 | MODULE_PARM_DESC(dma_desc_per_channel, | ||
| 48 | "Number of DMA descriptors per channel (default: 128)"); | ||
| 49 | |||
| 38 | static inline struct tsi721_bdma_chan *to_tsi721_chan(struct dma_chan *chan) | 50 | static inline struct tsi721_bdma_chan *to_tsi721_chan(struct dma_chan *chan) |
| 39 | { | 51 | { |
| 40 | return container_of(chan, struct tsi721_bdma_chan, dchan); | 52 | return container_of(chan, struct tsi721_bdma_chan, dchan); |
| @@ -59,7 +71,7 @@ struct tsi721_tx_desc *tsi721_dma_first_active( | |||
| 59 | struct tsi721_tx_desc, desc_node); | 71 | struct tsi721_tx_desc, desc_node); |
| 60 | } | 72 | } |
| 61 | 73 | ||
| 62 | static int tsi721_bdma_ch_init(struct tsi721_bdma_chan *bdma_chan) | 74 | static int tsi721_bdma_ch_init(struct tsi721_bdma_chan *bdma_chan, int bd_num) |
| 63 | { | 75 | { |
| 64 | struct tsi721_dma_desc *bd_ptr; | 76 | struct tsi721_dma_desc *bd_ptr; |
| 65 | struct device *dev = bdma_chan->dchan.device->dev; | 77 | struct device *dev = bdma_chan->dchan.device->dev; |
| @@ -67,17 +79,23 @@ static int tsi721_bdma_ch_init(struct tsi721_bdma_chan *bdma_chan) | |||
| 67 | dma_addr_t bd_phys; | 79 | dma_addr_t bd_phys; |
| 68 | dma_addr_t sts_phys; | 80 | dma_addr_t sts_phys; |
| 69 | int sts_size; | 81 | int sts_size; |
| 70 | int bd_num = bdma_chan->bd_num; | 82 | #ifdef CONFIG_PCI_MSI |
| 83 | struct tsi721_device *priv = to_tsi721(bdma_chan->dchan.device); | ||
| 84 | #endif | ||
| 71 | 85 | ||
| 72 | dev_dbg(dev, "Init Block DMA Engine, CH%d\n", bdma_chan->id); | 86 | dev_dbg(dev, "Init Block DMA Engine, CH%d\n", bdma_chan->id); |
| 73 | 87 | ||
| 74 | /* Allocate space for DMA descriptors */ | 88 | /* |
| 89 | * Allocate space for DMA descriptors | ||
| 90 | * (add an extra element for link descriptor) | ||
| 91 | */ | ||
| 75 | bd_ptr = dma_zalloc_coherent(dev, | 92 | bd_ptr = dma_zalloc_coherent(dev, |
| 76 | bd_num * sizeof(struct tsi721_dma_desc), | 93 | (bd_num + 1) * sizeof(struct tsi721_dma_desc), |
| 77 | &bd_phys, GFP_KERNEL); | 94 | &bd_phys, GFP_KERNEL); |
| 78 | if (!bd_ptr) | 95 | if (!bd_ptr) |
| 79 | return -ENOMEM; | 96 | return -ENOMEM; |
| 80 | 97 | ||
| 98 | bdma_chan->bd_num = bd_num; | ||
| 81 | bdma_chan->bd_phys = bd_phys; | 99 | bdma_chan->bd_phys = bd_phys; |
| 82 | bdma_chan->bd_base = bd_ptr; | 100 | bdma_chan->bd_base = bd_ptr; |
| 83 | 101 | ||
| @@ -85,8 +103,8 @@ static int tsi721_bdma_ch_init(struct tsi721_bdma_chan *bdma_chan) | |||
| 85 | bd_ptr, (unsigned long long)bd_phys); | 103 | bd_ptr, (unsigned long long)bd_phys); |
| 86 | 104 | ||
| 87 | /* Allocate space for descriptor status FIFO */ | 105 | /* Allocate space for descriptor status FIFO */ |
| 88 | sts_size = (bd_num >= TSI721_DMA_MINSTSSZ) ? | 106 | sts_size = ((bd_num + 1) >= TSI721_DMA_MINSTSSZ) ? |
| 89 | bd_num : TSI721_DMA_MINSTSSZ; | 107 | (bd_num + 1) : TSI721_DMA_MINSTSSZ; |
| 90 | sts_size = roundup_pow_of_two(sts_size); | 108 | sts_size = roundup_pow_of_two(sts_size); |
| 91 | sts_ptr = dma_zalloc_coherent(dev, | 109 | sts_ptr = dma_zalloc_coherent(dev, |
| 92 | sts_size * sizeof(struct tsi721_dma_sts), | 110 | sts_size * sizeof(struct tsi721_dma_sts), |
| @@ -94,7 +112,7 @@ static int tsi721_bdma_ch_init(struct tsi721_bdma_chan *bdma_chan) | |||
| 94 | if (!sts_ptr) { | 112 | if (!sts_ptr) { |
| 95 | /* Free space allocated for DMA descriptors */ | 113 | /* Free space allocated for DMA descriptors */ |
| 96 | dma_free_coherent(dev, | 114 | dma_free_coherent(dev, |
| 97 | bd_num * sizeof(struct tsi721_dma_desc), | 115 | (bd_num + 1) * sizeof(struct tsi721_dma_desc), |
| 98 | bd_ptr, bd_phys); | 116 | bd_ptr, bd_phys); |
| 99 | bdma_chan->bd_base = NULL; | 117 | bdma_chan->bd_base = NULL; |
| 100 | return -ENOMEM; | 118 | return -ENOMEM; |
| @@ -108,11 +126,11 @@ static int tsi721_bdma_ch_init(struct tsi721_bdma_chan *bdma_chan) | |||
| 108 | "desc status FIFO @ %p (phys = %llx) size=0x%x\n", | 126 | "desc status FIFO @ %p (phys = %llx) size=0x%x\n", |
| 109 | sts_ptr, (unsigned long long)sts_phys, sts_size); | 127 | sts_ptr, (unsigned long long)sts_phys, sts_size); |
| 110 | 128 | ||
| 111 | /* Initialize DMA descriptors ring */ | 129 | /* Initialize DMA descriptors ring using added link descriptor */ |
| 112 | bd_ptr[bd_num - 1].type_id = cpu_to_le32(DTYPE3 << 29); | 130 | bd_ptr[bd_num].type_id = cpu_to_le32(DTYPE3 << 29); |
| 113 | bd_ptr[bd_num - 1].next_lo = cpu_to_le32((u64)bd_phys & | 131 | bd_ptr[bd_num].next_lo = cpu_to_le32((u64)bd_phys & |
| 114 | TSI721_DMAC_DPTRL_MASK); | 132 | TSI721_DMAC_DPTRL_MASK); |
| 115 | bd_ptr[bd_num - 1].next_hi = cpu_to_le32((u64)bd_phys >> 32); | 133 | bd_ptr[bd_num].next_hi = cpu_to_le32((u64)bd_phys >> 32); |
| 116 | 134 | ||
| 117 | /* Setup DMA descriptor pointers */ | 135 | /* Setup DMA descriptor pointers */ |
| 118 | iowrite32(((u64)bd_phys >> 32), | 136 | iowrite32(((u64)bd_phys >> 32), |
| @@ -134,6 +152,55 @@ static int tsi721_bdma_ch_init(struct tsi721_bdma_chan *bdma_chan) | |||
| 134 | 152 | ||
| 135 | ioread32(bdma_chan->regs + TSI721_DMAC_INT); | 153 | ioread32(bdma_chan->regs + TSI721_DMAC_INT); |
| 136 | 154 | ||
| 155 | #ifdef CONFIG_PCI_MSI | ||
| 156 | /* Request interrupt service if we are in MSI-X mode */ | ||
| 157 | if (priv->flags & TSI721_USING_MSIX) { | ||
| 158 | int rc, idx; | ||
| 159 | |||
| 160 | idx = TSI721_VECT_DMA0_DONE + bdma_chan->id; | ||
| 161 | |||
| 162 | rc = request_irq(priv->msix[idx].vector, tsi721_bdma_msix, 0, | ||
| 163 | priv->msix[idx].irq_name, (void *)bdma_chan); | ||
| 164 | |||
| 165 | if (rc) { | ||
| 166 | dev_dbg(dev, "Unable to get MSI-X for BDMA%d-DONE\n", | ||
| 167 | bdma_chan->id); | ||
| 168 | goto err_out; | ||
| 169 | } | ||
| 170 | |||
| 171 | idx = TSI721_VECT_DMA0_INT + bdma_chan->id; | ||
| 172 | |||
| 173 | rc = request_irq(priv->msix[idx].vector, tsi721_bdma_msix, 0, | ||
| 174 | priv->msix[idx].irq_name, (void *)bdma_chan); | ||
| 175 | |||
| 176 | if (rc) { | ||
| 177 | dev_dbg(dev, "Unable to get MSI-X for BDMA%d-INT\n", | ||
| 178 | bdma_chan->id); | ||
| 179 | free_irq( | ||
| 180 | priv->msix[TSI721_VECT_DMA0_DONE + | ||
| 181 | bdma_chan->id].vector, | ||
| 182 | (void *)bdma_chan); | ||
| 183 | } | ||
| 184 | |||
| 185 | err_out: | ||
| 186 | if (rc) { | ||
| 187 | /* Free space allocated for DMA descriptors */ | ||
| 188 | dma_free_coherent(dev, | ||
| 189 | (bd_num + 1) * sizeof(struct tsi721_dma_desc), | ||
| 190 | bd_ptr, bd_phys); | ||
| 191 | bdma_chan->bd_base = NULL; | ||
| 192 | |||
| 193 | /* Free space allocated for status descriptors */ | ||
| 194 | dma_free_coherent(dev, | ||
| 195 | sts_size * sizeof(struct tsi721_dma_sts), | ||
| 196 | sts_ptr, sts_phys); | ||
| 197 | bdma_chan->sts_base = NULL; | ||
| 198 | |||
| 199 | return -EIO; | ||
| 200 | } | ||
| 201 | } | ||
| 202 | #endif /* CONFIG_PCI_MSI */ | ||
| 203 | |||
| 137 | /* Toggle DMA channel initialization */ | 204 | /* Toggle DMA channel initialization */ |
| 138 | iowrite32(TSI721_DMAC_CTL_INIT, bdma_chan->regs + TSI721_DMAC_CTL); | 205 | iowrite32(TSI721_DMAC_CTL_INIT, bdma_chan->regs + TSI721_DMAC_CTL); |
| 139 | ioread32(bdma_chan->regs + TSI721_DMAC_CTL); | 206 | ioread32(bdma_chan->regs + TSI721_DMAC_CTL); |
| @@ -147,6 +214,9 @@ static int tsi721_bdma_ch_init(struct tsi721_bdma_chan *bdma_chan) | |||
| 147 | static int tsi721_bdma_ch_free(struct tsi721_bdma_chan *bdma_chan) | 214 | static int tsi721_bdma_ch_free(struct tsi721_bdma_chan *bdma_chan) |
| 148 | { | 215 | { |
| 149 | u32 ch_stat; | 216 | u32 ch_stat; |
| 217 | #ifdef CONFIG_PCI_MSI | ||
| 218 | struct tsi721_device *priv = to_tsi721(bdma_chan->dchan.device); | ||
| 219 | #endif | ||
| 150 | 220 | ||
| 151 | if (bdma_chan->bd_base == NULL) | 221 | if (bdma_chan->bd_base == NULL) |
| 152 | return 0; | 222 | return 0; |
| @@ -159,9 +229,18 @@ static int tsi721_bdma_ch_free(struct tsi721_bdma_chan *bdma_chan) | |||
| 159 | /* Put DMA channel into init state */ | 229 | /* Put DMA channel into init state */ |
| 160 | iowrite32(TSI721_DMAC_CTL_INIT, bdma_chan->regs + TSI721_DMAC_CTL); | 230 | iowrite32(TSI721_DMAC_CTL_INIT, bdma_chan->regs + TSI721_DMAC_CTL); |
| 161 | 231 | ||
| 232 | #ifdef CONFIG_PCI_MSI | ||
| 233 | if (priv->flags & TSI721_USING_MSIX) { | ||
| 234 | free_irq(priv->msix[TSI721_VECT_DMA0_DONE + | ||
| 235 | bdma_chan->id].vector, (void *)bdma_chan); | ||
| 236 | free_irq(priv->msix[TSI721_VECT_DMA0_INT + | ||
| 237 | bdma_chan->id].vector, (void *)bdma_chan); | ||
| 238 | } | ||
| 239 | #endif /* CONFIG_PCI_MSI */ | ||
| 240 | |||
| 162 | /* Free space allocated for DMA descriptors */ | 241 | /* Free space allocated for DMA descriptors */ |
| 163 | dma_free_coherent(bdma_chan->dchan.device->dev, | 242 | dma_free_coherent(bdma_chan->dchan.device->dev, |
| 164 | bdma_chan->bd_num * sizeof(struct tsi721_dma_desc), | 243 | (bdma_chan->bd_num + 1) * sizeof(struct tsi721_dma_desc), |
| 165 | bdma_chan->bd_base, bdma_chan->bd_phys); | 244 | bdma_chan->bd_base, bdma_chan->bd_phys); |
| 166 | bdma_chan->bd_base = NULL; | 245 | bdma_chan->bd_base = NULL; |
| 167 | 246 | ||
| @@ -243,8 +322,8 @@ static void tsi721_start_dma(struct tsi721_bdma_chan *bdma_chan) | |||
| 243 | } | 322 | } |
| 244 | 323 | ||
| 245 | dev_dbg(bdma_chan->dchan.device->dev, | 324 | dev_dbg(bdma_chan->dchan.device->dev, |
| 246 | "tx_chan: %p, chan: %d, regs: %p\n", | 325 | "%s: chan_%d (wrc=%d)\n", __func__, bdma_chan->id, |
| 247 | bdma_chan, bdma_chan->dchan.chan_id, bdma_chan->regs); | 326 | bdma_chan->wr_count_next); |
| 248 | 327 | ||
| 249 | iowrite32(bdma_chan->wr_count_next, | 328 | iowrite32(bdma_chan->wr_count_next, |
| 250 | bdma_chan->regs + TSI721_DMAC_DWRCNT); | 329 | bdma_chan->regs + TSI721_DMAC_DWRCNT); |
| @@ -253,72 +332,19 @@ static void tsi721_start_dma(struct tsi721_bdma_chan *bdma_chan) | |||
| 253 | bdma_chan->wr_count = bdma_chan->wr_count_next; | 332 | bdma_chan->wr_count = bdma_chan->wr_count_next; |
| 254 | } | 333 | } |
| 255 | 334 | ||
| 256 | static void tsi721_desc_put(struct tsi721_bdma_chan *bdma_chan, | ||
| 257 | struct tsi721_tx_desc *desc) | ||
| 258 | { | ||
| 259 | dev_dbg(bdma_chan->dchan.device->dev, | ||
| 260 | "Put desc: %p into free list\n", desc); | ||
| 261 | |||
| 262 | if (desc) { | ||
| 263 | spin_lock_bh(&bdma_chan->lock); | ||
| 264 | list_splice_init(&desc->tx_list, &bdma_chan->free_list); | ||
| 265 | list_add(&desc->desc_node, &bdma_chan->free_list); | ||
| 266 | bdma_chan->wr_count_next = bdma_chan->wr_count; | ||
| 267 | spin_unlock_bh(&bdma_chan->lock); | ||
| 268 | } | ||
| 269 | } | ||
| 270 | |||
| 271 | static | ||
| 272 | struct tsi721_tx_desc *tsi721_desc_get(struct tsi721_bdma_chan *bdma_chan) | ||
| 273 | { | ||
| 274 | struct tsi721_tx_desc *tx_desc, *_tx_desc; | ||
| 275 | struct tsi721_tx_desc *ret = NULL; | ||
| 276 | int i; | ||
| 277 | |||
| 278 | spin_lock_bh(&bdma_chan->lock); | ||
| 279 | list_for_each_entry_safe(tx_desc, _tx_desc, | ||
| 280 | &bdma_chan->free_list, desc_node) { | ||
| 281 | if (async_tx_test_ack(&tx_desc->txd)) { | ||
| 282 | list_del(&tx_desc->desc_node); | ||
| 283 | ret = tx_desc; | ||
| 284 | break; | ||
| 285 | } | ||
| 286 | dev_dbg(bdma_chan->dchan.device->dev, | ||
| 287 | "desc %p not ACKed\n", tx_desc); | ||
| 288 | } | ||
| 289 | |||
| 290 | if (ret == NULL) { | ||
| 291 | dev_dbg(bdma_chan->dchan.device->dev, | ||
| 292 | "%s: unable to obtain tx descriptor\n", __func__); | ||
| 293 | goto err_out; | ||
| 294 | } | ||
| 295 | |||
| 296 | i = bdma_chan->wr_count_next % bdma_chan->bd_num; | ||
| 297 | if (i == bdma_chan->bd_num - 1) { | ||
| 298 | i = 0; | ||
| 299 | bdma_chan->wr_count_next++; /* skip link descriptor */ | ||
| 300 | } | ||
| 301 | |||
| 302 | bdma_chan->wr_count_next++; | ||
| 303 | tx_desc->txd.phys = bdma_chan->bd_phys + | ||
| 304 | i * sizeof(struct tsi721_dma_desc); | ||
| 305 | tx_desc->hw_desc = &((struct tsi721_dma_desc *)bdma_chan->bd_base)[i]; | ||
| 306 | err_out: | ||
| 307 | spin_unlock_bh(&bdma_chan->lock); | ||
| 308 | |||
| 309 | return ret; | ||
| 310 | } | ||
| 311 | |||
| 312 | static int | 335 | static int |
| 313 | tsi721_desc_fill_init(struct tsi721_tx_desc *desc, struct scatterlist *sg, | 336 | tsi721_desc_fill_init(struct tsi721_tx_desc *desc, |
| 314 | enum dma_rtype rtype, u32 sys_size) | 337 | struct tsi721_dma_desc *bd_ptr, |
| 338 | struct scatterlist *sg, u32 sys_size) | ||
| 315 | { | 339 | { |
| 316 | struct tsi721_dma_desc *bd_ptr = desc->hw_desc; | ||
| 317 | u64 rio_addr; | 340 | u64 rio_addr; |
| 318 | 341 | ||
| 342 | if (bd_ptr == NULL) | ||
| 343 | return -EINVAL; | ||
| 344 | |||
| 319 | /* Initialize DMA descriptor */ | 345 | /* Initialize DMA descriptor */ |
| 320 | bd_ptr->type_id = cpu_to_le32((DTYPE1 << 29) | | 346 | bd_ptr->type_id = cpu_to_le32((DTYPE1 << 29) | |
| 321 | (rtype << 19) | desc->destid); | 347 | (desc->rtype << 19) | desc->destid); |
| 322 | bd_ptr->bcount = cpu_to_le32(((desc->rio_addr & 0x3) << 30) | | 348 | bd_ptr->bcount = cpu_to_le32(((desc->rio_addr & 0x3) << 30) | |
| 323 | (sys_size << 26)); | 349 | (sys_size << 26)); |
| 324 | rio_addr = (desc->rio_addr >> 2) | | 350 | rio_addr = (desc->rio_addr >> 2) | |
| @@ -335,51 +361,32 @@ tsi721_desc_fill_init(struct tsi721_tx_desc *desc, struct scatterlist *sg, | |||
| 335 | } | 361 | } |
| 336 | 362 | ||
| 337 | static int | 363 | static int |
| 338 | tsi721_desc_fill_end(struct tsi721_tx_desc *desc) | 364 | tsi721_desc_fill_end(struct tsi721_dma_desc *bd_ptr, u32 bcount, bool interrupt) |
| 339 | { | 365 | { |
| 340 | struct tsi721_dma_desc *bd_ptr = desc->hw_desc; | 366 | if (bd_ptr == NULL) |
| 367 | return -EINVAL; | ||
| 341 | 368 | ||
| 342 | /* Update DMA descriptor */ | 369 | /* Update DMA descriptor */ |
| 343 | if (desc->interrupt) | 370 | if (interrupt) |
| 344 | bd_ptr->type_id |= cpu_to_le32(TSI721_DMAD_IOF); | 371 | bd_ptr->type_id |= cpu_to_le32(TSI721_DMAD_IOF); |
| 345 | bd_ptr->bcount |= cpu_to_le32(desc->bcount & TSI721_DMAD_BCOUNT1); | 372 | bd_ptr->bcount |= cpu_to_le32(bcount & TSI721_DMAD_BCOUNT1); |
| 346 | 373 | ||
| 347 | return 0; | 374 | return 0; |
| 348 | } | 375 | } |
| 349 | 376 | ||
| 350 | 377 | static void tsi721_dma_tx_err(struct tsi721_bdma_chan *bdma_chan, | |
| 351 | static void tsi721_dma_chain_complete(struct tsi721_bdma_chan *bdma_chan, | 378 | struct tsi721_tx_desc *desc) |
| 352 | struct tsi721_tx_desc *desc) | ||
| 353 | { | 379 | { |
| 354 | struct dma_async_tx_descriptor *txd = &desc->txd; | 380 | struct dma_async_tx_descriptor *txd = &desc->txd; |
| 355 | dma_async_tx_callback callback = txd->callback; | 381 | dma_async_tx_callback callback = txd->callback; |
| 356 | void *param = txd->callback_param; | 382 | void *param = txd->callback_param; |
| 357 | 383 | ||
| 358 | list_splice_init(&desc->tx_list, &bdma_chan->free_list); | ||
| 359 | list_move(&desc->desc_node, &bdma_chan->free_list); | 384 | list_move(&desc->desc_node, &bdma_chan->free_list); |
| 360 | bdma_chan->completed_cookie = txd->cookie; | ||
| 361 | 385 | ||
| 362 | if (callback) | 386 | if (callback) |
| 363 | callback(param); | 387 | callback(param); |
| 364 | } | 388 | } |
| 365 | 389 | ||
| 366 | static void tsi721_dma_complete_all(struct tsi721_bdma_chan *bdma_chan) | ||
| 367 | { | ||
| 368 | struct tsi721_tx_desc *desc, *_d; | ||
| 369 | LIST_HEAD(list); | ||
| 370 | |||
| 371 | BUG_ON(!tsi721_dma_is_idle(bdma_chan)); | ||
| 372 | |||
| 373 | if (!list_empty(&bdma_chan->queue)) | ||
| 374 | tsi721_start_dma(bdma_chan); | ||
| 375 | |||
| 376 | list_splice_init(&bdma_chan->active_list, &list); | ||
| 377 | list_splice_init(&bdma_chan->queue, &bdma_chan->active_list); | ||
| 378 | |||
| 379 | list_for_each_entry_safe(desc, _d, &list, desc_node) | ||
| 380 | tsi721_dma_chain_complete(bdma_chan, desc); | ||
| 381 | } | ||
| 382 | |||
| 383 | static void tsi721_clr_stat(struct tsi721_bdma_chan *bdma_chan) | 390 | static void tsi721_clr_stat(struct tsi721_bdma_chan *bdma_chan) |
| 384 | { | 391 | { |
| 385 | u32 srd_ptr; | 392 | u32 srd_ptr; |
| @@ -403,20 +410,159 @@ static void tsi721_clr_stat(struct tsi721_bdma_chan *bdma_chan) | |||
| 403 | bdma_chan->sts_rdptr = srd_ptr; | 410 | bdma_chan->sts_rdptr = srd_ptr; |
| 404 | } | 411 | } |
| 405 | 412 | ||
| 413 | /* Must be called with the channel spinlock held */ | ||
| 414 | static int tsi721_submit_sg(struct tsi721_tx_desc *desc) | ||
| 415 | { | ||
| 416 | struct dma_chan *dchan = desc->txd.chan; | ||
| 417 | struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan); | ||
| 418 | u32 sys_size; | ||
| 419 | u64 rio_addr; | ||
| 420 | dma_addr_t next_addr; | ||
| 421 | u32 bcount; | ||
| 422 | struct scatterlist *sg; | ||
| 423 | unsigned int i; | ||
| 424 | int err = 0; | ||
| 425 | struct tsi721_dma_desc *bd_ptr = NULL; | ||
| 426 | u32 idx, rd_idx; | ||
| 427 | u32 add_count = 0; | ||
| 428 | |||
| 429 | if (!tsi721_dma_is_idle(bdma_chan)) { | ||
| 430 | dev_err(bdma_chan->dchan.device->dev, | ||
| 431 | "BUG: Attempt to use non-idle channel\n"); | ||
| 432 | return -EIO; | ||
| 433 | } | ||
| 434 | |||
| 435 | /* | ||
| 436 | * Fill DMA channel's hardware buffer descriptors. | ||
| 437 | * (NOTE: RapidIO destination address is limited to 64 bits for now) | ||
| 438 | */ | ||
| 439 | rio_addr = desc->rio_addr; | ||
| 440 | next_addr = -1; | ||
| 441 | bcount = 0; | ||
| 442 | sys_size = dma_to_mport(bdma_chan->dchan.device)->sys_size; | ||
| 443 | |||
| 444 | rd_idx = ioread32(bdma_chan->regs + TSI721_DMAC_DRDCNT); | ||
| 445 | rd_idx %= (bdma_chan->bd_num + 1); | ||
| 446 | |||
| 447 | idx = bdma_chan->wr_count_next % (bdma_chan->bd_num + 1); | ||
| 448 | if (idx == bdma_chan->bd_num) { | ||
| 449 | /* wrap around link descriptor */ | ||
| 450 | idx = 0; | ||
| 451 | add_count++; | ||
| 452 | } | ||
| 453 | |||
| 454 | dev_dbg(dchan->device->dev, "%s: BD ring status: rdi=%d wri=%d\n", | ||
| 455 | __func__, rd_idx, idx); | ||
| 456 | |||
| 457 | for_each_sg(desc->sg, sg, desc->sg_len, i) { | ||
| 458 | |||
| 459 | dev_dbg(dchan->device->dev, "sg%d/%d addr: 0x%llx len: %d\n", | ||
| 460 | i, desc->sg_len, | ||
| 461 | (unsigned long long)sg_dma_address(sg), sg_dma_len(sg)); | ||
| 462 | |||
| 463 | if (sg_dma_len(sg) > TSI721_BDMA_MAX_BCOUNT) { | ||
| 464 | dev_err(dchan->device->dev, | ||
| 465 | "%s: SG entry %d is too large\n", __func__, i); | ||
| 466 | err = -EINVAL; | ||
| 467 | break; | ||
| 468 | } | ||
| 469 | |||
| 470 | /* | ||
| 471 | * If this sg entry forms contiguous block with previous one, | ||
| 472 | * try to merge it into existing DMA descriptor | ||
| 473 | */ | ||
| 474 | if (next_addr == sg_dma_address(sg) && | ||
| 475 | bcount + sg_dma_len(sg) <= TSI721_BDMA_MAX_BCOUNT) { | ||
| 476 | /* Adjust byte count of the descriptor */ | ||
| 477 | bcount += sg_dma_len(sg); | ||
| 478 | goto entry_done; | ||
| 479 | } else if (next_addr != -1) { | ||
| 480 | /* Finalize descriptor using total byte count value */ | ||
| 481 | tsi721_desc_fill_end(bd_ptr, bcount, 0); | ||
| 482 | dev_dbg(dchan->device->dev, | ||
| 483 | "%s: prev desc final len: %d\n", | ||
| 484 | __func__, bcount); | ||
| 485 | } | ||
| 486 | |||
| 487 | desc->rio_addr = rio_addr; | ||
| 488 | |||
| 489 | if (i && idx == rd_idx) { | ||
| 490 | dev_dbg(dchan->device->dev, | ||
| 491 | "%s: HW descriptor ring is full @ %d\n", | ||
| 492 | __func__, i); | ||
| 493 | desc->sg = sg; | ||
| 494 | desc->sg_len -= i; | ||
| 495 | break; | ||
| 496 | } | ||
| 497 | |||
| 498 | bd_ptr = &((struct tsi721_dma_desc *)bdma_chan->bd_base)[idx]; | ||
| 499 | err = tsi721_desc_fill_init(desc, bd_ptr, sg, sys_size); | ||
| 500 | if (err) { | ||
| 501 | dev_err(dchan->device->dev, | ||
| 502 | "Failed to build desc: err=%d\n", err); | ||
| 503 | break; | ||
| 504 | } | ||
| 505 | |||
| 506 | dev_dbg(dchan->device->dev, "bd_ptr = %p did=%d raddr=0x%llx\n", | ||
| 507 | bd_ptr, desc->destid, desc->rio_addr); | ||
| 508 | |||
| 509 | next_addr = sg_dma_address(sg); | ||
| 510 | bcount = sg_dma_len(sg); | ||
| 511 | |||
| 512 | add_count++; | ||
| 513 | if (++idx == bdma_chan->bd_num) { | ||
| 514 | /* wrap around link descriptor */ | ||
| 515 | idx = 0; | ||
| 516 | add_count++; | ||
| 517 | } | ||
| 518 | |||
| 519 | entry_done: | ||
| 520 | if (sg_is_last(sg)) { | ||
| 521 | tsi721_desc_fill_end(bd_ptr, bcount, 0); | ||
| 522 | dev_dbg(dchan->device->dev, "%s: last desc final len: %d\n", | ||
| 523 | __func__, bcount); | ||
| 524 | desc->sg_len = 0; | ||
| 525 | } else { | ||
| 526 | rio_addr += sg_dma_len(sg); | ||
| 527 | next_addr += sg_dma_len(sg); | ||
| 528 | } | ||
| 529 | } | ||
| 530 | |||
| 531 | if (!err) | ||
| 532 | bdma_chan->wr_count_next += add_count; | ||
| 533 | |||
| 534 | return err; | ||
| 535 | } | ||
| 536 | |||
| 406 | static void tsi721_advance_work(struct tsi721_bdma_chan *bdma_chan) | 537 | static void tsi721_advance_work(struct tsi721_bdma_chan *bdma_chan) |
| 407 | { | 538 | { |
| 408 | if (list_empty(&bdma_chan->active_list) || | 539 | struct tsi721_tx_desc *desc; |
| 409 | list_is_singular(&bdma_chan->active_list)) { | 540 | int err; |
| 410 | dev_dbg(bdma_chan->dchan.device->dev, | 541 | |
| 411 | "%s: Active_list empty\n", __func__); | 542 | dev_dbg(bdma_chan->dchan.device->dev, "%s: Enter\n", __func__); |
| 412 | tsi721_dma_complete_all(bdma_chan); | 543 | |
| 413 | } else { | 544 | /* |
| 414 | dev_dbg(bdma_chan->dchan.device->dev, | 545 | * If there are any new transactions in the queue add them |
| 415 | "%s: Active_list NOT empty\n", __func__); | 546 | * into the processing list |
| 416 | tsi721_dma_chain_complete(bdma_chan, | 547 | */ |
| 417 | tsi721_dma_first_active(bdma_chan)); | 548 | if (!list_empty(&bdma_chan->queue)) |
| 418 | tsi721_start_dma(bdma_chan); | 549 | list_splice_init(&bdma_chan->queue, &bdma_chan->active_list); |
| 550 | |||
| 551 | /* Start new transaction (if available) */ | ||
| 552 | if (!list_empty(&bdma_chan->active_list)) { | ||
| 553 | desc = tsi721_dma_first_active(bdma_chan); | ||
| 554 | err = tsi721_submit_sg(desc); | ||
| 555 | if (!err) | ||
| 556 | tsi721_start_dma(bdma_chan); | ||
| 557 | else { | ||
| 558 | tsi721_dma_tx_err(bdma_chan, desc); | ||
| 559 | dev_dbg(bdma_chan->dchan.device->dev, | ||
| 560 | "ERR: tsi721_submit_sg failed with err=%d\n", | ||
| 561 | err); | ||
| 562 | } | ||
| 419 | } | 563 | } |
| 564 | |||
| 565 | dev_dbg(bdma_chan->dchan.device->dev, "%s: Exit\n", __func__); | ||
| 420 | } | 566 | } |
| 421 | 567 | ||
| 422 | static void tsi721_dma_tasklet(unsigned long data) | 568 | static void tsi721_dma_tasklet(unsigned long data) |
| @@ -444,8 +590,29 @@ static void tsi721_dma_tasklet(unsigned long data) | |||
| 444 | } | 590 | } |
| 445 | 591 | ||
| 446 | if (dmac_int & (TSI721_DMAC_INT_DONE | TSI721_DMAC_INT_IOFDONE)) { | 592 | if (dmac_int & (TSI721_DMAC_INT_DONE | TSI721_DMAC_INT_IOFDONE)) { |
| 593 | struct tsi721_tx_desc *desc; | ||
| 594 | |||
| 447 | tsi721_clr_stat(bdma_chan); | 595 | tsi721_clr_stat(bdma_chan); |
| 448 | spin_lock(&bdma_chan->lock); | 596 | spin_lock(&bdma_chan->lock); |
| 597 | desc = tsi721_dma_first_active(bdma_chan); | ||
| 598 | |||
| 599 | if (desc->sg_len == 0) { | ||
| 600 | dma_async_tx_callback callback = NULL; | ||
| 601 | void *param = NULL; | ||
| 602 | |||
| 603 | desc->status = DMA_COMPLETE; | ||
| 604 | dma_cookie_complete(&desc->txd); | ||
| 605 | if (desc->txd.flags & DMA_PREP_INTERRUPT) { | ||
| 606 | callback = desc->txd.callback; | ||
| 607 | param = desc->txd.callback_param; | ||
| 608 | } | ||
| 609 | list_move(&desc->desc_node, &bdma_chan->free_list); | ||
| 610 | spin_unlock(&bdma_chan->lock); | ||
| 611 | if (callback) | ||
| 612 | callback(param); | ||
| 613 | spin_lock(&bdma_chan->lock); | ||
| 614 | } | ||
| 615 | |||
| 449 | tsi721_advance_work(bdma_chan); | 616 | tsi721_advance_work(bdma_chan); |
| 450 | spin_unlock(&bdma_chan->lock); | 617 | spin_unlock(&bdma_chan->lock); |
| 451 | } | 618 | } |
| @@ -460,21 +627,24 @@ static dma_cookie_t tsi721_tx_submit(struct dma_async_tx_descriptor *txd) | |||
| 460 | struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(txd->chan); | 627 | struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(txd->chan); |
| 461 | dma_cookie_t cookie; | 628 | dma_cookie_t cookie; |
| 462 | 629 | ||
| 463 | spin_lock_bh(&bdma_chan->lock); | 630 | /* Check if the descriptor is detached from any lists */ |
| 631 | if (!list_empty(&desc->desc_node)) { | ||
| 632 | dev_err(bdma_chan->dchan.device->dev, | ||
| 633 | "%s: wrong state of descriptor %p\n", __func__, txd); | ||
| 634 | return -EIO; | ||
| 635 | } | ||
| 464 | 636 | ||
| 465 | cookie = txd->chan->cookie; | 637 | spin_lock_bh(&bdma_chan->lock); |
| 466 | if (++cookie < 0) | ||
| 467 | cookie = 1; | ||
| 468 | txd->chan->cookie = cookie; | ||
| 469 | txd->cookie = cookie; | ||
| 470 | 638 | ||
| 471 | if (list_empty(&bdma_chan->active_list)) { | 639 | if (!bdma_chan->active) { |
| 472 | list_add_tail(&desc->desc_node, &bdma_chan->active_list); | 640 | spin_unlock_bh(&bdma_chan->lock); |
| 473 | tsi721_start_dma(bdma_chan); | 641 | return -ENODEV; |
| 474 | } else { | ||
| 475 | list_add_tail(&desc->desc_node, &bdma_chan->queue); | ||
| 476 | } | 642 | } |
| 477 | 643 | ||
| 644 | cookie = dma_cookie_assign(txd); | ||
| 645 | desc->status = DMA_IN_PROGRESS; | ||
| 646 | list_add_tail(&desc->desc_node, &bdma_chan->queue); | ||
| 647 | |||
| 478 | spin_unlock_bh(&bdma_chan->lock); | 648 | spin_unlock_bh(&bdma_chan->lock); |
| 479 | return cookie; | 649 | return cookie; |
| 480 | } | 650 | } |
| @@ -482,115 +652,52 @@ static dma_cookie_t tsi721_tx_submit(struct dma_async_tx_descriptor *txd) | |||
| 482 | static int tsi721_alloc_chan_resources(struct dma_chan *dchan) | 652 | static int tsi721_alloc_chan_resources(struct dma_chan *dchan) |
| 483 | { | 653 | { |
| 484 | struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan); | 654 | struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan); |
| 485 | #ifdef CONFIG_PCI_MSI | ||
| 486 | struct tsi721_device *priv = to_tsi721(dchan->device); | ||
| 487 | #endif | ||
| 488 | struct tsi721_tx_desc *desc = NULL; | 655 | struct tsi721_tx_desc *desc = NULL; |
| 489 | LIST_HEAD(tmp_list); | ||
| 490 | int i; | 656 | int i; |
| 491 | int rc; | 657 | |
| 658 | dev_dbg(dchan->device->dev, "%s: for channel %d\n", | ||
| 659 | __func__, bdma_chan->id); | ||
| 492 | 660 | ||
| 493 | if (bdma_chan->bd_base) | 661 | if (bdma_chan->bd_base) |
| 494 | return bdma_chan->bd_num - 1; | 662 | return TSI721_DMA_TX_QUEUE_SZ; |
| 495 | 663 | ||
| 496 | /* Initialize BDMA channel */ | 664 | /* Initialize BDMA channel */ |
| 497 | if (tsi721_bdma_ch_init(bdma_chan)) { | 665 | if (tsi721_bdma_ch_init(bdma_chan, dma_desc_per_channel)) { |
| 498 | dev_err(dchan->device->dev, "Unable to initialize data DMA" | 666 | dev_err(dchan->device->dev, "Unable to initialize data DMA" |
| 499 | " channel %d, aborting\n", bdma_chan->id); | 667 | " channel %d, aborting\n", bdma_chan->id); |
| 500 | return -ENOMEM; | 668 | return -ENODEV; |
| 501 | } | 669 | } |
| 502 | 670 | ||
| 503 | /* Alocate matching number of logical descriptors */ | 671 | /* Allocate queue of transaction descriptors */ |
| 504 | desc = kcalloc((bdma_chan->bd_num - 1), sizeof(struct tsi721_tx_desc), | 672 | desc = kcalloc(TSI721_DMA_TX_QUEUE_SZ, sizeof(struct tsi721_tx_desc), |
| 505 | GFP_KERNEL); | 673 | GFP_KERNEL); |
| 506 | if (!desc) { | 674 | if (!desc) { |
| 507 | dev_err(dchan->device->dev, | 675 | dev_err(dchan->device->dev, |
| 508 | "Failed to allocate logical descriptors\n"); | 676 | "Failed to allocate logical descriptors\n"); |
| 509 | rc = -ENOMEM; | 677 | tsi721_bdma_ch_free(bdma_chan); |
| 510 | goto err_out; | 678 | return -ENOMEM; |
| 511 | } | 679 | } |
| 512 | 680 | ||
| 513 | bdma_chan->tx_desc = desc; | 681 | bdma_chan->tx_desc = desc; |
| 514 | 682 | ||
| 515 | for (i = 0; i < bdma_chan->bd_num - 1; i++) { | 683 | for (i = 0; i < TSI721_DMA_TX_QUEUE_SZ; i++) { |
| 516 | dma_async_tx_descriptor_init(&desc[i].txd, dchan); | 684 | dma_async_tx_descriptor_init(&desc[i].txd, dchan); |
| 517 | desc[i].txd.tx_submit = tsi721_tx_submit; | 685 | desc[i].txd.tx_submit = tsi721_tx_submit; |
| 518 | desc[i].txd.flags = DMA_CTRL_ACK; | 686 | desc[i].txd.flags = DMA_CTRL_ACK; |
| 519 | INIT_LIST_HEAD(&desc[i].tx_list); | 687 | list_add(&desc[i].desc_node, &bdma_chan->free_list); |
| 520 | list_add_tail(&desc[i].desc_node, &tmp_list); | ||
| 521 | } | 688 | } |
| 522 | 689 | ||
| 523 | spin_lock_bh(&bdma_chan->lock); | 690 | dma_cookie_init(dchan); |
| 524 | list_splice(&tmp_list, &bdma_chan->free_list); | ||
| 525 | bdma_chan->completed_cookie = dchan->cookie = 1; | ||
| 526 | spin_unlock_bh(&bdma_chan->lock); | ||
| 527 | |||
| 528 | #ifdef CONFIG_PCI_MSI | ||
| 529 | if (priv->flags & TSI721_USING_MSIX) { | ||
| 530 | /* Request interrupt service if we are in MSI-X mode */ | ||
| 531 | rc = request_irq( | ||
| 532 | priv->msix[TSI721_VECT_DMA0_DONE + | ||
| 533 | bdma_chan->id].vector, | ||
| 534 | tsi721_bdma_msix, 0, | ||
| 535 | priv->msix[TSI721_VECT_DMA0_DONE + | ||
| 536 | bdma_chan->id].irq_name, | ||
| 537 | (void *)bdma_chan); | ||
| 538 | |||
| 539 | if (rc) { | ||
| 540 | dev_dbg(dchan->device->dev, | ||
| 541 | "Unable to allocate MSI-X interrupt for " | ||
| 542 | "BDMA%d-DONE\n", bdma_chan->id); | ||
| 543 | goto err_out; | ||
| 544 | } | ||
| 545 | |||
| 546 | rc = request_irq(priv->msix[TSI721_VECT_DMA0_INT + | ||
| 547 | bdma_chan->id].vector, | ||
| 548 | tsi721_bdma_msix, 0, | ||
| 549 | priv->msix[TSI721_VECT_DMA0_INT + | ||
| 550 | bdma_chan->id].irq_name, | ||
| 551 | (void *)bdma_chan); | ||
| 552 | |||
| 553 | if (rc) { | ||
| 554 | dev_dbg(dchan->device->dev, | ||
| 555 | "Unable to allocate MSI-X interrupt for " | ||
| 556 | "BDMA%d-INT\n", bdma_chan->id); | ||
| 557 | free_irq( | ||
| 558 | priv->msix[TSI721_VECT_DMA0_DONE + | ||
| 559 | bdma_chan->id].vector, | ||
| 560 | (void *)bdma_chan); | ||
| 561 | rc = -EIO; | ||
| 562 | goto err_out; | ||
| 563 | } | ||
| 564 | } | ||
| 565 | #endif /* CONFIG_PCI_MSI */ | ||
| 566 | 691 | ||
| 567 | bdma_chan->active = true; | 692 | bdma_chan->active = true; |
| 568 | tsi721_bdma_interrupt_enable(bdma_chan, 1); | 693 | tsi721_bdma_interrupt_enable(bdma_chan, 1); |
| 569 | 694 | ||
| 570 | return bdma_chan->bd_num - 1; | 695 | return TSI721_DMA_TX_QUEUE_SZ; |
| 571 | |||
| 572 | err_out: | ||
| 573 | kfree(desc); | ||
| 574 | tsi721_bdma_ch_free(bdma_chan); | ||
| 575 | return rc; | ||
| 576 | } | 696 | } |
| 577 | 697 | ||
| 578 | static void tsi721_free_chan_resources(struct dma_chan *dchan) | 698 | static void tsi721_sync_dma_irq(struct tsi721_bdma_chan *bdma_chan) |
| 579 | { | 699 | { |
| 580 | struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan); | 700 | struct tsi721_device *priv = to_tsi721(bdma_chan->dchan.device); |
| 581 | struct tsi721_device *priv = to_tsi721(dchan->device); | ||
| 582 | LIST_HEAD(list); | ||
| 583 | |||
| 584 | dev_dbg(dchan->device->dev, "%s: Entry\n", __func__); | ||
| 585 | |||
| 586 | if (bdma_chan->bd_base == NULL) | ||
| 587 | return; | ||
| 588 | |||
| 589 | BUG_ON(!list_empty(&bdma_chan->active_list)); | ||
| 590 | BUG_ON(!list_empty(&bdma_chan->queue)); | ||
| 591 | |||
| 592 | tsi721_bdma_interrupt_enable(bdma_chan, 0); | ||
| 593 | bdma_chan->active = false; | ||
| 594 | 701 | ||
| 595 | #ifdef CONFIG_PCI_MSI | 702 | #ifdef CONFIG_PCI_MSI |
| 596 | if (priv->flags & TSI721_USING_MSIX) { | 703 | if (priv->flags & TSI721_USING_MSIX) { |
| @@ -601,64 +708,48 @@ static void tsi721_free_chan_resources(struct dma_chan *dchan) | |||
| 601 | } else | 708 | } else |
| 602 | #endif | 709 | #endif |
| 603 | synchronize_irq(priv->pdev->irq); | 710 | synchronize_irq(priv->pdev->irq); |
| 711 | } | ||
| 604 | 712 | ||
| 605 | tasklet_kill(&bdma_chan->tasklet); | 713 | static void tsi721_free_chan_resources(struct dma_chan *dchan) |
| 714 | { | ||
| 715 | struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan); | ||
| 606 | 716 | ||
| 607 | spin_lock_bh(&bdma_chan->lock); | 717 | dev_dbg(dchan->device->dev, "%s: for channel %d\n", |
| 608 | list_splice_init(&bdma_chan->free_list, &list); | 718 | __func__, bdma_chan->id); |
| 609 | spin_unlock_bh(&bdma_chan->lock); | ||
| 610 | 719 | ||
| 611 | #ifdef CONFIG_PCI_MSI | 720 | if (bdma_chan->bd_base == NULL) |
| 612 | if (priv->flags & TSI721_USING_MSIX) { | 721 | return; |
| 613 | free_irq(priv->msix[TSI721_VECT_DMA0_DONE + | ||
| 614 | bdma_chan->id].vector, (void *)bdma_chan); | ||
| 615 | free_irq(priv->msix[TSI721_VECT_DMA0_INT + | ||
| 616 | bdma_chan->id].vector, (void *)bdma_chan); | ||
| 617 | } | ||
| 618 | #endif /* CONFIG_PCI_MSI */ | ||
| 619 | 722 | ||
| 620 | tsi721_bdma_ch_free(bdma_chan); | 723 | BUG_ON(!list_empty(&bdma_chan->active_list)); |
| 724 | BUG_ON(!list_empty(&bdma_chan->queue)); | ||
| 725 | |||
| 726 | tsi721_bdma_interrupt_enable(bdma_chan, 0); | ||
| 727 | bdma_chan->active = false; | ||
| 728 | tsi721_sync_dma_irq(bdma_chan); | ||
| 729 | tasklet_kill(&bdma_chan->tasklet); | ||
| 730 | INIT_LIST_HEAD(&bdma_chan->free_list); | ||
| 621 | kfree(bdma_chan->tx_desc); | 731 | kfree(bdma_chan->tx_desc); |
| 732 | tsi721_bdma_ch_free(bdma_chan); | ||
| 622 | } | 733 | } |
| 623 | 734 | ||
| 624 | static | 735 | static |
| 625 | enum dma_status tsi721_tx_status(struct dma_chan *dchan, dma_cookie_t cookie, | 736 | enum dma_status tsi721_tx_status(struct dma_chan *dchan, dma_cookie_t cookie, |
| 626 | struct dma_tx_state *txstate) | 737 | struct dma_tx_state *txstate) |
| 627 | { | 738 | { |
| 628 | struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan); | 739 | return dma_cookie_status(dchan, cookie, txstate); |
| 629 | dma_cookie_t last_used; | ||
| 630 | dma_cookie_t last_completed; | ||
| 631 | int ret; | ||
| 632 | |||
| 633 | spin_lock_bh(&bdma_chan->lock); | ||
| 634 | last_completed = bdma_chan->completed_cookie; | ||
| 635 | last_used = dchan->cookie; | ||
| 636 | spin_unlock_bh(&bdma_chan->lock); | ||
| 637 | |||
| 638 | ret = dma_async_is_complete(cookie, last_completed, last_used); | ||
| 639 | |||
| 640 | dma_set_tx_state(txstate, last_completed, last_used, 0); | ||
| 641 | |||
| 642 | dev_dbg(dchan->device->dev, | ||
| 643 | "%s: exit, ret: %d, last_completed: %d, last_used: %d\n", | ||
| 644 | __func__, ret, last_completed, last_used); | ||
| 645 | |||
| 646 | return ret; | ||
| 647 | } | 740 | } |
| 648 | 741 | ||
| 649 | static void tsi721_issue_pending(struct dma_chan *dchan) | 742 | static void tsi721_issue_pending(struct dma_chan *dchan) |
| 650 | { | 743 | { |
| 651 | struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan); | 744 | struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan); |
| 652 | 745 | ||
| 653 | dev_dbg(dchan->device->dev, "%s: Entry\n", __func__); | 746 | dev_dbg(dchan->device->dev, "%s: Enter\n", __func__); |
| 654 | 747 | ||
| 655 | if (tsi721_dma_is_idle(bdma_chan)) { | 748 | if (tsi721_dma_is_idle(bdma_chan) && bdma_chan->active) { |
| 656 | spin_lock_bh(&bdma_chan->lock); | 749 | spin_lock_bh(&bdma_chan->lock); |
| 657 | tsi721_advance_work(bdma_chan); | 750 | tsi721_advance_work(bdma_chan); |
| 658 | spin_unlock_bh(&bdma_chan->lock); | 751 | spin_unlock_bh(&bdma_chan->lock); |
| 659 | } else | 752 | } |
| 660 | dev_dbg(dchan->device->dev, | ||
| 661 | "%s: DMA channel still busy\n", __func__); | ||
| 662 | } | 753 | } |
| 663 | 754 | ||
| 664 | static | 755 | static |
| @@ -668,21 +759,19 @@ struct dma_async_tx_descriptor *tsi721_prep_rio_sg(struct dma_chan *dchan, | |||
| 668 | void *tinfo) | 759 | void *tinfo) |
| 669 | { | 760 | { |
| 670 | struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan); | 761 | struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan); |
| 671 | struct tsi721_tx_desc *desc = NULL; | 762 | struct tsi721_tx_desc *desc, *_d; |
| 672 | struct tsi721_tx_desc *first = NULL; | ||
| 673 | struct scatterlist *sg; | ||
| 674 | struct rio_dma_ext *rext = tinfo; | 763 | struct rio_dma_ext *rext = tinfo; |
| 675 | u64 rio_addr = rext->rio_addr; /* limited to 64-bit rio_addr for now */ | ||
| 676 | unsigned int i; | ||
| 677 | u32 sys_size = dma_to_mport(dchan->device)->sys_size; | ||
| 678 | enum dma_rtype rtype; | 764 | enum dma_rtype rtype; |
| 679 | dma_addr_t next_addr = -1; | 765 | struct dma_async_tx_descriptor *txd = NULL; |
| 680 | 766 | ||
| 681 | if (!sgl || !sg_len) { | 767 | if (!sgl || !sg_len) { |
| 682 | dev_err(dchan->device->dev, "%s: No SG list\n", __func__); | 768 | dev_err(dchan->device->dev, "%s: No SG list\n", __func__); |
| 683 | return NULL; | 769 | return NULL; |
| 684 | } | 770 | } |
| 685 | 771 | ||
| 772 | dev_dbg(dchan->device->dev, "%s: %s\n", __func__, | ||
| 773 | (dir == DMA_DEV_TO_MEM)?"READ":"WRITE"); | ||
| 774 | |||
| 686 | if (dir == DMA_DEV_TO_MEM) | 775 | if (dir == DMA_DEV_TO_MEM) |
| 687 | rtype = NREAD; | 776 | rtype = NREAD; |
| 688 | else if (dir == DMA_MEM_TO_DEV) { | 777 | else if (dir == DMA_MEM_TO_DEV) { |
| @@ -704,97 +793,26 @@ struct dma_async_tx_descriptor *tsi721_prep_rio_sg(struct dma_chan *dchan, | |||
| 704 | return NULL; | 793 | return NULL; |
| 705 | } | 794 | } |
| 706 | 795 | ||
| 707 | for_each_sg(sgl, sg, sg_len, i) { | 796 | spin_lock_bh(&bdma_chan->lock); |
| 708 | int err; | ||
| 709 | |||
| 710 | if (sg_dma_len(sg) > TSI721_BDMA_MAX_BCOUNT) { | ||
| 711 | dev_err(dchan->device->dev, | ||
| 712 | "%s: SG entry %d is too large\n", __func__, i); | ||
| 713 | goto err_desc_put; | ||
| 714 | } | ||
| 715 | |||
| 716 | /* | ||
| 717 | * If this sg entry forms contiguous block with previous one, | ||
| 718 | * try to merge it into existing DMA descriptor | ||
| 719 | */ | ||
| 720 | if (desc) { | ||
| 721 | if (next_addr == sg_dma_address(sg) && | ||
| 722 | desc->bcount + sg_dma_len(sg) <= | ||
| 723 | TSI721_BDMA_MAX_BCOUNT) { | ||
| 724 | /* Adjust byte count of the descriptor */ | ||
| 725 | desc->bcount += sg_dma_len(sg); | ||
| 726 | goto entry_done; | ||
| 727 | } | ||
| 728 | |||
| 729 | /* | ||
| 730 | * Finalize this descriptor using total | ||
| 731 | * byte count value. | ||
| 732 | */ | ||
| 733 | tsi721_desc_fill_end(desc); | ||
| 734 | dev_dbg(dchan->device->dev, "%s: desc final len: %d\n", | ||
| 735 | __func__, desc->bcount); | ||
| 736 | } | ||
| 737 | |||
| 738 | /* | ||
| 739 | * Obtain and initialize a new descriptor | ||
| 740 | */ | ||
| 741 | desc = tsi721_desc_get(bdma_chan); | ||
| 742 | if (!desc) { | ||
| 743 | dev_err(dchan->device->dev, | ||
| 744 | "%s: Failed to get new descriptor for SG %d\n", | ||
| 745 | __func__, i); | ||
| 746 | goto err_desc_put; | ||
| 747 | } | ||
| 748 | |||
| 749 | desc->destid = rext->destid; | ||
| 750 | desc->rio_addr = rio_addr; | ||
| 751 | desc->rio_addr_u = 0; | ||
| 752 | desc->bcount = sg_dma_len(sg); | ||
| 753 | |||
| 754 | dev_dbg(dchan->device->dev, | ||
| 755 | "sg%d desc: 0x%llx, addr: 0x%llx len: %d\n", | ||
| 756 | i, (u64)desc->txd.phys, | ||
| 757 | (unsigned long long)sg_dma_address(sg), | ||
| 758 | sg_dma_len(sg)); | ||
| 759 | |||
| 760 | dev_dbg(dchan->device->dev, | ||
| 761 | "bd_ptr = %p did=%d raddr=0x%llx\n", | ||
| 762 | desc->hw_desc, desc->destid, desc->rio_addr); | ||
| 763 | |||
| 764 | err = tsi721_desc_fill_init(desc, sg, rtype, sys_size); | ||
| 765 | if (err) { | ||
| 766 | dev_err(dchan->device->dev, | ||
| 767 | "Failed to build desc: %d\n", err); | ||
| 768 | goto err_desc_put; | ||
| 769 | } | ||
| 770 | |||
| 771 | next_addr = sg_dma_address(sg); | ||
| 772 | |||
| 773 | if (!first) | ||
| 774 | first = desc; | ||
| 775 | else | ||
| 776 | list_add_tail(&desc->desc_node, &first->tx_list); | ||
| 777 | 797 | ||
| 778 | entry_done: | 798 | list_for_each_entry_safe(desc, _d, &bdma_chan->free_list, desc_node) { |
| 779 | if (sg_is_last(sg)) { | 799 | if (async_tx_test_ack(&desc->txd)) { |
| 780 | desc->interrupt = (flags & DMA_PREP_INTERRUPT) != 0; | 800 | list_del_init(&desc->desc_node); |
| 781 | tsi721_desc_fill_end(desc); | 801 | desc->destid = rext->destid; |
| 782 | dev_dbg(dchan->device->dev, "%s: desc final len: %d\n", | 802 | desc->rio_addr = rext->rio_addr; |
| 783 | __func__, desc->bcount); | 803 | desc->rio_addr_u = 0; |
| 784 | } else { | 804 | desc->rtype = rtype; |
| 785 | rio_addr += sg_dma_len(sg); | 805 | desc->sg_len = sg_len; |
| 786 | next_addr += sg_dma_len(sg); | 806 | desc->sg = sgl; |
| 807 | txd = &desc->txd; | ||
| 808 | txd->flags = flags; | ||
| 809 | break; | ||
| 787 | } | 810 | } |
| 788 | } | 811 | } |
| 789 | 812 | ||
| 790 | first->txd.cookie = -EBUSY; | 813 | spin_unlock_bh(&bdma_chan->lock); |
| 791 | desc->txd.flags = flags; | ||
| 792 | |||
| 793 | return &first->txd; | ||
| 794 | 814 | ||
| 795 | err_desc_put: | 815 | return txd; |
| 796 | tsi721_desc_put(bdma_chan, first); | ||
| 797 | return NULL; | ||
| 798 | } | 816 | } |
| 799 | 817 | ||
| 800 | static int tsi721_device_control(struct dma_chan *dchan, enum dma_ctrl_cmd cmd, | 818 | static int tsi721_device_control(struct dma_chan *dchan, enum dma_ctrl_cmd cmd, |
| @@ -802,23 +820,34 @@ static int tsi721_device_control(struct dma_chan *dchan, enum dma_ctrl_cmd cmd, | |||
| 802 | { | 820 | { |
| 803 | struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan); | 821 | struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan); |
| 804 | struct tsi721_tx_desc *desc, *_d; | 822 | struct tsi721_tx_desc *desc, *_d; |
| 823 | u32 dmac_int; | ||
| 805 | LIST_HEAD(list); | 824 | LIST_HEAD(list); |
| 806 | 825 | ||
| 807 | dev_dbg(dchan->device->dev, "%s: Entry\n", __func__); | 826 | dev_dbg(dchan->device->dev, "%s: Entry\n", __func__); |
| 808 | 827 | ||
| 809 | if (cmd != DMA_TERMINATE_ALL) | 828 | if (cmd != DMA_TERMINATE_ALL) |
| 810 | return -ENXIO; | 829 | return -ENOSYS; |
| 811 | 830 | ||
| 812 | spin_lock_bh(&bdma_chan->lock); | 831 | spin_lock_bh(&bdma_chan->lock); |
| 813 | 832 | ||
| 814 | /* make sure to stop the transfer */ | 833 | bdma_chan->active = false; |
| 815 | iowrite32(TSI721_DMAC_CTL_SUSP, bdma_chan->regs + TSI721_DMAC_CTL); | 834 | |
| 835 | if (!tsi721_dma_is_idle(bdma_chan)) { | ||
| 836 | /* make sure to stop the transfer */ | ||
| 837 | iowrite32(TSI721_DMAC_CTL_SUSP, | ||
| 838 | bdma_chan->regs + TSI721_DMAC_CTL); | ||
| 839 | |||
| 840 | /* Wait until DMA channel stops */ | ||
| 841 | do { | ||
| 842 | dmac_int = ioread32(bdma_chan->regs + TSI721_DMAC_INT); | ||
| 843 | } while ((dmac_int & TSI721_DMAC_INT_SUSP) == 0); | ||
| 844 | } | ||
| 816 | 845 | ||
| 817 | list_splice_init(&bdma_chan->active_list, &list); | 846 | list_splice_init(&bdma_chan->active_list, &list); |
| 818 | list_splice_init(&bdma_chan->queue, &list); | 847 | list_splice_init(&bdma_chan->queue, &list); |
| 819 | 848 | ||
| 820 | list_for_each_entry_safe(desc, _d, &list, desc_node) | 849 | list_for_each_entry_safe(desc, _d, &list, desc_node) |
| 821 | tsi721_dma_chain_complete(bdma_chan, desc); | 850 | tsi721_dma_tx_err(bdma_chan, desc); |
| 822 | 851 | ||
| 823 | spin_unlock_bh(&bdma_chan->lock); | 852 | spin_unlock_bh(&bdma_chan->lock); |
| 824 | 853 | ||
| @@ -828,22 +857,18 @@ static int tsi721_device_control(struct dma_chan *dchan, enum dma_ctrl_cmd cmd, | |||
| 828 | int tsi721_register_dma(struct tsi721_device *priv) | 857 | int tsi721_register_dma(struct tsi721_device *priv) |
| 829 | { | 858 | { |
| 830 | int i; | 859 | int i; |
| 831 | int nr_channels = TSI721_DMA_MAXCH; | 860 | int nr_channels = 0; |
| 832 | int err; | 861 | int err; |
| 833 | struct rio_mport *mport = priv->mport; | 862 | struct rio_mport *mport = priv->mport; |
| 834 | 863 | ||
| 835 | mport->dma.dev = &priv->pdev->dev; | ||
| 836 | mport->dma.chancnt = nr_channels; | ||
| 837 | |||
| 838 | INIT_LIST_HEAD(&mport->dma.channels); | 864 | INIT_LIST_HEAD(&mport->dma.channels); |
| 839 | 865 | ||
| 840 | for (i = 0; i < nr_channels; i++) { | 866 | for (i = 0; i < TSI721_DMA_MAXCH; i++) { |
| 841 | struct tsi721_bdma_chan *bdma_chan = &priv->bdma[i]; | 867 | struct tsi721_bdma_chan *bdma_chan = &priv->bdma[i]; |
| 842 | 868 | ||
| 843 | if (i == TSI721_DMACH_MAINT) | 869 | if (i == TSI721_DMACH_MAINT) |
| 844 | continue; | 870 | continue; |
| 845 | 871 | ||
| 846 | bdma_chan->bd_num = TSI721_BDMA_BD_RING_SZ; | ||
| 847 | bdma_chan->regs = priv->regs + TSI721_DMAC_BASE(i); | 872 | bdma_chan->regs = priv->regs + TSI721_DMAC_BASE(i); |
| 848 | 873 | ||
| 849 | bdma_chan->dchan.device = &mport->dma; | 874 | bdma_chan->dchan.device = &mport->dma; |
| @@ -862,12 +887,15 @@ int tsi721_register_dma(struct tsi721_device *priv) | |||
| 862 | (unsigned long)bdma_chan); | 887 | (unsigned long)bdma_chan); |
| 863 | list_add_tail(&bdma_chan->dchan.device_node, | 888 | list_add_tail(&bdma_chan->dchan.device_node, |
| 864 | &mport->dma.channels); | 889 | &mport->dma.channels); |
| 890 | nr_channels++; | ||
| 865 | } | 891 | } |
| 866 | 892 | ||
| 893 | mport->dma.chancnt = nr_channels; | ||
| 867 | dma_cap_zero(mport->dma.cap_mask); | 894 | dma_cap_zero(mport->dma.cap_mask); |
| 868 | dma_cap_set(DMA_PRIVATE, mport->dma.cap_mask); | 895 | dma_cap_set(DMA_PRIVATE, mport->dma.cap_mask); |
| 869 | dma_cap_set(DMA_SLAVE, mport->dma.cap_mask); | 896 | dma_cap_set(DMA_SLAVE, mport->dma.cap_mask); |
| 870 | 897 | ||
| 898 | mport->dma.dev = &priv->pdev->dev; | ||
| 871 | mport->dma.device_alloc_chan_resources = tsi721_alloc_chan_resources; | 899 | mport->dma.device_alloc_chan_resources = tsi721_alloc_chan_resources; |
| 872 | mport->dma.device_free_chan_resources = tsi721_free_chan_resources; | 900 | mport->dma.device_free_chan_resources = tsi721_free_chan_resources; |
| 873 | mport->dma.device_tx_status = tsi721_tx_status; | 901 | mport->dma.device_tx_status = tsi721_tx_status; |
diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c index a54ba0494dd3..d7b87c64b7cd 100644 --- a/drivers/rapidio/rio.c +++ b/drivers/rapidio/rio.c | |||
| @@ -1509,30 +1509,39 @@ EXPORT_SYMBOL_GPL(rio_route_clr_table); | |||
| 1509 | 1509 | ||
| 1510 | static bool rio_chan_filter(struct dma_chan *chan, void *arg) | 1510 | static bool rio_chan_filter(struct dma_chan *chan, void *arg) |
| 1511 | { | 1511 | { |
| 1512 | struct rio_dev *rdev = arg; | 1512 | struct rio_mport *mport = arg; |
| 1513 | 1513 | ||
| 1514 | /* Check that DMA device belongs to the right MPORT */ | 1514 | /* Check that DMA device belongs to the right MPORT */ |
| 1515 | return (rdev->net->hport == | 1515 | return mport == container_of(chan->device, struct rio_mport, dma); |
| 1516 | container_of(chan->device, struct rio_mport, dma)); | ||
| 1517 | } | 1516 | } |
| 1518 | 1517 | ||
| 1519 | /** | 1518 | /** |
| 1520 | * rio_request_dma - request RapidIO capable DMA channel that supports | 1519 | * rio_request_mport_dma - request RapidIO capable DMA channel associated |
| 1521 | * specified target RapidIO device. | 1520 | * with specified local RapidIO mport device. |
| 1522 | * @rdev: RIO device control structure | 1521 | * @mport: RIO mport to perform DMA data transfers |
| 1523 | * | 1522 | * |
| 1524 | * Returns pointer to allocated DMA channel or NULL if failed. | 1523 | * Returns pointer to allocated DMA channel or NULL if failed. |
| 1525 | */ | 1524 | */ |
| 1526 | struct dma_chan *rio_request_dma(struct rio_dev *rdev) | 1525 | struct dma_chan *rio_request_mport_dma(struct rio_mport *mport) |
| 1527 | { | 1526 | { |
| 1528 | dma_cap_mask_t mask; | 1527 | dma_cap_mask_t mask; |
| 1529 | struct dma_chan *dchan; | ||
| 1530 | 1528 | ||
| 1531 | dma_cap_zero(mask); | 1529 | dma_cap_zero(mask); |
| 1532 | dma_cap_set(DMA_SLAVE, mask); | 1530 | dma_cap_set(DMA_SLAVE, mask); |
| 1533 | dchan = dma_request_channel(mask, rio_chan_filter, rdev); | 1531 | return dma_request_channel(mask, rio_chan_filter, mport); |
| 1532 | } | ||
| 1533 | EXPORT_SYMBOL_GPL(rio_request_mport_dma); | ||
| 1534 | 1534 | ||
| 1535 | return dchan; | 1535 | /** |
| 1536 | * rio_request_dma - request RapidIO capable DMA channel that supports | ||
| 1537 | * specified target RapidIO device. | ||
| 1538 | * @rdev: RIO device associated with DMA transfer | ||
| 1539 | * | ||
| 1540 | * Returns pointer to allocated DMA channel or NULL if failed. | ||
| 1541 | */ | ||
| 1542 | struct dma_chan *rio_request_dma(struct rio_dev *rdev) | ||
| 1543 | { | ||
| 1544 | return rio_request_mport_dma(rdev->net->hport); | ||
| 1536 | } | 1545 | } |
| 1537 | EXPORT_SYMBOL_GPL(rio_request_dma); | 1546 | EXPORT_SYMBOL_GPL(rio_request_dma); |
| 1538 | 1547 | ||
| @@ -1547,10 +1556,10 @@ void rio_release_dma(struct dma_chan *dchan) | |||
| 1547 | EXPORT_SYMBOL_GPL(rio_release_dma); | 1556 | EXPORT_SYMBOL_GPL(rio_release_dma); |
| 1548 | 1557 | ||
| 1549 | /** | 1558 | /** |
| 1550 | * rio_dma_prep_slave_sg - RapidIO specific wrapper | 1559 | * rio_dma_prep_xfer - RapidIO specific wrapper |
| 1551 | * for device_prep_slave_sg callback defined by DMAENGINE. | 1560 | * for device_prep_slave_sg callback defined by DMAENGINE. |
| 1552 | * @rdev: RIO device control structure | ||
| 1553 | * @dchan: DMA channel to configure | 1561 | * @dchan: DMA channel to configure |
| 1562 | * @destid: target RapidIO device destination ID | ||
| 1554 | * @data: RIO specific data descriptor | 1563 | * @data: RIO specific data descriptor |
| 1555 | * @direction: DMA data transfer direction (TO or FROM the device) | 1564 | * @direction: DMA data transfer direction (TO or FROM the device) |
| 1556 | * @flags: dmaengine defined flags | 1565 | * @flags: dmaengine defined flags |
| @@ -1560,11 +1569,10 @@ EXPORT_SYMBOL_GPL(rio_release_dma); | |||
| 1560 | * target RIO device. | 1569 | * target RIO device. |
| 1561 | * Returns pointer to DMA transaction descriptor or NULL if failed. | 1570 | * Returns pointer to DMA transaction descriptor or NULL if failed. |
| 1562 | */ | 1571 | */ |
| 1563 | struct dma_async_tx_descriptor *rio_dma_prep_slave_sg(struct rio_dev *rdev, | 1572 | struct dma_async_tx_descriptor *rio_dma_prep_xfer(struct dma_chan *dchan, |
| 1564 | struct dma_chan *dchan, struct rio_dma_data *data, | 1573 | u16 destid, struct rio_dma_data *data, |
| 1565 | enum dma_transfer_direction direction, unsigned long flags) | 1574 | enum dma_transfer_direction direction, unsigned long flags) |
| 1566 | { | 1575 | { |
| 1567 | struct dma_async_tx_descriptor *txd = NULL; | ||
| 1568 | struct rio_dma_ext rio_ext; | 1576 | struct rio_dma_ext rio_ext; |
| 1569 | 1577 | ||
| 1570 | if (dchan->device->device_prep_slave_sg == NULL) { | 1578 | if (dchan->device->device_prep_slave_sg == NULL) { |
| @@ -1572,15 +1580,35 @@ struct dma_async_tx_descriptor *rio_dma_prep_slave_sg(struct rio_dev *rdev, | |||
| 1572 | return NULL; | 1580 | return NULL; |
| 1573 | } | 1581 | } |
| 1574 | 1582 | ||
| 1575 | rio_ext.destid = rdev->destid; | 1583 | rio_ext.destid = destid; |
| 1576 | rio_ext.rio_addr_u = data->rio_addr_u; | 1584 | rio_ext.rio_addr_u = data->rio_addr_u; |
| 1577 | rio_ext.rio_addr = data->rio_addr; | 1585 | rio_ext.rio_addr = data->rio_addr; |
| 1578 | rio_ext.wr_type = data->wr_type; | 1586 | rio_ext.wr_type = data->wr_type; |
| 1579 | 1587 | ||
| 1580 | txd = dmaengine_prep_rio_sg(dchan, data->sg, data->sg_len, | 1588 | return dmaengine_prep_rio_sg(dchan, data->sg, data->sg_len, |
| 1581 | direction, flags, &rio_ext); | 1589 | direction, flags, &rio_ext); |
| 1590 | } | ||
| 1591 | EXPORT_SYMBOL_GPL(rio_dma_prep_xfer); | ||
| 1582 | 1592 | ||
| 1583 | return txd; | 1593 | /** |
| 1594 | * rio_dma_prep_slave_sg - RapidIO specific wrapper | ||
| 1595 | * for device_prep_slave_sg callback defined by DMAENGINE. | ||
| 1596 | * @rdev: RIO device control structure | ||
| 1597 | * @dchan: DMA channel to configure | ||
| 1598 | * @data: RIO specific data descriptor | ||
| 1599 | * @direction: DMA data transfer direction (TO or FROM the device) | ||
| 1600 | * @flags: dmaengine defined flags | ||
| 1601 | * | ||
| 1602 | * Initializes RapidIO capable DMA channel for the specified data transfer. | ||
| 1603 | * Uses DMA channel private extension to pass information related to remote | ||
| 1604 | * target RIO device. | ||
| 1605 | * Returns pointer to DMA transaction descriptor or NULL if failed. | ||
| 1606 | */ | ||
| 1607 | struct dma_async_tx_descriptor *rio_dma_prep_slave_sg(struct rio_dev *rdev, | ||
| 1608 | struct dma_chan *dchan, struct rio_dma_data *data, | ||
| 1609 | enum dma_transfer_direction direction, unsigned long flags) | ||
| 1610 | { | ||
| 1611 | return rio_dma_prep_xfer(dchan, rdev->destid, data, direction, flags); | ||
| 1584 | } | 1612 | } |
| 1585 | EXPORT_SYMBOL_GPL(rio_dma_prep_slave_sg); | 1613 | EXPORT_SYMBOL_GPL(rio_dma_prep_slave_sg); |
| 1586 | 1614 | ||
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 0754f5c7cb3b..a168e96142b9 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
| @@ -373,6 +373,14 @@ config RTC_DRV_PCF8563 | |||
| 373 | This driver can also be built as a module. If so, the module | 373 | This driver can also be built as a module. If so, the module |
| 374 | will be called rtc-pcf8563. | 374 | will be called rtc-pcf8563. |
| 375 | 375 | ||
| 376 | config RTC_DRV_PCF85063 | ||
| 377 | tristate "nxp PCF85063" | ||
| 378 | help | ||
| 379 | If you say yes here you get support for the PCF85063 RTC chip | ||
| 380 | |||
| 381 | This driver can also be built as a module. If so, the module | ||
| 382 | will be called rtc-pcf85063. | ||
| 383 | |||
| 376 | config RTC_DRV_PCF8583 | 384 | config RTC_DRV_PCF8583 |
| 377 | tristate "Philips PCF8583" | 385 | tristate "Philips PCF8583" |
| 378 | help | 386 | help |
| @@ -760,6 +768,15 @@ config RTC_DRV_DS1742 | |||
| 760 | This driver can also be built as a module. If so, the module | 768 | This driver can also be built as a module. If so, the module |
| 761 | will be called rtc-ds1742. | 769 | will be called rtc-ds1742. |
| 762 | 770 | ||
| 771 | config RTC_DRV_DS2404 | ||
| 772 | tristate "Maxim/Dallas DS2404" | ||
| 773 | help | ||
| 774 | If you say yes here you get support for the | ||
| 775 | Dallas DS2404 RTC chip. | ||
| 776 | |||
| 777 | This driver can also be built as a module. If so, the module | ||
| 778 | will be called rtc-ds2404. | ||
| 779 | |||
| 763 | config RTC_DRV_DA9052 | 780 | config RTC_DRV_DA9052 |
| 764 | tristate "Dialog DA9052/DA9053 RTC" | 781 | tristate "Dialog DA9052/DA9053 RTC" |
| 765 | depends on PMIC_DA9052 | 782 | depends on PMIC_DA9052 |
| @@ -789,7 +806,7 @@ config RTC_DRV_DA9063 | |||
| 789 | 806 | ||
| 790 | config RTC_DRV_EFI | 807 | config RTC_DRV_EFI |
| 791 | tristate "EFI RTC" | 808 | tristate "EFI RTC" |
| 792 | depends on IA64 | 809 | depends on EFI |
| 793 | help | 810 | help |
| 794 | If you say yes here you will get support for the EFI | 811 | If you say yes here you will get support for the EFI |
| 795 | Real Time Clock. | 812 | Real Time Clock. |
| @@ -873,15 +890,6 @@ config RTC_DRV_V3020 | |||
| 873 | This driver can also be built as a module. If so, the module | 890 | This driver can also be built as a module. If so, the module |
| 874 | will be called rtc-v3020. | 891 | will be called rtc-v3020. |
| 875 | 892 | ||
| 876 | config RTC_DRV_DS2404 | ||
| 877 | tristate "Dallas DS2404" | ||
| 878 | help | ||
| 879 | If you say yes here you get support for the | ||
| 880 | Dallas DS2404 RTC chip. | ||
| 881 | |||
| 882 | This driver can also be built as a module. If so, the module | ||
| 883 | will be called rtc-ds2404. | ||
| 884 | |||
| 885 | config RTC_DRV_WM831X | 893 | config RTC_DRV_WM831X |
| 886 | tristate "Wolfson Microelectronics WM831x RTC" | 894 | tristate "Wolfson Microelectronics WM831x RTC" |
| 887 | depends on MFD_WM831X | 895 | depends on MFD_WM831X |
| @@ -1349,6 +1357,7 @@ config RTC_DRV_SIRFSOC | |||
| 1349 | 1357 | ||
| 1350 | config RTC_DRV_MOXART | 1358 | config RTC_DRV_MOXART |
| 1351 | tristate "MOXA ART RTC" | 1359 | tristate "MOXA ART RTC" |
| 1360 | depends on ARCH_MOXART || COMPILE_TEST | ||
| 1352 | help | 1361 | help |
| 1353 | If you say yes here you get support for the MOXA ART | 1362 | If you say yes here you get support for the MOXA ART |
| 1354 | RTC module. | 1363 | RTC module. |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 70347d041d10..56f061c7c815 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
| @@ -10,6 +10,10 @@ obj-$(CONFIG_RTC_SYSTOHC) += systohc.o | |||
| 10 | obj-$(CONFIG_RTC_CLASS) += rtc-core.o | 10 | obj-$(CONFIG_RTC_CLASS) += rtc-core.o |
| 11 | rtc-core-y := class.o interface.o | 11 | rtc-core-y := class.o interface.o |
| 12 | 12 | ||
| 13 | ifdef CONFIG_RTC_DRV_EFI | ||
| 14 | rtc-core-y += rtc-efi-platform.o | ||
| 15 | endif | ||
| 16 | |||
| 13 | rtc-core-$(CONFIG_RTC_INTF_DEV) += rtc-dev.o | 17 | rtc-core-$(CONFIG_RTC_INTF_DEV) += rtc-dev.o |
| 14 | rtc-core-$(CONFIG_RTC_INTF_PROC) += rtc-proc.o | 18 | rtc-core-$(CONFIG_RTC_INTF_PROC) += rtc-proc.o |
| 15 | rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o | 19 | rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o |
| @@ -93,6 +97,7 @@ obj-$(CONFIG_RTC_DRV_PCAP) += rtc-pcap.o | |||
| 93 | obj-$(CONFIG_RTC_DRV_PCF2127) += rtc-pcf2127.o | 97 | obj-$(CONFIG_RTC_DRV_PCF2127) += rtc-pcf2127.o |
| 94 | obj-$(CONFIG_RTC_DRV_PCF8523) += rtc-pcf8523.o | 98 | obj-$(CONFIG_RTC_DRV_PCF8523) += rtc-pcf8523.o |
| 95 | obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o | 99 | obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o |
| 100 | obj-$(CONFIG_RTC_DRV_PCF85063) += rtc-pcf85063.o | ||
| 96 | obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o | 101 | obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o |
| 97 | obj-$(CONFIG_RTC_DRV_PCF2123) += rtc-pcf2123.o | 102 | obj-$(CONFIG_RTC_DRV_PCF2123) += rtc-pcf2123.o |
| 98 | obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o | 103 | obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o |
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 589351ef75d0..38e26be705be 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c | |||
| @@ -53,6 +53,7 @@ static int rtc_suspend(struct device *dev) | |||
| 53 | struct rtc_device *rtc = to_rtc_device(dev); | 53 | struct rtc_device *rtc = to_rtc_device(dev); |
| 54 | struct rtc_time tm; | 54 | struct rtc_time tm; |
| 55 | struct timespec delta, delta_delta; | 55 | struct timespec delta, delta_delta; |
| 56 | int err; | ||
| 56 | 57 | ||
| 57 | if (has_persistent_clock()) | 58 | if (has_persistent_clock()) |
| 58 | return 0; | 59 | return 0; |
| @@ -61,7 +62,12 @@ static int rtc_suspend(struct device *dev) | |||
| 61 | return 0; | 62 | return 0; |
| 62 | 63 | ||
| 63 | /* snapshot the current RTC and system time at suspend*/ | 64 | /* snapshot the current RTC and system time at suspend*/ |
| 64 | rtc_read_time(rtc, &tm); | 65 | err = rtc_read_time(rtc, &tm); |
| 66 | if (err < 0) { | ||
| 67 | pr_debug("%s: fail to read rtc time\n", dev_name(&rtc->dev)); | ||
| 68 | return 0; | ||
| 69 | } | ||
| 70 | |||
| 65 | getnstimeofday(&old_system); | 71 | getnstimeofday(&old_system); |
| 66 | rtc_tm_to_time(&tm, &old_rtc.tv_sec); | 72 | rtc_tm_to_time(&tm, &old_rtc.tv_sec); |
| 67 | 73 | ||
| @@ -94,6 +100,7 @@ static int rtc_resume(struct device *dev) | |||
| 94 | struct rtc_time tm; | 100 | struct rtc_time tm; |
| 95 | struct timespec new_system, new_rtc; | 101 | struct timespec new_system, new_rtc; |
| 96 | struct timespec sleep_time; | 102 | struct timespec sleep_time; |
| 103 | int err; | ||
| 97 | 104 | ||
| 98 | if (has_persistent_clock()) | 105 | if (has_persistent_clock()) |
| 99 | return 0; | 106 | return 0; |
| @@ -104,7 +111,12 @@ static int rtc_resume(struct device *dev) | |||
| 104 | 111 | ||
| 105 | /* snapshot the current rtc and system time at resume */ | 112 | /* snapshot the current rtc and system time at resume */ |
| 106 | getnstimeofday(&new_system); | 113 | getnstimeofday(&new_system); |
| 107 | rtc_read_time(rtc, &tm); | 114 | err = rtc_read_time(rtc, &tm); |
| 115 | if (err < 0) { | ||
| 116 | pr_debug("%s: fail to read rtc time\n", dev_name(&rtc->dev)); | ||
| 117 | return 0; | ||
| 118 | } | ||
| 119 | |||
| 108 | if (rtc_valid_tm(&tm) != 0) { | 120 | if (rtc_valid_tm(&tm) != 0) { |
| 109 | pr_debug("%s: bogus resume time\n", dev_name(&rtc->dev)); | 121 | pr_debug("%s: bogus resume time\n", dev_name(&rtc->dev)); |
| 110 | return 0; | 122 | return 0; |
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 5813fa52c3d4..5b2717f5dafa 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c | |||
| @@ -348,6 +348,8 @@ static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | |||
| 348 | 348 | ||
| 349 | /* Make sure we're not setting alarms in the past */ | 349 | /* Make sure we're not setting alarms in the past */ |
| 350 | err = __rtc_read_time(rtc, &tm); | 350 | err = __rtc_read_time(rtc, &tm); |
| 351 | if (err) | ||
| 352 | return err; | ||
| 351 | rtc_tm_to_time(&tm, &now); | 353 | rtc_tm_to_time(&tm, &now); |
| 352 | if (scheduled <= now) | 354 | if (scheduled <= now) |
| 353 | return -ETIME; | 355 | return -ETIME; |
diff --git a/drivers/rtc/rtc-ds1343.c b/drivers/rtc/rtc-ds1343.c index c3719189dd96..ae9f997223b1 100644 --- a/drivers/rtc/rtc-ds1343.c +++ b/drivers/rtc/rtc-ds1343.c | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | * Real Time Clock | 4 | * Real Time Clock |
| 5 | * | 5 | * |
| 6 | * Author : Raghavendra Chandra Ganiga <ravi23ganiga@gmail.com> | 6 | * Author : Raghavendra Chandra Ganiga <ravi23ganiga@gmail.com> |
| 7 | * Ankur Srivastava <sankurece@gmail.com> : DS1343 Nvram Support | ||
| 7 | * | 8 | * |
| 8 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
| 9 | * it under the terms of the GNU General Public License version 2 as | 10 | * it under the terms of the GNU General Public License version 2 as |
| @@ -45,6 +46,9 @@ | |||
| 45 | #define DS1343_CONTROL_REG 0x0F | 46 | #define DS1343_CONTROL_REG 0x0F |
| 46 | #define DS1343_STATUS_REG 0x10 | 47 | #define DS1343_STATUS_REG 0x10 |
| 47 | #define DS1343_TRICKLE_REG 0x11 | 48 | #define DS1343_TRICKLE_REG 0x11 |
| 49 | #define DS1343_NVRAM 0x20 | ||
| 50 | |||
| 51 | #define DS1343_NVRAM_LEN 96 | ||
| 48 | 52 | ||
| 49 | /* DS1343 Control Registers bits */ | 53 | /* DS1343 Control Registers bits */ |
| 50 | #define DS1343_EOSC 0x80 | 54 | #define DS1343_EOSC 0x80 |
| @@ -149,6 +153,64 @@ static ssize_t ds1343_store_glitchfilter(struct device *dev, | |||
| 149 | static DEVICE_ATTR(glitch_filter, S_IRUGO | S_IWUSR, ds1343_show_glitchfilter, | 153 | static DEVICE_ATTR(glitch_filter, S_IRUGO | S_IWUSR, ds1343_show_glitchfilter, |
| 150 | ds1343_store_glitchfilter); | 154 | ds1343_store_glitchfilter); |
| 151 | 155 | ||
| 156 | static ssize_t ds1343_nvram_write(struct file *filp, struct kobject *kobj, | ||
| 157 | struct bin_attribute *attr, | ||
| 158 | char *buf, loff_t off, size_t count) | ||
| 159 | { | ||
| 160 | int ret; | ||
| 161 | unsigned char address; | ||
| 162 | struct device *dev = kobj_to_dev(kobj); | ||
| 163 | struct ds1343_priv *priv = dev_get_drvdata(dev); | ||
| 164 | |||
| 165 | if (unlikely(!count)) | ||
| 166 | return count; | ||
| 167 | |||
| 168 | if ((count + off) > DS1343_NVRAM_LEN) | ||
| 169 | count = DS1343_NVRAM_LEN - off; | ||
| 170 | |||
| 171 | address = DS1343_NVRAM + off; | ||
| 172 | |||
| 173 | ret = regmap_bulk_write(priv->map, address, buf, count); | ||
| 174 | if (ret < 0) | ||
| 175 | dev_err(&priv->spi->dev, "Error in nvram write %d", ret); | ||
| 176 | |||
| 177 | return (ret < 0) ? ret : count; | ||
| 178 | } | ||
| 179 | |||
| 180 | |||
| 181 | static ssize_t ds1343_nvram_read(struct file *filp, struct kobject *kobj, | ||
| 182 | struct bin_attribute *attr, | ||
| 183 | char *buf, loff_t off, size_t count) | ||
| 184 | { | ||
| 185 | int ret; | ||
| 186 | unsigned char address; | ||
| 187 | struct device *dev = kobj_to_dev(kobj); | ||
| 188 | struct ds1343_priv *priv = dev_get_drvdata(dev); | ||
| 189 | |||
| 190 | if (unlikely(!count)) | ||
| 191 | return count; | ||
| 192 | |||
| 193 | if ((count + off) > DS1343_NVRAM_LEN) | ||
| 194 | count = DS1343_NVRAM_LEN - off; | ||
| 195 | |||
| 196 | address = DS1343_NVRAM + off; | ||
| 197 | |||
| 198 | ret = regmap_bulk_read(priv->map, address, buf, count); | ||
| 199 | if (ret < 0) | ||
| 200 | dev_err(&priv->spi->dev, "Error in nvram read %d\n", ret); | ||
| 201 | |||
| 202 | return (ret < 0) ? ret : count; | ||
| 203 | } | ||
| 204 | |||
| 205 | |||
| 206 | static struct bin_attribute nvram_attr = { | ||
| 207 | .attr.name = "nvram", | ||
| 208 | .attr.mode = S_IRUGO | S_IWUSR, | ||
| 209 | .read = ds1343_nvram_read, | ||
| 210 | .write = ds1343_nvram_write, | ||
| 211 | .size = DS1343_NVRAM_LEN, | ||
| 212 | }; | ||
| 213 | |||
| 152 | static ssize_t ds1343_show_alarmstatus(struct device *dev, | 214 | static ssize_t ds1343_show_alarmstatus(struct device *dev, |
| 153 | struct device_attribute *attr, char *buf) | 215 | struct device_attribute *attr, char *buf) |
| 154 | { | 216 | { |
| @@ -274,12 +336,16 @@ static int ds1343_sysfs_register(struct device *dev) | |||
| 274 | if (err) | 336 | if (err) |
| 275 | goto error1; | 337 | goto error1; |
| 276 | 338 | ||
| 339 | err = device_create_bin_file(dev, &nvram_attr); | ||
| 340 | if (err) | ||
| 341 | goto error2; | ||
| 342 | |||
| 277 | if (priv->irq <= 0) | 343 | if (priv->irq <= 0) |
| 278 | return err; | 344 | return err; |
| 279 | 345 | ||
| 280 | err = device_create_file(dev, &dev_attr_alarm_mode); | 346 | err = device_create_file(dev, &dev_attr_alarm_mode); |
| 281 | if (err) | 347 | if (err) |
| 282 | goto error2; | 348 | goto error3; |
| 283 | 349 | ||
| 284 | err = device_create_file(dev, &dev_attr_alarm_status); | 350 | err = device_create_file(dev, &dev_attr_alarm_status); |
| 285 | if (!err) | 351 | if (!err) |
| @@ -287,6 +353,9 @@ static int ds1343_sysfs_register(struct device *dev) | |||
| 287 | 353 | ||
| 288 | device_remove_file(dev, &dev_attr_alarm_mode); | 354 | device_remove_file(dev, &dev_attr_alarm_mode); |
| 289 | 355 | ||
| 356 | error3: | ||
| 357 | device_remove_bin_file(dev, &nvram_attr); | ||
| 358 | |||
| 290 | error2: | 359 | error2: |
| 291 | device_remove_file(dev, &dev_attr_trickle_charger); | 360 | device_remove_file(dev, &dev_attr_trickle_charger); |
| 292 | 361 | ||
| @@ -302,6 +371,7 @@ static void ds1343_sysfs_unregister(struct device *dev) | |||
| 302 | 371 | ||
| 303 | device_remove_file(dev, &dev_attr_glitch_filter); | 372 | device_remove_file(dev, &dev_attr_glitch_filter); |
| 304 | device_remove_file(dev, &dev_attr_trickle_charger); | 373 | device_remove_file(dev, &dev_attr_trickle_charger); |
| 374 | device_remove_bin_file(dev, &nvram_attr); | ||
| 305 | 375 | ||
| 306 | if (priv->irq <= 0) | 376 | if (priv->irq <= 0) |
| 307 | return; | 377 | return; |
| @@ -684,6 +754,7 @@ static struct spi_driver ds1343_driver = { | |||
| 684 | module_spi_driver(ds1343_driver); | 754 | module_spi_driver(ds1343_driver); |
| 685 | 755 | ||
| 686 | MODULE_DESCRIPTION("DS1343 RTC SPI Driver"); | 756 | MODULE_DESCRIPTION("DS1343 RTC SPI Driver"); |
| 687 | MODULE_AUTHOR("Raghavendra Chandra Ganiga <ravi23ganiga@gmail.com>"); | 757 | MODULE_AUTHOR("Raghavendra Chandra Ganiga <ravi23ganiga@gmail.com>," |
| 758 | "Ankur Srivastava <sankurece@gmail.com>"); | ||
| 688 | MODULE_LICENSE("GPL v2"); | 759 | MODULE_LICENSE("GPL v2"); |
| 689 | MODULE_VERSION(DS1343_DRV_VERSION); | 760 | MODULE_VERSION(DS1343_DRV_VERSION); |
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c index c6b2191a4128..9822715db8ba 100644 --- a/drivers/rtc/rtc-ds1742.c +++ b/drivers/rtc/rtc-ds1742.c | |||
| @@ -231,7 +231,7 @@ static struct platform_driver ds1742_rtc_driver = { | |||
| 231 | .driver = { | 231 | .driver = { |
| 232 | .name = "rtc-ds1742", | 232 | .name = "rtc-ds1742", |
| 233 | .owner = THIS_MODULE, | 233 | .owner = THIS_MODULE, |
| 234 | .of_match_table = ds1742_rtc_of_match, | 234 | .of_match_table = of_match_ptr(ds1742_rtc_of_match), |
| 235 | }, | 235 | }, |
| 236 | }; | 236 | }; |
| 237 | 237 | ||
diff --git a/drivers/rtc/rtc-efi-platform.c b/drivers/rtc/rtc-efi-platform.c new file mode 100644 index 000000000000..b40fbe332af4 --- /dev/null +++ b/drivers/rtc/rtc-efi-platform.c | |||
| @@ -0,0 +1,31 @@ | |||
| 1 | /* | ||
| 2 | * Moved from arch/ia64/kernel/time.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 1998-2003 Hewlett-Packard Co | ||
| 5 | * Stephane Eranian <eranian@hpl.hp.com> | ||
| 6 | * David Mosberger <davidm@hpl.hp.com> | ||
| 7 | * Copyright (C) 1999 Don Dugger <don.dugger@intel.com> | ||
| 8 | * Copyright (C) 1999-2000 VA Linux Systems | ||
| 9 | * Copyright (C) 1999-2000 Walt Drummond <drummond@valinux.com> | ||
| 10 | */ | ||
| 11 | #include <linux/init.h> | ||
| 12 | #include <linux/kernel.h> | ||
| 13 | #include <linux/module.h> | ||
| 14 | #include <linux/efi.h> | ||
| 15 | #include <linux/platform_device.h> | ||
| 16 | |||
| 17 | static struct platform_device rtc_efi_dev = { | ||
| 18 | .name = "rtc-efi", | ||
| 19 | .id = -1, | ||
| 20 | }; | ||
| 21 | |||
| 22 | static int __init rtc_init(void) | ||
| 23 | { | ||
| 24 | if (efi_enabled(EFI_RUNTIME_SERVICES)) | ||
| 25 | if (platform_device_register(&rtc_efi_dev) < 0) | ||
| 26 | pr_err("unable to register rtc device...\n"); | ||
| 27 | |||
| 28 | /* not necessarily an error */ | ||
| 29 | return 0; | ||
| 30 | } | ||
| 31 | module_init(rtc_init); | ||
diff --git a/drivers/rtc/rtc-efi.c b/drivers/rtc/rtc-efi.c index c4c38431012e..8225b89de810 100644 --- a/drivers/rtc/rtc-efi.c +++ b/drivers/rtc/rtc-efi.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | 17 | ||
| 18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
| 19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
| 20 | #include <linux/stringify.h> | ||
| 20 | #include <linux/time.h> | 21 | #include <linux/time.h> |
| 21 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
| 22 | #include <linux/rtc.h> | 23 | #include <linux/rtc.h> |
| @@ -48,8 +49,8 @@ compute_wday(efi_time_t *eft) | |||
| 48 | int y; | 49 | int y; |
| 49 | int ndays = 0; | 50 | int ndays = 0; |
| 50 | 51 | ||
| 51 | if (eft->year < 1998) { | 52 | if (eft->year < EFI_RTC_EPOCH) { |
| 52 | pr_err("EFI year < 1998, invalid date\n"); | 53 | pr_err("EFI year < " __stringify(EFI_RTC_EPOCH) ", invalid date\n"); |
| 53 | return -1; | 54 | return -1; |
| 54 | } | 55 | } |
| 55 | 56 | ||
| @@ -78,19 +79,36 @@ convert_to_efi_time(struct rtc_time *wtime, efi_time_t *eft) | |||
| 78 | eft->timezone = EFI_UNSPECIFIED_TIMEZONE; | 79 | eft->timezone = EFI_UNSPECIFIED_TIMEZONE; |
| 79 | } | 80 | } |
| 80 | 81 | ||
| 81 | static void | 82 | static bool |
| 82 | convert_from_efi_time(efi_time_t *eft, struct rtc_time *wtime) | 83 | convert_from_efi_time(efi_time_t *eft, struct rtc_time *wtime) |
| 83 | { | 84 | { |
| 84 | memset(wtime, 0, sizeof(*wtime)); | 85 | memset(wtime, 0, sizeof(*wtime)); |
| 86 | |||
| 87 | if (eft->second >= 60) | ||
| 88 | return false; | ||
| 85 | wtime->tm_sec = eft->second; | 89 | wtime->tm_sec = eft->second; |
| 90 | |||
| 91 | if (eft->minute >= 60) | ||
| 92 | return false; | ||
| 86 | wtime->tm_min = eft->minute; | 93 | wtime->tm_min = eft->minute; |
| 94 | |||
| 95 | if (eft->hour >= 24) | ||
| 96 | return false; | ||
| 87 | wtime->tm_hour = eft->hour; | 97 | wtime->tm_hour = eft->hour; |
| 98 | |||
| 99 | if (!eft->day || eft->day > 31) | ||
| 100 | return false; | ||
| 88 | wtime->tm_mday = eft->day; | 101 | wtime->tm_mday = eft->day; |
| 102 | |||
| 103 | if (!eft->month || eft->month > 12) | ||
| 104 | return false; | ||
| 89 | wtime->tm_mon = eft->month - 1; | 105 | wtime->tm_mon = eft->month - 1; |
| 90 | wtime->tm_year = eft->year - 1900; | 106 | wtime->tm_year = eft->year - 1900; |
| 91 | 107 | ||
| 92 | /* day of the week [0-6], Sunday=0 */ | 108 | /* day of the week [0-6], Sunday=0 */ |
| 93 | wtime->tm_wday = compute_wday(eft); | 109 | wtime->tm_wday = compute_wday(eft); |
| 110 | if (wtime->tm_wday < 0) | ||
| 111 | return false; | ||
| 94 | 112 | ||
| 95 | /* day in the year [1-365]*/ | 113 | /* day in the year [1-365]*/ |
| 96 | wtime->tm_yday = compute_yday(eft); | 114 | wtime->tm_yday = compute_yday(eft); |
| @@ -106,6 +124,8 @@ convert_from_efi_time(efi_time_t *eft, struct rtc_time *wtime) | |||
| 106 | default: | 124 | default: |
| 107 | wtime->tm_isdst = -1; | 125 | wtime->tm_isdst = -1; |
| 108 | } | 126 | } |
| 127 | |||
| 128 | return true; | ||
| 109 | } | 129 | } |
| 110 | 130 | ||
| 111 | static int efi_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) | 131 | static int efi_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) |
| @@ -122,7 +142,8 @@ static int efi_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) | |||
| 122 | if (status != EFI_SUCCESS) | 142 | if (status != EFI_SUCCESS) |
| 123 | return -EINVAL; | 143 | return -EINVAL; |
| 124 | 144 | ||
| 125 | convert_from_efi_time(&eft, &wkalrm->time); | 145 | if (!convert_from_efi_time(&eft, &wkalrm->time)) |
| 146 | return -EIO; | ||
| 126 | 147 | ||
| 127 | return rtc_valid_tm(&wkalrm->time); | 148 | return rtc_valid_tm(&wkalrm->time); |
| 128 | } | 149 | } |
| @@ -163,7 +184,8 @@ static int efi_read_time(struct device *dev, struct rtc_time *tm) | |||
| 163 | return -EINVAL; | 184 | return -EINVAL; |
| 164 | } | 185 | } |
| 165 | 186 | ||
| 166 | convert_from_efi_time(&eft, tm); | 187 | if (!convert_from_efi_time(&eft, tm)) |
| 188 | return -EIO; | ||
| 167 | 189 | ||
| 168 | return rtc_valid_tm(tm); | 190 | return rtc_valid_tm(tm); |
| 169 | } | 191 | } |
diff --git a/drivers/rtc/rtc-isl12022.c b/drivers/rtc/rtc-isl12022.c index 03b891129428..aa55f081c505 100644 --- a/drivers/rtc/rtc-isl12022.c +++ b/drivers/rtc/rtc-isl12022.c | |||
| @@ -17,6 +17,8 @@ | |||
| 17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
| 18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
| 19 | #include <linux/err.h> | 19 | #include <linux/err.h> |
| 20 | #include <linux/of.h> | ||
| 21 | #include <linux/of_device.h> | ||
| 20 | 22 | ||
| 21 | #define DRV_VERSION "0.1" | 23 | #define DRV_VERSION "0.1" |
| 22 | 24 | ||
| @@ -271,6 +273,13 @@ static int isl12022_probe(struct i2c_client *client, | |||
| 271 | return PTR_ERR_OR_ZERO(isl12022->rtc); | 273 | return PTR_ERR_OR_ZERO(isl12022->rtc); |
| 272 | } | 274 | } |
| 273 | 275 | ||
| 276 | #ifdef CONFIG_OF | ||
| 277 | static struct of_device_id isl12022_dt_match[] = { | ||
| 278 | { .compatible = "isl,isl12022" }, | ||
| 279 | { }, | ||
| 280 | }; | ||
| 281 | #endif | ||
| 282 | |||
| 274 | static const struct i2c_device_id isl12022_id[] = { | 283 | static const struct i2c_device_id isl12022_id[] = { |
| 275 | { "isl12022", 0 }, | 284 | { "isl12022", 0 }, |
| 276 | { } | 285 | { } |
| @@ -280,6 +289,9 @@ MODULE_DEVICE_TABLE(i2c, isl12022_id); | |||
| 280 | static struct i2c_driver isl12022_driver = { | 289 | static struct i2c_driver isl12022_driver = { |
| 281 | .driver = { | 290 | .driver = { |
| 282 | .name = "rtc-isl12022", | 291 | .name = "rtc-isl12022", |
| 292 | #ifdef CONFIG_OF | ||
| 293 | .of_match_table = of_match_ptr(isl12022_dt_match), | ||
| 294 | #endif | ||
| 283 | }, | 295 | }, |
| 284 | .probe = isl12022_probe, | 296 | .probe = isl12022_probe, |
| 285 | .id_table = isl12022_id, | 297 | .id_table = isl12022_id, |
diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c new file mode 100644 index 000000000000..6a12bf62c504 --- /dev/null +++ b/drivers/rtc/rtc-pcf85063.c | |||
| @@ -0,0 +1,204 @@ | |||
| 1 | /* | ||
| 2 | * An I2C driver for the PCF85063 RTC | ||
| 3 | * Copyright 2014 Rose Technology | ||
| 4 | * | ||
| 5 | * Author: Søren Andersen <san@rosetechnology.dk> | ||
| 6 | * Maintainers: http://www.nslu2-linux.org/ | ||
| 7 | * | ||
| 8 | * based on the other drivers in this same directory. | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License version 2 as | ||
| 12 | * published by the Free Software Foundation. | ||
| 13 | */ | ||
| 14 | #include <linux/i2c.h> | ||
| 15 | #include <linux/bcd.h> | ||
| 16 | #include <linux/rtc.h> | ||
| 17 | #include <linux/module.h> | ||
| 18 | |||
| 19 | #define DRV_VERSION "0.0.1" | ||
| 20 | |||
| 21 | #define PCF85063_REG_CTRL1 0x00 /* status */ | ||
| 22 | #define PCF85063_REG_CTRL2 0x01 | ||
| 23 | |||
| 24 | #define PCF85063_REG_SC 0x04 /* datetime */ | ||
| 25 | #define PCF85063_REG_MN 0x05 | ||
| 26 | #define PCF85063_REG_HR 0x06 | ||
| 27 | #define PCF85063_REG_DM 0x07 | ||
| 28 | #define PCF85063_REG_DW 0x08 | ||
| 29 | #define PCF85063_REG_MO 0x09 | ||
| 30 | #define PCF85063_REG_YR 0x0A | ||
| 31 | |||
| 32 | #define PCF85063_MO_C 0x80 /* century */ | ||
| 33 | |||
| 34 | static struct i2c_driver pcf85063_driver; | ||
| 35 | |||
| 36 | struct pcf85063 { | ||
| 37 | struct rtc_device *rtc; | ||
| 38 | int c_polarity; /* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */ | ||
| 39 | int voltage_low; /* indicates if a low_voltage was detected */ | ||
| 40 | }; | ||
| 41 | |||
| 42 | /* | ||
| 43 | * In the routines that deal directly with the pcf85063 hardware, we use | ||
| 44 | * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch. | ||
| 45 | */ | ||
| 46 | static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm) | ||
| 47 | { | ||
| 48 | struct pcf85063 *pcf85063 = i2c_get_clientdata(client); | ||
| 49 | unsigned char buf[13] = { PCF85063_REG_CTRL1 }; | ||
| 50 | struct i2c_msg msgs[] = { | ||
| 51 | {/* setup read ptr */ | ||
| 52 | .addr = client->addr, | ||
| 53 | .len = 1, | ||
| 54 | .buf = buf | ||
| 55 | }, | ||
| 56 | {/* read status + date */ | ||
| 57 | .addr = client->addr, | ||
| 58 | .flags = I2C_M_RD, | ||
| 59 | .len = 13, | ||
| 60 | .buf = buf | ||
| 61 | }, | ||
| 62 | }; | ||
| 63 | |||
| 64 | /* read registers */ | ||
| 65 | if ((i2c_transfer(client->adapter, msgs, 2)) != 2) { | ||
| 66 | dev_err(&client->dev, "%s: read error\n", __func__); | ||
| 67 | return -EIO; | ||
| 68 | } | ||
| 69 | |||
| 70 | tm->tm_sec = bcd2bin(buf[PCF85063_REG_SC] & 0x7F); | ||
| 71 | tm->tm_min = bcd2bin(buf[PCF85063_REG_MN] & 0x7F); | ||
| 72 | tm->tm_hour = bcd2bin(buf[PCF85063_REG_HR] & 0x3F); /* rtc hr 0-23 */ | ||
| 73 | tm->tm_mday = bcd2bin(buf[PCF85063_REG_DM] & 0x3F); | ||
| 74 | tm->tm_wday = buf[PCF85063_REG_DW] & 0x07; | ||
| 75 | tm->tm_mon = bcd2bin(buf[PCF85063_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */ | ||
| 76 | tm->tm_year = bcd2bin(buf[PCF85063_REG_YR]); | ||
| 77 | if (tm->tm_year < 70) | ||
| 78 | tm->tm_year += 100; /* assume we are in 1970...2069 */ | ||
| 79 | /* detect the polarity heuristically. see note above. */ | ||
| 80 | pcf85063->c_polarity = (buf[PCF85063_REG_MO] & PCF85063_MO_C) ? | ||
| 81 | (tm->tm_year >= 100) : (tm->tm_year < 100); | ||
| 82 | |||
| 83 | /* the clock can give out invalid datetime, but we cannot return | ||
| 84 | * -EINVAL otherwise hwclock will refuse to set the time on bootup. | ||
| 85 | */ | ||
| 86 | if (rtc_valid_tm(tm) < 0) | ||
| 87 | dev_err(&client->dev, "retrieved date/time is not valid.\n"); | ||
| 88 | |||
| 89 | return 0; | ||
| 90 | } | ||
| 91 | |||
| 92 | static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm) | ||
| 93 | { | ||
| 94 | int i = 0, err = 0; | ||
| 95 | unsigned char buf[11]; | ||
| 96 | |||
| 97 | /* Control & status */ | ||
| 98 | buf[PCF85063_REG_CTRL1] = 0; | ||
| 99 | buf[PCF85063_REG_CTRL2] = 5; | ||
| 100 | |||
| 101 | /* hours, minutes and seconds */ | ||
| 102 | buf[PCF85063_REG_SC] = bin2bcd(tm->tm_sec) & 0x7F; | ||
| 103 | |||
| 104 | buf[PCF85063_REG_MN] = bin2bcd(tm->tm_min); | ||
| 105 | buf[PCF85063_REG_HR] = bin2bcd(tm->tm_hour); | ||
| 106 | |||
| 107 | /* Day of month, 1 - 31 */ | ||
| 108 | buf[PCF85063_REG_DM] = bin2bcd(tm->tm_mday); | ||
| 109 | |||
| 110 | /* Day, 0 - 6 */ | ||
| 111 | buf[PCF85063_REG_DW] = tm->tm_wday & 0x07; | ||
| 112 | |||
| 113 | /* month, 1 - 12 */ | ||
| 114 | buf[PCF85063_REG_MO] = bin2bcd(tm->tm_mon + 1); | ||
| 115 | |||
| 116 | /* year and century */ | ||
| 117 | buf[PCF85063_REG_YR] = bin2bcd(tm->tm_year % 100); | ||
| 118 | |||
| 119 | /* write register's data */ | ||
| 120 | for (i = 0; i < sizeof(buf); i++) { | ||
| 121 | unsigned char data[2] = { i, buf[i] }; | ||
| 122 | |||
| 123 | err = i2c_master_send(client, data, sizeof(data)); | ||
| 124 | if (err != sizeof(data)) { | ||
| 125 | dev_err(&client->dev, "%s: err=%d addr=%02x, data=%02x\n", | ||
| 126 | __func__, err, data[0], data[1]); | ||
| 127 | return -EIO; | ||
| 128 | } | ||
| 129 | } | ||
| 130 | |||
| 131 | return 0; | ||
| 132 | } | ||
| 133 | |||
| 134 | static int pcf85063_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
| 135 | { | ||
| 136 | return pcf85063_get_datetime(to_i2c_client(dev), tm); | ||
| 137 | } | ||
| 138 | |||
| 139 | static int pcf85063_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
| 140 | { | ||
| 141 | return pcf85063_set_datetime(to_i2c_client(dev), tm); | ||
| 142 | } | ||
| 143 | |||
| 144 | static const struct rtc_class_ops pcf85063_rtc_ops = { | ||
| 145 | .read_time = pcf85063_rtc_read_time, | ||
| 146 | .set_time = pcf85063_rtc_set_time | ||
| 147 | }; | ||
| 148 | |||
| 149 | static int pcf85063_probe(struct i2c_client *client, | ||
| 150 | const struct i2c_device_id *id) | ||
| 151 | { | ||
| 152 | struct pcf85063 *pcf85063; | ||
| 153 | |||
| 154 | dev_dbg(&client->dev, "%s\n", __func__); | ||
| 155 | |||
| 156 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) | ||
| 157 | return -ENODEV; | ||
| 158 | |||
| 159 | pcf85063 = devm_kzalloc(&client->dev, sizeof(struct pcf85063), | ||
| 160 | GFP_KERNEL); | ||
| 161 | if (!pcf85063) | ||
| 162 | return -ENOMEM; | ||
| 163 | |||
| 164 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); | ||
| 165 | |||
| 166 | i2c_set_clientdata(client, pcf85063); | ||
| 167 | |||
| 168 | pcf85063->rtc = devm_rtc_device_register(&client->dev, | ||
| 169 | pcf85063_driver.driver.name, | ||
| 170 | &pcf85063_rtc_ops, THIS_MODULE); | ||
| 171 | |||
| 172 | return PTR_ERR_OR_ZERO(pcf85063->rtc); | ||
| 173 | } | ||
| 174 | |||
| 175 | static const struct i2c_device_id pcf85063_id[] = { | ||
| 176 | { "pcf85063", 0 }, | ||
| 177 | { } | ||
| 178 | }; | ||
| 179 | MODULE_DEVICE_TABLE(i2c, pcf85063_id); | ||
| 180 | |||
| 181 | #ifdef CONFIG_OF | ||
| 182 | static const struct of_device_id pcf85063_of_match[] = { | ||
| 183 | { .compatible = "nxp,pcf85063" }, | ||
| 184 | {} | ||
| 185 | }; | ||
| 186 | MODULE_DEVICE_TABLE(of, pcf85063_of_match); | ||
| 187 | #endif | ||
| 188 | |||
| 189 | static struct i2c_driver pcf85063_driver = { | ||
| 190 | .driver = { | ||
| 191 | .name = "rtc-pcf85063", | ||
| 192 | .owner = THIS_MODULE, | ||
| 193 | .of_match_table = of_match_ptr(pcf85063_of_match), | ||
| 194 | }, | ||
| 195 | .probe = pcf85063_probe, | ||
| 196 | .id_table = pcf85063_id, | ||
| 197 | }; | ||
| 198 | |||
| 199 | module_i2c_driver(pcf85063_driver); | ||
| 200 | |||
| 201 | MODULE_AUTHOR("Søren Andersen <san@rosetechnology.dk>"); | ||
| 202 | MODULE_DESCRIPTION("PCF85063 RTC driver"); | ||
| 203 | MODULE_LICENSE("GPL"); | ||
| 204 | MODULE_VERSION(DRV_VERSION); | ||
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index 63b558c48196..5a197d9dc7e7 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c | |||
| @@ -26,6 +26,8 @@ | |||
| 26 | 26 | ||
| 27 | #define PCF8563_REG_ST1 0x00 /* status */ | 27 | #define PCF8563_REG_ST1 0x00 /* status */ |
| 28 | #define PCF8563_REG_ST2 0x01 | 28 | #define PCF8563_REG_ST2 0x01 |
| 29 | #define PCF8563_BIT_AIE (1 << 1) | ||
| 30 | #define PCF8563_BIT_AF (1 << 3) | ||
| 29 | 31 | ||
| 30 | #define PCF8563_REG_SC 0x02 /* datetime */ | 32 | #define PCF8563_REG_SC 0x02 /* datetime */ |
| 31 | #define PCF8563_REG_MN 0x03 | 33 | #define PCF8563_REG_MN 0x03 |
| @@ -36,9 +38,6 @@ | |||
| 36 | #define PCF8563_REG_YR 0x08 | 38 | #define PCF8563_REG_YR 0x08 |
| 37 | 39 | ||
| 38 | #define PCF8563_REG_AMN 0x09 /* alarm */ | 40 | #define PCF8563_REG_AMN 0x09 /* alarm */ |
| 39 | #define PCF8563_REG_AHR 0x0A | ||
| 40 | #define PCF8563_REG_ADM 0x0B | ||
| 41 | #define PCF8563_REG_ADW 0x0C | ||
| 42 | 41 | ||
| 43 | #define PCF8563_REG_CLKO 0x0D /* clock out */ | 42 | #define PCF8563_REG_CLKO 0x0D /* clock out */ |
| 44 | #define PCF8563_REG_TMRC 0x0E /* timer control */ | 43 | #define PCF8563_REG_TMRC 0x0E /* timer control */ |
| @@ -67,37 +66,133 @@ struct pcf8563 { | |||
| 67 | */ | 66 | */ |
| 68 | int c_polarity; /* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */ | 67 | int c_polarity; /* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */ |
| 69 | int voltage_low; /* incicates if a low_voltage was detected */ | 68 | int voltage_low; /* incicates if a low_voltage was detected */ |
| 69 | |||
| 70 | struct i2c_client *client; | ||
| 70 | }; | 71 | }; |
| 71 | 72 | ||
| 72 | /* | 73 | static int pcf8563_read_block_data(struct i2c_client *client, unsigned char reg, |
| 73 | * In the routines that deal directly with the pcf8563 hardware, we use | 74 | unsigned char length, unsigned char *buf) |
| 74 | * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch. | ||
| 75 | */ | ||
| 76 | static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm) | ||
| 77 | { | 75 | { |
| 78 | struct pcf8563 *pcf8563 = i2c_get_clientdata(client); | ||
| 79 | unsigned char buf[13] = { PCF8563_REG_ST1 }; | ||
| 80 | |||
| 81 | struct i2c_msg msgs[] = { | 76 | struct i2c_msg msgs[] = { |
| 82 | {/* setup read ptr */ | 77 | {/* setup read ptr */ |
| 83 | .addr = client->addr, | 78 | .addr = client->addr, |
| 84 | .len = 1, | 79 | .len = 1, |
| 85 | .buf = buf | 80 | .buf = ®, |
| 86 | }, | 81 | }, |
| 87 | {/* read status + date */ | 82 | { |
| 88 | .addr = client->addr, | 83 | .addr = client->addr, |
| 89 | .flags = I2C_M_RD, | 84 | .flags = I2C_M_RD, |
| 90 | .len = 13, | 85 | .len = length, |
| 91 | .buf = buf | 86 | .buf = buf |
| 92 | }, | 87 | }, |
| 93 | }; | 88 | }; |
| 94 | 89 | ||
| 95 | /* read registers */ | ||
| 96 | if ((i2c_transfer(client->adapter, msgs, 2)) != 2) { | 90 | if ((i2c_transfer(client->adapter, msgs, 2)) != 2) { |
| 97 | dev_err(&client->dev, "%s: read error\n", __func__); | 91 | dev_err(&client->dev, "%s: read error\n", __func__); |
| 98 | return -EIO; | 92 | return -EIO; |
| 99 | } | 93 | } |
| 100 | 94 | ||
| 95 | return 0; | ||
| 96 | } | ||
| 97 | |||
| 98 | static int pcf8563_write_block_data(struct i2c_client *client, | ||
| 99 | unsigned char reg, unsigned char length, | ||
| 100 | unsigned char *buf) | ||
| 101 | { | ||
| 102 | int i, err; | ||
| 103 | |||
| 104 | for (i = 0; i < length; i++) { | ||
| 105 | unsigned char data[2] = { reg + i, buf[i] }; | ||
| 106 | |||
| 107 | err = i2c_master_send(client, data, sizeof(data)); | ||
| 108 | if (err != sizeof(data)) { | ||
| 109 | dev_err(&client->dev, | ||
| 110 | "%s: err=%d addr=%02x, data=%02x\n", | ||
| 111 | __func__, err, data[0], data[1]); | ||
| 112 | return -EIO; | ||
| 113 | } | ||
| 114 | } | ||
| 115 | |||
| 116 | return 0; | ||
| 117 | } | ||
| 118 | |||
| 119 | static int pcf8563_set_alarm_mode(struct i2c_client *client, bool on) | ||
| 120 | { | ||
| 121 | unsigned char buf[2]; | ||
| 122 | int err; | ||
| 123 | |||
| 124 | err = pcf8563_read_block_data(client, PCF8563_REG_ST2, 1, buf + 1); | ||
| 125 | if (err < 0) | ||
| 126 | return err; | ||
| 127 | |||
| 128 | if (on) | ||
| 129 | buf[1] |= PCF8563_BIT_AIE; | ||
| 130 | else | ||
| 131 | buf[1] &= ~PCF8563_BIT_AIE; | ||
| 132 | |||
| 133 | buf[1] &= ~PCF8563_BIT_AF; | ||
| 134 | buf[0] = PCF8563_REG_ST2; | ||
| 135 | |||
| 136 | err = pcf8563_write_block_data(client, PCF8563_REG_ST2, 1, buf + 1); | ||
| 137 | if (err < 0) { | ||
| 138 | dev_err(&client->dev, "%s: write error\n", __func__); | ||
| 139 | return -EIO; | ||
| 140 | } | ||
| 141 | |||
| 142 | return 0; | ||
| 143 | } | ||
| 144 | |||
| 145 | static int pcf8563_get_alarm_mode(struct i2c_client *client, unsigned char *en, | ||
| 146 | unsigned char *pen) | ||
| 147 | { | ||
| 148 | unsigned char buf; | ||
| 149 | int err; | ||
| 150 | |||
| 151 | err = pcf8563_read_block_data(client, PCF8563_REG_ST2, 1, &buf); | ||
| 152 | if (err) | ||
| 153 | return err; | ||
| 154 | |||
| 155 | if (en) | ||
| 156 | *en = !!(buf & PCF8563_BIT_AIE); | ||
| 157 | if (pen) | ||
| 158 | *pen = !!(buf & PCF8563_BIT_AF); | ||
| 159 | |||
| 160 | return 0; | ||
| 161 | } | ||
| 162 | |||
| 163 | static irqreturn_t pcf8563_irq(int irq, void *dev_id) | ||
| 164 | { | ||
| 165 | struct pcf8563 *pcf8563 = i2c_get_clientdata(dev_id); | ||
| 166 | int err; | ||
| 167 | char pending; | ||
| 168 | |||
| 169 | err = pcf8563_get_alarm_mode(pcf8563->client, NULL, &pending); | ||
| 170 | if (err < 0) | ||
| 171 | return err; | ||
| 172 | |||
| 173 | if (pending) { | ||
| 174 | rtc_update_irq(pcf8563->rtc, 1, RTC_IRQF | RTC_AF); | ||
| 175 | pcf8563_set_alarm_mode(pcf8563->client, 1); | ||
| 176 | return IRQ_HANDLED; | ||
| 177 | } | ||
| 178 | |||
| 179 | return IRQ_NONE; | ||
| 180 | } | ||
| 181 | |||
| 182 | /* | ||
| 183 | * In the routines that deal directly with the pcf8563 hardware, we use | ||
| 184 | * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch. | ||
| 185 | */ | ||
| 186 | static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm) | ||
| 187 | { | ||
| 188 | struct pcf8563 *pcf8563 = i2c_get_clientdata(client); | ||
| 189 | unsigned char buf[9]; | ||
| 190 | int err; | ||
| 191 | |||
| 192 | err = pcf8563_read_block_data(client, PCF8563_REG_ST1, 9, buf); | ||
| 193 | if (err) | ||
| 194 | return err; | ||
| 195 | |||
| 101 | if (buf[PCF8563_REG_SC] & PCF8563_SC_LV) { | 196 | if (buf[PCF8563_REG_SC] & PCF8563_SC_LV) { |
| 102 | pcf8563->voltage_low = 1; | 197 | pcf8563->voltage_low = 1; |
| 103 | dev_info(&client->dev, | 198 | dev_info(&client->dev, |
| @@ -144,7 +239,7 @@ static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
| 144 | static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm) | 239 | static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm) |
| 145 | { | 240 | { |
| 146 | struct pcf8563 *pcf8563 = i2c_get_clientdata(client); | 241 | struct pcf8563 *pcf8563 = i2c_get_clientdata(client); |
| 147 | int i, err; | 242 | int err; |
| 148 | unsigned char buf[9]; | 243 | unsigned char buf[9]; |
| 149 | 244 | ||
| 150 | dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, " | 245 | dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, " |
| @@ -170,19 +265,10 @@ static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
| 170 | 265 | ||
| 171 | buf[PCF8563_REG_DW] = tm->tm_wday & 0x07; | 266 | buf[PCF8563_REG_DW] = tm->tm_wday & 0x07; |
| 172 | 267 | ||
| 173 | /* write register's data */ | 268 | err = pcf8563_write_block_data(client, PCF8563_REG_SC, |
| 174 | for (i = 0; i < 7; i++) { | 269 | 9 - PCF8563_REG_SC, buf + PCF8563_REG_SC); |
| 175 | unsigned char data[2] = { PCF8563_REG_SC + i, | 270 | if (err) |
| 176 | buf[PCF8563_REG_SC + i] }; | 271 | return err; |
| 177 | |||
| 178 | err = i2c_master_send(client, data, sizeof(data)); | ||
| 179 | if (err != sizeof(data)) { | ||
| 180 | dev_err(&client->dev, | ||
| 181 | "%s: err=%d addr=%02x, data=%02x\n", | ||
| 182 | __func__, err, data[0], data[1]); | ||
| 183 | return -EIO; | ||
| 184 | } | ||
| 185 | } | ||
| 186 | 272 | ||
| 187 | return 0; | 273 | return 0; |
| 188 | } | 274 | } |
| @@ -235,16 +321,83 @@ static int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
| 235 | return pcf8563_set_datetime(to_i2c_client(dev), tm); | 321 | return pcf8563_set_datetime(to_i2c_client(dev), tm); |
| 236 | } | 322 | } |
| 237 | 323 | ||
| 324 | static int pcf8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm) | ||
| 325 | { | ||
| 326 | struct i2c_client *client = to_i2c_client(dev); | ||
| 327 | unsigned char buf[4]; | ||
| 328 | int err; | ||
| 329 | |||
| 330 | err = pcf8563_read_block_data(client, PCF8563_REG_AMN, 4, buf); | ||
| 331 | if (err) | ||
| 332 | return err; | ||
| 333 | |||
| 334 | dev_dbg(&client->dev, | ||
| 335 | "%s: raw data is min=%02x, hr=%02x, mday=%02x, wday=%02x\n", | ||
| 336 | __func__, buf[0], buf[1], buf[2], buf[3]); | ||
| 337 | |||
| 338 | tm->time.tm_min = bcd2bin(buf[0] & 0x7F); | ||
| 339 | tm->time.tm_hour = bcd2bin(buf[1] & 0x7F); | ||
| 340 | tm->time.tm_mday = bcd2bin(buf[2] & 0x1F); | ||
| 341 | tm->time.tm_wday = bcd2bin(buf[3] & 0x7); | ||
| 342 | tm->time.tm_mon = -1; | ||
| 343 | tm->time.tm_year = -1; | ||
| 344 | tm->time.tm_yday = -1; | ||
| 345 | tm->time.tm_isdst = -1; | ||
| 346 | |||
| 347 | err = pcf8563_get_alarm_mode(client, &tm->enabled, &tm->pending); | ||
| 348 | if (err < 0) | ||
| 349 | return err; | ||
| 350 | |||
| 351 | dev_dbg(&client->dev, "%s: tm is mins=%d, hours=%d, mday=%d, wday=%d," | ||
| 352 | " enabled=%d, pending=%d\n", __func__, tm->time.tm_min, | ||
| 353 | tm->time.tm_hour, tm->time.tm_mday, tm->time.tm_wday, | ||
| 354 | tm->enabled, tm->pending); | ||
| 355 | |||
| 356 | return 0; | ||
| 357 | } | ||
| 358 | |||
| 359 | static int pcf8563_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *tm) | ||
| 360 | { | ||
| 361 | struct i2c_client *client = to_i2c_client(dev); | ||
| 362 | unsigned char buf[4]; | ||
| 363 | int err; | ||
| 364 | |||
| 365 | dev_dbg(dev, "%s, min=%d hour=%d wday=%d mday=%d " | ||
| 366 | "enabled=%d pending=%d\n", __func__, | ||
| 367 | tm->time.tm_min, tm->time.tm_hour, tm->time.tm_wday, | ||
| 368 | tm->time.tm_mday, tm->enabled, tm->pending); | ||
| 369 | |||
| 370 | buf[0] = bin2bcd(tm->time.tm_min); | ||
| 371 | buf[1] = bin2bcd(tm->time.tm_hour); | ||
| 372 | buf[2] = bin2bcd(tm->time.tm_mday); | ||
| 373 | buf[3] = tm->time.tm_wday & 0x07; | ||
| 374 | |||
| 375 | err = pcf8563_write_block_data(client, PCF8563_REG_AMN, 4, buf); | ||
| 376 | if (err) | ||
| 377 | return err; | ||
| 378 | |||
| 379 | return pcf8563_set_alarm_mode(client, 1); | ||
| 380 | } | ||
| 381 | |||
| 382 | static int pcf8563_irq_enable(struct device *dev, unsigned int enabled) | ||
| 383 | { | ||
| 384 | return pcf8563_set_alarm_mode(to_i2c_client(dev), !!enabled); | ||
| 385 | } | ||
| 386 | |||
| 238 | static const struct rtc_class_ops pcf8563_rtc_ops = { | 387 | static const struct rtc_class_ops pcf8563_rtc_ops = { |
| 239 | .ioctl = pcf8563_rtc_ioctl, | 388 | .ioctl = pcf8563_rtc_ioctl, |
| 240 | .read_time = pcf8563_rtc_read_time, | 389 | .read_time = pcf8563_rtc_read_time, |
| 241 | .set_time = pcf8563_rtc_set_time, | 390 | .set_time = pcf8563_rtc_set_time, |
| 391 | .read_alarm = pcf8563_rtc_read_alarm, | ||
| 392 | .set_alarm = pcf8563_rtc_set_alarm, | ||
| 393 | .alarm_irq_enable = pcf8563_irq_enable, | ||
| 242 | }; | 394 | }; |
| 243 | 395 | ||
| 244 | static int pcf8563_probe(struct i2c_client *client, | 396 | static int pcf8563_probe(struct i2c_client *client, |
| 245 | const struct i2c_device_id *id) | 397 | const struct i2c_device_id *id) |
| 246 | { | 398 | { |
| 247 | struct pcf8563 *pcf8563; | 399 | struct pcf8563 *pcf8563; |
| 400 | int err; | ||
| 248 | 401 | ||
| 249 | dev_dbg(&client->dev, "%s\n", __func__); | 402 | dev_dbg(&client->dev, "%s\n", __func__); |
| 250 | 403 | ||
| @@ -259,12 +412,30 @@ static int pcf8563_probe(struct i2c_client *client, | |||
| 259 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); | 412 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); |
| 260 | 413 | ||
| 261 | i2c_set_clientdata(client, pcf8563); | 414 | i2c_set_clientdata(client, pcf8563); |
| 415 | pcf8563->client = client; | ||
| 416 | device_set_wakeup_capable(&client->dev, 1); | ||
| 262 | 417 | ||
| 263 | pcf8563->rtc = devm_rtc_device_register(&client->dev, | 418 | pcf8563->rtc = devm_rtc_device_register(&client->dev, |
| 264 | pcf8563_driver.driver.name, | 419 | pcf8563_driver.driver.name, |
| 265 | &pcf8563_rtc_ops, THIS_MODULE); | 420 | &pcf8563_rtc_ops, THIS_MODULE); |
| 266 | 421 | ||
| 267 | return PTR_ERR_OR_ZERO(pcf8563->rtc); | 422 | if (IS_ERR(pcf8563->rtc)) |
| 423 | return PTR_ERR(pcf8563->rtc); | ||
| 424 | |||
| 425 | if (client->irq > 0) { | ||
| 426 | err = devm_request_threaded_irq(&client->dev, client->irq, | ||
| 427 | NULL, pcf8563_irq, | ||
| 428 | IRQF_SHARED|IRQF_ONESHOT|IRQF_TRIGGER_FALLING, | ||
| 429 | pcf8563->rtc->name, client); | ||
| 430 | if (err) { | ||
| 431 | dev_err(&client->dev, "unable to request IRQ %d\n", | ||
| 432 | client->irq); | ||
| 433 | return err; | ||
| 434 | } | ||
| 435 | |||
| 436 | } | ||
| 437 | |||
| 438 | return 0; | ||
| 268 | } | 439 | } |
| 269 | 440 | ||
| 270 | static const struct i2c_device_id pcf8563_id[] = { | 441 | static const struct i2c_device_id pcf8563_id[] = { |
diff --git a/drivers/rtc/rtc-tps65910.c b/drivers/rtc/rtc-tps65910.c index 7af00208d637..2583349fbde5 100644 --- a/drivers/rtc/rtc-tps65910.c +++ b/drivers/rtc/rtc-tps65910.c | |||
| @@ -258,6 +258,8 @@ static int tps65910_rtc_probe(struct platform_device *pdev) | |||
| 258 | if (ret < 0) | 258 | if (ret < 0) |
| 259 | return ret; | 259 | return ret; |
| 260 | 260 | ||
| 261 | platform_set_drvdata(pdev, tps_rtc); | ||
| 262 | |||
| 261 | irq = platform_get_irq(pdev, 0); | 263 | irq = platform_get_irq(pdev, 0); |
| 262 | if (irq <= 0) { | 264 | if (irq <= 0) { |
| 263 | dev_warn(&pdev->dev, "Wake up is not possible as irq = %d\n", | 265 | dev_warn(&pdev->dev, "Wake up is not possible as irq = %d\n", |
| @@ -283,8 +285,6 @@ static int tps65910_rtc_probe(struct platform_device *pdev) | |||
| 283 | return ret; | 285 | return ret; |
| 284 | } | 286 | } |
| 285 | 287 | ||
| 286 | platform_set_drvdata(pdev, tps_rtc); | ||
| 287 | |||
| 288 | return 0; | 288 | return 0; |
| 289 | } | 289 | } |
| 290 | 290 | ||
diff --git a/drivers/scsi/3w-sas.c b/drivers/scsi/3w-sas.c index 4de346017e9f..6da6cec9a651 100644 --- a/drivers/scsi/3w-sas.c +++ b/drivers/scsi/3w-sas.c | |||
| @@ -683,14 +683,13 @@ static int twl_allocate_memory(TW_Device_Extension *tw_dev, int size, int which) | |||
| 683 | unsigned long *cpu_addr; | 683 | unsigned long *cpu_addr; |
| 684 | int retval = 1; | 684 | int retval = 1; |
| 685 | 685 | ||
| 686 | cpu_addr = pci_alloc_consistent(tw_dev->tw_pci_dev, size*TW_Q_LENGTH, &dma_handle); | 686 | cpu_addr = pci_zalloc_consistent(tw_dev->tw_pci_dev, size * TW_Q_LENGTH, |
| 687 | &dma_handle); | ||
| 687 | if (!cpu_addr) { | 688 | if (!cpu_addr) { |
| 688 | TW_PRINTK(tw_dev->host, TW_DRIVER, 0x5, "Memory allocation failed"); | 689 | TW_PRINTK(tw_dev->host, TW_DRIVER, 0x5, "Memory allocation failed"); |
| 689 | goto out; | 690 | goto out; |
| 690 | } | 691 | } |
| 691 | 692 | ||
| 692 | memset(cpu_addr, 0, size*TW_Q_LENGTH); | ||
| 693 | |||
| 694 | for (i = 0; i < TW_Q_LENGTH; i++) { | 693 | for (i = 0; i < TW_Q_LENGTH; i++) { |
| 695 | switch(which) { | 694 | switch(which) { |
| 696 | case 0: | 695 | case 0: |
diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c index 522570d297ca..7e33a61c1ba4 100644 --- a/drivers/scsi/a100u2w.c +++ b/drivers/scsi/a100u2w.c | |||
| @@ -1125,23 +1125,19 @@ static int inia100_probe_one(struct pci_dev *pdev, | |||
| 1125 | 1125 | ||
| 1126 | /* Get total memory needed for SCB */ | 1126 | /* Get total memory needed for SCB */ |
| 1127 | sz = ORC_MAXQUEUE * sizeof(struct orc_scb); | 1127 | sz = ORC_MAXQUEUE * sizeof(struct orc_scb); |
| 1128 | host->scb_virt = pci_alloc_consistent(pdev, sz, | 1128 | host->scb_virt = pci_zalloc_consistent(pdev, sz, &host->scb_phys); |
| 1129 | &host->scb_phys); | ||
| 1130 | if (!host->scb_virt) { | 1129 | if (!host->scb_virt) { |
| 1131 | printk("inia100: SCB memory allocation error\n"); | 1130 | printk("inia100: SCB memory allocation error\n"); |
| 1132 | goto out_host_put; | 1131 | goto out_host_put; |
| 1133 | } | 1132 | } |
| 1134 | memset(host->scb_virt, 0, sz); | ||
| 1135 | 1133 | ||
| 1136 | /* Get total memory needed for ESCB */ | 1134 | /* Get total memory needed for ESCB */ |
| 1137 | sz = ORC_MAXQUEUE * sizeof(struct orc_extended_scb); | 1135 | sz = ORC_MAXQUEUE * sizeof(struct orc_extended_scb); |
| 1138 | host->escb_virt = pci_alloc_consistent(pdev, sz, | 1136 | host->escb_virt = pci_zalloc_consistent(pdev, sz, &host->escb_phys); |
| 1139 | &host->escb_phys); | ||
| 1140 | if (!host->escb_virt) { | 1137 | if (!host->escb_virt) { |
| 1141 | printk("inia100: ESCB memory allocation error\n"); | 1138 | printk("inia100: ESCB memory allocation error\n"); |
| 1142 | goto out_free_scb_array; | 1139 | goto out_free_scb_array; |
| 1143 | } | 1140 | } |
| 1144 | memset(host->escb_virt, 0, sz); | ||
| 1145 | 1141 | ||
| 1146 | biosaddr = host->BIOScfg; | 1142 | biosaddr = host->BIOScfg; |
| 1147 | biosaddr = (biosaddr << 4); | 1143 | biosaddr = (biosaddr << 4); |
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 56467df3d6de..eb3e3e619155 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c | |||
| @@ -3538,10 +3538,9 @@ static int be_queue_alloc(struct beiscsi_hba *phba, struct be_queue_info *q, | |||
| 3538 | q->len = len; | 3538 | q->len = len; |
| 3539 | q->entry_size = entry_size; | 3539 | q->entry_size = entry_size; |
| 3540 | mem->size = len * entry_size; | 3540 | mem->size = len * entry_size; |
| 3541 | mem->va = pci_alloc_consistent(phba->pcidev, mem->size, &mem->dma); | 3541 | mem->va = pci_zalloc_consistent(phba->pcidev, mem->size, &mem->dma); |
| 3542 | if (!mem->va) | 3542 | if (!mem->va) |
| 3543 | return -ENOMEM; | 3543 | return -ENOMEM; |
| 3544 | memset(mem->va, 0, mem->size); | ||
| 3545 | return 0; | 3544 | return 0; |
| 3546 | } | 3545 | } |
| 3547 | 3546 | ||
| @@ -4320,9 +4319,9 @@ static int beiscsi_get_boot_info(struct beiscsi_hba *phba) | |||
| 4320 | "BM_%d : No boot session\n"); | 4319 | "BM_%d : No boot session\n"); |
| 4321 | return ret; | 4320 | return ret; |
| 4322 | } | 4321 | } |
| 4323 | nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev, | 4322 | nonemb_cmd.va = pci_zalloc_consistent(phba->ctrl.pdev, |
| 4324 | sizeof(*session_resp), | 4323 | sizeof(*session_resp), |
| 4325 | &nonemb_cmd.dma); | 4324 | &nonemb_cmd.dma); |
| 4326 | if (nonemb_cmd.va == NULL) { | 4325 | if (nonemb_cmd.va == NULL) { |
| 4327 | beiscsi_log(phba, KERN_ERR, | 4326 | beiscsi_log(phba, KERN_ERR, |
| 4328 | BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, | 4327 | BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, |
| @@ -4332,7 +4331,6 @@ static int beiscsi_get_boot_info(struct beiscsi_hba *phba) | |||
| 4332 | return -ENOMEM; | 4331 | return -ENOMEM; |
| 4333 | } | 4332 | } |
| 4334 | 4333 | ||
| 4335 | memset(nonemb_cmd.va, 0, sizeof(*session_resp)); | ||
| 4336 | tag = mgmt_get_session_info(phba, s_handle, | 4334 | tag = mgmt_get_session_info(phba, s_handle, |
| 4337 | &nonemb_cmd); | 4335 | &nonemb_cmd); |
| 4338 | if (!tag) { | 4336 | if (!tag) { |
diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index a3e56487616c..665afcb74a56 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c | |||
| @@ -900,13 +900,12 @@ free_cmd: | |||
| 900 | static int mgmt_alloc_cmd_data(struct beiscsi_hba *phba, struct be_dma_mem *cmd, | 900 | static int mgmt_alloc_cmd_data(struct beiscsi_hba *phba, struct be_dma_mem *cmd, |
| 901 | int iscsi_cmd, int size) | 901 | int iscsi_cmd, int size) |
| 902 | { | 902 | { |
| 903 | cmd->va = pci_alloc_consistent(phba->ctrl.pdev, size, &cmd->dma); | 903 | cmd->va = pci_zalloc_consistent(phba->ctrl.pdev, size, &cmd->dma); |
| 904 | if (!cmd->va) { | 904 | if (!cmd->va) { |
| 905 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | 905 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, |
| 906 | "BG_%d : Failed to allocate memory for if info\n"); | 906 | "BG_%d : Failed to allocate memory for if info\n"); |
| 907 | return -ENOMEM; | 907 | return -ENOMEM; |
| 908 | } | 908 | } |
| 909 | memset(cmd->va, 0, size); | ||
| 910 | cmd->size = size; | 909 | cmd->size = size; |
| 911 | be_cmd_hdr_prepare(cmd->va, CMD_SUBSYSTEM_ISCSI, iscsi_cmd, size); | 910 | be_cmd_hdr_prepare(cmd->va, CMD_SUBSYSTEM_ISCSI, iscsi_cmd, size); |
| 912 | return 0; | 911 | return 0; |
diff --git a/drivers/scsi/csiostor/csio_wr.c b/drivers/scsi/csiostor/csio_wr.c index 4255ce264abf..773da14cfa14 100644 --- a/drivers/scsi/csiostor/csio_wr.c +++ b/drivers/scsi/csiostor/csio_wr.c | |||
| @@ -232,7 +232,7 @@ csio_wr_alloc_q(struct csio_hw *hw, uint32_t qsize, uint32_t wrsize, | |||
| 232 | 232 | ||
| 233 | q = wrm->q_arr[free_idx]; | 233 | q = wrm->q_arr[free_idx]; |
| 234 | 234 | ||
| 235 | q->vstart = pci_alloc_consistent(hw->pdev, qsz, &q->pstart); | 235 | q->vstart = pci_zalloc_consistent(hw->pdev, qsz, &q->pstart); |
| 236 | if (!q->vstart) { | 236 | if (!q->vstart) { |
| 237 | csio_err(hw, | 237 | csio_err(hw, |
| 238 | "Failed to allocate DMA memory for " | 238 | "Failed to allocate DMA memory for " |
| @@ -240,12 +240,6 @@ csio_wr_alloc_q(struct csio_hw *hw, uint32_t qsize, uint32_t wrsize, | |||
| 240 | return -1; | 240 | return -1; |
| 241 | } | 241 | } |
| 242 | 242 | ||
| 243 | /* | ||
| 244 | * We need to zero out the contents, importantly for ingress, | ||
| 245 | * since we start with a generatiom bit of 1 for ingress. | ||
| 246 | */ | ||
| 247 | memset(q->vstart, 0, qsz); | ||
| 248 | |||
| 249 | q->type = type; | 243 | q->type = type; |
| 250 | q->owner = owner; | 244 | q->owner = owner; |
| 251 | q->pidx = q->cidx = q->inc_idx = 0; | 245 | q->pidx = q->cidx = q->inc_idx = 0; |
diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c index 03372cff38f3..813dd5c998e4 100644 --- a/drivers/scsi/eata.c +++ b/drivers/scsi/eata.c | |||
| @@ -1238,8 +1238,8 @@ static int port_detect(unsigned long port_base, unsigned int j, | |||
| 1238 | struct eata_config *cf; | 1238 | struct eata_config *cf; |
| 1239 | dma_addr_t cf_dma_addr; | 1239 | dma_addr_t cf_dma_addr; |
| 1240 | 1240 | ||
| 1241 | cf = pci_alloc_consistent(pdev, sizeof(struct eata_config), | 1241 | cf = pci_zalloc_consistent(pdev, sizeof(struct eata_config), |
| 1242 | &cf_dma_addr); | 1242 | &cf_dma_addr); |
| 1243 | 1243 | ||
| 1244 | if (!cf) { | 1244 | if (!cf) { |
| 1245 | printk | 1245 | printk |
| @@ -1249,7 +1249,6 @@ static int port_detect(unsigned long port_base, unsigned int j, | |||
| 1249 | } | 1249 | } |
| 1250 | 1250 | ||
| 1251 | /* Set board configuration */ | 1251 | /* Set board configuration */ |
| 1252 | memset((char *)cf, 0, sizeof(struct eata_config)); | ||
| 1253 | cf->len = (ushort) H2DEV16((ushort) 510); | 1252 | cf->len = (ushort) H2DEV16((ushort) 510); |
| 1254 | cf->ocena = 1; | 1253 | cf->ocena = 1; |
| 1255 | 1254 | ||
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 8545d1826725..6b35d0dfe64c 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c | |||
| @@ -4732,23 +4732,21 @@ static struct CommandList *cmd_special_alloc(struct ctlr_info *h) | |||
| 4732 | union u64bit temp64; | 4732 | union u64bit temp64; |
| 4733 | dma_addr_t cmd_dma_handle, err_dma_handle; | 4733 | dma_addr_t cmd_dma_handle, err_dma_handle; |
| 4734 | 4734 | ||
| 4735 | c = pci_alloc_consistent(h->pdev, sizeof(*c), &cmd_dma_handle); | 4735 | c = pci_zalloc_consistent(h->pdev, sizeof(*c), &cmd_dma_handle); |
| 4736 | if (c == NULL) | 4736 | if (c == NULL) |
| 4737 | return NULL; | 4737 | return NULL; |
| 4738 | memset(c, 0, sizeof(*c)); | ||
| 4739 | 4738 | ||
| 4740 | c->cmd_type = CMD_SCSI; | 4739 | c->cmd_type = CMD_SCSI; |
| 4741 | c->cmdindex = -1; | 4740 | c->cmdindex = -1; |
| 4742 | 4741 | ||
| 4743 | c->err_info = pci_alloc_consistent(h->pdev, sizeof(*c->err_info), | 4742 | c->err_info = pci_zalloc_consistent(h->pdev, sizeof(*c->err_info), |
| 4744 | &err_dma_handle); | 4743 | &err_dma_handle); |
| 4745 | 4744 | ||
| 4746 | if (c->err_info == NULL) { | 4745 | if (c->err_info == NULL) { |
| 4747 | pci_free_consistent(h->pdev, | 4746 | pci_free_consistent(h->pdev, |
| 4748 | sizeof(*c), c, cmd_dma_handle); | 4747 | sizeof(*c), c, cmd_dma_handle); |
| 4749 | return NULL; | 4748 | return NULL; |
| 4750 | } | 4749 | } |
| 4751 | memset(c->err_info, 0, sizeof(*c->err_info)); | ||
| 4752 | 4750 | ||
| 4753 | INIT_LIST_HEAD(&c->list); | 4751 | INIT_LIST_HEAD(&c->list); |
| 4754 | c->busaddr = (u32) cmd_dma_handle; | 4752 | c->busaddr = (u32) cmd_dma_handle; |
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c index e2237a97cb9d..531dce419c18 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.c +++ b/drivers/scsi/megaraid/megaraid_mbox.c | |||
| @@ -998,8 +998,9 @@ megaraid_alloc_cmd_packets(adapter_t *adapter) | |||
| 998 | * Allocate the common 16-byte aligned memory for the handshake | 998 | * Allocate the common 16-byte aligned memory for the handshake |
| 999 | * mailbox. | 999 | * mailbox. |
| 1000 | */ | 1000 | */ |
| 1001 | raid_dev->una_mbox64 = pci_alloc_consistent(adapter->pdev, | 1001 | raid_dev->una_mbox64 = pci_zalloc_consistent(adapter->pdev, |
| 1002 | sizeof(mbox64_t), &raid_dev->una_mbox64_dma); | 1002 | sizeof(mbox64_t), |
| 1003 | &raid_dev->una_mbox64_dma); | ||
| 1003 | 1004 | ||
| 1004 | if (!raid_dev->una_mbox64) { | 1005 | if (!raid_dev->una_mbox64) { |
| 1005 | con_log(CL_ANN, (KERN_WARNING | 1006 | con_log(CL_ANN, (KERN_WARNING |
| @@ -1007,7 +1008,6 @@ megaraid_alloc_cmd_packets(adapter_t *adapter) | |||
| 1007 | __LINE__)); | 1008 | __LINE__)); |
| 1008 | return -1; | 1009 | return -1; |
| 1009 | } | 1010 | } |
| 1010 | memset(raid_dev->una_mbox64, 0, sizeof(mbox64_t)); | ||
| 1011 | 1011 | ||
| 1012 | /* | 1012 | /* |
| 1013 | * Align the mailbox at 16-byte boundary | 1013 | * Align the mailbox at 16-byte boundary |
| @@ -1026,8 +1026,8 @@ megaraid_alloc_cmd_packets(adapter_t *adapter) | |||
| 1026 | align; | 1026 | align; |
| 1027 | 1027 | ||
| 1028 | // Allocate memory for commands issued internally | 1028 | // Allocate memory for commands issued internally |
| 1029 | adapter->ibuf = pci_alloc_consistent(pdev, MBOX_IBUF_SIZE, | 1029 | adapter->ibuf = pci_zalloc_consistent(pdev, MBOX_IBUF_SIZE, |
| 1030 | &adapter->ibuf_dma_h); | 1030 | &adapter->ibuf_dma_h); |
| 1031 | if (!adapter->ibuf) { | 1031 | if (!adapter->ibuf) { |
| 1032 | 1032 | ||
| 1033 | con_log(CL_ANN, (KERN_WARNING | 1033 | con_log(CL_ANN, (KERN_WARNING |
| @@ -1036,7 +1036,6 @@ megaraid_alloc_cmd_packets(adapter_t *adapter) | |||
| 1036 | 1036 | ||
| 1037 | goto out_free_common_mbox; | 1037 | goto out_free_common_mbox; |
| 1038 | } | 1038 | } |
| 1039 | memset(adapter->ibuf, 0, MBOX_IBUF_SIZE); | ||
| 1040 | 1039 | ||
| 1041 | // Allocate memory for our SCSI Command Blocks and their associated | 1040 | // Allocate memory for our SCSI Command Blocks and their associated |
| 1042 | // memory | 1041 | // memory |
| @@ -2972,8 +2971,8 @@ megaraid_mbox_product_info(adapter_t *adapter) | |||
| 2972 | * Issue an ENQUIRY3 command to find out certain adapter parameters, | 2971 | * Issue an ENQUIRY3 command to find out certain adapter parameters, |
| 2973 | * e.g., max channels, max commands etc. | 2972 | * e.g., max channels, max commands etc. |
| 2974 | */ | 2973 | */ |
| 2975 | pinfo = pci_alloc_consistent(adapter->pdev, sizeof(mraid_pinfo_t), | 2974 | pinfo = pci_zalloc_consistent(adapter->pdev, sizeof(mraid_pinfo_t), |
| 2976 | &pinfo_dma_h); | 2975 | &pinfo_dma_h); |
| 2977 | 2976 | ||
| 2978 | if (pinfo == NULL) { | 2977 | if (pinfo == NULL) { |
| 2979 | con_log(CL_ANN, (KERN_WARNING | 2978 | con_log(CL_ANN, (KERN_WARNING |
| @@ -2982,7 +2981,6 @@ megaraid_mbox_product_info(adapter_t *adapter) | |||
| 2982 | 2981 | ||
| 2983 | return -1; | 2982 | return -1; |
| 2984 | } | 2983 | } |
| 2985 | memset(pinfo, 0, sizeof(mraid_pinfo_t)); | ||
| 2986 | 2984 | ||
| 2987 | mbox->xferaddr = (uint32_t)adapter->ibuf_dma_h; | 2985 | mbox->xferaddr = (uint32_t)adapter->ibuf_dma_h; |
| 2988 | memset((void *)adapter->ibuf, 0, MBOX_IBUF_SIZE); | 2986 | memset((void *)adapter->ibuf, 0, MBOX_IBUF_SIZE); |
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 112799b131a9..22a04e37b70a 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c | |||
| @@ -2038,9 +2038,9 @@ int megasas_sriov_start_heartbeat(struct megasas_instance *instance, | |||
| 2038 | 2038 | ||
| 2039 | if (initial) { | 2039 | if (initial) { |
| 2040 | instance->hb_host_mem = | 2040 | instance->hb_host_mem = |
| 2041 | pci_alloc_consistent(instance->pdev, | 2041 | pci_zalloc_consistent(instance->pdev, |
| 2042 | sizeof(struct MR_CTRL_HB_HOST_MEM), | 2042 | sizeof(struct MR_CTRL_HB_HOST_MEM), |
| 2043 | &instance->hb_host_mem_h); | 2043 | &instance->hb_host_mem_h); |
| 2044 | if (!instance->hb_host_mem) { | 2044 | if (!instance->hb_host_mem) { |
| 2045 | printk(KERN_DEBUG "megasas: SR-IOV: Couldn't allocate" | 2045 | printk(KERN_DEBUG "megasas: SR-IOV: Couldn't allocate" |
| 2046 | " memory for heartbeat host memory for " | 2046 | " memory for heartbeat host memory for " |
| @@ -2048,8 +2048,6 @@ int megasas_sriov_start_heartbeat(struct megasas_instance *instance, | |||
| 2048 | retval = -ENOMEM; | 2048 | retval = -ENOMEM; |
| 2049 | goto out; | 2049 | goto out; |
| 2050 | } | 2050 | } |
| 2051 | memset(instance->hb_host_mem, 0, | ||
| 2052 | sizeof(struct MR_CTRL_HB_HOST_MEM)); | ||
| 2053 | } | 2051 | } |
| 2054 | 2052 | ||
| 2055 | memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); | 2053 | memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); |
diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c index 7a6160f172ce..57a95e2c3442 100644 --- a/drivers/scsi/mesh.c +++ b/drivers/scsi/mesh.c | |||
| @@ -1915,14 +1915,12 @@ static int mesh_probe(struct macio_dev *mdev, const struct of_device_id *match) | |||
| 1915 | /* We use the PCI APIs for now until the generic one gets fixed | 1915 | /* We use the PCI APIs for now until the generic one gets fixed |
| 1916 | * enough or until we get some macio-specific versions | 1916 | * enough or until we get some macio-specific versions |
| 1917 | */ | 1917 | */ |
| 1918 | dma_cmd_space = pci_alloc_consistent(macio_get_pci_dev(mdev), | 1918 | dma_cmd_space = pci_zalloc_consistent(macio_get_pci_dev(mdev), |
| 1919 | ms->dma_cmd_size, | 1919 | ms->dma_cmd_size, &dma_cmd_bus); |
| 1920 | &dma_cmd_bus); | ||
| 1921 | if (dma_cmd_space == NULL) { | 1920 | if (dma_cmd_space == NULL) { |
| 1922 | printk(KERN_ERR "mesh: can't allocate DMA table\n"); | 1921 | printk(KERN_ERR "mesh: can't allocate DMA table\n"); |
| 1923 | goto out_unmap; | 1922 | goto out_unmap; |
| 1924 | } | 1923 | } |
| 1925 | memset(dma_cmd_space, 0, ms->dma_cmd_size); | ||
| 1926 | 1924 | ||
| 1927 | ms->dma_cmds = (struct dbdma_cmd *) DBDMA_ALIGN(dma_cmd_space); | 1925 | ms->dma_cmds = (struct dbdma_cmd *) DBDMA_ALIGN(dma_cmd_space); |
| 1928 | ms->dma_cmd_space = dma_cmd_space; | 1926 | ms->dma_cmd_space = dma_cmd_space; |
diff --git a/drivers/scsi/mvumi.c b/drivers/scsi/mvumi.c index edbee8dc62c9..3e716b2f611a 100644 --- a/drivers/scsi/mvumi.c +++ b/drivers/scsi/mvumi.c | |||
| @@ -142,8 +142,8 @@ static struct mvumi_res *mvumi_alloc_mem_resource(struct mvumi_hba *mhba, | |||
| 142 | 142 | ||
| 143 | case RESOURCE_UNCACHED_MEMORY: | 143 | case RESOURCE_UNCACHED_MEMORY: |
| 144 | size = round_up(size, 8); | 144 | size = round_up(size, 8); |
| 145 | res->virt_addr = pci_alloc_consistent(mhba->pdev, size, | 145 | res->virt_addr = pci_zalloc_consistent(mhba->pdev, size, |
| 146 | &res->bus_addr); | 146 | &res->bus_addr); |
| 147 | if (!res->virt_addr) { | 147 | if (!res->virt_addr) { |
| 148 | dev_err(&mhba->pdev->dev, | 148 | dev_err(&mhba->pdev->dev, |
| 149 | "unable to allocate consistent mem," | 149 | "unable to allocate consistent mem," |
| @@ -151,7 +151,6 @@ static struct mvumi_res *mvumi_alloc_mem_resource(struct mvumi_hba *mhba, | |||
| 151 | kfree(res); | 151 | kfree(res); |
| 152 | return NULL; | 152 | return NULL; |
| 153 | } | 153 | } |
| 154 | memset(res->virt_addr, 0, size); | ||
| 155 | break; | 154 | break; |
| 156 | 155 | ||
| 157 | default: | 156 | default: |
| @@ -258,12 +257,10 @@ static int mvumi_internal_cmd_sgl(struct mvumi_hba *mhba, struct mvumi_cmd *cmd, | |||
| 258 | if (size == 0) | 257 | if (size == 0) |
| 259 | return 0; | 258 | return 0; |
| 260 | 259 | ||
| 261 | virt_addr = pci_alloc_consistent(mhba->pdev, size, &phy_addr); | 260 | virt_addr = pci_zalloc_consistent(mhba->pdev, size, &phy_addr); |
| 262 | if (!virt_addr) | 261 | if (!virt_addr) |
| 263 | return -1; | 262 | return -1; |
| 264 | 263 | ||
| 265 | memset(virt_addr, 0, size); | ||
| 266 | |||
| 267 | m_sg = (struct mvumi_sgl *) &cmd->frame->payload[0]; | 264 | m_sg = (struct mvumi_sgl *) &cmd->frame->payload[0]; |
| 268 | cmd->frame->sg_counts = 1; | 265 | cmd->frame->sg_counts = 1; |
| 269 | cmd->data_buf = virt_addr; | 266 | cmd->data_buf = virt_addr; |
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index 34cea8291772..76570e6a547d 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c | |||
| @@ -116,13 +116,12 @@ int pm8001_mem_alloc(struct pci_dev *pdev, void **virt_addr, | |||
| 116 | u64 align_offset = 0; | 116 | u64 align_offset = 0; |
| 117 | if (align) | 117 | if (align) |
| 118 | align_offset = (dma_addr_t)align - 1; | 118 | align_offset = (dma_addr_t)align - 1; |
| 119 | mem_virt_alloc = | 119 | mem_virt_alloc = pci_zalloc_consistent(pdev, mem_size + align, |
| 120 | pci_alloc_consistent(pdev, mem_size + align, &mem_dma_handle); | 120 | &mem_dma_handle); |
| 121 | if (!mem_virt_alloc) { | 121 | if (!mem_virt_alloc) { |
| 122 | pm8001_printk("memory allocation error\n"); | 122 | pm8001_printk("memory allocation error\n"); |
| 123 | return -1; | 123 | return -1; |
| 124 | } | 124 | } |
| 125 | memset((void *)mem_virt_alloc, 0, mem_size+align); | ||
| 126 | *pphys_addr = mem_dma_handle; | 125 | *pphys_addr = mem_dma_handle; |
| 127 | phys_align = (*pphys_addr + align_offset) & ~align_offset; | 126 | phys_align = (*pphys_addr + align_offset) & ~align_offset; |
| 128 | *virt_addr = (void *)mem_virt_alloc + phys_align - *pphys_addr; | 127 | *virt_addr = (void *)mem_virt_alloc + phys_align - *pphys_addr; |
diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c index 017f8b9554e5..6f3275d020a0 100644 --- a/drivers/scsi/pmcraid.c +++ b/drivers/scsi/pmcraid.c | |||
| @@ -4213,9 +4213,9 @@ static ssize_t pmcraid_store_log_level( | |||
| 4213 | { | 4213 | { |
| 4214 | struct Scsi_Host *shost; | 4214 | struct Scsi_Host *shost; |
| 4215 | struct pmcraid_instance *pinstance; | 4215 | struct pmcraid_instance *pinstance; |
| 4216 | unsigned long val; | 4216 | u8 val; |
| 4217 | 4217 | ||
| 4218 | if (strict_strtoul(buf, 10, &val)) | 4218 | if (kstrtou8(buf, 10, &val)) |
| 4219 | return -EINVAL; | 4219 | return -EINVAL; |
| 4220 | /* log-level should be from 0 to 2 */ | 4220 | /* log-level should be from 0 to 2 */ |
| 4221 | if (val > 2) | 4221 | if (val > 2) |
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 406b3038bbad..8b4105a22ac2 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c | |||
| @@ -910,9 +910,9 @@ sdev_store_queue_ramp_up_period(struct device *dev, | |||
| 910 | const char *buf, size_t count) | 910 | const char *buf, size_t count) |
| 911 | { | 911 | { |
| 912 | struct scsi_device *sdev = to_scsi_device(dev); | 912 | struct scsi_device *sdev = to_scsi_device(dev); |
| 913 | unsigned long period; | 913 | unsigned int period; |
| 914 | 914 | ||
| 915 | if (strict_strtoul(buf, 10, &period)) | 915 | if (kstrtouint(buf, 10, &period)) |
| 916 | return -EINVAL; | 916 | return -EINVAL; |
| 917 | 917 | ||
| 918 | sdev->queue_ramp_up_period = msecs_to_jiffies(period); | 918 | sdev->queue_ramp_up_period = msecs_to_jiffies(period); |
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c index 2920e406030a..5729cf678765 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c | |||
| @@ -2065,20 +2065,16 @@ static short rtl8192_alloc_rx_desc_ring(struct net_device *dev) | |||
| 2065 | int i, rx_queue_idx; | 2065 | int i, rx_queue_idx; |
| 2066 | 2066 | ||
| 2067 | for (rx_queue_idx = 0; rx_queue_idx < MAX_RX_QUEUE; rx_queue_idx++) { | 2067 | for (rx_queue_idx = 0; rx_queue_idx < MAX_RX_QUEUE; rx_queue_idx++) { |
| 2068 | priv->rx_ring[rx_queue_idx] = pci_alloc_consistent(priv->pdev, | 2068 | priv->rx_ring[rx_queue_idx] = |
| 2069 | sizeof(*priv->rx_ring[rx_queue_idx]) * | 2069 | pci_zalloc_consistent(priv->pdev, |
| 2070 | priv->rxringcount, | 2070 | sizeof(*priv->rx_ring[rx_queue_idx]) * priv->rxringcount, |
| 2071 | &priv->rx_ring_dma[rx_queue_idx]); | 2071 | &priv->rx_ring_dma[rx_queue_idx]); |
| 2072 | |||
| 2073 | if (!priv->rx_ring[rx_queue_idx] || | 2072 | if (!priv->rx_ring[rx_queue_idx] || |
| 2074 | (unsigned long)priv->rx_ring[rx_queue_idx] & 0xFF) { | 2073 | (unsigned long)priv->rx_ring[rx_queue_idx] & 0xFF) { |
| 2075 | RT_TRACE(COMP_ERR, "Cannot allocate RX ring\n"); | 2074 | RT_TRACE(COMP_ERR, "Cannot allocate RX ring\n"); |
| 2076 | return -ENOMEM; | 2075 | return -ENOMEM; |
| 2077 | } | 2076 | } |
| 2078 | 2077 | ||
| 2079 | memset(priv->rx_ring[rx_queue_idx], 0, | ||
| 2080 | sizeof(*priv->rx_ring[rx_queue_idx]) * | ||
| 2081 | priv->rxringcount); | ||
| 2082 | priv->rx_idx[rx_queue_idx] = 0; | 2078 | priv->rx_idx[rx_queue_idx] = 0; |
| 2083 | 2079 | ||
| 2084 | for (i = 0; i < priv->rxringcount; i++) { | 2080 | for (i = 0; i < priv->rxringcount; i++) { |
| @@ -2118,14 +2114,13 @@ static int rtl8192_alloc_tx_desc_ring(struct net_device *dev, | |||
| 2118 | dma_addr_t dma; | 2114 | dma_addr_t dma; |
| 2119 | int i; | 2115 | int i; |
| 2120 | 2116 | ||
| 2121 | ring = pci_alloc_consistent(priv->pdev, sizeof(*ring) * entries, &dma); | 2117 | ring = pci_zalloc_consistent(priv->pdev, sizeof(*ring) * entries, &dma); |
| 2122 | if (!ring || (unsigned long)ring & 0xFF) { | 2118 | if (!ring || (unsigned long)ring & 0xFF) { |
| 2123 | RT_TRACE(COMP_ERR, "Cannot allocate TX ring (prio = %d)\n", | 2119 | RT_TRACE(COMP_ERR, "Cannot allocate TX ring (prio = %d)\n", |
| 2124 | prio); | 2120 | prio); |
| 2125 | return -ENOMEM; | 2121 | return -ENOMEM; |
| 2126 | } | 2122 | } |
| 2127 | 2123 | ||
| 2128 | memset(ring, 0, sizeof(*ring)*entries); | ||
| 2129 | priv->tx_ring[prio].desc = ring; | 2124 | priv->tx_ring[prio].desc = ring; |
| 2130 | priv->tx_ring[prio].dma = dma; | 2125 | priv->tx_ring[prio].dma = dma; |
| 2131 | priv->tx_ring[prio].idx = 0; | 2126 | priv->tx_ring[prio].idx = 0; |
diff --git a/drivers/staging/rtl8192ee/pci.c b/drivers/staging/rtl8192ee/pci.c index f3abbcc9f3ba..0215aef1eacc 100644 --- a/drivers/staging/rtl8192ee/pci.c +++ b/drivers/staging/rtl8192ee/pci.c | |||
| @@ -1224,10 +1224,10 @@ static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw, | |||
| 1224 | 1224 | ||
| 1225 | /* alloc tx buffer desc for new trx flow*/ | 1225 | /* alloc tx buffer desc for new trx flow*/ |
| 1226 | if (rtlpriv->use_new_trx_flow) { | 1226 | if (rtlpriv->use_new_trx_flow) { |
| 1227 | buffer_desc = pci_alloc_consistent(rtlpci->pdev, | 1227 | buffer_desc = |
| 1228 | sizeof(*buffer_desc) * entries, | 1228 | pci_zalloc_consistent(rtlpci->pdev, |
| 1229 | &buffer_desc_dma); | 1229 | sizeof(*buffer_desc) * entries, |
| 1230 | 1230 | &buffer_desc_dma); | |
| 1231 | if (!buffer_desc || (unsigned long)buffer_desc & 0xFF) { | 1231 | if (!buffer_desc || (unsigned long)buffer_desc & 0xFF) { |
| 1232 | RT_TRACE(COMP_ERR, DBG_EMERG, | 1232 | RT_TRACE(COMP_ERR, DBG_EMERG, |
| 1233 | ("Cannot allocate TX ring (prio = %d)\n", | 1233 | ("Cannot allocate TX ring (prio = %d)\n", |
| @@ -1235,7 +1235,6 @@ static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw, | |||
| 1235 | return -ENOMEM; | 1235 | return -ENOMEM; |
| 1236 | } | 1236 | } |
| 1237 | 1237 | ||
| 1238 | memset(buffer_desc, 0, sizeof(*buffer_desc) * entries); | ||
| 1239 | rtlpci->tx_ring[prio].buffer_desc = buffer_desc; | 1238 | rtlpci->tx_ring[prio].buffer_desc = buffer_desc; |
| 1240 | rtlpci->tx_ring[prio].buffer_desc_dma = buffer_desc_dma; | 1239 | rtlpci->tx_ring[prio].buffer_desc_dma = buffer_desc_dma; |
| 1241 | 1240 | ||
| @@ -1245,16 +1244,14 @@ static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw, | |||
| 1245 | } | 1244 | } |
| 1246 | 1245 | ||
| 1247 | /* alloc dma for this ring */ | 1246 | /* alloc dma for this ring */ |
| 1248 | desc = pci_alloc_consistent(rtlpci->pdev, | 1247 | desc = pci_zalloc_consistent(rtlpci->pdev, sizeof(*desc) * entries, |
| 1249 | sizeof(*desc) * entries, &desc_dma); | 1248 | &desc_dma); |
| 1250 | |||
| 1251 | if (!desc || (unsigned long)desc & 0xFF) { | 1249 | if (!desc || (unsigned long)desc & 0xFF) { |
| 1252 | RT_TRACE(COMP_ERR, DBG_EMERG, | 1250 | RT_TRACE(COMP_ERR, DBG_EMERG, |
| 1253 | ("Cannot allocate TX ring (prio = %d)\n", prio)); | 1251 | ("Cannot allocate TX ring (prio = %d)\n", prio)); |
| 1254 | return -ENOMEM; | 1252 | return -ENOMEM; |
| 1255 | } | 1253 | } |
| 1256 | 1254 | ||
| 1257 | memset(desc, 0, sizeof(*desc) * entries); | ||
| 1258 | rtlpci->tx_ring[prio].desc = desc; | 1255 | rtlpci->tx_ring[prio].desc = desc; |
| 1259 | rtlpci->tx_ring[prio].dma = desc_dma; | 1256 | rtlpci->tx_ring[prio].dma = desc_dma; |
| 1260 | 1257 | ||
| @@ -1290,11 +1287,9 @@ static int _rtl_pci_init_rx_ring(struct ieee80211_hw *hw, int rxring_idx) | |||
| 1290 | struct rtl_rx_buffer_desc *entry = NULL; | 1287 | struct rtl_rx_buffer_desc *entry = NULL; |
| 1291 | /* alloc dma for this ring */ | 1288 | /* alloc dma for this ring */ |
| 1292 | rtlpci->rx_ring[rxring_idx].buffer_desc = | 1289 | rtlpci->rx_ring[rxring_idx].buffer_desc = |
| 1293 | pci_alloc_consistent(rtlpci->pdev, | 1290 | pci_zalloc_consistent(rtlpci->pdev, |
| 1294 | sizeof(*rtlpci->rx_ring[rxring_idx]. | 1291 | sizeof(*rtlpci->rx_ring[rxring_idx].buffer_desc) * rtlpci->rxringcount, |
| 1295 | buffer_desc) * | 1292 | &rtlpci->rx_ring[rxring_idx].dma); |
| 1296 | rtlpci->rxringcount, | ||
| 1297 | &rtlpci->rx_ring[rxring_idx].dma); | ||
| 1298 | if (!rtlpci->rx_ring[rxring_idx].buffer_desc || | 1293 | if (!rtlpci->rx_ring[rxring_idx].buffer_desc || |
| 1299 | (unsigned long)rtlpci->rx_ring[rxring_idx].buffer_desc & 0xFF) { | 1294 | (unsigned long)rtlpci->rx_ring[rxring_idx].buffer_desc & 0xFF) { |
| 1300 | RT_TRACE(COMP_ERR, DBG_EMERG, | 1295 | RT_TRACE(COMP_ERR, DBG_EMERG, |
| @@ -1302,10 +1297,6 @@ static int _rtl_pci_init_rx_ring(struct ieee80211_hw *hw, int rxring_idx) | |||
| 1302 | return -ENOMEM; | 1297 | return -ENOMEM; |
| 1303 | } | 1298 | } |
| 1304 | 1299 | ||
| 1305 | memset(rtlpci->rx_ring[rxring_idx].buffer_desc, 0, | ||
| 1306 | sizeof(*rtlpci->rx_ring[rxring_idx].buffer_desc) * | ||
| 1307 | rtlpci->rxringcount); | ||
| 1308 | |||
| 1309 | /* init every desc in this ring */ | 1300 | /* init every desc in this ring */ |
| 1310 | rtlpci->rx_ring[rxring_idx].idx = 0; | 1301 | rtlpci->rx_ring[rxring_idx].idx = 0; |
| 1311 | 1302 | ||
| @@ -1320,19 +1311,15 @@ static int _rtl_pci_init_rx_ring(struct ieee80211_hw *hw, int rxring_idx) | |||
| 1320 | u8 tmp_one = 1; | 1311 | u8 tmp_one = 1; |
| 1321 | /* alloc dma for this ring */ | 1312 | /* alloc dma for this ring */ |
| 1322 | rtlpci->rx_ring[rxring_idx].desc = | 1313 | rtlpci->rx_ring[rxring_idx].desc = |
| 1323 | pci_alloc_consistent(rtlpci->pdev, | 1314 | pci_zalloc_consistent(rtlpci->pdev, |
| 1324 | sizeof(*rtlpci->rx_ring[rxring_idx]. | 1315 | sizeof(*rtlpci->rx_ring[rxring_idx].desc) * rtlpci->rxringcount, |
| 1325 | desc) * rtlpci->rxringcount, | 1316 | &rtlpci->rx_ring[rxring_idx].dma); |
| 1326 | &rtlpci->rx_ring[rxring_idx].dma); | ||
| 1327 | if (!rtlpci->rx_ring[rxring_idx].desc || | 1317 | if (!rtlpci->rx_ring[rxring_idx].desc || |
| 1328 | (unsigned long)rtlpci->rx_ring[rxring_idx].desc & 0xFF) { | 1318 | (unsigned long)rtlpci->rx_ring[rxring_idx].desc & 0xFF) { |
| 1329 | RT_TRACE(COMP_ERR, DBG_EMERG, | 1319 | RT_TRACE(COMP_ERR, DBG_EMERG, |
| 1330 | ("Cannot allocate RX ring\n")); | 1320 | ("Cannot allocate RX ring\n")); |
| 1331 | return -ENOMEM; | 1321 | return -ENOMEM; |
| 1332 | } | 1322 | } |
| 1333 | memset(rtlpci->rx_ring[rxring_idx].desc, 0, | ||
| 1334 | sizeof(*rtlpci->rx_ring[rxring_idx].desc) * | ||
| 1335 | rtlpci->rxringcount); | ||
| 1336 | 1323 | ||
| 1337 | /* init every desc in this ring */ | 1324 | /* init every desc in this ring */ |
| 1338 | rtlpci->rx_ring[rxring_idx].idx = 0; | 1325 | rtlpci->rx_ring[rxring_idx].idx = 0; |
diff --git a/drivers/staging/rtl8821ae/pci.c b/drivers/staging/rtl8821ae/pci.c index f9847d1fbdeb..26d7b2fc852a 100644 --- a/drivers/staging/rtl8821ae/pci.c +++ b/drivers/staging/rtl8821ae/pci.c | |||
| @@ -1248,9 +1248,10 @@ static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw, | |||
| 1248 | 1248 | ||
| 1249 | /* alloc tx buffer desc for new trx flow*/ | 1249 | /* alloc tx buffer desc for new trx flow*/ |
| 1250 | if (rtlpriv->use_new_trx_flow) { | 1250 | if (rtlpriv->use_new_trx_flow) { |
| 1251 | buffer_desc = pci_alloc_consistent(rtlpci->pdev, | 1251 | buffer_desc = |
| 1252 | sizeof(*buffer_desc) * entries, | 1252 | pci_zalloc_consistent(rtlpci->pdev, |
| 1253 | &buffer_desc_dma); | 1253 | sizeof(*buffer_desc) * entries, |
| 1254 | &buffer_desc_dma); | ||
| 1254 | 1255 | ||
| 1255 | if (!buffer_desc || (unsigned long)buffer_desc & 0xFF) { | 1256 | if (!buffer_desc || (unsigned long)buffer_desc & 0xFF) { |
| 1256 | RT_TRACE(COMP_ERR, DBG_EMERG, | 1257 | RT_TRACE(COMP_ERR, DBG_EMERG, |
| @@ -1259,7 +1260,6 @@ static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw, | |||
| 1259 | return -ENOMEM; | 1260 | return -ENOMEM; |
| 1260 | } | 1261 | } |
| 1261 | 1262 | ||
| 1262 | memset(buffer_desc, 0, sizeof(*buffer_desc) * entries); | ||
| 1263 | rtlpci->tx_ring[prio].buffer_desc = buffer_desc; | 1263 | rtlpci->tx_ring[prio].buffer_desc = buffer_desc; |
| 1264 | rtlpci->tx_ring[prio].buffer_desc_dma = buffer_desc_dma; | 1264 | rtlpci->tx_ring[prio].buffer_desc_dma = buffer_desc_dma; |
| 1265 | 1265 | ||
| @@ -1270,8 +1270,8 @@ static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw, | |||
| 1270 | } | 1270 | } |
| 1271 | 1271 | ||
| 1272 | /* alloc dma for this ring */ | 1272 | /* alloc dma for this ring */ |
| 1273 | desc = pci_alloc_consistent(rtlpci->pdev, | 1273 | desc = pci_zalloc_consistent(rtlpci->pdev, sizeof(*desc) * entries, |
| 1274 | sizeof(*desc) * entries, &desc_dma); | 1274 | &desc_dma); |
| 1275 | 1275 | ||
| 1276 | if (!desc || (unsigned long)desc & 0xFF) { | 1276 | if (!desc || (unsigned long)desc & 0xFF) { |
| 1277 | RT_TRACE(COMP_ERR, DBG_EMERG, | 1277 | RT_TRACE(COMP_ERR, DBG_EMERG, |
| @@ -1279,7 +1279,6 @@ static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw, | |||
| 1279 | return -ENOMEM; | 1279 | return -ENOMEM; |
| 1280 | } | 1280 | } |
| 1281 | 1281 | ||
| 1282 | memset(desc, 0, sizeof(*desc) * entries); | ||
| 1283 | rtlpci->tx_ring[prio].desc = desc; | 1282 | rtlpci->tx_ring[prio].desc = desc; |
| 1284 | rtlpci->tx_ring[prio].dma = desc_dma; | 1283 | rtlpci->tx_ring[prio].dma = desc_dma; |
| 1285 | 1284 | ||
| @@ -1316,21 +1315,15 @@ static int _rtl_pci_init_rx_ring(struct ieee80211_hw *hw, int rxring_idx) | |||
| 1316 | struct rtl_rx_buffer_desc *entry = NULL; | 1315 | struct rtl_rx_buffer_desc *entry = NULL; |
| 1317 | /* alloc dma for this ring */ | 1316 | /* alloc dma for this ring */ |
| 1318 | rtlpci->rx_ring[rxring_idx].buffer_desc = | 1317 | rtlpci->rx_ring[rxring_idx].buffer_desc = |
| 1319 | pci_alloc_consistent(rtlpci->pdev, | 1318 | pci_zalloc_consistent(rtlpci->pdev, |
| 1320 | sizeof(*rtlpci->rx_ring[rxring_idx]. | 1319 | sizeof(*rtlpci->rx_ring[rxring_idx].buffer_desc) * rtlpci->rxringcount, |
| 1321 | buffer_desc) * | 1320 | &rtlpci->rx_ring[rxring_idx].dma); |
| 1322 | rtlpci->rxringcount, | ||
| 1323 | &rtlpci->rx_ring[rxring_idx].dma); | ||
| 1324 | if (!rtlpci->rx_ring[rxring_idx].buffer_desc || | 1321 | if (!rtlpci->rx_ring[rxring_idx].buffer_desc || |
| 1325 | (unsigned long)rtlpci->rx_ring[rxring_idx].buffer_desc & 0xFF) { | 1322 | (unsigned long)rtlpci->rx_ring[rxring_idx].buffer_desc & 0xFF) { |
| 1326 | RT_TRACE(COMP_ERR, DBG_EMERG, ("Cannot allocate RX ring\n")); | 1323 | RT_TRACE(COMP_ERR, DBG_EMERG, ("Cannot allocate RX ring\n")); |
| 1327 | return -ENOMEM; | 1324 | return -ENOMEM; |
| 1328 | } | 1325 | } |
| 1329 | 1326 | ||
| 1330 | memset(rtlpci->rx_ring[rxring_idx].buffer_desc, 0, | ||
| 1331 | sizeof(*rtlpci->rx_ring[rxring_idx].buffer_desc) * | ||
| 1332 | rtlpci->rxringcount); | ||
| 1333 | |||
| 1334 | /* init every desc in this ring */ | 1327 | /* init every desc in this ring */ |
| 1335 | rtlpci->rx_ring[rxring_idx].idx = 0; | 1328 | rtlpci->rx_ring[rxring_idx].idx = 0; |
| 1336 | for (i = 0; i < rtlpci->rxringcount; i++) { | 1329 | for (i = 0; i < rtlpci->rxringcount; i++) { |
| @@ -1344,10 +1337,9 @@ static int _rtl_pci_init_rx_ring(struct ieee80211_hw *hw, int rxring_idx) | |||
| 1344 | u8 tmp_one = 1; | 1337 | u8 tmp_one = 1; |
| 1345 | /* alloc dma for this ring */ | 1338 | /* alloc dma for this ring */ |
| 1346 | rtlpci->rx_ring[rxring_idx].desc = | 1339 | rtlpci->rx_ring[rxring_idx].desc = |
| 1347 | pci_alloc_consistent(rtlpci->pdev, | 1340 | pci_zalloc_consistent(rtlpci->pdev, |
| 1348 | sizeof(*rtlpci->rx_ring[rxring_idx]. | 1341 | sizeof(*rtlpci->rx_ring[rxring_idx].desc) * rtlpci->rxringcount, |
| 1349 | desc) * rtlpci->rxringcount, | 1342 | &rtlpci->rx_ring[rxring_idx].dma); |
| 1350 | &rtlpci->rx_ring[rxring_idx].dma); | ||
| 1351 | if (!rtlpci->rx_ring[rxring_idx].desc || | 1343 | if (!rtlpci->rx_ring[rxring_idx].desc || |
| 1352 | (unsigned long)rtlpci->rx_ring[rxring_idx].desc & 0xFF) { | 1344 | (unsigned long)rtlpci->rx_ring[rxring_idx].desc & 0xFF) { |
| 1353 | RT_TRACE(COMP_ERR, DBG_EMERG, | 1345 | RT_TRACE(COMP_ERR, DBG_EMERG, |
| @@ -1355,10 +1347,6 @@ static int _rtl_pci_init_rx_ring(struct ieee80211_hw *hw, int rxring_idx) | |||
| 1355 | return -ENOMEM; | 1347 | return -ENOMEM; |
| 1356 | } | 1348 | } |
| 1357 | 1349 | ||
| 1358 | memset(rtlpci->rx_ring[rxring_idx].desc, 0, | ||
| 1359 | sizeof(*rtlpci->rx_ring[rxring_idx].desc) * | ||
| 1360 | rtlpci->rxringcount); | ||
| 1361 | |||
| 1362 | /* init every desc in this ring */ | 1350 | /* init every desc in this ring */ |
| 1363 | rtlpci->rx_ring[rxring_idx].idx = 0; | 1351 | rtlpci->rx_ring[rxring_idx].idx = 0; |
| 1364 | for (i = 0; i < rtlpci->rxringcount; i++) { | 1352 | for (i = 0; i < rtlpci->rxringcount; i++) { |
diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c index 50ece291fc6a..f35fa3dfe22c 100644 --- a/drivers/staging/slicoss/slicoss.c +++ b/drivers/staging/slicoss/slicoss.c | |||
| @@ -1191,18 +1191,15 @@ static int slic_rspqueue_init(struct adapter *adapter) | |||
| 1191 | rspq->num_pages = SLIC_RSPQ_PAGES_GB; | 1191 | rspq->num_pages = SLIC_RSPQ_PAGES_GB; |
| 1192 | 1192 | ||
| 1193 | for (i = 0; i < rspq->num_pages; i++) { | 1193 | for (i = 0; i < rspq->num_pages; i++) { |
| 1194 | rspq->vaddr[i] = pci_alloc_consistent(adapter->pcidev, | 1194 | rspq->vaddr[i] = pci_zalloc_consistent(adapter->pcidev, |
| 1195 | PAGE_SIZE, | 1195 | PAGE_SIZE, |
| 1196 | &rspq->paddr[i]); | 1196 | &rspq->paddr[i]); |
| 1197 | if (!rspq->vaddr[i]) { | 1197 | if (!rspq->vaddr[i]) { |
| 1198 | dev_err(&adapter->pcidev->dev, | 1198 | dev_err(&adapter->pcidev->dev, |
| 1199 | "pci_alloc_consistent failed\n"); | 1199 | "pci_alloc_consistent failed\n"); |
| 1200 | slic_rspqueue_free(adapter); | 1200 | slic_rspqueue_free(adapter); |
| 1201 | return -ENOMEM; | 1201 | return -ENOMEM; |
| 1202 | } | 1202 | } |
| 1203 | /* FIXME: | ||
| 1204 | * do we really need this assertions (4K PAGE_SIZE aligned addr)? */ | ||
| 1205 | memset(rspq->vaddr[i], 0, PAGE_SIZE); | ||
| 1206 | 1203 | ||
| 1207 | if (paddrh == 0) { | 1204 | if (paddrh == 0) { |
| 1208 | slic_reg32_write(&slic_regs->slic_rbar, | 1205 | slic_reg32_write(&slic_regs->slic_rbar, |
diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index c78d06eff7ea..0b583a37f5b3 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c | |||
| @@ -1111,25 +1111,17 @@ static bool device_init_rings(PSDevice pDevice) | |||
| 1111 | void *vir_pool; | 1111 | void *vir_pool; |
| 1112 | 1112 | ||
| 1113 | /*allocate all RD/TD rings a single pool*/ | 1113 | /*allocate all RD/TD rings a single pool*/ |
| 1114 | vir_pool = pci_alloc_consistent(pDevice->pcid, | 1114 | vir_pool = pci_zalloc_consistent(pDevice->pcid, |
| 1115 | pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) + | 1115 | pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) + |
| 1116 | pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) + | 1116 | pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) + |
| 1117 | pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) + | 1117 | pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) + |
| 1118 | pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc), | 1118 | pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc), |
| 1119 | &pDevice->pool_dma); | 1119 | &pDevice->pool_dma); |
| 1120 | |||
| 1121 | if (vir_pool == NULL) { | 1120 | if (vir_pool == NULL) { |
| 1122 | DBG_PRT(MSG_LEVEL_ERR, KERN_ERR "%s : allocate desc dma memory failed\n", pDevice->dev->name); | 1121 | DBG_PRT(MSG_LEVEL_ERR, KERN_ERR "%s : allocate desc dma memory failed\n", pDevice->dev->name); |
| 1123 | return false; | 1122 | return false; |
| 1124 | } | 1123 | } |
| 1125 | 1124 | ||
| 1126 | memset(vir_pool, 0, | ||
| 1127 | pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) + | ||
| 1128 | pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) + | ||
| 1129 | pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) + | ||
| 1130 | pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc) | ||
| 1131 | ); | ||
| 1132 | |||
| 1133 | pDevice->aRD0Ring = vir_pool; | 1125 | pDevice->aRD0Ring = vir_pool; |
| 1134 | pDevice->aRD1Ring = vir_pool + | 1126 | pDevice->aRD1Ring = vir_pool + |
| 1135 | pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc); | 1127 | pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc); |
| @@ -1138,13 +1130,12 @@ static bool device_init_rings(PSDevice pDevice) | |||
| 1138 | pDevice->rd1_pool_dma = pDevice->rd0_pool_dma + | 1130 | pDevice->rd1_pool_dma = pDevice->rd0_pool_dma + |
| 1139 | pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc); | 1131 | pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc); |
| 1140 | 1132 | ||
| 1141 | pDevice->tx0_bufs = pci_alloc_consistent(pDevice->pcid, | 1133 | pDevice->tx0_bufs = pci_zalloc_consistent(pDevice->pcid, |
| 1142 | pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ + | 1134 | pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ + |
| 1143 | pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ + | 1135 | pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ + |
| 1144 | CB_BEACON_BUF_SIZE + | 1136 | CB_BEACON_BUF_SIZE + |
| 1145 | CB_MAX_BUF_SIZE, | 1137 | CB_MAX_BUF_SIZE, |
| 1146 | &pDevice->tx_bufs_dma0); | 1138 | &pDevice->tx_bufs_dma0); |
| 1147 | |||
| 1148 | if (pDevice->tx0_bufs == NULL) { | 1139 | if (pDevice->tx0_bufs == NULL) { |
| 1149 | DBG_PRT(MSG_LEVEL_ERR, KERN_ERR "%s: allocate buf dma memory failed\n", pDevice->dev->name); | 1140 | DBG_PRT(MSG_LEVEL_ERR, KERN_ERR "%s: allocate buf dma memory failed\n", pDevice->dev->name); |
| 1150 | pci_free_consistent(pDevice->pcid, | 1141 | pci_free_consistent(pDevice->pcid, |
| @@ -1157,13 +1148,6 @@ static bool device_init_rings(PSDevice pDevice) | |||
| 1157 | return false; | 1148 | return false; |
| 1158 | } | 1149 | } |
| 1159 | 1150 | ||
| 1160 | memset(pDevice->tx0_bufs, 0, | ||
| 1161 | pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ + | ||
| 1162 | pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ + | ||
| 1163 | CB_BEACON_BUF_SIZE + | ||
| 1164 | CB_MAX_BUF_SIZE | ||
| 1165 | ); | ||
| 1166 | |||
| 1167 | pDevice->td0_pool_dma = pDevice->rd1_pool_dma + | 1151 | pDevice->td0_pool_dma = pDevice->rd1_pool_dma + |
| 1168 | pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc); | 1152 | pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc); |
| 1169 | 1153 | ||
diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c index ba1dbcdf4609..0e8c39b6ccd4 100644 --- a/drivers/tty/synclink_gt.c +++ b/drivers/tty/synclink_gt.c | |||
| @@ -3383,12 +3383,11 @@ static int alloc_desc(struct slgt_info *info) | |||
| 3383 | unsigned int pbufs; | 3383 | unsigned int pbufs; |
| 3384 | 3384 | ||
| 3385 | /* allocate memory to hold descriptor lists */ | 3385 | /* allocate memory to hold descriptor lists */ |
| 3386 | info->bufs = pci_alloc_consistent(info->pdev, DESC_LIST_SIZE, &info->bufs_dma_addr); | 3386 | info->bufs = pci_zalloc_consistent(info->pdev, DESC_LIST_SIZE, |
| 3387 | &info->bufs_dma_addr); | ||
| 3387 | if (info->bufs == NULL) | 3388 | if (info->bufs == NULL) |
| 3388 | return -ENOMEM; | 3389 | return -ENOMEM; |
| 3389 | 3390 | ||
| 3390 | memset(info->bufs, 0, DESC_LIST_SIZE); | ||
| 3391 | |||
| 3392 | info->rbufs = (struct slgt_desc*)info->bufs; | 3391 | info->rbufs = (struct slgt_desc*)info->bufs; |
| 3393 | info->tbufs = ((struct slgt_desc*)info->bufs) + info->rbuf_count; | 3392 | info->tbufs = ((struct slgt_desc*)info->bufs) + info->rbuf_count; |
| 3394 | 3393 | ||
diff --git a/drivers/vme/bridges/vme_ca91cx42.c b/drivers/vme/bridges/vme_ca91cx42.c index bfb2d3f06738..18078ecbfcc6 100644 --- a/drivers/vme/bridges/vme_ca91cx42.c +++ b/drivers/vme/bridges/vme_ca91cx42.c | |||
| @@ -1555,16 +1555,14 @@ static int ca91cx42_crcsr_init(struct vme_bridge *ca91cx42_bridge, | |||
| 1555 | } | 1555 | } |
| 1556 | 1556 | ||
| 1557 | /* Allocate mem for CR/CSR image */ | 1557 | /* Allocate mem for CR/CSR image */ |
| 1558 | bridge->crcsr_kernel = pci_alloc_consistent(pdev, VME_CRCSR_BUF_SIZE, | 1558 | bridge->crcsr_kernel = pci_zalloc_consistent(pdev, VME_CRCSR_BUF_SIZE, |
| 1559 | &bridge->crcsr_bus); | 1559 | &bridge->crcsr_bus); |
| 1560 | if (bridge->crcsr_kernel == NULL) { | 1560 | if (bridge->crcsr_kernel == NULL) { |
| 1561 | dev_err(&pdev->dev, "Failed to allocate memory for CR/CSR " | 1561 | dev_err(&pdev->dev, "Failed to allocate memory for CR/CSR " |
| 1562 | "image\n"); | 1562 | "image\n"); |
| 1563 | return -ENOMEM; | 1563 | return -ENOMEM; |
| 1564 | } | 1564 | } |
| 1565 | 1565 | ||
| 1566 | memset(bridge->crcsr_kernel, 0, VME_CRCSR_BUF_SIZE); | ||
| 1567 | |||
| 1568 | crcsr_addr = slot * (512 * 1024); | 1566 | crcsr_addr = slot * (512 * 1024); |
| 1569 | iowrite32(bridge->crcsr_bus - crcsr_addr, bridge->base + VCSR_TO); | 1567 | iowrite32(bridge->crcsr_bus - crcsr_addr, bridge->base + VCSR_TO); |
| 1570 | 1568 | ||
diff --git a/drivers/vme/bridges/vme_tsi148.c b/drivers/vme/bridges/vme_tsi148.c index 61e706c0e00c..e07cfa8001bb 100644 --- a/drivers/vme/bridges/vme_tsi148.c +++ b/drivers/vme/bridges/vme_tsi148.c | |||
| @@ -2275,16 +2275,14 @@ static int tsi148_crcsr_init(struct vme_bridge *tsi148_bridge, | |||
| 2275 | bridge = tsi148_bridge->driver_priv; | 2275 | bridge = tsi148_bridge->driver_priv; |
| 2276 | 2276 | ||
| 2277 | /* Allocate mem for CR/CSR image */ | 2277 | /* Allocate mem for CR/CSR image */ |
| 2278 | bridge->crcsr_kernel = pci_alloc_consistent(pdev, VME_CRCSR_BUF_SIZE, | 2278 | bridge->crcsr_kernel = pci_zalloc_consistent(pdev, VME_CRCSR_BUF_SIZE, |
| 2279 | &bridge->crcsr_bus); | 2279 | &bridge->crcsr_bus); |
| 2280 | if (bridge->crcsr_kernel == NULL) { | 2280 | if (bridge->crcsr_kernel == NULL) { |
| 2281 | dev_err(tsi148_bridge->parent, "Failed to allocate memory for " | 2281 | dev_err(tsi148_bridge->parent, "Failed to allocate memory for " |
| 2282 | "CR/CSR image\n"); | 2282 | "CR/CSR image\n"); |
| 2283 | return -ENOMEM; | 2283 | return -ENOMEM; |
| 2284 | } | 2284 | } |
| 2285 | 2285 | ||
| 2286 | memset(bridge->crcsr_kernel, 0, VME_CRCSR_BUF_SIZE); | ||
| 2287 | |||
| 2288 | reg_split(bridge->crcsr_bus, &crcsr_bus_high, &crcsr_bus_low); | 2286 | reg_split(bridge->crcsr_bus, &crcsr_bus_high, &crcsr_bus_low); |
| 2289 | 2287 | ||
| 2290 | iowrite32be(crcsr_bus_high, bridge->base + TSI148_LCSR_CROU); | 2288 | iowrite32be(crcsr_bus_high, bridge->base + TSI148_LCSR_CROU); |
diff --git a/fs/adfs/adfs.h b/fs/adfs/adfs.h index c770337c4b45..24575d9d882d 100644 --- a/fs/adfs/adfs.h +++ b/fs/adfs/adfs.h | |||
| @@ -153,6 +153,7 @@ extern int adfs_map_lookup(struct super_block *sb, unsigned int frag_id, unsigne | |||
| 153 | extern unsigned int adfs_map_free(struct super_block *sb); | 153 | extern unsigned int adfs_map_free(struct super_block *sb); |
| 154 | 154 | ||
| 155 | /* Misc */ | 155 | /* Misc */ |
| 156 | __printf(3, 4) | ||
| 156 | void __adfs_error(struct super_block *sb, const char *function, | 157 | void __adfs_error(struct super_block *sb, const char *function, |
| 157 | const char *fmt, ...); | 158 | const char *fmt, ...); |
| 158 | #define adfs_error(sb, fmt...) __adfs_error(sb, __func__, fmt) | 159 | #define adfs_error(sb, fmt...) __adfs_error(sb, __func__, fmt) |
diff --git a/fs/adfs/dir.c b/fs/adfs/dir.c index 0d138c0de293..51c279a29845 100644 --- a/fs/adfs/dir.c +++ b/fs/adfs/dir.c | |||
| @@ -138,7 +138,7 @@ adfs_dir_lookup_byname(struct inode *inode, struct qstr *name, struct object_inf | |||
| 138 | goto out; | 138 | goto out; |
| 139 | 139 | ||
| 140 | if (ADFS_I(inode)->parent_id != dir.parent_id) { | 140 | if (ADFS_I(inode)->parent_id != dir.parent_id) { |
| 141 | adfs_error(sb, "parent directory changed under me! (%lx but got %lx)\n", | 141 | adfs_error(sb, "parent directory changed under me! (%lx but got %x)\n", |
| 142 | ADFS_I(inode)->parent_id, dir.parent_id); | 142 | ADFS_I(inode)->parent_id, dir.parent_id); |
| 143 | ret = -EIO; | 143 | ret = -EIO; |
| 144 | goto free_out; | 144 | goto free_out; |
diff --git a/fs/adfs/dir_fplus.c b/fs/adfs/dir_fplus.c index d9e3bee4e653..f2ba88ab4aed 100644 --- a/fs/adfs/dir_fplus.c +++ b/fs/adfs/dir_fplus.c | |||
| @@ -55,10 +55,10 @@ adfs_fplus_read(struct super_block *sb, unsigned int id, unsigned int sz, struct | |||
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | size >>= sb->s_blocksize_bits; | 57 | size >>= sb->s_blocksize_bits; |
| 58 | if (size > sizeof(dir->bh)/sizeof(dir->bh[0])) { | 58 | if (size > ARRAY_SIZE(dir->bh)) { |
| 59 | /* this directory is too big for fixed bh set, must allocate */ | 59 | /* this directory is too big for fixed bh set, must allocate */ |
| 60 | struct buffer_head **bh_fplus = | 60 | struct buffer_head **bh_fplus = |
| 61 | kzalloc(size * sizeof(struct buffer_head *), | 61 | kcalloc(size, sizeof(struct buffer_head *), |
| 62 | GFP_KERNEL); | 62 | GFP_KERNEL); |
| 63 | if (!bh_fplus) { | 63 | if (!bh_fplus) { |
| 64 | adfs_error(sb, "not enough memory for" | 64 | adfs_error(sb, "not enough memory for" |
| @@ -79,9 +79,8 @@ adfs_fplus_read(struct super_block *sb, unsigned int id, unsigned int sz, struct | |||
| 79 | 79 | ||
| 80 | dir->bh_fplus[blk] = sb_bread(sb, block); | 80 | dir->bh_fplus[blk] = sb_bread(sb, block); |
| 81 | if (!dir->bh_fplus[blk]) { | 81 | if (!dir->bh_fplus[blk]) { |
| 82 | adfs_error(sb, "dir object %X failed read for" | 82 | adfs_error(sb, "dir object %x failed read for offset %d, mapped block %lX", |
| 83 | " offset %d, mapped block %X", | 83 | id, blk, block); |
| 84 | id, blk, block); | ||
| 85 | goto out; | 84 | goto out; |
| 86 | } | 85 | } |
| 87 | 86 | ||
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index acf32054edd8..9e359fb20c0a 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h | |||
| @@ -143,20 +143,6 @@ static inline int autofs4_oz_mode(struct autofs_sb_info *sbi) { | |||
| 143 | return sbi->catatonic || task_pgrp(current) == sbi->oz_pgrp; | 143 | return sbi->catatonic || task_pgrp(current) == sbi->oz_pgrp; |
| 144 | } | 144 | } |
| 145 | 145 | ||
| 146 | /* Does a dentry have some pending activity? */ | ||
| 147 | static inline int autofs4_ispending(struct dentry *dentry) | ||
| 148 | { | ||
| 149 | struct autofs_info *inf = autofs4_dentry_ino(dentry); | ||
| 150 | |||
| 151 | if (inf->flags & AUTOFS_INF_PENDING) | ||
| 152 | return 1; | ||
| 153 | |||
| 154 | if (inf->flags & AUTOFS_INF_EXPIRING) | ||
| 155 | return 1; | ||
| 156 | |||
| 157 | return 0; | ||
| 158 | } | ||
| 159 | |||
| 160 | struct inode *autofs4_get_inode(struct super_block *, umode_t); | 146 | struct inode *autofs4_get_inode(struct super_block *, umode_t); |
| 161 | void autofs4_free_ino(struct autofs_info *); | 147 | void autofs4_free_ino(struct autofs_info *); |
| 162 | 148 | ||
| @@ -191,55 +177,6 @@ extern const struct file_operations autofs4_root_operations; | |||
| 191 | extern const struct dentry_operations autofs4_dentry_operations; | 177 | extern const struct dentry_operations autofs4_dentry_operations; |
| 192 | 178 | ||
| 193 | /* VFS automount flags management functions */ | 179 | /* VFS automount flags management functions */ |
| 194 | |||
| 195 | static inline void __managed_dentry_set_automount(struct dentry *dentry) | ||
| 196 | { | ||
| 197 | dentry->d_flags |= DCACHE_NEED_AUTOMOUNT; | ||
| 198 | } | ||
| 199 | |||
| 200 | static inline void managed_dentry_set_automount(struct dentry *dentry) | ||
| 201 | { | ||
| 202 | spin_lock(&dentry->d_lock); | ||
| 203 | __managed_dentry_set_automount(dentry); | ||
| 204 | spin_unlock(&dentry->d_lock); | ||
| 205 | } | ||
| 206 | |||
| 207 | static inline void __managed_dentry_clear_automount(struct dentry *dentry) | ||
| 208 | { | ||
| 209 | dentry->d_flags &= ~DCACHE_NEED_AUTOMOUNT; | ||
| 210 | } | ||
| 211 | |||
| 212 | static inline void managed_dentry_clear_automount(struct dentry *dentry) | ||
| 213 | { | ||
| 214 | spin_lock(&dentry->d_lock); | ||
| 215 | __managed_dentry_clear_automount(dentry); | ||
| 216 | spin_unlock(&dentry->d_lock); | ||
| 217 | } | ||
| 218 | |||
| 219 | static inline void __managed_dentry_set_transit(struct dentry *dentry) | ||
| 220 | { | ||
| 221 | dentry->d_flags |= DCACHE_MANAGE_TRANSIT; | ||
| 222 | } | ||
| 223 | |||
| 224 | static inline void managed_dentry_set_transit(struct dentry *dentry) | ||
| 225 | { | ||
| 226 | spin_lock(&dentry->d_lock); | ||
| 227 | __managed_dentry_set_transit(dentry); | ||
| 228 | spin_unlock(&dentry->d_lock); | ||
| 229 | } | ||
| 230 | |||
| 231 | static inline void __managed_dentry_clear_transit(struct dentry *dentry) | ||
| 232 | { | ||
| 233 | dentry->d_flags &= ~DCACHE_MANAGE_TRANSIT; | ||
| 234 | } | ||
| 235 | |||
| 236 | static inline void managed_dentry_clear_transit(struct dentry *dentry) | ||
| 237 | { | ||
| 238 | spin_lock(&dentry->d_lock); | ||
| 239 | __managed_dentry_clear_transit(dentry); | ||
| 240 | spin_unlock(&dentry->d_lock); | ||
| 241 | } | ||
| 242 | |||
| 243 | static inline void __managed_dentry_set_managed(struct dentry *dentry) | 180 | static inline void __managed_dentry_set_managed(struct dentry *dentry) |
| 244 | { | 181 | { |
| 245 | dentry->d_flags |= (DCACHE_NEED_AUTOMOUNT|DCACHE_MANAGE_TRANSIT); | 182 | dentry->d_flags |= (DCACHE_NEED_AUTOMOUNT|DCACHE_MANAGE_TRANSIT); |
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c index 394e90b02c5e..a7be57e39be7 100644 --- a/fs/autofs4/expire.c +++ b/fs/autofs4/expire.c | |||
| @@ -333,7 +333,6 @@ struct dentry *autofs4_expire_direct(struct super_block *sb, | |||
| 333 | if (ino->flags & AUTOFS_INF_PENDING) | 333 | if (ino->flags & AUTOFS_INF_PENDING) |
| 334 | goto out; | 334 | goto out; |
| 335 | if (!autofs4_direct_busy(mnt, root, timeout, do_now)) { | 335 | if (!autofs4_direct_busy(mnt, root, timeout, do_now)) { |
| 336 | struct autofs_info *ino = autofs4_dentry_ino(root); | ||
| 337 | ino->flags |= AUTOFS_INF_EXPIRING; | 336 | ino->flags |= AUTOFS_INF_EXPIRING; |
| 338 | init_completion(&ino->expire_complete); | 337 | init_completion(&ino->expire_complete); |
| 339 | spin_unlock(&sbi->fs_lock); | 338 | spin_unlock(&sbi->fs_lock); |
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index cc87c1abac97..cdb25ebccc4c 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c | |||
| @@ -166,8 +166,10 @@ static struct dentry *autofs4_lookup_active(struct dentry *dentry) | |||
| 166 | const unsigned char *str = name->name; | 166 | const unsigned char *str = name->name; |
| 167 | struct list_head *p, *head; | 167 | struct list_head *p, *head; |
| 168 | 168 | ||
| 169 | spin_lock(&sbi->lookup_lock); | ||
| 170 | head = &sbi->active_list; | 169 | head = &sbi->active_list; |
| 170 | if (list_empty(head)) | ||
| 171 | return NULL; | ||
| 172 | spin_lock(&sbi->lookup_lock); | ||
| 171 | list_for_each(p, head) { | 173 | list_for_each(p, head) { |
| 172 | struct autofs_info *ino; | 174 | struct autofs_info *ino; |
| 173 | struct dentry *active; | 175 | struct dentry *active; |
| @@ -218,8 +220,10 @@ static struct dentry *autofs4_lookup_expiring(struct dentry *dentry) | |||
| 218 | const unsigned char *str = name->name; | 220 | const unsigned char *str = name->name; |
| 219 | struct list_head *p, *head; | 221 | struct list_head *p, *head; |
| 220 | 222 | ||
| 221 | spin_lock(&sbi->lookup_lock); | ||
| 222 | head = &sbi->expiring_list; | 223 | head = &sbi->expiring_list; |
| 224 | if (list_empty(head)) | ||
| 225 | return NULL; | ||
| 226 | spin_lock(&sbi->lookup_lock); | ||
| 223 | list_for_each(p, head) { | 227 | list_for_each(p, head) { |
| 224 | struct autofs_info *ino; | 228 | struct autofs_info *ino; |
| 225 | struct dentry *expiring; | 229 | struct dentry *expiring; |
| @@ -373,7 +377,7 @@ static struct vfsmount *autofs4_d_automount(struct path *path) | |||
| 373 | * this because the leaves of the directory tree under the | 377 | * this because the leaves of the directory tree under the |
| 374 | * mount never trigger mounts themselves (they have an autofs | 378 | * mount never trigger mounts themselves (they have an autofs |
| 375 | * trigger mount mounted on them). But v4 pseudo direct mounts | 379 | * trigger mount mounted on them). But v4 pseudo direct mounts |
| 376 | * do need the leaves to to trigger mounts. In this case we | 380 | * do need the leaves to trigger mounts. In this case we |
| 377 | * have no choice but to use the list_empty() check and | 381 | * have no choice but to use the list_empty() check and |
| 378 | * require user space behave. | 382 | * require user space behave. |
| 379 | */ | 383 | */ |
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index 0d6c07cc1149..4cf61ec6b7a8 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c | |||
| @@ -832,16 +832,14 @@ befs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 832 | (befs_super_block *) ((void *) bh->b_data + x86_sb_off); | 832 | (befs_super_block *) ((void *) bh->b_data + x86_sb_off); |
| 833 | } | 833 | } |
| 834 | 834 | ||
| 835 | if (befs_load_sb(sb, disk_sb) != BEFS_OK) | 835 | if ((befs_load_sb(sb, disk_sb) != BEFS_OK) || |
| 836 | (befs_check_sb(sb) != BEFS_OK)) | ||
| 836 | goto unacquire_bh; | 837 | goto unacquire_bh; |
| 837 | 838 | ||
| 838 | befs_dump_super_block(sb, disk_sb); | 839 | befs_dump_super_block(sb, disk_sb); |
| 839 | 840 | ||
| 840 | brelse(bh); | 841 | brelse(bh); |
| 841 | 842 | ||
| 842 | if (befs_check_sb(sb) != BEFS_OK) | ||
| 843 | goto unacquire_priv_sbp; | ||
| 844 | |||
| 845 | if( befs_sb->num_blocks > ~((sector_t)0) ) { | 843 | if( befs_sb->num_blocks > ~((sector_t)0) ) { |
| 846 | befs_error(sb, "blocks count: %llu " | 844 | befs_error(sb, "blocks count: %llu " |
| 847 | "is larger than the host can use", | 845 | "is larger than the host can use", |
diff --git a/fs/bfs/bfs.h b/fs/bfs/bfs.h index f7f87e233dd9..f40006db36df 100644 --- a/fs/bfs/bfs.h +++ b/fs/bfs/bfs.h | |||
| @@ -46,6 +46,7 @@ static inline struct bfs_inode_info *BFS_I(struct inode *inode) | |||
| 46 | 46 | ||
| 47 | /* inode.c */ | 47 | /* inode.c */ |
| 48 | extern struct inode *bfs_iget(struct super_block *sb, unsigned long ino); | 48 | extern struct inode *bfs_iget(struct super_block *sb, unsigned long ino); |
| 49 | extern void bfs_dump_imap(const char *, struct super_block *); | ||
| 49 | 50 | ||
| 50 | /* file.c */ | 51 | /* file.c */ |
| 51 | extern const struct inode_operations bfs_file_inops; | 52 | extern const struct inode_operations bfs_file_inops; |
diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c index a399e6d9dc74..08063ae0a17c 100644 --- a/fs/bfs/dir.c +++ b/fs/bfs/dir.c | |||
| @@ -75,8 +75,6 @@ const struct file_operations bfs_dir_operations = { | |||
| 75 | .llseek = generic_file_llseek, | 75 | .llseek = generic_file_llseek, |
| 76 | }; | 76 | }; |
| 77 | 77 | ||
| 78 | extern void dump_imap(const char *, struct super_block *); | ||
| 79 | |||
| 80 | static int bfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, | 78 | static int bfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, |
| 81 | bool excl) | 79 | bool excl) |
| 82 | { | 80 | { |
| @@ -110,7 +108,7 @@ static int bfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, | |||
| 110 | BFS_I(inode)->i_eblock = 0; | 108 | BFS_I(inode)->i_eblock = 0; |
| 111 | insert_inode_hash(inode); | 109 | insert_inode_hash(inode); |
| 112 | mark_inode_dirty(inode); | 110 | mark_inode_dirty(inode); |
| 113 | dump_imap("create", s); | 111 | bfs_dump_imap("create", s); |
| 114 | 112 | ||
| 115 | err = bfs_add_entry(dir, dentry->d_name.name, dentry->d_name.len, | 113 | err = bfs_add_entry(dir, dentry->d_name.name, dentry->d_name.len, |
| 116 | inode->i_ino); | 114 | inode->i_ino); |
diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c index 7041ac35ace8..90bc079d9982 100644 --- a/fs/bfs/inode.c +++ b/fs/bfs/inode.c | |||
| @@ -30,8 +30,6 @@ MODULE_LICENSE("GPL"); | |||
| 30 | #define dprintf(x...) | 30 | #define dprintf(x...) |
| 31 | #endif | 31 | #endif |
| 32 | 32 | ||
| 33 | void dump_imap(const char *prefix, struct super_block *s); | ||
| 34 | |||
| 35 | struct inode *bfs_iget(struct super_block *sb, unsigned long ino) | 33 | struct inode *bfs_iget(struct super_block *sb, unsigned long ino) |
| 36 | { | 34 | { |
| 37 | struct bfs_inode *di; | 35 | struct bfs_inode *di; |
| @@ -194,7 +192,7 @@ static void bfs_evict_inode(struct inode *inode) | |||
| 194 | info->si_freeb += bi->i_eblock + 1 - bi->i_sblock; | 192 | info->si_freeb += bi->i_eblock + 1 - bi->i_sblock; |
| 195 | info->si_freei++; | 193 | info->si_freei++; |
| 196 | clear_bit(ino, info->si_imap); | 194 | clear_bit(ino, info->si_imap); |
| 197 | dump_imap("delete_inode", s); | 195 | bfs_dump_imap("delete_inode", s); |
| 198 | } | 196 | } |
| 199 | 197 | ||
| 200 | /* | 198 | /* |
| @@ -297,7 +295,7 @@ static const struct super_operations bfs_sops = { | |||
| 297 | .statfs = bfs_statfs, | 295 | .statfs = bfs_statfs, |
| 298 | }; | 296 | }; |
| 299 | 297 | ||
| 300 | void dump_imap(const char *prefix, struct super_block *s) | 298 | void bfs_dump_imap(const char *prefix, struct super_block *s) |
| 301 | { | 299 | { |
| 302 | #ifdef DEBUG | 300 | #ifdef DEBUG |
| 303 | int i; | 301 | int i; |
| @@ -443,7 +441,7 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent) | |||
| 443 | } | 441 | } |
| 444 | brelse(bh); | 442 | brelse(bh); |
| 445 | brelse(sbh); | 443 | brelse(sbh); |
| 446 | dump_imap("read_super", s); | 444 | bfs_dump_imap("read_super", s); |
| 447 | return 0; | 445 | return 0; |
| 448 | 446 | ||
| 449 | out3: | 447 | out3: |
diff --git a/fs/coda/cache.c b/fs/coda/cache.c index 1da168c61d35..278f8fdeb9ef 100644 --- a/fs/coda/cache.c +++ b/fs/coda/cache.c | |||
| @@ -13,7 +13,7 @@ | |||
| 13 | #include <linux/fs.h> | 13 | #include <linux/fs.h> |
| 14 | #include <linux/stat.h> | 14 | #include <linux/stat.h> |
| 15 | #include <linux/errno.h> | 15 | #include <linux/errno.h> |
| 16 | #include <asm/uaccess.h> | 16 | #include <linux/uaccess.h> |
| 17 | #include <linux/string.h> | 17 | #include <linux/string.h> |
| 18 | #include <linux/list.h> | 18 | #include <linux/list.h> |
| 19 | #include <linux/sched.h> | 19 | #include <linux/sched.h> |
diff --git a/fs/coda/coda_linux.c b/fs/coda/coda_linux.c index 2849f41e72a2..1326d38960db 100644 --- a/fs/coda/coda_linux.c +++ b/fs/coda/coda_linux.c | |||
| @@ -13,7 +13,7 @@ | |||
| 13 | #include <linux/fs.h> | 13 | #include <linux/fs.h> |
| 14 | #include <linux/stat.h> | 14 | #include <linux/stat.h> |
| 15 | #include <linux/errno.h> | 15 | #include <linux/errno.h> |
| 16 | #include <asm/uaccess.h> | 16 | #include <linux/uaccess.h> |
| 17 | #include <linux/string.h> | 17 | #include <linux/string.h> |
| 18 | 18 | ||
| 19 | #include <linux/coda.h> | 19 | #include <linux/coda.h> |
diff --git a/fs/coda/dir.c b/fs/coda/dir.c index cd8a63238b11..9c3dedc000d1 100644 --- a/fs/coda/dir.c +++ b/fs/coda/dir.c | |||
| @@ -19,8 +19,7 @@ | |||
| 19 | #include <linux/string.h> | 19 | #include <linux/string.h> |
| 20 | #include <linux/spinlock.h> | 20 | #include <linux/spinlock.h> |
| 21 | #include <linux/namei.h> | 21 | #include <linux/namei.h> |
| 22 | 22 | #include <linux/uaccess.h> | |
| 23 | #include <asm/uaccess.h> | ||
| 24 | 23 | ||
| 25 | #include <linux/coda.h> | 24 | #include <linux/coda.h> |
| 26 | #include <linux/coda_psdev.h> | 25 | #include <linux/coda_psdev.h> |
diff --git a/fs/coda/file.c b/fs/coda/file.c index 9e83b7790212..d244d743a232 100644 --- a/fs/coda/file.c +++ b/fs/coda/file.c | |||
| @@ -18,7 +18,7 @@ | |||
| 18 | #include <linux/spinlock.h> | 18 | #include <linux/spinlock.h> |
| 19 | #include <linux/string.h> | 19 | #include <linux/string.h> |
| 20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
| 21 | #include <asm/uaccess.h> | 21 | #include <linux/uaccess.h> |
| 22 | 22 | ||
| 23 | #include <linux/coda.h> | 23 | #include <linux/coda.h> |
| 24 | #include <linux/coda_psdev.h> | 24 | #include <linux/coda_psdev.h> |
diff --git a/fs/coda/inode.c b/fs/coda/inode.c index fe3afb2de880..b945410bfcd5 100644 --- a/fs/coda/inode.c +++ b/fs/coda/inode.c | |||
| @@ -21,9 +21,7 @@ | |||
| 21 | #include <linux/vfs.h> | 21 | #include <linux/vfs.h> |
| 22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
| 23 | #include <linux/pid_namespace.h> | 23 | #include <linux/pid_namespace.h> |
| 24 | 24 | #include <linux/uaccess.h> | |
| 25 | #include <asm/uaccess.h> | ||
| 26 | |||
| 27 | #include <linux/fs.h> | 25 | #include <linux/fs.h> |
| 28 | #include <linux/vmalloc.h> | 26 | #include <linux/vmalloc.h> |
| 29 | 27 | ||
diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c index 3f5de96bbb58..4326d172fc27 100644 --- a/fs/coda/pioctl.c +++ b/fs/coda/pioctl.c | |||
| @@ -16,7 +16,7 @@ | |||
| 16 | #include <linux/string.h> | 16 | #include <linux/string.h> |
| 17 | #include <linux/namei.h> | 17 | #include <linux/namei.h> |
| 18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
| 19 | #include <asm/uaccess.h> | 19 | #include <linux/uaccess.h> |
| 20 | 20 | ||
| 21 | #include <linux/coda.h> | 21 | #include <linux/coda.h> |
| 22 | #include <linux/coda_psdev.h> | 22 | #include <linux/coda_psdev.h> |
diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c index 5c1e4242368b..822629126e89 100644 --- a/fs/coda/psdev.c +++ b/fs/coda/psdev.c | |||
| @@ -40,7 +40,7 @@ | |||
| 40 | #include <linux/pid_namespace.h> | 40 | #include <linux/pid_namespace.h> |
| 41 | #include <asm/io.h> | 41 | #include <asm/io.h> |
| 42 | #include <asm/poll.h> | 42 | #include <asm/poll.h> |
| 43 | #include <asm/uaccess.h> | 43 | #include <linux/uaccess.h> |
| 44 | 44 | ||
| 45 | #include <linux/coda.h> | 45 | #include <linux/coda.h> |
| 46 | #include <linux/coda_psdev.h> | 46 | #include <linux/coda_psdev.h> |
diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c index 21fcf8dcb9cd..5bb6e27298a4 100644 --- a/fs/coda/upcall.c +++ b/fs/coda/upcall.c | |||
| @@ -27,7 +27,7 @@ | |||
| 27 | #include <linux/string.h> | 27 | #include <linux/string.h> |
| 28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
| 29 | #include <linux/mutex.h> | 29 | #include <linux/mutex.h> |
| 30 | #include <asm/uaccess.h> | 30 | #include <linux/uaccess.h> |
| 31 | #include <linux/vmalloc.h> | 31 | #include <linux/vmalloc.h> |
| 32 | #include <linux/vfs.h> | 32 | #include <linux/vfs.h> |
| 33 | 33 | ||
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c index ddcfe590b8a8..355c522f3585 100644 --- a/fs/cramfs/inode.c +++ b/fs/cramfs/inode.c | |||
| @@ -11,6 +11,8 @@ | |||
| 11 | * The actual compression is based on zlib, see the other files. | 11 | * The actual compression is based on zlib, see the other files. |
| 12 | */ | 12 | */ |
| 13 | 13 | ||
| 14 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 15 | |||
| 14 | #include <linux/module.h> | 16 | #include <linux/module.h> |
| 15 | #include <linux/fs.h> | 17 | #include <linux/fs.h> |
| 16 | #include <linux/pagemap.h> | 18 | #include <linux/pagemap.h> |
| @@ -21,7 +23,7 @@ | |||
| 21 | #include <linux/vfs.h> | 23 | #include <linux/vfs.h> |
| 22 | #include <linux/mutex.h> | 24 | #include <linux/mutex.h> |
| 23 | #include <uapi/linux/cramfs_fs.h> | 25 | #include <uapi/linux/cramfs_fs.h> |
| 24 | #include <asm/uaccess.h> | 26 | #include <linux/uaccess.h> |
| 25 | 27 | ||
| 26 | #include "internal.h" | 28 | #include "internal.h" |
| 27 | 29 | ||
| @@ -153,7 +155,7 @@ static struct inode *get_cramfs_inode(struct super_block *sb, | |||
| 153 | 155 | ||
| 154 | static unsigned char read_buffers[READ_BUFFERS][BUFFER_SIZE]; | 156 | static unsigned char read_buffers[READ_BUFFERS][BUFFER_SIZE]; |
| 155 | static unsigned buffer_blocknr[READ_BUFFERS]; | 157 | static unsigned buffer_blocknr[READ_BUFFERS]; |
| 156 | static struct super_block * buffer_dev[READ_BUFFERS]; | 158 | static struct super_block *buffer_dev[READ_BUFFERS]; |
| 157 | static int next_buffer; | 159 | static int next_buffer; |
| 158 | 160 | ||
| 159 | /* | 161 | /* |
| @@ -205,6 +207,7 @@ static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned i | |||
| 205 | 207 | ||
| 206 | for (i = 0; i < BLKS_PER_BUF; i++) { | 208 | for (i = 0; i < BLKS_PER_BUF; i++) { |
| 207 | struct page *page = pages[i]; | 209 | struct page *page = pages[i]; |
| 210 | |||
| 208 | if (page) { | 211 | if (page) { |
| 209 | wait_on_page_locked(page); | 212 | wait_on_page_locked(page); |
| 210 | if (!PageUptodate(page)) { | 213 | if (!PageUptodate(page)) { |
| @@ -223,6 +226,7 @@ static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned i | |||
| 223 | data = read_buffers[buffer]; | 226 | data = read_buffers[buffer]; |
| 224 | for (i = 0; i < BLKS_PER_BUF; i++) { | 227 | for (i = 0; i < BLKS_PER_BUF; i++) { |
| 225 | struct page *page = pages[i]; | 228 | struct page *page = pages[i]; |
| 229 | |||
| 226 | if (page) { | 230 | if (page) { |
| 227 | memcpy(data, kmap(page), PAGE_CACHE_SIZE); | 231 | memcpy(data, kmap(page), PAGE_CACHE_SIZE); |
| 228 | kunmap(page); | 232 | kunmap(page); |
| @@ -237,6 +241,7 @@ static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned i | |||
| 237 | static void cramfs_kill_sb(struct super_block *sb) | 241 | static void cramfs_kill_sb(struct super_block *sb) |
| 238 | { | 242 | { |
| 239 | struct cramfs_sb_info *sbi = CRAMFS_SB(sb); | 243 | struct cramfs_sb_info *sbi = CRAMFS_SB(sb); |
| 244 | |||
| 240 | kill_block_super(sb); | 245 | kill_block_super(sb); |
| 241 | kfree(sbi); | 246 | kfree(sbi); |
| 242 | } | 247 | } |
| @@ -277,7 +282,7 @@ static int cramfs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 277 | /* check for wrong endianness */ | 282 | /* check for wrong endianness */ |
| 278 | if (super.magic == CRAMFS_MAGIC_WEND) { | 283 | if (super.magic == CRAMFS_MAGIC_WEND) { |
| 279 | if (!silent) | 284 | if (!silent) |
| 280 | printk(KERN_ERR "cramfs: wrong endianness\n"); | 285 | pr_err("wrong endianness\n"); |
| 281 | return -EINVAL; | 286 | return -EINVAL; |
| 282 | } | 287 | } |
| 283 | 288 | ||
| @@ -287,22 +292,22 @@ static int cramfs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 287 | mutex_unlock(&read_mutex); | 292 | mutex_unlock(&read_mutex); |
| 288 | if (super.magic != CRAMFS_MAGIC) { | 293 | if (super.magic != CRAMFS_MAGIC) { |
| 289 | if (super.magic == CRAMFS_MAGIC_WEND && !silent) | 294 | if (super.magic == CRAMFS_MAGIC_WEND && !silent) |
| 290 | printk(KERN_ERR "cramfs: wrong endianness\n"); | 295 | pr_err("wrong endianness\n"); |
| 291 | else if (!silent) | 296 | else if (!silent) |
| 292 | printk(KERN_ERR "cramfs: wrong magic\n"); | 297 | pr_err("wrong magic\n"); |
| 293 | return -EINVAL; | 298 | return -EINVAL; |
| 294 | } | 299 | } |
| 295 | } | 300 | } |
| 296 | 301 | ||
| 297 | /* get feature flags first */ | 302 | /* get feature flags first */ |
| 298 | if (super.flags & ~CRAMFS_SUPPORTED_FLAGS) { | 303 | if (super.flags & ~CRAMFS_SUPPORTED_FLAGS) { |
| 299 | printk(KERN_ERR "cramfs: unsupported filesystem features\n"); | 304 | pr_err("unsupported filesystem features\n"); |
| 300 | return -EINVAL; | 305 | return -EINVAL; |
| 301 | } | 306 | } |
| 302 | 307 | ||
| 303 | /* Check that the root inode is in a sane state */ | 308 | /* Check that the root inode is in a sane state */ |
| 304 | if (!S_ISDIR(super.root.mode)) { | 309 | if (!S_ISDIR(super.root.mode)) { |
| 305 | printk(KERN_ERR "cramfs: root is not a directory\n"); | 310 | pr_err("root is not a directory\n"); |
| 306 | return -EINVAL; | 311 | return -EINVAL; |
| 307 | } | 312 | } |
| 308 | /* correct strange, hard-coded permissions of mkcramfs */ | 313 | /* correct strange, hard-coded permissions of mkcramfs */ |
| @@ -310,23 +315,23 @@ static int cramfs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 310 | 315 | ||
| 311 | root_offset = super.root.offset << 2; | 316 | root_offset = super.root.offset << 2; |
| 312 | if (super.flags & CRAMFS_FLAG_FSID_VERSION_2) { | 317 | if (super.flags & CRAMFS_FLAG_FSID_VERSION_2) { |
| 313 | sbi->size=super.size; | 318 | sbi->size = super.size; |
| 314 | sbi->blocks=super.fsid.blocks; | 319 | sbi->blocks = super.fsid.blocks; |
| 315 | sbi->files=super.fsid.files; | 320 | sbi->files = super.fsid.files; |
| 316 | } else { | 321 | } else { |
| 317 | sbi->size=1<<28; | 322 | sbi->size = 1<<28; |
| 318 | sbi->blocks=0; | 323 | sbi->blocks = 0; |
| 319 | sbi->files=0; | 324 | sbi->files = 0; |
| 320 | } | 325 | } |
| 321 | sbi->magic=super.magic; | 326 | sbi->magic = super.magic; |
| 322 | sbi->flags=super.flags; | 327 | sbi->flags = super.flags; |
| 323 | if (root_offset == 0) | 328 | if (root_offset == 0) |
| 324 | printk(KERN_INFO "cramfs: empty filesystem"); | 329 | pr_info("empty filesystem"); |
| 325 | else if (!(super.flags & CRAMFS_FLAG_SHIFTED_ROOT_OFFSET) && | 330 | else if (!(super.flags & CRAMFS_FLAG_SHIFTED_ROOT_OFFSET) && |
| 326 | ((root_offset != sizeof(struct cramfs_super)) && | 331 | ((root_offset != sizeof(struct cramfs_super)) && |
| 327 | (root_offset != 512 + sizeof(struct cramfs_super)))) | 332 | (root_offset != 512 + sizeof(struct cramfs_super)))) |
| 328 | { | 333 | { |
| 329 | printk(KERN_ERR "cramfs: bad root offset %lu\n", root_offset); | 334 | pr_err("bad root offset %lu\n", root_offset); |
| 330 | return -EINVAL; | 335 | return -EINVAL; |
| 331 | } | 336 | } |
| 332 | 337 | ||
| @@ -425,7 +430,7 @@ static int cramfs_readdir(struct file *file, struct dir_context *ctx) | |||
| 425 | /* | 430 | /* |
| 426 | * Lookup and fill in the inode data.. | 431 | * Lookup and fill in the inode data.. |
| 427 | */ | 432 | */ |
| 428 | static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) | 433 | static struct dentry *cramfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) |
| 429 | { | 434 | { |
| 430 | unsigned int offset = 0; | 435 | unsigned int offset = 0; |
| 431 | struct inode *inode = NULL; | 436 | struct inode *inode = NULL; |
| @@ -483,7 +488,7 @@ out: | |||
| 483 | return NULL; | 488 | return NULL; |
| 484 | } | 489 | } |
| 485 | 490 | ||
| 486 | static int cramfs_readpage(struct file *file, struct page * page) | 491 | static int cramfs_readpage(struct file *file, struct page *page) |
| 487 | { | 492 | { |
| 488 | struct inode *inode = page->mapping->host; | 493 | struct inode *inode = page->mapping->host; |
| 489 | u32 maxblock; | 494 | u32 maxblock; |
| @@ -511,7 +516,7 @@ static int cramfs_readpage(struct file *file, struct page * page) | |||
| 511 | if (compr_len == 0) | 516 | if (compr_len == 0) |
| 512 | ; /* hole */ | 517 | ; /* hole */ |
| 513 | else if (unlikely(compr_len > (PAGE_CACHE_SIZE << 1))) { | 518 | else if (unlikely(compr_len > (PAGE_CACHE_SIZE << 1))) { |
| 514 | pr_err("cramfs: bad compressed blocksize %u\n", | 519 | pr_err("bad compressed blocksize %u\n", |
| 515 | compr_len); | 520 | compr_len); |
| 516 | goto err; | 521 | goto err; |
| 517 | } else { | 522 | } else { |
diff --git a/fs/cramfs/uncompress.c b/fs/cramfs/uncompress.c index 1760c1b84d97..ec4f1d4fdad0 100644 --- a/fs/cramfs/uncompress.c +++ b/fs/cramfs/uncompress.c | |||
| @@ -15,6 +15,8 @@ | |||
| 15 | * then is used by multiple filesystems. | 15 | * then is used by multiple filesystems. |
| 16 | */ | 16 | */ |
| 17 | 17 | ||
| 18 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 19 | |||
| 18 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
| 19 | #include <linux/errno.h> | 21 | #include <linux/errno.h> |
| 20 | #include <linux/vmalloc.h> | 22 | #include <linux/vmalloc.h> |
| @@ -37,7 +39,7 @@ int cramfs_uncompress_block(void *dst, int dstlen, void *src, int srclen) | |||
| 37 | 39 | ||
| 38 | err = zlib_inflateReset(&stream); | 40 | err = zlib_inflateReset(&stream); |
| 39 | if (err != Z_OK) { | 41 | if (err != Z_OK) { |
| 40 | printk("zlib_inflateReset error %d\n", err); | 42 | pr_err("zlib_inflateReset error %d\n", err); |
| 41 | zlib_inflateEnd(&stream); | 43 | zlib_inflateEnd(&stream); |
| 42 | zlib_inflateInit(&stream); | 44 | zlib_inflateInit(&stream); |
| 43 | } | 45 | } |
| @@ -48,8 +50,8 @@ int cramfs_uncompress_block(void *dst, int dstlen, void *src, int srclen) | |||
| 48 | return stream.total_out; | 50 | return stream.total_out; |
| 49 | 51 | ||
| 50 | err: | 52 | err: |
| 51 | printk("Error %d while decompressing!\n", err); | 53 | pr_err("Error %d while decompressing!\n", err); |
| 52 | printk("%p(%d)->%p(%d)\n", src, srclen, dst, dstlen); | 54 | pr_err("%p(%d)->%p(%d)\n", src, srclen, dst, dstlen); |
| 53 | return -EIO; | 55 | return -EIO; |
| 54 | } | 56 | } |
| 55 | 57 | ||
| @@ -57,7 +59,7 @@ int cramfs_uncompress_init(void) | |||
| 57 | { | 59 | { |
| 58 | if (!initialized++) { | 60 | if (!initialized++) { |
| 59 | stream.workspace = vmalloc(zlib_inflate_workspacesize()); | 61 | stream.workspace = vmalloc(zlib_inflate_workspacesize()); |
| 60 | if ( !stream.workspace ) { | 62 | if (!stream.workspace) { |
| 61 | initialized = 0; | 63 | initialized = 0; |
| 62 | return -ENOMEM; | 64 | return -ENOMEM; |
| 63 | } | 65 | } |
diff --git a/fs/dlm/debug_fs.c b/fs/dlm/debug_fs.c index 8d77ba7b1756..1323c568e362 100644 --- a/fs/dlm/debug_fs.c +++ b/fs/dlm/debug_fs.c | |||
| @@ -718,16 +718,11 @@ static const struct file_operations waiters_fops = { | |||
| 718 | 718 | ||
| 719 | void dlm_delete_debug_file(struct dlm_ls *ls) | 719 | void dlm_delete_debug_file(struct dlm_ls *ls) |
| 720 | { | 720 | { |
| 721 | if (ls->ls_debug_rsb_dentry) | 721 | debugfs_remove(ls->ls_debug_rsb_dentry); |
| 722 | debugfs_remove(ls->ls_debug_rsb_dentry); | 722 | debugfs_remove(ls->ls_debug_waiters_dentry); |
| 723 | if (ls->ls_debug_waiters_dentry) | 723 | debugfs_remove(ls->ls_debug_locks_dentry); |
| 724 | debugfs_remove(ls->ls_debug_waiters_dentry); | 724 | debugfs_remove(ls->ls_debug_all_dentry); |
| 725 | if (ls->ls_debug_locks_dentry) | 725 | debugfs_remove(ls->ls_debug_toss_dentry); |
| 726 | debugfs_remove(ls->ls_debug_locks_dentry); | ||
| 727 | if (ls->ls_debug_all_dentry) | ||
| 728 | debugfs_remove(ls->ls_debug_all_dentry); | ||
| 729 | if (ls->ls_debug_toss_dentry) | ||
| 730 | debugfs_remove(ls->ls_debug_toss_dentry); | ||
| 731 | } | 726 | } |
| 732 | 727 | ||
| 733 | int dlm_create_debug_file(struct dlm_ls *ls) | 728 | int dlm_create_debug_file(struct dlm_ls *ls) |
diff --git a/fs/efs/namei.c b/fs/efs/namei.c index 356c044e2cd3..bbee8f063dfa 100644 --- a/fs/efs/namei.c +++ b/fs/efs/namei.c | |||
| @@ -12,7 +12,8 @@ | |||
| 12 | #include "efs.h" | 12 | #include "efs.h" |
| 13 | 13 | ||
| 14 | 14 | ||
| 15 | static efs_ino_t efs_find_entry(struct inode *inode, const char *name, int len) { | 15 | static efs_ino_t efs_find_entry(struct inode *inode, const char *name, int len) |
| 16 | { | ||
| 16 | struct buffer_head *bh; | 17 | struct buffer_head *bh; |
| 17 | 18 | ||
| 18 | int slot, namelen; | 19 | int slot, namelen; |
| @@ -40,10 +41,10 @@ static efs_ino_t efs_find_entry(struct inode *inode, const char *name, int len) | |||
| 40 | if (be16_to_cpu(dirblock->magic) != EFS_DIRBLK_MAGIC) { | 41 | if (be16_to_cpu(dirblock->magic) != EFS_DIRBLK_MAGIC) { |
| 41 | pr_err("%s(): invalid directory block\n", __func__); | 42 | pr_err("%s(): invalid directory block\n", __func__); |
| 42 | brelse(bh); | 43 | brelse(bh); |
| 43 | return(0); | 44 | return 0; |
| 44 | } | 45 | } |
| 45 | 46 | ||
| 46 | for(slot = 0; slot < dirblock->slots; slot++) { | 47 | for (slot = 0; slot < dirblock->slots; slot++) { |
| 47 | dirslot = (struct efs_dentry *) (((char *) bh->b_data) + EFS_SLOTAT(dirblock, slot)); | 48 | dirslot = (struct efs_dentry *) (((char *) bh->b_data) + EFS_SLOTAT(dirblock, slot)); |
| 48 | 49 | ||
| 49 | namelen = dirslot->namelen; | 50 | namelen = dirslot->namelen; |
| @@ -52,12 +53,12 @@ static efs_ino_t efs_find_entry(struct inode *inode, const char *name, int len) | |||
| 52 | if ((namelen == len) && (!memcmp(name, nameptr, len))) { | 53 | if ((namelen == len) && (!memcmp(name, nameptr, len))) { |
| 53 | inodenum = be32_to_cpu(dirslot->inode); | 54 | inodenum = be32_to_cpu(dirslot->inode); |
| 54 | brelse(bh); | 55 | brelse(bh); |
| 55 | return(inodenum); | 56 | return inodenum; |
| 56 | } | 57 | } |
| 57 | } | 58 | } |
| 58 | brelse(bh); | 59 | brelse(bh); |
| 59 | } | 60 | } |
| 60 | return(0); | 61 | return 0; |
| 61 | } | 62 | } |
| 62 | 63 | ||
| 63 | struct dentry *efs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) | 64 | struct dentry *efs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) |
| @@ -368,10 +368,6 @@ static int bprm_mm_init(struct linux_binprm *bprm) | |||
| 368 | if (!mm) | 368 | if (!mm) |
| 369 | goto err; | 369 | goto err; |
| 370 | 370 | ||
| 371 | err = init_new_context(current, mm); | ||
| 372 | if (err) | ||
| 373 | goto err; | ||
| 374 | |||
| 375 | err = __bprm_mm_init(bprm); | 371 | err = __bprm_mm_init(bprm); |
| 376 | if (err) | 372 | if (err) |
| 377 | goto err; | 373 | goto err; |
diff --git a/fs/exofs/ore_raid.c b/fs/exofs/ore_raid.c index 7f20f25c232c..84529b8a331b 100644 --- a/fs/exofs/ore_raid.c +++ b/fs/exofs/ore_raid.c | |||
| @@ -116,7 +116,7 @@ static int _sp2d_alloc(unsigned pages_in_unit, unsigned group_width, | |||
| 116 | num_a1pa = min_t(unsigned, PAGE_SIZE / sizeof__a1pa, | 116 | num_a1pa = min_t(unsigned, PAGE_SIZE / sizeof__a1pa, |
| 117 | pages_in_unit - i); | 117 | pages_in_unit - i); |
| 118 | 118 | ||
| 119 | __a1pa = kzalloc(num_a1pa * sizeof__a1pa, GFP_KERNEL); | 119 | __a1pa = kcalloc(num_a1pa, sizeof__a1pa, GFP_KERNEL); |
| 120 | if (unlikely(!__a1pa)) { | 120 | if (unlikely(!__a1pa)) { |
| 121 | ORE_DBGMSG("!! Failed to _alloc_1p_arrays=%d\n", | 121 | ORE_DBGMSG("!! Failed to _alloc_1p_arrays=%d\n", |
| 122 | num_a1pa); | 122 | num_a1pa); |
diff --git a/fs/fcntl.c b/fs/fcntl.c index 72c82f69b01b..22d1c3df61ac 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/rcupdate.h> | 21 | #include <linux/rcupdate.h> |
| 22 | #include <linux/pid_namespace.h> | 22 | #include <linux/pid_namespace.h> |
| 23 | #include <linux/user_namespace.h> | 23 | #include <linux/user_namespace.h> |
| 24 | #include <linux/shmem_fs.h> | ||
| 24 | 25 | ||
| 25 | #include <asm/poll.h> | 26 | #include <asm/poll.h> |
| 26 | #include <asm/siginfo.h> | 27 | #include <asm/siginfo.h> |
| @@ -336,6 +337,10 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg, | |||
| 336 | case F_GETPIPE_SZ: | 337 | case F_GETPIPE_SZ: |
| 337 | err = pipe_fcntl(filp, cmd, arg); | 338 | err = pipe_fcntl(filp, cmd, arg); |
| 338 | break; | 339 | break; |
| 340 | case F_ADD_SEALS: | ||
| 341 | case F_GET_SEALS: | ||
| 342 | err = shmem_fcntl(filp, cmd, arg); | ||
| 343 | break; | ||
| 339 | default: | 344 | default: |
| 340 | break; | 345 | break; |
| 341 | } | 346 | } |
diff --git a/fs/hpfs/dnode.c b/fs/hpfs/dnode.c index f36fc010fccb..2923a7bd82ac 100644 --- a/fs/hpfs/dnode.c +++ b/fs/hpfs/dnode.c | |||
| @@ -545,12 +545,13 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno) | |||
| 545 | struct dnode *d1; | 545 | struct dnode *d1; |
| 546 | struct quad_buffer_head qbh1; | 546 | struct quad_buffer_head qbh1; |
| 547 | if (hpfs_sb(i->i_sb)->sb_chk) | 547 | if (hpfs_sb(i->i_sb)->sb_chk) |
| 548 | if (up != i->i_ino) { | 548 | if (up != i->i_ino) { |
| 549 | hpfs_error(i->i_sb, | 549 | hpfs_error(i->i_sb, |
| 550 | "bad pointer to fnode, dnode %08x, pointing to %08x, should be %08lx", | 550 | "bad pointer to fnode, dnode %08x, pointing to %08x, should be %08lx", |
| 551 | dno, up, (unsigned long)i->i_ino); | 551 | dno, up, |
| 552 | return; | 552 | (unsigned long)i->i_ino); |
| 553 | } | 553 | return; |
| 554 | } | ||
| 554 | if ((d1 = hpfs_map_dnode(i->i_sb, down, &qbh1))) { | 555 | if ((d1 = hpfs_map_dnode(i->i_sb, down, &qbh1))) { |
| 555 | d1->up = cpu_to_le32(up); | 556 | d1->up = cpu_to_le32(up); |
| 556 | d1->root_dnode = 1; | 557 | d1->root_dnode = 1; |
| @@ -1061,8 +1062,8 @@ struct hpfs_dirent *map_fnode_dirent(struct super_block *s, fnode_secno fno, | |||
| 1061 | hpfs_brelse4(qbh); | 1062 | hpfs_brelse4(qbh); |
| 1062 | if (hpfs_sb(s)->sb_chk) | 1063 | if (hpfs_sb(s)->sb_chk) |
| 1063 | if (hpfs_stop_cycles(s, dno, &c1, &c2, "map_fnode_dirent #1")) { | 1064 | if (hpfs_stop_cycles(s, dno, &c1, &c2, "map_fnode_dirent #1")) { |
| 1064 | kfree(name2); | 1065 | kfree(name2); |
| 1065 | return NULL; | 1066 | return NULL; |
| 1066 | } | 1067 | } |
| 1067 | goto go_down; | 1068 | goto go_down; |
| 1068 | } | 1069 | } |
diff --git a/fs/inode.c b/fs/inode.c index 5938f3928944..26753ba7b6d6 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
| @@ -165,6 +165,7 @@ int inode_init_always(struct super_block *sb, struct inode *inode) | |||
| 165 | mapping->a_ops = &empty_aops; | 165 | mapping->a_ops = &empty_aops; |
| 166 | mapping->host = inode; | 166 | mapping->host = inode; |
| 167 | mapping->flags = 0; | 167 | mapping->flags = 0; |
| 168 | atomic_set(&mapping->i_mmap_writable, 0); | ||
| 168 | mapping_set_gfp_mask(mapping, GFP_HIGHUSER_MOVABLE); | 169 | mapping_set_gfp_mask(mapping, GFP_HIGHUSER_MOVABLE); |
| 169 | mapping->private_data = NULL; | 170 | mapping->private_data = NULL; |
| 170 | mapping->backing_dev_info = &default_backing_dev_info; | 171 | mapping->backing_dev_info = &default_backing_dev_info; |
diff --git a/fs/isofs/compress.c b/fs/isofs/compress.c index 592e5115a561..f311bf084015 100644 --- a/fs/isofs/compress.c +++ b/fs/isofs/compress.c | |||
| @@ -158,8 +158,8 @@ static loff_t zisofs_uncompress_block(struct inode *inode, loff_t block_start, | |||
| 158 | "zisofs: zisofs_inflate returned" | 158 | "zisofs: zisofs_inflate returned" |
| 159 | " %d, inode = %lu," | 159 | " %d, inode = %lu," |
| 160 | " page idx = %d, bh idx = %d," | 160 | " page idx = %d, bh idx = %d," |
| 161 | " avail_in = %d," | 161 | " avail_in = %ld," |
| 162 | " avail_out = %d\n", | 162 | " avail_out = %ld\n", |
| 163 | zerr, inode->i_ino, curpage, | 163 | zerr, inode->i_ino, curpage, |
| 164 | curbh, stream.avail_in, | 164 | curbh, stream.avail_in, |
| 165 | stream.avail_out); | 165 | stream.avail_out); |
diff --git a/fs/jffs2/compr_zlib.c b/fs/jffs2/compr_zlib.c index 0b9a1e44e833..5698dae5d92d 100644 --- a/fs/jffs2/compr_zlib.c +++ b/fs/jffs2/compr_zlib.c | |||
| @@ -94,11 +94,12 @@ static int jffs2_zlib_compress(unsigned char *data_in, | |||
| 94 | 94 | ||
| 95 | while (def_strm.total_out < *dstlen - STREAM_END_SPACE && def_strm.total_in < *sourcelen) { | 95 | while (def_strm.total_out < *dstlen - STREAM_END_SPACE && def_strm.total_in < *sourcelen) { |
| 96 | def_strm.avail_out = *dstlen - (def_strm.total_out + STREAM_END_SPACE); | 96 | def_strm.avail_out = *dstlen - (def_strm.total_out + STREAM_END_SPACE); |
| 97 | def_strm.avail_in = min((unsigned)(*sourcelen-def_strm.total_in), def_strm.avail_out); | 97 | def_strm.avail_in = min_t(unsigned long, |
| 98 | jffs2_dbg(1, "calling deflate with avail_in %d, avail_out %d\n", | 98 | (*sourcelen-def_strm.total_in), def_strm.avail_out); |
| 99 | jffs2_dbg(1, "calling deflate with avail_in %ld, avail_out %ld\n", | ||
| 99 | def_strm.avail_in, def_strm.avail_out); | 100 | def_strm.avail_in, def_strm.avail_out); |
| 100 | ret = zlib_deflate(&def_strm, Z_PARTIAL_FLUSH); | 101 | ret = zlib_deflate(&def_strm, Z_PARTIAL_FLUSH); |
| 101 | jffs2_dbg(1, "deflate returned with avail_in %d, avail_out %d, total_in %ld, total_out %ld\n", | 102 | jffs2_dbg(1, "deflate returned with avail_in %ld, avail_out %ld, total_in %ld, total_out %ld\n", |
| 102 | def_strm.avail_in, def_strm.avail_out, | 103 | def_strm.avail_in, def_strm.avail_out, |
| 103 | def_strm.total_in, def_strm.total_out); | 104 | def_strm.total_in, def_strm.total_out); |
| 104 | if (ret != Z_OK) { | 105 | if (ret != Z_OK) { |
diff --git a/fs/minix/bitmap.c b/fs/minix/bitmap.c index 4bc50dac8e97..742942a983be 100644 --- a/fs/minix/bitmap.c +++ b/fs/minix/bitmap.c | |||
| @@ -96,7 +96,7 @@ int minix_new_block(struct inode * inode) | |||
| 96 | unsigned long minix_count_free_blocks(struct super_block *sb) | 96 | unsigned long minix_count_free_blocks(struct super_block *sb) |
| 97 | { | 97 | { |
| 98 | struct minix_sb_info *sbi = minix_sb(sb); | 98 | struct minix_sb_info *sbi = minix_sb(sb); |
| 99 | u32 bits = sbi->s_nzones - (sbi->s_firstdatazone + 1); | 99 | u32 bits = sbi->s_nzones - sbi->s_firstdatazone + 1; |
| 100 | 100 | ||
| 101 | return (count_free(sbi->s_zmap, sb->s_blocksize, bits) | 101 | return (count_free(sbi->s_zmap, sb->s_blocksize, bits) |
| 102 | << sbi->s_log_zone_size); | 102 | << sbi->s_log_zone_size); |
diff --git a/fs/minix/inode.c b/fs/minix/inode.c index f007a3355570..3f57af196a7d 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c | |||
| @@ -267,12 +267,12 @@ static int minix_fill_super(struct super_block *s, void *data, int silent) | |||
| 267 | block = minix_blocks_needed(sbi->s_ninodes, s->s_blocksize); | 267 | block = minix_blocks_needed(sbi->s_ninodes, s->s_blocksize); |
| 268 | if (sbi->s_imap_blocks < block) { | 268 | if (sbi->s_imap_blocks < block) { |
| 269 | printk("MINIX-fs: file system does not have enough " | 269 | printk("MINIX-fs: file system does not have enough " |
| 270 | "imap blocks allocated. Refusing to mount\n"); | 270 | "imap blocks allocated. Refusing to mount.\n"); |
| 271 | goto out_no_bitmap; | 271 | goto out_no_bitmap; |
| 272 | } | 272 | } |
| 273 | 273 | ||
| 274 | block = minix_blocks_needed( | 274 | block = minix_blocks_needed( |
| 275 | (sbi->s_nzones - (sbi->s_firstdatazone + 1)), | 275 | (sbi->s_nzones - sbi->s_firstdatazone + 1), |
| 276 | s->s_blocksize); | 276 | s->s_blocksize); |
| 277 | if (sbi->s_zmap_blocks < block) { | 277 | if (sbi->s_zmap_blocks < block) { |
| 278 | printk("MINIX-fs: file system does not have enough " | 278 | printk("MINIX-fs: file system does not have enough " |
diff --git a/fs/nilfs2/Makefile b/fs/nilfs2/Makefile index 85c98737a146..fc603e0431bb 100644 --- a/fs/nilfs2/Makefile +++ b/fs/nilfs2/Makefile | |||
| @@ -2,4 +2,4 @@ obj-$(CONFIG_NILFS2_FS) += nilfs2.o | |||
| 2 | nilfs2-y := inode.o file.o dir.o super.o namei.o page.o mdt.o \ | 2 | nilfs2-y := inode.o file.o dir.o super.o namei.o page.o mdt.o \ |
| 3 | btnode.o bmap.o btree.o direct.o dat.o recovery.o \ | 3 | btnode.o bmap.o btree.o direct.o dat.o recovery.o \ |
| 4 | the_nilfs.o segbuf.o segment.o cpfile.o sufile.o \ | 4 | the_nilfs.o segbuf.o segment.o cpfile.o sufile.o \ |
| 5 | ifile.o alloc.o gcinode.o ioctl.o | 5 | ifile.o alloc.o gcinode.o ioctl.o sysfs.o |
diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h index 9bc72dec3fa6..0696161bf59d 100644 --- a/fs/nilfs2/nilfs.h +++ b/fs/nilfs2/nilfs.h | |||
| @@ -320,6 +320,14 @@ int nilfs_gccache_wait_and_mark_dirty(struct buffer_head *); | |||
| 320 | int nilfs_init_gcinode(struct inode *inode); | 320 | int nilfs_init_gcinode(struct inode *inode); |
| 321 | void nilfs_remove_all_gcinodes(struct the_nilfs *nilfs); | 321 | void nilfs_remove_all_gcinodes(struct the_nilfs *nilfs); |
| 322 | 322 | ||
| 323 | /* sysfs.c */ | ||
| 324 | int __init nilfs_sysfs_init(void); | ||
| 325 | void nilfs_sysfs_exit(void); | ||
| 326 | int nilfs_sysfs_create_device_group(struct super_block *); | ||
| 327 | void nilfs_sysfs_delete_device_group(struct the_nilfs *); | ||
| 328 | int nilfs_sysfs_create_snapshot_group(struct nilfs_root *); | ||
| 329 | void nilfs_sysfs_delete_snapshot_group(struct nilfs_root *); | ||
| 330 | |||
| 323 | /* | 331 | /* |
| 324 | * Inodes and files operations | 332 | * Inodes and files operations |
| 325 | */ | 333 | */ |
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 8c532b2ca3ab..c519927b7b5e 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c | |||
| @@ -1452,13 +1452,19 @@ static int __init init_nilfs_fs(void) | |||
| 1452 | if (err) | 1452 | if (err) |
| 1453 | goto fail; | 1453 | goto fail; |
| 1454 | 1454 | ||
| 1455 | err = register_filesystem(&nilfs_fs_type); | 1455 | err = nilfs_sysfs_init(); |
| 1456 | if (err) | 1456 | if (err) |
| 1457 | goto free_cachep; | 1457 | goto free_cachep; |
| 1458 | 1458 | ||
| 1459 | err = register_filesystem(&nilfs_fs_type); | ||
| 1460 | if (err) | ||
| 1461 | goto deinit_sysfs_entry; | ||
| 1462 | |||
| 1459 | printk(KERN_INFO "NILFS version 2 loaded\n"); | 1463 | printk(KERN_INFO "NILFS version 2 loaded\n"); |
| 1460 | return 0; | 1464 | return 0; |
| 1461 | 1465 | ||
| 1466 | deinit_sysfs_entry: | ||
| 1467 | nilfs_sysfs_exit(); | ||
| 1462 | free_cachep: | 1468 | free_cachep: |
| 1463 | nilfs_destroy_cachep(); | 1469 | nilfs_destroy_cachep(); |
| 1464 | fail: | 1470 | fail: |
| @@ -1468,6 +1474,7 @@ fail: | |||
| 1468 | static void __exit exit_nilfs_fs(void) | 1474 | static void __exit exit_nilfs_fs(void) |
| 1469 | { | 1475 | { |
| 1470 | nilfs_destroy_cachep(); | 1476 | nilfs_destroy_cachep(); |
| 1477 | nilfs_sysfs_exit(); | ||
| 1471 | unregister_filesystem(&nilfs_fs_type); | 1478 | unregister_filesystem(&nilfs_fs_type); |
| 1472 | } | 1479 | } |
| 1473 | 1480 | ||
diff --git a/fs/nilfs2/sysfs.c b/fs/nilfs2/sysfs.c new file mode 100644 index 000000000000..bbb0dcc35905 --- /dev/null +++ b/fs/nilfs2/sysfs.c | |||
| @@ -0,0 +1,1137 @@ | |||
| 1 | /* | ||
| 2 | * sysfs.c - sysfs support implementation. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2005-2014 Nippon Telegraph and Telephone Corporation. | ||
| 5 | * Copyright (C) 2014 HGST, Inc., a Western Digital Company. | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * Written by Vyacheslav Dubeyko <Vyacheslav.Dubeyko@hgst.com> | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <linux/kobject.h> | ||
| 21 | |||
| 22 | #include "nilfs.h" | ||
| 23 | #include "mdt.h" | ||
| 24 | #include "sufile.h" | ||
| 25 | #include "cpfile.h" | ||
| 26 | #include "sysfs.h" | ||
| 27 | |||
| 28 | /* /sys/fs/<nilfs>/ */ | ||
| 29 | static struct kset *nilfs_kset; | ||
| 30 | |||
| 31 | #define NILFS_SHOW_TIME(time_t_val, buf) ({ \ | ||
| 32 | struct tm res; \ | ||
| 33 | int count = 0; \ | ||
| 34 | time_to_tm(time_t_val, 0, &res); \ | ||
| 35 | res.tm_year += 1900; \ | ||
| 36 | res.tm_mon += 1; \ | ||
| 37 | count = scnprintf(buf, PAGE_SIZE, \ | ||
| 38 | "%ld-%.2d-%.2d %.2d:%.2d:%.2d\n", \ | ||
| 39 | res.tm_year, res.tm_mon, res.tm_mday, \ | ||
| 40 | res.tm_hour, res.tm_min, res.tm_sec);\ | ||
| 41 | count; \ | ||
| 42 | }) | ||
| 43 | |||
| 44 | #define NILFS_DEV_INT_GROUP_OPS(name, parent_name) \ | ||
| 45 | static ssize_t nilfs_##name##_attr_show(struct kobject *kobj, \ | ||
| 46 | struct attribute *attr, char *buf) \ | ||
| 47 | { \ | ||
| 48 | struct the_nilfs *nilfs = container_of(kobj->parent, \ | ||
| 49 | struct the_nilfs, \ | ||
| 50 | ns_##parent_name##_kobj); \ | ||
| 51 | struct nilfs_##name##_attr *a = container_of(attr, \ | ||
| 52 | struct nilfs_##name##_attr, \ | ||
| 53 | attr); \ | ||
| 54 | return a->show ? a->show(a, nilfs, buf) : 0; \ | ||
| 55 | } \ | ||
| 56 | static ssize_t nilfs_##name##_attr_store(struct kobject *kobj, \ | ||
| 57 | struct attribute *attr, \ | ||
| 58 | const char *buf, size_t len) \ | ||
| 59 | { \ | ||
| 60 | struct the_nilfs *nilfs = container_of(kobj->parent, \ | ||
| 61 | struct the_nilfs, \ | ||
| 62 | ns_##parent_name##_kobj); \ | ||
| 63 | struct nilfs_##name##_attr *a = container_of(attr, \ | ||
| 64 | struct nilfs_##name##_attr, \ | ||
| 65 | attr); \ | ||
| 66 | return a->store ? a->store(a, nilfs, buf, len) : 0; \ | ||
| 67 | } \ | ||
| 68 | static const struct sysfs_ops nilfs_##name##_attr_ops = { \ | ||
| 69 | .show = nilfs_##name##_attr_show, \ | ||
| 70 | .store = nilfs_##name##_attr_store, \ | ||
| 71 | }; | ||
| 72 | |||
| 73 | #define NILFS_DEV_INT_GROUP_TYPE(name, parent_name) \ | ||
| 74 | static void nilfs_##name##_attr_release(struct kobject *kobj) \ | ||
| 75 | { \ | ||
| 76 | struct nilfs_sysfs_##parent_name##_subgroups *subgroups; \ | ||
| 77 | struct the_nilfs *nilfs = container_of(kobj->parent, \ | ||
| 78 | struct the_nilfs, \ | ||
| 79 | ns_##parent_name##_kobj); \ | ||
| 80 | subgroups = nilfs->ns_##parent_name##_subgroups; \ | ||
| 81 | complete(&subgroups->sg_##name##_kobj_unregister); \ | ||
| 82 | } \ | ||
| 83 | static struct kobj_type nilfs_##name##_ktype = { \ | ||
| 84 | .default_attrs = nilfs_##name##_attrs, \ | ||
| 85 | .sysfs_ops = &nilfs_##name##_attr_ops, \ | ||
| 86 | .release = nilfs_##name##_attr_release, \ | ||
| 87 | }; | ||
| 88 | |||
| 89 | #define NILFS_DEV_INT_GROUP_FNS(name, parent_name) \ | ||
| 90 | static int nilfs_sysfs_create_##name##_group(struct the_nilfs *nilfs) \ | ||
| 91 | { \ | ||
| 92 | struct kobject *parent; \ | ||
| 93 | struct kobject *kobj; \ | ||
| 94 | struct completion *kobj_unregister; \ | ||
| 95 | struct nilfs_sysfs_##parent_name##_subgroups *subgroups; \ | ||
| 96 | int err; \ | ||
| 97 | subgroups = nilfs->ns_##parent_name##_subgroups; \ | ||
| 98 | kobj = &subgroups->sg_##name##_kobj; \ | ||
| 99 | kobj_unregister = &subgroups->sg_##name##_kobj_unregister; \ | ||
| 100 | parent = &nilfs->ns_##parent_name##_kobj; \ | ||
| 101 | kobj->kset = nilfs_kset; \ | ||
| 102 | init_completion(kobj_unregister); \ | ||
| 103 | err = kobject_init_and_add(kobj, &nilfs_##name##_ktype, parent, \ | ||
| 104 | #name); \ | ||
| 105 | if (err) \ | ||
| 106 | return err; \ | ||
| 107 | return 0; \ | ||
| 108 | } \ | ||
| 109 | static void nilfs_sysfs_delete_##name##_group(struct the_nilfs *nilfs) \ | ||
| 110 | { \ | ||
| 111 | kobject_del(&nilfs->ns_##parent_name##_subgroups->sg_##name##_kobj); \ | ||
| 112 | } | ||
| 113 | |||
| 114 | /************************************************************************ | ||
| 115 | * NILFS snapshot attrs * | ||
| 116 | ************************************************************************/ | ||
| 117 | |||
| 118 | static ssize_t | ||
| 119 | nilfs_snapshot_inodes_count_show(struct nilfs_snapshot_attr *attr, | ||
| 120 | struct nilfs_root *root, char *buf) | ||
| 121 | { | ||
| 122 | return snprintf(buf, PAGE_SIZE, "%llu\n", | ||
| 123 | (unsigned long long)atomic64_read(&root->inodes_count)); | ||
| 124 | } | ||
| 125 | |||
| 126 | static ssize_t | ||
| 127 | nilfs_snapshot_blocks_count_show(struct nilfs_snapshot_attr *attr, | ||
| 128 | struct nilfs_root *root, char *buf) | ||
| 129 | { | ||
| 130 | return snprintf(buf, PAGE_SIZE, "%llu\n", | ||
| 131 | (unsigned long long)atomic64_read(&root->blocks_count)); | ||
| 132 | } | ||
| 133 | |||
| 134 | static const char snapshot_readme_str[] = | ||
| 135 | "The group contains details about mounted snapshot.\n\n" | ||
| 136 | "(1) inodes_count\n\tshow number of inodes for snapshot.\n\n" | ||
| 137 | "(2) blocks_count\n\tshow number of blocks for snapshot.\n\n"; | ||
| 138 | |||
| 139 | static ssize_t | ||
| 140 | nilfs_snapshot_README_show(struct nilfs_snapshot_attr *attr, | ||
| 141 | struct nilfs_root *root, char *buf) | ||
| 142 | { | ||
| 143 | return snprintf(buf, PAGE_SIZE, snapshot_readme_str); | ||
| 144 | } | ||
| 145 | |||
| 146 | NILFS_SNAPSHOT_RO_ATTR(inodes_count); | ||
| 147 | NILFS_SNAPSHOT_RO_ATTR(blocks_count); | ||
| 148 | NILFS_SNAPSHOT_RO_ATTR(README); | ||
| 149 | |||
| 150 | static struct attribute *nilfs_snapshot_attrs[] = { | ||
| 151 | NILFS_SNAPSHOT_ATTR_LIST(inodes_count), | ||
| 152 | NILFS_SNAPSHOT_ATTR_LIST(blocks_count), | ||
| 153 | NILFS_SNAPSHOT_ATTR_LIST(README), | ||
| 154 | NULL, | ||
| 155 | }; | ||
| 156 | |||
| 157 | static ssize_t nilfs_snapshot_attr_show(struct kobject *kobj, | ||
| 158 | struct attribute *attr, char *buf) | ||
| 159 | { | ||
| 160 | struct nilfs_root *root = | ||
| 161 | container_of(kobj, struct nilfs_root, snapshot_kobj); | ||
| 162 | struct nilfs_snapshot_attr *a = | ||
| 163 | container_of(attr, struct nilfs_snapshot_attr, attr); | ||
| 164 | |||
| 165 | return a->show ? a->show(a, root, buf) : 0; | ||
| 166 | } | ||
| 167 | |||
| 168 | static ssize_t nilfs_snapshot_attr_store(struct kobject *kobj, | ||
| 169 | struct attribute *attr, | ||
| 170 | const char *buf, size_t len) | ||
| 171 | { | ||
| 172 | struct nilfs_root *root = | ||
| 173 | container_of(kobj, struct nilfs_root, snapshot_kobj); | ||
| 174 | struct nilfs_snapshot_attr *a = | ||
| 175 | container_of(attr, struct nilfs_snapshot_attr, attr); | ||
| 176 | |||
| 177 | return a->store ? a->store(a, root, buf, len) : 0; | ||
| 178 | } | ||
| 179 | |||
| 180 | static void nilfs_snapshot_attr_release(struct kobject *kobj) | ||
| 181 | { | ||
| 182 | struct nilfs_root *root = container_of(kobj, struct nilfs_root, | ||
| 183 | snapshot_kobj); | ||
| 184 | complete(&root->snapshot_kobj_unregister); | ||
| 185 | } | ||
| 186 | |||
| 187 | static const struct sysfs_ops nilfs_snapshot_attr_ops = { | ||
| 188 | .show = nilfs_snapshot_attr_show, | ||
| 189 | .store = nilfs_snapshot_attr_store, | ||
| 190 | }; | ||
| 191 | |||
| 192 | static struct kobj_type nilfs_snapshot_ktype = { | ||
| 193 | .default_attrs = nilfs_snapshot_attrs, | ||
| 194 | .sysfs_ops = &nilfs_snapshot_attr_ops, | ||
| 195 | .release = nilfs_snapshot_attr_release, | ||
| 196 | }; | ||
| 197 | |||
| 198 | int nilfs_sysfs_create_snapshot_group(struct nilfs_root *root) | ||
| 199 | { | ||
| 200 | struct the_nilfs *nilfs; | ||
| 201 | struct kobject *parent; | ||
| 202 | int err; | ||
| 203 | |||
| 204 | nilfs = root->nilfs; | ||
| 205 | parent = &nilfs->ns_dev_subgroups->sg_mounted_snapshots_kobj; | ||
| 206 | root->snapshot_kobj.kset = nilfs_kset; | ||
| 207 | init_completion(&root->snapshot_kobj_unregister); | ||
| 208 | |||
| 209 | if (root->cno == NILFS_CPTREE_CURRENT_CNO) { | ||
| 210 | err = kobject_init_and_add(&root->snapshot_kobj, | ||
| 211 | &nilfs_snapshot_ktype, | ||
| 212 | &nilfs->ns_dev_kobj, | ||
| 213 | "current_checkpoint"); | ||
| 214 | } else { | ||
| 215 | err = kobject_init_and_add(&root->snapshot_kobj, | ||
| 216 | &nilfs_snapshot_ktype, | ||
| 217 | parent, | ||
| 218 | "%llu", root->cno); | ||
| 219 | } | ||
| 220 | |||
| 221 | if (err) | ||
| 222 | return err; | ||
| 223 | |||
| 224 | return 0; | ||
| 225 | } | ||
| 226 | |||
| 227 | void nilfs_sysfs_delete_snapshot_group(struct nilfs_root *root) | ||
| 228 | { | ||
| 229 | kobject_del(&root->snapshot_kobj); | ||
| 230 | } | ||
| 231 | |||
| 232 | /************************************************************************ | ||
| 233 | * NILFS mounted snapshots attrs * | ||
| 234 | ************************************************************************/ | ||
| 235 | |||
| 236 | static const char mounted_snapshots_readme_str[] = | ||
| 237 | "The mounted_snapshots group contains group for\n" | ||
| 238 | "every mounted snapshot.\n"; | ||
| 239 | |||
| 240 | static ssize_t | ||
| 241 | nilfs_mounted_snapshots_README_show(struct nilfs_mounted_snapshots_attr *attr, | ||
| 242 | struct the_nilfs *nilfs, char *buf) | ||
| 243 | { | ||
| 244 | return snprintf(buf, PAGE_SIZE, mounted_snapshots_readme_str); | ||
| 245 | } | ||
| 246 | |||
| 247 | NILFS_MOUNTED_SNAPSHOTS_RO_ATTR(README); | ||
| 248 | |||
| 249 | static struct attribute *nilfs_mounted_snapshots_attrs[] = { | ||
| 250 | NILFS_MOUNTED_SNAPSHOTS_ATTR_LIST(README), | ||
| 251 | NULL, | ||
| 252 | }; | ||
| 253 | |||
| 254 | NILFS_DEV_INT_GROUP_OPS(mounted_snapshots, dev); | ||
| 255 | NILFS_DEV_INT_GROUP_TYPE(mounted_snapshots, dev); | ||
| 256 | NILFS_DEV_INT_GROUP_FNS(mounted_snapshots, dev); | ||
| 257 | |||
| 258 | /************************************************************************ | ||
| 259 | * NILFS checkpoints attrs * | ||
| 260 | ************************************************************************/ | ||
| 261 | |||
| 262 | static ssize_t | ||
| 263 | nilfs_checkpoints_checkpoints_number_show(struct nilfs_checkpoints_attr *attr, | ||
| 264 | struct the_nilfs *nilfs, | ||
| 265 | char *buf) | ||
| 266 | { | ||
| 267 | __u64 ncheckpoints; | ||
| 268 | struct nilfs_cpstat cpstat; | ||
| 269 | int err; | ||
| 270 | |||
| 271 | down_read(&nilfs->ns_segctor_sem); | ||
| 272 | err = nilfs_cpfile_get_stat(nilfs->ns_cpfile, &cpstat); | ||
| 273 | up_read(&nilfs->ns_segctor_sem); | ||
| 274 | if (err < 0) { | ||
| 275 | printk(KERN_ERR "NILFS: unable to get checkpoint stat: err=%d\n", | ||
| 276 | err); | ||
| 277 | return err; | ||
| 278 | } | ||
| 279 | |||
| 280 | ncheckpoints = cpstat.cs_ncps; | ||
| 281 | |||
| 282 | return snprintf(buf, PAGE_SIZE, "%llu\n", ncheckpoints); | ||
| 283 | } | ||
| 284 | |||
| 285 | static ssize_t | ||
| 286 | nilfs_checkpoints_snapshots_number_show(struct nilfs_checkpoints_attr *attr, | ||
| 287 | struct the_nilfs *nilfs, | ||
| 288 | char *buf) | ||
| 289 | { | ||
| 290 | __u64 nsnapshots; | ||
| 291 | struct nilfs_cpstat cpstat; | ||
| 292 | int err; | ||
| 293 | |||
| 294 | down_read(&nilfs->ns_segctor_sem); | ||
| 295 | err = nilfs_cpfile_get_stat(nilfs->ns_cpfile, &cpstat); | ||
| 296 | up_read(&nilfs->ns_segctor_sem); | ||
| 297 | if (err < 0) { | ||
| 298 | printk(KERN_ERR "NILFS: unable to get checkpoint stat: err=%d\n", | ||
| 299 | err); | ||
| 300 | return err; | ||
| 301 | } | ||
| 302 | |||
| 303 | nsnapshots = cpstat.cs_nsss; | ||
| 304 | |||
| 305 | return snprintf(buf, PAGE_SIZE, "%llu\n", nsnapshots); | ||
| 306 | } | ||
| 307 | |||
| 308 | static ssize_t | ||
| 309 | nilfs_checkpoints_last_seg_checkpoint_show(struct nilfs_checkpoints_attr *attr, | ||
| 310 | struct the_nilfs *nilfs, | ||
| 311 | char *buf) | ||
| 312 | { | ||
| 313 | __u64 last_cno; | ||
| 314 | |||
| 315 | spin_lock(&nilfs->ns_last_segment_lock); | ||
| 316 | last_cno = nilfs->ns_last_cno; | ||
| 317 | spin_unlock(&nilfs->ns_last_segment_lock); | ||
| 318 | |||
| 319 | return snprintf(buf, PAGE_SIZE, "%llu\n", last_cno); | ||
| 320 | } | ||
| 321 | |||
| 322 | static ssize_t | ||
| 323 | nilfs_checkpoints_next_checkpoint_show(struct nilfs_checkpoints_attr *attr, | ||
| 324 | struct the_nilfs *nilfs, | ||
| 325 | char *buf) | ||
| 326 | { | ||
| 327 | __u64 cno; | ||
| 328 | |||
| 329 | down_read(&nilfs->ns_sem); | ||
| 330 | cno = nilfs->ns_cno; | ||
| 331 | up_read(&nilfs->ns_sem); | ||
| 332 | |||
| 333 | return snprintf(buf, PAGE_SIZE, "%llu\n", cno); | ||
| 334 | } | ||
| 335 | |||
| 336 | static const char checkpoints_readme_str[] = | ||
| 337 | "The checkpoints group contains attributes that describe\n" | ||
| 338 | "details about volume's checkpoints.\n\n" | ||
| 339 | "(1) checkpoints_number\n\tshow number of checkpoints on volume.\n\n" | ||
| 340 | "(2) snapshots_number\n\tshow number of snapshots on volume.\n\n" | ||
| 341 | "(3) last_seg_checkpoint\n" | ||
| 342 | "\tshow checkpoint number of the latest segment.\n\n" | ||
| 343 | "(4) next_checkpoint\n\tshow next checkpoint number.\n\n"; | ||
| 344 | |||
| 345 | static ssize_t | ||
| 346 | nilfs_checkpoints_README_show(struct nilfs_checkpoints_attr *attr, | ||
| 347 | struct the_nilfs *nilfs, char *buf) | ||
| 348 | { | ||
| 349 | return snprintf(buf, PAGE_SIZE, checkpoints_readme_str); | ||
| 350 | } | ||
| 351 | |||
| 352 | NILFS_CHECKPOINTS_RO_ATTR(checkpoints_number); | ||
| 353 | NILFS_CHECKPOINTS_RO_ATTR(snapshots_number); | ||
| 354 | NILFS_CHECKPOINTS_RO_ATTR(last_seg_checkpoint); | ||
| 355 | NILFS_CHECKPOINTS_RO_ATTR(next_checkpoint); | ||
| 356 | NILFS_CHECKPOINTS_RO_ATTR(README); | ||
| 357 | |||
| 358 | static struct attribute *nilfs_checkpoints_attrs[] = { | ||
| 359 | NILFS_CHECKPOINTS_ATTR_LIST(checkpoints_number), | ||
| 360 | NILFS_CHECKPOINTS_ATTR_LIST(snapshots_number), | ||
| 361 | NILFS_CHECKPOINTS_ATTR_LIST(last_seg_checkpoint), | ||
| 362 | NILFS_CHECKPOINTS_ATTR_LIST(next_checkpoint), | ||
| 363 | NILFS_CHECKPOINTS_ATTR_LIST(README), | ||
| 364 | NULL, | ||
| 365 | }; | ||
| 366 | |||
| 367 | NILFS_DEV_INT_GROUP_OPS(checkpoints, dev); | ||
| 368 | NILFS_DEV_INT_GROUP_TYPE(checkpoints, dev); | ||
| 369 | NILFS_DEV_INT_GROUP_FNS(checkpoints, dev); | ||
| 370 | |||
| 371 | /************************************************************************ | ||
| 372 | * NILFS segments attrs * | ||
| 373 | ************************************************************************/ | ||
| 374 | |||
| 375 | static ssize_t | ||
| 376 | nilfs_segments_segments_number_show(struct nilfs_segments_attr *attr, | ||
| 377 | struct the_nilfs *nilfs, | ||
| 378 | char *buf) | ||
| 379 | { | ||
| 380 | return snprintf(buf, PAGE_SIZE, "%lu\n", nilfs->ns_nsegments); | ||
| 381 | } | ||
| 382 | |||
| 383 | static ssize_t | ||
| 384 | nilfs_segments_blocks_per_segment_show(struct nilfs_segments_attr *attr, | ||
| 385 | struct the_nilfs *nilfs, | ||
| 386 | char *buf) | ||
| 387 | { | ||
| 388 | return snprintf(buf, PAGE_SIZE, "%lu\n", nilfs->ns_blocks_per_segment); | ||
| 389 | } | ||
| 390 | |||
| 391 | static ssize_t | ||
| 392 | nilfs_segments_clean_segments_show(struct nilfs_segments_attr *attr, | ||
| 393 | struct the_nilfs *nilfs, | ||
| 394 | char *buf) | ||
| 395 | { | ||
| 396 | unsigned long ncleansegs; | ||
| 397 | |||
| 398 | down_read(&NILFS_MDT(nilfs->ns_dat)->mi_sem); | ||
| 399 | ncleansegs = nilfs_sufile_get_ncleansegs(nilfs->ns_sufile); | ||
| 400 | up_read(&NILFS_MDT(nilfs->ns_dat)->mi_sem); | ||
| 401 | |||
| 402 | return snprintf(buf, PAGE_SIZE, "%lu\n", ncleansegs); | ||
| 403 | } | ||
| 404 | |||
| 405 | static ssize_t | ||
| 406 | nilfs_segments_dirty_segments_show(struct nilfs_segments_attr *attr, | ||
| 407 | struct the_nilfs *nilfs, | ||
| 408 | char *buf) | ||
| 409 | { | ||
| 410 | struct nilfs_sustat sustat; | ||
| 411 | int err; | ||
| 412 | |||
| 413 | down_read(&nilfs->ns_segctor_sem); | ||
| 414 | err = nilfs_sufile_get_stat(nilfs->ns_sufile, &sustat); | ||
| 415 | up_read(&nilfs->ns_segctor_sem); | ||
| 416 | if (err < 0) { | ||
| 417 | printk(KERN_ERR "NILFS: unable to get segment stat: err=%d\n", | ||
| 418 | err); | ||
| 419 | return err; | ||
| 420 | } | ||
| 421 | |||
| 422 | return snprintf(buf, PAGE_SIZE, "%llu\n", sustat.ss_ndirtysegs); | ||
| 423 | } | ||
| 424 | |||
| 425 | static const char segments_readme_str[] = | ||
| 426 | "The segments group contains attributes that describe\n" | ||
| 427 | "details about volume's segments.\n\n" | ||
| 428 | "(1) segments_number\n\tshow number of segments on volume.\n\n" | ||
| 429 | "(2) blocks_per_segment\n\tshow number of blocks in segment.\n\n" | ||
| 430 | "(3) clean_segments\n\tshow count of clean segments.\n\n" | ||
| 431 | "(4) dirty_segments\n\tshow count of dirty segments.\n\n"; | ||
| 432 | |||
| 433 | static ssize_t | ||
| 434 | nilfs_segments_README_show(struct nilfs_segments_attr *attr, | ||
| 435 | struct the_nilfs *nilfs, | ||
| 436 | char *buf) | ||
| 437 | { | ||
| 438 | return snprintf(buf, PAGE_SIZE, segments_readme_str); | ||
| 439 | } | ||
| 440 | |||
| 441 | NILFS_SEGMENTS_RO_ATTR(segments_number); | ||
| 442 | NILFS_SEGMENTS_RO_ATTR(blocks_per_segment); | ||
| 443 | NILFS_SEGMENTS_RO_ATTR(clean_segments); | ||
| 444 | NILFS_SEGMENTS_RO_ATTR(dirty_segments); | ||
| 445 | NILFS_SEGMENTS_RO_ATTR(README); | ||
| 446 | |||
| 447 | static struct attribute *nilfs_segments_attrs[] = { | ||
| 448 | NILFS_SEGMENTS_ATTR_LIST(segments_number), | ||
| 449 | NILFS_SEGMENTS_ATTR_LIST(blocks_per_segment), | ||
| 450 | NILFS_SEGMENTS_ATTR_LIST(clean_segments), | ||
| 451 | NILFS_SEGMENTS_ATTR_LIST(dirty_segments), | ||
| 452 | NILFS_SEGMENTS_ATTR_LIST(README), | ||
| 453 | NULL, | ||
| 454 | }; | ||
| 455 | |||
| 456 | NILFS_DEV_INT_GROUP_OPS(segments, dev); | ||
| 457 | NILFS_DEV_INT_GROUP_TYPE(segments, dev); | ||
| 458 | NILFS_DEV_INT_GROUP_FNS(segments, dev); | ||
| 459 | |||
| 460 | /************************************************************************ | ||
| 461 | * NILFS segctor attrs * | ||
| 462 | ************************************************************************/ | ||
| 463 | |||
| 464 | static ssize_t | ||
| 465 | nilfs_segctor_last_pseg_block_show(struct nilfs_segctor_attr *attr, | ||
| 466 | struct the_nilfs *nilfs, | ||
| 467 | char *buf) | ||
| 468 | { | ||
| 469 | sector_t last_pseg; | ||
| 470 | |||
| 471 | spin_lock(&nilfs->ns_last_segment_lock); | ||
| 472 | last_pseg = nilfs->ns_last_pseg; | ||
| 473 | spin_unlock(&nilfs->ns_last_segment_lock); | ||
| 474 | |||
| 475 | return snprintf(buf, PAGE_SIZE, "%llu\n", | ||
| 476 | (unsigned long long)last_pseg); | ||
| 477 | } | ||
| 478 | |||
| 479 | static ssize_t | ||
| 480 | nilfs_segctor_last_seg_sequence_show(struct nilfs_segctor_attr *attr, | ||
| 481 | struct the_nilfs *nilfs, | ||
| 482 | char *buf) | ||
| 483 | { | ||
| 484 | u64 last_seq; | ||
| 485 | |||
| 486 | spin_lock(&nilfs->ns_last_segment_lock); | ||
| 487 | last_seq = nilfs->ns_last_seq; | ||
| 488 | spin_unlock(&nilfs->ns_last_segment_lock); | ||
| 489 | |||
| 490 | return snprintf(buf, PAGE_SIZE, "%llu\n", last_seq); | ||
| 491 | } | ||
| 492 | |||
| 493 | static ssize_t | ||
| 494 | nilfs_segctor_last_seg_checkpoint_show(struct nilfs_segctor_attr *attr, | ||
| 495 | struct the_nilfs *nilfs, | ||
| 496 | char *buf) | ||
| 497 | { | ||
| 498 | __u64 last_cno; | ||
| 499 | |||
| 500 | spin_lock(&nilfs->ns_last_segment_lock); | ||
| 501 | last_cno = nilfs->ns_last_cno; | ||
| 502 | spin_unlock(&nilfs->ns_last_segment_lock); | ||
| 503 | |||
| 504 | return snprintf(buf, PAGE_SIZE, "%llu\n", last_cno); | ||
| 505 | } | ||
| 506 | |||
| 507 | static ssize_t | ||
| 508 | nilfs_segctor_current_seg_sequence_show(struct nilfs_segctor_attr *attr, | ||
| 509 | struct the_nilfs *nilfs, | ||
| 510 | char *buf) | ||
| 511 | { | ||
| 512 | u64 seg_seq; | ||
| 513 | |||
| 514 | down_read(&nilfs->ns_sem); | ||
| 515 | seg_seq = nilfs->ns_seg_seq; | ||
| 516 | up_read(&nilfs->ns_sem); | ||
| 517 | |||
| 518 | return snprintf(buf, PAGE_SIZE, "%llu\n", seg_seq); | ||
| 519 | } | ||
| 520 | |||
| 521 | static ssize_t | ||
| 522 | nilfs_segctor_current_last_full_seg_show(struct nilfs_segctor_attr *attr, | ||
| 523 | struct the_nilfs *nilfs, | ||
| 524 | char *buf) | ||
| 525 | { | ||
| 526 | __u64 segnum; | ||
| 527 | |||
| 528 | down_read(&nilfs->ns_sem); | ||
| 529 | segnum = nilfs->ns_segnum; | ||
| 530 | up_read(&nilfs->ns_sem); | ||
| 531 | |||
| 532 | return snprintf(buf, PAGE_SIZE, "%llu\n", segnum); | ||
| 533 | } | ||
| 534 | |||
| 535 | static ssize_t | ||
| 536 | nilfs_segctor_next_full_seg_show(struct nilfs_segctor_attr *attr, | ||
| 537 | struct the_nilfs *nilfs, | ||
| 538 | char *buf) | ||
| 539 | { | ||
| 540 | __u64 nextnum; | ||
| 541 | |||
| 542 | down_read(&nilfs->ns_sem); | ||
| 543 | nextnum = nilfs->ns_nextnum; | ||
| 544 | up_read(&nilfs->ns_sem); | ||
| 545 | |||
| 546 | return snprintf(buf, PAGE_SIZE, "%llu\n", nextnum); | ||
| 547 | } | ||
| 548 | |||
| 549 | static ssize_t | ||
| 550 | nilfs_segctor_next_pseg_offset_show(struct nilfs_segctor_attr *attr, | ||
| 551 | struct the_nilfs *nilfs, | ||
| 552 | char *buf) | ||
| 553 | { | ||
| 554 | unsigned long pseg_offset; | ||
| 555 | |||
| 556 | down_read(&nilfs->ns_sem); | ||
| 557 | pseg_offset = nilfs->ns_pseg_offset; | ||
| 558 | up_read(&nilfs->ns_sem); | ||
| 559 | |||
| 560 | return snprintf(buf, PAGE_SIZE, "%lu\n", pseg_offset); | ||
| 561 | } | ||
| 562 | |||
| 563 | static ssize_t | ||
| 564 | nilfs_segctor_next_checkpoint_show(struct nilfs_segctor_attr *attr, | ||
| 565 | struct the_nilfs *nilfs, | ||
| 566 | char *buf) | ||
| 567 | { | ||
| 568 | __u64 cno; | ||
| 569 | |||
| 570 | down_read(&nilfs->ns_sem); | ||
| 571 | cno = nilfs->ns_cno; | ||
| 572 | up_read(&nilfs->ns_sem); | ||
| 573 | |||
| 574 | return snprintf(buf, PAGE_SIZE, "%llu\n", cno); | ||
| 575 | } | ||
| 576 | |||
| 577 | static ssize_t | ||
| 578 | nilfs_segctor_last_seg_write_time_show(struct nilfs_segctor_attr *attr, | ||
| 579 | struct the_nilfs *nilfs, | ||
| 580 | char *buf) | ||
| 581 | { | ||
| 582 | time_t ctime; | ||
| 583 | |||
| 584 | down_read(&nilfs->ns_sem); | ||
| 585 | ctime = nilfs->ns_ctime; | ||
| 586 | up_read(&nilfs->ns_sem); | ||
| 587 | |||
| 588 | return NILFS_SHOW_TIME(ctime, buf); | ||
| 589 | } | ||
| 590 | |||
| 591 | static ssize_t | ||
| 592 | nilfs_segctor_last_seg_write_time_secs_show(struct nilfs_segctor_attr *attr, | ||
| 593 | struct the_nilfs *nilfs, | ||
| 594 | char *buf) | ||
| 595 | { | ||
| 596 | time_t ctime; | ||
| 597 | |||
| 598 | down_read(&nilfs->ns_sem); | ||
| 599 | ctime = nilfs->ns_ctime; | ||
| 600 | up_read(&nilfs->ns_sem); | ||
| 601 | |||
| 602 | return snprintf(buf, PAGE_SIZE, "%llu\n", (unsigned long long)ctime); | ||
| 603 | } | ||
| 604 | |||
| 605 | static ssize_t | ||
| 606 | nilfs_segctor_last_nongc_write_time_show(struct nilfs_segctor_attr *attr, | ||
| 607 | struct the_nilfs *nilfs, | ||
| 608 | char *buf) | ||
| 609 | { | ||
| 610 | time_t nongc_ctime; | ||
| 611 | |||
| 612 | down_read(&nilfs->ns_sem); | ||
| 613 | nongc_ctime = nilfs->ns_nongc_ctime; | ||
| 614 | up_read(&nilfs->ns_sem); | ||
| 615 | |||
| 616 | return NILFS_SHOW_TIME(nongc_ctime, buf); | ||
| 617 | } | ||
| 618 | |||
| 619 | static ssize_t | ||
| 620 | nilfs_segctor_last_nongc_write_time_secs_show(struct nilfs_segctor_attr *attr, | ||
| 621 | struct the_nilfs *nilfs, | ||
| 622 | char *buf) | ||
| 623 | { | ||
| 624 | time_t nongc_ctime; | ||
| 625 | |||
| 626 | down_read(&nilfs->ns_sem); | ||
| 627 | nongc_ctime = nilfs->ns_nongc_ctime; | ||
| 628 | up_read(&nilfs->ns_sem); | ||
| 629 | |||
| 630 | return snprintf(buf, PAGE_SIZE, "%llu\n", | ||
| 631 | (unsigned long long)nongc_ctime); | ||
| 632 | } | ||
| 633 | |||
| 634 | static ssize_t | ||
| 635 | nilfs_segctor_dirty_data_blocks_count_show(struct nilfs_segctor_attr *attr, | ||
| 636 | struct the_nilfs *nilfs, | ||
| 637 | char *buf) | ||
| 638 | { | ||
| 639 | u32 ndirtyblks; | ||
| 640 | |||
| 641 | down_read(&nilfs->ns_sem); | ||
| 642 | ndirtyblks = atomic_read(&nilfs->ns_ndirtyblks); | ||
| 643 | up_read(&nilfs->ns_sem); | ||
| 644 | |||
| 645 | return snprintf(buf, PAGE_SIZE, "%u\n", ndirtyblks); | ||
| 646 | } | ||
| 647 | |||
| 648 | static const char segctor_readme_str[] = | ||
| 649 | "The segctor group contains attributes that describe\n" | ||
| 650 | "segctor thread activity details.\n\n" | ||
| 651 | "(1) last_pseg_block\n" | ||
| 652 | "\tshow start block number of the latest segment.\n\n" | ||
| 653 | "(2) last_seg_sequence\n" | ||
| 654 | "\tshow sequence value of the latest segment.\n\n" | ||
| 655 | "(3) last_seg_checkpoint\n" | ||
| 656 | "\tshow checkpoint number of the latest segment.\n\n" | ||
| 657 | "(4) current_seg_sequence\n\tshow segment sequence counter.\n\n" | ||
| 658 | "(5) current_last_full_seg\n" | ||
| 659 | "\tshow index number of the latest full segment.\n\n" | ||
| 660 | "(6) next_full_seg\n" | ||
| 661 | "\tshow index number of the full segment index to be used next.\n\n" | ||
| 662 | "(7) next_pseg_offset\n" | ||
| 663 | "\tshow offset of next partial segment in the current full segment.\n\n" | ||
| 664 | "(8) next_checkpoint\n\tshow next checkpoint number.\n\n" | ||
| 665 | "(9) last_seg_write_time\n" | ||
| 666 | "\tshow write time of the last segment in human-readable format.\n\n" | ||
| 667 | "(10) last_seg_write_time_secs\n" | ||
| 668 | "\tshow write time of the last segment in seconds.\n\n" | ||
| 669 | "(11) last_nongc_write_time\n" | ||
| 670 | "\tshow write time of the last segment not for cleaner operation " | ||
| 671 | "in human-readable format.\n\n" | ||
| 672 | "(12) last_nongc_write_time_secs\n" | ||
| 673 | "\tshow write time of the last segment not for cleaner operation " | ||
| 674 | "in seconds.\n\n" | ||
| 675 | "(13) dirty_data_blocks_count\n" | ||
| 676 | "\tshow number of dirty data blocks.\n\n"; | ||
| 677 | |||
| 678 | static ssize_t | ||
| 679 | nilfs_segctor_README_show(struct nilfs_segctor_attr *attr, | ||
| 680 | struct the_nilfs *nilfs, char *buf) | ||
| 681 | { | ||
| 682 | return snprintf(buf, PAGE_SIZE, segctor_readme_str); | ||
| 683 | } | ||
| 684 | |||
| 685 | NILFS_SEGCTOR_RO_ATTR(last_pseg_block); | ||
| 686 | NILFS_SEGCTOR_RO_ATTR(last_seg_sequence); | ||
| 687 | NILFS_SEGCTOR_RO_ATTR(last_seg_checkpoint); | ||
| 688 | NILFS_SEGCTOR_RO_ATTR(current_seg_sequence); | ||
| 689 | NILFS_SEGCTOR_RO_ATTR(current_last_full_seg); | ||
| 690 | NILFS_SEGCTOR_RO_ATTR(next_full_seg); | ||
| 691 | NILFS_SEGCTOR_RO_ATTR(next_pseg_offset); | ||
| 692 | NILFS_SEGCTOR_RO_ATTR(next_checkpoint); | ||
| 693 | NILFS_SEGCTOR_RO_ATTR(last_seg_write_time); | ||
| 694 | NILFS_SEGCTOR_RO_ATTR(last_seg_write_time_secs); | ||
| 695 | NILFS_SEGCTOR_RO_ATTR(last_nongc_write_time); | ||
| 696 | NILFS_SEGCTOR_RO_ATTR(last_nongc_write_time_secs); | ||
| 697 | NILFS_SEGCTOR_RO_ATTR(dirty_data_blocks_count); | ||
| 698 | NILFS_SEGCTOR_RO_ATTR(README); | ||
| 699 | |||
| 700 | static struct attribute *nilfs_segctor_attrs[] = { | ||
| 701 | NILFS_SEGCTOR_ATTR_LIST(last_pseg_block), | ||
| 702 | NILFS_SEGCTOR_ATTR_LIST(last_seg_sequence), | ||
| 703 | NILFS_SEGCTOR_ATTR_LIST(last_seg_checkpoint), | ||
| 704 | NILFS_SEGCTOR_ATTR_LIST(current_seg_sequence), | ||
| 705 | NILFS_SEGCTOR_ATTR_LIST(current_last_full_seg), | ||
| 706 | NILFS_SEGCTOR_ATTR_LIST(next_full_seg), | ||
| 707 | NILFS_SEGCTOR_ATTR_LIST(next_pseg_offset), | ||
| 708 | NILFS_SEGCTOR_ATTR_LIST(next_checkpoint), | ||
| 709 | NILFS_SEGCTOR_ATTR_LIST(last_seg_write_time), | ||
| 710 | NILFS_SEGCTOR_ATTR_LIST(last_seg_write_time_secs), | ||
| 711 | NILFS_SEGCTOR_ATTR_LIST(last_nongc_write_time), | ||
| 712 | NILFS_SEGCTOR_ATTR_LIST(last_nongc_write_time_secs), | ||
| 713 | NILFS_SEGCTOR_ATTR_LIST(dirty_data_blocks_count), | ||
| 714 | NILFS_SEGCTOR_ATTR_LIST(README), | ||
| 715 | NULL, | ||
| 716 | }; | ||
| 717 | |||
| 718 | NILFS_DEV_INT_GROUP_OPS(segctor, dev); | ||
| 719 | NILFS_DEV_INT_GROUP_TYPE(segctor, dev); | ||
| 720 | NILFS_DEV_INT_GROUP_FNS(segctor, dev); | ||
| 721 | |||
| 722 | /************************************************************************ | ||
| 723 | * NILFS superblock attrs * | ||
| 724 | ************************************************************************/ | ||
| 725 | |||
| 726 | static ssize_t | ||
| 727 | nilfs_superblock_sb_write_time_show(struct nilfs_superblock_attr *attr, | ||
| 728 | struct the_nilfs *nilfs, | ||
| 729 | char *buf) | ||
| 730 | { | ||
| 731 | time_t sbwtime; | ||
| 732 | |||
| 733 | down_read(&nilfs->ns_sem); | ||
| 734 | sbwtime = nilfs->ns_sbwtime; | ||
| 735 | up_read(&nilfs->ns_sem); | ||
| 736 | |||
| 737 | return NILFS_SHOW_TIME(sbwtime, buf); | ||
| 738 | } | ||
| 739 | |||
| 740 | static ssize_t | ||
| 741 | nilfs_superblock_sb_write_time_secs_show(struct nilfs_superblock_attr *attr, | ||
| 742 | struct the_nilfs *nilfs, | ||
| 743 | char *buf) | ||
| 744 | { | ||
| 745 | time_t sbwtime; | ||
| 746 | |||
| 747 | down_read(&nilfs->ns_sem); | ||
| 748 | sbwtime = nilfs->ns_sbwtime; | ||
| 749 | up_read(&nilfs->ns_sem); | ||
| 750 | |||
| 751 | return snprintf(buf, PAGE_SIZE, "%llu\n", (unsigned long long)sbwtime); | ||
| 752 | } | ||
| 753 | |||
| 754 | static ssize_t | ||
| 755 | nilfs_superblock_sb_write_count_show(struct nilfs_superblock_attr *attr, | ||
| 756 | struct the_nilfs *nilfs, | ||
| 757 | char *buf) | ||
| 758 | { | ||
| 759 | unsigned sbwcount; | ||
| 760 | |||
| 761 | down_read(&nilfs->ns_sem); | ||
| 762 | sbwcount = nilfs->ns_sbwcount; | ||
| 763 | up_read(&nilfs->ns_sem); | ||
| 764 | |||
| 765 | return snprintf(buf, PAGE_SIZE, "%u\n", sbwcount); | ||
| 766 | } | ||
| 767 | |||
| 768 | static ssize_t | ||
| 769 | nilfs_superblock_sb_update_frequency_show(struct nilfs_superblock_attr *attr, | ||
| 770 | struct the_nilfs *nilfs, | ||
| 771 | char *buf) | ||
| 772 | { | ||
| 773 | unsigned sb_update_freq; | ||
| 774 | |||
| 775 | down_read(&nilfs->ns_sem); | ||
| 776 | sb_update_freq = nilfs->ns_sb_update_freq; | ||
| 777 | up_read(&nilfs->ns_sem); | ||
| 778 | |||
| 779 | return snprintf(buf, PAGE_SIZE, "%u\n", sb_update_freq); | ||
| 780 | } | ||
| 781 | |||
| 782 | static ssize_t | ||
| 783 | nilfs_superblock_sb_update_frequency_store(struct nilfs_superblock_attr *attr, | ||
| 784 | struct the_nilfs *nilfs, | ||
| 785 | const char *buf, size_t count) | ||
| 786 | { | ||
| 787 | unsigned val; | ||
| 788 | int err; | ||
| 789 | |||
| 790 | err = kstrtouint(skip_spaces(buf), 0, &val); | ||
| 791 | if (err) { | ||
| 792 | printk(KERN_ERR "NILFS: unable to convert string: err=%d\n", | ||
| 793 | err); | ||
| 794 | return err; | ||
| 795 | } | ||
| 796 | |||
| 797 | if (val < NILFS_SB_FREQ) { | ||
| 798 | val = NILFS_SB_FREQ; | ||
| 799 | printk(KERN_WARNING "NILFS: superblock update frequency cannot be lesser than 10 seconds\n"); | ||
| 800 | } | ||
| 801 | |||
| 802 | down_write(&nilfs->ns_sem); | ||
| 803 | nilfs->ns_sb_update_freq = val; | ||
| 804 | up_write(&nilfs->ns_sem); | ||
| 805 | |||
| 806 | return count; | ||
| 807 | } | ||
| 808 | |||
| 809 | static const char sb_readme_str[] = | ||
| 810 | "The superblock group contains attributes that describe\n" | ||
| 811 | "superblock's details.\n\n" | ||
| 812 | "(1) sb_write_time\n\tshow previous write time of super block " | ||
| 813 | "in human-readable format.\n\n" | ||
| 814 | "(2) sb_write_time_secs\n\tshow previous write time of super block " | ||
| 815 | "in seconds.\n\n" | ||
| 816 | "(3) sb_write_count\n\tshow write count of super block.\n\n" | ||
| 817 | "(4) sb_update_frequency\n" | ||
| 818 | "\tshow/set interval of periodical update of superblock (in seconds).\n\n" | ||
| 819 | "\tYou can set preferable frequency of superblock update by command:\n\n" | ||
| 820 | "\t'echo <val> > /sys/fs/<nilfs>/<dev>/superblock/sb_update_frequency'\n"; | ||
| 821 | |||
| 822 | static ssize_t | ||
| 823 | nilfs_superblock_README_show(struct nilfs_superblock_attr *attr, | ||
| 824 | struct the_nilfs *nilfs, char *buf) | ||
| 825 | { | ||
| 826 | return snprintf(buf, PAGE_SIZE, sb_readme_str); | ||
| 827 | } | ||
| 828 | |||
| 829 | NILFS_SUPERBLOCK_RO_ATTR(sb_write_time); | ||
| 830 | NILFS_SUPERBLOCK_RO_ATTR(sb_write_time_secs); | ||
| 831 | NILFS_SUPERBLOCK_RO_ATTR(sb_write_count); | ||
| 832 | NILFS_SUPERBLOCK_RW_ATTR(sb_update_frequency); | ||
| 833 | NILFS_SUPERBLOCK_RO_ATTR(README); | ||
| 834 | |||
| 835 | static struct attribute *nilfs_superblock_attrs[] = { | ||
| 836 | NILFS_SUPERBLOCK_ATTR_LIST(sb_write_time), | ||
| 837 | NILFS_SUPERBLOCK_ATTR_LIST(sb_write_time_secs), | ||
| 838 | NILFS_SUPERBLOCK_ATTR_LIST(sb_write_count), | ||
| 839 | NILFS_SUPERBLOCK_ATTR_LIST(sb_update_frequency), | ||
| 840 | NILFS_SUPERBLOCK_ATTR_LIST(README), | ||
| 841 | NULL, | ||
| 842 | }; | ||
| 843 | |||
| 844 | NILFS_DEV_INT_GROUP_OPS(superblock, dev); | ||
| 845 | NILFS_DEV_INT_GROUP_TYPE(superblock, dev); | ||
| 846 | NILFS_DEV_INT_GROUP_FNS(superblock, dev); | ||
| 847 | |||
| 848 | /************************************************************************ | ||
| 849 | * NILFS device attrs * | ||
| 850 | ************************************************************************/ | ||
| 851 | |||
| 852 | static | ||
| 853 | ssize_t nilfs_dev_revision_show(struct nilfs_dev_attr *attr, | ||
| 854 | struct the_nilfs *nilfs, | ||
| 855 | char *buf) | ||
| 856 | { | ||
| 857 | struct nilfs_super_block **sbp = nilfs->ns_sbp; | ||
| 858 | u32 major = le32_to_cpu(sbp[0]->s_rev_level); | ||
| 859 | u16 minor = le16_to_cpu(sbp[0]->s_minor_rev_level); | ||
| 860 | |||
| 861 | return snprintf(buf, PAGE_SIZE, "%d.%d\n", major, minor); | ||
| 862 | } | ||
| 863 | |||
| 864 | static | ||
| 865 | ssize_t nilfs_dev_blocksize_show(struct nilfs_dev_attr *attr, | ||
| 866 | struct the_nilfs *nilfs, | ||
| 867 | char *buf) | ||
| 868 | { | ||
| 869 | return snprintf(buf, PAGE_SIZE, "%u\n", nilfs->ns_blocksize); | ||
| 870 | } | ||
| 871 | |||
| 872 | static | ||
| 873 | ssize_t nilfs_dev_device_size_show(struct nilfs_dev_attr *attr, | ||
| 874 | struct the_nilfs *nilfs, | ||
| 875 | char *buf) | ||
| 876 | { | ||
| 877 | struct nilfs_super_block **sbp = nilfs->ns_sbp; | ||
| 878 | u64 dev_size = le64_to_cpu(sbp[0]->s_dev_size); | ||
| 879 | |||
| 880 | return snprintf(buf, PAGE_SIZE, "%llu\n", dev_size); | ||
| 881 | } | ||
| 882 | |||
| 883 | static | ||
| 884 | ssize_t nilfs_dev_free_blocks_show(struct nilfs_dev_attr *attr, | ||
| 885 | struct the_nilfs *nilfs, | ||
| 886 | char *buf) | ||
| 887 | { | ||
| 888 | sector_t free_blocks = 0; | ||
| 889 | |||
| 890 | nilfs_count_free_blocks(nilfs, &free_blocks); | ||
| 891 | return snprintf(buf, PAGE_SIZE, "%llu\n", | ||
| 892 | (unsigned long long)free_blocks); | ||
| 893 | } | ||
| 894 | |||
| 895 | static | ||
| 896 | ssize_t nilfs_dev_uuid_show(struct nilfs_dev_attr *attr, | ||
| 897 | struct the_nilfs *nilfs, | ||
| 898 | char *buf) | ||
| 899 | { | ||
| 900 | struct nilfs_super_block **sbp = nilfs->ns_sbp; | ||
| 901 | |||
| 902 | return snprintf(buf, PAGE_SIZE, "%pUb\n", sbp[0]->s_uuid); | ||
| 903 | } | ||
| 904 | |||
| 905 | static | ||
| 906 | ssize_t nilfs_dev_volume_name_show(struct nilfs_dev_attr *attr, | ||
| 907 | struct the_nilfs *nilfs, | ||
| 908 | char *buf) | ||
| 909 | { | ||
| 910 | struct nilfs_super_block **sbp = nilfs->ns_sbp; | ||
| 911 | |||
| 912 | return scnprintf(buf, sizeof(sbp[0]->s_volume_name), "%s\n", | ||
| 913 | sbp[0]->s_volume_name); | ||
| 914 | } | ||
| 915 | |||
| 916 | static const char dev_readme_str[] = | ||
| 917 | "The <device> group contains attributes that describe file system\n" | ||
| 918 | "partition's details.\n\n" | ||
| 919 | "(1) revision\n\tshow NILFS file system revision.\n\n" | ||
| 920 | "(2) blocksize\n\tshow volume block size in bytes.\n\n" | ||
| 921 | "(3) device_size\n\tshow volume size in bytes.\n\n" | ||
| 922 | "(4) free_blocks\n\tshow count of free blocks on volume.\n\n" | ||
| 923 | "(5) uuid\n\tshow volume's UUID.\n\n" | ||
| 924 | "(6) volume_name\n\tshow volume's name.\n\n"; | ||
| 925 | |||
| 926 | static ssize_t nilfs_dev_README_show(struct nilfs_dev_attr *attr, | ||
| 927 | struct the_nilfs *nilfs, | ||
| 928 | char *buf) | ||
| 929 | { | ||
| 930 | return snprintf(buf, PAGE_SIZE, dev_readme_str); | ||
| 931 | } | ||
| 932 | |||
| 933 | NILFS_DEV_RO_ATTR(revision); | ||
| 934 | NILFS_DEV_RO_ATTR(blocksize); | ||
| 935 | NILFS_DEV_RO_ATTR(device_size); | ||
| 936 | NILFS_DEV_RO_ATTR(free_blocks); | ||
| 937 | NILFS_DEV_RO_ATTR(uuid); | ||
| 938 | NILFS_DEV_RO_ATTR(volume_name); | ||
| 939 | NILFS_DEV_RO_ATTR(README); | ||
| 940 | |||
| 941 | static struct attribute *nilfs_dev_attrs[] = { | ||
| 942 | NILFS_DEV_ATTR_LIST(revision), | ||
| 943 | NILFS_DEV_ATTR_LIST(blocksize), | ||
| 944 | NILFS_DEV_ATTR_LIST(device_size), | ||
| 945 | NILFS_DEV_ATTR_LIST(free_blocks), | ||
| 946 | NILFS_DEV_ATTR_LIST(uuid), | ||
| 947 | NILFS_DEV_ATTR_LIST(volume_name), | ||
| 948 | NILFS_DEV_ATTR_LIST(README), | ||
| 949 | NULL, | ||
| 950 | }; | ||
| 951 | |||
| 952 | static ssize_t nilfs_dev_attr_show(struct kobject *kobj, | ||
| 953 | struct attribute *attr, char *buf) | ||
| 954 | { | ||
| 955 | struct the_nilfs *nilfs = container_of(kobj, struct the_nilfs, | ||
| 956 | ns_dev_kobj); | ||
| 957 | struct nilfs_dev_attr *a = container_of(attr, struct nilfs_dev_attr, | ||
| 958 | attr); | ||
| 959 | |||
| 960 | return a->show ? a->show(a, nilfs, buf) : 0; | ||
| 961 | } | ||
| 962 | |||
| 963 | static ssize_t nilfs_dev_attr_store(struct kobject *kobj, | ||
| 964 | struct attribute *attr, | ||
| 965 | const char *buf, size_t len) | ||
| 966 | { | ||
| 967 | struct the_nilfs *nilfs = container_of(kobj, struct the_nilfs, | ||
| 968 | ns_dev_kobj); | ||
| 969 | struct nilfs_dev_attr *a = container_of(attr, struct nilfs_dev_attr, | ||
| 970 | attr); | ||
| 971 | |||
| 972 | return a->store ? a->store(a, nilfs, buf, len) : 0; | ||
| 973 | } | ||
| 974 | |||
| 975 | static void nilfs_dev_attr_release(struct kobject *kobj) | ||
| 976 | { | ||
| 977 | struct the_nilfs *nilfs = container_of(kobj, struct the_nilfs, | ||
| 978 | ns_dev_kobj); | ||
| 979 | complete(&nilfs->ns_dev_kobj_unregister); | ||
| 980 | } | ||
| 981 | |||
| 982 | static const struct sysfs_ops nilfs_dev_attr_ops = { | ||
| 983 | .show = nilfs_dev_attr_show, | ||
| 984 | .store = nilfs_dev_attr_store, | ||
| 985 | }; | ||
| 986 | |||
| 987 | static struct kobj_type nilfs_dev_ktype = { | ||
| 988 | .default_attrs = nilfs_dev_attrs, | ||
| 989 | .sysfs_ops = &nilfs_dev_attr_ops, | ||
| 990 | .release = nilfs_dev_attr_release, | ||
| 991 | }; | ||
| 992 | |||
| 993 | int nilfs_sysfs_create_device_group(struct super_block *sb) | ||
| 994 | { | ||
| 995 | struct the_nilfs *nilfs = sb->s_fs_info; | ||
| 996 | size_t devgrp_size = sizeof(struct nilfs_sysfs_dev_subgroups); | ||
| 997 | int err; | ||
| 998 | |||
| 999 | nilfs->ns_dev_subgroups = kzalloc(devgrp_size, GFP_KERNEL); | ||
| 1000 | if (unlikely(!nilfs->ns_dev_subgroups)) { | ||
| 1001 | err = -ENOMEM; | ||
| 1002 | printk(KERN_ERR "NILFS: unable to allocate memory for device group\n"); | ||
| 1003 | goto failed_create_device_group; | ||
| 1004 | } | ||
| 1005 | |||
| 1006 | nilfs->ns_dev_kobj.kset = nilfs_kset; | ||
| 1007 | init_completion(&nilfs->ns_dev_kobj_unregister); | ||
| 1008 | err = kobject_init_and_add(&nilfs->ns_dev_kobj, &nilfs_dev_ktype, NULL, | ||
| 1009 | "%s", sb->s_id); | ||
| 1010 | if (err) | ||
| 1011 | goto free_dev_subgroups; | ||
| 1012 | |||
| 1013 | err = nilfs_sysfs_create_mounted_snapshots_group(nilfs); | ||
| 1014 | if (err) | ||
| 1015 | goto cleanup_dev_kobject; | ||
| 1016 | |||
| 1017 | err = nilfs_sysfs_create_checkpoints_group(nilfs); | ||
| 1018 | if (err) | ||
| 1019 | goto delete_mounted_snapshots_group; | ||
| 1020 | |||
| 1021 | err = nilfs_sysfs_create_segments_group(nilfs); | ||
| 1022 | if (err) | ||
| 1023 | goto delete_checkpoints_group; | ||
| 1024 | |||
| 1025 | err = nilfs_sysfs_create_superblock_group(nilfs); | ||
| 1026 | if (err) | ||
| 1027 | goto delete_segments_group; | ||
| 1028 | |||
| 1029 | err = nilfs_sysfs_create_segctor_group(nilfs); | ||
| 1030 | if (err) | ||
| 1031 | goto delete_superblock_group; | ||
| 1032 | |||
| 1033 | return 0; | ||
| 1034 | |||
| 1035 | delete_superblock_group: | ||
| 1036 | nilfs_sysfs_delete_superblock_group(nilfs); | ||
| 1037 | |||
| 1038 | delete_segments_group: | ||
| 1039 | nilfs_sysfs_delete_segments_group(nilfs); | ||
| 1040 | |||
| 1041 | delete_checkpoints_group: | ||
| 1042 | nilfs_sysfs_delete_checkpoints_group(nilfs); | ||
| 1043 | |||
| 1044 | delete_mounted_snapshots_group: | ||
| 1045 | nilfs_sysfs_delete_mounted_snapshots_group(nilfs); | ||
| 1046 | |||
| 1047 | cleanup_dev_kobject: | ||
| 1048 | kobject_del(&nilfs->ns_dev_kobj); | ||
| 1049 | |||
| 1050 | free_dev_subgroups: | ||
| 1051 | kfree(nilfs->ns_dev_subgroups); | ||
| 1052 | |||
| 1053 | failed_create_device_group: | ||
| 1054 | return err; | ||
| 1055 | } | ||
| 1056 | |||
| 1057 | void nilfs_sysfs_delete_device_group(struct the_nilfs *nilfs) | ||
| 1058 | { | ||
| 1059 | nilfs_sysfs_delete_mounted_snapshots_group(nilfs); | ||
| 1060 | nilfs_sysfs_delete_checkpoints_group(nilfs); | ||
| 1061 | nilfs_sysfs_delete_segments_group(nilfs); | ||
| 1062 | nilfs_sysfs_delete_superblock_group(nilfs); | ||
| 1063 | nilfs_sysfs_delete_segctor_group(nilfs); | ||
| 1064 | kobject_del(&nilfs->ns_dev_kobj); | ||
| 1065 | kfree(nilfs->ns_dev_subgroups); | ||
| 1066 | } | ||
| 1067 | |||
| 1068 | /************************************************************************ | ||
| 1069 | * NILFS feature attrs * | ||
| 1070 | ************************************************************************/ | ||
| 1071 | |||
| 1072 | static ssize_t nilfs_feature_revision_show(struct kobject *kobj, | ||
| 1073 | struct attribute *attr, char *buf) | ||
| 1074 | { | ||
| 1075 | return snprintf(buf, PAGE_SIZE, "%d.%d\n", | ||
| 1076 | NILFS_CURRENT_REV, NILFS_MINOR_REV); | ||
| 1077 | } | ||
| 1078 | |||
| 1079 | static const char features_readme_str[] = | ||
| 1080 | "The features group contains attributes that describe NILFS file\n" | ||
| 1081 | "system driver features.\n\n" | ||
| 1082 | "(1) revision\n\tshow current revision of NILFS file system driver.\n"; | ||
| 1083 | |||
| 1084 | static ssize_t nilfs_feature_README_show(struct kobject *kobj, | ||
| 1085 | struct attribute *attr, | ||
| 1086 | char *buf) | ||
| 1087 | { | ||
| 1088 | return snprintf(buf, PAGE_SIZE, features_readme_str); | ||
| 1089 | } | ||
| 1090 | |||
| 1091 | NILFS_FEATURE_RO_ATTR(revision); | ||
| 1092 | NILFS_FEATURE_RO_ATTR(README); | ||
| 1093 | |||
| 1094 | static struct attribute *nilfs_feature_attrs[] = { | ||
| 1095 | NILFS_FEATURE_ATTR_LIST(revision), | ||
| 1096 | NILFS_FEATURE_ATTR_LIST(README), | ||
| 1097 | NULL, | ||
| 1098 | }; | ||
| 1099 | |||
| 1100 | static const struct attribute_group nilfs_feature_attr_group = { | ||
| 1101 | .name = "features", | ||
| 1102 | .attrs = nilfs_feature_attrs, | ||
| 1103 | }; | ||
| 1104 | |||
| 1105 | int __init nilfs_sysfs_init(void) | ||
| 1106 | { | ||
| 1107 | int err; | ||
| 1108 | |||
| 1109 | nilfs_kset = kset_create_and_add(NILFS_ROOT_GROUP_NAME, NULL, fs_kobj); | ||
| 1110 | if (!nilfs_kset) { | ||
| 1111 | err = -ENOMEM; | ||
| 1112 | printk(KERN_ERR "NILFS: unable to create sysfs entry: err %d\n", | ||
| 1113 | err); | ||
| 1114 | goto failed_sysfs_init; | ||
| 1115 | } | ||
| 1116 | |||
| 1117 | err = sysfs_create_group(&nilfs_kset->kobj, &nilfs_feature_attr_group); | ||
| 1118 | if (unlikely(err)) { | ||
| 1119 | printk(KERN_ERR "NILFS: unable to create feature group: err %d\n", | ||
| 1120 | err); | ||
| 1121 | goto cleanup_sysfs_init; | ||
| 1122 | } | ||
| 1123 | |||
| 1124 | return 0; | ||
| 1125 | |||
| 1126 | cleanup_sysfs_init: | ||
| 1127 | kset_unregister(nilfs_kset); | ||
| 1128 | |||
| 1129 | failed_sysfs_init: | ||
| 1130 | return err; | ||
| 1131 | } | ||
| 1132 | |||
| 1133 | void nilfs_sysfs_exit(void) | ||
| 1134 | { | ||
| 1135 | sysfs_remove_group(&nilfs_kset->kobj, &nilfs_feature_attr_group); | ||
| 1136 | kset_unregister(nilfs_kset); | ||
| 1137 | } | ||
diff --git a/fs/nilfs2/sysfs.h b/fs/nilfs2/sysfs.h new file mode 100644 index 000000000000..677e3a1a8370 --- /dev/null +++ b/fs/nilfs2/sysfs.h | |||
| @@ -0,0 +1,176 @@ | |||
| 1 | /* | ||
| 2 | * sysfs.h - sysfs support declarations. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2005-2014 Nippon Telegraph and Telephone Corporation. | ||
| 5 | * Copyright (C) 2014 HGST, Inc., a Western Digital Company. | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * Written by Vyacheslav Dubeyko <Vyacheslav.Dubeyko@hgst.com> | ||
| 18 | */ | ||
| 19 | |||
| 20 | #ifndef _NILFS_SYSFS_H | ||
| 21 | #define _NILFS_SYSFS_H | ||
| 22 | |||
| 23 | #include <linux/sysfs.h> | ||
| 24 | |||
| 25 | #define NILFS_ROOT_GROUP_NAME "nilfs2" | ||
| 26 | |||
| 27 | /* | ||
| 28 | * struct nilfs_sysfs_dev_subgroups - device subgroup kernel objects | ||
| 29 | * @sg_superblock_kobj: /sys/fs/<nilfs>/<device>/superblock | ||
| 30 | * @sg_superblock_kobj_unregister: completion state | ||
| 31 | * @sg_segctor_kobj: /sys/fs/<nilfs>/<device>/segctor | ||
| 32 | * @sg_segctor_kobj_unregister: completion state | ||
| 33 | * @sg_mounted_snapshots_kobj: /sys/fs/<nilfs>/<device>/mounted_snapshots | ||
| 34 | * @sg_mounted_snapshots_kobj_unregister: completion state | ||
| 35 | * @sg_checkpoints_kobj: /sys/fs/<nilfs>/<device>/checkpoints | ||
| 36 | * @sg_checkpoints_kobj_unregister: completion state | ||
| 37 | * @sg_segments_kobj: /sys/fs/<nilfs>/<device>/segments | ||
| 38 | * @sg_segments_kobj_unregister: completion state | ||
| 39 | */ | ||
| 40 | struct nilfs_sysfs_dev_subgroups { | ||
| 41 | /* /sys/fs/<nilfs>/<device>/superblock */ | ||
| 42 | struct kobject sg_superblock_kobj; | ||
| 43 | struct completion sg_superblock_kobj_unregister; | ||
| 44 | |||
| 45 | /* /sys/fs/<nilfs>/<device>/segctor */ | ||
| 46 | struct kobject sg_segctor_kobj; | ||
| 47 | struct completion sg_segctor_kobj_unregister; | ||
| 48 | |||
| 49 | /* /sys/fs/<nilfs>/<device>/mounted_snapshots */ | ||
| 50 | struct kobject sg_mounted_snapshots_kobj; | ||
| 51 | struct completion sg_mounted_snapshots_kobj_unregister; | ||
| 52 | |||
| 53 | /* /sys/fs/<nilfs>/<device>/checkpoints */ | ||
| 54 | struct kobject sg_checkpoints_kobj; | ||
| 55 | struct completion sg_checkpoints_kobj_unregister; | ||
| 56 | |||
| 57 | /* /sys/fs/<nilfs>/<device>/segments */ | ||
| 58 | struct kobject sg_segments_kobj; | ||
| 59 | struct completion sg_segments_kobj_unregister; | ||
| 60 | }; | ||
| 61 | |||
| 62 | #define NILFS_COMMON_ATTR_STRUCT(name) \ | ||
| 63 | struct nilfs_##name##_attr { \ | ||
| 64 | struct attribute attr; \ | ||
| 65 | ssize_t (*show)(struct kobject *, struct attribute *, \ | ||
| 66 | char *); \ | ||
| 67 | ssize_t (*store)(struct kobject *, struct attribute *, \ | ||
| 68 | const char *, size_t); \ | ||
| 69 | }; | ||
| 70 | |||
| 71 | NILFS_COMMON_ATTR_STRUCT(feature); | ||
| 72 | |||
| 73 | #define NILFS_DEV_ATTR_STRUCT(name) \ | ||
| 74 | struct nilfs_##name##_attr { \ | ||
| 75 | struct attribute attr; \ | ||
| 76 | ssize_t (*show)(struct nilfs_##name##_attr *, struct the_nilfs *, \ | ||
| 77 | char *); \ | ||
| 78 | ssize_t (*store)(struct nilfs_##name##_attr *, struct the_nilfs *, \ | ||
| 79 | const char *, size_t); \ | ||
| 80 | }; | ||
| 81 | |||
| 82 | NILFS_DEV_ATTR_STRUCT(dev); | ||
| 83 | NILFS_DEV_ATTR_STRUCT(segments); | ||
| 84 | NILFS_DEV_ATTR_STRUCT(mounted_snapshots); | ||
| 85 | NILFS_DEV_ATTR_STRUCT(checkpoints); | ||
| 86 | NILFS_DEV_ATTR_STRUCT(superblock); | ||
| 87 | NILFS_DEV_ATTR_STRUCT(segctor); | ||
| 88 | |||
| 89 | #define NILFS_CP_ATTR_STRUCT(name) \ | ||
| 90 | struct nilfs_##name##_attr { \ | ||
| 91 | struct attribute attr; \ | ||
| 92 | ssize_t (*show)(struct nilfs_##name##_attr *, struct nilfs_root *, \ | ||
| 93 | char *); \ | ||
| 94 | ssize_t (*store)(struct nilfs_##name##_attr *, struct nilfs_root *, \ | ||
| 95 | const char *, size_t); \ | ||
| 96 | }; | ||
| 97 | |||
| 98 | NILFS_CP_ATTR_STRUCT(snapshot); | ||
| 99 | |||
| 100 | #define NILFS_ATTR(type, name, mode, show, store) \ | ||
| 101 | static struct nilfs_##type##_attr nilfs_##type##_attr_##name = \ | ||
| 102 | __ATTR(name, mode, show, store) | ||
| 103 | |||
| 104 | #define NILFS_INFO_ATTR(type, name) \ | ||
| 105 | NILFS_ATTR(type, name, 0444, NULL, NULL) | ||
| 106 | #define NILFS_RO_ATTR(type, name) \ | ||
| 107 | NILFS_ATTR(type, name, 0444, nilfs_##type##_##name##_show, NULL) | ||
| 108 | #define NILFS_RW_ATTR(type, name) \ | ||
| 109 | NILFS_ATTR(type, name, 0644, \ | ||
| 110 | nilfs_##type##_##name##_show, \ | ||
| 111 | nilfs_##type##_##name##_store) | ||
| 112 | |||
| 113 | #define NILFS_FEATURE_INFO_ATTR(name) \ | ||
| 114 | NILFS_INFO_ATTR(feature, name) | ||
| 115 | #define NILFS_FEATURE_RO_ATTR(name) \ | ||
| 116 | NILFS_RO_ATTR(feature, name) | ||
| 117 | #define NILFS_FEATURE_RW_ATTR(name) \ | ||
| 118 | NILFS_RW_ATTR(feature, name) | ||
| 119 | |||
| 120 | #define NILFS_DEV_INFO_ATTR(name) \ | ||
| 121 | NILFS_INFO_ATTR(dev, name) | ||
| 122 | #define NILFS_DEV_RO_ATTR(name) \ | ||
| 123 | NILFS_RO_ATTR(dev, name) | ||
| 124 | #define NILFS_DEV_RW_ATTR(name) \ | ||
| 125 | NILFS_RW_ATTR(dev, name) | ||
| 126 | |||
| 127 | #define NILFS_SEGMENTS_RO_ATTR(name) \ | ||
| 128 | NILFS_RO_ATTR(segments, name) | ||
| 129 | #define NILFS_SEGMENTS_RW_ATTR(name) \ | ||
| 130 | NILFS_RW_ATTR(segs_info, name) | ||
| 131 | |||
| 132 | #define NILFS_MOUNTED_SNAPSHOTS_RO_ATTR(name) \ | ||
| 133 | NILFS_RO_ATTR(mounted_snapshots, name) | ||
| 134 | |||
| 135 | #define NILFS_CHECKPOINTS_RO_ATTR(name) \ | ||
| 136 | NILFS_RO_ATTR(checkpoints, name) | ||
| 137 | #define NILFS_CHECKPOINTS_RW_ATTR(name) \ | ||
| 138 | NILFS_RW_ATTR(checkpoints, name) | ||
| 139 | |||
| 140 | #define NILFS_SNAPSHOT_INFO_ATTR(name) \ | ||
| 141 | NILFS_INFO_ATTR(snapshot, name) | ||
| 142 | #define NILFS_SNAPSHOT_RO_ATTR(name) \ | ||
| 143 | NILFS_RO_ATTR(snapshot, name) | ||
| 144 | #define NILFS_SNAPSHOT_RW_ATTR(name) \ | ||
| 145 | NILFS_RW_ATTR(snapshot, name) | ||
| 146 | |||
| 147 | #define NILFS_SUPERBLOCK_RO_ATTR(name) \ | ||
| 148 | NILFS_RO_ATTR(superblock, name) | ||
| 149 | #define NILFS_SUPERBLOCK_RW_ATTR(name) \ | ||
| 150 | NILFS_RW_ATTR(superblock, name) | ||
| 151 | |||
| 152 | #define NILFS_SEGCTOR_INFO_ATTR(name) \ | ||
| 153 | NILFS_INFO_ATTR(segctor, name) | ||
| 154 | #define NILFS_SEGCTOR_RO_ATTR(name) \ | ||
| 155 | NILFS_RO_ATTR(segctor, name) | ||
| 156 | #define NILFS_SEGCTOR_RW_ATTR(name) \ | ||
| 157 | NILFS_RW_ATTR(segctor, name) | ||
| 158 | |||
| 159 | #define NILFS_FEATURE_ATTR_LIST(name) \ | ||
| 160 | (&nilfs_feature_attr_##name.attr) | ||
| 161 | #define NILFS_DEV_ATTR_LIST(name) \ | ||
| 162 | (&nilfs_dev_attr_##name.attr) | ||
| 163 | #define NILFS_SEGMENTS_ATTR_LIST(name) \ | ||
| 164 | (&nilfs_segments_attr_##name.attr) | ||
| 165 | #define NILFS_MOUNTED_SNAPSHOTS_ATTR_LIST(name) \ | ||
| 166 | (&nilfs_mounted_snapshots_attr_##name.attr) | ||
| 167 | #define NILFS_CHECKPOINTS_ATTR_LIST(name) \ | ||
| 168 | (&nilfs_checkpoints_attr_##name.attr) | ||
| 169 | #define NILFS_SNAPSHOT_ATTR_LIST(name) \ | ||
| 170 | (&nilfs_snapshot_attr_##name.attr) | ||
| 171 | #define NILFS_SUPERBLOCK_ATTR_LIST(name) \ | ||
| 172 | (&nilfs_superblock_attr_##name.attr) | ||
| 173 | #define NILFS_SEGCTOR_ATTR_LIST(name) \ | ||
| 174 | (&nilfs_segctor_attr_##name.attr) | ||
| 175 | |||
| 176 | #endif /* _NILFS_SYSFS_H */ | ||
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c index 8ba8229ba076..9da25fe9ea61 100644 --- a/fs/nilfs2/the_nilfs.c +++ b/fs/nilfs2/the_nilfs.c | |||
| @@ -85,6 +85,7 @@ struct the_nilfs *alloc_nilfs(struct block_device *bdev) | |||
| 85 | nilfs->ns_cptree = RB_ROOT; | 85 | nilfs->ns_cptree = RB_ROOT; |
| 86 | spin_lock_init(&nilfs->ns_cptree_lock); | 86 | spin_lock_init(&nilfs->ns_cptree_lock); |
| 87 | init_rwsem(&nilfs->ns_segctor_sem); | 87 | init_rwsem(&nilfs->ns_segctor_sem); |
| 88 | nilfs->ns_sb_update_freq = NILFS_SB_FREQ; | ||
| 88 | 89 | ||
| 89 | return nilfs; | 90 | return nilfs; |
| 90 | } | 91 | } |
| @@ -97,6 +98,7 @@ void destroy_nilfs(struct the_nilfs *nilfs) | |||
| 97 | { | 98 | { |
| 98 | might_sleep(); | 99 | might_sleep(); |
| 99 | if (nilfs_init(nilfs)) { | 100 | if (nilfs_init(nilfs)) { |
| 101 | nilfs_sysfs_delete_device_group(nilfs); | ||
| 100 | brelse(nilfs->ns_sbh[0]); | 102 | brelse(nilfs->ns_sbh[0]); |
| 101 | brelse(nilfs->ns_sbh[1]); | 103 | brelse(nilfs->ns_sbh[1]); |
| 102 | } | 104 | } |
| @@ -640,6 +642,10 @@ int init_nilfs(struct the_nilfs *nilfs, struct super_block *sb, char *data) | |||
| 640 | if (err) | 642 | if (err) |
| 641 | goto failed_sbh; | 643 | goto failed_sbh; |
| 642 | 644 | ||
| 645 | err = nilfs_sysfs_create_device_group(sb); | ||
| 646 | if (err) | ||
| 647 | goto failed_sbh; | ||
| 648 | |||
| 643 | set_nilfs_init(nilfs); | 649 | set_nilfs_init(nilfs); |
| 644 | err = 0; | 650 | err = 0; |
| 645 | out: | 651 | out: |
| @@ -740,12 +746,13 @@ nilfs_find_or_create_root(struct the_nilfs *nilfs, __u64 cno) | |||
| 740 | { | 746 | { |
| 741 | struct rb_node **p, *parent; | 747 | struct rb_node **p, *parent; |
| 742 | struct nilfs_root *root, *new; | 748 | struct nilfs_root *root, *new; |
| 749 | int err; | ||
| 743 | 750 | ||
| 744 | root = nilfs_lookup_root(nilfs, cno); | 751 | root = nilfs_lookup_root(nilfs, cno); |
| 745 | if (root) | 752 | if (root) |
| 746 | return root; | 753 | return root; |
| 747 | 754 | ||
| 748 | new = kmalloc(sizeof(*root), GFP_KERNEL); | 755 | new = kzalloc(sizeof(*root), GFP_KERNEL); |
| 749 | if (!new) | 756 | if (!new) |
| 750 | return NULL; | 757 | return NULL; |
| 751 | 758 | ||
| @@ -782,6 +789,12 @@ nilfs_find_or_create_root(struct the_nilfs *nilfs, __u64 cno) | |||
| 782 | 789 | ||
| 783 | spin_unlock(&nilfs->ns_cptree_lock); | 790 | spin_unlock(&nilfs->ns_cptree_lock); |
| 784 | 791 | ||
| 792 | err = nilfs_sysfs_create_snapshot_group(new); | ||
| 793 | if (err) { | ||
| 794 | kfree(new); | ||
| 795 | new = NULL; | ||
| 796 | } | ||
| 797 | |||
| 785 | return new; | 798 | return new; |
| 786 | } | 799 | } |
| 787 | 800 | ||
| @@ -790,6 +803,8 @@ void nilfs_put_root(struct nilfs_root *root) | |||
| 790 | if (atomic_dec_and_test(&root->count)) { | 803 | if (atomic_dec_and_test(&root->count)) { |
| 791 | struct the_nilfs *nilfs = root->nilfs; | 804 | struct the_nilfs *nilfs = root->nilfs; |
| 792 | 805 | ||
| 806 | nilfs_sysfs_delete_snapshot_group(root); | ||
| 807 | |||
| 793 | spin_lock(&nilfs->ns_cptree_lock); | 808 | spin_lock(&nilfs->ns_cptree_lock); |
| 794 | rb_erase(&root->rb_node, &nilfs->ns_cptree); | 809 | rb_erase(&root->rb_node, &nilfs->ns_cptree); |
| 795 | spin_unlock(&nilfs->ns_cptree_lock); | 810 | spin_unlock(&nilfs->ns_cptree_lock); |
diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index de8cc53b4a5c..d01ead1bea9a 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
| 34 | 34 | ||
| 35 | struct nilfs_sc_info; | 35 | struct nilfs_sc_info; |
| 36 | struct nilfs_sysfs_dev_subgroups; | ||
| 36 | 37 | ||
| 37 | /* the_nilfs struct */ | 38 | /* the_nilfs struct */ |
| 38 | enum { | 39 | enum { |
| @@ -54,6 +55,7 @@ enum { | |||
| 54 | * @ns_sbwcount: write count of super block | 55 | * @ns_sbwcount: write count of super block |
| 55 | * @ns_sbsize: size of valid data in super block | 56 | * @ns_sbsize: size of valid data in super block |
| 56 | * @ns_mount_state: file system state | 57 | * @ns_mount_state: file system state |
| 58 | * @ns_sb_update_freq: interval of periodical update of superblocks (in seconds) | ||
| 57 | * @ns_seg_seq: segment sequence counter | 59 | * @ns_seg_seq: segment sequence counter |
| 58 | * @ns_segnum: index number of the latest full segment. | 60 | * @ns_segnum: index number of the latest full segment. |
| 59 | * @ns_nextnum: index number of the full segment index to be used next | 61 | * @ns_nextnum: index number of the full segment index to be used next |
| @@ -95,6 +97,9 @@ enum { | |||
| 95 | * @ns_inode_size: size of on-disk inode | 97 | * @ns_inode_size: size of on-disk inode |
| 96 | * @ns_first_ino: first not-special inode number | 98 | * @ns_first_ino: first not-special inode number |
| 97 | * @ns_crc_seed: seed value of CRC32 calculation | 99 | * @ns_crc_seed: seed value of CRC32 calculation |
| 100 | * @ns_dev_kobj: /sys/fs/<nilfs>/<device> | ||
| 101 | * @ns_dev_kobj_unregister: completion state | ||
| 102 | * @ns_dev_subgroups: <device> subgroups pointer | ||
| 98 | */ | 103 | */ |
| 99 | struct the_nilfs { | 104 | struct the_nilfs { |
| 100 | unsigned long ns_flags; | 105 | unsigned long ns_flags; |
| @@ -114,6 +119,7 @@ struct the_nilfs { | |||
| 114 | unsigned ns_sbwcount; | 119 | unsigned ns_sbwcount; |
| 115 | unsigned ns_sbsize; | 120 | unsigned ns_sbsize; |
| 116 | unsigned ns_mount_state; | 121 | unsigned ns_mount_state; |
| 122 | unsigned ns_sb_update_freq; | ||
| 117 | 123 | ||
| 118 | /* | 124 | /* |
| 119 | * Following fields are dedicated to a writable FS-instance. | 125 | * Following fields are dedicated to a writable FS-instance. |
| @@ -188,6 +194,11 @@ struct the_nilfs { | |||
| 188 | int ns_inode_size; | 194 | int ns_inode_size; |
| 189 | int ns_first_ino; | 195 | int ns_first_ino; |
| 190 | u32 ns_crc_seed; | 196 | u32 ns_crc_seed; |
| 197 | |||
| 198 | /* /sys/fs/<nilfs>/<device> */ | ||
| 199 | struct kobject ns_dev_kobj; | ||
| 200 | struct completion ns_dev_kobj_unregister; | ||
| 201 | struct nilfs_sysfs_dev_subgroups *ns_dev_subgroups; | ||
| 191 | }; | 202 | }; |
| 192 | 203 | ||
| 193 | #define THE_NILFS_FNS(bit, name) \ | 204 | #define THE_NILFS_FNS(bit, name) \ |
| @@ -232,6 +243,8 @@ THE_NILFS_FNS(SB_DIRTY, sb_dirty) | |||
| 232 | * @ifile: inode file | 243 | * @ifile: inode file |
| 233 | * @inodes_count: number of inodes | 244 | * @inodes_count: number of inodes |
| 234 | * @blocks_count: number of blocks | 245 | * @blocks_count: number of blocks |
| 246 | * @snapshot_kobj: /sys/fs/<nilfs>/<device>/mounted_snapshots/<snapshot> | ||
| 247 | * @snapshot_kobj_unregister: completion state for kernel object | ||
| 235 | */ | 248 | */ |
| 236 | struct nilfs_root { | 249 | struct nilfs_root { |
| 237 | __u64 cno; | 250 | __u64 cno; |
| @@ -243,6 +256,10 @@ struct nilfs_root { | |||
| 243 | 256 | ||
| 244 | atomic64_t inodes_count; | 257 | atomic64_t inodes_count; |
| 245 | atomic64_t blocks_count; | 258 | atomic64_t blocks_count; |
| 259 | |||
| 260 | /* /sys/fs/<nilfs>/<device>/mounted_snapshots/<snapshot> */ | ||
| 261 | struct kobject snapshot_kobj; | ||
| 262 | struct completion snapshot_kobj_unregister; | ||
| 246 | }; | 263 | }; |
| 247 | 264 | ||
| 248 | /* Special checkpoint number */ | 265 | /* Special checkpoint number */ |
| @@ -254,7 +271,8 @@ struct nilfs_root { | |||
| 254 | static inline int nilfs_sb_need_update(struct the_nilfs *nilfs) | 271 | static inline int nilfs_sb_need_update(struct the_nilfs *nilfs) |
| 255 | { | 272 | { |
| 256 | u64 t = get_seconds(); | 273 | u64 t = get_seconds(); |
| 257 | return t < nilfs->ns_sbwtime || t > nilfs->ns_sbwtime + NILFS_SB_FREQ; | 274 | return t < nilfs->ns_sbwtime || |
| 275 | t > nilfs->ns_sbwtime + nilfs->ns_sb_update_freq; | ||
| 258 | } | 276 | } |
| 259 | 277 | ||
| 260 | static inline int nilfs_sb_will_flip(struct the_nilfs *nilfs) | 278 | static inline int nilfs_sb_will_flip(struct the_nilfs *nilfs) |
diff --git a/fs/omfs/inode.c b/fs/omfs/inode.c index ec58c7659183..ba8819702c56 100644 --- a/fs/omfs/inode.c +++ b/fs/omfs/inode.c | |||
| @@ -321,7 +321,7 @@ static int omfs_get_imap(struct super_block *sb) | |||
| 321 | goto out; | 321 | goto out; |
| 322 | 322 | ||
| 323 | sbi->s_imap_size = array_size; | 323 | sbi->s_imap_size = array_size; |
| 324 | sbi->s_imap = kzalloc(array_size * sizeof(unsigned long *), GFP_KERNEL); | 324 | sbi->s_imap = kcalloc(array_size, sizeof(unsigned long *), GFP_KERNEL); |
| 325 | if (!sbi->s_imap) | 325 | if (!sbi->s_imap) |
| 326 | goto nomem; | 326 | goto nomem; |
| 327 | 327 | ||
diff --git a/fs/proc/base.c b/fs/proc/base.c index 2d696b0c93bf..043c83cb51f9 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
| @@ -105,7 +105,7 @@ | |||
| 105 | */ | 105 | */ |
| 106 | 106 | ||
| 107 | struct pid_entry { | 107 | struct pid_entry { |
| 108 | char *name; | 108 | const char *name; |
| 109 | int len; | 109 | int len; |
| 110 | umode_t mode; | 110 | umode_t mode; |
| 111 | const struct inode_operations *iop; | 111 | const struct inode_operations *iop; |
| @@ -130,10 +130,6 @@ struct pid_entry { | |||
| 130 | { .proc_get_link = get_link } ) | 130 | { .proc_get_link = get_link } ) |
| 131 | #define REG(NAME, MODE, fops) \ | 131 | #define REG(NAME, MODE, fops) \ |
| 132 | NOD(NAME, (S_IFREG|(MODE)), NULL, &fops, {}) | 132 | NOD(NAME, (S_IFREG|(MODE)), NULL, &fops, {}) |
| 133 | #define INF(NAME, MODE, read) \ | ||
| 134 | NOD(NAME, (S_IFREG|(MODE)), \ | ||
| 135 | NULL, &proc_info_file_operations, \ | ||
| 136 | { .proc_read = read } ) | ||
| 137 | #define ONE(NAME, MODE, show) \ | 133 | #define ONE(NAME, MODE, show) \ |
| 138 | NOD(NAME, (S_IFREG|(MODE)), \ | 134 | NOD(NAME, (S_IFREG|(MODE)), \ |
| 139 | NULL, &proc_single_file_operations, \ | 135 | NULL, &proc_single_file_operations, \ |
| @@ -200,27 +196,32 @@ static int proc_root_link(struct dentry *dentry, struct path *path) | |||
| 200 | return result; | 196 | return result; |
| 201 | } | 197 | } |
| 202 | 198 | ||
| 203 | static int proc_pid_cmdline(struct task_struct *task, char *buffer) | 199 | static int proc_pid_cmdline(struct seq_file *m, struct pid_namespace *ns, |
| 200 | struct pid *pid, struct task_struct *task) | ||
| 204 | { | 201 | { |
| 205 | return get_cmdline(task, buffer, PAGE_SIZE); | 202 | /* |
| 203 | * Rely on struct seq_operations::show() being called once | ||
| 204 | * per internal buffer allocation. See single_open(), traverse(). | ||
| 205 | */ | ||
| 206 | BUG_ON(m->size < PAGE_SIZE); | ||
| 207 | m->count += get_cmdline(task, m->buf, PAGE_SIZE); | ||
| 208 | return 0; | ||
| 206 | } | 209 | } |
| 207 | 210 | ||
| 208 | static int proc_pid_auxv(struct task_struct *task, char *buffer) | 211 | static int proc_pid_auxv(struct seq_file *m, struct pid_namespace *ns, |
| 212 | struct pid *pid, struct task_struct *task) | ||
| 209 | { | 213 | { |
| 210 | struct mm_struct *mm = mm_access(task, PTRACE_MODE_READ); | 214 | struct mm_struct *mm = mm_access(task, PTRACE_MODE_READ); |
| 211 | int res = PTR_ERR(mm); | ||
| 212 | if (mm && !IS_ERR(mm)) { | 215 | if (mm && !IS_ERR(mm)) { |
| 213 | unsigned int nwords = 0; | 216 | unsigned int nwords = 0; |
| 214 | do { | 217 | do { |
| 215 | nwords += 2; | 218 | nwords += 2; |
| 216 | } while (mm->saved_auxv[nwords - 2] != 0); /* AT_NULL */ | 219 | } while (mm->saved_auxv[nwords - 2] != 0); /* AT_NULL */ |
| 217 | res = nwords * sizeof(mm->saved_auxv[0]); | 220 | seq_write(m, mm->saved_auxv, nwords * sizeof(mm->saved_auxv[0])); |
| 218 | if (res > PAGE_SIZE) | ||
| 219 | res = PAGE_SIZE; | ||
| 220 | memcpy(buffer, mm->saved_auxv, res); | ||
| 221 | mmput(mm); | 221 | mmput(mm); |
| 222 | } | 222 | return 0; |
| 223 | return res; | 223 | } else |
| 224 | return PTR_ERR(mm); | ||
| 224 | } | 225 | } |
| 225 | 226 | ||
| 226 | 227 | ||
| @@ -229,7 +230,8 @@ static int proc_pid_auxv(struct task_struct *task, char *buffer) | |||
| 229 | * Provides a wchan file via kallsyms in a proper one-value-per-file format. | 230 | * Provides a wchan file via kallsyms in a proper one-value-per-file format. |
| 230 | * Returns the resolved symbol. If that fails, simply return the address. | 231 | * Returns the resolved symbol. If that fails, simply return the address. |
| 231 | */ | 232 | */ |
| 232 | static int proc_pid_wchan(struct task_struct *task, char *buffer) | 233 | static int proc_pid_wchan(struct seq_file *m, struct pid_namespace *ns, |
| 234 | struct pid *pid, struct task_struct *task) | ||
| 233 | { | 235 | { |
| 234 | unsigned long wchan; | 236 | unsigned long wchan; |
| 235 | char symname[KSYM_NAME_LEN]; | 237 | char symname[KSYM_NAME_LEN]; |
| @@ -240,9 +242,9 @@ static int proc_pid_wchan(struct task_struct *task, char *buffer) | |||
| 240 | if (!ptrace_may_access(task, PTRACE_MODE_READ)) | 242 | if (!ptrace_may_access(task, PTRACE_MODE_READ)) |
| 241 | return 0; | 243 | return 0; |
| 242 | else | 244 | else |
| 243 | return sprintf(buffer, "%lu", wchan); | 245 | return seq_printf(m, "%lu", wchan); |
| 244 | else | 246 | else |
| 245 | return sprintf(buffer, "%s", symname); | 247 | return seq_printf(m, "%s", symname); |
| 246 | } | 248 | } |
| 247 | #endif /* CONFIG_KALLSYMS */ | 249 | #endif /* CONFIG_KALLSYMS */ |
| 248 | 250 | ||
| @@ -304,9 +306,10 @@ static int proc_pid_stack(struct seq_file *m, struct pid_namespace *ns, | |||
| 304 | /* | 306 | /* |
| 305 | * Provides /proc/PID/schedstat | 307 | * Provides /proc/PID/schedstat |
| 306 | */ | 308 | */ |
| 307 | static int proc_pid_schedstat(struct task_struct *task, char *buffer) | 309 | static int proc_pid_schedstat(struct seq_file *m, struct pid_namespace *ns, |
| 310 | struct pid *pid, struct task_struct *task) | ||
| 308 | { | 311 | { |
| 309 | return sprintf(buffer, "%llu %llu %lu\n", | 312 | return seq_printf(m, "%llu %llu %lu\n", |
| 310 | (unsigned long long)task->se.sum_exec_runtime, | 313 | (unsigned long long)task->se.sum_exec_runtime, |
| 311 | (unsigned long long)task->sched_info.run_delay, | 314 | (unsigned long long)task->sched_info.run_delay, |
| 312 | task->sched_info.pcount); | 315 | task->sched_info.pcount); |
| @@ -404,7 +407,8 @@ static const struct file_operations proc_cpuset_operations = { | |||
| 404 | }; | 407 | }; |
| 405 | #endif | 408 | #endif |
| 406 | 409 | ||
| 407 | static int proc_oom_score(struct task_struct *task, char *buffer) | 410 | static int proc_oom_score(struct seq_file *m, struct pid_namespace *ns, |
| 411 | struct pid *pid, struct task_struct *task) | ||
| 408 | { | 412 | { |
| 409 | unsigned long totalpages = totalram_pages + total_swap_pages; | 413 | unsigned long totalpages = totalram_pages + total_swap_pages; |
| 410 | unsigned long points = 0; | 414 | unsigned long points = 0; |
| @@ -414,12 +418,12 @@ static int proc_oom_score(struct task_struct *task, char *buffer) | |||
| 414 | points = oom_badness(task, NULL, NULL, totalpages) * | 418 | points = oom_badness(task, NULL, NULL, totalpages) * |
| 415 | 1000 / totalpages; | 419 | 1000 / totalpages; |
| 416 | read_unlock(&tasklist_lock); | 420 | read_unlock(&tasklist_lock); |
| 417 | return sprintf(buffer, "%lu\n", points); | 421 | return seq_printf(m, "%lu\n", points); |
| 418 | } | 422 | } |
| 419 | 423 | ||
| 420 | struct limit_names { | 424 | struct limit_names { |
| 421 | char *name; | 425 | const char *name; |
| 422 | char *unit; | 426 | const char *unit; |
| 423 | }; | 427 | }; |
| 424 | 428 | ||
| 425 | static const struct limit_names lnames[RLIM_NLIMITS] = { | 429 | static const struct limit_names lnames[RLIM_NLIMITS] = { |
| @@ -442,12 +446,11 @@ static const struct limit_names lnames[RLIM_NLIMITS] = { | |||
| 442 | }; | 446 | }; |
| 443 | 447 | ||
| 444 | /* Display limits for a process */ | 448 | /* Display limits for a process */ |
| 445 | static int proc_pid_limits(struct task_struct *task, char *buffer) | 449 | static int proc_pid_limits(struct seq_file *m, struct pid_namespace *ns, |
| 450 | struct pid *pid, struct task_struct *task) | ||
| 446 | { | 451 | { |
| 447 | unsigned int i; | 452 | unsigned int i; |
| 448 | int count = 0; | ||
| 449 | unsigned long flags; | 453 | unsigned long flags; |
| 450 | char *bufptr = buffer; | ||
| 451 | 454 | ||
| 452 | struct rlimit rlim[RLIM_NLIMITS]; | 455 | struct rlimit rlim[RLIM_NLIMITS]; |
| 453 | 456 | ||
| @@ -459,35 +462,34 @@ static int proc_pid_limits(struct task_struct *task, char *buffer) | |||
| 459 | /* | 462 | /* |
| 460 | * print the file header | 463 | * print the file header |
| 461 | */ | 464 | */ |
| 462 | count += sprintf(&bufptr[count], "%-25s %-20s %-20s %-10s\n", | 465 | seq_printf(m, "%-25s %-20s %-20s %-10s\n", |
| 463 | "Limit", "Soft Limit", "Hard Limit", "Units"); | 466 | "Limit", "Soft Limit", "Hard Limit", "Units"); |
| 464 | 467 | ||
| 465 | for (i = 0; i < RLIM_NLIMITS; i++) { | 468 | for (i = 0; i < RLIM_NLIMITS; i++) { |
| 466 | if (rlim[i].rlim_cur == RLIM_INFINITY) | 469 | if (rlim[i].rlim_cur == RLIM_INFINITY) |
| 467 | count += sprintf(&bufptr[count], "%-25s %-20s ", | 470 | seq_printf(m, "%-25s %-20s ", |
| 468 | lnames[i].name, "unlimited"); | 471 | lnames[i].name, "unlimited"); |
| 469 | else | 472 | else |
| 470 | count += sprintf(&bufptr[count], "%-25s %-20lu ", | 473 | seq_printf(m, "%-25s %-20lu ", |
| 471 | lnames[i].name, rlim[i].rlim_cur); | 474 | lnames[i].name, rlim[i].rlim_cur); |
| 472 | 475 | ||
| 473 | if (rlim[i].rlim_max == RLIM_INFINITY) | 476 | if (rlim[i].rlim_max == RLIM_INFINITY) |
| 474 | count += sprintf(&bufptr[count], "%-20s ", "unlimited"); | 477 | seq_printf(m, "%-20s ", "unlimited"); |
| 475 | else | 478 | else |
| 476 | count += sprintf(&bufptr[count], "%-20lu ", | 479 | seq_printf(m, "%-20lu ", rlim[i].rlim_max); |
| 477 | rlim[i].rlim_max); | ||
| 478 | 480 | ||
| 479 | if (lnames[i].unit) | 481 | if (lnames[i].unit) |
| 480 | count += sprintf(&bufptr[count], "%-10s\n", | 482 | seq_printf(m, "%-10s\n", lnames[i].unit); |
| 481 | lnames[i].unit); | ||
| 482 | else | 483 | else |
| 483 | count += sprintf(&bufptr[count], "\n"); | 484 | seq_putc(m, '\n'); |
| 484 | } | 485 | } |
| 485 | 486 | ||
| 486 | return count; | 487 | return 0; |
| 487 | } | 488 | } |
| 488 | 489 | ||
| 489 | #ifdef CONFIG_HAVE_ARCH_TRACEHOOK | 490 | #ifdef CONFIG_HAVE_ARCH_TRACEHOOK |
| 490 | static int proc_pid_syscall(struct task_struct *task, char *buffer) | 491 | static int proc_pid_syscall(struct seq_file *m, struct pid_namespace *ns, |
| 492 | struct pid *pid, struct task_struct *task) | ||
| 491 | { | 493 | { |
| 492 | long nr; | 494 | long nr; |
| 493 | unsigned long args[6], sp, pc; | 495 | unsigned long args[6], sp, pc; |
| @@ -496,11 +498,11 @@ static int proc_pid_syscall(struct task_struct *task, char *buffer) | |||
| 496 | return res; | 498 | return res; |
| 497 | 499 | ||
| 498 | if (task_current_syscall(task, &nr, args, 6, &sp, &pc)) | 500 | if (task_current_syscall(task, &nr, args, 6, &sp, &pc)) |
| 499 | res = sprintf(buffer, "running\n"); | 501 | seq_puts(m, "running\n"); |
| 500 | else if (nr < 0) | 502 | else if (nr < 0) |
| 501 | res = sprintf(buffer, "%ld 0x%lx 0x%lx\n", nr, sp, pc); | 503 | seq_printf(m, "%ld 0x%lx 0x%lx\n", nr, sp, pc); |
| 502 | else | 504 | else |
| 503 | res = sprintf(buffer, | 505 | seq_printf(m, |
| 504 | "%ld 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n", | 506 | "%ld 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n", |
| 505 | nr, | 507 | nr, |
| 506 | args[0], args[1], args[2], args[3], args[4], args[5], | 508 | args[0], args[1], args[2], args[3], args[4], args[5], |
| @@ -598,43 +600,6 @@ static const struct inode_operations proc_def_inode_operations = { | |||
| 598 | .setattr = proc_setattr, | 600 | .setattr = proc_setattr, |
| 599 | }; | 601 | }; |
| 600 | 602 | ||
| 601 | #define PROC_BLOCK_SIZE (3*1024) /* 4K page size but our output routines use some slack for overruns */ | ||
| 602 | |||
| 603 | static ssize_t proc_info_read(struct file * file, char __user * buf, | ||
| 604 | size_t count, loff_t *ppos) | ||
| 605 | { | ||
| 606 | struct inode * inode = file_inode(file); | ||
| 607 | unsigned long page; | ||
| 608 | ssize_t length; | ||
| 609 | struct task_struct *task = get_proc_task(inode); | ||
| 610 | |||
| 611 | length = -ESRCH; | ||
| 612 | if (!task) | ||
| 613 | goto out_no_task; | ||
| 614 | |||
| 615 | if (count > PROC_BLOCK_SIZE) | ||
| 616 | count = PROC_BLOCK_SIZE; | ||
| 617 | |||
| 618 | length = -ENOMEM; | ||
| 619 | if (!(page = __get_free_page(GFP_TEMPORARY))) | ||
| 620 | goto out; | ||
| 621 | |||
| 622 | length = PROC_I(inode)->op.proc_read(task, (char*)page); | ||
| 623 | |||
| 624 | if (length >= 0) | ||
| 625 | length = simple_read_from_buffer(buf, count, ppos, (char *)page, length); | ||
| 626 | free_page(page); | ||
| 627 | out: | ||
| 628 | put_task_struct(task); | ||
| 629 | out_no_task: | ||
| 630 | return length; | ||
| 631 | } | ||
| 632 | |||
| 633 | static const struct file_operations proc_info_file_operations = { | ||
| 634 | .read = proc_info_read, | ||
| 635 | .llseek = generic_file_llseek, | ||
| 636 | }; | ||
| 637 | |||
| 638 | static int proc_single_show(struct seq_file *m, void *v) | 603 | static int proc_single_show(struct seq_file *m, void *v) |
| 639 | { | 604 | { |
| 640 | struct inode *inode = m->private; | 605 | struct inode *inode = m->private; |
| @@ -2056,7 +2021,7 @@ static int show_timer(struct seq_file *m, void *v) | |||
| 2056 | struct k_itimer *timer; | 2021 | struct k_itimer *timer; |
| 2057 | struct timers_private *tp = m->private; | 2022 | struct timers_private *tp = m->private; |
| 2058 | int notify; | 2023 | int notify; |
| 2059 | static char *nstr[] = { | 2024 | static const char * const nstr[] = { |
| 2060 | [SIGEV_SIGNAL] = "signal", | 2025 | [SIGEV_SIGNAL] = "signal", |
| 2061 | [SIGEV_NONE] = "none", | 2026 | [SIGEV_NONE] = "none", |
| 2062 | [SIGEV_THREAD] = "thread", | 2027 | [SIGEV_THREAD] = "thread", |
| @@ -2392,7 +2357,7 @@ static const struct file_operations proc_coredump_filter_operations = { | |||
| 2392 | #endif | 2357 | #endif |
| 2393 | 2358 | ||
| 2394 | #ifdef CONFIG_TASK_IO_ACCOUNTING | 2359 | #ifdef CONFIG_TASK_IO_ACCOUNTING |
| 2395 | static int do_io_accounting(struct task_struct *task, char *buffer, int whole) | 2360 | static int do_io_accounting(struct task_struct *task, struct seq_file *m, int whole) |
| 2396 | { | 2361 | { |
| 2397 | struct task_io_accounting acct = task->ioac; | 2362 | struct task_io_accounting acct = task->ioac; |
| 2398 | unsigned long flags; | 2363 | unsigned long flags; |
| @@ -2416,7 +2381,7 @@ static int do_io_accounting(struct task_struct *task, char *buffer, int whole) | |||
| 2416 | 2381 | ||
| 2417 | unlock_task_sighand(task, &flags); | 2382 | unlock_task_sighand(task, &flags); |
| 2418 | } | 2383 | } |
| 2419 | result = sprintf(buffer, | 2384 | result = seq_printf(m, |
| 2420 | "rchar: %llu\n" | 2385 | "rchar: %llu\n" |
| 2421 | "wchar: %llu\n" | 2386 | "wchar: %llu\n" |
| 2422 | "syscr: %llu\n" | 2387 | "syscr: %llu\n" |
| @@ -2436,20 +2401,22 @@ out_unlock: | |||
| 2436 | return result; | 2401 | return result; |
| 2437 | } | 2402 | } |
| 2438 | 2403 | ||
| 2439 | static int proc_tid_io_accounting(struct task_struct *task, char *buffer) | 2404 | static int proc_tid_io_accounting(struct seq_file *m, struct pid_namespace *ns, |
| 2405 | struct pid *pid, struct task_struct *task) | ||
| 2440 | { | 2406 | { |
| 2441 | return do_io_accounting(task, buffer, 0); | 2407 | return do_io_accounting(task, m, 0); |
| 2442 | } | 2408 | } |
| 2443 | 2409 | ||
| 2444 | static int proc_tgid_io_accounting(struct task_struct *task, char *buffer) | 2410 | static int proc_tgid_io_accounting(struct seq_file *m, struct pid_namespace *ns, |
| 2411 | struct pid *pid, struct task_struct *task) | ||
| 2445 | { | 2412 | { |
| 2446 | return do_io_accounting(task, buffer, 1); | 2413 | return do_io_accounting(task, m, 1); |
| 2447 | } | 2414 | } |
| 2448 | #endif /* CONFIG_TASK_IO_ACCOUNTING */ | 2415 | #endif /* CONFIG_TASK_IO_ACCOUNTING */ |
| 2449 | 2416 | ||
| 2450 | #ifdef CONFIG_USER_NS | 2417 | #ifdef CONFIG_USER_NS |
| 2451 | static int proc_id_map_open(struct inode *inode, struct file *file, | 2418 | static int proc_id_map_open(struct inode *inode, struct file *file, |
| 2452 | struct seq_operations *seq_ops) | 2419 | const struct seq_operations *seq_ops) |
| 2453 | { | 2420 | { |
| 2454 | struct user_namespace *ns = NULL; | 2421 | struct user_namespace *ns = NULL; |
| 2455 | struct task_struct *task; | 2422 | struct task_struct *task; |
| @@ -2557,10 +2524,10 @@ static const struct pid_entry tgid_base_stuff[] = { | |||
| 2557 | DIR("net", S_IRUGO|S_IXUGO, proc_net_inode_operations, proc_net_operations), | 2524 | DIR("net", S_IRUGO|S_IXUGO, proc_net_inode_operations, proc_net_operations), |
| 2558 | #endif | 2525 | #endif |
| 2559 | REG("environ", S_IRUSR, proc_environ_operations), | 2526 | REG("environ", S_IRUSR, proc_environ_operations), |
| 2560 | INF("auxv", S_IRUSR, proc_pid_auxv), | 2527 | ONE("auxv", S_IRUSR, proc_pid_auxv), |
| 2561 | ONE("status", S_IRUGO, proc_pid_status), | 2528 | ONE("status", S_IRUGO, proc_pid_status), |
| 2562 | ONE("personality", S_IRUSR, proc_pid_personality), | 2529 | ONE("personality", S_IRUSR, proc_pid_personality), |
| 2563 | INF("limits", S_IRUGO, proc_pid_limits), | 2530 | ONE("limits", S_IRUGO, proc_pid_limits), |
| 2564 | #ifdef CONFIG_SCHED_DEBUG | 2531 | #ifdef CONFIG_SCHED_DEBUG |
| 2565 | REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations), | 2532 | REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations), |
| 2566 | #endif | 2533 | #endif |
| @@ -2569,9 +2536,9 @@ static const struct pid_entry tgid_base_stuff[] = { | |||
| 2569 | #endif | 2536 | #endif |
| 2570 | REG("comm", S_IRUGO|S_IWUSR, proc_pid_set_comm_operations), | 2537 | REG("comm", S_IRUGO|S_IWUSR, proc_pid_set_comm_operations), |
| 2571 | #ifdef CONFIG_HAVE_ARCH_TRACEHOOK | 2538 | #ifdef CONFIG_HAVE_ARCH_TRACEHOOK |
| 2572 | INF("syscall", S_IRUSR, proc_pid_syscall), | 2539 | ONE("syscall", S_IRUSR, proc_pid_syscall), |
| 2573 | #endif | 2540 | #endif |
| 2574 | INF("cmdline", S_IRUGO, proc_pid_cmdline), | 2541 | ONE("cmdline", S_IRUGO, proc_pid_cmdline), |
| 2575 | ONE("stat", S_IRUGO, proc_tgid_stat), | 2542 | ONE("stat", S_IRUGO, proc_tgid_stat), |
| 2576 | ONE("statm", S_IRUGO, proc_pid_statm), | 2543 | ONE("statm", S_IRUGO, proc_pid_statm), |
| 2577 | REG("maps", S_IRUGO, proc_pid_maps_operations), | 2544 | REG("maps", S_IRUGO, proc_pid_maps_operations), |
| @@ -2594,13 +2561,13 @@ static const struct pid_entry tgid_base_stuff[] = { | |||
| 2594 | DIR("attr", S_IRUGO|S_IXUGO, proc_attr_dir_inode_operations, proc_attr_dir_operations), | 2561 | DIR("attr", S_IRUGO|S_IXUGO, proc_attr_dir_inode_operations, proc_attr_dir_operations), |
| 2595 | #endif | 2562 | #endif |
| 2596 | #ifdef CONFIG_KALLSYMS | 2563 | #ifdef CONFIG_KALLSYMS |
| 2597 | INF("wchan", S_IRUGO, proc_pid_wchan), | 2564 | ONE("wchan", S_IRUGO, proc_pid_wchan), |
| 2598 | #endif | 2565 | #endif |
| 2599 | #ifdef CONFIG_STACKTRACE | 2566 | #ifdef CONFIG_STACKTRACE |
| 2600 | ONE("stack", S_IRUSR, proc_pid_stack), | 2567 | ONE("stack", S_IRUSR, proc_pid_stack), |
| 2601 | #endif | 2568 | #endif |
| 2602 | #ifdef CONFIG_SCHEDSTATS | 2569 | #ifdef CONFIG_SCHEDSTATS |
| 2603 | INF("schedstat", S_IRUGO, proc_pid_schedstat), | 2570 | ONE("schedstat", S_IRUGO, proc_pid_schedstat), |
| 2604 | #endif | 2571 | #endif |
| 2605 | #ifdef CONFIG_LATENCYTOP | 2572 | #ifdef CONFIG_LATENCYTOP |
| 2606 | REG("latency", S_IRUGO, proc_lstats_operations), | 2573 | REG("latency", S_IRUGO, proc_lstats_operations), |
| @@ -2611,7 +2578,7 @@ static const struct pid_entry tgid_base_stuff[] = { | |||
| 2611 | #ifdef CONFIG_CGROUPS | 2578 | #ifdef CONFIG_CGROUPS |
| 2612 | REG("cgroup", S_IRUGO, proc_cgroup_operations), | 2579 | REG("cgroup", S_IRUGO, proc_cgroup_operations), |
| 2613 | #endif | 2580 | #endif |
| 2614 | INF("oom_score", S_IRUGO, proc_oom_score), | 2581 | ONE("oom_score", S_IRUGO, proc_oom_score), |
| 2615 | REG("oom_adj", S_IRUGO|S_IWUSR, proc_oom_adj_operations), | 2582 | REG("oom_adj", S_IRUGO|S_IWUSR, proc_oom_adj_operations), |
| 2616 | REG("oom_score_adj", S_IRUGO|S_IWUSR, proc_oom_score_adj_operations), | 2583 | REG("oom_score_adj", S_IRUGO|S_IWUSR, proc_oom_score_adj_operations), |
| 2617 | #ifdef CONFIG_AUDITSYSCALL | 2584 | #ifdef CONFIG_AUDITSYSCALL |
| @@ -2625,10 +2592,10 @@ static const struct pid_entry tgid_base_stuff[] = { | |||
| 2625 | REG("coredump_filter", S_IRUGO|S_IWUSR, proc_coredump_filter_operations), | 2592 | REG("coredump_filter", S_IRUGO|S_IWUSR, proc_coredump_filter_operations), |
| 2626 | #endif | 2593 | #endif |
| 2627 | #ifdef CONFIG_TASK_IO_ACCOUNTING | 2594 | #ifdef CONFIG_TASK_IO_ACCOUNTING |
| 2628 | INF("io", S_IRUSR, proc_tgid_io_accounting), | 2595 | ONE("io", S_IRUSR, proc_tgid_io_accounting), |
| 2629 | #endif | 2596 | #endif |
| 2630 | #ifdef CONFIG_HARDWALL | 2597 | #ifdef CONFIG_HARDWALL |
| 2631 | INF("hardwall", S_IRUGO, proc_pid_hardwall), | 2598 | ONE("hardwall", S_IRUGO, proc_pid_hardwall), |
| 2632 | #endif | 2599 | #endif |
| 2633 | #ifdef CONFIG_USER_NS | 2600 | #ifdef CONFIG_USER_NS |
| 2634 | REG("uid_map", S_IRUGO|S_IWUSR, proc_uid_map_operations), | 2601 | REG("uid_map", S_IRUGO|S_IWUSR, proc_uid_map_operations), |
| @@ -2780,12 +2747,12 @@ out: | |||
| 2780 | 2747 | ||
| 2781 | struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags) | 2748 | struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags) |
| 2782 | { | 2749 | { |
| 2783 | int result = 0; | 2750 | int result = -ENOENT; |
| 2784 | struct task_struct *task; | 2751 | struct task_struct *task; |
| 2785 | unsigned tgid; | 2752 | unsigned tgid; |
| 2786 | struct pid_namespace *ns; | 2753 | struct pid_namespace *ns; |
| 2787 | 2754 | ||
| 2788 | tgid = name_to_int(dentry); | 2755 | tgid = name_to_int(&dentry->d_name); |
| 2789 | if (tgid == ~0U) | 2756 | if (tgid == ~0U) |
| 2790 | goto out; | 2757 | goto out; |
| 2791 | 2758 | ||
| @@ -2896,18 +2863,18 @@ static const struct pid_entry tid_base_stuff[] = { | |||
| 2896 | DIR("fdinfo", S_IRUSR|S_IXUSR, proc_fdinfo_inode_operations, proc_fdinfo_operations), | 2863 | DIR("fdinfo", S_IRUSR|S_IXUSR, proc_fdinfo_inode_operations, proc_fdinfo_operations), |
| 2897 | DIR("ns", S_IRUSR|S_IXUGO, proc_ns_dir_inode_operations, proc_ns_dir_operations), | 2864 | DIR("ns", S_IRUSR|S_IXUGO, proc_ns_dir_inode_operations, proc_ns_dir_operations), |
| 2898 | REG("environ", S_IRUSR, proc_environ_operations), | 2865 | REG("environ", S_IRUSR, proc_environ_operations), |
| 2899 | INF("auxv", S_IRUSR, proc_pid_auxv), | 2866 | ONE("auxv", S_IRUSR, proc_pid_auxv), |
| 2900 | ONE("status", S_IRUGO, proc_pid_status), | 2867 | ONE("status", S_IRUGO, proc_pid_status), |
| 2901 | ONE("personality", S_IRUSR, proc_pid_personality), | 2868 | ONE("personality", S_IRUSR, proc_pid_personality), |
| 2902 | INF("limits", S_IRUGO, proc_pid_limits), | 2869 | ONE("limits", S_IRUGO, proc_pid_limits), |
| 2903 | #ifdef CONFIG_SCHED_DEBUG | 2870 | #ifdef CONFIG_SCHED_DEBUG |
| 2904 | REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations), | 2871 | REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations), |
| 2905 | #endif | 2872 | #endif |
| 2906 | REG("comm", S_IRUGO|S_IWUSR, proc_pid_set_comm_operations), | 2873 | REG("comm", S_IRUGO|S_IWUSR, proc_pid_set_comm_operations), |
| 2907 | #ifdef CONFIG_HAVE_ARCH_TRACEHOOK | 2874 | #ifdef CONFIG_HAVE_ARCH_TRACEHOOK |
| 2908 | INF("syscall", S_IRUSR, proc_pid_syscall), | 2875 | ONE("syscall", S_IRUSR, proc_pid_syscall), |
| 2909 | #endif | 2876 | #endif |
| 2910 | INF("cmdline", S_IRUGO, proc_pid_cmdline), | 2877 | ONE("cmdline", S_IRUGO, proc_pid_cmdline), |
| 2911 | ONE("stat", S_IRUGO, proc_tid_stat), | 2878 | ONE("stat", S_IRUGO, proc_tid_stat), |
| 2912 | ONE("statm", S_IRUGO, proc_pid_statm), | 2879 | ONE("statm", S_IRUGO, proc_pid_statm), |
| 2913 | REG("maps", S_IRUGO, proc_tid_maps_operations), | 2880 | REG("maps", S_IRUGO, proc_tid_maps_operations), |
| @@ -2932,13 +2899,13 @@ static const struct pid_entry tid_base_stuff[] = { | |||
| 2932 | DIR("attr", S_IRUGO|S_IXUGO, proc_attr_dir_inode_operations, proc_attr_dir_operations), | 2899 | DIR("attr", S_IRUGO|S_IXUGO, proc_attr_dir_inode_operations, proc_attr_dir_operations), |
| 2933 | #endif | 2900 | #endif |
| 2934 | #ifdef CONFIG_KALLSYMS | 2901 | #ifdef CONFIG_KALLSYMS |
| 2935 | INF("wchan", S_IRUGO, proc_pid_wchan), | 2902 | ONE("wchan", S_IRUGO, proc_pid_wchan), |
| 2936 | #endif | 2903 | #endif |
| 2937 | #ifdef CONFIG_STACKTRACE | 2904 | #ifdef CONFIG_STACKTRACE |
| 2938 | ONE("stack", S_IRUSR, proc_pid_stack), | 2905 | ONE("stack", S_IRUSR, proc_pid_stack), |
| 2939 | #endif | 2906 | #endif |
| 2940 | #ifdef CONFIG_SCHEDSTATS | 2907 | #ifdef CONFIG_SCHEDSTATS |
| 2941 | INF("schedstat", S_IRUGO, proc_pid_schedstat), | 2908 | ONE("schedstat", S_IRUGO, proc_pid_schedstat), |
| 2942 | #endif | 2909 | #endif |
| 2943 | #ifdef CONFIG_LATENCYTOP | 2910 | #ifdef CONFIG_LATENCYTOP |
| 2944 | REG("latency", S_IRUGO, proc_lstats_operations), | 2911 | REG("latency", S_IRUGO, proc_lstats_operations), |
| @@ -2949,7 +2916,7 @@ static const struct pid_entry tid_base_stuff[] = { | |||
| 2949 | #ifdef CONFIG_CGROUPS | 2916 | #ifdef CONFIG_CGROUPS |
| 2950 | REG("cgroup", S_IRUGO, proc_cgroup_operations), | 2917 | REG("cgroup", S_IRUGO, proc_cgroup_operations), |
| 2951 | #endif | 2918 | #endif |
| 2952 | INF("oom_score", S_IRUGO, proc_oom_score), | 2919 | ONE("oom_score", S_IRUGO, proc_oom_score), |
| 2953 | REG("oom_adj", S_IRUGO|S_IWUSR, proc_oom_adj_operations), | 2920 | REG("oom_adj", S_IRUGO|S_IWUSR, proc_oom_adj_operations), |
| 2954 | REG("oom_score_adj", S_IRUGO|S_IWUSR, proc_oom_score_adj_operations), | 2921 | REG("oom_score_adj", S_IRUGO|S_IWUSR, proc_oom_score_adj_operations), |
| 2955 | #ifdef CONFIG_AUDITSYSCALL | 2922 | #ifdef CONFIG_AUDITSYSCALL |
| @@ -2960,10 +2927,10 @@ static const struct pid_entry tid_base_stuff[] = { | |||
| 2960 | REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations), | 2927 | REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations), |
| 2961 | #endif | 2928 | #endif |
| 2962 | #ifdef CONFIG_TASK_IO_ACCOUNTING | 2929 | #ifdef CONFIG_TASK_IO_ACCOUNTING |
| 2963 | INF("io", S_IRUSR, proc_tid_io_accounting), | 2930 | ONE("io", S_IRUSR, proc_tid_io_accounting), |
| 2964 | #endif | 2931 | #endif |
| 2965 | #ifdef CONFIG_HARDWALL | 2932 | #ifdef CONFIG_HARDWALL |
| 2966 | INF("hardwall", S_IRUGO, proc_pid_hardwall), | 2933 | ONE("hardwall", S_IRUGO, proc_pid_hardwall), |
| 2967 | #endif | 2934 | #endif |
| 2968 | #ifdef CONFIG_USER_NS | 2935 | #ifdef CONFIG_USER_NS |
| 2969 | REG("uid_map", S_IRUGO|S_IWUSR, proc_uid_map_operations), | 2936 | REG("uid_map", S_IRUGO|S_IWUSR, proc_uid_map_operations), |
| @@ -3033,7 +3000,7 @@ static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry | |||
| 3033 | if (!leader) | 3000 | if (!leader) |
| 3034 | goto out_no_task; | 3001 | goto out_no_task; |
| 3035 | 3002 | ||
| 3036 | tid = name_to_int(dentry); | 3003 | tid = name_to_int(&dentry->d_name); |
| 3037 | if (tid == ~0U) | 3004 | if (tid == ~0U) |
| 3038 | goto out; | 3005 | goto out; |
| 3039 | 3006 | ||
diff --git a/fs/proc/fd.c b/fs/proc/fd.c index 0788d093f5d8..955bb55fab8c 100644 --- a/fs/proc/fd.c +++ b/fs/proc/fd.c | |||
| @@ -206,7 +206,7 @@ static struct dentry *proc_lookupfd_common(struct inode *dir, | |||
| 206 | { | 206 | { |
| 207 | struct task_struct *task = get_proc_task(dir); | 207 | struct task_struct *task = get_proc_task(dir); |
| 208 | int result = -ENOENT; | 208 | int result = -ENOENT; |
| 209 | unsigned fd = name_to_int(dentry); | 209 | unsigned fd = name_to_int(&dentry->d_name); |
| 210 | 210 | ||
| 211 | if (!task) | 211 | if (!task) |
| 212 | goto out_no_task; | 212 | goto out_no_task; |
diff --git a/fs/proc/generic.c b/fs/proc/generic.c index b7f268eb5f45..317b72641ebf 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c | |||
| @@ -27,7 +27,7 @@ | |||
| 27 | 27 | ||
| 28 | #include "internal.h" | 28 | #include "internal.h" |
| 29 | 29 | ||
| 30 | DEFINE_SPINLOCK(proc_subdir_lock); | 30 | static DEFINE_SPINLOCK(proc_subdir_lock); |
| 31 | 31 | ||
| 32 | static int proc_match(unsigned int len, const char *name, struct proc_dir_entry *de) | 32 | static int proc_match(unsigned int len, const char *name, struct proc_dir_entry *de) |
| 33 | { | 33 | { |
| @@ -330,28 +330,28 @@ static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent, | |||
| 330 | nlink_t nlink) | 330 | nlink_t nlink) |
| 331 | { | 331 | { |
| 332 | struct proc_dir_entry *ent = NULL; | 332 | struct proc_dir_entry *ent = NULL; |
| 333 | const char *fn = name; | 333 | const char *fn; |
| 334 | unsigned int len; | 334 | struct qstr qstr; |
| 335 | |||
| 336 | /* make sure name is valid */ | ||
| 337 | if (!name || !strlen(name)) | ||
| 338 | goto out; | ||
| 339 | 335 | ||
| 340 | if (xlate_proc_name(name, parent, &fn) != 0) | 336 | if (xlate_proc_name(name, parent, &fn) != 0) |
| 341 | goto out; | 337 | goto out; |
| 338 | qstr.name = fn; | ||
| 339 | qstr.len = strlen(fn); | ||
| 340 | if (qstr.len == 0 || qstr.len >= 256) { | ||
| 341 | WARN(1, "name len %u\n", qstr.len); | ||
| 342 | return NULL; | ||
| 343 | } | ||
| 344 | if (*parent == &proc_root && name_to_int(&qstr) != ~0U) { | ||
| 345 | WARN(1, "create '/proc/%s' by hand\n", qstr.name); | ||
| 346 | return NULL; | ||
| 347 | } | ||
| 342 | 348 | ||
| 343 | /* At this point there must not be any '/' characters beyond *fn */ | 349 | ent = kzalloc(sizeof(struct proc_dir_entry) + qstr.len + 1, GFP_KERNEL); |
| 344 | if (strchr(fn, '/')) | ||
| 345 | goto out; | ||
| 346 | |||
| 347 | len = strlen(fn); | ||
| 348 | |||
| 349 | ent = kzalloc(sizeof(struct proc_dir_entry) + len + 1, GFP_KERNEL); | ||
| 350 | if (!ent) | 350 | if (!ent) |
| 351 | goto out; | 351 | goto out; |
| 352 | 352 | ||
| 353 | memcpy(ent->name, fn, len + 1); | 353 | memcpy(ent->name, fn, qstr.len + 1); |
| 354 | ent->namelen = len; | 354 | ent->namelen = qstr.len; |
| 355 | ent->mode = mode; | 355 | ent->mode = mode; |
| 356 | ent->nlink = nlink; | 356 | ent->nlink = nlink; |
| 357 | atomic_set(&ent->count, 1); | 357 | atomic_set(&ent->count, 1); |
diff --git a/fs/proc/internal.h b/fs/proc/internal.h index 3ab6d14e71c5..a024cf7b260f 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h | |||
| @@ -52,7 +52,6 @@ struct proc_dir_entry { | |||
| 52 | 52 | ||
| 53 | union proc_op { | 53 | union proc_op { |
| 54 | int (*proc_get_link)(struct dentry *, struct path *); | 54 | int (*proc_get_link)(struct dentry *, struct path *); |
| 55 | int (*proc_read)(struct task_struct *task, char *page); | ||
| 56 | int (*proc_show)(struct seq_file *m, | 55 | int (*proc_show)(struct seq_file *m, |
| 57 | struct pid_namespace *ns, struct pid *pid, | 56 | struct pid_namespace *ns, struct pid *pid, |
| 58 | struct task_struct *task); | 57 | struct task_struct *task); |
| @@ -112,10 +111,10 @@ static inline int task_dumpable(struct task_struct *task) | |||
| 112 | return 0; | 111 | return 0; |
| 113 | } | 112 | } |
| 114 | 113 | ||
| 115 | static inline unsigned name_to_int(struct dentry *dentry) | 114 | static inline unsigned name_to_int(const struct qstr *qstr) |
| 116 | { | 115 | { |
| 117 | const char *name = dentry->d_name.name; | 116 | const char *name = qstr->name; |
| 118 | int len = dentry->d_name.len; | 117 | int len = qstr->len; |
| 119 | unsigned n = 0; | 118 | unsigned n = 0; |
| 120 | 119 | ||
| 121 | if (len > 1 && *name == '0') | 120 | if (len > 1 && *name == '0') |
| @@ -178,8 +177,6 @@ extern bool proc_fill_cache(struct file *, struct dir_context *, const char *, i | |||
| 178 | /* | 177 | /* |
| 179 | * generic.c | 178 | * generic.c |
| 180 | */ | 179 | */ |
| 181 | extern spinlock_t proc_subdir_lock; | ||
| 182 | |||
| 183 | extern struct dentry *proc_lookup(struct inode *, struct dentry *, unsigned int); | 180 | extern struct dentry *proc_lookup(struct inode *, struct dentry *, unsigned int); |
| 184 | extern struct dentry *proc_lookup_de(struct proc_dir_entry *, struct inode *, | 181 | extern struct dentry *proc_lookup_de(struct proc_dir_entry *, struct inode *, |
| 185 | struct dentry *); | 182 | struct dentry *); |
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c index 39e6ef32f0bd..6df8d0722c97 100644 --- a/fs/proc/kcore.c +++ b/fs/proc/kcore.c | |||
| @@ -172,7 +172,7 @@ get_sparsemem_vmemmap_info(struct kcore_list *ent, struct list_head *head) | |||
| 172 | 172 | ||
| 173 | start = ((unsigned long)pfn_to_page(pfn)) & PAGE_MASK; | 173 | start = ((unsigned long)pfn_to_page(pfn)) & PAGE_MASK; |
| 174 | end = ((unsigned long)pfn_to_page(pfn + nr_pages)) - 1; | 174 | end = ((unsigned long)pfn_to_page(pfn + nr_pages)) - 1; |
| 175 | end = ALIGN(end, PAGE_SIZE); | 175 | end = PAGE_ALIGN(end); |
| 176 | /* overlap check (because we have to align page */ | 176 | /* overlap check (because we have to align page */ |
| 177 | list_for_each_entry(tmp, head, list) { | 177 | list_for_each_entry(tmp, head, list) { |
| 178 | if (tmp->type != KCORE_VMEMMAP) | 178 | if (tmp->type != KCORE_VMEMMAP) |
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index 71290463a1d3..f92d5dd578a4 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c | |||
| @@ -632,7 +632,7 @@ out: | |||
| 632 | return ret; | 632 | return ret; |
| 633 | } | 633 | } |
| 634 | 634 | ||
| 635 | static int scan(struct ctl_table_header *head, ctl_table *table, | 635 | static int scan(struct ctl_table_header *head, struct ctl_table *table, |
| 636 | unsigned long *pos, struct file *file, | 636 | unsigned long *pos, struct file *file, |
| 637 | struct dir_context *ctx) | 637 | struct dir_context *ctx) |
| 638 | { | 638 | { |
diff --git a/fs/proc/proc_tty.c b/fs/proc/proc_tty.c index cb761f010300..15f327bed8c6 100644 --- a/fs/proc/proc_tty.c +++ b/fs/proc/proc_tty.c | |||
| @@ -18,7 +18,7 @@ | |||
| 18 | /* | 18 | /* |
| 19 | * The /proc/tty directory inodes... | 19 | * The /proc/tty directory inodes... |
| 20 | */ | 20 | */ |
| 21 | static struct proc_dir_entry *proc_tty_ldisc, *proc_tty_driver; | 21 | static struct proc_dir_entry *proc_tty_driver; |
| 22 | 22 | ||
| 23 | /* | 23 | /* |
| 24 | * This is the handler for /proc/tty/drivers | 24 | * This is the handler for /proc/tty/drivers |
| @@ -176,7 +176,7 @@ void __init proc_tty_init(void) | |||
| 176 | { | 176 | { |
| 177 | if (!proc_mkdir("tty", NULL)) | 177 | if (!proc_mkdir("tty", NULL)) |
| 178 | return; | 178 | return; |
| 179 | proc_tty_ldisc = proc_mkdir("tty/ldisc", NULL); | 179 | proc_mkdir("tty/ldisc", NULL); /* Preserved: it's userspace visible */ |
| 180 | /* | 180 | /* |
| 181 | * /proc/tty/driver/serial reveals the exact character counts for | 181 | * /proc/tty/driver/serial reveals the exact character counts for |
| 182 | * serial links which is just too easy to abuse for inferring | 182 | * serial links which is just too easy to abuse for inferring |
diff --git a/fs/proc/root.c b/fs/proc/root.c index 5dbadecb234d..574bafc41f0b 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c | |||
| @@ -199,10 +199,10 @@ static int proc_root_getattr(struct vfsmount *mnt, struct dentry *dentry, struct | |||
| 199 | 199 | ||
| 200 | static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry, unsigned int flags) | 200 | static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry, unsigned int flags) |
| 201 | { | 201 | { |
| 202 | if (!proc_lookup(dir, dentry, flags)) | 202 | if (!proc_pid_lookup(dir, dentry, flags)) |
| 203 | return NULL; | 203 | return NULL; |
| 204 | 204 | ||
| 205 | return proc_pid_lookup(dir, dentry, flags); | 205 | return proc_lookup(dir, dentry, flags); |
| 206 | } | 206 | } |
| 207 | 207 | ||
| 208 | static int proc_root_readdir(struct file *file, struct dir_context *ctx) | 208 | static int proc_root_readdir(struct file *file, struct dir_context *ctx) |
diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c index 382aa890e228..a90d6d354199 100644 --- a/fs/proc/vmcore.c +++ b/fs/proc/vmcore.c | |||
| @@ -328,6 +328,82 @@ static inline char *alloc_elfnotes_buf(size_t notes_sz) | |||
| 328 | * virtually contiguous user-space in ELF layout. | 328 | * virtually contiguous user-space in ELF layout. |
| 329 | */ | 329 | */ |
| 330 | #ifdef CONFIG_MMU | 330 | #ifdef CONFIG_MMU |
| 331 | /* | ||
| 332 | * remap_oldmem_pfn_checked - do remap_oldmem_pfn_range replacing all pages | ||
| 333 | * reported as not being ram with the zero page. | ||
| 334 | * | ||
| 335 | * @vma: vm_area_struct describing requested mapping | ||
| 336 | * @from: start remapping from | ||
| 337 | * @pfn: page frame number to start remapping to | ||
| 338 | * @size: remapping size | ||
| 339 | * @prot: protection bits | ||
| 340 | * | ||
| 341 | * Returns zero on success, -EAGAIN on failure. | ||
| 342 | */ | ||
| 343 | static int remap_oldmem_pfn_checked(struct vm_area_struct *vma, | ||
| 344 | unsigned long from, unsigned long pfn, | ||
| 345 | unsigned long size, pgprot_t prot) | ||
| 346 | { | ||
| 347 | unsigned long map_size; | ||
| 348 | unsigned long pos_start, pos_end, pos; | ||
| 349 | unsigned long zeropage_pfn = my_zero_pfn(0); | ||
| 350 | size_t len = 0; | ||
| 351 | |||
| 352 | pos_start = pfn; | ||
| 353 | pos_end = pfn + (size >> PAGE_SHIFT); | ||
| 354 | |||
| 355 | for (pos = pos_start; pos < pos_end; ++pos) { | ||
| 356 | if (!pfn_is_ram(pos)) { | ||
| 357 | /* | ||
| 358 | * We hit a page which is not ram. Remap the continuous | ||
| 359 | * region between pos_start and pos-1 and replace | ||
| 360 | * the non-ram page at pos with the zero page. | ||
| 361 | */ | ||
| 362 | if (pos > pos_start) { | ||
| 363 | /* Remap continuous region */ | ||
| 364 | map_size = (pos - pos_start) << PAGE_SHIFT; | ||
| 365 | if (remap_oldmem_pfn_range(vma, from + len, | ||
| 366 | pos_start, map_size, | ||
| 367 | prot)) | ||
| 368 | goto fail; | ||
| 369 | len += map_size; | ||
| 370 | } | ||
| 371 | /* Remap the zero page */ | ||
| 372 | if (remap_oldmem_pfn_range(vma, from + len, | ||
| 373 | zeropage_pfn, | ||
| 374 | PAGE_SIZE, prot)) | ||
| 375 | goto fail; | ||
| 376 | len += PAGE_SIZE; | ||
| 377 | pos_start = pos + 1; | ||
| 378 | } | ||
| 379 | } | ||
| 380 | if (pos > pos_start) { | ||
| 381 | /* Remap the rest */ | ||
| 382 | map_size = (pos - pos_start) << PAGE_SHIFT; | ||
| 383 | if (remap_oldmem_pfn_range(vma, from + len, pos_start, | ||
| 384 | map_size, prot)) | ||
| 385 | goto fail; | ||
| 386 | } | ||
| 387 | return 0; | ||
| 388 | fail: | ||
| 389 | do_munmap(vma->vm_mm, from, len); | ||
| 390 | return -EAGAIN; | ||
| 391 | } | ||
| 392 | |||
| 393 | static int vmcore_remap_oldmem_pfn(struct vm_area_struct *vma, | ||
| 394 | unsigned long from, unsigned long pfn, | ||
| 395 | unsigned long size, pgprot_t prot) | ||
| 396 | { | ||
| 397 | /* | ||
| 398 | * Check if oldmem_pfn_is_ram was registered to avoid | ||
| 399 | * looping over all pages without a reason. | ||
| 400 | */ | ||
| 401 | if (oldmem_pfn_is_ram) | ||
| 402 | return remap_oldmem_pfn_checked(vma, from, pfn, size, prot); | ||
| 403 | else | ||
| 404 | return remap_oldmem_pfn_range(vma, from, pfn, size, prot); | ||
| 405 | } | ||
| 406 | |||
| 331 | static int mmap_vmcore(struct file *file, struct vm_area_struct *vma) | 407 | static int mmap_vmcore(struct file *file, struct vm_area_struct *vma) |
| 332 | { | 408 | { |
| 333 | size_t size = vma->vm_end - vma->vm_start; | 409 | size_t size = vma->vm_end - vma->vm_start; |
| @@ -387,9 +463,9 @@ static int mmap_vmcore(struct file *file, struct vm_area_struct *vma) | |||
| 387 | 463 | ||
| 388 | tsz = min_t(size_t, m->offset + m->size - start, size); | 464 | tsz = min_t(size_t, m->offset + m->size - start, size); |
| 389 | paddr = m->paddr + start - m->offset; | 465 | paddr = m->paddr + start - m->offset; |
| 390 | if (remap_oldmem_pfn_range(vma, vma->vm_start + len, | 466 | if (vmcore_remap_oldmem_pfn(vma, vma->vm_start + len, |
| 391 | paddr >> PAGE_SHIFT, tsz, | 467 | paddr >> PAGE_SHIFT, tsz, |
| 392 | vma->vm_page_prot)) | 468 | vma->vm_page_prot)) |
| 393 | goto fail; | 469 | goto fail; |
| 394 | size -= tsz; | 470 | size -= tsz; |
| 395 | start += tsz; | 471 | start += tsz; |
diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c index 34a1e5aa848c..9d7b9a83699e 100644 --- a/fs/pstore/ram_core.c +++ b/fs/pstore/ram_core.c | |||
| @@ -394,7 +394,7 @@ static void *persistent_ram_vmap(phys_addr_t start, size_t size) | |||
| 394 | 394 | ||
| 395 | prot = pgprot_noncached(PAGE_KERNEL); | 395 | prot = pgprot_noncached(PAGE_KERNEL); |
| 396 | 396 | ||
| 397 | pages = kmalloc(sizeof(struct page *) * page_count, GFP_KERNEL); | 397 | pages = kmalloc_array(page_count, sizeof(struct page *), GFP_KERNEL); |
| 398 | if (!pages) { | 398 | if (!pages) { |
| 399 | pr_err("%s: Failed to allocate array for %u pages\n", | 399 | pr_err("%s: Failed to allocate array for %u pages\n", |
| 400 | __func__, page_count); | 400 | __func__, page_count); |
diff --git a/fs/qnx6/Makefile b/fs/qnx6/Makefile index 9dd06199afc9..5e6bae6fae50 100644 --- a/fs/qnx6/Makefile +++ b/fs/qnx6/Makefile | |||
| @@ -5,3 +5,4 @@ | |||
| 5 | obj-$(CONFIG_QNX6FS_FS) += qnx6.o | 5 | obj-$(CONFIG_QNX6FS_FS) += qnx6.o |
| 6 | 6 | ||
| 7 | qnx6-objs := inode.o dir.o namei.o super_mmi.o | 7 | qnx6-objs := inode.o dir.o namei.o super_mmi.o |
| 8 | ccflags-$(CONFIG_QNX6FS_DEBUG) += -DDEBUG | ||
diff --git a/fs/qnx6/dir.c b/fs/qnx6/dir.c index 15b7d92ed60d..8d64bb5366bf 100644 --- a/fs/qnx6/dir.c +++ b/fs/qnx6/dir.c | |||
| @@ -77,21 +77,20 @@ static int qnx6_dir_longfilename(struct inode *inode, | |||
| 77 | if (de->de_size != 0xff) { | 77 | if (de->de_size != 0xff) { |
| 78 | /* error - long filename entries always have size 0xff | 78 | /* error - long filename entries always have size 0xff |
| 79 | in direntry */ | 79 | in direntry */ |
| 80 | printk(KERN_ERR "qnx6: invalid direntry size (%i).\n", | 80 | pr_err("invalid direntry size (%i).\n", de->de_size); |
| 81 | de->de_size); | ||
| 82 | return 0; | 81 | return 0; |
| 83 | } | 82 | } |
| 84 | lf = qnx6_longname(s, de, &page); | 83 | lf = qnx6_longname(s, de, &page); |
| 85 | if (IS_ERR(lf)) { | 84 | if (IS_ERR(lf)) { |
| 86 | printk(KERN_ERR "qnx6:Error reading longname\n"); | 85 | pr_err("Error reading longname\n"); |
| 87 | return 0; | 86 | return 0; |
| 88 | } | 87 | } |
| 89 | 88 | ||
| 90 | lf_size = fs16_to_cpu(sbi, lf->lf_size); | 89 | lf_size = fs16_to_cpu(sbi, lf->lf_size); |
| 91 | 90 | ||
| 92 | if (lf_size > QNX6_LONG_NAME_MAX) { | 91 | if (lf_size > QNX6_LONG_NAME_MAX) { |
| 93 | QNX6DEBUG((KERN_INFO "file %s\n", lf->lf_fname)); | 92 | pr_debug("file %s\n", lf->lf_fname); |
| 94 | printk(KERN_ERR "qnx6:Filename too long (%i)\n", lf_size); | 93 | pr_err("Filename too long (%i)\n", lf_size); |
| 95 | qnx6_put_page(page); | 94 | qnx6_put_page(page); |
| 96 | return 0; | 95 | return 0; |
| 97 | } | 96 | } |
| @@ -100,10 +99,10 @@ static int qnx6_dir_longfilename(struct inode *inode, | |||
| 100 | mmi 3g filesystem does not have that checksum */ | 99 | mmi 3g filesystem does not have that checksum */ |
| 101 | if (!test_opt(s, MMI_FS) && fs32_to_cpu(sbi, de->de_checksum) != | 100 | if (!test_opt(s, MMI_FS) && fs32_to_cpu(sbi, de->de_checksum) != |
| 102 | qnx6_lfile_checksum(lf->lf_fname, lf_size)) | 101 | qnx6_lfile_checksum(lf->lf_fname, lf_size)) |
| 103 | printk(KERN_INFO "qnx6: long filename checksum error.\n"); | 102 | pr_info("long filename checksum error.\n"); |
| 104 | 103 | ||
| 105 | QNX6DEBUG((KERN_INFO "qnx6_readdir:%.*s inode:%u\n", | 104 | pr_debug("qnx6_readdir:%.*s inode:%u\n", |
| 106 | lf_size, lf->lf_fname, de_inode)); | 105 | lf_size, lf->lf_fname, de_inode); |
| 107 | if (!dir_emit(ctx, lf->lf_fname, lf_size, de_inode, DT_UNKNOWN)) { | 106 | if (!dir_emit(ctx, lf->lf_fname, lf_size, de_inode, DT_UNKNOWN)) { |
| 108 | qnx6_put_page(page); | 107 | qnx6_put_page(page); |
| 109 | return 0; | 108 | return 0; |
| @@ -136,7 +135,7 @@ static int qnx6_readdir(struct file *file, struct dir_context *ctx) | |||
| 136 | int i = start; | 135 | int i = start; |
| 137 | 136 | ||
| 138 | if (IS_ERR(page)) { | 137 | if (IS_ERR(page)) { |
| 139 | printk(KERN_ERR "qnx6_readdir: read failed\n"); | 138 | pr_err("%s(): read failed\n", __func__); |
| 140 | ctx->pos = (n + 1) << PAGE_CACHE_SHIFT; | 139 | ctx->pos = (n + 1) << PAGE_CACHE_SHIFT; |
| 141 | return PTR_ERR(page); | 140 | return PTR_ERR(page); |
| 142 | } | 141 | } |
| @@ -159,9 +158,9 @@ static int qnx6_readdir(struct file *file, struct dir_context *ctx) | |||
| 159 | break; | 158 | break; |
| 160 | } | 159 | } |
| 161 | } else { | 160 | } else { |
| 162 | QNX6DEBUG((KERN_INFO "qnx6_readdir:%.*s" | 161 | pr_debug("%s():%.*s inode:%u\n", |
| 163 | " inode:%u\n", size, de->de_fname, | 162 | __func__, size, de->de_fname, |
| 164 | no_inode)); | 163 | no_inode); |
| 165 | if (!dir_emit(ctx, de->de_fname, size, | 164 | if (!dir_emit(ctx, de->de_fname, size, |
| 166 | no_inode, DT_UNKNOWN)) { | 165 | no_inode, DT_UNKNOWN)) { |
| 167 | done = true; | 166 | done = true; |
| @@ -259,8 +258,7 @@ unsigned qnx6_find_entry(int len, struct inode *dir, const char *name, | |||
| 259 | if (ino) | 258 | if (ino) |
| 260 | goto found; | 259 | goto found; |
| 261 | } else | 260 | } else |
| 262 | printk(KERN_ERR "qnx6: undefined " | 261 | pr_err("undefined filename size in inode.\n"); |
| 263 | "filename size in inode.\n"); | ||
| 264 | } | 262 | } |
| 265 | qnx6_put_page(page); | 263 | qnx6_put_page(page); |
| 266 | } | 264 | } |
diff --git a/fs/qnx6/inode.c b/fs/qnx6/inode.c index 65cdaab3ed49..44e73923670d 100644 --- a/fs/qnx6/inode.c +++ b/fs/qnx6/inode.c | |||
| @@ -73,8 +73,8 @@ static int qnx6_get_block(struct inode *inode, sector_t iblock, | |||
| 73 | { | 73 | { |
| 74 | unsigned phys; | 74 | unsigned phys; |
| 75 | 75 | ||
| 76 | QNX6DEBUG((KERN_INFO "qnx6: qnx6_get_block inode=[%ld] iblock=[%ld]\n", | 76 | pr_debug("qnx6_get_block inode=[%ld] iblock=[%ld]\n", |
| 77 | inode->i_ino, (unsigned long)iblock)); | 77 | inode->i_ino, (unsigned long)iblock); |
| 78 | 78 | ||
| 79 | phys = qnx6_block_map(inode, iblock); | 79 | phys = qnx6_block_map(inode, iblock); |
| 80 | if (phys) { | 80 | if (phys) { |
| @@ -87,7 +87,7 @@ static int qnx6_get_block(struct inode *inode, sector_t iblock, | |||
| 87 | static int qnx6_check_blockptr(__fs32 ptr) | 87 | static int qnx6_check_blockptr(__fs32 ptr) |
| 88 | { | 88 | { |
| 89 | if (ptr == ~(__fs32)0) { | 89 | if (ptr == ~(__fs32)0) { |
| 90 | printk(KERN_ERR "qnx6: hit unused blockpointer.\n"); | 90 | pr_err("hit unused blockpointer.\n"); |
| 91 | return 0; | 91 | return 0; |
| 92 | } | 92 | } |
| 93 | return 1; | 93 | return 1; |
| @@ -127,8 +127,7 @@ static unsigned qnx6_block_map(struct inode *inode, unsigned no) | |||
| 127 | levelptr = no >> bitdelta; | 127 | levelptr = no >> bitdelta; |
| 128 | 128 | ||
| 129 | if (levelptr > QNX6_NO_DIRECT_POINTERS - 1) { | 129 | if (levelptr > QNX6_NO_DIRECT_POINTERS - 1) { |
| 130 | printk(KERN_ERR "qnx6:Requested file block number (%u) too big.", | 130 | pr_err("Requested file block number (%u) too big.", no); |
| 131 | no); | ||
| 132 | return 0; | 131 | return 0; |
| 133 | } | 132 | } |
| 134 | 133 | ||
| @@ -137,8 +136,7 @@ static unsigned qnx6_block_map(struct inode *inode, unsigned no) | |||
| 137 | for (i = 0; i < depth; i++) { | 136 | for (i = 0; i < depth; i++) { |
| 138 | bh = sb_bread(s, block); | 137 | bh = sb_bread(s, block); |
| 139 | if (!bh) { | 138 | if (!bh) { |
| 140 | printk(KERN_ERR "qnx6:Error reading block (%u)\n", | 139 | pr_err("Error reading block (%u)\n", block); |
| 141 | block); | ||
| 142 | return 0; | 140 | return 0; |
| 143 | } | 141 | } |
| 144 | bitdelta -= ptrbits; | 142 | bitdelta -= ptrbits; |
| @@ -207,26 +205,16 @@ void qnx6_superblock_debug(struct qnx6_super_block *sb, struct super_block *s) | |||
| 207 | { | 205 | { |
| 208 | struct qnx6_sb_info *sbi = QNX6_SB(s); | 206 | struct qnx6_sb_info *sbi = QNX6_SB(s); |
| 209 | 207 | ||
| 210 | QNX6DEBUG((KERN_INFO "magic: %08x\n", | 208 | pr_debug("magic: %08x\n", fs32_to_cpu(sbi, sb->sb_magic)); |
| 211 | fs32_to_cpu(sbi, sb->sb_magic))); | 209 | pr_debug("checksum: %08x\n", fs32_to_cpu(sbi, sb->sb_checksum)); |
| 212 | QNX6DEBUG((KERN_INFO "checksum: %08x\n", | 210 | pr_debug("serial: %llx\n", fs64_to_cpu(sbi, sb->sb_serial)); |
| 213 | fs32_to_cpu(sbi, sb->sb_checksum))); | 211 | pr_debug("flags: %08x\n", fs32_to_cpu(sbi, sb->sb_flags)); |
| 214 | QNX6DEBUG((KERN_INFO "serial: %llx\n", | 212 | pr_debug("blocksize: %08x\n", fs32_to_cpu(sbi, sb->sb_blocksize)); |
| 215 | fs64_to_cpu(sbi, sb->sb_serial))); | 213 | pr_debug("num_inodes: %08x\n", fs32_to_cpu(sbi, sb->sb_num_inodes)); |
| 216 | QNX6DEBUG((KERN_INFO "flags: %08x\n", | 214 | pr_debug("free_inodes: %08x\n", fs32_to_cpu(sbi, sb->sb_free_inodes)); |
| 217 | fs32_to_cpu(sbi, sb->sb_flags))); | 215 | pr_debug("num_blocks: %08x\n", fs32_to_cpu(sbi, sb->sb_num_blocks)); |
| 218 | QNX6DEBUG((KERN_INFO "blocksize: %08x\n", | 216 | pr_debug("free_blocks: %08x\n", fs32_to_cpu(sbi, sb->sb_free_blocks)); |
| 219 | fs32_to_cpu(sbi, sb->sb_blocksize))); | 217 | pr_debug("inode_levels: %02x\n", sb->Inode.levels); |
| 220 | QNX6DEBUG((KERN_INFO "num_inodes: %08x\n", | ||
| 221 | fs32_to_cpu(sbi, sb->sb_num_inodes))); | ||
| 222 | QNX6DEBUG((KERN_INFO "free_inodes: %08x\n", | ||
| 223 | fs32_to_cpu(sbi, sb->sb_free_inodes))); | ||
| 224 | QNX6DEBUG((KERN_INFO "num_blocks: %08x\n", | ||
| 225 | fs32_to_cpu(sbi, sb->sb_num_blocks))); | ||
| 226 | QNX6DEBUG((KERN_INFO "free_blocks: %08x\n", | ||
| 227 | fs32_to_cpu(sbi, sb->sb_free_blocks))); | ||
| 228 | QNX6DEBUG((KERN_INFO "inode_levels: %02x\n", | ||
| 229 | sb->Inode.levels)); | ||
| 230 | } | 218 | } |
| 231 | #endif | 219 | #endif |
| 232 | 220 | ||
| @@ -277,7 +265,7 @@ static struct buffer_head *qnx6_check_first_superblock(struct super_block *s, | |||
| 277 | start with the first superblock */ | 265 | start with the first superblock */ |
| 278 | bh = sb_bread(s, offset); | 266 | bh = sb_bread(s, offset); |
| 279 | if (!bh) { | 267 | if (!bh) { |
| 280 | printk(KERN_ERR "qnx6: unable to read the first superblock\n"); | 268 | pr_err("unable to read the first superblock\n"); |
| 281 | return NULL; | 269 | return NULL; |
| 282 | } | 270 | } |
| 283 | sb = (struct qnx6_super_block *)bh->b_data; | 271 | sb = (struct qnx6_super_block *)bh->b_data; |
| @@ -285,20 +273,16 @@ static struct buffer_head *qnx6_check_first_superblock(struct super_block *s, | |||
| 285 | sbi->s_bytesex = BYTESEX_BE; | 273 | sbi->s_bytesex = BYTESEX_BE; |
| 286 | if (fs32_to_cpu(sbi, sb->sb_magic) == QNX6_SUPER_MAGIC) { | 274 | if (fs32_to_cpu(sbi, sb->sb_magic) == QNX6_SUPER_MAGIC) { |
| 287 | /* we got a big endian fs */ | 275 | /* we got a big endian fs */ |
| 288 | QNX6DEBUG((KERN_INFO "qnx6: fs got different" | 276 | pr_debug("fs got different endianness.\n"); |
| 289 | " endianness.\n")); | ||
| 290 | return bh; | 277 | return bh; |
| 291 | } else | 278 | } else |
| 292 | sbi->s_bytesex = BYTESEX_LE; | 279 | sbi->s_bytesex = BYTESEX_LE; |
| 293 | if (!silent) { | 280 | if (!silent) { |
| 294 | if (offset == 0) { | 281 | if (offset == 0) { |
| 295 | printk(KERN_ERR "qnx6: wrong signature (magic)" | 282 | pr_err("wrong signature (magic) in superblock #1.\n"); |
| 296 | " in superblock #1.\n"); | ||
| 297 | } else { | 283 | } else { |
| 298 | printk(KERN_INFO "qnx6: wrong signature (magic)" | 284 | pr_info("wrong signature (magic) at position (0x%lx) - will try alternative position (0x0000).\n", |
| 299 | " at position (0x%lx) - will try" | 285 | offset * s->s_blocksize); |
| 300 | " alternative position (0x0000).\n", | ||
| 301 | offset * s->s_blocksize); | ||
| 302 | } | 286 | } |
| 303 | } | 287 | } |
| 304 | brelse(bh); | 288 | brelse(bh); |
| @@ -329,13 +313,13 @@ static int qnx6_fill_super(struct super_block *s, void *data, int silent) | |||
| 329 | 313 | ||
| 330 | /* Superblock always is 512 Byte long */ | 314 | /* Superblock always is 512 Byte long */ |
| 331 | if (!sb_set_blocksize(s, QNX6_SUPERBLOCK_SIZE)) { | 315 | if (!sb_set_blocksize(s, QNX6_SUPERBLOCK_SIZE)) { |
| 332 | printk(KERN_ERR "qnx6: unable to set blocksize\n"); | 316 | pr_err("unable to set blocksize\n"); |
| 333 | goto outnobh; | 317 | goto outnobh; |
| 334 | } | 318 | } |
| 335 | 319 | ||
| 336 | /* parse the mount-options */ | 320 | /* parse the mount-options */ |
| 337 | if (!qnx6_parse_options((char *) data, s)) { | 321 | if (!qnx6_parse_options((char *) data, s)) { |
| 338 | printk(KERN_ERR "qnx6: invalid mount options.\n"); | 322 | pr_err("invalid mount options.\n"); |
| 339 | goto outnobh; | 323 | goto outnobh; |
| 340 | } | 324 | } |
| 341 | if (test_opt(s, MMI_FS)) { | 325 | if (test_opt(s, MMI_FS)) { |
| @@ -355,7 +339,7 @@ static int qnx6_fill_super(struct super_block *s, void *data, int silent) | |||
| 355 | /* try again without bootblock offset */ | 339 | /* try again without bootblock offset */ |
| 356 | bh1 = qnx6_check_first_superblock(s, 0, silent); | 340 | bh1 = qnx6_check_first_superblock(s, 0, silent); |
| 357 | if (!bh1) { | 341 | if (!bh1) { |
| 358 | printk(KERN_ERR "qnx6: unable to read the first superblock\n"); | 342 | pr_err("unable to read the first superblock\n"); |
| 359 | goto outnobh; | 343 | goto outnobh; |
| 360 | } | 344 | } |
| 361 | /* seems that no bootblock at partition start */ | 345 | /* seems that no bootblock at partition start */ |
| @@ -370,13 +354,13 @@ static int qnx6_fill_super(struct super_block *s, void *data, int silent) | |||
| 370 | /* checksum check - start at byte 8 and end at byte 512 */ | 354 | /* checksum check - start at byte 8 and end at byte 512 */ |
| 371 | if (fs32_to_cpu(sbi, sb1->sb_checksum) != | 355 | if (fs32_to_cpu(sbi, sb1->sb_checksum) != |
| 372 | crc32_be(0, (char *)(bh1->b_data + 8), 504)) { | 356 | crc32_be(0, (char *)(bh1->b_data + 8), 504)) { |
| 373 | printk(KERN_ERR "qnx6: superblock #1 checksum error\n"); | 357 | pr_err("superblock #1 checksum error\n"); |
| 374 | goto out; | 358 | goto out; |
| 375 | } | 359 | } |
| 376 | 360 | ||
| 377 | /* set new blocksize */ | 361 | /* set new blocksize */ |
| 378 | if (!sb_set_blocksize(s, fs32_to_cpu(sbi, sb1->sb_blocksize))) { | 362 | if (!sb_set_blocksize(s, fs32_to_cpu(sbi, sb1->sb_blocksize))) { |
| 379 | printk(KERN_ERR "qnx6: unable to set blocksize\n"); | 363 | pr_err("unable to set blocksize\n"); |
| 380 | goto out; | 364 | goto out; |
| 381 | } | 365 | } |
| 382 | /* blocksize invalidates bh - pull it back in */ | 366 | /* blocksize invalidates bh - pull it back in */ |
| @@ -398,21 +382,20 @@ static int qnx6_fill_super(struct super_block *s, void *data, int silent) | |||
| 398 | /* next the second superblock */ | 382 | /* next the second superblock */ |
| 399 | bh2 = sb_bread(s, offset); | 383 | bh2 = sb_bread(s, offset); |
| 400 | if (!bh2) { | 384 | if (!bh2) { |
| 401 | printk(KERN_ERR "qnx6: unable to read the second superblock\n"); | 385 | pr_err("unable to read the second superblock\n"); |
| 402 | goto out; | 386 | goto out; |
| 403 | } | 387 | } |
| 404 | sb2 = (struct qnx6_super_block *)bh2->b_data; | 388 | sb2 = (struct qnx6_super_block *)bh2->b_data; |
| 405 | if (fs32_to_cpu(sbi, sb2->sb_magic) != QNX6_SUPER_MAGIC) { | 389 | if (fs32_to_cpu(sbi, sb2->sb_magic) != QNX6_SUPER_MAGIC) { |
| 406 | if (!silent) | 390 | if (!silent) |
| 407 | printk(KERN_ERR "qnx6: wrong signature (magic)" | 391 | pr_err("wrong signature (magic) in superblock #2.\n"); |
| 408 | " in superblock #2.\n"); | ||
| 409 | goto out; | 392 | goto out; |
| 410 | } | 393 | } |
| 411 | 394 | ||
| 412 | /* checksum check - start at byte 8 and end at byte 512 */ | 395 | /* checksum check - start at byte 8 and end at byte 512 */ |
| 413 | if (fs32_to_cpu(sbi, sb2->sb_checksum) != | 396 | if (fs32_to_cpu(sbi, sb2->sb_checksum) != |
| 414 | crc32_be(0, (char *)(bh2->b_data + 8), 504)) { | 397 | crc32_be(0, (char *)(bh2->b_data + 8), 504)) { |
| 415 | printk(KERN_ERR "qnx6: superblock #2 checksum error\n"); | 398 | pr_err("superblock #2 checksum error\n"); |
| 416 | goto out; | 399 | goto out; |
| 417 | } | 400 | } |
| 418 | 401 | ||
| @@ -422,25 +405,24 @@ static int qnx6_fill_super(struct super_block *s, void *data, int silent) | |||
| 422 | sbi->sb_buf = bh1; | 405 | sbi->sb_buf = bh1; |
| 423 | sbi->sb = (struct qnx6_super_block *)bh1->b_data; | 406 | sbi->sb = (struct qnx6_super_block *)bh1->b_data; |
| 424 | brelse(bh2); | 407 | brelse(bh2); |
| 425 | printk(KERN_INFO "qnx6: superblock #1 active\n"); | 408 | pr_info("superblock #1 active\n"); |
| 426 | } else { | 409 | } else { |
| 427 | /* superblock #2 active */ | 410 | /* superblock #2 active */ |
| 428 | sbi->sb_buf = bh2; | 411 | sbi->sb_buf = bh2; |
| 429 | sbi->sb = (struct qnx6_super_block *)bh2->b_data; | 412 | sbi->sb = (struct qnx6_super_block *)bh2->b_data; |
| 430 | brelse(bh1); | 413 | brelse(bh1); |
| 431 | printk(KERN_INFO "qnx6: superblock #2 active\n"); | 414 | pr_info("superblock #2 active\n"); |
| 432 | } | 415 | } |
| 433 | mmi_success: | 416 | mmi_success: |
| 434 | /* sanity check - limit maximum indirect pointer levels */ | 417 | /* sanity check - limit maximum indirect pointer levels */ |
| 435 | if (sb1->Inode.levels > QNX6_PTR_MAX_LEVELS) { | 418 | if (sb1->Inode.levels > QNX6_PTR_MAX_LEVELS) { |
| 436 | printk(KERN_ERR "qnx6: too many inode levels (max %i, sb %i)\n", | 419 | pr_err("too many inode levels (max %i, sb %i)\n", |
| 437 | QNX6_PTR_MAX_LEVELS, sb1->Inode.levels); | 420 | QNX6_PTR_MAX_LEVELS, sb1->Inode.levels); |
| 438 | goto out; | 421 | goto out; |
| 439 | } | 422 | } |
| 440 | if (sb1->Longfile.levels > QNX6_PTR_MAX_LEVELS) { | 423 | if (sb1->Longfile.levels > QNX6_PTR_MAX_LEVELS) { |
| 441 | printk(KERN_ERR "qnx6: too many longfilename levels" | 424 | pr_err("too many longfilename levels (max %i, sb %i)\n", |
| 442 | " (max %i, sb %i)\n", | 425 | QNX6_PTR_MAX_LEVELS, sb1->Longfile.levels); |
| 443 | QNX6_PTR_MAX_LEVELS, sb1->Longfile.levels); | ||
| 444 | goto out; | 426 | goto out; |
| 445 | } | 427 | } |
| 446 | s->s_op = &qnx6_sops; | 428 | s->s_op = &qnx6_sops; |
| @@ -460,7 +442,7 @@ mmi_success: | |||
| 460 | /* prefetch root inode */ | 442 | /* prefetch root inode */ |
| 461 | root = qnx6_iget(s, QNX6_ROOT_INO); | 443 | root = qnx6_iget(s, QNX6_ROOT_INO); |
| 462 | if (IS_ERR(root)) { | 444 | if (IS_ERR(root)) { |
| 463 | printk(KERN_ERR "qnx6: get inode failed\n"); | 445 | pr_err("get inode failed\n"); |
| 464 | ret = PTR_ERR(root); | 446 | ret = PTR_ERR(root); |
| 465 | goto out2; | 447 | goto out2; |
| 466 | } | 448 | } |
| @@ -474,7 +456,7 @@ mmi_success: | |||
| 474 | errmsg = qnx6_checkroot(s); | 456 | errmsg = qnx6_checkroot(s); |
| 475 | if (errmsg != NULL) { | 457 | if (errmsg != NULL) { |
| 476 | if (!silent) | 458 | if (!silent) |
| 477 | printk(KERN_ERR "qnx6: %s\n", errmsg); | 459 | pr_err("%s\n", errmsg); |
| 478 | goto out3; | 460 | goto out3; |
| 479 | } | 461 | } |
| 480 | return 0; | 462 | return 0; |
| @@ -555,8 +537,7 @@ struct inode *qnx6_iget(struct super_block *sb, unsigned ino) | |||
| 555 | inode->i_mode = 0; | 537 | inode->i_mode = 0; |
| 556 | 538 | ||
| 557 | if (ino == 0) { | 539 | if (ino == 0) { |
| 558 | printk(KERN_ERR "qnx6: bad inode number on dev %s: %u is " | 540 | pr_err("bad inode number on dev %s: %u is out of range\n", |
| 559 | "out of range\n", | ||
| 560 | sb->s_id, ino); | 541 | sb->s_id, ino); |
| 561 | iget_failed(inode); | 542 | iget_failed(inode); |
| 562 | return ERR_PTR(-EIO); | 543 | return ERR_PTR(-EIO); |
| @@ -566,8 +547,8 @@ struct inode *qnx6_iget(struct super_block *sb, unsigned ino) | |||
| 566 | mapping = sbi->inodes->i_mapping; | 547 | mapping = sbi->inodes->i_mapping; |
| 567 | page = read_mapping_page(mapping, n, NULL); | 548 | page = read_mapping_page(mapping, n, NULL); |
| 568 | if (IS_ERR(page)) { | 549 | if (IS_ERR(page)) { |
| 569 | printk(KERN_ERR "qnx6: major problem: unable to read inode from " | 550 | pr_err("major problem: unable to read inode from dev %s\n", |
| 570 | "dev %s\n", sb->s_id); | 551 | sb->s_id); |
| 571 | iget_failed(inode); | 552 | iget_failed(inode); |
| 572 | return ERR_CAST(page); | 553 | return ERR_CAST(page); |
| 573 | } | 554 | } |
| @@ -689,7 +670,7 @@ static int __init init_qnx6_fs(void) | |||
| 689 | return err; | 670 | return err; |
| 690 | } | 671 | } |
| 691 | 672 | ||
| 692 | printk(KERN_INFO "QNX6 filesystem 1.0.0 registered.\n"); | 673 | pr_info("QNX6 filesystem 1.0.0 registered.\n"); |
| 693 | return 0; | 674 | return 0; |
| 694 | } | 675 | } |
| 695 | 676 | ||
diff --git a/fs/qnx6/namei.c b/fs/qnx6/namei.c index 0561326a94f5..6c1a323137dd 100644 --- a/fs/qnx6/namei.c +++ b/fs/qnx6/namei.c | |||
| @@ -29,12 +29,12 @@ struct dentry *qnx6_lookup(struct inode *dir, struct dentry *dentry, | |||
| 29 | foundinode = qnx6_iget(dir->i_sb, ino); | 29 | foundinode = qnx6_iget(dir->i_sb, ino); |
| 30 | qnx6_put_page(page); | 30 | qnx6_put_page(page); |
| 31 | if (IS_ERR(foundinode)) { | 31 | if (IS_ERR(foundinode)) { |
| 32 | QNX6DEBUG((KERN_ERR "qnx6: lookup->iget -> " | 32 | pr_debug("lookup->iget -> error %ld\n", |
| 33 | " error %ld\n", PTR_ERR(foundinode))); | 33 | PTR_ERR(foundinode)); |
| 34 | return ERR_CAST(foundinode); | 34 | return ERR_CAST(foundinode); |
| 35 | } | 35 | } |
| 36 | } else { | 36 | } else { |
| 37 | QNX6DEBUG((KERN_INFO "qnx6_lookup: not found %s\n", name)); | 37 | pr_debug("%s(): not found %s\n", __func__, name); |
| 38 | return NULL; | 38 | return NULL; |
| 39 | } | 39 | } |
| 40 | d_add(dentry, foundinode); | 40 | d_add(dentry, foundinode); |
diff --git a/fs/qnx6/qnx6.h b/fs/qnx6/qnx6.h index b00fcc960d37..d3fb2b698800 100644 --- a/fs/qnx6/qnx6.h +++ b/fs/qnx6/qnx6.h | |||
| @@ -10,6 +10,12 @@ | |||
| 10 | * | 10 | * |
| 11 | */ | 11 | */ |
| 12 | 12 | ||
| 13 | #ifdef pr_fmt | ||
| 14 | #undef pr_fmt | ||
| 15 | #endif | ||
| 16 | |||
| 17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 18 | |||
| 13 | #include <linux/fs.h> | 19 | #include <linux/fs.h> |
| 14 | #include <linux/pagemap.h> | 20 | #include <linux/pagemap.h> |
| 15 | 21 | ||
| @@ -19,12 +25,6 @@ typedef __u64 __bitwise __fs64; | |||
| 19 | 25 | ||
| 20 | #include <linux/qnx6_fs.h> | 26 | #include <linux/qnx6_fs.h> |
| 21 | 27 | ||
| 22 | #ifdef CONFIG_QNX6FS_DEBUG | ||
| 23 | #define QNX6DEBUG(X) printk X | ||
| 24 | #else | ||
| 25 | #define QNX6DEBUG(X) (void) 0 | ||
| 26 | #endif | ||
| 27 | |||
| 28 | struct qnx6_sb_info { | 28 | struct qnx6_sb_info { |
| 29 | struct buffer_head *sb_buf; /* superblock buffer */ | 29 | struct buffer_head *sb_buf; /* superblock buffer */ |
| 30 | struct qnx6_super_block *sb; /* our superblock */ | 30 | struct qnx6_super_block *sb; /* our superblock */ |
diff --git a/fs/qnx6/super_mmi.c b/fs/qnx6/super_mmi.c index 29c32cba62d6..62aaf3e3126a 100644 --- a/fs/qnx6/super_mmi.c +++ b/fs/qnx6/super_mmi.c | |||
| @@ -44,15 +44,14 @@ struct qnx6_super_block *qnx6_mmi_fill_super(struct super_block *s, int silent) | |||
| 44 | start with the first superblock */ | 44 | start with the first superblock */ |
| 45 | bh1 = sb_bread(s, 0); | 45 | bh1 = sb_bread(s, 0); |
| 46 | if (!bh1) { | 46 | if (!bh1) { |
| 47 | printk(KERN_ERR "qnx6: Unable to read first mmi superblock\n"); | 47 | pr_err("Unable to read first mmi superblock\n"); |
| 48 | return NULL; | 48 | return NULL; |
| 49 | } | 49 | } |
| 50 | sb1 = (struct qnx6_mmi_super_block *)bh1->b_data; | 50 | sb1 = (struct qnx6_mmi_super_block *)bh1->b_data; |
| 51 | sbi = QNX6_SB(s); | 51 | sbi = QNX6_SB(s); |
| 52 | if (fs32_to_cpu(sbi, sb1->sb_magic) != QNX6_SUPER_MAGIC) { | 52 | if (fs32_to_cpu(sbi, sb1->sb_magic) != QNX6_SUPER_MAGIC) { |
| 53 | if (!silent) { | 53 | if (!silent) { |
| 54 | printk(KERN_ERR "qnx6: wrong signature (magic) in" | 54 | pr_err("wrong signature (magic) in superblock #1.\n"); |
| 55 | " superblock #1.\n"); | ||
| 56 | goto out; | 55 | goto out; |
| 57 | } | 56 | } |
| 58 | } | 57 | } |
| @@ -60,7 +59,7 @@ struct qnx6_super_block *qnx6_mmi_fill_super(struct super_block *s, int silent) | |||
| 60 | /* checksum check - start at byte 8 and end at byte 512 */ | 59 | /* checksum check - start at byte 8 and end at byte 512 */ |
| 61 | if (fs32_to_cpu(sbi, sb1->sb_checksum) != | 60 | if (fs32_to_cpu(sbi, sb1->sb_checksum) != |
| 62 | crc32_be(0, (char *)(bh1->b_data + 8), 504)) { | 61 | crc32_be(0, (char *)(bh1->b_data + 8), 504)) { |
| 63 | printk(KERN_ERR "qnx6: superblock #1 checksum error\n"); | 62 | pr_err("superblock #1 checksum error\n"); |
| 64 | goto out; | 63 | goto out; |
| 65 | } | 64 | } |
| 66 | 65 | ||
| @@ -70,7 +69,7 @@ struct qnx6_super_block *qnx6_mmi_fill_super(struct super_block *s, int silent) | |||
| 70 | 69 | ||
| 71 | /* set new blocksize */ | 70 | /* set new blocksize */ |
| 72 | if (!sb_set_blocksize(s, fs32_to_cpu(sbi, sb1->sb_blocksize))) { | 71 | if (!sb_set_blocksize(s, fs32_to_cpu(sbi, sb1->sb_blocksize))) { |
| 73 | printk(KERN_ERR "qnx6: unable to set blocksize\n"); | 72 | pr_err("unable to set blocksize\n"); |
| 74 | goto out; | 73 | goto out; |
| 75 | } | 74 | } |
| 76 | /* blocksize invalidates bh - pull it back in */ | 75 | /* blocksize invalidates bh - pull it back in */ |
| @@ -83,27 +82,26 @@ struct qnx6_super_block *qnx6_mmi_fill_super(struct super_block *s, int silent) | |||
| 83 | /* read second superblock */ | 82 | /* read second superblock */ |
| 84 | bh2 = sb_bread(s, offset); | 83 | bh2 = sb_bread(s, offset); |
| 85 | if (!bh2) { | 84 | if (!bh2) { |
| 86 | printk(KERN_ERR "qnx6: unable to read the second superblock\n"); | 85 | pr_err("unable to read the second superblock\n"); |
| 87 | goto out; | 86 | goto out; |
| 88 | } | 87 | } |
| 89 | sb2 = (struct qnx6_mmi_super_block *)bh2->b_data; | 88 | sb2 = (struct qnx6_mmi_super_block *)bh2->b_data; |
| 90 | if (fs32_to_cpu(sbi, sb2->sb_magic) != QNX6_SUPER_MAGIC) { | 89 | if (fs32_to_cpu(sbi, sb2->sb_magic) != QNX6_SUPER_MAGIC) { |
| 91 | if (!silent) | 90 | if (!silent) |
| 92 | printk(KERN_ERR "qnx6: wrong signature (magic) in" | 91 | pr_err("wrong signature (magic) in superblock #2.\n"); |
| 93 | " superblock #2.\n"); | ||
| 94 | goto out; | 92 | goto out; |
| 95 | } | 93 | } |
| 96 | 94 | ||
| 97 | /* checksum check - start at byte 8 and end at byte 512 */ | 95 | /* checksum check - start at byte 8 and end at byte 512 */ |
| 98 | if (fs32_to_cpu(sbi, sb2->sb_checksum) | 96 | if (fs32_to_cpu(sbi, sb2->sb_checksum) |
| 99 | != crc32_be(0, (char *)(bh2->b_data + 8), 504)) { | 97 | != crc32_be(0, (char *)(bh2->b_data + 8), 504)) { |
| 100 | printk(KERN_ERR "qnx6: superblock #1 checksum error\n"); | 98 | pr_err("superblock #1 checksum error\n"); |
| 101 | goto out; | 99 | goto out; |
| 102 | } | 100 | } |
| 103 | 101 | ||
| 104 | qsb = kmalloc(sizeof(*qsb), GFP_KERNEL); | 102 | qsb = kmalloc(sizeof(*qsb), GFP_KERNEL); |
| 105 | if (!qsb) { | 103 | if (!qsb) { |
| 106 | printk(KERN_ERR "qnx6: unable to allocate memory.\n"); | 104 | pr_err("unable to allocate memory.\n"); |
| 107 | goto out; | 105 | goto out; |
| 108 | } | 106 | } |
| 109 | 107 | ||
| @@ -119,7 +117,7 @@ struct qnx6_super_block *qnx6_mmi_fill_super(struct super_block *s, int silent) | |||
| 119 | sbi->sb_buf = bh1; | 117 | sbi->sb_buf = bh1; |
| 120 | sbi->sb = (struct qnx6_super_block *)bh1->b_data; | 118 | sbi->sb = (struct qnx6_super_block *)bh1->b_data; |
| 121 | brelse(bh2); | 119 | brelse(bh2); |
| 122 | printk(KERN_INFO "qnx6: superblock #1 active\n"); | 120 | pr_info("superblock #1 active\n"); |
| 123 | } else { | 121 | } else { |
| 124 | /* superblock #2 active */ | 122 | /* superblock #2 active */ |
| 125 | qnx6_mmi_copy_sb(qsb, sb2); | 123 | qnx6_mmi_copy_sb(qsb, sb2); |
| @@ -131,7 +129,7 @@ struct qnx6_super_block *qnx6_mmi_fill_super(struct super_block *s, int silent) | |||
| 131 | sbi->sb_buf = bh2; | 129 | sbi->sb_buf = bh2; |
| 132 | sbi->sb = (struct qnx6_super_block *)bh2->b_data; | 130 | sbi->sb = (struct qnx6_super_block *)bh2->b_data; |
| 133 | brelse(bh1); | 131 | brelse(bh1); |
| 134 | printk(KERN_INFO "qnx6: superblock #2 active\n"); | 132 | pr_info("superblock #2 active\n"); |
| 135 | } | 133 | } |
| 136 | kfree(qsb); | 134 | kfree(qsb); |
| 137 | 135 | ||
diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c index dda012ad4208..bbafbde3471a 100644 --- a/fs/ramfs/file-nommu.c +++ b/fs/ramfs/file-nommu.c | |||
| @@ -222,7 +222,7 @@ static unsigned long ramfs_nommu_get_unmapped_area(struct file *file, | |||
| 222 | 222 | ||
| 223 | /* gang-find the pages */ | 223 | /* gang-find the pages */ |
| 224 | ret = -ENOMEM; | 224 | ret = -ENOMEM; |
| 225 | pages = kzalloc(lpages * sizeof(struct page *), GFP_KERNEL); | 225 | pages = kcalloc(lpages, sizeof(struct page *), GFP_KERNEL); |
| 226 | if (!pages) | 226 | if (!pages) |
| 227 | goto out_free; | 227 | goto out_free; |
| 228 | 228 | ||
diff --git a/fs/reiserfs/dir.c b/fs/reiserfs/dir.c index d9f5a60dd59b..0a7dc941aaf4 100644 --- a/fs/reiserfs/dir.c +++ b/fs/reiserfs/dir.c | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | #include <linux/stat.h> | 9 | #include <linux/stat.h> |
| 10 | #include <linux/buffer_head.h> | 10 | #include <linux/buffer_head.h> |
| 11 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
| 12 | #include <asm/uaccess.h> | 12 | #include <linux/uaccess.h> |
| 13 | 13 | ||
| 14 | extern const struct reiserfs_key MIN_KEY; | 14 | extern const struct reiserfs_key MIN_KEY; |
| 15 | 15 | ||
diff --git a/fs/reiserfs/do_balan.c b/fs/reiserfs/do_balan.c index 54fdf196bfb2..5739cb99de7b 100644 --- a/fs/reiserfs/do_balan.c +++ b/fs/reiserfs/do_balan.c | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | * and using buffers obtained after all above. | 10 | * and using buffers obtained after all above. |
| 11 | */ | 11 | */ |
| 12 | 12 | ||
| 13 | #include <asm/uaccess.h> | 13 | #include <linux/uaccess.h> |
| 14 | #include <linux/time.h> | 14 | #include <linux/time.h> |
| 15 | #include "reiserfs.h" | 15 | #include "reiserfs.h" |
| 16 | #include <linux/buffer_head.h> | 16 | #include <linux/buffer_head.h> |
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c index db9e80ba53a0..751dd3f4346b 100644 --- a/fs/reiserfs/file.c +++ b/fs/reiserfs/file.c | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | #include "reiserfs.h" | 6 | #include "reiserfs.h" |
| 7 | #include "acl.h" | 7 | #include "acl.h" |
| 8 | #include "xattr.h" | 8 | #include "xattr.h" |
| 9 | #include <asm/uaccess.h> | 9 | #include <linux/uaccess.h> |
| 10 | #include <linux/pagemap.h> | 10 | #include <linux/pagemap.h> |
| 11 | #include <linux/swap.h> | 11 | #include <linux/swap.h> |
| 12 | #include <linux/writeback.h> | 12 | #include <linux/writeback.h> |
diff --git a/fs/reiserfs/ibalance.c b/fs/reiserfs/ibalance.c index 73231b1ebdbe..b751eea32e20 100644 --- a/fs/reiserfs/ibalance.c +++ b/fs/reiserfs/ibalance.c | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README | 2 | * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README |
| 3 | */ | 3 | */ |
| 4 | 4 | ||
| 5 | #include <asm/uaccess.h> | 5 | #include <linux/uaccess.h> |
| 6 | #include <linux/string.h> | 6 | #include <linux/string.h> |
| 7 | #include <linux/time.h> | 7 | #include <linux/time.h> |
| 8 | #include "reiserfs.h" | 8 | #include "reiserfs.h" |
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 63b2b0ec49e6..a7eec9888f10 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c | |||
| @@ -11,7 +11,7 @@ | |||
| 11 | #include <linux/pagemap.h> | 11 | #include <linux/pagemap.h> |
| 12 | #include <linux/highmem.h> | 12 | #include <linux/highmem.h> |
| 13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
| 14 | #include <asm/uaccess.h> | 14 | #include <linux/uaccess.h> |
| 15 | #include <asm/unaligned.h> | 15 | #include <asm/unaligned.h> |
| 16 | #include <linux/buffer_head.h> | 16 | #include <linux/buffer_head.h> |
| 17 | #include <linux/mpage.h> | 17 | #include <linux/mpage.h> |
diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c index 501ed6811a2b..6ec8a30a0911 100644 --- a/fs/reiserfs/ioctl.c +++ b/fs/reiserfs/ioctl.c | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | #include <linux/mount.h> | 7 | #include <linux/mount.h> |
| 8 | #include "reiserfs.h" | 8 | #include "reiserfs.h" |
| 9 | #include <linux/time.h> | 9 | #include <linux/time.h> |
| 10 | #include <asm/uaccess.h> | 10 | #include <linux/uaccess.h> |
| 11 | #include <linux/pagemap.h> | 11 | #include <linux/pagemap.h> |
| 12 | #include <linux/compat.h> | 12 | #include <linux/compat.h> |
| 13 | 13 | ||
diff --git a/fs/reiserfs/item_ops.c b/fs/reiserfs/item_ops.c index cfaee912ee09..aca73dd73906 100644 --- a/fs/reiserfs/item_ops.c +++ b/fs/reiserfs/item_ops.c | |||
| @@ -54,7 +54,7 @@ static void sd_print_item(struct item_head *ih, char *item) | |||
| 54 | } else { | 54 | } else { |
| 55 | struct stat_data *sd = (struct stat_data *)item; | 55 | struct stat_data *sd = (struct stat_data *)item; |
| 56 | 56 | ||
| 57 | printk("\t0%-6o | %6Lu | %2u | %d | %s\n", sd_v2_mode(sd), | 57 | printk("\t0%-6o | %6llu | %2u | %d | %s\n", sd_v2_mode(sd), |
| 58 | (unsigned long long)sd_v2_size(sd), sd_v2_nlink(sd), | 58 | (unsigned long long)sd_v2_size(sd), sd_v2_nlink(sd), |
| 59 | sd_v2_rdev(sd), print_time(sd_v2_mtime(sd))); | 59 | sd_v2_rdev(sd), print_time(sd_v2_mtime(sd))); |
| 60 | } | 60 | } |
| @@ -408,7 +408,7 @@ static void direntry_print_item(struct item_head *ih, char *item) | |||
| 408 | namebuf[namelen + 2] = 0; | 408 | namebuf[namelen + 2] = 0; |
| 409 | } | 409 | } |
| 410 | 410 | ||
| 411 | printk("%d: %-15s%-15d%-15d%-15Ld%-15Ld(%s)\n", | 411 | printk("%d: %-15s%-15d%-15d%-15lld%-15lld(%s)\n", |
| 412 | i, namebuf, | 412 | i, namebuf, |
| 413 | deh_dir_id(deh), deh_objectid(deh), | 413 | deh_dir_id(deh), deh_objectid(deh), |
| 414 | GET_HASH_VALUE(deh_offset(deh)), | 414 | GET_HASH_VALUE(deh_offset(deh)), |
diff --git a/fs/reiserfs/lbalance.c b/fs/reiserfs/lbalance.c index d6744c8b24e1..814dda3ec998 100644 --- a/fs/reiserfs/lbalance.c +++ b/fs/reiserfs/lbalance.c | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README | 2 | * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README |
| 3 | */ | 3 | */ |
| 4 | 4 | ||
| 5 | #include <asm/uaccess.h> | 5 | #include <linux/uaccess.h> |
| 6 | #include <linux/string.h> | 6 | #include <linux/string.h> |
| 7 | #include <linux/time.h> | 7 | #include <linux/time.h> |
| 8 | #include "reiserfs.h" | 8 | #include "reiserfs.h" |
diff --git a/fs/reiserfs/prints.c b/fs/reiserfs/prints.c index c9b47e91baf8..ae1dc841db3a 100644 --- a/fs/reiserfs/prints.c +++ b/fs/reiserfs/prints.c | |||
| @@ -17,7 +17,7 @@ static char off_buf[80]; | |||
| 17 | static char *reiserfs_cpu_offset(struct cpu_key *key) | 17 | static char *reiserfs_cpu_offset(struct cpu_key *key) |
| 18 | { | 18 | { |
| 19 | if (cpu_key_k_type(key) == TYPE_DIRENTRY) | 19 | if (cpu_key_k_type(key) == TYPE_DIRENTRY) |
| 20 | sprintf(off_buf, "%Lu(%Lu)", | 20 | sprintf(off_buf, "%llu(%llu)", |
| 21 | (unsigned long long) | 21 | (unsigned long long) |
| 22 | GET_HASH_VALUE(cpu_key_k_offset(key)), | 22 | GET_HASH_VALUE(cpu_key_k_offset(key)), |
| 23 | (unsigned long long) | 23 | (unsigned long long) |
| @@ -34,7 +34,7 @@ static char *le_offset(struct reiserfs_key *key) | |||
| 34 | 34 | ||
| 35 | version = le_key_version(key); | 35 | version = le_key_version(key); |
| 36 | if (le_key_k_type(version, key) == TYPE_DIRENTRY) | 36 | if (le_key_k_type(version, key) == TYPE_DIRENTRY) |
| 37 | sprintf(off_buf, "%Lu(%Lu)", | 37 | sprintf(off_buf, "%llu(%llu)", |
| 38 | (unsigned long long) | 38 | (unsigned long long) |
| 39 | GET_HASH_VALUE(le_key_k_offset(version, key)), | 39 | GET_HASH_VALUE(le_key_k_offset(version, key)), |
| 40 | (unsigned long long) | 40 | (unsigned long long) |
diff --git a/fs/reiserfs/procfs.c b/fs/reiserfs/procfs.c index 02b0b7d0f7d5..621b9f381fe1 100644 --- a/fs/reiserfs/procfs.c +++ b/fs/reiserfs/procfs.c | |||
| @@ -11,7 +11,7 @@ | |||
| 11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
| 12 | #include <linux/time.h> | 12 | #include <linux/time.h> |
| 13 | #include <linux/seq_file.h> | 13 | #include <linux/seq_file.h> |
| 14 | #include <asm/uaccess.h> | 14 | #include <linux/uaccess.h> |
| 15 | #include "reiserfs.h" | 15 | #include "reiserfs.h" |
| 16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
| 17 | #include <linux/proc_fs.h> | 17 | #include <linux/proc_fs.h> |
diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c index dd44468edc2b..24cbe013240f 100644 --- a/fs/reiserfs/stree.c +++ b/fs/reiserfs/stree.c | |||
| @@ -2006,7 +2006,7 @@ int reiserfs_do_truncate(struct reiserfs_transaction_handle *th, | |||
| 2006 | &s_search_path) == POSITION_FOUND); | 2006 | &s_search_path) == POSITION_FOUND); |
| 2007 | 2007 | ||
| 2008 | RFALSE(file_size > ROUND_UP(new_file_size), | 2008 | RFALSE(file_size > ROUND_UP(new_file_size), |
| 2009 | "PAP-5680: truncate did not finish: new_file_size %Ld, current %Ld, oid %d", | 2009 | "PAP-5680: truncate did not finish: new_file_size %lld, current %lld, oid %d", |
| 2010 | new_file_size, file_size, s_item_key.on_disk_key.k_objectid); | 2010 | new_file_size, file_size, s_item_key.on_disk_key.k_objectid); |
| 2011 | 2011 | ||
| 2012 | update_and_out: | 2012 | update_and_out: |
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index a392cef6acc6..709ea92d716f 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c | |||
| @@ -15,7 +15,7 @@ | |||
| 15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
| 16 | #include <linux/vmalloc.h> | 16 | #include <linux/vmalloc.h> |
| 17 | #include <linux/time.h> | 17 | #include <linux/time.h> |
| 18 | #include <asm/uaccess.h> | 18 | #include <linux/uaccess.h> |
| 19 | #include "reiserfs.h" | 19 | #include "reiserfs.h" |
| 20 | #include "acl.h" | 20 | #include "acl.h" |
| 21 | #include "xattr.h" | 21 | #include "xattr.h" |
| @@ -331,7 +331,7 @@ static int finish_unfinished(struct super_block *s) | |||
| 331 | * not completed truncate found. New size was | 331 | * not completed truncate found. New size was |
| 332 | * committed together with "save" link | 332 | * committed together with "save" link |
| 333 | */ | 333 | */ |
| 334 | reiserfs_info(s, "Truncating %k to %Ld ..", | 334 | reiserfs_info(s, "Truncating %k to %lld ..", |
| 335 | INODE_PKEY(inode), inode->i_size); | 335 | INODE_PKEY(inode), inode->i_size); |
| 336 | 336 | ||
| 337 | /* don't update modification time */ | 337 | /* don't update modification time */ |
| @@ -1577,7 +1577,7 @@ static int read_super_block(struct super_block *s, int offset) | |||
| 1577 | rs = (struct reiserfs_super_block *)bh->b_data; | 1577 | rs = (struct reiserfs_super_block *)bh->b_data; |
| 1578 | if (sb_blocksize(rs) != s->s_blocksize) { | 1578 | if (sb_blocksize(rs) != s->s_blocksize) { |
| 1579 | reiserfs_warning(s, "sh-2011", "can't find a reiserfs " | 1579 | reiserfs_warning(s, "sh-2011", "can't find a reiserfs " |
| 1580 | "filesystem on (dev %s, block %Lu, size %lu)", | 1580 | "filesystem on (dev %s, block %llu, size %lu)", |
| 1581 | s->s_id, | 1581 | s->s_id, |
| 1582 | (unsigned long long)bh->b_blocknr, | 1582 | (unsigned long long)bh->b_blocknr, |
| 1583 | s->s_blocksize); | 1583 | s->s_blocksize); |
| @@ -2441,8 +2441,7 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type, | |||
| 2441 | struct buffer_head tmp_bh, *bh; | 2441 | struct buffer_head tmp_bh, *bh; |
| 2442 | 2442 | ||
| 2443 | if (!current->journal_info) { | 2443 | if (!current->journal_info) { |
| 2444 | printk(KERN_WARNING "reiserfs: Quota write (off=%Lu, len=%Lu)" | 2444 | printk(KERN_WARNING "reiserfs: Quota write (off=%llu, len=%llu) cancelled because transaction is not started.\n", |
| 2445 | " cancelled because transaction is not started.\n", | ||
| 2446 | (unsigned long long)off, (unsigned long long)len); | 2445 | (unsigned long long)off, (unsigned long long)len); |
| 2447 | return -EIO; | 2446 | return -EIO; |
| 2448 | } | 2447 | } |
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index ca416d099e7d..7c36898af402 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c | |||
| @@ -45,7 +45,7 @@ | |||
| 45 | #include <linux/xattr.h> | 45 | #include <linux/xattr.h> |
| 46 | #include "xattr.h" | 46 | #include "xattr.h" |
| 47 | #include "acl.h" | 47 | #include "acl.h" |
| 48 | #include <asm/uaccess.h> | 48 | #include <linux/uaccess.h> |
| 49 | #include <net/checksum.h> | 49 | #include <net/checksum.h> |
| 50 | #include <linux/stat.h> | 50 | #include <linux/stat.h> |
| 51 | #include <linux/quotaops.h> | 51 | #include <linux/quotaops.h> |
| @@ -84,6 +84,7 @@ static int xattr_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | |||
| 84 | static int xattr_unlink(struct inode *dir, struct dentry *dentry) | 84 | static int xattr_unlink(struct inode *dir, struct dentry *dentry) |
| 85 | { | 85 | { |
| 86 | int error; | 86 | int error; |
| 87 | |||
| 87 | BUG_ON(!mutex_is_locked(&dir->i_mutex)); | 88 | BUG_ON(!mutex_is_locked(&dir->i_mutex)); |
| 88 | 89 | ||
| 89 | mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD); | 90 | mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD); |
| @@ -98,6 +99,7 @@ static int xattr_unlink(struct inode *dir, struct dentry *dentry) | |||
| 98 | static int xattr_rmdir(struct inode *dir, struct dentry *dentry) | 99 | static int xattr_rmdir(struct inode *dir, struct dentry *dentry) |
| 99 | { | 100 | { |
| 100 | int error; | 101 | int error; |
| 102 | |||
| 101 | BUG_ON(!mutex_is_locked(&dir->i_mutex)); | 103 | BUG_ON(!mutex_is_locked(&dir->i_mutex)); |
| 102 | 104 | ||
| 103 | mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD); | 105 | mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD); |
| @@ -117,6 +119,7 @@ static struct dentry *open_xa_root(struct super_block *sb, int flags) | |||
| 117 | { | 119 | { |
| 118 | struct dentry *privroot = REISERFS_SB(sb)->priv_root; | 120 | struct dentry *privroot = REISERFS_SB(sb)->priv_root; |
| 119 | struct dentry *xaroot; | 121 | struct dentry *xaroot; |
| 122 | |||
| 120 | if (!privroot->d_inode) | 123 | if (!privroot->d_inode) |
| 121 | return ERR_PTR(-ENODATA); | 124 | return ERR_PTR(-ENODATA); |
| 122 | 125 | ||
| @@ -127,6 +130,7 @@ static struct dentry *open_xa_root(struct super_block *sb, int flags) | |||
| 127 | xaroot = ERR_PTR(-ENODATA); | 130 | xaroot = ERR_PTR(-ENODATA); |
| 128 | else if (!xaroot->d_inode) { | 131 | else if (!xaroot->d_inode) { |
| 129 | int err = -ENODATA; | 132 | int err = -ENODATA; |
| 133 | |||
| 130 | if (xattr_may_create(flags)) | 134 | if (xattr_may_create(flags)) |
| 131 | err = xattr_mkdir(privroot->d_inode, xaroot, 0700); | 135 | err = xattr_mkdir(privroot->d_inode, xaroot, 0700); |
| 132 | if (err) { | 136 | if (err) { |
| @@ -157,6 +161,7 @@ static struct dentry *open_xa_dir(const struct inode *inode, int flags) | |||
| 157 | xadir = lookup_one_len(namebuf, xaroot, strlen(namebuf)); | 161 | xadir = lookup_one_len(namebuf, xaroot, strlen(namebuf)); |
| 158 | if (!IS_ERR(xadir) && !xadir->d_inode) { | 162 | if (!IS_ERR(xadir) && !xadir->d_inode) { |
| 159 | int err = -ENODATA; | 163 | int err = -ENODATA; |
| 164 | |||
| 160 | if (xattr_may_create(flags)) | 165 | if (xattr_may_create(flags)) |
| 161 | err = xattr_mkdir(xaroot->d_inode, xadir, 0700); | 166 | err = xattr_mkdir(xaroot->d_inode, xadir, 0700); |
| 162 | if (err) { | 167 | if (err) { |
| @@ -188,6 +193,7 @@ fill_with_dentries(void *buf, const char *name, int namelen, loff_t offset, | |||
| 188 | { | 193 | { |
| 189 | struct reiserfs_dentry_buf *dbuf = buf; | 194 | struct reiserfs_dentry_buf *dbuf = buf; |
| 190 | struct dentry *dentry; | 195 | struct dentry *dentry; |
| 196 | |||
| 191 | WARN_ON_ONCE(!mutex_is_locked(&dbuf->xadir->d_inode->i_mutex)); | 197 | WARN_ON_ONCE(!mutex_is_locked(&dbuf->xadir->d_inode->i_mutex)); |
| 192 | 198 | ||
| 193 | if (dbuf->count == ARRAY_SIZE(dbuf->dentries)) | 199 | if (dbuf->count == ARRAY_SIZE(dbuf->dentries)) |
| @@ -218,6 +224,7 @@ static void | |||
| 218 | cleanup_dentry_buf(struct reiserfs_dentry_buf *buf) | 224 | cleanup_dentry_buf(struct reiserfs_dentry_buf *buf) |
| 219 | { | 225 | { |
| 220 | int i; | 226 | int i; |
| 227 | |||
| 221 | for (i = 0; i < buf->count; i++) | 228 | for (i = 0; i < buf->count; i++) |
| 222 | if (buf->dentries[i]) | 229 | if (buf->dentries[i]) |
| 223 | dput(buf->dentries[i]); | 230 | dput(buf->dentries[i]); |
| @@ -283,11 +290,13 @@ static int reiserfs_for_each_xattr(struct inode *inode, | |||
| 283 | int blocks = JOURNAL_PER_BALANCE_CNT * 2 + 2 + | 290 | int blocks = JOURNAL_PER_BALANCE_CNT * 2 + 2 + |
| 284 | 4 * REISERFS_QUOTA_TRANS_BLOCKS(inode->i_sb); | 291 | 4 * REISERFS_QUOTA_TRANS_BLOCKS(inode->i_sb); |
| 285 | struct reiserfs_transaction_handle th; | 292 | struct reiserfs_transaction_handle th; |
| 293 | |||
| 286 | reiserfs_write_lock(inode->i_sb); | 294 | reiserfs_write_lock(inode->i_sb); |
| 287 | err = journal_begin(&th, inode->i_sb, blocks); | 295 | err = journal_begin(&th, inode->i_sb, blocks); |
| 288 | reiserfs_write_unlock(inode->i_sb); | 296 | reiserfs_write_unlock(inode->i_sb); |
| 289 | if (!err) { | 297 | if (!err) { |
| 290 | int jerror; | 298 | int jerror; |
| 299 | |||
| 291 | mutex_lock_nested(&dir->d_parent->d_inode->i_mutex, | 300 | mutex_lock_nested(&dir->d_parent->d_inode->i_mutex, |
| 292 | I_MUTEX_XATTR); | 301 | I_MUTEX_XATTR); |
| 293 | err = action(dir, data); | 302 | err = action(dir, data); |
| @@ -340,6 +349,7 @@ static int chown_one_xattr(struct dentry *dentry, void *data) | |||
| 340 | int reiserfs_delete_xattrs(struct inode *inode) | 349 | int reiserfs_delete_xattrs(struct inode *inode) |
| 341 | { | 350 | { |
| 342 | int err = reiserfs_for_each_xattr(inode, delete_one_xattr, NULL); | 351 | int err = reiserfs_for_each_xattr(inode, delete_one_xattr, NULL); |
| 352 | |||
| 343 | if (err) | 353 | if (err) |
| 344 | reiserfs_warning(inode->i_sb, "jdm-20004", | 354 | reiserfs_warning(inode->i_sb, "jdm-20004", |
| 345 | "Couldn't delete all xattrs (%d)\n", err); | 355 | "Couldn't delete all xattrs (%d)\n", err); |
| @@ -350,6 +360,7 @@ int reiserfs_delete_xattrs(struct inode *inode) | |||
| 350 | int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs) | 360 | int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs) |
| 351 | { | 361 | { |
| 352 | int err = reiserfs_for_each_xattr(inode, chown_one_xattr, attrs); | 362 | int err = reiserfs_for_each_xattr(inode, chown_one_xattr, attrs); |
| 363 | |||
| 353 | if (err) | 364 | if (err) |
| 354 | reiserfs_warning(inode->i_sb, "jdm-20007", | 365 | reiserfs_warning(inode->i_sb, "jdm-20007", |
| 355 | "Couldn't chown all xattrs (%d)\n", err); | 366 | "Couldn't chown all xattrs (%d)\n", err); |
| @@ -439,6 +450,7 @@ int reiserfs_commit_write(struct file *f, struct page *page, | |||
| 439 | static void update_ctime(struct inode *inode) | 450 | static void update_ctime(struct inode *inode) |
| 440 | { | 451 | { |
| 441 | struct timespec now = current_fs_time(inode->i_sb); | 452 | struct timespec now = current_fs_time(inode->i_sb); |
| 453 | |||
| 442 | if (inode_unhashed(inode) || !inode->i_nlink || | 454 | if (inode_unhashed(inode) || !inode->i_nlink || |
| 443 | timespec_equal(&inode->i_ctime, &now)) | 455 | timespec_equal(&inode->i_ctime, &now)) |
| 444 | return; | 456 | return; |
| @@ -514,6 +526,7 @@ reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th, | |||
| 514 | size_t chunk; | 526 | size_t chunk; |
| 515 | size_t skip = 0; | 527 | size_t skip = 0; |
| 516 | size_t page_offset = (file_pos & (PAGE_CACHE_SIZE - 1)); | 528 | size_t page_offset = (file_pos & (PAGE_CACHE_SIZE - 1)); |
| 529 | |||
| 517 | if (buffer_size - buffer_pos > PAGE_CACHE_SIZE) | 530 | if (buffer_size - buffer_pos > PAGE_CACHE_SIZE) |
| 518 | chunk = PAGE_CACHE_SIZE; | 531 | chunk = PAGE_CACHE_SIZE; |
| 519 | else | 532 | else |
| @@ -530,6 +543,7 @@ reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th, | |||
| 530 | 543 | ||
| 531 | if (file_pos == 0) { | 544 | if (file_pos == 0) { |
| 532 | struct reiserfs_xattr_header *rxh; | 545 | struct reiserfs_xattr_header *rxh; |
| 546 | |||
| 533 | skip = file_pos = sizeof(struct reiserfs_xattr_header); | 547 | skip = file_pos = sizeof(struct reiserfs_xattr_header); |
| 534 | if (chunk + skip > PAGE_CACHE_SIZE) | 548 | if (chunk + skip > PAGE_CACHE_SIZE) |
| 535 | chunk = PAGE_CACHE_SIZE - skip; | 549 | chunk = PAGE_CACHE_SIZE - skip; |
| @@ -659,6 +673,7 @@ reiserfs_xattr_get(struct inode *inode, const char *name, void *buffer, | |||
| 659 | size_t chunk; | 673 | size_t chunk; |
| 660 | char *data; | 674 | char *data; |
| 661 | size_t skip = 0; | 675 | size_t skip = 0; |
| 676 | |||
| 662 | if (isize - file_pos > PAGE_CACHE_SIZE) | 677 | if (isize - file_pos > PAGE_CACHE_SIZE) |
| 663 | chunk = PAGE_CACHE_SIZE; | 678 | chunk = PAGE_CACHE_SIZE; |
| 664 | else | 679 | else |
| @@ -792,6 +807,7 @@ reiserfs_setxattr(struct dentry *dentry, const char *name, const void *value, | |||
| 792 | int reiserfs_removexattr(struct dentry *dentry, const char *name) | 807 | int reiserfs_removexattr(struct dentry *dentry, const char *name) |
| 793 | { | 808 | { |
| 794 | const struct xattr_handler *handler; | 809 | const struct xattr_handler *handler; |
| 810 | |||
| 795 | handler = find_xattr_handler_prefix(dentry->d_sb->s_xattr, name); | 811 | handler = find_xattr_handler_prefix(dentry->d_sb->s_xattr, name); |
| 796 | 812 | ||
| 797 | if (!handler || get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1) | 813 | if (!handler || get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1) |
| @@ -813,9 +829,11 @@ static int listxattr_filler(void *buf, const char *name, int namelen, | |||
| 813 | { | 829 | { |
| 814 | struct listxattr_buf *b = (struct listxattr_buf *)buf; | 830 | struct listxattr_buf *b = (struct listxattr_buf *)buf; |
| 815 | size_t size; | 831 | size_t size; |
| 832 | |||
| 816 | if (name[0] != '.' || | 833 | if (name[0] != '.' || |
| 817 | (namelen != 1 && (name[1] != '.' || namelen != 2))) { | 834 | (namelen != 1 && (name[1] != '.' || namelen != 2))) { |
| 818 | const struct xattr_handler *handler; | 835 | const struct xattr_handler *handler; |
| 836 | |||
| 819 | handler = find_xattr_handler_prefix(b->dentry->d_sb->s_xattr, | 837 | handler = find_xattr_handler_prefix(b->dentry->d_sb->s_xattr, |
| 820 | name); | 838 | name); |
| 821 | if (!handler) /* Unsupported xattr name */ | 839 | if (!handler) /* Unsupported xattr name */ |
| @@ -885,6 +903,7 @@ static int create_privroot(struct dentry *dentry) | |||
| 885 | { | 903 | { |
| 886 | int err; | 904 | int err; |
| 887 | struct inode *inode = dentry->d_parent->d_inode; | 905 | struct inode *inode = dentry->d_parent->d_inode; |
| 906 | |||
| 888 | WARN_ON_ONCE(!mutex_is_locked(&inode->i_mutex)); | 907 | WARN_ON_ONCE(!mutex_is_locked(&inode->i_mutex)); |
| 889 | 908 | ||
| 890 | err = xattr_mkdir(inode, dentry, 0700); | 909 | err = xattr_mkdir(inode, dentry, 0700); |
| @@ -1015,6 +1034,7 @@ int reiserfs_xattr_init(struct super_block *s, int mount_flags) | |||
| 1015 | mutex_lock(&privroot->d_inode->i_mutex); | 1034 | mutex_lock(&privroot->d_inode->i_mutex); |
| 1016 | if (!REISERFS_SB(s)->xattr_root) { | 1035 | if (!REISERFS_SB(s)->xattr_root) { |
| 1017 | struct dentry *dentry; | 1036 | struct dentry *dentry; |
| 1037 | |||
| 1018 | dentry = lookup_one_len(XAROOT_NAME, privroot, | 1038 | dentry = lookup_one_len(XAROOT_NAME, privroot, |
| 1019 | strlen(XAROOT_NAME)); | 1039 | strlen(XAROOT_NAME)); |
| 1020 | if (!IS_ERR(dentry)) | 1040 | if (!IS_ERR(dentry)) |
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c index 44503e293790..4b34b9dc03dd 100644 --- a/fs/reiserfs/xattr_acl.c +++ b/fs/reiserfs/xattr_acl.c | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | #include <linux/posix_acl_xattr.h> | 9 | #include <linux/posix_acl_xattr.h> |
| 10 | #include "xattr.h" | 10 | #include "xattr.h" |
| 11 | #include "acl.h" | 11 | #include "acl.h" |
| 12 | #include <asm/uaccess.h> | 12 | #include <linux/uaccess.h> |
| 13 | 13 | ||
| 14 | static int __reiserfs_set_acl(struct reiserfs_transaction_handle *th, | 14 | static int __reiserfs_set_acl(struct reiserfs_transaction_handle *th, |
| 15 | struct inode *inode, int type, | 15 | struct inode *inode, int type, |
diff --git a/fs/reiserfs/xattr_security.c b/fs/reiserfs/xattr_security.c index 800a3cef6f62..e7f8939a4cb5 100644 --- a/fs/reiserfs/xattr_security.c +++ b/fs/reiserfs/xattr_security.c | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | #include <linux/slab.h> | 6 | #include <linux/slab.h> |
| 7 | #include "xattr.h" | 7 | #include "xattr.h" |
| 8 | #include <linux/security.h> | 8 | #include <linux/security.h> |
| 9 | #include <asm/uaccess.h> | 9 | #include <linux/uaccess.h> |
| 10 | 10 | ||
| 11 | static int | 11 | static int |
| 12 | security_get(struct dentry *dentry, const char *name, void *buffer, size_t size, | 12 | security_get(struct dentry *dentry, const char *name, void *buffer, size_t size, |
diff --git a/fs/reiserfs/xattr_trusted.c b/fs/reiserfs/xattr_trusted.c index a0035719f66b..5eeb0c48ba46 100644 --- a/fs/reiserfs/xattr_trusted.c +++ b/fs/reiserfs/xattr_trusted.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | #include <linux/pagemap.h> | 5 | #include <linux/pagemap.h> |
| 6 | #include <linux/xattr.h> | 6 | #include <linux/xattr.h> |
| 7 | #include "xattr.h" | 7 | #include "xattr.h" |
| 8 | #include <asm/uaccess.h> | 8 | #include <linux/uaccess.h> |
| 9 | 9 | ||
| 10 | static int | 10 | static int |
| 11 | trusted_get(struct dentry *dentry, const char *name, void *buffer, size_t size, | 11 | trusted_get(struct dentry *dentry, const char *name, void *buffer, size_t size, |
diff --git a/fs/reiserfs/xattr_user.c b/fs/reiserfs/xattr_user.c index 8667491ae7c3..e50eab046471 100644 --- a/fs/reiserfs/xattr_user.c +++ b/fs/reiserfs/xattr_user.c | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | #include <linux/pagemap.h> | 4 | #include <linux/pagemap.h> |
| 5 | #include <linux/xattr.h> | 5 | #include <linux/xattr.h> |
| 6 | #include "xattr.h" | 6 | #include "xattr.h" |
| 7 | #include <asm/uaccess.h> | 7 | #include <linux/uaccess.h> |
| 8 | 8 | ||
| 9 | static int | 9 | static int |
| 10 | user_get(struct dentry *dentry, const char *name, void *buffer, size_t size, | 10 | user_get(struct dentry *dentry, const char *name, void *buffer, size_t size, |
diff --git a/fs/romfs/super.c b/fs/romfs/super.c index ef90e8bca95a..e98dd88197d5 100644 --- a/fs/romfs/super.c +++ b/fs/romfs/super.c | |||
| @@ -56,6 +56,8 @@ | |||
| 56 | * 2 of the Licence, or (at your option) any later version. | 56 | * 2 of the Licence, or (at your option) any later version. |
| 57 | */ | 57 | */ |
| 58 | 58 | ||
| 59 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 60 | |||
| 59 | #include <linux/module.h> | 61 | #include <linux/module.h> |
| 60 | #include <linux/string.h> | 62 | #include <linux/string.h> |
| 61 | #include <linux/fs.h> | 63 | #include <linux/fs.h> |
| @@ -380,7 +382,7 @@ static struct inode *romfs_iget(struct super_block *sb, unsigned long pos) | |||
| 380 | eio: | 382 | eio: |
| 381 | ret = -EIO; | 383 | ret = -EIO; |
| 382 | error: | 384 | error: |
| 383 | printk(KERN_ERR "ROMFS: read error for inode 0x%lx\n", pos); | 385 | pr_err("read error for inode 0x%lx\n", pos); |
| 384 | return ERR_PTR(ret); | 386 | return ERR_PTR(ret); |
| 385 | } | 387 | } |
| 386 | 388 | ||
| @@ -390,6 +392,7 @@ error: | |||
| 390 | static struct inode *romfs_alloc_inode(struct super_block *sb) | 392 | static struct inode *romfs_alloc_inode(struct super_block *sb) |
| 391 | { | 393 | { |
| 392 | struct romfs_inode_info *inode; | 394 | struct romfs_inode_info *inode; |
| 395 | |||
| 393 | inode = kmem_cache_alloc(romfs_inode_cachep, GFP_KERNEL); | 396 | inode = kmem_cache_alloc(romfs_inode_cachep, GFP_KERNEL); |
| 394 | return inode ? &inode->vfs_inode : NULL; | 397 | return inode ? &inode->vfs_inode : NULL; |
| 395 | } | 398 | } |
| @@ -400,6 +403,7 @@ static struct inode *romfs_alloc_inode(struct super_block *sb) | |||
| 400 | static void romfs_i_callback(struct rcu_head *head) | 403 | static void romfs_i_callback(struct rcu_head *head) |
| 401 | { | 404 | { |
| 402 | struct inode *inode = container_of(head, struct inode, i_rcu); | 405 | struct inode *inode = container_of(head, struct inode, i_rcu); |
| 406 | |||
| 403 | kmem_cache_free(romfs_inode_cachep, ROMFS_I(inode)); | 407 | kmem_cache_free(romfs_inode_cachep, ROMFS_I(inode)); |
| 404 | } | 408 | } |
| 405 | 409 | ||
| @@ -507,15 +511,13 @@ static int romfs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 507 | if (rsb->word0 != ROMSB_WORD0 || rsb->word1 != ROMSB_WORD1 || | 511 | if (rsb->word0 != ROMSB_WORD0 || rsb->word1 != ROMSB_WORD1 || |
| 508 | img_size < ROMFH_SIZE) { | 512 | img_size < ROMFH_SIZE) { |
| 509 | if (!silent) | 513 | if (!silent) |
| 510 | printk(KERN_WARNING "VFS:" | 514 | pr_warn("VFS: Can't find a romfs filesystem on dev %s.\n", |
| 511 | " Can't find a romfs filesystem on dev %s.\n", | ||
| 512 | sb->s_id); | 515 | sb->s_id); |
| 513 | goto error_rsb_inval; | 516 | goto error_rsb_inval; |
| 514 | } | 517 | } |
| 515 | 518 | ||
| 516 | if (romfs_checksum(rsb, min_t(size_t, img_size, 512))) { | 519 | if (romfs_checksum(rsb, min_t(size_t, img_size, 512))) { |
| 517 | printk(KERN_ERR "ROMFS: bad initial checksum on dev %s.\n", | 520 | pr_err("bad initial checksum on dev %s.\n", sb->s_id); |
| 518 | sb->s_id); | ||
| 519 | goto error_rsb_inval; | 521 | goto error_rsb_inval; |
| 520 | } | 522 | } |
| 521 | 523 | ||
| @@ -523,8 +525,8 @@ static int romfs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 523 | 525 | ||
| 524 | len = strnlen(rsb->name, ROMFS_MAXFN); | 526 | len = strnlen(rsb->name, ROMFS_MAXFN); |
| 525 | if (!silent) | 527 | if (!silent) |
| 526 | printk(KERN_NOTICE "ROMFS: Mounting image '%*.*s' through %s\n", | 528 | pr_notice("Mounting image '%*.*s' through %s\n", |
| 527 | (unsigned) len, (unsigned) len, rsb->name, storage); | 529 | (unsigned) len, (unsigned) len, rsb->name, storage); |
| 528 | 530 | ||
| 529 | kfree(rsb); | 531 | kfree(rsb); |
| 530 | rsb = NULL; | 532 | rsb = NULL; |
| @@ -614,7 +616,7 @@ static int __init init_romfs_fs(void) | |||
| 614 | { | 616 | { |
| 615 | int ret; | 617 | int ret; |
| 616 | 618 | ||
| 617 | printk(KERN_INFO "ROMFS MTD (C) 2007 Red Hat, Inc.\n"); | 619 | pr_info("ROMFS MTD (C) 2007 Red Hat, Inc.\n"); |
| 618 | 620 | ||
| 619 | romfs_inode_cachep = | 621 | romfs_inode_cachep = |
| 620 | kmem_cache_create("romfs_i", | 622 | kmem_cache_create("romfs_i", |
| @@ -623,13 +625,12 @@ static int __init init_romfs_fs(void) | |||
| 623 | romfs_i_init_once); | 625 | romfs_i_init_once); |
| 624 | 626 | ||
| 625 | if (!romfs_inode_cachep) { | 627 | if (!romfs_inode_cachep) { |
| 626 | printk(KERN_ERR | 628 | pr_err("Failed to initialise inode cache\n"); |
| 627 | "ROMFS error: Failed to initialise inode cache\n"); | ||
| 628 | return -ENOMEM; | 629 | return -ENOMEM; |
| 629 | } | 630 | } |
| 630 | ret = register_filesystem(&romfs_fs_type); | 631 | ret = register_filesystem(&romfs_fs_type); |
| 631 | if (ret) { | 632 | if (ret) { |
| 632 | printk(KERN_ERR "ROMFS error: Failed to register filesystem\n"); | 633 | pr_err("Failed to register filesystem\n"); |
| 633 | goto error_register; | 634 | goto error_register; |
| 634 | } | 635 | } |
| 635 | return 0; | 636 | return 0; |
diff --git a/fs/ufs/Makefile b/fs/ufs/Makefile index dd39980437fc..4d0e02b022b3 100644 --- a/fs/ufs/Makefile +++ b/fs/ufs/Makefile | |||
| @@ -6,3 +6,4 @@ obj-$(CONFIG_UFS_FS) += ufs.o | |||
| 6 | 6 | ||
| 7 | ufs-objs := balloc.o cylinder.o dir.o file.o ialloc.o inode.o \ | 7 | ufs-objs := balloc.o cylinder.o dir.o file.o ialloc.o inode.o \ |
| 8 | namei.o super.o symlink.o truncate.o util.o | 8 | namei.o super.o symlink.o truncate.o util.o |
| 9 | ccflags-$(CONFIG_UFS_DEBUG) += -DDEBUG | ||
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index 61e8a9b021dd..7c580c97990e 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c | |||
| @@ -158,16 +158,16 @@ out: | |||
| 158 | 158 | ||
| 159 | /** | 159 | /** |
| 160 | * ufs_inode_getfrag() - allocate new fragment(s) | 160 | * ufs_inode_getfrag() - allocate new fragment(s) |
| 161 | * @inode - pointer to inode | 161 | * @inode: pointer to inode |
| 162 | * @fragment - number of `fragment' which hold pointer | 162 | * @fragment: number of `fragment' which hold pointer |
| 163 | * to new allocated fragment(s) | 163 | * to new allocated fragment(s) |
| 164 | * @new_fragment - number of new allocated fragment(s) | 164 | * @new_fragment: number of new allocated fragment(s) |
| 165 | * @required - how many fragment(s) we require | 165 | * @required: how many fragment(s) we require |
| 166 | * @err - we set it if something wrong | 166 | * @err: we set it if something wrong |
| 167 | * @phys - pointer to where we save physical number of new allocated fragments, | 167 | * @phys: pointer to where we save physical number of new allocated fragments, |
| 168 | * NULL if we allocate not data(indirect blocks for example). | 168 | * NULL if we allocate not data(indirect blocks for example). |
| 169 | * @new - we set it if we allocate new block | 169 | * @new: we set it if we allocate new block |
| 170 | * @locked_page - for ufs_new_fragments() | 170 | * @locked_page: for ufs_new_fragments() |
| 171 | */ | 171 | */ |
| 172 | static struct buffer_head * | 172 | static struct buffer_head * |
| 173 | ufs_inode_getfrag(struct inode *inode, u64 fragment, | 173 | ufs_inode_getfrag(struct inode *inode, u64 fragment, |
| @@ -315,16 +315,16 @@ repeat2: | |||
| 315 | 315 | ||
| 316 | /** | 316 | /** |
| 317 | * ufs_inode_getblock() - allocate new block | 317 | * ufs_inode_getblock() - allocate new block |
| 318 | * @inode - pointer to inode | 318 | * @inode: pointer to inode |
| 319 | * @bh - pointer to block which hold "pointer" to new allocated block | 319 | * @bh: pointer to block which hold "pointer" to new allocated block |
| 320 | * @fragment - number of `fragment' which hold pointer | 320 | * @fragment: number of `fragment' which hold pointer |
| 321 | * to new allocated block | 321 | * to new allocated block |
| 322 | * @new_fragment - number of new allocated fragment | 322 | * @new_fragment: number of new allocated fragment |
| 323 | * (block will hold this fragment and also uspi->s_fpb-1) | 323 | * (block will hold this fragment and also uspi->s_fpb-1) |
| 324 | * @err - see ufs_inode_getfrag() | 324 | * @err: see ufs_inode_getfrag() |
| 325 | * @phys - see ufs_inode_getfrag() | 325 | * @phys: see ufs_inode_getfrag() |
| 326 | * @new - see ufs_inode_getfrag() | 326 | * @new: see ufs_inode_getfrag() |
| 327 | * @locked_page - see ufs_inode_getfrag() | 327 | * @locked_page: see ufs_inode_getfrag() |
| 328 | */ | 328 | */ |
| 329 | static struct buffer_head * | 329 | static struct buffer_head * |
| 330 | ufs_inode_getblock(struct inode *inode, struct buffer_head *bh, | 330 | ufs_inode_getblock(struct inode *inode, struct buffer_head *bh, |
diff --git a/fs/ufs/super.c b/fs/ufs/super.c index b879f1ba3439..da73801301d5 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c | |||
| @@ -65,7 +65,6 @@ | |||
| 65 | * Evgeniy Dushistov <dushistov@mail.ru>, 2007 | 65 | * Evgeniy Dushistov <dushistov@mail.ru>, 2007 |
| 66 | */ | 66 | */ |
| 67 | 67 | ||
| 68 | |||
| 69 | #include <linux/exportfs.h> | 68 | #include <linux/exportfs.h> |
| 70 | #include <linux/module.h> | 69 | #include <linux/module.h> |
| 71 | #include <linux/bitops.h> | 70 | #include <linux/bitops.h> |
| @@ -172,73 +171,73 @@ static void ufs_print_super_stuff(struct super_block *sb, | |||
| 172 | { | 171 | { |
| 173 | u32 magic = fs32_to_cpu(sb, usb3->fs_magic); | 172 | u32 magic = fs32_to_cpu(sb, usb3->fs_magic); |
| 174 | 173 | ||
| 175 | printk("ufs_print_super_stuff\n"); | 174 | pr_debug("ufs_print_super_stuff\n"); |
| 176 | printk(" magic: 0x%x\n", magic); | 175 | pr_debug(" magic: 0x%x\n", magic); |
| 177 | if (fs32_to_cpu(sb, usb3->fs_magic) == UFS2_MAGIC) { | 176 | if (fs32_to_cpu(sb, usb3->fs_magic) == UFS2_MAGIC) { |
| 178 | printk(" fs_size: %llu\n", (unsigned long long) | 177 | pr_debug(" fs_size: %llu\n", (unsigned long long) |
| 179 | fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_size)); | 178 | fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_size)); |
| 180 | printk(" fs_dsize: %llu\n", (unsigned long long) | 179 | pr_debug(" fs_dsize: %llu\n", (unsigned long long) |
| 181 | fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_dsize)); | 180 | fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_dsize)); |
| 182 | printk(" bsize: %u\n", | 181 | pr_debug(" bsize: %u\n", |
| 183 | fs32_to_cpu(sb, usb1->fs_bsize)); | 182 | fs32_to_cpu(sb, usb1->fs_bsize)); |
| 184 | printk(" fsize: %u\n", | 183 | pr_debug(" fsize: %u\n", |
| 185 | fs32_to_cpu(sb, usb1->fs_fsize)); | 184 | fs32_to_cpu(sb, usb1->fs_fsize)); |
| 186 | printk(" fs_volname: %s\n", usb2->fs_un.fs_u2.fs_volname); | 185 | pr_debug(" fs_volname: %s\n", usb2->fs_un.fs_u2.fs_volname); |
| 187 | printk(" fs_sblockloc: %llu\n", (unsigned long long) | 186 | pr_debug(" fs_sblockloc: %llu\n", (unsigned long long) |
| 188 | fs64_to_cpu(sb, usb2->fs_un.fs_u2.fs_sblockloc)); | 187 | fs64_to_cpu(sb, usb2->fs_un.fs_u2.fs_sblockloc)); |
| 189 | printk(" cs_ndir(No of dirs): %llu\n", (unsigned long long) | 188 | pr_debug(" cs_ndir(No of dirs): %llu\n", (unsigned long long) |
| 190 | fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_ndir)); | 189 | fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_ndir)); |
| 191 | printk(" cs_nbfree(No of free blocks): %llu\n", | 190 | pr_debug(" cs_nbfree(No of free blocks): %llu\n", |
| 192 | (unsigned long long) | 191 | (unsigned long long) |
| 193 | fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_nbfree)); | 192 | fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_nbfree)); |
| 194 | printk(KERN_INFO" cs_nifree(Num of free inodes): %llu\n", | 193 | pr_info(" cs_nifree(Num of free inodes): %llu\n", |
| 195 | (unsigned long long) | 194 | (unsigned long long) |
| 196 | fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nifree)); | 195 | fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nifree)); |
| 197 | printk(KERN_INFO" cs_nffree(Num of free frags): %llu\n", | 196 | pr_info(" cs_nffree(Num of free frags): %llu\n", |
| 198 | (unsigned long long) | 197 | (unsigned long long) |
| 199 | fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nffree)); | 198 | fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nffree)); |
| 200 | printk(KERN_INFO" fs_maxsymlinklen: %u\n", | 199 | pr_info(" fs_maxsymlinklen: %u\n", |
| 201 | fs32_to_cpu(sb, usb3->fs_un2.fs_44.fs_maxsymlinklen)); | 200 | fs32_to_cpu(sb, usb3->fs_un2.fs_44.fs_maxsymlinklen)); |
| 202 | } else { | 201 | } else { |
| 203 | printk(" sblkno: %u\n", fs32_to_cpu(sb, usb1->fs_sblkno)); | 202 | pr_debug(" sblkno: %u\n", fs32_to_cpu(sb, usb1->fs_sblkno)); |
| 204 | printk(" cblkno: %u\n", fs32_to_cpu(sb, usb1->fs_cblkno)); | 203 | pr_debug(" cblkno: %u\n", fs32_to_cpu(sb, usb1->fs_cblkno)); |
| 205 | printk(" iblkno: %u\n", fs32_to_cpu(sb, usb1->fs_iblkno)); | 204 | pr_debug(" iblkno: %u\n", fs32_to_cpu(sb, usb1->fs_iblkno)); |
| 206 | printk(" dblkno: %u\n", fs32_to_cpu(sb, usb1->fs_dblkno)); | 205 | pr_debug(" dblkno: %u\n", fs32_to_cpu(sb, usb1->fs_dblkno)); |
| 207 | printk(" cgoffset: %u\n", | 206 | pr_debug(" cgoffset: %u\n", |
| 208 | fs32_to_cpu(sb, usb1->fs_cgoffset)); | 207 | fs32_to_cpu(sb, usb1->fs_cgoffset)); |
| 209 | printk(" ~cgmask: 0x%x\n", | 208 | pr_debug(" ~cgmask: 0x%x\n", |
| 210 | ~fs32_to_cpu(sb, usb1->fs_cgmask)); | 209 | ~fs32_to_cpu(sb, usb1->fs_cgmask)); |
| 211 | printk(" size: %u\n", fs32_to_cpu(sb, usb1->fs_size)); | 210 | pr_debug(" size: %u\n", fs32_to_cpu(sb, usb1->fs_size)); |
| 212 | printk(" dsize: %u\n", fs32_to_cpu(sb, usb1->fs_dsize)); | 211 | pr_debug(" dsize: %u\n", fs32_to_cpu(sb, usb1->fs_dsize)); |
| 213 | printk(" ncg: %u\n", fs32_to_cpu(sb, usb1->fs_ncg)); | 212 | pr_debug(" ncg: %u\n", fs32_to_cpu(sb, usb1->fs_ncg)); |
| 214 | printk(" bsize: %u\n", fs32_to_cpu(sb, usb1->fs_bsize)); | 213 | pr_debug(" bsize: %u\n", fs32_to_cpu(sb, usb1->fs_bsize)); |
| 215 | printk(" fsize: %u\n", fs32_to_cpu(sb, usb1->fs_fsize)); | 214 | pr_debug(" fsize: %u\n", fs32_to_cpu(sb, usb1->fs_fsize)); |
| 216 | printk(" frag: %u\n", fs32_to_cpu(sb, usb1->fs_frag)); | 215 | pr_debug(" frag: %u\n", fs32_to_cpu(sb, usb1->fs_frag)); |
| 217 | printk(" fragshift: %u\n", | 216 | pr_debug(" fragshift: %u\n", |
| 218 | fs32_to_cpu(sb, usb1->fs_fragshift)); | 217 | fs32_to_cpu(sb, usb1->fs_fragshift)); |
| 219 | printk(" ~fmask: %u\n", ~fs32_to_cpu(sb, usb1->fs_fmask)); | 218 | pr_debug(" ~fmask: %u\n", ~fs32_to_cpu(sb, usb1->fs_fmask)); |
| 220 | printk(" fshift: %u\n", fs32_to_cpu(sb, usb1->fs_fshift)); | 219 | pr_debug(" fshift: %u\n", fs32_to_cpu(sb, usb1->fs_fshift)); |
| 221 | printk(" sbsize: %u\n", fs32_to_cpu(sb, usb1->fs_sbsize)); | 220 | pr_debug(" sbsize: %u\n", fs32_to_cpu(sb, usb1->fs_sbsize)); |
| 222 | printk(" spc: %u\n", fs32_to_cpu(sb, usb1->fs_spc)); | 221 | pr_debug(" spc: %u\n", fs32_to_cpu(sb, usb1->fs_spc)); |
| 223 | printk(" cpg: %u\n", fs32_to_cpu(sb, usb1->fs_cpg)); | 222 | pr_debug(" cpg: %u\n", fs32_to_cpu(sb, usb1->fs_cpg)); |
| 224 | printk(" ipg: %u\n", fs32_to_cpu(sb, usb1->fs_ipg)); | 223 | pr_debug(" ipg: %u\n", fs32_to_cpu(sb, usb1->fs_ipg)); |
| 225 | printk(" fpg: %u\n", fs32_to_cpu(sb, usb1->fs_fpg)); | 224 | pr_debug(" fpg: %u\n", fs32_to_cpu(sb, usb1->fs_fpg)); |
| 226 | printk(" csaddr: %u\n", fs32_to_cpu(sb, usb1->fs_csaddr)); | 225 | pr_debug(" csaddr: %u\n", fs32_to_cpu(sb, usb1->fs_csaddr)); |
| 227 | printk(" cssize: %u\n", fs32_to_cpu(sb, usb1->fs_cssize)); | 226 | pr_debug(" cssize: %u\n", fs32_to_cpu(sb, usb1->fs_cssize)); |
| 228 | printk(" cgsize: %u\n", fs32_to_cpu(sb, usb1->fs_cgsize)); | 227 | pr_debug(" cgsize: %u\n", fs32_to_cpu(sb, usb1->fs_cgsize)); |
| 229 | printk(" fstodb: %u\n", | 228 | pr_debug(" fstodb: %u\n", |
| 230 | fs32_to_cpu(sb, usb1->fs_fsbtodb)); | 229 | fs32_to_cpu(sb, usb1->fs_fsbtodb)); |
| 231 | printk(" nrpos: %u\n", fs32_to_cpu(sb, usb3->fs_nrpos)); | 230 | pr_debug(" nrpos: %u\n", fs32_to_cpu(sb, usb3->fs_nrpos)); |
| 232 | printk(" ndir %u\n", | 231 | pr_debug(" ndir %u\n", |
| 233 | fs32_to_cpu(sb, usb1->fs_cstotal.cs_ndir)); | 232 | fs32_to_cpu(sb, usb1->fs_cstotal.cs_ndir)); |
| 234 | printk(" nifree %u\n", | 233 | pr_debug(" nifree %u\n", |
| 235 | fs32_to_cpu(sb, usb1->fs_cstotal.cs_nifree)); | 234 | fs32_to_cpu(sb, usb1->fs_cstotal.cs_nifree)); |
| 236 | printk(" nbfree %u\n", | 235 | pr_debug(" nbfree %u\n", |
| 237 | fs32_to_cpu(sb, usb1->fs_cstotal.cs_nbfree)); | 236 | fs32_to_cpu(sb, usb1->fs_cstotal.cs_nbfree)); |
| 238 | printk(" nffree %u\n", | 237 | pr_debug(" nffree %u\n", |
| 239 | fs32_to_cpu(sb, usb1->fs_cstotal.cs_nffree)); | 238 | fs32_to_cpu(sb, usb1->fs_cstotal.cs_nffree)); |
| 240 | } | 239 | } |
| 241 | printk("\n"); | 240 | pr_debug("\n"); |
| 242 | } | 241 | } |
| 243 | 242 | ||
| 244 | /* | 243 | /* |
| @@ -247,38 +246,38 @@ static void ufs_print_super_stuff(struct super_block *sb, | |||
| 247 | static void ufs_print_cylinder_stuff(struct super_block *sb, | 246 | static void ufs_print_cylinder_stuff(struct super_block *sb, |
| 248 | struct ufs_cylinder_group *cg) | 247 | struct ufs_cylinder_group *cg) |
| 249 | { | 248 | { |
| 250 | printk("\nufs_print_cylinder_stuff\n"); | 249 | pr_debug("\nufs_print_cylinder_stuff\n"); |
| 251 | printk("size of ucg: %zu\n", sizeof(struct ufs_cylinder_group)); | 250 | pr_debug("size of ucg: %zu\n", sizeof(struct ufs_cylinder_group)); |
| 252 | printk(" magic: %x\n", fs32_to_cpu(sb, cg->cg_magic)); | 251 | pr_debug(" magic: %x\n", fs32_to_cpu(sb, cg->cg_magic)); |
| 253 | printk(" time: %u\n", fs32_to_cpu(sb, cg->cg_time)); | 252 | pr_debug(" time: %u\n", fs32_to_cpu(sb, cg->cg_time)); |
| 254 | printk(" cgx: %u\n", fs32_to_cpu(sb, cg->cg_cgx)); | 253 | pr_debug(" cgx: %u\n", fs32_to_cpu(sb, cg->cg_cgx)); |
| 255 | printk(" ncyl: %u\n", fs16_to_cpu(sb, cg->cg_ncyl)); | 254 | pr_debug(" ncyl: %u\n", fs16_to_cpu(sb, cg->cg_ncyl)); |
| 256 | printk(" niblk: %u\n", fs16_to_cpu(sb, cg->cg_niblk)); | 255 | pr_debug(" niblk: %u\n", fs16_to_cpu(sb, cg->cg_niblk)); |
| 257 | printk(" ndblk: %u\n", fs32_to_cpu(sb, cg->cg_ndblk)); | 256 | pr_debug(" ndblk: %u\n", fs32_to_cpu(sb, cg->cg_ndblk)); |
| 258 | printk(" cs_ndir: %u\n", fs32_to_cpu(sb, cg->cg_cs.cs_ndir)); | 257 | pr_debug(" cs_ndir: %u\n", fs32_to_cpu(sb, cg->cg_cs.cs_ndir)); |
| 259 | printk(" cs_nbfree: %u\n", fs32_to_cpu(sb, cg->cg_cs.cs_nbfree)); | 258 | pr_debug(" cs_nbfree: %u\n", fs32_to_cpu(sb, cg->cg_cs.cs_nbfree)); |
| 260 | printk(" cs_nifree: %u\n", fs32_to_cpu(sb, cg->cg_cs.cs_nifree)); | 259 | pr_debug(" cs_nifree: %u\n", fs32_to_cpu(sb, cg->cg_cs.cs_nifree)); |
| 261 | printk(" cs_nffree: %u\n", fs32_to_cpu(sb, cg->cg_cs.cs_nffree)); | 260 | pr_debug(" cs_nffree: %u\n", fs32_to_cpu(sb, cg->cg_cs.cs_nffree)); |
| 262 | printk(" rotor: %u\n", fs32_to_cpu(sb, cg->cg_rotor)); | 261 | pr_debug(" rotor: %u\n", fs32_to_cpu(sb, cg->cg_rotor)); |
| 263 | printk(" frotor: %u\n", fs32_to_cpu(sb, cg->cg_frotor)); | 262 | pr_debug(" frotor: %u\n", fs32_to_cpu(sb, cg->cg_frotor)); |
| 264 | printk(" irotor: %u\n", fs32_to_cpu(sb, cg->cg_irotor)); | 263 | pr_debug(" irotor: %u\n", fs32_to_cpu(sb, cg->cg_irotor)); |
| 265 | printk(" frsum: %u, %u, %u, %u, %u, %u, %u, %u\n", | 264 | pr_debug(" frsum: %u, %u, %u, %u, %u, %u, %u, %u\n", |
| 266 | fs32_to_cpu(sb, cg->cg_frsum[0]), fs32_to_cpu(sb, cg->cg_frsum[1]), | 265 | fs32_to_cpu(sb, cg->cg_frsum[0]), fs32_to_cpu(sb, cg->cg_frsum[1]), |
| 267 | fs32_to_cpu(sb, cg->cg_frsum[2]), fs32_to_cpu(sb, cg->cg_frsum[3]), | 266 | fs32_to_cpu(sb, cg->cg_frsum[2]), fs32_to_cpu(sb, cg->cg_frsum[3]), |
| 268 | fs32_to_cpu(sb, cg->cg_frsum[4]), fs32_to_cpu(sb, cg->cg_frsum[5]), | 267 | fs32_to_cpu(sb, cg->cg_frsum[4]), fs32_to_cpu(sb, cg->cg_frsum[5]), |
| 269 | fs32_to_cpu(sb, cg->cg_frsum[6]), fs32_to_cpu(sb, cg->cg_frsum[7])); | 268 | fs32_to_cpu(sb, cg->cg_frsum[6]), fs32_to_cpu(sb, cg->cg_frsum[7])); |
| 270 | printk(" btotoff: %u\n", fs32_to_cpu(sb, cg->cg_btotoff)); | 269 | pr_debug(" btotoff: %u\n", fs32_to_cpu(sb, cg->cg_btotoff)); |
| 271 | printk(" boff: %u\n", fs32_to_cpu(sb, cg->cg_boff)); | 270 | pr_debug(" boff: %u\n", fs32_to_cpu(sb, cg->cg_boff)); |
| 272 | printk(" iuseoff: %u\n", fs32_to_cpu(sb, cg->cg_iusedoff)); | 271 | pr_debug(" iuseoff: %u\n", fs32_to_cpu(sb, cg->cg_iusedoff)); |
| 273 | printk(" freeoff: %u\n", fs32_to_cpu(sb, cg->cg_freeoff)); | 272 | pr_debug(" freeoff: %u\n", fs32_to_cpu(sb, cg->cg_freeoff)); |
| 274 | printk(" nextfreeoff: %u\n", fs32_to_cpu(sb, cg->cg_nextfreeoff)); | 273 | pr_debug(" nextfreeoff: %u\n", fs32_to_cpu(sb, cg->cg_nextfreeoff)); |
| 275 | printk(" clustersumoff %u\n", | 274 | pr_debug(" clustersumoff %u\n", |
| 276 | fs32_to_cpu(sb, cg->cg_u.cg_44.cg_clustersumoff)); | 275 | fs32_to_cpu(sb, cg->cg_u.cg_44.cg_clustersumoff)); |
| 277 | printk(" clusteroff %u\n", | 276 | pr_debug(" clusteroff %u\n", |
| 278 | fs32_to_cpu(sb, cg->cg_u.cg_44.cg_clusteroff)); | 277 | fs32_to_cpu(sb, cg->cg_u.cg_44.cg_clusteroff)); |
| 279 | printk(" nclusterblks %u\n", | 278 | pr_debug(" nclusterblks %u\n", |
| 280 | fs32_to_cpu(sb, cg->cg_u.cg_44.cg_nclusterblks)); | 279 | fs32_to_cpu(sb, cg->cg_u.cg_44.cg_nclusterblks)); |
| 281 | printk("\n"); | 280 | pr_debug("\n"); |
| 282 | } | 281 | } |
| 283 | #else | 282 | #else |
| 284 | # define ufs_print_super_stuff(sb, usb1, usb2, usb3) /**/ | 283 | # define ufs_print_super_stuff(sb, usb1, usb2, usb3) /**/ |
| @@ -287,13 +286,12 @@ static void ufs_print_cylinder_stuff(struct super_block *sb, | |||
| 287 | 286 | ||
| 288 | static const struct super_operations ufs_super_ops; | 287 | static const struct super_operations ufs_super_ops; |
| 289 | 288 | ||
| 290 | static char error_buf[1024]; | ||
| 291 | |||
| 292 | void ufs_error (struct super_block * sb, const char * function, | 289 | void ufs_error (struct super_block * sb, const char * function, |
| 293 | const char * fmt, ...) | 290 | const char * fmt, ...) |
| 294 | { | 291 | { |
| 295 | struct ufs_sb_private_info * uspi; | 292 | struct ufs_sb_private_info * uspi; |
| 296 | struct ufs_super_block_first * usb1; | 293 | struct ufs_super_block_first * usb1; |
| 294 | struct va_format vaf; | ||
| 297 | va_list args; | 295 | va_list args; |
| 298 | 296 | ||
| 299 | uspi = UFS_SB(sb)->s_uspi; | 297 | uspi = UFS_SB(sb)->s_uspi; |
| @@ -305,20 +303,21 @@ void ufs_error (struct super_block * sb, const char * function, | |||
| 305 | ufs_mark_sb_dirty(sb); | 303 | ufs_mark_sb_dirty(sb); |
| 306 | sb->s_flags |= MS_RDONLY; | 304 | sb->s_flags |= MS_RDONLY; |
| 307 | } | 305 | } |
| 308 | va_start (args, fmt); | 306 | va_start(args, fmt); |
| 309 | vsnprintf (error_buf, sizeof(error_buf), fmt, args); | 307 | vaf.fmt = fmt; |
| 310 | va_end (args); | 308 | vaf.va = &args; |
| 311 | switch (UFS_SB(sb)->s_mount_opt & UFS_MOUNT_ONERROR) { | 309 | switch (UFS_SB(sb)->s_mount_opt & UFS_MOUNT_ONERROR) { |
| 312 | case UFS_MOUNT_ONERROR_PANIC: | 310 | case UFS_MOUNT_ONERROR_PANIC: |
| 313 | panic ("UFS-fs panic (device %s): %s: %s\n", | 311 | panic("panic (device %s): %s: %pV\n", |
| 314 | sb->s_id, function, error_buf); | 312 | sb->s_id, function, &vaf); |
| 315 | 313 | ||
| 316 | case UFS_MOUNT_ONERROR_LOCK: | 314 | case UFS_MOUNT_ONERROR_LOCK: |
| 317 | case UFS_MOUNT_ONERROR_UMOUNT: | 315 | case UFS_MOUNT_ONERROR_UMOUNT: |
| 318 | case UFS_MOUNT_ONERROR_REPAIR: | 316 | case UFS_MOUNT_ONERROR_REPAIR: |
| 319 | printk (KERN_CRIT "UFS-fs error (device %s): %s: %s\n", | 317 | pr_crit("error (device %s): %s: %pV\n", |
| 320 | sb->s_id, function, error_buf); | 318 | sb->s_id, function, &vaf); |
| 321 | } | 319 | } |
| 320 | va_end(args); | ||
| 322 | } | 321 | } |
| 323 | 322 | ||
| 324 | void ufs_panic (struct super_block * sb, const char * function, | 323 | void ufs_panic (struct super_block * sb, const char * function, |
| @@ -326,6 +325,7 @@ void ufs_panic (struct super_block * sb, const char * function, | |||
| 326 | { | 325 | { |
| 327 | struct ufs_sb_private_info * uspi; | 326 | struct ufs_sb_private_info * uspi; |
| 328 | struct ufs_super_block_first * usb1; | 327 | struct ufs_super_block_first * usb1; |
| 328 | struct va_format vaf; | ||
| 329 | va_list args; | 329 | va_list args; |
| 330 | 330 | ||
| 331 | uspi = UFS_SB(sb)->s_uspi; | 331 | uspi = UFS_SB(sb)->s_uspi; |
| @@ -336,24 +336,27 @@ void ufs_panic (struct super_block * sb, const char * function, | |||
| 336 | ubh_mark_buffer_dirty(USPI_UBH(uspi)); | 336 | ubh_mark_buffer_dirty(USPI_UBH(uspi)); |
| 337 | ufs_mark_sb_dirty(sb); | 337 | ufs_mark_sb_dirty(sb); |
| 338 | } | 338 | } |
| 339 | va_start (args, fmt); | 339 | va_start(args, fmt); |
| 340 | vsnprintf (error_buf, sizeof(error_buf), fmt, args); | 340 | vaf.fmt = fmt; |
| 341 | va_end (args); | 341 | vaf.va = &args; |
| 342 | sb->s_flags |= MS_RDONLY; | 342 | sb->s_flags |= MS_RDONLY; |
| 343 | printk (KERN_CRIT "UFS-fs panic (device %s): %s: %s\n", | 343 | pr_crit("panic (device %s): %s: %pV\n", |
| 344 | sb->s_id, function, error_buf); | 344 | sb->s_id, function, &vaf); |
| 345 | va_end(args); | ||
| 345 | } | 346 | } |
| 346 | 347 | ||
| 347 | void ufs_warning (struct super_block * sb, const char * function, | 348 | void ufs_warning (struct super_block * sb, const char * function, |
| 348 | const char * fmt, ...) | 349 | const char * fmt, ...) |
| 349 | { | 350 | { |
| 351 | struct va_format vaf; | ||
| 350 | va_list args; | 352 | va_list args; |
| 351 | 353 | ||
| 352 | va_start (args, fmt); | 354 | va_start(args, fmt); |
| 353 | vsnprintf (error_buf, sizeof(error_buf), fmt, args); | 355 | vaf.fmt = fmt; |
| 354 | va_end (args); | 356 | vaf.va = &args; |
| 355 | printk (KERN_WARNING "UFS-fs warning (device %s): %s: %s\n", | 357 | pr_warn("(device %s): %s: %pV\n", |
| 356 | sb->s_id, function, error_buf); | 358 | sb->s_id, function, &vaf); |
| 359 | va_end(args); | ||
| 357 | } | 360 | } |
| 358 | 361 | ||
| 359 | enum { | 362 | enum { |
| @@ -464,14 +467,12 @@ static int ufs_parse_options (char * options, unsigned * mount_options) | |||
| 464 | ufs_set_opt (*mount_options, ONERROR_UMOUNT); | 467 | ufs_set_opt (*mount_options, ONERROR_UMOUNT); |
| 465 | break; | 468 | break; |
| 466 | case Opt_onerror_repair: | 469 | case Opt_onerror_repair: |
| 467 | printk("UFS-fs: Unable to do repair on error, " | 470 | pr_err("Unable to do repair on error, will lock lock instead\n"); |
| 468 | "will lock lock instead\n"); | ||
| 469 | ufs_clear_opt (*mount_options, ONERROR); | 471 | ufs_clear_opt (*mount_options, ONERROR); |
| 470 | ufs_set_opt (*mount_options, ONERROR_REPAIR); | 472 | ufs_set_opt (*mount_options, ONERROR_REPAIR); |
| 471 | break; | 473 | break; |
| 472 | default: | 474 | default: |
| 473 | printk("UFS-fs: Invalid option: \"%s\" " | 475 | pr_err("Invalid option: \"%s\" or missing value\n", p); |
| 474 | "or missing value\n", p); | ||
| 475 | return 0; | 476 | return 0; |
| 476 | } | 477 | } |
| 477 | } | 478 | } |
| @@ -788,8 +789,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 788 | 789 | ||
| 789 | #ifndef CONFIG_UFS_FS_WRITE | 790 | #ifndef CONFIG_UFS_FS_WRITE |
| 790 | if (!(sb->s_flags & MS_RDONLY)) { | 791 | if (!(sb->s_flags & MS_RDONLY)) { |
| 791 | printk("ufs was compiled with read-only support, " | 792 | pr_err("ufs was compiled with read-only support, can't be mounted as read-write\n"); |
| 792 | "can't be mounted as read-write\n"); | ||
| 793 | return -EROFS; | 793 | return -EROFS; |
| 794 | } | 794 | } |
| 795 | #endif | 795 | #endif |
| @@ -812,12 +812,12 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 812 | sbi->s_mount_opt = 0; | 812 | sbi->s_mount_opt = 0; |
| 813 | ufs_set_opt (sbi->s_mount_opt, ONERROR_LOCK); | 813 | ufs_set_opt (sbi->s_mount_opt, ONERROR_LOCK); |
| 814 | if (!ufs_parse_options ((char *) data, &sbi->s_mount_opt)) { | 814 | if (!ufs_parse_options ((char *) data, &sbi->s_mount_opt)) { |
| 815 | printk("wrong mount options\n"); | 815 | pr_err("wrong mount options\n"); |
| 816 | goto failed; | 816 | goto failed; |
| 817 | } | 817 | } |
| 818 | if (!(sbi->s_mount_opt & UFS_MOUNT_UFSTYPE)) { | 818 | if (!(sbi->s_mount_opt & UFS_MOUNT_UFSTYPE)) { |
| 819 | if (!silent) | 819 | if (!silent) |
| 820 | printk("You didn't specify the type of your ufs filesystem\n\n" | 820 | pr_err("You didn't specify the type of your ufs filesystem\n\n" |
| 821 | "mount -t ufs -o ufstype=" | 821 | "mount -t ufs -o ufstype=" |
| 822 | "sun|sunx86|44bsd|ufs2|5xbsd|old|hp|nextstep|nextstep-cd|openstep ...\n\n" | 822 | "sun|sunx86|44bsd|ufs2|5xbsd|old|hp|nextstep|nextstep-cd|openstep ...\n\n" |
| 823 | ">>>WARNING<<< Wrong ufstype may corrupt your filesystem, " | 823 | ">>>WARNING<<< Wrong ufstype may corrupt your filesystem, " |
| @@ -868,7 +868,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 868 | break; | 868 | break; |
| 869 | 869 | ||
| 870 | case UFS_MOUNT_UFSTYPE_SUNOS: | 870 | case UFS_MOUNT_UFSTYPE_SUNOS: |
| 871 | UFSD(("ufstype=sunos\n")) | 871 | UFSD("ufstype=sunos\n"); |
| 872 | uspi->s_fsize = block_size = 1024; | 872 | uspi->s_fsize = block_size = 1024; |
| 873 | uspi->s_fmask = ~(1024 - 1); | 873 | uspi->s_fmask = ~(1024 - 1); |
| 874 | uspi->s_fshift = 10; | 874 | uspi->s_fshift = 10; |
| @@ -900,7 +900,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 900 | flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD; | 900 | flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD; |
| 901 | if (!(sb->s_flags & MS_RDONLY)) { | 901 | if (!(sb->s_flags & MS_RDONLY)) { |
| 902 | if (!silent) | 902 | if (!silent) |
| 903 | printk(KERN_INFO "ufstype=old is supported read-only\n"); | 903 | pr_info("ufstype=old is supported read-only\n"); |
| 904 | sb->s_flags |= MS_RDONLY; | 904 | sb->s_flags |= MS_RDONLY; |
| 905 | } | 905 | } |
| 906 | break; | 906 | break; |
| @@ -916,7 +916,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 916 | flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD; | 916 | flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD; |
| 917 | if (!(sb->s_flags & MS_RDONLY)) { | 917 | if (!(sb->s_flags & MS_RDONLY)) { |
| 918 | if (!silent) | 918 | if (!silent) |
| 919 | printk(KERN_INFO "ufstype=nextstep is supported read-only\n"); | 919 | pr_info("ufstype=nextstep is supported read-only\n"); |
| 920 | sb->s_flags |= MS_RDONLY; | 920 | sb->s_flags |= MS_RDONLY; |
| 921 | } | 921 | } |
| 922 | break; | 922 | break; |
| @@ -932,7 +932,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 932 | flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD; | 932 | flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD; |
| 933 | if (!(sb->s_flags & MS_RDONLY)) { | 933 | if (!(sb->s_flags & MS_RDONLY)) { |
| 934 | if (!silent) | 934 | if (!silent) |
| 935 | printk(KERN_INFO "ufstype=nextstep-cd is supported read-only\n"); | 935 | pr_info("ufstype=nextstep-cd is supported read-only\n"); |
| 936 | sb->s_flags |= MS_RDONLY; | 936 | sb->s_flags |= MS_RDONLY; |
| 937 | } | 937 | } |
| 938 | break; | 938 | break; |
| @@ -948,7 +948,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 948 | flags |= UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD; | 948 | flags |= UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD; |
| 949 | if (!(sb->s_flags & MS_RDONLY)) { | 949 | if (!(sb->s_flags & MS_RDONLY)) { |
| 950 | if (!silent) | 950 | if (!silent) |
| 951 | printk(KERN_INFO "ufstype=openstep is supported read-only\n"); | 951 | pr_info("ufstype=openstep is supported read-only\n"); |
| 952 | sb->s_flags |= MS_RDONLY; | 952 | sb->s_flags |= MS_RDONLY; |
| 953 | } | 953 | } |
| 954 | break; | 954 | break; |
| @@ -963,19 +963,19 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 963 | flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD; | 963 | flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD; |
| 964 | if (!(sb->s_flags & MS_RDONLY)) { | 964 | if (!(sb->s_flags & MS_RDONLY)) { |
| 965 | if (!silent) | 965 | if (!silent) |
| 966 | printk(KERN_INFO "ufstype=hp is supported read-only\n"); | 966 | pr_info("ufstype=hp is supported read-only\n"); |
| 967 | sb->s_flags |= MS_RDONLY; | 967 | sb->s_flags |= MS_RDONLY; |
| 968 | } | 968 | } |
| 969 | break; | 969 | break; |
| 970 | default: | 970 | default: |
| 971 | if (!silent) | 971 | if (!silent) |
| 972 | printk("unknown ufstype\n"); | 972 | pr_err("unknown ufstype\n"); |
| 973 | goto failed; | 973 | goto failed; |
| 974 | } | 974 | } |
| 975 | 975 | ||
| 976 | again: | 976 | again: |
| 977 | if (!sb_set_blocksize(sb, block_size)) { | 977 | if (!sb_set_blocksize(sb, block_size)) { |
| 978 | printk(KERN_ERR "UFS: failed to set blocksize\n"); | 978 | pr_err("failed to set blocksize\n"); |
| 979 | goto failed; | 979 | goto failed; |
| 980 | } | 980 | } |
| 981 | 981 | ||
| @@ -1034,7 +1034,7 @@ again: | |||
| 1034 | goto again; | 1034 | goto again; |
| 1035 | } | 1035 | } |
| 1036 | if (!silent) | 1036 | if (!silent) |
| 1037 | printk("ufs_read_super: bad magic number\n"); | 1037 | pr_err("%s(): bad magic number\n", __func__); |
| 1038 | goto failed; | 1038 | goto failed; |
| 1039 | 1039 | ||
| 1040 | magic_found: | 1040 | magic_found: |
| @@ -1048,33 +1048,33 @@ magic_found: | |||
| 1048 | uspi->s_fshift = fs32_to_cpu(sb, usb1->fs_fshift); | 1048 | uspi->s_fshift = fs32_to_cpu(sb, usb1->fs_fshift); |
| 1049 | 1049 | ||
| 1050 | if (!is_power_of_2(uspi->s_fsize)) { | 1050 | if (!is_power_of_2(uspi->s_fsize)) { |
| 1051 | printk(KERN_ERR "ufs_read_super: fragment size %u is not a power of 2\n", | 1051 | pr_err("%s(): fragment size %u is not a power of 2\n", |
| 1052 | uspi->s_fsize); | 1052 | __func__, uspi->s_fsize); |
| 1053 | goto failed; | 1053 | goto failed; |
| 1054 | } | 1054 | } |
| 1055 | if (uspi->s_fsize < 512) { | 1055 | if (uspi->s_fsize < 512) { |
| 1056 | printk(KERN_ERR "ufs_read_super: fragment size %u is too small\n", | 1056 | pr_err("%s(): fragment size %u is too small\n", |
| 1057 | uspi->s_fsize); | 1057 | __func__, uspi->s_fsize); |
| 1058 | goto failed; | 1058 | goto failed; |
| 1059 | } | 1059 | } |
| 1060 | if (uspi->s_fsize > 4096) { | 1060 | if (uspi->s_fsize > 4096) { |
| 1061 | printk(KERN_ERR "ufs_read_super: fragment size %u is too large\n", | 1061 | pr_err("%s(): fragment size %u is too large\n", |
| 1062 | uspi->s_fsize); | 1062 | __func__, uspi->s_fsize); |
| 1063 | goto failed; | 1063 | goto failed; |
| 1064 | } | 1064 | } |
| 1065 | if (!is_power_of_2(uspi->s_bsize)) { | 1065 | if (!is_power_of_2(uspi->s_bsize)) { |
| 1066 | printk(KERN_ERR "ufs_read_super: block size %u is not a power of 2\n", | 1066 | pr_err("%s(): block size %u is not a power of 2\n", |
| 1067 | uspi->s_bsize); | 1067 | __func__, uspi->s_bsize); |
| 1068 | goto failed; | 1068 | goto failed; |
| 1069 | } | 1069 | } |
| 1070 | if (uspi->s_bsize < 4096) { | 1070 | if (uspi->s_bsize < 4096) { |
| 1071 | printk(KERN_ERR "ufs_read_super: block size %u is too small\n", | 1071 | pr_err("%s(): block size %u is too small\n", |
| 1072 | uspi->s_bsize); | 1072 | __func__, uspi->s_bsize); |
| 1073 | goto failed; | 1073 | goto failed; |
| 1074 | } | 1074 | } |
| 1075 | if (uspi->s_bsize / uspi->s_fsize > 8) { | 1075 | if (uspi->s_bsize / uspi->s_fsize > 8) { |
| 1076 | printk(KERN_ERR "ufs_read_super: too many fragments per block (%u)\n", | 1076 | pr_err("%s(): too many fragments per block (%u)\n", |
| 1077 | uspi->s_bsize / uspi->s_fsize); | 1077 | __func__, uspi->s_bsize / uspi->s_fsize); |
| 1078 | goto failed; | 1078 | goto failed; |
| 1079 | } | 1079 | } |
| 1080 | if (uspi->s_fsize != block_size || uspi->s_sbsize != super_block_size) { | 1080 | if (uspi->s_fsize != block_size || uspi->s_sbsize != super_block_size) { |
| @@ -1113,20 +1113,21 @@ magic_found: | |||
| 1113 | UFSD("fs is DEC OSF/1\n"); | 1113 | UFSD("fs is DEC OSF/1\n"); |
| 1114 | break; | 1114 | break; |
| 1115 | case UFS_FSACTIVE: | 1115 | case UFS_FSACTIVE: |
| 1116 | printk("ufs_read_super: fs is active\n"); | 1116 | pr_err("%s(): fs is active\n", __func__); |
| 1117 | sb->s_flags |= MS_RDONLY; | 1117 | sb->s_flags |= MS_RDONLY; |
| 1118 | break; | 1118 | break; |
| 1119 | case UFS_FSBAD: | 1119 | case UFS_FSBAD: |
| 1120 | printk("ufs_read_super: fs is bad\n"); | 1120 | pr_err("%s(): fs is bad\n", __func__); |
| 1121 | sb->s_flags |= MS_RDONLY; | 1121 | sb->s_flags |= MS_RDONLY; |
| 1122 | break; | 1122 | break; |
| 1123 | default: | 1123 | default: |
| 1124 | printk("ufs_read_super: can't grok fs_clean 0x%x\n", usb1->fs_clean); | 1124 | pr_err("%s(): can't grok fs_clean 0x%x\n", |
| 1125 | __func__, usb1->fs_clean); | ||
| 1125 | sb->s_flags |= MS_RDONLY; | 1126 | sb->s_flags |= MS_RDONLY; |
| 1126 | break; | 1127 | break; |
| 1127 | } | 1128 | } |
| 1128 | } else { | 1129 | } else { |
| 1129 | printk("ufs_read_super: fs needs fsck\n"); | 1130 | pr_err("%s(): fs needs fsck\n", __func__); |
| 1130 | sb->s_flags |= MS_RDONLY; | 1131 | sb->s_flags |= MS_RDONLY; |
| 1131 | } | 1132 | } |
| 1132 | 1133 | ||
| @@ -1299,7 +1300,7 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data) | |||
| 1299 | if (!(new_mount_opt & UFS_MOUNT_UFSTYPE)) { | 1300 | if (!(new_mount_opt & UFS_MOUNT_UFSTYPE)) { |
| 1300 | new_mount_opt |= ufstype; | 1301 | new_mount_opt |= ufstype; |
| 1301 | } else if ((new_mount_opt & UFS_MOUNT_UFSTYPE) != ufstype) { | 1302 | } else if ((new_mount_opt & UFS_MOUNT_UFSTYPE) != ufstype) { |
| 1302 | printk("ufstype can't be changed during remount\n"); | 1303 | pr_err("ufstype can't be changed during remount\n"); |
| 1303 | unlock_ufs(sb); | 1304 | unlock_ufs(sb); |
| 1304 | return -EINVAL; | 1305 | return -EINVAL; |
| 1305 | } | 1306 | } |
| @@ -1328,8 +1329,7 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data) | |||
| 1328 | * fs was mounted as ro, remounting rw | 1329 | * fs was mounted as ro, remounting rw |
| 1329 | */ | 1330 | */ |
| 1330 | #ifndef CONFIG_UFS_FS_WRITE | 1331 | #ifndef CONFIG_UFS_FS_WRITE |
| 1331 | printk("ufs was compiled with read-only support, " | 1332 | pr_err("ufs was compiled with read-only support, can't be mounted as read-write\n"); |
| 1332 | "can't be mounted as read-write\n"); | ||
| 1333 | unlock_ufs(sb); | 1333 | unlock_ufs(sb); |
| 1334 | return -EINVAL; | 1334 | return -EINVAL; |
| 1335 | #else | 1335 | #else |
| @@ -1338,12 +1338,12 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data) | |||
| 1338 | ufstype != UFS_MOUNT_UFSTYPE_44BSD && | 1338 | ufstype != UFS_MOUNT_UFSTYPE_44BSD && |
| 1339 | ufstype != UFS_MOUNT_UFSTYPE_SUNx86 && | 1339 | ufstype != UFS_MOUNT_UFSTYPE_SUNx86 && |
| 1340 | ufstype != UFS_MOUNT_UFSTYPE_UFS2) { | 1340 | ufstype != UFS_MOUNT_UFSTYPE_UFS2) { |
| 1341 | printk("this ufstype is read-only supported\n"); | 1341 | pr_err("this ufstype is read-only supported\n"); |
| 1342 | unlock_ufs(sb); | 1342 | unlock_ufs(sb); |
| 1343 | return -EINVAL; | 1343 | return -EINVAL; |
| 1344 | } | 1344 | } |
| 1345 | if (!ufs_read_cylinder_structures(sb)) { | 1345 | if (!ufs_read_cylinder_structures(sb)) { |
| 1346 | printk("failed during remounting\n"); | 1346 | pr_err("failed during remounting\n"); |
| 1347 | unlock_ufs(sb); | 1347 | unlock_ufs(sb); |
| 1348 | return -EPERM; | 1348 | return -EPERM; |
| 1349 | } | 1349 | } |
diff --git a/fs/ufs/ufs.h b/fs/ufs/ufs.h index 343e6fc571e5..2a07396d5f9e 100644 --- a/fs/ufs/ufs.h +++ b/fs/ufs/ufs.h | |||
| @@ -1,6 +1,12 @@ | |||
| 1 | #ifndef _UFS_UFS_H | 1 | #ifndef _UFS_UFS_H |
| 2 | #define _UFS_UFS_H 1 | 2 | #define _UFS_UFS_H 1 |
| 3 | 3 | ||
| 4 | #ifdef pr_fmt | ||
| 5 | #undef pr_fmt | ||
| 6 | #endif | ||
| 7 | |||
| 8 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 9 | |||
| 4 | #define UFS_MAX_GROUP_LOADED 8 | 10 | #define UFS_MAX_GROUP_LOADED 8 |
| 5 | #define UFS_CGNO_EMPTY ((unsigned)-1) | 11 | #define UFS_CGNO_EMPTY ((unsigned)-1) |
| 6 | 12 | ||
| @@ -71,9 +77,9 @@ struct ufs_inode_info { | |||
| 71 | */ | 77 | */ |
| 72 | #ifdef CONFIG_UFS_DEBUG | 78 | #ifdef CONFIG_UFS_DEBUG |
| 73 | # define UFSD(f, a...) { \ | 79 | # define UFSD(f, a...) { \ |
| 74 | printk ("UFSD (%s, %d): %s:", \ | 80 | pr_debug("UFSD (%s, %d): %s:", \ |
| 75 | __FILE__, __LINE__, __func__); \ | 81 | __FILE__, __LINE__, __func__); \ |
| 76 | printk (f, ## a); \ | 82 | pr_debug(f, ## a); \ |
| 77 | } | 83 | } |
| 78 | #else | 84 | #else |
| 79 | # define UFSD(f, a...) /**/ | 85 | # define UFSD(f, a...) /**/ |
diff --git a/include/asm-generic/pci-dma-compat.h b/include/asm-generic/pci-dma-compat.h index 1437b7da09b2..c110843fc53b 100644 --- a/include/asm-generic/pci-dma-compat.h +++ b/include/asm-generic/pci-dma-compat.h | |||
| @@ -19,6 +19,14 @@ pci_alloc_consistent(struct pci_dev *hwdev, size_t size, | |||
| 19 | return dma_alloc_coherent(hwdev == NULL ? NULL : &hwdev->dev, size, dma_handle, GFP_ATOMIC); | 19 | return dma_alloc_coherent(hwdev == NULL ? NULL : &hwdev->dev, size, dma_handle, GFP_ATOMIC); |
| 20 | } | 20 | } |
| 21 | 21 | ||
| 22 | static inline void * | ||
| 23 | pci_zalloc_consistent(struct pci_dev *hwdev, size_t size, | ||
| 24 | dma_addr_t *dma_handle) | ||
| 25 | { | ||
| 26 | return dma_zalloc_coherent(hwdev == NULL ? NULL : &hwdev->dev, | ||
| 27 | size, dma_handle, GFP_ATOMIC); | ||
| 28 | } | ||
| 29 | |||
| 22 | static inline void | 30 | static inline void |
| 23 | pci_free_consistent(struct pci_dev *hwdev, size_t size, | 31 | pci_free_consistent(struct pci_dev *hwdev, size_t size, |
| 24 | void *vaddr, dma_addr_t dma_handle) | 32 | void *vaddr, dma_addr_t dma_handle) |
diff --git a/include/linux/decompress/bunzip2.h b/include/linux/decompress/bunzip2.h index 115272137a9c..4d683df898e6 100644 --- a/include/linux/decompress/bunzip2.h +++ b/include/linux/decompress/bunzip2.h | |||
| @@ -1,10 +1,10 @@ | |||
| 1 | #ifndef DECOMPRESS_BUNZIP2_H | 1 | #ifndef DECOMPRESS_BUNZIP2_H |
| 2 | #define DECOMPRESS_BUNZIP2_H | 2 | #define DECOMPRESS_BUNZIP2_H |
| 3 | 3 | ||
| 4 | int bunzip2(unsigned char *inbuf, int len, | 4 | int bunzip2(unsigned char *inbuf, long len, |
| 5 | int(*fill)(void*, unsigned int), | 5 | long (*fill)(void*, unsigned long), |
| 6 | int(*flush)(void*, unsigned int), | 6 | long (*flush)(void*, unsigned long), |
| 7 | unsigned char *output, | 7 | unsigned char *output, |
| 8 | int *pos, | 8 | long *pos, |
| 9 | void(*error)(char *x)); | 9 | void(*error)(char *x)); |
| 10 | #endif | 10 | #endif |
diff --git a/include/linux/decompress/generic.h b/include/linux/decompress/generic.h index 0c7111a55a1a..1fcfd64b5076 100644 --- a/include/linux/decompress/generic.h +++ b/include/linux/decompress/generic.h | |||
| @@ -1,11 +1,11 @@ | |||
| 1 | #ifndef DECOMPRESS_GENERIC_H | 1 | #ifndef DECOMPRESS_GENERIC_H |
| 2 | #define DECOMPRESS_GENERIC_H | 2 | #define DECOMPRESS_GENERIC_H |
| 3 | 3 | ||
| 4 | typedef int (*decompress_fn) (unsigned char *inbuf, int len, | 4 | typedef int (*decompress_fn) (unsigned char *inbuf, long len, |
| 5 | int(*fill)(void*, unsigned int), | 5 | long (*fill)(void*, unsigned long), |
| 6 | int(*flush)(void*, unsigned int), | 6 | long (*flush)(void*, unsigned long), |
| 7 | unsigned char *outbuf, | 7 | unsigned char *outbuf, |
| 8 | int *posp, | 8 | long *posp, |
| 9 | void(*error)(char *x)); | 9 | void(*error)(char *x)); |
| 10 | 10 | ||
| 11 | /* inbuf - input buffer | 11 | /* inbuf - input buffer |
| @@ -33,7 +33,7 @@ typedef int (*decompress_fn) (unsigned char *inbuf, int len, | |||
| 33 | 33 | ||
| 34 | 34 | ||
| 35 | /* Utility routine to detect the decompression method */ | 35 | /* Utility routine to detect the decompression method */ |
| 36 | decompress_fn decompress_method(const unsigned char *inbuf, int len, | 36 | decompress_fn decompress_method(const unsigned char *inbuf, long len, |
| 37 | const char **name); | 37 | const char **name); |
| 38 | 38 | ||
| 39 | #endif | 39 | #endif |
diff --git a/include/linux/decompress/inflate.h b/include/linux/decompress/inflate.h index 1d0aedef9822..e4f411fdbd24 100644 --- a/include/linux/decompress/inflate.h +++ b/include/linux/decompress/inflate.h | |||
| @@ -1,10 +1,10 @@ | |||
| 1 | #ifndef LINUX_DECOMPRESS_INFLATE_H | 1 | #ifndef LINUX_DECOMPRESS_INFLATE_H |
| 2 | #define LINUX_DECOMPRESS_INFLATE_H | 2 | #define LINUX_DECOMPRESS_INFLATE_H |
| 3 | 3 | ||
| 4 | int gunzip(unsigned char *inbuf, int len, | 4 | int gunzip(unsigned char *inbuf, long len, |
| 5 | int(*fill)(void*, unsigned int), | 5 | long (*fill)(void*, unsigned long), |
| 6 | int(*flush)(void*, unsigned int), | 6 | long (*flush)(void*, unsigned long), |
| 7 | unsigned char *output, | 7 | unsigned char *output, |
| 8 | int *pos, | 8 | long *pos, |
| 9 | void(*error_fn)(char *x)); | 9 | void(*error_fn)(char *x)); |
| 10 | #endif | 10 | #endif |
diff --git a/include/linux/decompress/unlz4.h b/include/linux/decompress/unlz4.h index d5b68bf3ec92..3273c2f36496 100644 --- a/include/linux/decompress/unlz4.h +++ b/include/linux/decompress/unlz4.h | |||
| @@ -1,10 +1,10 @@ | |||
| 1 | #ifndef DECOMPRESS_UNLZ4_H | 1 | #ifndef DECOMPRESS_UNLZ4_H |
| 2 | #define DECOMPRESS_UNLZ4_H | 2 | #define DECOMPRESS_UNLZ4_H |
| 3 | 3 | ||
| 4 | int unlz4(unsigned char *inbuf, int len, | 4 | int unlz4(unsigned char *inbuf, long len, |
| 5 | int(*fill)(void*, unsigned int), | 5 | long (*fill)(void*, unsigned long), |
| 6 | int(*flush)(void*, unsigned int), | 6 | long (*flush)(void*, unsigned long), |
| 7 | unsigned char *output, | 7 | unsigned char *output, |
| 8 | int *pos, | 8 | long *pos, |
| 9 | void(*error)(char *x)); | 9 | void(*error)(char *x)); |
| 10 | #endif | 10 | #endif |
diff --git a/include/linux/decompress/unlzma.h b/include/linux/decompress/unlzma.h index 7796538f1bf4..8a891a193840 100644 --- a/include/linux/decompress/unlzma.h +++ b/include/linux/decompress/unlzma.h | |||
| @@ -1,11 +1,11 @@ | |||
| 1 | #ifndef DECOMPRESS_UNLZMA_H | 1 | #ifndef DECOMPRESS_UNLZMA_H |
| 2 | #define DECOMPRESS_UNLZMA_H | 2 | #define DECOMPRESS_UNLZMA_H |
| 3 | 3 | ||
| 4 | int unlzma(unsigned char *, int, | 4 | int unlzma(unsigned char *, long, |
| 5 | int(*fill)(void*, unsigned int), | 5 | long (*fill)(void*, unsigned long), |
| 6 | int(*flush)(void*, unsigned int), | 6 | long (*flush)(void*, unsigned long), |
| 7 | unsigned char *output, | 7 | unsigned char *output, |
| 8 | int *posp, | 8 | long *posp, |
| 9 | void(*error)(char *x) | 9 | void(*error)(char *x) |
| 10 | ); | 10 | ); |
| 11 | 11 | ||
diff --git a/include/linux/decompress/unlzo.h b/include/linux/decompress/unlzo.h index 987229752519..af18f95d6570 100644 --- a/include/linux/decompress/unlzo.h +++ b/include/linux/decompress/unlzo.h | |||
| @@ -1,10 +1,10 @@ | |||
| 1 | #ifndef DECOMPRESS_UNLZO_H | 1 | #ifndef DECOMPRESS_UNLZO_H |
| 2 | #define DECOMPRESS_UNLZO_H | 2 | #define DECOMPRESS_UNLZO_H |
| 3 | 3 | ||
| 4 | int unlzo(unsigned char *inbuf, int len, | 4 | int unlzo(unsigned char *inbuf, long len, |
| 5 | int(*fill)(void*, unsigned int), | 5 | long (*fill)(void*, unsigned long), |
| 6 | int(*flush)(void*, unsigned int), | 6 | long (*flush)(void*, unsigned long), |
| 7 | unsigned char *output, | 7 | unsigned char *output, |
| 8 | int *pos, | 8 | long *pos, |
| 9 | void(*error)(char *x)); | 9 | void(*error)(char *x)); |
| 10 | #endif | 10 | #endif |
diff --git a/include/linux/decompress/unxz.h b/include/linux/decompress/unxz.h index 41728fc6c8a1..f764e2a7201e 100644 --- a/include/linux/decompress/unxz.h +++ b/include/linux/decompress/unxz.h | |||
| @@ -10,10 +10,10 @@ | |||
| 10 | #ifndef DECOMPRESS_UNXZ_H | 10 | #ifndef DECOMPRESS_UNXZ_H |
| 11 | #define DECOMPRESS_UNXZ_H | 11 | #define DECOMPRESS_UNXZ_H |
| 12 | 12 | ||
| 13 | int unxz(unsigned char *in, int in_size, | 13 | int unxz(unsigned char *in, long in_size, |
| 14 | int (*fill)(void *dest, unsigned int size), | 14 | long (*fill)(void *dest, unsigned long size), |
| 15 | int (*flush)(void *src, unsigned int size), | 15 | long (*flush)(void *src, unsigned long size), |
| 16 | unsigned char *out, int *in_used, | 16 | unsigned char *out, long *in_used, |
| 17 | void (*error)(char *x)); | 17 | void (*error)(char *x)); |
| 18 | 18 | ||
| 19 | #endif | 19 | #endif |
diff --git a/include/linux/efi.h b/include/linux/efi.h index efc681fd5895..45cb4ffdea62 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h | |||
| @@ -1156,6 +1156,9 @@ int efivars_sysfs_init(void); | |||
| 1156 | #ifdef CONFIG_EFI_RUNTIME_MAP | 1156 | #ifdef CONFIG_EFI_RUNTIME_MAP |
| 1157 | int efi_runtime_map_init(struct kobject *); | 1157 | int efi_runtime_map_init(struct kobject *); |
| 1158 | void efi_runtime_map_setup(void *, int, u32); | 1158 | void efi_runtime_map_setup(void *, int, u32); |
| 1159 | int efi_get_runtime_map_size(void); | ||
| 1160 | int efi_get_runtime_map_desc_size(void); | ||
| 1161 | int efi_runtime_map_copy(void *buf, size_t bufsz); | ||
| 1159 | #else | 1162 | #else |
| 1160 | static inline int efi_runtime_map_init(struct kobject *kobj) | 1163 | static inline int efi_runtime_map_init(struct kobject *kobj) |
| 1161 | { | 1164 | { |
| @@ -1164,6 +1167,22 @@ static inline int efi_runtime_map_init(struct kobject *kobj) | |||
| 1164 | 1167 | ||
| 1165 | static inline void | 1168 | static inline void |
| 1166 | efi_runtime_map_setup(void *map, int nr_entries, u32 desc_size) {} | 1169 | efi_runtime_map_setup(void *map, int nr_entries, u32 desc_size) {} |
| 1170 | |||
| 1171 | static inline int efi_get_runtime_map_size(void) | ||
| 1172 | { | ||
| 1173 | return 0; | ||
| 1174 | } | ||
| 1175 | |||
| 1176 | static inline int efi_get_runtime_map_desc_size(void) | ||
| 1177 | { | ||
| 1178 | return 0; | ||
| 1179 | } | ||
| 1180 | |||
| 1181 | static inline int efi_runtime_map_copy(void *buf, size_t bufsz) | ||
| 1182 | { | ||
| 1183 | return 0; | ||
| 1184 | } | ||
| 1185 | |||
| 1167 | #endif | 1186 | #endif |
| 1168 | 1187 | ||
| 1169 | /* prototypes shared between arch specific and generic stub code */ | 1188 | /* prototypes shared between arch specific and generic stub code */ |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 1ab6c6913040..f0890e4a7c25 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
| @@ -387,7 +387,7 @@ struct address_space { | |||
| 387 | struct inode *host; /* owner: inode, block_device */ | 387 | struct inode *host; /* owner: inode, block_device */ |
| 388 | struct radix_tree_root page_tree; /* radix tree of all pages */ | 388 | struct radix_tree_root page_tree; /* radix tree of all pages */ |
| 389 | spinlock_t tree_lock; /* and lock protecting it */ | 389 | spinlock_t tree_lock; /* and lock protecting it */ |
| 390 | unsigned int i_mmap_writable;/* count VM_SHARED mappings */ | 390 | atomic_t i_mmap_writable;/* count VM_SHARED mappings */ |
| 391 | struct rb_root i_mmap; /* tree of private and shared mappings */ | 391 | struct rb_root i_mmap; /* tree of private and shared mappings */ |
| 392 | struct list_head i_mmap_nonlinear;/*list VM_NONLINEAR mappings */ | 392 | struct list_head i_mmap_nonlinear;/*list VM_NONLINEAR mappings */ |
| 393 | struct mutex i_mmap_mutex; /* protect tree, count, list */ | 393 | struct mutex i_mmap_mutex; /* protect tree, count, list */ |
| @@ -470,10 +470,35 @@ static inline int mapping_mapped(struct address_space *mapping) | |||
| 470 | * Note that i_mmap_writable counts all VM_SHARED vmas: do_mmap_pgoff | 470 | * Note that i_mmap_writable counts all VM_SHARED vmas: do_mmap_pgoff |
| 471 | * marks vma as VM_SHARED if it is shared, and the file was opened for | 471 | * marks vma as VM_SHARED if it is shared, and the file was opened for |
| 472 | * writing i.e. vma may be mprotected writable even if now readonly. | 472 | * writing i.e. vma may be mprotected writable even if now readonly. |
| 473 | * | ||
| 474 | * If i_mmap_writable is negative, no new writable mappings are allowed. You | ||
| 475 | * can only deny writable mappings, if none exists right now. | ||
| 473 | */ | 476 | */ |
| 474 | static inline int mapping_writably_mapped(struct address_space *mapping) | 477 | static inline int mapping_writably_mapped(struct address_space *mapping) |
| 475 | { | 478 | { |
| 476 | return mapping->i_mmap_writable != 0; | 479 | return atomic_read(&mapping->i_mmap_writable) > 0; |
| 480 | } | ||
| 481 | |||
| 482 | static inline int mapping_map_writable(struct address_space *mapping) | ||
| 483 | { | ||
| 484 | return atomic_inc_unless_negative(&mapping->i_mmap_writable) ? | ||
| 485 | 0 : -EPERM; | ||
| 486 | } | ||
| 487 | |||
| 488 | static inline void mapping_unmap_writable(struct address_space *mapping) | ||
| 489 | { | ||
| 490 | atomic_dec(&mapping->i_mmap_writable); | ||
| 491 | } | ||
| 492 | |||
| 493 | static inline int mapping_deny_writable(struct address_space *mapping) | ||
| 494 | { | ||
| 495 | return atomic_dec_unless_positive(&mapping->i_mmap_writable) ? | ||
| 496 | 0 : -EBUSY; | ||
| 497 | } | ||
| 498 | |||
| 499 | static inline void mapping_allow_writable(struct address_space *mapping) | ||
| 500 | { | ||
| 501 | atomic_inc(&mapping->i_mmap_writable); | ||
| 477 | } | 502 | } |
| 478 | 503 | ||
| 479 | /* | 504 | /* |
diff --git a/include/linux/ioport.h b/include/linux/ioport.h index 5e3a906cc089..142ec544167c 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h | |||
| @@ -237,6 +237,12 @@ extern int iomem_is_exclusive(u64 addr); | |||
| 237 | extern int | 237 | extern int |
| 238 | walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages, | 238 | walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages, |
| 239 | void *arg, int (*func)(unsigned long, unsigned long, void *)); | 239 | void *arg, int (*func)(unsigned long, unsigned long, void *)); |
| 240 | extern int | ||
| 241 | walk_system_ram_res(u64 start, u64 end, void *arg, | ||
| 242 | int (*func)(u64, u64, void *)); | ||
| 243 | extern int | ||
| 244 | walk_iomem_res(char *name, unsigned long flags, u64 start, u64 end, void *arg, | ||
| 245 | int (*func)(u64, u64, void *)); | ||
| 240 | 246 | ||
| 241 | /* True if any part of r1 overlaps r2 */ | 247 | /* True if any part of r1 overlaps r2 */ |
| 242 | static inline bool resource_overlaps(struct resource *r1, struct resource *r2) | 248 | static inline bool resource_overlaps(struct resource *r1, struct resource *r2) |
diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 3dc22abbc68a..31ae66f34235 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h | |||
| @@ -470,6 +470,7 @@ extern enum system_states { | |||
| 470 | #define TAINT_FIRMWARE_WORKAROUND 11 | 470 | #define TAINT_FIRMWARE_WORKAROUND 11 |
| 471 | #define TAINT_OOT_MODULE 12 | 471 | #define TAINT_OOT_MODULE 12 |
| 472 | #define TAINT_UNSIGNED_MODULE 13 | 472 | #define TAINT_UNSIGNED_MODULE 13 |
| 473 | #define TAINT_SOFTLOCKUP 14 | ||
| 473 | 474 | ||
| 474 | extern const char hex_asc[]; | 475 | extern const char hex_asc[]; |
| 475 | #define hex_asc_lo(x) hex_asc[((x) & 0x0f)] | 476 | #define hex_asc_lo(x) hex_asc[((x) & 0x0f)] |
diff --git a/include/linux/kexec.h b/include/linux/kexec.h index a75641930049..4b2a0e11cc5b 100644 --- a/include/linux/kexec.h +++ b/include/linux/kexec.h | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include <linux/ioport.h> | 10 | #include <linux/ioport.h> |
| 11 | #include <linux/elfcore.h> | 11 | #include <linux/elfcore.h> |
| 12 | #include <linux/elf.h> | 12 | #include <linux/elf.h> |
| 13 | #include <linux/module.h> | ||
| 13 | #include <asm/kexec.h> | 14 | #include <asm/kexec.h> |
| 14 | 15 | ||
| 15 | /* Verify architecture specific macros are defined */ | 16 | /* Verify architecture specific macros are defined */ |
| @@ -69,7 +70,18 @@ typedef unsigned long kimage_entry_t; | |||
| 69 | #define IND_SOURCE 0x8 | 70 | #define IND_SOURCE 0x8 |
| 70 | 71 | ||
| 71 | struct kexec_segment { | 72 | struct kexec_segment { |
| 72 | void __user *buf; | 73 | /* |
| 74 | * This pointer can point to user memory if kexec_load() system | ||
| 75 | * call is used or will point to kernel memory if | ||
| 76 | * kexec_file_load() system call is used. | ||
| 77 | * | ||
| 78 | * Use ->buf when expecting to deal with user memory and use ->kbuf | ||
| 79 | * when expecting to deal with kernel memory. | ||
| 80 | */ | ||
| 81 | union { | ||
| 82 | void __user *buf; | ||
| 83 | void *kbuf; | ||
| 84 | }; | ||
| 73 | size_t bufsz; | 85 | size_t bufsz; |
| 74 | unsigned long mem; | 86 | unsigned long mem; |
| 75 | size_t memsz; | 87 | size_t memsz; |
| @@ -84,6 +96,27 @@ struct compat_kexec_segment { | |||
| 84 | }; | 96 | }; |
| 85 | #endif | 97 | #endif |
| 86 | 98 | ||
| 99 | struct kexec_sha_region { | ||
| 100 | unsigned long start; | ||
| 101 | unsigned long len; | ||
| 102 | }; | ||
| 103 | |||
| 104 | struct purgatory_info { | ||
| 105 | /* Pointer to elf header of read only purgatory */ | ||
| 106 | Elf_Ehdr *ehdr; | ||
| 107 | |||
| 108 | /* Pointer to purgatory sechdrs which are modifiable */ | ||
| 109 | Elf_Shdr *sechdrs; | ||
| 110 | /* | ||
| 111 | * Temporary buffer location where purgatory is loaded and relocated | ||
| 112 | * This memory can be freed post image load | ||
| 113 | */ | ||
| 114 | void *purgatory_buf; | ||
| 115 | |||
| 116 | /* Address where purgatory is finally loaded and is executed from */ | ||
| 117 | unsigned long purgatory_load_addr; | ||
| 118 | }; | ||
| 119 | |||
| 87 | struct kimage { | 120 | struct kimage { |
| 88 | kimage_entry_t head; | 121 | kimage_entry_t head; |
| 89 | kimage_entry_t *entry; | 122 | kimage_entry_t *entry; |
| @@ -100,7 +133,7 @@ struct kimage { | |||
| 100 | 133 | ||
| 101 | struct list_head control_pages; | 134 | struct list_head control_pages; |
| 102 | struct list_head dest_pages; | 135 | struct list_head dest_pages; |
| 103 | struct list_head unuseable_pages; | 136 | struct list_head unusable_pages; |
| 104 | 137 | ||
| 105 | /* Address of next control page to allocate for crash kernels. */ | 138 | /* Address of next control page to allocate for crash kernels. */ |
| 106 | unsigned long control_page; | 139 | unsigned long control_page; |
| @@ -110,13 +143,63 @@ struct kimage { | |||
| 110 | #define KEXEC_TYPE_DEFAULT 0 | 143 | #define KEXEC_TYPE_DEFAULT 0 |
| 111 | #define KEXEC_TYPE_CRASH 1 | 144 | #define KEXEC_TYPE_CRASH 1 |
| 112 | unsigned int preserve_context : 1; | 145 | unsigned int preserve_context : 1; |
| 146 | /* If set, we are using file mode kexec syscall */ | ||
| 147 | unsigned int file_mode:1; | ||
| 113 | 148 | ||
| 114 | #ifdef ARCH_HAS_KIMAGE_ARCH | 149 | #ifdef ARCH_HAS_KIMAGE_ARCH |
| 115 | struct kimage_arch arch; | 150 | struct kimage_arch arch; |
| 116 | #endif | 151 | #endif |
| 152 | |||
| 153 | /* Additional fields for file based kexec syscall */ | ||
| 154 | void *kernel_buf; | ||
| 155 | unsigned long kernel_buf_len; | ||
| 156 | |||
| 157 | void *initrd_buf; | ||
| 158 | unsigned long initrd_buf_len; | ||
| 159 | |||
| 160 | char *cmdline_buf; | ||
| 161 | unsigned long cmdline_buf_len; | ||
| 162 | |||
| 163 | /* File operations provided by image loader */ | ||
| 164 | struct kexec_file_ops *fops; | ||
| 165 | |||
| 166 | /* Image loader handling the kernel can store a pointer here */ | ||
| 167 | void *image_loader_data; | ||
| 168 | |||
| 169 | /* Information for loading purgatory */ | ||
| 170 | struct purgatory_info purgatory_info; | ||
| 117 | }; | 171 | }; |
| 118 | 172 | ||
| 173 | /* | ||
| 174 | * Keeps track of buffer parameters as provided by caller for requesting | ||
| 175 | * memory placement of buffer. | ||
| 176 | */ | ||
| 177 | struct kexec_buf { | ||
| 178 | struct kimage *image; | ||
| 179 | char *buffer; | ||
| 180 | unsigned long bufsz; | ||
| 181 | unsigned long memsz; | ||
| 182 | unsigned long buf_align; | ||
| 183 | unsigned long buf_min; | ||
| 184 | unsigned long buf_max; | ||
| 185 | bool top_down; /* allocate from top of memory hole */ | ||
| 186 | }; | ||
| 119 | 187 | ||
| 188 | typedef int (kexec_probe_t)(const char *kernel_buf, unsigned long kernel_size); | ||
| 189 | typedef void *(kexec_load_t)(struct kimage *image, char *kernel_buf, | ||
| 190 | unsigned long kernel_len, char *initrd, | ||
| 191 | unsigned long initrd_len, char *cmdline, | ||
| 192 | unsigned long cmdline_len); | ||
| 193 | typedef int (kexec_cleanup_t)(void *loader_data); | ||
| 194 | typedef int (kexec_verify_sig_t)(const char *kernel_buf, | ||
| 195 | unsigned long kernel_len); | ||
| 196 | |||
| 197 | struct kexec_file_ops { | ||
| 198 | kexec_probe_t *probe; | ||
| 199 | kexec_load_t *load; | ||
| 200 | kexec_cleanup_t *cleanup; | ||
| 201 | kexec_verify_sig_t *verify_sig; | ||
| 202 | }; | ||
| 120 | 203 | ||
| 121 | /* kexec interface functions */ | 204 | /* kexec interface functions */ |
| 122 | extern void machine_kexec(struct kimage *image); | 205 | extern void machine_kexec(struct kimage *image); |
| @@ -127,8 +210,21 @@ extern asmlinkage long sys_kexec_load(unsigned long entry, | |||
| 127 | struct kexec_segment __user *segments, | 210 | struct kexec_segment __user *segments, |
| 128 | unsigned long flags); | 211 | unsigned long flags); |
| 129 | extern int kernel_kexec(void); | 212 | extern int kernel_kexec(void); |
| 213 | extern int kexec_add_buffer(struct kimage *image, char *buffer, | ||
| 214 | unsigned long bufsz, unsigned long memsz, | ||
| 215 | unsigned long buf_align, unsigned long buf_min, | ||
| 216 | unsigned long buf_max, bool top_down, | ||
| 217 | unsigned long *load_addr); | ||
| 130 | extern struct page *kimage_alloc_control_pages(struct kimage *image, | 218 | extern struct page *kimage_alloc_control_pages(struct kimage *image, |
| 131 | unsigned int order); | 219 | unsigned int order); |
| 220 | extern int kexec_load_purgatory(struct kimage *image, unsigned long min, | ||
| 221 | unsigned long max, int top_down, | ||
| 222 | unsigned long *load_addr); | ||
| 223 | extern int kexec_purgatory_get_set_symbol(struct kimage *image, | ||
| 224 | const char *name, void *buf, | ||
| 225 | unsigned int size, bool get_value); | ||
| 226 | extern void *kexec_purgatory_get_symbol_addr(struct kimage *image, | ||
| 227 | const char *name); | ||
| 132 | extern void crash_kexec(struct pt_regs *); | 228 | extern void crash_kexec(struct pt_regs *); |
| 133 | int kexec_should_crash(struct task_struct *); | 229 | int kexec_should_crash(struct task_struct *); |
| 134 | void crash_save_cpu(struct pt_regs *regs, int cpu); | 230 | void crash_save_cpu(struct pt_regs *regs, int cpu); |
| @@ -177,6 +273,10 @@ extern int kexec_load_disabled; | |||
| 177 | #define KEXEC_FLAGS (KEXEC_ON_CRASH | KEXEC_PRESERVE_CONTEXT) | 273 | #define KEXEC_FLAGS (KEXEC_ON_CRASH | KEXEC_PRESERVE_CONTEXT) |
| 178 | #endif | 274 | #endif |
| 179 | 275 | ||
| 276 | /* List of defined/legal kexec file flags */ | ||
| 277 | #define KEXEC_FILE_FLAGS (KEXEC_FILE_UNLOAD | KEXEC_FILE_ON_CRASH | \ | ||
| 278 | KEXEC_FILE_NO_INITRAMFS) | ||
| 279 | |||
| 180 | #define VMCOREINFO_BYTES (4096) | 280 | #define VMCOREINFO_BYTES (4096) |
| 181 | #define VMCOREINFO_NOTE_NAME "VMCOREINFO" | 281 | #define VMCOREINFO_NOTE_NAME "VMCOREINFO" |
| 182 | #define VMCOREINFO_NOTE_NAME_BYTES ALIGN(sizeof(VMCOREINFO_NOTE_NAME), 4) | 282 | #define VMCOREINFO_NOTE_NAME_BYTES ALIGN(sizeof(VMCOREINFO_NOTE_NAME), 4) |
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index eb65d29516ca..e0752d204d9e 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h | |||
| @@ -54,39 +54,20 @@ struct mem_cgroup_reclaim_cookie { | |||
| 54 | }; | 54 | }; |
| 55 | 55 | ||
| 56 | #ifdef CONFIG_MEMCG | 56 | #ifdef CONFIG_MEMCG |
| 57 | /* | 57 | int mem_cgroup_try_charge(struct page *page, struct mm_struct *mm, |
| 58 | * All "charge" functions with gfp_mask should use GFP_KERNEL or | 58 | gfp_t gfp_mask, struct mem_cgroup **memcgp); |
| 59 | * (gfp_mask & GFP_RECLAIM_MASK). In current implementatin, memcg doesn't | 59 | void mem_cgroup_commit_charge(struct page *page, struct mem_cgroup *memcg, |
| 60 | * alloc memory but reclaims memory from all available zones. So, "where I want | 60 | bool lrucare); |
| 61 | * memory from" bits of gfp_mask has no meaning. So any bits of that field is | 61 | void mem_cgroup_cancel_charge(struct page *page, struct mem_cgroup *memcg); |
| 62 | * available but adding a rule is better. charge functions' gfp_mask should | 62 | void mem_cgroup_uncharge(struct page *page); |
| 63 | * be set to GFP_KERNEL or gfp_mask & GFP_RECLAIM_MASK for avoiding ambiguous | 63 | void mem_cgroup_uncharge_list(struct list_head *page_list); |
| 64 | * codes. | ||
| 65 | * (Of course, if memcg does memory allocation in future, GFP_KERNEL is sane.) | ||
| 66 | */ | ||
| 67 | 64 | ||
| 68 | extern int mem_cgroup_charge_anon(struct page *page, struct mm_struct *mm, | 65 | void mem_cgroup_migrate(struct page *oldpage, struct page *newpage, |
| 69 | gfp_t gfp_mask); | 66 | bool lrucare); |
| 70 | /* for swap handling */ | ||
| 71 | extern int mem_cgroup_try_charge_swapin(struct mm_struct *mm, | ||
| 72 | struct page *page, gfp_t mask, struct mem_cgroup **memcgp); | ||
| 73 | extern void mem_cgroup_commit_charge_swapin(struct page *page, | ||
| 74 | struct mem_cgroup *memcg); | ||
| 75 | extern void mem_cgroup_cancel_charge_swapin(struct mem_cgroup *memcg); | ||
| 76 | |||
| 77 | extern int mem_cgroup_charge_file(struct page *page, struct mm_struct *mm, | ||
| 78 | gfp_t gfp_mask); | ||
| 79 | 67 | ||
| 80 | struct lruvec *mem_cgroup_zone_lruvec(struct zone *, struct mem_cgroup *); | 68 | struct lruvec *mem_cgroup_zone_lruvec(struct zone *, struct mem_cgroup *); |
| 81 | struct lruvec *mem_cgroup_page_lruvec(struct page *, struct zone *); | 69 | struct lruvec *mem_cgroup_page_lruvec(struct page *, struct zone *); |
| 82 | 70 | ||
| 83 | /* For coalescing uncharge for reducing memcg' overhead*/ | ||
| 84 | extern void mem_cgroup_uncharge_start(void); | ||
| 85 | extern void mem_cgroup_uncharge_end(void); | ||
| 86 | |||
| 87 | extern void mem_cgroup_uncharge_page(struct page *page); | ||
| 88 | extern void mem_cgroup_uncharge_cache_page(struct page *page); | ||
| 89 | |||
| 90 | bool __mem_cgroup_same_or_subtree(const struct mem_cgroup *root_memcg, | 71 | bool __mem_cgroup_same_or_subtree(const struct mem_cgroup *root_memcg, |
| 91 | struct mem_cgroup *memcg); | 72 | struct mem_cgroup *memcg); |
| 92 | bool task_in_mem_cgroup(struct task_struct *task, | 73 | bool task_in_mem_cgroup(struct task_struct *task, |
| @@ -113,12 +94,6 @@ bool mm_match_cgroup(const struct mm_struct *mm, const struct mem_cgroup *memcg) | |||
| 113 | 94 | ||
| 114 | extern struct cgroup_subsys_state *mem_cgroup_css(struct mem_cgroup *memcg); | 95 | extern struct cgroup_subsys_state *mem_cgroup_css(struct mem_cgroup *memcg); |
| 115 | 96 | ||
| 116 | extern void | ||
| 117 | mem_cgroup_prepare_migration(struct page *page, struct page *newpage, | ||
| 118 | struct mem_cgroup **memcgp); | ||
| 119 | extern void mem_cgroup_end_migration(struct mem_cgroup *memcg, | ||
| 120 | struct page *oldpage, struct page *newpage, bool migration_ok); | ||
| 121 | |||
| 122 | struct mem_cgroup *mem_cgroup_iter(struct mem_cgroup *, | 97 | struct mem_cgroup *mem_cgroup_iter(struct mem_cgroup *, |
| 123 | struct mem_cgroup *, | 98 | struct mem_cgroup *, |
| 124 | struct mem_cgroup_reclaim_cookie *); | 99 | struct mem_cgroup_reclaim_cookie *); |
| @@ -133,8 +108,6 @@ unsigned long mem_cgroup_get_lru_size(struct lruvec *lruvec, enum lru_list); | |||
| 133 | void mem_cgroup_update_lru_size(struct lruvec *, enum lru_list, int); | 108 | void mem_cgroup_update_lru_size(struct lruvec *, enum lru_list, int); |
| 134 | extern void mem_cgroup_print_oom_info(struct mem_cgroup *memcg, | 109 | extern void mem_cgroup_print_oom_info(struct mem_cgroup *memcg, |
| 135 | struct task_struct *p); | 110 | struct task_struct *p); |
| 136 | extern void mem_cgroup_replace_page_cache(struct page *oldpage, | ||
| 137 | struct page *newpage); | ||
| 138 | 111 | ||
| 139 | static inline void mem_cgroup_oom_enable(void) | 112 | static inline void mem_cgroup_oom_enable(void) |
| 140 | { | 113 | { |
| @@ -233,46 +206,36 @@ void mem_cgroup_print_bad_page(struct page *page); | |||
| 233 | #else /* CONFIG_MEMCG */ | 206 | #else /* CONFIG_MEMCG */ |
| 234 | struct mem_cgroup; | 207 | struct mem_cgroup; |
| 235 | 208 | ||
| 236 | static inline int mem_cgroup_charge_anon(struct page *page, | 209 | static inline int mem_cgroup_try_charge(struct page *page, struct mm_struct *mm, |
| 237 | struct mm_struct *mm, gfp_t gfp_mask) | 210 | gfp_t gfp_mask, |
| 238 | { | 211 | struct mem_cgroup **memcgp) |
| 239 | return 0; | ||
| 240 | } | ||
| 241 | |||
| 242 | static inline int mem_cgroup_charge_file(struct page *page, | ||
| 243 | struct mm_struct *mm, gfp_t gfp_mask) | ||
| 244 | { | ||
| 245 | return 0; | ||
| 246 | } | ||
| 247 | |||
| 248 | static inline int mem_cgroup_try_charge_swapin(struct mm_struct *mm, | ||
| 249 | struct page *page, gfp_t gfp_mask, struct mem_cgroup **memcgp) | ||
| 250 | { | 212 | { |
| 213 | *memcgp = NULL; | ||
| 251 | return 0; | 214 | return 0; |
| 252 | } | 215 | } |
| 253 | 216 | ||
| 254 | static inline void mem_cgroup_commit_charge_swapin(struct page *page, | 217 | static inline void mem_cgroup_commit_charge(struct page *page, |
| 255 | struct mem_cgroup *memcg) | 218 | struct mem_cgroup *memcg, |
| 256 | { | 219 | bool lrucare) |
| 257 | } | ||
| 258 | |||
| 259 | static inline void mem_cgroup_cancel_charge_swapin(struct mem_cgroup *memcg) | ||
| 260 | { | 220 | { |
| 261 | } | 221 | } |
| 262 | 222 | ||
| 263 | static inline void mem_cgroup_uncharge_start(void) | 223 | static inline void mem_cgroup_cancel_charge(struct page *page, |
| 224 | struct mem_cgroup *memcg) | ||
| 264 | { | 225 | { |
| 265 | } | 226 | } |
| 266 | 227 | ||
| 267 | static inline void mem_cgroup_uncharge_end(void) | 228 | static inline void mem_cgroup_uncharge(struct page *page) |
| 268 | { | 229 | { |
| 269 | } | 230 | } |
| 270 | 231 | ||
| 271 | static inline void mem_cgroup_uncharge_page(struct page *page) | 232 | static inline void mem_cgroup_uncharge_list(struct list_head *page_list) |
| 272 | { | 233 | { |
| 273 | } | 234 | } |
| 274 | 235 | ||
| 275 | static inline void mem_cgroup_uncharge_cache_page(struct page *page) | 236 | static inline void mem_cgroup_migrate(struct page *oldpage, |
| 237 | struct page *newpage, | ||
| 238 | bool lrucare) | ||
| 276 | { | 239 | { |
| 277 | } | 240 | } |
| 278 | 241 | ||
| @@ -311,17 +274,6 @@ static inline struct cgroup_subsys_state | |||
| 311 | return NULL; | 274 | return NULL; |
| 312 | } | 275 | } |
| 313 | 276 | ||
| 314 | static inline void | ||
| 315 | mem_cgroup_prepare_migration(struct page *page, struct page *newpage, | ||
| 316 | struct mem_cgroup **memcgp) | ||
| 317 | { | ||
| 318 | } | ||
| 319 | |||
| 320 | static inline void mem_cgroup_end_migration(struct mem_cgroup *memcg, | ||
| 321 | struct page *oldpage, struct page *newpage, bool migration_ok) | ||
| 322 | { | ||
| 323 | } | ||
| 324 | |||
| 325 | static inline struct mem_cgroup * | 277 | static inline struct mem_cgroup * |
| 326 | mem_cgroup_iter(struct mem_cgroup *root, | 278 | mem_cgroup_iter(struct mem_cgroup *root, |
| 327 | struct mem_cgroup *prev, | 279 | struct mem_cgroup *prev, |
| @@ -417,10 +369,6 @@ static inline | |||
| 417 | void mem_cgroup_count_vm_event(struct mm_struct *mm, enum vm_event_item idx) | 369 | void mem_cgroup_count_vm_event(struct mm_struct *mm, enum vm_event_item idx) |
| 418 | { | 370 | { |
| 419 | } | 371 | } |
| 420 | static inline void mem_cgroup_replace_page_cache(struct page *oldpage, | ||
| 421 | struct page *newpage) | ||
| 422 | { | ||
| 423 | } | ||
| 424 | #endif /* CONFIG_MEMCG */ | 372 | #endif /* CONFIG_MEMCG */ |
| 425 | 373 | ||
| 426 | #if !defined(CONFIG_MEMCG) || !defined(CONFIG_DEBUG_VM) | 374 | #if !defined(CONFIG_MEMCG) || !defined(CONFIG_DEBUG_VM) |
diff --git a/include/linux/mm.h b/include/linux/mm.h index e03dd29145a0..8981cc882ed2 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
| @@ -2014,13 +2014,20 @@ static inline bool kernel_page_present(struct page *page) { return true; } | |||
| 2014 | #endif /* CONFIG_HIBERNATION */ | 2014 | #endif /* CONFIG_HIBERNATION */ |
| 2015 | #endif | 2015 | #endif |
| 2016 | 2016 | ||
| 2017 | #ifdef __HAVE_ARCH_GATE_AREA | ||
| 2017 | extern struct vm_area_struct *get_gate_vma(struct mm_struct *mm); | 2018 | extern struct vm_area_struct *get_gate_vma(struct mm_struct *mm); |
| 2018 | #ifdef __HAVE_ARCH_GATE_AREA | 2019 | extern int in_gate_area_no_mm(unsigned long addr); |
| 2019 | int in_gate_area_no_mm(unsigned long addr); | 2020 | extern int in_gate_area(struct mm_struct *mm, unsigned long addr); |
| 2020 | int in_gate_area(struct mm_struct *mm, unsigned long addr); | ||
| 2021 | #else | 2021 | #else |
| 2022 | int in_gate_area_no_mm(unsigned long addr); | 2022 | static inline struct vm_area_struct *get_gate_vma(struct mm_struct *mm) |
| 2023 | #define in_gate_area(mm, addr) ({(void)mm; in_gate_area_no_mm(addr);}) | 2023 | { |
| 2024 | return NULL; | ||
| 2025 | } | ||
| 2026 | static inline int in_gate_area_no_mm(unsigned long addr) { return 0; } | ||
| 2027 | static inline int in_gate_area(struct mm_struct *mm, unsigned long addr) | ||
| 2028 | { | ||
| 2029 | return 0; | ||
| 2030 | } | ||
| 2024 | #endif /* __HAVE_ARCH_GATE_AREA */ | 2031 | #endif /* __HAVE_ARCH_GATE_AREA */ |
| 2025 | 2032 | ||
| 2026 | #ifdef CONFIG_SYSCTL | 2033 | #ifdef CONFIG_SYSCTL |
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index 796deac19fcf..6e0b286649f1 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h | |||
| @@ -461,6 +461,7 @@ static inline void mm_init_cpumask(struct mm_struct *mm) | |||
| 461 | #ifdef CONFIG_CPUMASK_OFFSTACK | 461 | #ifdef CONFIG_CPUMASK_OFFSTACK |
| 462 | mm->cpu_vm_mask_var = &mm->cpumask_allocation; | 462 | mm->cpu_vm_mask_var = &mm->cpumask_allocation; |
| 463 | #endif | 463 | #endif |
| 464 | cpumask_clear(mm->cpu_vm_mask_var); | ||
| 464 | } | 465 | } |
| 465 | 466 | ||
| 466 | /* Future-safe accessor for struct mm_struct's cpu_vm_mask. */ | 467 | /* Future-safe accessor for struct mm_struct's cpu_vm_mask. */ |
diff --git a/include/linux/page_cgroup.h b/include/linux/page_cgroup.h index 777a524716db..5c831f1eca79 100644 --- a/include/linux/page_cgroup.h +++ b/include/linux/page_cgroup.h | |||
| @@ -3,17 +3,15 @@ | |||
| 3 | 3 | ||
| 4 | enum { | 4 | enum { |
| 5 | /* flags for mem_cgroup */ | 5 | /* flags for mem_cgroup */ |
| 6 | PCG_LOCK, /* Lock for pc->mem_cgroup and following bits. */ | 6 | PCG_USED = 0x01, /* This page is charged to a memcg */ |
| 7 | PCG_USED, /* this object is in use. */ | 7 | PCG_MEM = 0x02, /* This page holds a memory charge */ |
| 8 | PCG_MIGRATION, /* under page migration */ | 8 | PCG_MEMSW = 0x04, /* This page holds a memory+swap charge */ |
| 9 | __NR_PCG_FLAGS, | ||
| 10 | }; | 9 | }; |
| 11 | 10 | ||
| 12 | #ifndef __GENERATING_BOUNDS_H | 11 | struct pglist_data; |
| 13 | #include <generated/bounds.h> | ||
| 14 | 12 | ||
| 15 | #ifdef CONFIG_MEMCG | 13 | #ifdef CONFIG_MEMCG |
| 16 | #include <linux/bit_spinlock.h> | 14 | struct mem_cgroup; |
| 17 | 15 | ||
| 18 | /* | 16 | /* |
| 19 | * Page Cgroup can be considered as an extended mem_map. | 17 | * Page Cgroup can be considered as an extended mem_map. |
| @@ -27,65 +25,30 @@ struct page_cgroup { | |||
| 27 | struct mem_cgroup *mem_cgroup; | 25 | struct mem_cgroup *mem_cgroup; |
| 28 | }; | 26 | }; |
| 29 | 27 | ||
| 30 | void __meminit pgdat_page_cgroup_init(struct pglist_data *pgdat); | 28 | extern void pgdat_page_cgroup_init(struct pglist_data *pgdat); |
| 31 | 29 | ||
| 32 | #ifdef CONFIG_SPARSEMEM | 30 | #ifdef CONFIG_SPARSEMEM |
| 33 | static inline void __init page_cgroup_init_flatmem(void) | 31 | static inline void page_cgroup_init_flatmem(void) |
| 34 | { | 32 | { |
| 35 | } | 33 | } |
| 36 | extern void __init page_cgroup_init(void); | 34 | extern void page_cgroup_init(void); |
| 37 | #else | 35 | #else |
| 38 | void __init page_cgroup_init_flatmem(void); | 36 | extern void page_cgroup_init_flatmem(void); |
| 39 | static inline void __init page_cgroup_init(void) | 37 | static inline void page_cgroup_init(void) |
| 40 | { | 38 | { |
| 41 | } | 39 | } |
| 42 | #endif | 40 | #endif |
| 43 | 41 | ||
| 44 | struct page_cgroup *lookup_page_cgroup(struct page *page); | 42 | struct page_cgroup *lookup_page_cgroup(struct page *page); |
| 45 | struct page *lookup_cgroup_page(struct page_cgroup *pc); | ||
| 46 | |||
| 47 | #define TESTPCGFLAG(uname, lname) \ | ||
| 48 | static inline int PageCgroup##uname(struct page_cgroup *pc) \ | ||
| 49 | { return test_bit(PCG_##lname, &pc->flags); } | ||
| 50 | |||
| 51 | #define SETPCGFLAG(uname, lname) \ | ||
| 52 | static inline void SetPageCgroup##uname(struct page_cgroup *pc)\ | ||
| 53 | { set_bit(PCG_##lname, &pc->flags); } | ||
| 54 | |||
| 55 | #define CLEARPCGFLAG(uname, lname) \ | ||
| 56 | static inline void ClearPageCgroup##uname(struct page_cgroup *pc) \ | ||
| 57 | { clear_bit(PCG_##lname, &pc->flags); } | ||
| 58 | |||
| 59 | #define TESTCLEARPCGFLAG(uname, lname) \ | ||
| 60 | static inline int TestClearPageCgroup##uname(struct page_cgroup *pc) \ | ||
| 61 | { return test_and_clear_bit(PCG_##lname, &pc->flags); } | ||
| 62 | |||
| 63 | TESTPCGFLAG(Used, USED) | ||
| 64 | CLEARPCGFLAG(Used, USED) | ||
| 65 | SETPCGFLAG(Used, USED) | ||
| 66 | |||
| 67 | SETPCGFLAG(Migration, MIGRATION) | ||
| 68 | CLEARPCGFLAG(Migration, MIGRATION) | ||
| 69 | TESTPCGFLAG(Migration, MIGRATION) | ||
| 70 | 43 | ||
| 71 | static inline void lock_page_cgroup(struct page_cgroup *pc) | 44 | static inline int PageCgroupUsed(struct page_cgroup *pc) |
| 72 | { | 45 | { |
| 73 | /* | 46 | return !!(pc->flags & PCG_USED); |
| 74 | * Don't take this lock in IRQ context. | ||
| 75 | * This lock is for pc->mem_cgroup, USED, MIGRATION | ||
| 76 | */ | ||
| 77 | bit_spin_lock(PCG_LOCK, &pc->flags); | ||
| 78 | } | 47 | } |
| 79 | 48 | #else /* !CONFIG_MEMCG */ | |
| 80 | static inline void unlock_page_cgroup(struct page_cgroup *pc) | ||
| 81 | { | ||
| 82 | bit_spin_unlock(PCG_LOCK, &pc->flags); | ||
| 83 | } | ||
| 84 | |||
| 85 | #else /* CONFIG_MEMCG */ | ||
| 86 | struct page_cgroup; | 49 | struct page_cgroup; |
| 87 | 50 | ||
| 88 | static inline void __meminit pgdat_page_cgroup_init(struct pglist_data *pgdat) | 51 | static inline void pgdat_page_cgroup_init(struct pglist_data *pgdat) |
| 89 | { | 52 | { |
| 90 | } | 53 | } |
| 91 | 54 | ||
| @@ -98,10 +61,9 @@ static inline void page_cgroup_init(void) | |||
| 98 | { | 61 | { |
| 99 | } | 62 | } |
| 100 | 63 | ||
| 101 | static inline void __init page_cgroup_init_flatmem(void) | 64 | static inline void page_cgroup_init_flatmem(void) |
| 102 | { | 65 | { |
| 103 | } | 66 | } |
| 104 | |||
| 105 | #endif /* CONFIG_MEMCG */ | 67 | #endif /* CONFIG_MEMCG */ |
| 106 | 68 | ||
| 107 | #include <linux/swap.h> | 69 | #include <linux/swap.h> |
| @@ -140,6 +102,4 @@ static inline void swap_cgroup_swapoff(int type) | |||
| 140 | 102 | ||
| 141 | #endif /* CONFIG_MEMCG_SWAP */ | 103 | #endif /* CONFIG_MEMCG_SWAP */ |
| 142 | 104 | ||
| 143 | #endif /* !__GENERATING_BOUNDS_H */ | ||
| 144 | |||
| 145 | #endif /* __LINUX_PAGE_CGROUP_H */ | 105 | #endif /* __LINUX_PAGE_CGROUP_H */ |
diff --git a/include/linux/rio_drv.h b/include/linux/rio_drv.h index 5059994fe297..9fc2f213e74f 100644 --- a/include/linux/rio_drv.h +++ b/include/linux/rio_drv.h | |||
| @@ -384,11 +384,16 @@ void rio_dev_put(struct rio_dev *); | |||
| 384 | 384 | ||
| 385 | #ifdef CONFIG_RAPIDIO_DMA_ENGINE | 385 | #ifdef CONFIG_RAPIDIO_DMA_ENGINE |
| 386 | extern struct dma_chan *rio_request_dma(struct rio_dev *rdev); | 386 | extern struct dma_chan *rio_request_dma(struct rio_dev *rdev); |
| 387 | extern struct dma_chan *rio_request_mport_dma(struct rio_mport *mport); | ||
| 387 | extern void rio_release_dma(struct dma_chan *dchan); | 388 | extern void rio_release_dma(struct dma_chan *dchan); |
| 388 | extern struct dma_async_tx_descriptor *rio_dma_prep_slave_sg( | 389 | extern struct dma_async_tx_descriptor *rio_dma_prep_slave_sg( |
| 389 | struct rio_dev *rdev, struct dma_chan *dchan, | 390 | struct rio_dev *rdev, struct dma_chan *dchan, |
| 390 | struct rio_dma_data *data, | 391 | struct rio_dma_data *data, |
| 391 | enum dma_transfer_direction direction, unsigned long flags); | 392 | enum dma_transfer_direction direction, unsigned long flags); |
| 393 | extern struct dma_async_tx_descriptor *rio_dma_prep_xfer( | ||
| 394 | struct dma_chan *dchan, u16 destid, | ||
| 395 | struct rio_dma_data *data, | ||
| 396 | enum dma_transfer_direction direction, unsigned long flags); | ||
| 392 | #endif | 397 | #endif |
| 393 | 398 | ||
| 394 | /** | 399 | /** |
diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h index f4ec8bbcb372..ed8f9e70df9b 100644 --- a/include/linux/scatterlist.h +++ b/include/linux/scatterlist.h | |||
| @@ -136,7 +136,7 @@ static inline void sg_set_buf(struct scatterlist *sg, const void *buf, | |||
| 136 | static inline void sg_chain(struct scatterlist *prv, unsigned int prv_nents, | 136 | static inline void sg_chain(struct scatterlist *prv, unsigned int prv_nents, |
| 137 | struct scatterlist *sgl) | 137 | struct scatterlist *sgl) |
| 138 | { | 138 | { |
| 139 | #ifndef ARCH_HAS_SG_CHAIN | 139 | #ifndef CONFIG_ARCH_HAS_SG_CHAIN |
| 140 | BUG(); | 140 | BUG(); |
| 141 | #endif | 141 | #endif |
| 142 | 142 | ||
diff --git a/include/linux/sched.h b/include/linux/sched.h index 7c19d552dc3f..db2f6474e95e 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
| @@ -33,6 +33,7 @@ struct sched_param { | |||
| 33 | 33 | ||
| 34 | #include <linux/smp.h> | 34 | #include <linux/smp.h> |
| 35 | #include <linux/sem.h> | 35 | #include <linux/sem.h> |
| 36 | #include <linux/shm.h> | ||
| 36 | #include <linux/signal.h> | 37 | #include <linux/signal.h> |
| 37 | #include <linux/compiler.h> | 38 | #include <linux/compiler.h> |
| 38 | #include <linux/completion.h> | 39 | #include <linux/completion.h> |
| @@ -1385,6 +1386,7 @@ struct task_struct { | |||
| 1385 | #ifdef CONFIG_SYSVIPC | 1386 | #ifdef CONFIG_SYSVIPC |
| 1386 | /* ipc stuff */ | 1387 | /* ipc stuff */ |
| 1387 | struct sysv_sem sysvsem; | 1388 | struct sysv_sem sysvsem; |
| 1389 | struct sysv_shm sysvshm; | ||
| 1388 | #endif | 1390 | #endif |
| 1389 | #ifdef CONFIG_DETECT_HUNG_TASK | 1391 | #ifdef CONFIG_DETECT_HUNG_TASK |
| 1390 | /* hung task detection */ | 1392 | /* hung task detection */ |
| @@ -1628,12 +1630,6 @@ struct task_struct { | |||
| 1628 | unsigned long trace_recursion; | 1630 | unsigned long trace_recursion; |
| 1629 | #endif /* CONFIG_TRACING */ | 1631 | #endif /* CONFIG_TRACING */ |
| 1630 | #ifdef CONFIG_MEMCG /* memcg uses this to do batch job */ | 1632 | #ifdef CONFIG_MEMCG /* memcg uses this to do batch job */ |
| 1631 | struct memcg_batch_info { | ||
| 1632 | int do_batch; /* incremented when batch uncharge started */ | ||
| 1633 | struct mem_cgroup *memcg; /* target memcg of uncharge */ | ||
| 1634 | unsigned long nr_pages; /* uncharged usage */ | ||
| 1635 | unsigned long memsw_nr_pages; /* uncharged mem+swap usage */ | ||
| 1636 | } memcg_batch; | ||
| 1637 | unsigned int memcg_kmem_skip_account; | 1633 | unsigned int memcg_kmem_skip_account; |
| 1638 | struct memcg_oom_info { | 1634 | struct memcg_oom_info { |
| 1639 | struct mem_cgroup *memcg; | 1635 | struct mem_cgroup *memcg; |
| @@ -2967,15 +2963,10 @@ static inline void inc_syscw(struct task_struct *tsk) | |||
| 2967 | 2963 | ||
| 2968 | #ifdef CONFIG_MEMCG | 2964 | #ifdef CONFIG_MEMCG |
| 2969 | extern void mm_update_next_owner(struct mm_struct *mm); | 2965 | extern void mm_update_next_owner(struct mm_struct *mm); |
| 2970 | extern void mm_init_owner(struct mm_struct *mm, struct task_struct *p); | ||
| 2971 | #else | 2966 | #else |
| 2972 | static inline void mm_update_next_owner(struct mm_struct *mm) | 2967 | static inline void mm_update_next_owner(struct mm_struct *mm) |
| 2973 | { | 2968 | { |
| 2974 | } | 2969 | } |
| 2975 | |||
| 2976 | static inline void mm_init_owner(struct mm_struct *mm, struct task_struct *p) | ||
| 2977 | { | ||
| 2978 | } | ||
| 2979 | #endif /* CONFIG_MEMCG */ | 2970 | #endif /* CONFIG_MEMCG */ |
| 2980 | 2971 | ||
| 2981 | static inline unsigned long task_rlimit(const struct task_struct *tsk, | 2972 | static inline unsigned long task_rlimit(const struct task_struct *tsk, |
diff --git a/include/linux/shm.h b/include/linux/shm.h index 57d77709fbe2..6fb801686ad6 100644 --- a/include/linux/shm.h +++ b/include/linux/shm.h | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | #ifndef _LINUX_SHM_H_ | 1 | #ifndef _LINUX_SHM_H_ |
| 2 | #define _LINUX_SHM_H_ | 2 | #define _LINUX_SHM_H_ |
| 3 | 3 | ||
| 4 | #include <linux/list.h> | ||
| 4 | #include <asm/page.h> | 5 | #include <asm/page.h> |
| 5 | #include <uapi/linux/shm.h> | 6 | #include <uapi/linux/shm.h> |
| 6 | #include <asm/shmparam.h> | 7 | #include <asm/shmparam.h> |
| @@ -20,6 +21,7 @@ struct shmid_kernel /* private to the kernel */ | |||
| 20 | 21 | ||
| 21 | /* The task created the shm object. NULL if the task is dead. */ | 22 | /* The task created the shm object. NULL if the task is dead. */ |
| 22 | struct task_struct *shm_creator; | 23 | struct task_struct *shm_creator; |
| 24 | struct list_head shm_clist; /* list by creator */ | ||
| 23 | }; | 25 | }; |
| 24 | 26 | ||
| 25 | /* shm_mode upper byte flags */ | 27 | /* shm_mode upper byte flags */ |
| @@ -44,11 +46,20 @@ struct shmid_kernel /* private to the kernel */ | |||
| 44 | #define SHM_HUGE_1GB (30 << SHM_HUGE_SHIFT) | 46 | #define SHM_HUGE_1GB (30 << SHM_HUGE_SHIFT) |
| 45 | 47 | ||
| 46 | #ifdef CONFIG_SYSVIPC | 48 | #ifdef CONFIG_SYSVIPC |
| 49 | struct sysv_shm { | ||
| 50 | struct list_head shm_clist; | ||
| 51 | }; | ||
| 52 | |||
| 47 | long do_shmat(int shmid, char __user *shmaddr, int shmflg, unsigned long *addr, | 53 | long do_shmat(int shmid, char __user *shmaddr, int shmflg, unsigned long *addr, |
| 48 | unsigned long shmlba); | 54 | unsigned long shmlba); |
| 49 | extern int is_file_shm_hugepages(struct file *file); | 55 | int is_file_shm_hugepages(struct file *file); |
| 50 | extern void exit_shm(struct task_struct *task); | 56 | void exit_shm(struct task_struct *task); |
| 57 | #define shm_init_task(task) INIT_LIST_HEAD(&(task)->sysvshm.shm_clist) | ||
| 51 | #else | 58 | #else |
| 59 | struct sysv_shm { | ||
| 60 | /* empty */ | ||
| 61 | }; | ||
| 62 | |||
| 52 | static inline long do_shmat(int shmid, char __user *shmaddr, | 63 | static inline long do_shmat(int shmid, char __user *shmaddr, |
| 53 | int shmflg, unsigned long *addr, | 64 | int shmflg, unsigned long *addr, |
| 54 | unsigned long shmlba) | 65 | unsigned long shmlba) |
| @@ -62,6 +73,9 @@ static inline int is_file_shm_hugepages(struct file *file) | |||
| 62 | static inline void exit_shm(struct task_struct *task) | 73 | static inline void exit_shm(struct task_struct *task) |
| 63 | { | 74 | { |
| 64 | } | 75 | } |
| 76 | static inline void shm_init_task(struct task_struct *task) | ||
| 77 | { | ||
| 78 | } | ||
| 65 | #endif | 79 | #endif |
| 66 | 80 | ||
| 67 | #endif /* _LINUX_SHM_H_ */ | 81 | #endif /* _LINUX_SHM_H_ */ |
diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h index 4d1771c2d29f..50777b5b1e4c 100644 --- a/include/linux/shmem_fs.h +++ b/include/linux/shmem_fs.h | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | #ifndef __SHMEM_FS_H | 1 | #ifndef __SHMEM_FS_H |
| 2 | #define __SHMEM_FS_H | 2 | #define __SHMEM_FS_H |
| 3 | 3 | ||
| 4 | #include <linux/file.h> | ||
| 4 | #include <linux/swap.h> | 5 | #include <linux/swap.h> |
| 5 | #include <linux/mempolicy.h> | 6 | #include <linux/mempolicy.h> |
| 6 | #include <linux/pagemap.h> | 7 | #include <linux/pagemap.h> |
| @@ -11,6 +12,7 @@ | |||
| 11 | 12 | ||
| 12 | struct shmem_inode_info { | 13 | struct shmem_inode_info { |
| 13 | spinlock_t lock; | 14 | spinlock_t lock; |
| 15 | unsigned int seals; /* shmem seals */ | ||
| 14 | unsigned long flags; | 16 | unsigned long flags; |
| 15 | unsigned long alloced; /* data pages alloced to file */ | 17 | unsigned long alloced; /* data pages alloced to file */ |
| 16 | union { | 18 | union { |
| @@ -65,4 +67,19 @@ static inline struct page *shmem_read_mapping_page( | |||
| 65 | mapping_gfp_mask(mapping)); | 67 | mapping_gfp_mask(mapping)); |
| 66 | } | 68 | } |
| 67 | 69 | ||
| 70 | #ifdef CONFIG_TMPFS | ||
| 71 | |||
| 72 | extern int shmem_add_seals(struct file *file, unsigned int seals); | ||
| 73 | extern int shmem_get_seals(struct file *file); | ||
| 74 | extern long shmem_fcntl(struct file *file, unsigned int cmd, unsigned long arg); | ||
| 75 | |||
| 76 | #else | ||
| 77 | |||
| 78 | static inline long shmem_fcntl(struct file *f, unsigned int c, unsigned long a) | ||
| 79 | { | ||
| 80 | return -EINVAL; | ||
| 81 | } | ||
| 82 | |||
| 83 | #endif | ||
| 84 | |||
| 68 | #endif | 85 | #endif |
diff --git a/include/linux/swap.h b/include/linux/swap.h index 1eb64043c076..1b72060f093a 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h | |||
| @@ -320,6 +320,9 @@ extern void swap_setup(void); | |||
| 320 | 320 | ||
| 321 | extern void add_page_to_unevictable_list(struct page *page); | 321 | extern void add_page_to_unevictable_list(struct page *page); |
| 322 | 322 | ||
| 323 | extern void lru_cache_add_active_or_unevictable(struct page *page, | ||
| 324 | struct vm_area_struct *vma); | ||
| 325 | |||
| 323 | /* linux/mm/vmscan.c */ | 326 | /* linux/mm/vmscan.c */ |
| 324 | extern unsigned long try_to_free_pages(struct zonelist *zonelist, int order, | 327 | extern unsigned long try_to_free_pages(struct zonelist *zonelist, int order, |
| 325 | gfp_t gfp_mask, nodemask_t *mask); | 328 | gfp_t gfp_mask, nodemask_t *mask); |
| @@ -378,9 +381,13 @@ static inline int mem_cgroup_swappiness(struct mem_cgroup *mem) | |||
| 378 | } | 381 | } |
| 379 | #endif | 382 | #endif |
| 380 | #ifdef CONFIG_MEMCG_SWAP | 383 | #ifdef CONFIG_MEMCG_SWAP |
| 381 | extern void mem_cgroup_uncharge_swap(swp_entry_t ent); | 384 | extern void mem_cgroup_swapout(struct page *page, swp_entry_t entry); |
| 385 | extern void mem_cgroup_uncharge_swap(swp_entry_t entry); | ||
| 382 | #else | 386 | #else |
| 383 | static inline void mem_cgroup_uncharge_swap(swp_entry_t ent) | 387 | static inline void mem_cgroup_swapout(struct page *page, swp_entry_t entry) |
| 388 | { | ||
| 389 | } | ||
| 390 | static inline void mem_cgroup_uncharge_swap(swp_entry_t entry) | ||
| 384 | { | 391 | { |
| 385 | } | 392 | } |
| 386 | #endif | 393 | #endif |
| @@ -440,7 +447,7 @@ extern void swap_shmem_alloc(swp_entry_t); | |||
| 440 | extern int swap_duplicate(swp_entry_t); | 447 | extern int swap_duplicate(swp_entry_t); |
| 441 | extern int swapcache_prepare(swp_entry_t); | 448 | extern int swapcache_prepare(swp_entry_t); |
| 442 | extern void swap_free(swp_entry_t); | 449 | extern void swap_free(swp_entry_t); |
| 443 | extern void swapcache_free(swp_entry_t, struct page *page); | 450 | extern void swapcache_free(swp_entry_t); |
| 444 | extern int free_swap_and_cache(swp_entry_t); | 451 | extern int free_swap_and_cache(swp_entry_t); |
| 445 | extern int swap_type_of(dev_t, sector_t, struct block_device **); | 452 | extern int swap_type_of(dev_t, sector_t, struct block_device **); |
| 446 | extern unsigned int count_swap_pages(int, int); | 453 | extern unsigned int count_swap_pages(int, int); |
| @@ -504,7 +511,7 @@ static inline void swap_free(swp_entry_t swp) | |||
| 504 | { | 511 | { |
| 505 | } | 512 | } |
| 506 | 513 | ||
| 507 | static inline void swapcache_free(swp_entry_t swp, struct page *page) | 514 | static inline void swapcache_free(swp_entry_t swp) |
| 508 | { | 515 | { |
| 509 | } | 516 | } |
| 510 | 517 | ||
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 701daff5d899..0f86d85a9ce4 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h | |||
| @@ -317,6 +317,10 @@ asmlinkage long sys_restart_syscall(void); | |||
| 317 | asmlinkage long sys_kexec_load(unsigned long entry, unsigned long nr_segments, | 317 | asmlinkage long sys_kexec_load(unsigned long entry, unsigned long nr_segments, |
| 318 | struct kexec_segment __user *segments, | 318 | struct kexec_segment __user *segments, |
| 319 | unsigned long flags); | 319 | unsigned long flags); |
| 320 | asmlinkage long sys_kexec_file_load(int kernel_fd, int initrd_fd, | ||
| 321 | unsigned long cmdline_len, | ||
| 322 | const char __user *cmdline_ptr, | ||
| 323 | unsigned long flags); | ||
| 320 | 324 | ||
| 321 | asmlinkage long sys_exit(int error_code); | 325 | asmlinkage long sys_exit(int error_code); |
| 322 | asmlinkage long sys_exit_group(int error_code); | 326 | asmlinkage long sys_exit_group(int error_code); |
| @@ -802,6 +806,7 @@ asmlinkage long sys_timerfd_settime(int ufd, int flags, | |||
| 802 | asmlinkage long sys_timerfd_gettime(int ufd, struct itimerspec __user *otmr); | 806 | asmlinkage long sys_timerfd_gettime(int ufd, struct itimerspec __user *otmr); |
| 803 | asmlinkage long sys_eventfd(unsigned int count); | 807 | asmlinkage long sys_eventfd(unsigned int count); |
| 804 | asmlinkage long sys_eventfd2(unsigned int count, int flags); | 808 | asmlinkage long sys_eventfd2(unsigned int count, int flags); |
| 809 | asmlinkage long sys_memfd_create(const char __user *uname_ptr, unsigned int flags); | ||
| 805 | asmlinkage long sys_fallocate(int fd, int mode, loff_t offset, loff_t len); | 810 | asmlinkage long sys_fallocate(int fd, int mode, loff_t offset, loff_t len); |
| 806 | asmlinkage long sys_old_readdir(unsigned int, struct old_linux_dirent __user *, unsigned int); | 811 | asmlinkage long sys_old_readdir(unsigned int, struct old_linux_dirent __user *, unsigned int); |
| 807 | asmlinkage long sys_pselect6(int, fd_set __user *, fd_set __user *, | 812 | asmlinkage long sys_pselect6(int, fd_set __user *, fd_set __user *, |
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index 14a8ff2de11e..b7361f831226 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h | |||
| @@ -34,8 +34,6 @@ struct ctl_table_root; | |||
| 34 | struct ctl_table_header; | 34 | struct ctl_table_header; |
| 35 | struct ctl_dir; | 35 | struct ctl_dir; |
| 36 | 36 | ||
| 37 | typedef struct ctl_table ctl_table; | ||
| 38 | |||
| 39 | typedef int proc_handler (struct ctl_table *ctl, int write, | 37 | typedef int proc_handler (struct ctl_table *ctl, int write, |
| 40 | void __user *buffer, size_t *lenp, loff_t *ppos); | 38 | void __user *buffer, size_t *lenp, loff_t *ppos); |
| 41 | 39 | ||
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h index 4836ba3c1cd8..e95372654f09 100644 --- a/include/linux/user_namespace.h +++ b/include/linux/user_namespace.h | |||
| @@ -57,9 +57,9 @@ static inline void put_user_ns(struct user_namespace *ns) | |||
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | struct seq_operations; | 59 | struct seq_operations; |
| 60 | extern struct seq_operations proc_uid_seq_operations; | 60 | extern const struct seq_operations proc_uid_seq_operations; |
| 61 | extern struct seq_operations proc_gid_seq_operations; | 61 | extern const struct seq_operations proc_gid_seq_operations; |
| 62 | extern struct seq_operations proc_projid_seq_operations; | 62 | extern const struct seq_operations proc_projid_seq_operations; |
| 63 | extern ssize_t proc_uid_map_write(struct file *, const char __user *, size_t, loff_t *); | 63 | extern ssize_t proc_uid_map_write(struct file *, const char __user *, size_t, loff_t *); |
| 64 | extern ssize_t proc_gid_map_write(struct file *, const char __user *, size_t, loff_t *); | 64 | extern ssize_t proc_gid_map_write(struct file *, const char __user *, size_t, loff_t *); |
| 65 | extern ssize_t proc_projid_map_write(struct file *, const char __user *, size_t, loff_t *); | 65 | extern ssize_t proc_projid_map_write(struct file *, const char __user *, size_t, loff_t *); |
diff --git a/include/linux/zlib.h b/include/linux/zlib.h index 197abb2a54c5..92dbbd3f6c75 100644 --- a/include/linux/zlib.h +++ b/include/linux/zlib.h | |||
| @@ -83,11 +83,11 @@ struct internal_state; | |||
| 83 | 83 | ||
| 84 | typedef struct z_stream_s { | 84 | typedef struct z_stream_s { |
| 85 | const Byte *next_in; /* next input byte */ | 85 | const Byte *next_in; /* next input byte */ |
| 86 | uInt avail_in; /* number of bytes available at next_in */ | 86 | uLong avail_in; /* number of bytes available at next_in */ |
| 87 | uLong total_in; /* total nb of input bytes read so far */ | 87 | uLong total_in; /* total nb of input bytes read so far */ |
| 88 | 88 | ||
| 89 | Byte *next_out; /* next output byte should be put there */ | 89 | Byte *next_out; /* next output byte should be put there */ |
| 90 | uInt avail_out; /* remaining free space at next_out */ | 90 | uLong avail_out; /* remaining free space at next_out */ |
| 91 | uLong total_out; /* total nb of bytes output so far */ | 91 | uLong total_out; /* total nb of bytes output so far */ |
| 92 | 92 | ||
| 93 | char *msg; /* last error message, NULL if no error */ | 93 | char *msg; /* last error message, NULL if no error */ |
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index e6df23cae7be..261e708010da 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h | |||
| @@ -31,7 +31,7 @@ enum scsi_timeouts { | |||
| 31 | * Like SCSI_MAX_SG_SEGMENTS, but for archs that have sg chaining. This limit | 31 | * Like SCSI_MAX_SG_SEGMENTS, but for archs that have sg chaining. This limit |
| 32 | * is totally arbitrary, a setting of 2048 will get you at least 8mb ios. | 32 | * is totally arbitrary, a setting of 2048 will get you at least 8mb ios. |
| 33 | */ | 33 | */ |
| 34 | #ifdef ARCH_HAS_SG_CHAIN | 34 | #ifdef CONFIG_ARCH_HAS_SG_CHAIN |
| 35 | #define SCSI_MAX_SG_CHAIN_SEGMENTS 2048 | 35 | #define SCSI_MAX_SG_CHAIN_SEGMENTS 2048 |
| 36 | #else | 36 | #else |
| 37 | #define SCSI_MAX_SG_CHAIN_SEGMENTS SCSI_MAX_SG_SEGMENTS | 37 | #define SCSI_MAX_SG_CHAIN_SEGMENTS SCSI_MAX_SG_SEGMENTS |
diff --git a/include/uapi/linux/fcntl.h b/include/uapi/linux/fcntl.h index 074b886c6be0..beed138bd359 100644 --- a/include/uapi/linux/fcntl.h +++ b/include/uapi/linux/fcntl.h | |||
| @@ -28,6 +28,21 @@ | |||
| 28 | #define F_GETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 8) | 28 | #define F_GETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 8) |
| 29 | 29 | ||
| 30 | /* | 30 | /* |
| 31 | * Set/Get seals | ||
| 32 | */ | ||
| 33 | #define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9) | ||
| 34 | #define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10) | ||
| 35 | |||
| 36 | /* | ||
| 37 | * Types of seals | ||
| 38 | */ | ||
| 39 | #define F_SEAL_SEAL 0x0001 /* prevent further seals from being set */ | ||
| 40 | #define F_SEAL_SHRINK 0x0002 /* prevent file from shrinking */ | ||
| 41 | #define F_SEAL_GROW 0x0004 /* prevent file from growing */ | ||
| 42 | #define F_SEAL_WRITE 0x0008 /* prevent writes */ | ||
| 43 | /* (1U << 31) is reserved for signed error codes */ | ||
| 44 | |||
| 45 | /* | ||
| 31 | * Types of directory notifications that may be requested. | 46 | * Types of directory notifications that may be requested. |
| 32 | */ | 47 | */ |
| 33 | #define DN_ACCESS 0x00000001 /* File accessed */ | 48 | #define DN_ACCESS 0x00000001 /* File accessed */ |
diff --git a/include/uapi/linux/kexec.h b/include/uapi/linux/kexec.h index d6629d49a243..6925f5b42f89 100644 --- a/include/uapi/linux/kexec.h +++ b/include/uapi/linux/kexec.h | |||
| @@ -13,6 +13,17 @@ | |||
| 13 | #define KEXEC_PRESERVE_CONTEXT 0x00000002 | 13 | #define KEXEC_PRESERVE_CONTEXT 0x00000002 |
| 14 | #define KEXEC_ARCH_MASK 0xffff0000 | 14 | #define KEXEC_ARCH_MASK 0xffff0000 |
| 15 | 15 | ||
| 16 | /* | ||
| 17 | * Kexec file load interface flags. | ||
| 18 | * KEXEC_FILE_UNLOAD : Unload already loaded kexec/kdump image. | ||
| 19 | * KEXEC_FILE_ON_CRASH : Load/unload operation belongs to kdump image. | ||
| 20 | * KEXEC_FILE_NO_INITRAMFS : No initramfs is being loaded. Ignore the initrd | ||
| 21 | * fd field. | ||
| 22 | */ | ||
| 23 | #define KEXEC_FILE_UNLOAD 0x00000001 | ||
| 24 | #define KEXEC_FILE_ON_CRASH 0x00000002 | ||
| 25 | #define KEXEC_FILE_NO_INITRAMFS 0x00000004 | ||
| 26 | |||
| 16 | /* These values match the ELF architecture values. | 27 | /* These values match the ELF architecture values. |
| 17 | * Unless there is a good reason that should continue to be the case. | 28 | * Unless there is a good reason that should continue to be the case. |
| 18 | */ | 29 | */ |
diff --git a/include/uapi/linux/memfd.h b/include/uapi/linux/memfd.h new file mode 100644 index 000000000000..534e364bda92 --- /dev/null +++ b/include/uapi/linux/memfd.h | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | #ifndef _UAPI_LINUX_MEMFD_H | ||
| 2 | #define _UAPI_LINUX_MEMFD_H | ||
| 3 | |||
| 4 | /* flags for memfd_create(2) (unsigned int) */ | ||
| 5 | #define MFD_CLOEXEC 0x0001U | ||
| 6 | #define MFD_ALLOW_SEALING 0x0002U | ||
| 7 | |||
| 8 | #endif /* _UAPI_LINUX_MEMFD_H */ | ||
diff --git a/init/Kconfig b/init/Kconfig index a291b7ef4738..44f9ed3dae22 100644 --- a/init/Kconfig +++ b/init/Kconfig | |||
| @@ -783,8 +783,13 @@ endchoice | |||
| 783 | 783 | ||
| 784 | endmenu # "RCU Subsystem" | 784 | endmenu # "RCU Subsystem" |
| 785 | 785 | ||
| 786 | config BUILD_BIN2C | ||
| 787 | bool | ||
| 788 | default n | ||
| 789 | |||
| 786 | config IKCONFIG | 790 | config IKCONFIG |
| 787 | tristate "Kernel .config support" | 791 | tristate "Kernel .config support" |
| 792 | select BUILD_BIN2C | ||
| 788 | ---help--- | 793 | ---help--- |
| 789 | This option enables the complete Linux kernel ".config" file | 794 | This option enables the complete Linux kernel ".config" file |
| 790 | contents to be saved in the kernel. It provides documentation | 795 | contents to be saved in the kernel. It provides documentation |
diff --git a/init/do_mounts.c b/init/do_mounts.c index 82f22885c87e..b6237c31b0e2 100644 --- a/init/do_mounts.c +++ b/init/do_mounts.c | |||
| @@ -539,12 +539,6 @@ void __init prepare_namespace(void) | |||
| 539 | { | 539 | { |
| 540 | int is_floppy; | 540 | int is_floppy; |
| 541 | 541 | ||
| 542 | if (root_delay) { | ||
| 543 | printk(KERN_INFO "Waiting %d sec before mounting root device...\n", | ||
| 544 | root_delay); | ||
| 545 | ssleep(root_delay); | ||
| 546 | } | ||
| 547 | |||
| 548 | /* | 542 | /* |
| 549 | * wait for the known devices to complete their probing | 543 | * wait for the known devices to complete their probing |
| 550 | * | 544 | * |
| @@ -571,6 +565,12 @@ void __init prepare_namespace(void) | |||
| 571 | if (initrd_load()) | 565 | if (initrd_load()) |
| 572 | goto out; | 566 | goto out; |
| 573 | 567 | ||
| 568 | if (root_delay) { | ||
| 569 | pr_info("Waiting %d sec before mounting root device...\n", | ||
| 570 | root_delay); | ||
| 571 | ssleep(root_delay); | ||
| 572 | } | ||
| 573 | |||
| 574 | /* wait for any asynchronous scanning to complete */ | 574 | /* wait for any asynchronous scanning to complete */ |
| 575 | if ((ROOT_DEV == 0) && root_wait) { | 575 | if ((ROOT_DEV == 0) && root_wait) { |
| 576 | printk(KERN_INFO "Waiting for root device %s...\n", | 576 | printk(KERN_INFO "Waiting for root device %s...\n", |
diff --git a/init/do_mounts_rd.c b/init/do_mounts_rd.c index a8227022e3a0..e5d059e8aa11 100644 --- a/init/do_mounts_rd.c +++ b/init/do_mounts_rd.c | |||
| @@ -311,9 +311,9 @@ static int exit_code; | |||
| 311 | static int decompress_error; | 311 | static int decompress_error; |
| 312 | static int crd_infd, crd_outfd; | 312 | static int crd_infd, crd_outfd; |
| 313 | 313 | ||
| 314 | static int __init compr_fill(void *buf, unsigned int len) | 314 | static long __init compr_fill(void *buf, unsigned long len) |
| 315 | { | 315 | { |
| 316 | int r = sys_read(crd_infd, buf, len); | 316 | long r = sys_read(crd_infd, buf, len); |
| 317 | if (r < 0) | 317 | if (r < 0) |
| 318 | printk(KERN_ERR "RAMDISK: error while reading compressed data"); | 318 | printk(KERN_ERR "RAMDISK: error while reading compressed data"); |
| 319 | else if (r == 0) | 319 | else if (r == 0) |
| @@ -321,13 +321,13 @@ static int __init compr_fill(void *buf, unsigned int len) | |||
| 321 | return r; | 321 | return r; |
| 322 | } | 322 | } |
| 323 | 323 | ||
| 324 | static int __init compr_flush(void *window, unsigned int outcnt) | 324 | static long __init compr_flush(void *window, unsigned long outcnt) |
| 325 | { | 325 | { |
| 326 | int written = sys_write(crd_outfd, window, outcnt); | 326 | long written = sys_write(crd_outfd, window, outcnt); |
| 327 | if (written != outcnt) { | 327 | if (written != outcnt) { |
| 328 | if (decompress_error == 0) | 328 | if (decompress_error == 0) |
| 329 | printk(KERN_ERR | 329 | printk(KERN_ERR |
| 330 | "RAMDISK: incomplete write (%d != %d)\n", | 330 | "RAMDISK: incomplete write (%ld != %ld)\n", |
| 331 | written, outcnt); | 331 | written, outcnt); |
| 332 | decompress_error = 1; | 332 | decompress_error = 1; |
| 333 | return -1; | 333 | return -1; |
diff --git a/init/initramfs.c b/init/initramfs.c index a8497fab1c3d..bece48c3461e 100644 --- a/init/initramfs.c +++ b/init/initramfs.c | |||
| @@ -19,6 +19,29 @@ | |||
| 19 | #include <linux/syscalls.h> | 19 | #include <linux/syscalls.h> |
| 20 | #include <linux/utime.h> | 20 | #include <linux/utime.h> |
| 21 | 21 | ||
| 22 | static ssize_t __init xwrite(int fd, const char *p, size_t count) | ||
| 23 | { | ||
| 24 | ssize_t out = 0; | ||
| 25 | |||
| 26 | /* sys_write only can write MAX_RW_COUNT aka 2G-4K bytes at most */ | ||
| 27 | while (count) { | ||
| 28 | ssize_t rv = sys_write(fd, p, count); | ||
| 29 | |||
| 30 | if (rv < 0) { | ||
| 31 | if (rv == -EINTR || rv == -EAGAIN) | ||
| 32 | continue; | ||
| 33 | return out ? out : rv; | ||
| 34 | } else if (rv == 0) | ||
| 35 | break; | ||
| 36 | |||
| 37 | p += rv; | ||
| 38 | out += rv; | ||
| 39 | count -= rv; | ||
| 40 | } | ||
| 41 | |||
| 42 | return out; | ||
| 43 | } | ||
| 44 | |||
| 22 | static __initdata char *message; | 45 | static __initdata char *message; |
| 23 | static void __init error(char *x) | 46 | static void __init error(char *x) |
| 24 | { | 47 | { |
| @@ -174,7 +197,7 @@ static __initdata enum state { | |||
| 174 | } state, next_state; | 197 | } state, next_state; |
| 175 | 198 | ||
| 176 | static __initdata char *victim; | 199 | static __initdata char *victim; |
| 177 | static __initdata unsigned count; | 200 | static unsigned long count __initdata; |
| 178 | static __initdata loff_t this_header, next_header; | 201 | static __initdata loff_t this_header, next_header; |
| 179 | 202 | ||
| 180 | static inline void __init eat(unsigned n) | 203 | static inline void __init eat(unsigned n) |
| @@ -186,7 +209,7 @@ static inline void __init eat(unsigned n) | |||
| 186 | 209 | ||
| 187 | static __initdata char *vcollected; | 210 | static __initdata char *vcollected; |
| 188 | static __initdata char *collected; | 211 | static __initdata char *collected; |
| 189 | static __initdata int remains; | 212 | static long remains __initdata; |
| 190 | static __initdata char *collect; | 213 | static __initdata char *collect; |
| 191 | 214 | ||
| 192 | static void __init read_into(char *buf, unsigned size, enum state next) | 215 | static void __init read_into(char *buf, unsigned size, enum state next) |
| @@ -213,7 +236,7 @@ static int __init do_start(void) | |||
| 213 | 236 | ||
| 214 | static int __init do_collect(void) | 237 | static int __init do_collect(void) |
| 215 | { | 238 | { |
| 216 | unsigned n = remains; | 239 | unsigned long n = remains; |
| 217 | if (count < n) | 240 | if (count < n) |
| 218 | n = count; | 241 | n = count; |
| 219 | memcpy(collect, victim, n); | 242 | memcpy(collect, victim, n); |
| @@ -346,7 +369,8 @@ static int __init do_name(void) | |||
| 346 | static int __init do_copy(void) | 369 | static int __init do_copy(void) |
| 347 | { | 370 | { |
| 348 | if (count >= body_len) { | 371 | if (count >= body_len) { |
| 349 | sys_write(wfd, victim, body_len); | 372 | if (xwrite(wfd, victim, body_len) != body_len) |
| 373 | error("write error"); | ||
| 350 | sys_close(wfd); | 374 | sys_close(wfd); |
| 351 | do_utime(vcollected, mtime); | 375 | do_utime(vcollected, mtime); |
| 352 | kfree(vcollected); | 376 | kfree(vcollected); |
| @@ -354,7 +378,8 @@ static int __init do_copy(void) | |||
| 354 | state = SkipIt; | 378 | state = SkipIt; |
| 355 | return 0; | 379 | return 0; |
| 356 | } else { | 380 | } else { |
| 357 | sys_write(wfd, victim, count); | 381 | if (xwrite(wfd, victim, count) != count) |
| 382 | error("write error"); | ||
| 358 | body_len -= count; | 383 | body_len -= count; |
| 359 | eat(count); | 384 | eat(count); |
| 360 | return 1; | 385 | return 1; |
| @@ -384,7 +409,7 @@ static __initdata int (*actions[])(void) = { | |||
| 384 | [Reset] = do_reset, | 409 | [Reset] = do_reset, |
| 385 | }; | 410 | }; |
| 386 | 411 | ||
| 387 | static int __init write_buffer(char *buf, unsigned len) | 412 | static long __init write_buffer(char *buf, unsigned long len) |
| 388 | { | 413 | { |
| 389 | count = len; | 414 | count = len; |
| 390 | victim = buf; | 415 | victim = buf; |
| @@ -394,11 +419,11 @@ static int __init write_buffer(char *buf, unsigned len) | |||
| 394 | return len - count; | 419 | return len - count; |
| 395 | } | 420 | } |
| 396 | 421 | ||
| 397 | static int __init flush_buffer(void *bufv, unsigned len) | 422 | static long __init flush_buffer(void *bufv, unsigned long len) |
| 398 | { | 423 | { |
| 399 | char *buf = (char *) bufv; | 424 | char *buf = (char *) bufv; |
| 400 | int written; | 425 | long written; |
| 401 | int origLen = len; | 426 | long origLen = len; |
| 402 | if (message) | 427 | if (message) |
| 403 | return -1; | 428 | return -1; |
| 404 | while ((written = write_buffer(buf, len)) < len && !message) { | 429 | while ((written = write_buffer(buf, len)) < len && !message) { |
| @@ -417,13 +442,13 @@ static int __init flush_buffer(void *bufv, unsigned len) | |||
| 417 | return origLen; | 442 | return origLen; |
| 418 | } | 443 | } |
| 419 | 444 | ||
| 420 | static unsigned my_inptr; /* index of next byte to be processed in inbuf */ | 445 | static unsigned long my_inptr; /* index of next byte to be processed in inbuf */ |
| 421 | 446 | ||
| 422 | #include <linux/decompress/generic.h> | 447 | #include <linux/decompress/generic.h> |
| 423 | 448 | ||
| 424 | static char * __init unpack_to_rootfs(char *buf, unsigned len) | 449 | static char * __init unpack_to_rootfs(char *buf, unsigned long len) |
| 425 | { | 450 | { |
| 426 | int written, res; | 451 | long written; |
| 427 | decompress_fn decompress; | 452 | decompress_fn decompress; |
| 428 | const char *compress_name; | 453 | const char *compress_name; |
| 429 | static __initdata char msg_buf[64]; | 454 | static __initdata char msg_buf[64]; |
| @@ -457,7 +482,7 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len) | |||
| 457 | decompress = decompress_method(buf, len, &compress_name); | 482 | decompress = decompress_method(buf, len, &compress_name); |
| 458 | pr_debug("Detected %s compressed data\n", compress_name); | 483 | pr_debug("Detected %s compressed data\n", compress_name); |
| 459 | if (decompress) { | 484 | if (decompress) { |
| 460 | res = decompress(buf, len, NULL, flush_buffer, NULL, | 485 | int res = decompress(buf, len, NULL, flush_buffer, NULL, |
| 461 | &my_inptr, error); | 486 | &my_inptr, error); |
| 462 | if (res) | 487 | if (res) |
| 463 | error("decompressor failed"); | 488 | error("decompressor failed"); |
| @@ -603,8 +628,13 @@ static int __init populate_rootfs(void) | |||
| 603 | fd = sys_open("/initrd.image", | 628 | fd = sys_open("/initrd.image", |
| 604 | O_WRONLY|O_CREAT, 0700); | 629 | O_WRONLY|O_CREAT, 0700); |
| 605 | if (fd >= 0) { | 630 | if (fd >= 0) { |
| 606 | sys_write(fd, (char *)initrd_start, | 631 | ssize_t written = xwrite(fd, (char *)initrd_start, |
| 607 | initrd_end - initrd_start); | 632 | initrd_end - initrd_start); |
| 633 | |||
| 634 | if (written != initrd_end - initrd_start) | ||
| 635 | pr_err("/initrd.image: incomplete write (%zd != %ld)\n", | ||
| 636 | written, initrd_end - initrd_start); | ||
| 637 | |||
| 608 | sys_close(fd); | 638 | sys_close(fd); |
| 609 | free_initrd(); | 639 | free_initrd(); |
| 610 | } | 640 | } |
diff --git a/init/main.c b/init/main.c index e8ae1fef0908..bb1aed928f21 100644 --- a/init/main.c +++ b/init/main.c | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | * GK 2/5/95 - Changed to support mounting root fs via NFS | 6 | * GK 2/5/95 - Changed to support mounting root fs via NFS |
| 7 | * Added initrd & change_root: Werner Almesberger & Hans Lermen, Feb '96 | 7 | * Added initrd & change_root: Werner Almesberger & Hans Lermen, Feb '96 |
| 8 | * Moan early if gcc is old, avoiding bogus kernels - Paul Gortmaker, May '96 | 8 | * Moan early if gcc is old, avoiding bogus kernels - Paul Gortmaker, May '96 |
| 9 | * Simplified starting of init: Michael A. Griffith <grif@acm.org> | 9 | * Simplified starting of init: Michael A. Griffith <grif@acm.org> |
| 10 | */ | 10 | */ |
| 11 | 11 | ||
| 12 | #define DEBUG /* Enable initcall_debug */ | 12 | #define DEBUG /* Enable initcall_debug */ |
| @@ -136,7 +136,7 @@ static char *ramdisk_execute_command; | |||
| 136 | * Used to generate warnings if static_key manipulation functions are used | 136 | * Used to generate warnings if static_key manipulation functions are used |
| 137 | * before jump_label_init is called. | 137 | * before jump_label_init is called. |
| 138 | */ | 138 | */ |
| 139 | bool static_key_initialized __read_mostly = false; | 139 | bool static_key_initialized __read_mostly; |
| 140 | EXPORT_SYMBOL_GPL(static_key_initialized); | 140 | EXPORT_SYMBOL_GPL(static_key_initialized); |
| 141 | 141 | ||
| 142 | /* | 142 | /* |
| @@ -159,8 +159,8 @@ static int __init set_reset_devices(char *str) | |||
| 159 | 159 | ||
| 160 | __setup("reset_devices", set_reset_devices); | 160 | __setup("reset_devices", set_reset_devices); |
| 161 | 161 | ||
| 162 | static const char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, }; | 162 | static const char *argv_init[MAX_INIT_ARGS+2] = { "init", NULL, }; |
| 163 | const char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, }; | 163 | const char *envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, }; |
| 164 | static const char *panic_later, *panic_param; | 164 | static const char *panic_later, *panic_param; |
| 165 | 165 | ||
| 166 | extern const struct obs_kernel_param __setup_start[], __setup_end[]; | 166 | extern const struct obs_kernel_param __setup_start[], __setup_end[]; |
| @@ -199,7 +199,6 @@ static int __init obsolete_checksetup(char *line) | |||
| 199 | * still work even if initially too large, it will just take slightly longer | 199 | * still work even if initially too large, it will just take slightly longer |
| 200 | */ | 200 | */ |
| 201 | unsigned long loops_per_jiffy = (1<<12); | 201 | unsigned long loops_per_jiffy = (1<<12); |
| 202 | |||
| 203 | EXPORT_SYMBOL(loops_per_jiffy); | 202 | EXPORT_SYMBOL(loops_per_jiffy); |
| 204 | 203 | ||
| 205 | static int __init debug_kernel(char *str) | 204 | static int __init debug_kernel(char *str) |
| @@ -376,8 +375,8 @@ static void __init setup_command_line(char *command_line) | |||
| 376 | initcall_command_line = | 375 | initcall_command_line = |
| 377 | memblock_virt_alloc(strlen(boot_command_line) + 1, 0); | 376 | memblock_virt_alloc(strlen(boot_command_line) + 1, 0); |
| 378 | static_command_line = memblock_virt_alloc(strlen(command_line) + 1, 0); | 377 | static_command_line = memblock_virt_alloc(strlen(command_line) + 1, 0); |
| 379 | strcpy (saved_command_line, boot_command_line); | 378 | strcpy(saved_command_line, boot_command_line); |
| 380 | strcpy (static_command_line, command_line); | 379 | strcpy(static_command_line, command_line); |
| 381 | } | 380 | } |
| 382 | 381 | ||
| 383 | /* | 382 | /* |
| @@ -445,8 +444,8 @@ void __init parse_early_options(char *cmdline) | |||
| 445 | /* Arch code calls this early on, or if not, just before other parsing. */ | 444 | /* Arch code calls this early on, or if not, just before other parsing. */ |
| 446 | void __init parse_early_param(void) | 445 | void __init parse_early_param(void) |
| 447 | { | 446 | { |
| 448 | static __initdata int done = 0; | 447 | static int done __initdata; |
| 449 | static __initdata char tmp_cmdline[COMMAND_LINE_SIZE]; | 448 | static char tmp_cmdline[COMMAND_LINE_SIZE] __initdata; |
| 450 | 449 | ||
| 451 | if (done) | 450 | if (done) |
| 452 | return; | 451 | return; |
| @@ -500,7 +499,8 @@ static void __init mm_init(void) | |||
| 500 | 499 | ||
| 501 | asmlinkage __visible void __init start_kernel(void) | 500 | asmlinkage __visible void __init start_kernel(void) |
| 502 | { | 501 | { |
| 503 | char * command_line, *after_dashes; | 502 | char *command_line; |
| 503 | char *after_dashes; | ||
| 504 | extern const struct kernel_param __start___param[], __stop___param[]; | 504 | extern const struct kernel_param __start___param[], __stop___param[]; |
| 505 | 505 | ||
| 506 | /* | 506 | /* |
| @@ -572,7 +572,8 @@ asmlinkage __visible void __init start_kernel(void) | |||
| 572 | * fragile until we cpu_idle() for the first time. | 572 | * fragile until we cpu_idle() for the first time. |
| 573 | */ | 573 | */ |
| 574 | preempt_disable(); | 574 | preempt_disable(); |
| 575 | if (WARN(!irqs_disabled(), "Interrupts were enabled *very* early, fixing it\n")) | 575 | if (WARN(!irqs_disabled(), |
| 576 | "Interrupts were enabled *very* early, fixing it\n")) | ||
| 576 | local_irq_disable(); | 577 | local_irq_disable(); |
| 577 | idr_init_cache(); | 578 | idr_init_cache(); |
| 578 | rcu_init(); | 579 | rcu_init(); |
| @@ -178,6 +178,7 @@ static void shm_rcu_free(struct rcu_head *head) | |||
| 178 | 178 | ||
| 179 | static inline void shm_rmid(struct ipc_namespace *ns, struct shmid_kernel *s) | 179 | static inline void shm_rmid(struct ipc_namespace *ns, struct shmid_kernel *s) |
| 180 | { | 180 | { |
| 181 | list_del(&s->shm_clist); | ||
| 181 | ipc_rmid(&shm_ids(ns), &s->shm_perm); | 182 | ipc_rmid(&shm_ids(ns), &s->shm_perm); |
| 182 | } | 183 | } |
| 183 | 184 | ||
| @@ -268,37 +269,6 @@ static void shm_close(struct vm_area_struct *vma) | |||
| 268 | } | 269 | } |
| 269 | 270 | ||
| 270 | /* Called with ns->shm_ids(ns).rwsem locked */ | 271 | /* Called with ns->shm_ids(ns).rwsem locked */ |
| 271 | static int shm_try_destroy_current(int id, void *p, void *data) | ||
| 272 | { | ||
| 273 | struct ipc_namespace *ns = data; | ||
| 274 | struct kern_ipc_perm *ipcp = p; | ||
| 275 | struct shmid_kernel *shp = container_of(ipcp, struct shmid_kernel, shm_perm); | ||
| 276 | |||
| 277 | if (shp->shm_creator != current) | ||
| 278 | return 0; | ||
| 279 | |||
| 280 | /* | ||
| 281 | * Mark it as orphaned to destroy the segment when | ||
| 282 | * kernel.shm_rmid_forced is changed. | ||
| 283 | * It is noop if the following shm_may_destroy() returns true. | ||
| 284 | */ | ||
| 285 | shp->shm_creator = NULL; | ||
| 286 | |||
| 287 | /* | ||
| 288 | * Don't even try to destroy it. If shm_rmid_forced=0 and IPC_RMID | ||
| 289 | * is not set, it shouldn't be deleted here. | ||
| 290 | */ | ||
| 291 | if (!ns->shm_rmid_forced) | ||
| 292 | return 0; | ||
| 293 | |||
| 294 | if (shm_may_destroy(ns, shp)) { | ||
| 295 | shm_lock_by_ptr(shp); | ||
| 296 | shm_destroy(ns, shp); | ||
| 297 | } | ||
| 298 | return 0; | ||
| 299 | } | ||
| 300 | |||
| 301 | /* Called with ns->shm_ids(ns).rwsem locked */ | ||
| 302 | static int shm_try_destroy_orphaned(int id, void *p, void *data) | 272 | static int shm_try_destroy_orphaned(int id, void *p, void *data) |
| 303 | { | 273 | { |
| 304 | struct ipc_namespace *ns = data; | 274 | struct ipc_namespace *ns = data; |
| @@ -329,18 +299,50 @@ void shm_destroy_orphaned(struct ipc_namespace *ns) | |||
| 329 | up_write(&shm_ids(ns).rwsem); | 299 | up_write(&shm_ids(ns).rwsem); |
| 330 | } | 300 | } |
| 331 | 301 | ||
| 332 | 302 | /* Locking assumes this will only be called with task == current */ | |
| 333 | void exit_shm(struct task_struct *task) | 303 | void exit_shm(struct task_struct *task) |
| 334 | { | 304 | { |
| 335 | struct ipc_namespace *ns = task->nsproxy->ipc_ns; | 305 | struct ipc_namespace *ns = task->nsproxy->ipc_ns; |
| 306 | struct shmid_kernel *shp, *n; | ||
| 336 | 307 | ||
| 337 | if (shm_ids(ns).in_use == 0) | 308 | if (list_empty(&task->sysvshm.shm_clist)) |
| 338 | return; | 309 | return; |
| 339 | 310 | ||
| 340 | /* Destroy all already created segments, but not mapped yet */ | 311 | /* |
| 312 | * If kernel.shm_rmid_forced is not set then only keep track of | ||
| 313 | * which shmids are orphaned, so that a later set of the sysctl | ||
| 314 | * can clean them up. | ||
| 315 | */ | ||
| 316 | if (!ns->shm_rmid_forced) { | ||
| 317 | down_read(&shm_ids(ns).rwsem); | ||
| 318 | list_for_each_entry(shp, &task->sysvshm.shm_clist, shm_clist) | ||
| 319 | shp->shm_creator = NULL; | ||
| 320 | /* | ||
| 321 | * Only under read lock but we are only called on current | ||
| 322 | * so no entry on the list will be shared. | ||
| 323 | */ | ||
| 324 | list_del(&task->sysvshm.shm_clist); | ||
| 325 | up_read(&shm_ids(ns).rwsem); | ||
| 326 | return; | ||
| 327 | } | ||
| 328 | |||
| 329 | /* | ||
| 330 | * Destroy all already created segments, that were not yet mapped, | ||
| 331 | * and mark any mapped as orphan to cover the sysctl toggling. | ||
| 332 | * Destroy is skipped if shm_may_destroy() returns false. | ||
| 333 | */ | ||
| 341 | down_write(&shm_ids(ns).rwsem); | 334 | down_write(&shm_ids(ns).rwsem); |
| 342 | if (shm_ids(ns).in_use) | 335 | list_for_each_entry_safe(shp, n, &task->sysvshm.shm_clist, shm_clist) { |
| 343 | idr_for_each(&shm_ids(ns).ipcs_idr, &shm_try_destroy_current, ns); | 336 | shp->shm_creator = NULL; |
| 337 | |||
| 338 | if (shm_may_destroy(ns, shp)) { | ||
| 339 | shm_lock_by_ptr(shp); | ||
| 340 | shm_destroy(ns, shp); | ||
| 341 | } | ||
| 342 | } | ||
| 343 | |||
| 344 | /* Remove the list head from any segments still attached. */ | ||
| 345 | list_del(&task->sysvshm.shm_clist); | ||
| 344 | up_write(&shm_ids(ns).rwsem); | 346 | up_write(&shm_ids(ns).rwsem); |
| 345 | } | 347 | } |
| 346 | 348 | ||
| @@ -561,6 +563,7 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params) | |||
| 561 | shp->shm_nattch = 0; | 563 | shp->shm_nattch = 0; |
| 562 | shp->shm_file = file; | 564 | shp->shm_file = file; |
| 563 | shp->shm_creator = current; | 565 | shp->shm_creator = current; |
| 566 | list_add(&shp->shm_clist, ¤t->sysvshm.shm_clist); | ||
| 564 | 567 | ||
| 565 | /* | 568 | /* |
| 566 | * shmid gets reported as "inode#" in /proc/pid/maps. | 569 | * shmid gets reported as "inode#" in /proc/pid/maps. |
diff --git a/kernel/Makefile b/kernel/Makefile index 0026cf531769..dc5c77544fd6 100644 --- a/kernel/Makefile +++ b/kernel/Makefile | |||
| @@ -105,7 +105,7 @@ targets += config_data.gz | |||
| 105 | $(obj)/config_data.gz: $(KCONFIG_CONFIG) FORCE | 105 | $(obj)/config_data.gz: $(KCONFIG_CONFIG) FORCE |
| 106 | $(call if_changed,gzip) | 106 | $(call if_changed,gzip) |
| 107 | 107 | ||
| 108 | filechk_ikconfiggz = (echo "static const char kernel_config_data[] __used = MAGIC_START"; cat $< | scripts/bin2c; echo "MAGIC_END;") | 108 | filechk_ikconfiggz = (echo "static const char kernel_config_data[] __used = MAGIC_START"; cat $< | scripts/basic/bin2c; echo "MAGIC_END;") |
| 109 | targets += config_data.h | 109 | targets += config_data.h |
| 110 | $(obj)/config_data.h: $(obj)/config_data.gz FORCE | 110 | $(obj)/config_data.h: $(obj)/config_data.gz FORCE |
| 111 | $(call filechk,ikconfiggz) | 111 | $(call filechk,ikconfiggz) |
diff --git a/kernel/acct.c b/kernel/acct.c index a1844f14c6d6..51793520566f 100644 --- a/kernel/acct.c +++ b/kernel/acct.c | |||
| @@ -141,12 +141,12 @@ static int check_free_space(struct bsd_acct_struct *acct, struct file *file) | |||
| 141 | if (acct->active) { | 141 | if (acct->active) { |
| 142 | if (act < 0) { | 142 | if (act < 0) { |
| 143 | acct->active = 0; | 143 | acct->active = 0; |
| 144 | printk(KERN_INFO "Process accounting paused\n"); | 144 | pr_info("Process accounting paused\n"); |
| 145 | } | 145 | } |
| 146 | } else { | 146 | } else { |
| 147 | if (act > 0) { | 147 | if (act > 0) { |
| 148 | acct->active = 1; | 148 | acct->active = 1; |
| 149 | printk(KERN_INFO "Process accounting resumed\n"); | 149 | pr_info("Process accounting resumed\n"); |
| 150 | } | 150 | } |
| 151 | } | 151 | } |
| 152 | 152 | ||
| @@ -261,6 +261,7 @@ SYSCALL_DEFINE1(acct, const char __user *, name) | |||
| 261 | 261 | ||
| 262 | if (name) { | 262 | if (name) { |
| 263 | struct filename *tmp = getname(name); | 263 | struct filename *tmp = getname(name); |
| 264 | |||
| 264 | if (IS_ERR(tmp)) | 265 | if (IS_ERR(tmp)) |
| 265 | return PTR_ERR(tmp); | 266 | return PTR_ERR(tmp); |
| 266 | error = acct_on(tmp); | 267 | error = acct_on(tmp); |
| @@ -376,7 +377,7 @@ static comp_t encode_comp_t(unsigned long value) | |||
| 376 | return exp; | 377 | return exp; |
| 377 | } | 378 | } |
| 378 | 379 | ||
| 379 | #if ACCT_VERSION==1 || ACCT_VERSION==2 | 380 | #if ACCT_VERSION == 1 || ACCT_VERSION == 2 |
| 380 | /* | 381 | /* |
| 381 | * encode an u64 into a comp2_t (24 bits) | 382 | * encode an u64 into a comp2_t (24 bits) |
| 382 | * | 383 | * |
| @@ -389,7 +390,7 @@ static comp_t encode_comp_t(unsigned long value) | |||
| 389 | #define MANTSIZE2 20 /* 20 bit mantissa. */ | 390 | #define MANTSIZE2 20 /* 20 bit mantissa. */ |
| 390 | #define EXPSIZE2 5 /* 5 bit base 2 exponent. */ | 391 | #define EXPSIZE2 5 /* 5 bit base 2 exponent. */ |
| 391 | #define MAXFRACT2 ((1ul << MANTSIZE2) - 1) /* Maximum fractional value. */ | 392 | #define MAXFRACT2 ((1ul << MANTSIZE2) - 1) /* Maximum fractional value. */ |
| 392 | #define MAXEXP2 ((1 <<EXPSIZE2) - 1) /* Maximum exponent. */ | 393 | #define MAXEXP2 ((1 << EXPSIZE2) - 1) /* Maximum exponent. */ |
| 393 | 394 | ||
| 394 | static comp2_t encode_comp2_t(u64 value) | 395 | static comp2_t encode_comp2_t(u64 value) |
| 395 | { | 396 | { |
| @@ -420,7 +421,7 @@ static comp2_t encode_comp2_t(u64 value) | |||
| 420 | } | 421 | } |
| 421 | #endif | 422 | #endif |
| 422 | 423 | ||
| 423 | #if ACCT_VERSION==3 | 424 | #if ACCT_VERSION == 3 |
| 424 | /* | 425 | /* |
| 425 | * encode an u64 into a 32 bit IEEE float | 426 | * encode an u64 into a 32 bit IEEE float |
| 426 | */ | 427 | */ |
| @@ -429,8 +430,9 @@ static u32 encode_float(u64 value) | |||
| 429 | unsigned exp = 190; | 430 | unsigned exp = 190; |
| 430 | unsigned u; | 431 | unsigned u; |
| 431 | 432 | ||
| 432 | if (value==0) return 0; | 433 | if (value == 0) |
| 433 | while ((s64)value > 0){ | 434 | return 0; |
| 435 | while ((s64)value > 0) { | ||
| 434 | value <<= 1; | 436 | value <<= 1; |
| 435 | exp--; | 437 | exp--; |
| 436 | } | 438 | } |
| @@ -486,16 +488,17 @@ static void do_acct_process(struct bsd_acct_struct *acct, | |||
| 486 | run_time -= current->group_leader->start_time; | 488 | run_time -= current->group_leader->start_time; |
| 487 | /* convert nsec -> AHZ */ | 489 | /* convert nsec -> AHZ */ |
| 488 | elapsed = nsec_to_AHZ(run_time); | 490 | elapsed = nsec_to_AHZ(run_time); |
| 489 | #if ACCT_VERSION==3 | 491 | #if ACCT_VERSION == 3 |
| 490 | ac.ac_etime = encode_float(elapsed); | 492 | ac.ac_etime = encode_float(elapsed); |
| 491 | #else | 493 | #else |
| 492 | ac.ac_etime = encode_comp_t(elapsed < (unsigned long) -1l ? | 494 | ac.ac_etime = encode_comp_t(elapsed < (unsigned long) -1l ? |
| 493 | (unsigned long) elapsed : (unsigned long) -1l); | 495 | (unsigned long) elapsed : (unsigned long) -1l); |
| 494 | #endif | 496 | #endif |
| 495 | #if ACCT_VERSION==1 || ACCT_VERSION==2 | 497 | #if ACCT_VERSION == 1 || ACCT_VERSION == 2 |
| 496 | { | 498 | { |
| 497 | /* new enlarged etime field */ | 499 | /* new enlarged etime field */ |
| 498 | comp2_t etime = encode_comp2_t(elapsed); | 500 | comp2_t etime = encode_comp2_t(elapsed); |
| 501 | |||
| 499 | ac.ac_etime_hi = etime >> 16; | 502 | ac.ac_etime_hi = etime >> 16; |
| 500 | ac.ac_etime_lo = (u16) etime; | 503 | ac.ac_etime_lo = (u16) etime; |
| 501 | } | 504 | } |
| @@ -505,15 +508,15 @@ static void do_acct_process(struct bsd_acct_struct *acct, | |||
| 505 | /* we really need to bite the bullet and change layout */ | 508 | /* we really need to bite the bullet and change layout */ |
| 506 | ac.ac_uid = from_kuid_munged(file->f_cred->user_ns, orig_cred->uid); | 509 | ac.ac_uid = from_kuid_munged(file->f_cred->user_ns, orig_cred->uid); |
| 507 | ac.ac_gid = from_kgid_munged(file->f_cred->user_ns, orig_cred->gid); | 510 | ac.ac_gid = from_kgid_munged(file->f_cred->user_ns, orig_cred->gid); |
| 508 | #if ACCT_VERSION==2 | 511 | #if ACCT_VERSION == 2 |
| 509 | ac.ac_ahz = AHZ; | 512 | ac.ac_ahz = AHZ; |
| 510 | #endif | 513 | #endif |
| 511 | #if ACCT_VERSION==1 || ACCT_VERSION==2 | 514 | #if ACCT_VERSION == 1 || ACCT_VERSION == 2 |
| 512 | /* backward-compatible 16 bit fields */ | 515 | /* backward-compatible 16 bit fields */ |
| 513 | ac.ac_uid16 = ac.ac_uid; | 516 | ac.ac_uid16 = ac.ac_uid; |
| 514 | ac.ac_gid16 = ac.ac_gid; | 517 | ac.ac_gid16 = ac.ac_gid; |
| 515 | #endif | 518 | #endif |
| 516 | #if ACCT_VERSION==3 | 519 | #if ACCT_VERSION == 3 |
| 517 | ac.ac_pid = task_tgid_nr_ns(current, ns); | 520 | ac.ac_pid = task_tgid_nr_ns(current, ns); |
| 518 | rcu_read_lock(); | 521 | rcu_read_lock(); |
| 519 | ac.ac_ppid = task_tgid_nr_ns(rcu_dereference(current->real_parent), ns); | 522 | ac.ac_ppid = task_tgid_nr_ns(rcu_dereference(current->real_parent), ns); |
| @@ -574,6 +577,7 @@ void acct_collect(long exitcode, int group_dead) | |||
| 574 | 577 | ||
| 575 | if (group_dead && current->mm) { | 578 | if (group_dead && current->mm) { |
| 576 | struct vm_area_struct *vma; | 579 | struct vm_area_struct *vma; |
| 580 | |||
| 577 | down_read(¤t->mm->mmap_sem); | 581 | down_read(¤t->mm->mmap_sem); |
| 578 | vma = current->mm->mmap; | 582 | vma = current->mm->mmap; |
| 579 | while (vma) { | 583 | while (vma) { |
diff --git a/kernel/bounds.c b/kernel/bounds.c index 9fd4246b04b8..e1d1d1952bfa 100644 --- a/kernel/bounds.c +++ b/kernel/bounds.c | |||
| @@ -9,7 +9,6 @@ | |||
| 9 | #include <linux/page-flags.h> | 9 | #include <linux/page-flags.h> |
| 10 | #include <linux/mmzone.h> | 10 | #include <linux/mmzone.h> |
| 11 | #include <linux/kbuild.h> | 11 | #include <linux/kbuild.h> |
| 12 | #include <linux/page_cgroup.h> | ||
| 13 | #include <linux/log2.h> | 12 | #include <linux/log2.h> |
| 14 | #include <linux/spinlock_types.h> | 13 | #include <linux/spinlock_types.h> |
| 15 | 14 | ||
| @@ -18,7 +17,6 @@ void foo(void) | |||
| 18 | /* The enum constants to put into include/generated/bounds.h */ | 17 | /* The enum constants to put into include/generated/bounds.h */ |
| 19 | DEFINE(NR_PAGEFLAGS, __NR_PAGEFLAGS); | 18 | DEFINE(NR_PAGEFLAGS, __NR_PAGEFLAGS); |
| 20 | DEFINE(MAX_NR_ZONES, __MAX_NR_ZONES); | 19 | DEFINE(MAX_NR_ZONES, __MAX_NR_ZONES); |
| 21 | DEFINE(NR_PCG_FLAGS, __NR_PCG_FLAGS); | ||
| 22 | #ifdef CONFIG_SMP | 20 | #ifdef CONFIG_SMP |
| 23 | DEFINE(NR_CPUS_BITS, ilog2(CONFIG_NR_CPUS)); | 21 | DEFINE(NR_CPUS_BITS, ilog2(CONFIG_NR_CPUS)); |
| 24 | #endif | 22 | #endif |
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c index 6f3254e8c137..1d0af8a2c646 100644 --- a/kernel/events/uprobes.c +++ b/kernel/events/uprobes.c | |||
| @@ -167,6 +167,11 @@ static int __replace_page(struct vm_area_struct *vma, unsigned long addr, | |||
| 167 | /* For mmu_notifiers */ | 167 | /* For mmu_notifiers */ |
| 168 | const unsigned long mmun_start = addr; | 168 | const unsigned long mmun_start = addr; |
| 169 | const unsigned long mmun_end = addr + PAGE_SIZE; | 169 | const unsigned long mmun_end = addr + PAGE_SIZE; |
| 170 | struct mem_cgroup *memcg; | ||
| 171 | |||
| 172 | err = mem_cgroup_try_charge(kpage, vma->vm_mm, GFP_KERNEL, &memcg); | ||
| 173 | if (err) | ||
| 174 | return err; | ||
| 170 | 175 | ||
| 171 | /* For try_to_free_swap() and munlock_vma_page() below */ | 176 | /* For try_to_free_swap() and munlock_vma_page() below */ |
| 172 | lock_page(page); | 177 | lock_page(page); |
| @@ -179,6 +184,8 @@ static int __replace_page(struct vm_area_struct *vma, unsigned long addr, | |||
| 179 | 184 | ||
| 180 | get_page(kpage); | 185 | get_page(kpage); |
| 181 | page_add_new_anon_rmap(kpage, vma, addr); | 186 | page_add_new_anon_rmap(kpage, vma, addr); |
| 187 | mem_cgroup_commit_charge(kpage, memcg, false); | ||
| 188 | lru_cache_add_active_or_unevictable(kpage, vma); | ||
| 182 | 189 | ||
| 183 | if (!PageAnon(page)) { | 190 | if (!PageAnon(page)) { |
| 184 | dec_mm_counter(mm, MM_FILEPAGES); | 191 | dec_mm_counter(mm, MM_FILEPAGES); |
| @@ -200,6 +207,7 @@ static int __replace_page(struct vm_area_struct *vma, unsigned long addr, | |||
| 200 | 207 | ||
| 201 | err = 0; | 208 | err = 0; |
| 202 | unlock: | 209 | unlock: |
| 210 | mem_cgroup_cancel_charge(kpage, memcg); | ||
| 203 | mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end); | 211 | mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end); |
| 204 | unlock_page(page); | 212 | unlock_page(page); |
| 205 | return err; | 213 | return err; |
| @@ -315,18 +323,11 @@ retry: | |||
| 315 | if (!new_page) | 323 | if (!new_page) |
| 316 | goto put_old; | 324 | goto put_old; |
| 317 | 325 | ||
| 318 | if (mem_cgroup_charge_anon(new_page, mm, GFP_KERNEL)) | ||
| 319 | goto put_new; | ||
| 320 | |||
| 321 | __SetPageUptodate(new_page); | 326 | __SetPageUptodate(new_page); |
| 322 | copy_highpage(new_page, old_page); | 327 | copy_highpage(new_page, old_page); |
| 323 | copy_to_page(new_page, vaddr, &opcode, UPROBE_SWBP_INSN_SIZE); | 328 | copy_to_page(new_page, vaddr, &opcode, UPROBE_SWBP_INSN_SIZE); |
| 324 | 329 | ||
| 325 | ret = __replace_page(vma, vaddr, old_page, new_page); | 330 | ret = __replace_page(vma, vaddr, old_page, new_page); |
| 326 | if (ret) | ||
| 327 | mem_cgroup_uncharge_page(new_page); | ||
| 328 | |||
| 329 | put_new: | ||
| 330 | page_cache_release(new_page); | 331 | page_cache_release(new_page); |
| 331 | put_old: | 332 | put_old: |
| 332 | put_page(old_page); | 333 | put_page(old_page); |
diff --git a/kernel/exit.c b/kernel/exit.c index 88c6b3e42583..32c58f7433a3 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
| @@ -59,7 +59,7 @@ | |||
| 59 | #include <asm/pgtable.h> | 59 | #include <asm/pgtable.h> |
| 60 | #include <asm/mmu_context.h> | 60 | #include <asm/mmu_context.h> |
| 61 | 61 | ||
| 62 | static void exit_mm(struct task_struct * tsk); | 62 | static void exit_mm(struct task_struct *tsk); |
| 63 | 63 | ||
| 64 | static void __unhash_process(struct task_struct *p, bool group_dead) | 64 | static void __unhash_process(struct task_struct *p, bool group_dead) |
| 65 | { | 65 | { |
| @@ -151,7 +151,7 @@ static void __exit_signal(struct task_struct *tsk) | |||
| 151 | spin_unlock(&sighand->siglock); | 151 | spin_unlock(&sighand->siglock); |
| 152 | 152 | ||
| 153 | __cleanup_sighand(sighand); | 153 | __cleanup_sighand(sighand); |
| 154 | clear_tsk_thread_flag(tsk,TIF_SIGPENDING); | 154 | clear_tsk_thread_flag(tsk, TIF_SIGPENDING); |
| 155 | if (group_dead) { | 155 | if (group_dead) { |
| 156 | flush_sigqueue(&sig->shared_pending); | 156 | flush_sigqueue(&sig->shared_pending); |
| 157 | tty_kref_put(tty); | 157 | tty_kref_put(tty); |
| @@ -168,7 +168,7 @@ static void delayed_put_task_struct(struct rcu_head *rhp) | |||
| 168 | } | 168 | } |
| 169 | 169 | ||
| 170 | 170 | ||
| 171 | void release_task(struct task_struct * p) | 171 | void release_task(struct task_struct *p) |
| 172 | { | 172 | { |
| 173 | struct task_struct *leader; | 173 | struct task_struct *leader; |
| 174 | int zap_leader; | 174 | int zap_leader; |
| @@ -192,7 +192,8 @@ repeat: | |||
| 192 | */ | 192 | */ |
| 193 | zap_leader = 0; | 193 | zap_leader = 0; |
| 194 | leader = p->group_leader; | 194 | leader = p->group_leader; |
| 195 | if (leader != p && thread_group_empty(leader) && leader->exit_state == EXIT_ZOMBIE) { | 195 | if (leader != p && thread_group_empty(leader) |
| 196 | && leader->exit_state == EXIT_ZOMBIE) { | ||
| 196 | /* | 197 | /* |
| 197 | * If we were the last child thread and the leader has | 198 | * If we were the last child thread and the leader has |
| 198 | * exited already, and the leader's parent ignores SIGCHLD, | 199 | * exited already, and the leader's parent ignores SIGCHLD, |
| @@ -241,7 +242,8 @@ struct pid *session_of_pgrp(struct pid *pgrp) | |||
| 241 | * | 242 | * |
| 242 | * "I ask you, have you ever known what it is to be an orphan?" | 243 | * "I ask you, have you ever known what it is to be an orphan?" |
| 243 | */ | 244 | */ |
| 244 | static int will_become_orphaned_pgrp(struct pid *pgrp, struct task_struct *ignored_task) | 245 | static int will_become_orphaned_pgrp(struct pid *pgrp, |
| 246 | struct task_struct *ignored_task) | ||
| 245 | { | 247 | { |
| 246 | struct task_struct *p; | 248 | struct task_struct *p; |
| 247 | 249 | ||
| @@ -294,9 +296,9 @@ kill_orphaned_pgrp(struct task_struct *tsk, struct task_struct *parent) | |||
| 294 | struct task_struct *ignored_task = tsk; | 296 | struct task_struct *ignored_task = tsk; |
| 295 | 297 | ||
| 296 | if (!parent) | 298 | if (!parent) |
| 297 | /* exit: our father is in a different pgrp than | 299 | /* exit: our father is in a different pgrp than |
| 298 | * we are and we were the only connection outside. | 300 | * we are and we were the only connection outside. |
| 299 | */ | 301 | */ |
| 300 | parent = tsk->real_parent; | 302 | parent = tsk->real_parent; |
| 301 | else | 303 | else |
| 302 | /* reparent: our child is in a different pgrp than | 304 | /* reparent: our child is in a different pgrp than |
| @@ -405,7 +407,7 @@ assign_new_owner: | |||
| 405 | * Turn us into a lazy TLB process if we | 407 | * Turn us into a lazy TLB process if we |
| 406 | * aren't already.. | 408 | * aren't already.. |
| 407 | */ | 409 | */ |
| 408 | static void exit_mm(struct task_struct * tsk) | 410 | static void exit_mm(struct task_struct *tsk) |
| 409 | { | 411 | { |
| 410 | struct mm_struct *mm = tsk->mm; | 412 | struct mm_struct *mm = tsk->mm; |
| 411 | struct core_state *core_state; | 413 | struct core_state *core_state; |
| @@ -425,6 +427,7 @@ static void exit_mm(struct task_struct * tsk) | |||
| 425 | core_state = mm->core_state; | 427 | core_state = mm->core_state; |
| 426 | if (core_state) { | 428 | if (core_state) { |
| 427 | struct core_thread self; | 429 | struct core_thread self; |
| 430 | |||
| 428 | up_read(&mm->mmap_sem); | 431 | up_read(&mm->mmap_sem); |
| 429 | 432 | ||
| 430 | self.task = tsk; | 433 | self.task = tsk; |
| @@ -566,6 +569,7 @@ static void forget_original_parent(struct task_struct *father) | |||
| 566 | 569 | ||
| 567 | list_for_each_entry_safe(p, n, &father->children, sibling) { | 570 | list_for_each_entry_safe(p, n, &father->children, sibling) { |
| 568 | struct task_struct *t = p; | 571 | struct task_struct *t = p; |
| 572 | |||
| 569 | do { | 573 | do { |
| 570 | t->real_parent = reaper; | 574 | t->real_parent = reaper; |
| 571 | if (t->parent == father) { | 575 | if (t->parent == father) { |
| @@ -599,7 +603,7 @@ static void exit_notify(struct task_struct *tsk, int group_dead) | |||
| 599 | /* | 603 | /* |
| 600 | * This does two things: | 604 | * This does two things: |
| 601 | * | 605 | * |
| 602 | * A. Make init inherit all the child processes | 606 | * A. Make init inherit all the child processes |
| 603 | * B. Check to see if any process groups have become orphaned | 607 | * B. Check to see if any process groups have become orphaned |
| 604 | * as a result of our exiting, and if they have any stopped | 608 | * as a result of our exiting, and if they have any stopped |
| 605 | * jobs, send them a SIGHUP and then a SIGCONT. (POSIX 3.2.2.2) | 609 | * jobs, send them a SIGHUP and then a SIGCONT. (POSIX 3.2.2.2) |
| @@ -649,9 +653,8 @@ static void check_stack_usage(void) | |||
| 649 | 653 | ||
| 650 | spin_lock(&low_water_lock); | 654 | spin_lock(&low_water_lock); |
| 651 | if (free < lowest_to_date) { | 655 | if (free < lowest_to_date) { |
| 652 | printk(KERN_WARNING "%s (%d) used greatest stack depth: " | 656 | pr_warn("%s (%d) used greatest stack depth: %lu bytes left\n", |
| 653 | "%lu bytes left\n", | 657 | current->comm, task_pid_nr(current), free); |
| 654 | current->comm, task_pid_nr(current), free); | ||
| 655 | lowest_to_date = free; | 658 | lowest_to_date = free; |
| 656 | } | 659 | } |
| 657 | spin_unlock(&low_water_lock); | 660 | spin_unlock(&low_water_lock); |
| @@ -692,8 +695,7 @@ void do_exit(long code) | |||
| 692 | * leave this task alone and wait for reboot. | 695 | * leave this task alone and wait for reboot. |
| 693 | */ | 696 | */ |
| 694 | if (unlikely(tsk->flags & PF_EXITING)) { | 697 | if (unlikely(tsk->flags & PF_EXITING)) { |
| 695 | printk(KERN_ALERT | 698 | pr_alert("Fixing recursive fault but reboot is needed!\n"); |
| 696 | "Fixing recursive fault but reboot is needed!\n"); | ||
| 697 | /* | 699 | /* |
| 698 | * We can do this unlocked here. The futex code uses | 700 | * We can do this unlocked here. The futex code uses |
| 699 | * this flag just to verify whether the pi state | 701 | * this flag just to verify whether the pi state |
| @@ -717,9 +719,9 @@ void do_exit(long code) | |||
| 717 | raw_spin_unlock_wait(&tsk->pi_lock); | 719 | raw_spin_unlock_wait(&tsk->pi_lock); |
| 718 | 720 | ||
| 719 | if (unlikely(in_atomic())) | 721 | if (unlikely(in_atomic())) |
| 720 | printk(KERN_INFO "note: %s[%d] exited with preempt_count %d\n", | 722 | pr_info("note: %s[%d] exited with preempt_count %d\n", |
| 721 | current->comm, task_pid_nr(current), | 723 | current->comm, task_pid_nr(current), |
| 722 | preempt_count()); | 724 | preempt_count()); |
| 723 | 725 | ||
| 724 | acct_update_integrals(tsk); | 726 | acct_update_integrals(tsk); |
| 725 | /* sync mm's RSS info before statistics gathering */ | 727 | /* sync mm's RSS info before statistics gathering */ |
| @@ -837,7 +839,6 @@ void do_exit(long code) | |||
| 837 | for (;;) | 839 | for (;;) |
| 838 | cpu_relax(); /* For when BUG is null */ | 840 | cpu_relax(); /* For when BUG is null */ |
| 839 | } | 841 | } |
| 840 | |||
| 841 | EXPORT_SYMBOL_GPL(do_exit); | 842 | EXPORT_SYMBOL_GPL(do_exit); |
| 842 | 843 | ||
| 843 | void complete_and_exit(struct completion *comp, long code) | 844 | void complete_and_exit(struct completion *comp, long code) |
| @@ -847,7 +848,6 @@ void complete_and_exit(struct completion *comp, long code) | |||
| 847 | 848 | ||
| 848 | do_exit(code); | 849 | do_exit(code); |
| 849 | } | 850 | } |
| 850 | |||
| 851 | EXPORT_SYMBOL(complete_and_exit); | 851 | EXPORT_SYMBOL(complete_and_exit); |
| 852 | 852 | ||
| 853 | SYSCALL_DEFINE1(exit, int, error_code) | 853 | SYSCALL_DEFINE1(exit, int, error_code) |
| @@ -870,6 +870,7 @@ do_group_exit(int exit_code) | |||
| 870 | exit_code = sig->group_exit_code; | 870 | exit_code = sig->group_exit_code; |
| 871 | else if (!thread_group_empty(current)) { | 871 | else if (!thread_group_empty(current)) { |
| 872 | struct sighand_struct *const sighand = current->sighand; | 872 | struct sighand_struct *const sighand = current->sighand; |
| 873 | |||
| 873 | spin_lock_irq(&sighand->siglock); | 874 | spin_lock_irq(&sighand->siglock); |
| 874 | if (signal_group_exit(sig)) | 875 | if (signal_group_exit(sig)) |
| 875 | /* Another thread got here before we took the lock. */ | 876 | /* Another thread got here before we took the lock. */ |
| @@ -1034,9 +1035,9 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p) | |||
| 1034 | * as other threads in the parent group can be right | 1035 | * as other threads in the parent group can be right |
| 1035 | * here reaping other children at the same time. | 1036 | * here reaping other children at the same time. |
| 1036 | * | 1037 | * |
| 1037 | * We use thread_group_cputime_adjusted() to get times for the thread | 1038 | * We use thread_group_cputime_adjusted() to get times for |
| 1038 | * group, which consolidates times for all threads in the | 1039 | * the thread group, which consolidates times for all threads |
| 1039 | * group including the group leader. | 1040 | * in the group including the group leader. |
| 1040 | */ | 1041 | */ |
| 1041 | thread_group_cputime_adjusted(p, &tgutime, &tgstime); | 1042 | thread_group_cputime_adjusted(p, &tgutime, &tgstime); |
| 1042 | spin_lock_irq(&p->real_parent->sighand->siglock); | 1043 | spin_lock_irq(&p->real_parent->sighand->siglock); |
| @@ -1418,6 +1419,7 @@ static int do_wait_thread(struct wait_opts *wo, struct task_struct *tsk) | |||
| 1418 | 1419 | ||
| 1419 | list_for_each_entry(p, &tsk->children, sibling) { | 1420 | list_for_each_entry(p, &tsk->children, sibling) { |
| 1420 | int ret = wait_consider_task(wo, 0, p); | 1421 | int ret = wait_consider_task(wo, 0, p); |
| 1422 | |||
| 1421 | if (ret) | 1423 | if (ret) |
| 1422 | return ret; | 1424 | return ret; |
| 1423 | } | 1425 | } |
| @@ -1431,6 +1433,7 @@ static int ptrace_do_wait(struct wait_opts *wo, struct task_struct *tsk) | |||
| 1431 | 1433 | ||
| 1432 | list_for_each_entry(p, &tsk->ptraced, ptrace_entry) { | 1434 | list_for_each_entry(p, &tsk->ptraced, ptrace_entry) { |
| 1433 | int ret = wait_consider_task(wo, 1, p); | 1435 | int ret = wait_consider_task(wo, 1, p); |
| 1436 | |||
| 1434 | if (ret) | 1437 | if (ret) |
| 1435 | return ret; | 1438 | return ret; |
| 1436 | } | 1439 | } |
diff --git a/kernel/fork.c b/kernel/fork.c index fbd3497b221f..1380d8ace334 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
| @@ -374,12 +374,11 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) | |||
| 374 | */ | 374 | */ |
| 375 | down_write_nested(&mm->mmap_sem, SINGLE_DEPTH_NESTING); | 375 | down_write_nested(&mm->mmap_sem, SINGLE_DEPTH_NESTING); |
| 376 | 376 | ||
| 377 | mm->locked_vm = 0; | 377 | mm->total_vm = oldmm->total_vm; |
| 378 | mm->mmap = NULL; | 378 | mm->shared_vm = oldmm->shared_vm; |
| 379 | mm->vmacache_seqnum = 0; | 379 | mm->exec_vm = oldmm->exec_vm; |
| 380 | mm->map_count = 0; | 380 | mm->stack_vm = oldmm->stack_vm; |
| 381 | cpumask_clear(mm_cpumask(mm)); | 381 | |
| 382 | mm->mm_rb = RB_ROOT; | ||
| 383 | rb_link = &mm->mm_rb.rb_node; | 382 | rb_link = &mm->mm_rb.rb_node; |
| 384 | rb_parent = NULL; | 383 | rb_parent = NULL; |
| 385 | pprev = &mm->mmap; | 384 | pprev = &mm->mmap; |
| @@ -430,7 +429,7 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) | |||
| 430 | atomic_dec(&inode->i_writecount); | 429 | atomic_dec(&inode->i_writecount); |
| 431 | mutex_lock(&mapping->i_mmap_mutex); | 430 | mutex_lock(&mapping->i_mmap_mutex); |
| 432 | if (tmp->vm_flags & VM_SHARED) | 431 | if (tmp->vm_flags & VM_SHARED) |
| 433 | mapping->i_mmap_writable++; | 432 | atomic_inc(&mapping->i_mmap_writable); |
| 434 | flush_dcache_mmap_lock(mapping); | 433 | flush_dcache_mmap_lock(mapping); |
| 435 | /* insert tmp into the share list, just after mpnt */ | 434 | /* insert tmp into the share list, just after mpnt */ |
| 436 | if (unlikely(tmp->vm_flags & VM_NONLINEAR)) | 435 | if (unlikely(tmp->vm_flags & VM_NONLINEAR)) |
| @@ -536,19 +535,37 @@ static void mm_init_aio(struct mm_struct *mm) | |||
| 536 | #endif | 535 | #endif |
| 537 | } | 536 | } |
| 538 | 537 | ||
| 538 | static void mm_init_owner(struct mm_struct *mm, struct task_struct *p) | ||
| 539 | { | ||
| 540 | #ifdef CONFIG_MEMCG | ||
| 541 | mm->owner = p; | ||
| 542 | #endif | ||
| 543 | } | ||
| 544 | |||
| 539 | static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p) | 545 | static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p) |
| 540 | { | 546 | { |
| 547 | mm->mmap = NULL; | ||
| 548 | mm->mm_rb = RB_ROOT; | ||
| 549 | mm->vmacache_seqnum = 0; | ||
| 541 | atomic_set(&mm->mm_users, 1); | 550 | atomic_set(&mm->mm_users, 1); |
| 542 | atomic_set(&mm->mm_count, 1); | 551 | atomic_set(&mm->mm_count, 1); |
| 543 | init_rwsem(&mm->mmap_sem); | 552 | init_rwsem(&mm->mmap_sem); |
| 544 | INIT_LIST_HEAD(&mm->mmlist); | 553 | INIT_LIST_HEAD(&mm->mmlist); |
| 545 | mm->core_state = NULL; | 554 | mm->core_state = NULL; |
| 546 | atomic_long_set(&mm->nr_ptes, 0); | 555 | atomic_long_set(&mm->nr_ptes, 0); |
| 556 | mm->map_count = 0; | ||
| 557 | mm->locked_vm = 0; | ||
| 558 | mm->pinned_vm = 0; | ||
| 547 | memset(&mm->rss_stat, 0, sizeof(mm->rss_stat)); | 559 | memset(&mm->rss_stat, 0, sizeof(mm->rss_stat)); |
| 548 | spin_lock_init(&mm->page_table_lock); | 560 | spin_lock_init(&mm->page_table_lock); |
| 561 | mm_init_cpumask(mm); | ||
| 549 | mm_init_aio(mm); | 562 | mm_init_aio(mm); |
| 550 | mm_init_owner(mm, p); | 563 | mm_init_owner(mm, p); |
| 564 | mmu_notifier_mm_init(mm); | ||
| 551 | clear_tlb_flush_pending(mm); | 565 | clear_tlb_flush_pending(mm); |
| 566 | #if defined(CONFIG_TRANSPARENT_HUGEPAGE) && !USE_SPLIT_PMD_PTLOCKS | ||
| 567 | mm->pmd_huge_pte = NULL; | ||
| 568 | #endif | ||
| 552 | 569 | ||
| 553 | if (current->mm) { | 570 | if (current->mm) { |
| 554 | mm->flags = current->mm->flags & MMF_INIT_MASK; | 571 | mm->flags = current->mm->flags & MMF_INIT_MASK; |
| @@ -558,11 +575,17 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p) | |||
| 558 | mm->def_flags = 0; | 575 | mm->def_flags = 0; |
| 559 | } | 576 | } |
| 560 | 577 | ||
| 561 | if (likely(!mm_alloc_pgd(mm))) { | 578 | if (mm_alloc_pgd(mm)) |
| 562 | mmu_notifier_mm_init(mm); | 579 | goto fail_nopgd; |
| 563 | return mm; | 580 | |
| 564 | } | 581 | if (init_new_context(p, mm)) |
| 582 | goto fail_nocontext; | ||
| 583 | |||
| 584 | return mm; | ||
| 565 | 585 | ||
| 586 | fail_nocontext: | ||
| 587 | mm_free_pgd(mm); | ||
| 588 | fail_nopgd: | ||
| 566 | free_mm(mm); | 589 | free_mm(mm); |
| 567 | return NULL; | 590 | return NULL; |
| 568 | } | 591 | } |
| @@ -596,7 +619,6 @@ struct mm_struct *mm_alloc(void) | |||
| 596 | return NULL; | 619 | return NULL; |
| 597 | 620 | ||
| 598 | memset(mm, 0, sizeof(*mm)); | 621 | memset(mm, 0, sizeof(*mm)); |
| 599 | mm_init_cpumask(mm); | ||
| 600 | return mm_init(mm, current); | 622 | return mm_init(mm, current); |
| 601 | } | 623 | } |
| 602 | 624 | ||
| @@ -828,17 +850,10 @@ static struct mm_struct *dup_mm(struct task_struct *tsk) | |||
| 828 | goto fail_nomem; | 850 | goto fail_nomem; |
| 829 | 851 | ||
| 830 | memcpy(mm, oldmm, sizeof(*mm)); | 852 | memcpy(mm, oldmm, sizeof(*mm)); |
| 831 | mm_init_cpumask(mm); | ||
| 832 | 853 | ||
| 833 | #if defined(CONFIG_TRANSPARENT_HUGEPAGE) && !USE_SPLIT_PMD_PTLOCKS | ||
| 834 | mm->pmd_huge_pte = NULL; | ||
| 835 | #endif | ||
| 836 | if (!mm_init(mm, tsk)) | 854 | if (!mm_init(mm, tsk)) |
| 837 | goto fail_nomem; | 855 | goto fail_nomem; |
| 838 | 856 | ||
| 839 | if (init_new_context(tsk, mm)) | ||
| 840 | goto fail_nocontext; | ||
| 841 | |||
| 842 | dup_mm_exe_file(oldmm, mm); | 857 | dup_mm_exe_file(oldmm, mm); |
| 843 | 858 | ||
| 844 | err = dup_mmap(mm, oldmm); | 859 | err = dup_mmap(mm, oldmm); |
| @@ -860,15 +875,6 @@ free_pt: | |||
| 860 | 875 | ||
| 861 | fail_nomem: | 876 | fail_nomem: |
| 862 | return NULL; | 877 | return NULL; |
| 863 | |||
| 864 | fail_nocontext: | ||
| 865 | /* | ||
| 866 | * If init_new_context() failed, we cannot use mmput() to free the mm | ||
| 867 | * because it calls destroy_context() | ||
| 868 | */ | ||
| 869 | mm_free_pgd(mm); | ||
| 870 | free_mm(mm); | ||
| 871 | return NULL; | ||
| 872 | } | 878 | } |
| 873 | 879 | ||
| 874 | static int copy_mm(unsigned long clone_flags, struct task_struct *tsk) | 880 | static int copy_mm(unsigned long clone_flags, struct task_struct *tsk) |
| @@ -1140,13 +1146,6 @@ static void rt_mutex_init_task(struct task_struct *p) | |||
| 1140 | #endif | 1146 | #endif |
| 1141 | } | 1147 | } |
| 1142 | 1148 | ||
| 1143 | #ifdef CONFIG_MEMCG | ||
| 1144 | void mm_init_owner(struct mm_struct *mm, struct task_struct *p) | ||
| 1145 | { | ||
| 1146 | mm->owner = p; | ||
| 1147 | } | ||
| 1148 | #endif /* CONFIG_MEMCG */ | ||
| 1149 | |||
| 1150 | /* | 1149 | /* |
| 1151 | * Initialize POSIX timer handling for a single task. | 1150 | * Initialize POSIX timer handling for a single task. |
| 1152 | */ | 1151 | */ |
| @@ -1346,10 +1345,6 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
| 1346 | #ifdef CONFIG_DEBUG_MUTEXES | 1345 | #ifdef CONFIG_DEBUG_MUTEXES |
| 1347 | p->blocked_on = NULL; /* not blocked yet */ | 1346 | p->blocked_on = NULL; /* not blocked yet */ |
| 1348 | #endif | 1347 | #endif |
| 1349 | #ifdef CONFIG_MEMCG | ||
| 1350 | p->memcg_batch.do_batch = 0; | ||
| 1351 | p->memcg_batch.memcg = NULL; | ||
| 1352 | #endif | ||
| 1353 | #ifdef CONFIG_BCACHE | 1348 | #ifdef CONFIG_BCACHE |
| 1354 | p->sequential_io = 0; | 1349 | p->sequential_io = 0; |
| 1355 | p->sequential_io_avg = 0; | 1350 | p->sequential_io_avg = 0; |
| @@ -1367,6 +1362,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
| 1367 | if (retval) | 1362 | if (retval) |
| 1368 | goto bad_fork_cleanup_policy; | 1363 | goto bad_fork_cleanup_policy; |
| 1369 | /* copy all the process information */ | 1364 | /* copy all the process information */ |
| 1365 | shm_init_task(p); | ||
| 1370 | retval = copy_semundo(clone_flags, p); | 1366 | retval = copy_semundo(clone_flags, p); |
| 1371 | if (retval) | 1367 | if (retval) |
| 1372 | goto bad_fork_cleanup_audit; | 1368 | goto bad_fork_cleanup_audit; |
| @@ -1918,6 +1914,11 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags) | |||
| 1918 | */ | 1914 | */ |
| 1919 | exit_sem(current); | 1915 | exit_sem(current); |
| 1920 | } | 1916 | } |
| 1917 | if (unshare_flags & CLONE_NEWIPC) { | ||
| 1918 | /* Orphan segments in old ns (see sem above). */ | ||
| 1919 | exit_shm(current); | ||
| 1920 | shm_init_task(current); | ||
| 1921 | } | ||
| 1921 | 1922 | ||
| 1922 | if (new_nsproxy) | 1923 | if (new_nsproxy) |
| 1923 | switch_task_namespaces(current, new_nsproxy); | 1924 | switch_task_namespaces(current, new_nsproxy); |
diff --git a/kernel/gcov/fs.c b/kernel/gcov/fs.c index 15ff01a76379..edf67c493a8e 100644 --- a/kernel/gcov/fs.c +++ b/kernel/gcov/fs.c | |||
| @@ -784,8 +784,7 @@ static __init int gcov_fs_init(void) | |||
| 784 | 784 | ||
| 785 | err_remove: | 785 | err_remove: |
| 786 | pr_err("init failed\n"); | 786 | pr_err("init failed\n"); |
| 787 | if (root_node.dentry) | 787 | debugfs_remove(root_node.dentry); |
| 788 | debugfs_remove(root_node.dentry); | ||
| 789 | 788 | ||
| 790 | return rc; | 789 | return rc; |
| 791 | } | 790 | } |
diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c index cb0cf37dac3a..ae5167087845 100644 --- a/kernel/kallsyms.c +++ b/kernel/kallsyms.c | |||
| @@ -364,7 +364,7 @@ static int __sprint_symbol(char *buffer, unsigned long address, | |||
| 364 | address += symbol_offset; | 364 | address += symbol_offset; |
| 365 | name = kallsyms_lookup(address, &size, &offset, &modname, buffer); | 365 | name = kallsyms_lookup(address, &size, &offset, &modname, buffer); |
| 366 | if (!name) | 366 | if (!name) |
| 367 | return sprintf(buffer, "0x%lx", address); | 367 | return sprintf(buffer, "0x%lx", address - symbol_offset); |
| 368 | 368 | ||
| 369 | if (name != buffer) | 369 | if (name != buffer) |
| 370 | strcpy(buffer, name); | 370 | strcpy(buffer, name); |
diff --git a/kernel/kexec.c b/kernel/kexec.c index 4b8f0c925884..0b49a0a58102 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c | |||
| @@ -6,6 +6,8 @@ | |||
| 6 | * Version 2. See the file COPYING for more details. | 6 | * Version 2. See the file COPYING for more details. |
| 7 | */ | 7 | */ |
| 8 | 8 | ||
| 9 | #define pr_fmt(fmt) "kexec: " fmt | ||
| 10 | |||
| 9 | #include <linux/capability.h> | 11 | #include <linux/capability.h> |
| 10 | #include <linux/mm.h> | 12 | #include <linux/mm.h> |
| 11 | #include <linux/file.h> | 13 | #include <linux/file.h> |
| @@ -40,6 +42,9 @@ | |||
| 40 | #include <asm/io.h> | 42 | #include <asm/io.h> |
| 41 | #include <asm/sections.h> | 43 | #include <asm/sections.h> |
| 42 | 44 | ||
| 45 | #include <crypto/hash.h> | ||
| 46 | #include <crypto/sha.h> | ||
| 47 | |||
| 43 | /* Per cpu memory for storing cpu states in case of system crash. */ | 48 | /* Per cpu memory for storing cpu states in case of system crash. */ |
| 44 | note_buf_t __percpu *crash_notes; | 49 | note_buf_t __percpu *crash_notes; |
| 45 | 50 | ||
| @@ -52,6 +57,15 @@ size_t vmcoreinfo_max_size = sizeof(vmcoreinfo_data); | |||
| 52 | /* Flag to indicate we are going to kexec a new kernel */ | 57 | /* Flag to indicate we are going to kexec a new kernel */ |
| 53 | bool kexec_in_progress = false; | 58 | bool kexec_in_progress = false; |
| 54 | 59 | ||
| 60 | /* | ||
| 61 | * Declare these symbols weak so that if architecture provides a purgatory, | ||
| 62 | * these will be overridden. | ||
| 63 | */ | ||
| 64 | char __weak kexec_purgatory[0]; | ||
| 65 | size_t __weak kexec_purgatory_size = 0; | ||
| 66 | |||
| 67 | static int kexec_calculate_store_digests(struct kimage *image); | ||
| 68 | |||
| 55 | /* Location of the reserved area for the crash kernel */ | 69 | /* Location of the reserved area for the crash kernel */ |
| 56 | struct resource crashk_res = { | 70 | struct resource crashk_res = { |
| 57 | .name = "Crash kernel", | 71 | .name = "Crash kernel", |
| @@ -125,45 +139,27 @@ static struct page *kimage_alloc_page(struct kimage *image, | |||
| 125 | gfp_t gfp_mask, | 139 | gfp_t gfp_mask, |
| 126 | unsigned long dest); | 140 | unsigned long dest); |
| 127 | 141 | ||
| 128 | static int do_kimage_alloc(struct kimage **rimage, unsigned long entry, | 142 | static int copy_user_segment_list(struct kimage *image, |
| 129 | unsigned long nr_segments, | 143 | unsigned long nr_segments, |
| 130 | struct kexec_segment __user *segments) | 144 | struct kexec_segment __user *segments) |
| 131 | { | 145 | { |
| 146 | int ret; | ||
| 132 | size_t segment_bytes; | 147 | size_t segment_bytes; |
| 133 | struct kimage *image; | ||
| 134 | unsigned long i; | ||
| 135 | int result; | ||
| 136 | |||
| 137 | /* Allocate a controlling structure */ | ||
| 138 | result = -ENOMEM; | ||
| 139 | image = kzalloc(sizeof(*image), GFP_KERNEL); | ||
| 140 | if (!image) | ||
| 141 | goto out; | ||
| 142 | |||
| 143 | image->head = 0; | ||
| 144 | image->entry = &image->head; | ||
| 145 | image->last_entry = &image->head; | ||
| 146 | image->control_page = ~0; /* By default this does not apply */ | ||
| 147 | image->start = entry; | ||
| 148 | image->type = KEXEC_TYPE_DEFAULT; | ||
| 149 | |||
| 150 | /* Initialize the list of control pages */ | ||
| 151 | INIT_LIST_HEAD(&image->control_pages); | ||
| 152 | |||
| 153 | /* Initialize the list of destination pages */ | ||
| 154 | INIT_LIST_HEAD(&image->dest_pages); | ||
| 155 | |||
| 156 | /* Initialize the list of unusable pages */ | ||
| 157 | INIT_LIST_HEAD(&image->unuseable_pages); | ||
| 158 | 148 | ||
| 159 | /* Read in the segments */ | 149 | /* Read in the segments */ |
| 160 | image->nr_segments = nr_segments; | 150 | image->nr_segments = nr_segments; |
| 161 | segment_bytes = nr_segments * sizeof(*segments); | 151 | segment_bytes = nr_segments * sizeof(*segments); |
| 162 | result = copy_from_user(image->segment, segments, segment_bytes); | 152 | ret = copy_from_user(image->segment, segments, segment_bytes); |
| 163 | if (result) { | 153 | if (ret) |
| 164 | result = -EFAULT; | 154 | ret = -EFAULT; |
| 165 | goto out; | 155 | |
| 166 | } | 156 | return ret; |
| 157 | } | ||
| 158 | |||
| 159 | static int sanity_check_segment_list(struct kimage *image) | ||
| 160 | { | ||
| 161 | int result, i; | ||
| 162 | unsigned long nr_segments = image->nr_segments; | ||
| 167 | 163 | ||
| 168 | /* | 164 | /* |
| 169 | * Verify we have good destination addresses. The caller is | 165 | * Verify we have good destination addresses. The caller is |
| @@ -185,9 +181,9 @@ static int do_kimage_alloc(struct kimage **rimage, unsigned long entry, | |||
| 185 | mstart = image->segment[i].mem; | 181 | mstart = image->segment[i].mem; |
| 186 | mend = mstart + image->segment[i].memsz; | 182 | mend = mstart + image->segment[i].memsz; |
| 187 | if ((mstart & ~PAGE_MASK) || (mend & ~PAGE_MASK)) | 183 | if ((mstart & ~PAGE_MASK) || (mend & ~PAGE_MASK)) |
| 188 | goto out; | 184 | return result; |
| 189 | if (mend >= KEXEC_DESTINATION_MEMORY_LIMIT) | 185 | if (mend >= KEXEC_DESTINATION_MEMORY_LIMIT) |
| 190 | goto out; | 186 | return result; |
| 191 | } | 187 | } |
| 192 | 188 | ||
| 193 | /* Verify our destination addresses do not overlap. | 189 | /* Verify our destination addresses do not overlap. |
| @@ -208,7 +204,7 @@ static int do_kimage_alloc(struct kimage **rimage, unsigned long entry, | |||
| 208 | pend = pstart + image->segment[j].memsz; | 204 | pend = pstart + image->segment[j].memsz; |
| 209 | /* Do the segments overlap ? */ | 205 | /* Do the segments overlap ? */ |
| 210 | if ((mend > pstart) && (mstart < pend)) | 206 | if ((mend > pstart) && (mstart < pend)) |
| 211 | goto out; | 207 | return result; |
| 212 | } | 208 | } |
| 213 | } | 209 | } |
| 214 | 210 | ||
| @@ -220,130 +216,401 @@ static int do_kimage_alloc(struct kimage **rimage, unsigned long entry, | |||
| 220 | result = -EINVAL; | 216 | result = -EINVAL; |
| 221 | for (i = 0; i < nr_segments; i++) { | 217 | for (i = 0; i < nr_segments; i++) { |
| 222 | if (image->segment[i].bufsz > image->segment[i].memsz) | 218 | if (image->segment[i].bufsz > image->segment[i].memsz) |
| 223 | goto out; | 219 | return result; |
| 224 | } | 220 | } |
| 225 | 221 | ||
| 226 | result = 0; | 222 | /* |
| 227 | out: | 223 | * Verify we have good destination addresses. Normally |
| 228 | if (result == 0) | 224 | * the caller is responsible for making certain we don't |
| 229 | *rimage = image; | 225 | * attempt to load the new image into invalid or reserved |
| 230 | else | 226 | * areas of RAM. But crash kernels are preloaded into a |
| 231 | kfree(image); | 227 | * reserved area of ram. We must ensure the addresses |
| 228 | * are in the reserved area otherwise preloading the | ||
| 229 | * kernel could corrupt things. | ||
| 230 | */ | ||
| 232 | 231 | ||
| 233 | return result; | 232 | if (image->type == KEXEC_TYPE_CRASH) { |
| 233 | result = -EADDRNOTAVAIL; | ||
| 234 | for (i = 0; i < nr_segments; i++) { | ||
| 235 | unsigned long mstart, mend; | ||
| 236 | |||
| 237 | mstart = image->segment[i].mem; | ||
| 238 | mend = mstart + image->segment[i].memsz - 1; | ||
| 239 | /* Ensure we are within the crash kernel limits */ | ||
| 240 | if ((mstart < crashk_res.start) || | ||
| 241 | (mend > crashk_res.end)) | ||
| 242 | return result; | ||
| 243 | } | ||
| 244 | } | ||
| 234 | 245 | ||
| 246 | return 0; | ||
| 247 | } | ||
| 248 | |||
| 249 | static struct kimage *do_kimage_alloc_init(void) | ||
| 250 | { | ||
| 251 | struct kimage *image; | ||
| 252 | |||
| 253 | /* Allocate a controlling structure */ | ||
| 254 | image = kzalloc(sizeof(*image), GFP_KERNEL); | ||
| 255 | if (!image) | ||
| 256 | return NULL; | ||
| 257 | |||
| 258 | image->head = 0; | ||
| 259 | image->entry = &image->head; | ||
| 260 | image->last_entry = &image->head; | ||
| 261 | image->control_page = ~0; /* By default this does not apply */ | ||
| 262 | image->type = KEXEC_TYPE_DEFAULT; | ||
| 263 | |||
| 264 | /* Initialize the list of control pages */ | ||
| 265 | INIT_LIST_HEAD(&image->control_pages); | ||
| 266 | |||
| 267 | /* Initialize the list of destination pages */ | ||
| 268 | INIT_LIST_HEAD(&image->dest_pages); | ||
| 269 | |||
| 270 | /* Initialize the list of unusable pages */ | ||
| 271 | INIT_LIST_HEAD(&image->unusable_pages); | ||
| 272 | |||
| 273 | return image; | ||
| 235 | } | 274 | } |
| 236 | 275 | ||
| 237 | static void kimage_free_page_list(struct list_head *list); | 276 | static void kimage_free_page_list(struct list_head *list); |
| 238 | 277 | ||
| 239 | static int kimage_normal_alloc(struct kimage **rimage, unsigned long entry, | 278 | static int kimage_alloc_init(struct kimage **rimage, unsigned long entry, |
| 240 | unsigned long nr_segments, | 279 | unsigned long nr_segments, |
| 241 | struct kexec_segment __user *segments) | 280 | struct kexec_segment __user *segments, |
| 281 | unsigned long flags) | ||
| 242 | { | 282 | { |
| 243 | int result; | 283 | int ret; |
| 244 | struct kimage *image; | 284 | struct kimage *image; |
| 285 | bool kexec_on_panic = flags & KEXEC_ON_CRASH; | ||
| 286 | |||
| 287 | if (kexec_on_panic) { | ||
| 288 | /* Verify we have a valid entry point */ | ||
| 289 | if ((entry < crashk_res.start) || (entry > crashk_res.end)) | ||
| 290 | return -EADDRNOTAVAIL; | ||
| 291 | } | ||
| 245 | 292 | ||
| 246 | /* Allocate and initialize a controlling structure */ | 293 | /* Allocate and initialize a controlling structure */ |
| 247 | image = NULL; | 294 | image = do_kimage_alloc_init(); |
| 248 | result = do_kimage_alloc(&image, entry, nr_segments, segments); | 295 | if (!image) |
| 249 | if (result) | 296 | return -ENOMEM; |
| 250 | goto out; | 297 | |
| 298 | image->start = entry; | ||
| 299 | |||
| 300 | ret = copy_user_segment_list(image, nr_segments, segments); | ||
| 301 | if (ret) | ||
| 302 | goto out_free_image; | ||
| 303 | |||
| 304 | ret = sanity_check_segment_list(image); | ||
| 305 | if (ret) | ||
| 306 | goto out_free_image; | ||
| 307 | |||
| 308 | /* Enable the special crash kernel control page allocation policy. */ | ||
| 309 | if (kexec_on_panic) { | ||
| 310 | image->control_page = crashk_res.start; | ||
| 311 | image->type = KEXEC_TYPE_CRASH; | ||
| 312 | } | ||
| 251 | 313 | ||
| 252 | /* | 314 | /* |
| 253 | * Find a location for the control code buffer, and add it | 315 | * Find a location for the control code buffer, and add it |
| 254 | * the vector of segments so that it's pages will also be | 316 | * the vector of segments so that it's pages will also be |
| 255 | * counted as destination pages. | 317 | * counted as destination pages. |
| 256 | */ | 318 | */ |
| 257 | result = -ENOMEM; | 319 | ret = -ENOMEM; |
| 258 | image->control_code_page = kimage_alloc_control_pages(image, | 320 | image->control_code_page = kimage_alloc_control_pages(image, |
| 259 | get_order(KEXEC_CONTROL_PAGE_SIZE)); | 321 | get_order(KEXEC_CONTROL_PAGE_SIZE)); |
| 260 | if (!image->control_code_page) { | 322 | if (!image->control_code_page) { |
| 261 | pr_err("Could not allocate control_code_buffer\n"); | 323 | pr_err("Could not allocate control_code_buffer\n"); |
| 262 | goto out_free; | 324 | goto out_free_image; |
| 263 | } | 325 | } |
| 264 | 326 | ||
| 265 | image->swap_page = kimage_alloc_control_pages(image, 0); | 327 | if (!kexec_on_panic) { |
| 266 | if (!image->swap_page) { | 328 | image->swap_page = kimage_alloc_control_pages(image, 0); |
| 267 | pr_err("Could not allocate swap buffer\n"); | 329 | if (!image->swap_page) { |
| 268 | goto out_free; | 330 | pr_err("Could not allocate swap buffer\n"); |
| 331 | goto out_free_control_pages; | ||
| 332 | } | ||
| 269 | } | 333 | } |
| 270 | 334 | ||
| 271 | *rimage = image; | 335 | *rimage = image; |
| 272 | return 0; | 336 | return 0; |
| 273 | 337 | out_free_control_pages: | |
| 274 | out_free: | ||
| 275 | kimage_free_page_list(&image->control_pages); | 338 | kimage_free_page_list(&image->control_pages); |
| 339 | out_free_image: | ||
| 276 | kfree(image); | 340 | kfree(image); |
| 277 | out: | 341 | return ret; |
| 278 | return result; | ||
| 279 | } | 342 | } |
| 280 | 343 | ||
| 281 | static int kimage_crash_alloc(struct kimage **rimage, unsigned long entry, | 344 | static int copy_file_from_fd(int fd, void **buf, unsigned long *buf_len) |
| 282 | unsigned long nr_segments, | ||
| 283 | struct kexec_segment __user *segments) | ||
| 284 | { | 345 | { |
| 285 | int result; | 346 | struct fd f = fdget(fd); |
| 286 | struct kimage *image; | 347 | int ret; |
| 287 | unsigned long i; | 348 | struct kstat stat; |
| 349 | loff_t pos; | ||
| 350 | ssize_t bytes = 0; | ||
| 288 | 351 | ||
| 289 | image = NULL; | 352 | if (!f.file) |
| 290 | /* Verify we have a valid entry point */ | 353 | return -EBADF; |
| 291 | if ((entry < crashk_res.start) || (entry > crashk_res.end)) { | 354 | |
| 292 | result = -EADDRNOTAVAIL; | 355 | ret = vfs_getattr(&f.file->f_path, &stat); |
| 356 | if (ret) | ||
| 357 | goto out; | ||
| 358 | |||
| 359 | if (stat.size > INT_MAX) { | ||
| 360 | ret = -EFBIG; | ||
| 293 | goto out; | 361 | goto out; |
| 294 | } | 362 | } |
| 295 | 363 | ||
| 296 | /* Allocate and initialize a controlling structure */ | 364 | /* Don't hand 0 to vmalloc, it whines. */ |
| 297 | result = do_kimage_alloc(&image, entry, nr_segments, segments); | 365 | if (stat.size == 0) { |
| 298 | if (result) | 366 | ret = -EINVAL; |
| 299 | goto out; | 367 | goto out; |
| 368 | } | ||
| 300 | 369 | ||
| 301 | /* Enable the special crash kernel control page | 370 | *buf = vmalloc(stat.size); |
| 302 | * allocation policy. | 371 | if (!*buf) { |
| 303 | */ | 372 | ret = -ENOMEM; |
| 304 | image->control_page = crashk_res.start; | 373 | goto out; |
| 305 | image->type = KEXEC_TYPE_CRASH; | 374 | } |
| 306 | 375 | ||
| 307 | /* | 376 | pos = 0; |
| 308 | * Verify we have good destination addresses. Normally | 377 | while (pos < stat.size) { |
| 309 | * the caller is responsible for making certain we don't | 378 | bytes = kernel_read(f.file, pos, (char *)(*buf) + pos, |
| 310 | * attempt to load the new image into invalid or reserved | 379 | stat.size - pos); |
| 311 | * areas of RAM. But crash kernels are preloaded into a | 380 | if (bytes < 0) { |
| 312 | * reserved area of ram. We must ensure the addresses | 381 | vfree(*buf); |
| 313 | * are in the reserved area otherwise preloading the | 382 | ret = bytes; |
| 314 | * kernel could corrupt things. | 383 | goto out; |
| 315 | */ | 384 | } |
| 316 | result = -EADDRNOTAVAIL; | ||
| 317 | for (i = 0; i < nr_segments; i++) { | ||
| 318 | unsigned long mstart, mend; | ||
| 319 | 385 | ||
| 320 | mstart = image->segment[i].mem; | 386 | if (bytes == 0) |
| 321 | mend = mstart + image->segment[i].memsz - 1; | 387 | break; |
| 322 | /* Ensure we are within the crash kernel limits */ | 388 | pos += bytes; |
| 323 | if ((mstart < crashk_res.start) || (mend > crashk_res.end)) | ||
| 324 | goto out_free; | ||
| 325 | } | 389 | } |
| 326 | 390 | ||
| 391 | if (pos != stat.size) { | ||
| 392 | ret = -EBADF; | ||
| 393 | vfree(*buf); | ||
| 394 | goto out; | ||
| 395 | } | ||
| 396 | |||
| 397 | *buf_len = pos; | ||
| 398 | out: | ||
| 399 | fdput(f); | ||
| 400 | return ret; | ||
| 401 | } | ||
| 402 | |||
| 403 | /* Architectures can provide this probe function */ | ||
| 404 | int __weak arch_kexec_kernel_image_probe(struct kimage *image, void *buf, | ||
| 405 | unsigned long buf_len) | ||
| 406 | { | ||
| 407 | return -ENOEXEC; | ||
| 408 | } | ||
| 409 | |||
| 410 | void * __weak arch_kexec_kernel_image_load(struct kimage *image) | ||
| 411 | { | ||
| 412 | return ERR_PTR(-ENOEXEC); | ||
| 413 | } | ||
| 414 | |||
| 415 | void __weak arch_kimage_file_post_load_cleanup(struct kimage *image) | ||
| 416 | { | ||
| 417 | } | ||
| 418 | |||
| 419 | int __weak arch_kexec_kernel_verify_sig(struct kimage *image, void *buf, | ||
| 420 | unsigned long buf_len) | ||
| 421 | { | ||
| 422 | return -EKEYREJECTED; | ||
| 423 | } | ||
| 424 | |||
| 425 | /* Apply relocations of type RELA */ | ||
| 426 | int __weak | ||
| 427 | arch_kexec_apply_relocations_add(const Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, | ||
| 428 | unsigned int relsec) | ||
| 429 | { | ||
| 430 | pr_err("RELA relocation unsupported.\n"); | ||
| 431 | return -ENOEXEC; | ||
| 432 | } | ||
| 433 | |||
| 434 | /* Apply relocations of type REL */ | ||
| 435 | int __weak | ||
| 436 | arch_kexec_apply_relocations(const Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, | ||
| 437 | unsigned int relsec) | ||
| 438 | { | ||
| 439 | pr_err("REL relocation unsupported.\n"); | ||
| 440 | return -ENOEXEC; | ||
| 441 | } | ||
| 442 | |||
| 443 | /* | ||
| 444 | * Free up memory used by kernel, initrd, and comand line. This is temporary | ||
| 445 | * memory allocation which is not needed any more after these buffers have | ||
| 446 | * been loaded into separate segments and have been copied elsewhere. | ||
| 447 | */ | ||
| 448 | static void kimage_file_post_load_cleanup(struct kimage *image) | ||
| 449 | { | ||
| 450 | struct purgatory_info *pi = &image->purgatory_info; | ||
| 451 | |||
| 452 | vfree(image->kernel_buf); | ||
| 453 | image->kernel_buf = NULL; | ||
| 454 | |||
| 455 | vfree(image->initrd_buf); | ||
| 456 | image->initrd_buf = NULL; | ||
| 457 | |||
| 458 | kfree(image->cmdline_buf); | ||
| 459 | image->cmdline_buf = NULL; | ||
| 460 | |||
| 461 | vfree(pi->purgatory_buf); | ||
| 462 | pi->purgatory_buf = NULL; | ||
| 463 | |||
| 464 | vfree(pi->sechdrs); | ||
| 465 | pi->sechdrs = NULL; | ||
| 466 | |||
| 467 | /* See if architecture has anything to cleanup post load */ | ||
| 468 | arch_kimage_file_post_load_cleanup(image); | ||
| 469 | |||
| 327 | /* | 470 | /* |
| 328 | * Find a location for the control code buffer, and add | 471 | * Above call should have called into bootloader to free up |
| 329 | * the vector of segments so that it's pages will also be | 472 | * any data stored in kimage->image_loader_data. It should |
| 330 | * counted as destination pages. | 473 | * be ok now to free it up. |
| 331 | */ | 474 | */ |
| 332 | result = -ENOMEM; | 475 | kfree(image->image_loader_data); |
| 476 | image->image_loader_data = NULL; | ||
| 477 | } | ||
| 478 | |||
| 479 | /* | ||
| 480 | * In file mode list of segments is prepared by kernel. Copy relevant | ||
| 481 | * data from user space, do error checking, prepare segment list | ||
| 482 | */ | ||
| 483 | static int | ||
| 484 | kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd, | ||
| 485 | const char __user *cmdline_ptr, | ||
| 486 | unsigned long cmdline_len, unsigned flags) | ||
| 487 | { | ||
| 488 | int ret = 0; | ||
| 489 | void *ldata; | ||
| 490 | |||
| 491 | ret = copy_file_from_fd(kernel_fd, &image->kernel_buf, | ||
| 492 | &image->kernel_buf_len); | ||
| 493 | if (ret) | ||
| 494 | return ret; | ||
| 495 | |||
| 496 | /* Call arch image probe handlers */ | ||
| 497 | ret = arch_kexec_kernel_image_probe(image, image->kernel_buf, | ||
| 498 | image->kernel_buf_len); | ||
| 499 | |||
| 500 | if (ret) | ||
| 501 | goto out; | ||
| 502 | |||
| 503 | #ifdef CONFIG_KEXEC_VERIFY_SIG | ||
| 504 | ret = arch_kexec_kernel_verify_sig(image, image->kernel_buf, | ||
| 505 | image->kernel_buf_len); | ||
| 506 | if (ret) { | ||
| 507 | pr_debug("kernel signature verification failed.\n"); | ||
| 508 | goto out; | ||
| 509 | } | ||
| 510 | pr_debug("kernel signature verification successful.\n"); | ||
| 511 | #endif | ||
| 512 | /* It is possible that there no initramfs is being loaded */ | ||
| 513 | if (!(flags & KEXEC_FILE_NO_INITRAMFS)) { | ||
| 514 | ret = copy_file_from_fd(initrd_fd, &image->initrd_buf, | ||
| 515 | &image->initrd_buf_len); | ||
| 516 | if (ret) | ||
| 517 | goto out; | ||
| 518 | } | ||
| 519 | |||
| 520 | if (cmdline_len) { | ||
| 521 | image->cmdline_buf = kzalloc(cmdline_len, GFP_KERNEL); | ||
| 522 | if (!image->cmdline_buf) { | ||
| 523 | ret = -ENOMEM; | ||
| 524 | goto out; | ||
| 525 | } | ||
| 526 | |||
| 527 | ret = copy_from_user(image->cmdline_buf, cmdline_ptr, | ||
| 528 | cmdline_len); | ||
| 529 | if (ret) { | ||
| 530 | ret = -EFAULT; | ||
| 531 | goto out; | ||
| 532 | } | ||
| 533 | |||
| 534 | image->cmdline_buf_len = cmdline_len; | ||
| 535 | |||
| 536 | /* command line should be a string with last byte null */ | ||
| 537 | if (image->cmdline_buf[cmdline_len - 1] != '\0') { | ||
| 538 | ret = -EINVAL; | ||
| 539 | goto out; | ||
| 540 | } | ||
| 541 | } | ||
| 542 | |||
| 543 | /* Call arch image load handlers */ | ||
| 544 | ldata = arch_kexec_kernel_image_load(image); | ||
| 545 | |||
| 546 | if (IS_ERR(ldata)) { | ||
| 547 | ret = PTR_ERR(ldata); | ||
| 548 | goto out; | ||
| 549 | } | ||
| 550 | |||
| 551 | image->image_loader_data = ldata; | ||
| 552 | out: | ||
| 553 | /* In case of error, free up all allocated memory in this function */ | ||
| 554 | if (ret) | ||
| 555 | kimage_file_post_load_cleanup(image); | ||
| 556 | return ret; | ||
| 557 | } | ||
| 558 | |||
| 559 | static int | ||
| 560 | kimage_file_alloc_init(struct kimage **rimage, int kernel_fd, | ||
| 561 | int initrd_fd, const char __user *cmdline_ptr, | ||
| 562 | unsigned long cmdline_len, unsigned long flags) | ||
| 563 | { | ||
| 564 | int ret; | ||
| 565 | struct kimage *image; | ||
| 566 | bool kexec_on_panic = flags & KEXEC_FILE_ON_CRASH; | ||
| 567 | |||
| 568 | image = do_kimage_alloc_init(); | ||
| 569 | if (!image) | ||
| 570 | return -ENOMEM; | ||
| 571 | |||
| 572 | image->file_mode = 1; | ||
| 573 | |||
| 574 | if (kexec_on_panic) { | ||
| 575 | /* Enable special crash kernel control page alloc policy. */ | ||
| 576 | image->control_page = crashk_res.start; | ||
| 577 | image->type = KEXEC_TYPE_CRASH; | ||
| 578 | } | ||
| 579 | |||
| 580 | ret = kimage_file_prepare_segments(image, kernel_fd, initrd_fd, | ||
| 581 | cmdline_ptr, cmdline_len, flags); | ||
| 582 | if (ret) | ||
| 583 | goto out_free_image; | ||
| 584 | |||
| 585 | ret = sanity_check_segment_list(image); | ||
| 586 | if (ret) | ||
| 587 | goto out_free_post_load_bufs; | ||
| 588 | |||
| 589 | ret = -ENOMEM; | ||
| 333 | image->control_code_page = kimage_alloc_control_pages(image, | 590 | image->control_code_page = kimage_alloc_control_pages(image, |
| 334 | get_order(KEXEC_CONTROL_PAGE_SIZE)); | 591 | get_order(KEXEC_CONTROL_PAGE_SIZE)); |
| 335 | if (!image->control_code_page) { | 592 | if (!image->control_code_page) { |
| 336 | pr_err("Could not allocate control_code_buffer\n"); | 593 | pr_err("Could not allocate control_code_buffer\n"); |
| 337 | goto out_free; | 594 | goto out_free_post_load_bufs; |
| 595 | } | ||
| 596 | |||
| 597 | if (!kexec_on_panic) { | ||
| 598 | image->swap_page = kimage_alloc_control_pages(image, 0); | ||
| 599 | if (!image->swap_page) { | ||
| 600 | pr_err(KERN_ERR "Could not allocate swap buffer\n"); | ||
| 601 | goto out_free_control_pages; | ||
| 602 | } | ||
| 338 | } | 603 | } |
| 339 | 604 | ||
| 340 | *rimage = image; | 605 | *rimage = image; |
| 341 | return 0; | 606 | return 0; |
| 342 | 607 | out_free_control_pages: | |
| 343 | out_free: | 608 | kimage_free_page_list(&image->control_pages); |
| 609 | out_free_post_load_bufs: | ||
| 610 | kimage_file_post_load_cleanup(image); | ||
| 611 | out_free_image: | ||
| 344 | kfree(image); | 612 | kfree(image); |
| 345 | out: | 613 | return ret; |
| 346 | return result; | ||
| 347 | } | 614 | } |
| 348 | 615 | ||
| 349 | static int kimage_is_destination_range(struct kimage *image, | 616 | static int kimage_is_destination_range(struct kimage *image, |
| @@ -609,7 +876,7 @@ static void kimage_free_extra_pages(struct kimage *image) | |||
| 609 | kimage_free_page_list(&image->dest_pages); | 876 | kimage_free_page_list(&image->dest_pages); |
| 610 | 877 | ||
| 611 | /* Walk through and free any unusable pages I have cached */ | 878 | /* Walk through and free any unusable pages I have cached */ |
| 612 | kimage_free_page_list(&image->unuseable_pages); | 879 | kimage_free_page_list(&image->unusable_pages); |
| 613 | 880 | ||
| 614 | } | 881 | } |
| 615 | static void kimage_terminate(struct kimage *image) | 882 | static void kimage_terminate(struct kimage *image) |
| @@ -663,6 +930,14 @@ static void kimage_free(struct kimage *image) | |||
| 663 | 930 | ||
| 664 | /* Free the kexec control pages... */ | 931 | /* Free the kexec control pages... */ |
| 665 | kimage_free_page_list(&image->control_pages); | 932 | kimage_free_page_list(&image->control_pages); |
| 933 | |||
| 934 | /* | ||
| 935 | * Free up any temporary buffers allocated. This might hit if | ||
| 936 | * error occurred much later after buffer allocation. | ||
| 937 | */ | ||
| 938 | if (image->file_mode) | ||
| 939 | kimage_file_post_load_cleanup(image); | ||
| 940 | |||
| 666 | kfree(image); | 941 | kfree(image); |
| 667 | } | 942 | } |
| 668 | 943 | ||
| @@ -732,7 +1007,7 @@ static struct page *kimage_alloc_page(struct kimage *image, | |||
| 732 | /* If the page cannot be used file it away */ | 1007 | /* If the page cannot be used file it away */ |
| 733 | if (page_to_pfn(page) > | 1008 | if (page_to_pfn(page) > |
| 734 | (KEXEC_SOURCE_MEMORY_LIMIT >> PAGE_SHIFT)) { | 1009 | (KEXEC_SOURCE_MEMORY_LIMIT >> PAGE_SHIFT)) { |
| 735 | list_add(&page->lru, &image->unuseable_pages); | 1010 | list_add(&page->lru, &image->unusable_pages); |
| 736 | continue; | 1011 | continue; |
| 737 | } | 1012 | } |
| 738 | addr = page_to_pfn(page) << PAGE_SHIFT; | 1013 | addr = page_to_pfn(page) << PAGE_SHIFT; |
| @@ -791,10 +1066,14 @@ static int kimage_load_normal_segment(struct kimage *image, | |||
| 791 | unsigned long maddr; | 1066 | unsigned long maddr; |
| 792 | size_t ubytes, mbytes; | 1067 | size_t ubytes, mbytes; |
| 793 | int result; | 1068 | int result; |
| 794 | unsigned char __user *buf; | 1069 | unsigned char __user *buf = NULL; |
| 1070 | unsigned char *kbuf = NULL; | ||
| 795 | 1071 | ||
| 796 | result = 0; | 1072 | result = 0; |
| 797 | buf = segment->buf; | 1073 | if (image->file_mode) |
| 1074 | kbuf = segment->kbuf; | ||
| 1075 | else | ||
| 1076 | buf = segment->buf; | ||
| 798 | ubytes = segment->bufsz; | 1077 | ubytes = segment->bufsz; |
| 799 | mbytes = segment->memsz; | 1078 | mbytes = segment->memsz; |
| 800 | maddr = segment->mem; | 1079 | maddr = segment->mem; |
| @@ -826,7 +1105,11 @@ static int kimage_load_normal_segment(struct kimage *image, | |||
| 826 | PAGE_SIZE - (maddr & ~PAGE_MASK)); | 1105 | PAGE_SIZE - (maddr & ~PAGE_MASK)); |
| 827 | uchunk = min(ubytes, mchunk); | 1106 | uchunk = min(ubytes, mchunk); |
| 828 | 1107 | ||
| 829 | result = copy_from_user(ptr, buf, uchunk); | 1108 | /* For file based kexec, source pages are in kernel memory */ |
| 1109 | if (image->file_mode) | ||
| 1110 | memcpy(ptr, kbuf, uchunk); | ||
| 1111 | else | ||
| 1112 | result = copy_from_user(ptr, buf, uchunk); | ||
| 830 | kunmap(page); | 1113 | kunmap(page); |
| 831 | if (result) { | 1114 | if (result) { |
| 832 | result = -EFAULT; | 1115 | result = -EFAULT; |
| @@ -834,7 +1117,10 @@ static int kimage_load_normal_segment(struct kimage *image, | |||
| 834 | } | 1117 | } |
| 835 | ubytes -= uchunk; | 1118 | ubytes -= uchunk; |
| 836 | maddr += mchunk; | 1119 | maddr += mchunk; |
| 837 | buf += mchunk; | 1120 | if (image->file_mode) |
| 1121 | kbuf += mchunk; | ||
| 1122 | else | ||
| 1123 | buf += mchunk; | ||
| 838 | mbytes -= mchunk; | 1124 | mbytes -= mchunk; |
| 839 | } | 1125 | } |
| 840 | out: | 1126 | out: |
| @@ -851,10 +1137,14 @@ static int kimage_load_crash_segment(struct kimage *image, | |||
| 851 | unsigned long maddr; | 1137 | unsigned long maddr; |
| 852 | size_t ubytes, mbytes; | 1138 | size_t ubytes, mbytes; |
| 853 | int result; | 1139 | int result; |
| 854 | unsigned char __user *buf; | 1140 | unsigned char __user *buf = NULL; |
| 1141 | unsigned char *kbuf = NULL; | ||
| 855 | 1142 | ||
| 856 | result = 0; | 1143 | result = 0; |
| 857 | buf = segment->buf; | 1144 | if (image->file_mode) |
| 1145 | kbuf = segment->kbuf; | ||
| 1146 | else | ||
| 1147 | buf = segment->buf; | ||
| 858 | ubytes = segment->bufsz; | 1148 | ubytes = segment->bufsz; |
| 859 | mbytes = segment->memsz; | 1149 | mbytes = segment->memsz; |
| 860 | maddr = segment->mem; | 1150 | maddr = segment->mem; |
| @@ -877,7 +1167,12 @@ static int kimage_load_crash_segment(struct kimage *image, | |||
| 877 | /* Zero the trailing part of the page */ | 1167 | /* Zero the trailing part of the page */ |
| 878 | memset(ptr + uchunk, 0, mchunk - uchunk); | 1168 | memset(ptr + uchunk, 0, mchunk - uchunk); |
| 879 | } | 1169 | } |
| 880 | result = copy_from_user(ptr, buf, uchunk); | 1170 | |
| 1171 | /* For file based kexec, source pages are in kernel memory */ | ||
| 1172 | if (image->file_mode) | ||
| 1173 | memcpy(ptr, kbuf, uchunk); | ||
| 1174 | else | ||
| 1175 | result = copy_from_user(ptr, buf, uchunk); | ||
| 881 | kexec_flush_icache_page(page); | 1176 | kexec_flush_icache_page(page); |
| 882 | kunmap(page); | 1177 | kunmap(page); |
| 883 | if (result) { | 1178 | if (result) { |
| @@ -886,7 +1181,10 @@ static int kimage_load_crash_segment(struct kimage *image, | |||
| 886 | } | 1181 | } |
| 887 | ubytes -= uchunk; | 1182 | ubytes -= uchunk; |
| 888 | maddr += mchunk; | 1183 | maddr += mchunk; |
| 889 | buf += mchunk; | 1184 | if (image->file_mode) |
| 1185 | kbuf += mchunk; | ||
| 1186 | else | ||
| 1187 | buf += mchunk; | ||
| 890 | mbytes -= mchunk; | 1188 | mbytes -= mchunk; |
| 891 | } | 1189 | } |
| 892 | out: | 1190 | out: |
| @@ -986,16 +1284,16 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments, | |||
| 986 | 1284 | ||
| 987 | /* Loading another kernel to reboot into */ | 1285 | /* Loading another kernel to reboot into */ |
| 988 | if ((flags & KEXEC_ON_CRASH) == 0) | 1286 | if ((flags & KEXEC_ON_CRASH) == 0) |
| 989 | result = kimage_normal_alloc(&image, entry, | 1287 | result = kimage_alloc_init(&image, entry, nr_segments, |
| 990 | nr_segments, segments); | 1288 | segments, flags); |
| 991 | /* Loading another kernel to switch to if this one crashes */ | 1289 | /* Loading another kernel to switch to if this one crashes */ |
| 992 | else if (flags & KEXEC_ON_CRASH) { | 1290 | else if (flags & KEXEC_ON_CRASH) { |
| 993 | /* Free any current crash dump kernel before | 1291 | /* Free any current crash dump kernel before |
| 994 | * we corrupt it. | 1292 | * we corrupt it. |
| 995 | */ | 1293 | */ |
| 996 | kimage_free(xchg(&kexec_crash_image, NULL)); | 1294 | kimage_free(xchg(&kexec_crash_image, NULL)); |
| 997 | result = kimage_crash_alloc(&image, entry, | 1295 | result = kimage_alloc_init(&image, entry, nr_segments, |
| 998 | nr_segments, segments); | 1296 | segments, flags); |
| 999 | crash_map_reserved_pages(); | 1297 | crash_map_reserved_pages(); |
| 1000 | } | 1298 | } |
| 1001 | if (result) | 1299 | if (result) |
| @@ -1077,6 +1375,82 @@ COMPAT_SYSCALL_DEFINE4(kexec_load, compat_ulong_t, entry, | |||
| 1077 | } | 1375 | } |
| 1078 | #endif | 1376 | #endif |
| 1079 | 1377 | ||
| 1378 | SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd, | ||
| 1379 | unsigned long, cmdline_len, const char __user *, cmdline_ptr, | ||
| 1380 | unsigned long, flags) | ||
| 1381 | { | ||
| 1382 | int ret = 0, i; | ||
| 1383 | struct kimage **dest_image, *image; | ||
| 1384 | |||
| 1385 | /* We only trust the superuser with rebooting the system. */ | ||
| 1386 | if (!capable(CAP_SYS_BOOT) || kexec_load_disabled) | ||
| 1387 | return -EPERM; | ||
| 1388 | |||
| 1389 | /* Make sure we have a legal set of flags */ | ||
| 1390 | if (flags != (flags & KEXEC_FILE_FLAGS)) | ||
| 1391 | return -EINVAL; | ||
| 1392 | |||
| 1393 | image = NULL; | ||
| 1394 | |||
| 1395 | if (!mutex_trylock(&kexec_mutex)) | ||
| 1396 | return -EBUSY; | ||
| 1397 | |||
| 1398 | dest_image = &kexec_image; | ||
| 1399 | if (flags & KEXEC_FILE_ON_CRASH) | ||
| 1400 | dest_image = &kexec_crash_image; | ||
| 1401 | |||
| 1402 | if (flags & KEXEC_FILE_UNLOAD) | ||
| 1403 | goto exchange; | ||
| 1404 | |||
| 1405 | /* | ||
| 1406 | * In case of crash, new kernel gets loaded in reserved region. It is | ||
| 1407 | * same memory where old crash kernel might be loaded. Free any | ||
| 1408 | * current crash dump kernel before we corrupt it. | ||
| 1409 | */ | ||
| 1410 | if (flags & KEXEC_FILE_ON_CRASH) | ||
| 1411 | kimage_free(xchg(&kexec_crash_image, NULL)); | ||
| 1412 | |||
| 1413 | ret = kimage_file_alloc_init(&image, kernel_fd, initrd_fd, cmdline_ptr, | ||
| 1414 | cmdline_len, flags); | ||
| 1415 | if (ret) | ||
| 1416 | goto out; | ||
| 1417 | |||
| 1418 | ret = machine_kexec_prepare(image); | ||
| 1419 | if (ret) | ||
| 1420 | goto out; | ||
| 1421 | |||
| 1422 | ret = kexec_calculate_store_digests(image); | ||
| 1423 | if (ret) | ||
| 1424 | goto out; | ||
| 1425 | |||
| 1426 | for (i = 0; i < image->nr_segments; i++) { | ||
| 1427 | struct kexec_segment *ksegment; | ||
| 1428 | |||
| 1429 | ksegment = &image->segment[i]; | ||
| 1430 | pr_debug("Loading segment %d: buf=0x%p bufsz=0x%zx mem=0x%lx memsz=0x%zx\n", | ||
| 1431 | i, ksegment->buf, ksegment->bufsz, ksegment->mem, | ||
| 1432 | ksegment->memsz); | ||
| 1433 | |||
| 1434 | ret = kimage_load_segment(image, &image->segment[i]); | ||
| 1435 | if (ret) | ||
| 1436 | goto out; | ||
| 1437 | } | ||
| 1438 | |||
| 1439 | kimage_terminate(image); | ||
| 1440 | |||
| 1441 | /* | ||
| 1442 | * Free up any temporary buffers allocated which are not needed | ||
| 1443 | * after image has been loaded | ||
| 1444 | */ | ||
| 1445 | kimage_file_post_load_cleanup(image); | ||
| 1446 | exchange: | ||
| 1447 | image = xchg(dest_image, image); | ||
| 1448 | out: | ||
| 1449 | mutex_unlock(&kexec_mutex); | ||
| 1450 | kimage_free(image); | ||
| 1451 | return ret; | ||
| 1452 | } | ||
| 1453 | |||
| 1080 | void crash_kexec(struct pt_regs *regs) | 1454 | void crash_kexec(struct pt_regs *regs) |
| 1081 | { | 1455 | { |
| 1082 | /* Take the kexec_mutex here to prevent sys_kexec_load | 1456 | /* Take the kexec_mutex here to prevent sys_kexec_load |
| @@ -1632,6 +2006,683 @@ static int __init crash_save_vmcoreinfo_init(void) | |||
| 1632 | 2006 | ||
| 1633 | subsys_initcall(crash_save_vmcoreinfo_init); | 2007 | subsys_initcall(crash_save_vmcoreinfo_init); |
| 1634 | 2008 | ||
| 2009 | static int __kexec_add_segment(struct kimage *image, char *buf, | ||
| 2010 | unsigned long bufsz, unsigned long mem, | ||
| 2011 | unsigned long memsz) | ||
| 2012 | { | ||
| 2013 | struct kexec_segment *ksegment; | ||
| 2014 | |||
| 2015 | ksegment = &image->segment[image->nr_segments]; | ||
| 2016 | ksegment->kbuf = buf; | ||
| 2017 | ksegment->bufsz = bufsz; | ||
| 2018 | ksegment->mem = mem; | ||
| 2019 | ksegment->memsz = memsz; | ||
| 2020 | image->nr_segments++; | ||
| 2021 | |||
| 2022 | return 0; | ||
| 2023 | } | ||
| 2024 | |||
| 2025 | static int locate_mem_hole_top_down(unsigned long start, unsigned long end, | ||
| 2026 | struct kexec_buf *kbuf) | ||
| 2027 | { | ||
| 2028 | struct kimage *image = kbuf->image; | ||
| 2029 | unsigned long temp_start, temp_end; | ||
| 2030 | |||
| 2031 | temp_end = min(end, kbuf->buf_max); | ||
| 2032 | temp_start = temp_end - kbuf->memsz; | ||
| 2033 | |||
| 2034 | do { | ||
| 2035 | /* align down start */ | ||
| 2036 | temp_start = temp_start & (~(kbuf->buf_align - 1)); | ||
| 2037 | |||
| 2038 | if (temp_start < start || temp_start < kbuf->buf_min) | ||
| 2039 | return 0; | ||
| 2040 | |||
| 2041 | temp_end = temp_start + kbuf->memsz - 1; | ||
| 2042 | |||
| 2043 | /* | ||
| 2044 | * Make sure this does not conflict with any of existing | ||
| 2045 | * segments | ||
| 2046 | */ | ||
| 2047 | if (kimage_is_destination_range(image, temp_start, temp_end)) { | ||
| 2048 | temp_start = temp_start - PAGE_SIZE; | ||
| 2049 | continue; | ||
| 2050 | } | ||
| 2051 | |||
| 2052 | /* We found a suitable memory range */ | ||
| 2053 | break; | ||
| 2054 | } while (1); | ||
| 2055 | |||
| 2056 | /* If we are here, we found a suitable memory range */ | ||
| 2057 | __kexec_add_segment(image, kbuf->buffer, kbuf->bufsz, temp_start, | ||
| 2058 | kbuf->memsz); | ||
| 2059 | |||
| 2060 | /* Success, stop navigating through remaining System RAM ranges */ | ||
| 2061 | return 1; | ||
| 2062 | } | ||
| 2063 | |||
| 2064 | static int locate_mem_hole_bottom_up(unsigned long start, unsigned long end, | ||
| 2065 | struct kexec_buf *kbuf) | ||
| 2066 | { | ||
| 2067 | struct kimage *image = kbuf->image; | ||
| 2068 | unsigned long temp_start, temp_end; | ||
| 2069 | |||
| 2070 | temp_start = max(start, kbuf->buf_min); | ||
| 2071 | |||
| 2072 | do { | ||
| 2073 | temp_start = ALIGN(temp_start, kbuf->buf_align); | ||
| 2074 | temp_end = temp_start + kbuf->memsz - 1; | ||
| 2075 | |||
| 2076 | if (temp_end > end || temp_end > kbuf->buf_max) | ||
| 2077 | return 0; | ||
| 2078 | /* | ||
| 2079 | * Make sure this does not conflict with any of existing | ||
| 2080 | * segments | ||
| 2081 | */ | ||
| 2082 | if (kimage_is_destination_range(image, temp_start, temp_end)) { | ||
| 2083 | temp_start = temp_start + PAGE_SIZE; | ||
| 2084 | continue; | ||
| 2085 | } | ||
| 2086 | |||
| 2087 | /* We found a suitable memory range */ | ||
| 2088 | break; | ||
| 2089 | } while (1); | ||
| 2090 | |||
| 2091 | /* If we are here, we found a suitable memory range */ | ||
| 2092 | __kexec_add_segment(image, kbuf->buffer, kbuf->bufsz, temp_start, | ||
| 2093 | kbuf->memsz); | ||
| 2094 | |||
| 2095 | /* Success, stop navigating through remaining System RAM ranges */ | ||
| 2096 | return 1; | ||
| 2097 | } | ||
| 2098 | |||
| 2099 | static int locate_mem_hole_callback(u64 start, u64 end, void *arg) | ||
| 2100 | { | ||
| 2101 | struct kexec_buf *kbuf = (struct kexec_buf *)arg; | ||
| 2102 | unsigned long sz = end - start + 1; | ||
| 2103 | |||
| 2104 | /* Returning 0 will take to next memory range */ | ||
| 2105 | if (sz < kbuf->memsz) | ||
| 2106 | return 0; | ||
| 2107 | |||
| 2108 | if (end < kbuf->buf_min || start > kbuf->buf_max) | ||
| 2109 | return 0; | ||
| 2110 | |||
| 2111 | /* | ||
| 2112 | * Allocate memory top down with-in ram range. Otherwise bottom up | ||
| 2113 | * allocation. | ||
| 2114 | */ | ||
| 2115 | if (kbuf->top_down) | ||
| 2116 | return locate_mem_hole_top_down(start, end, kbuf); | ||
| 2117 | return locate_mem_hole_bottom_up(start, end, kbuf); | ||
| 2118 | } | ||
| 2119 | |||
| 2120 | /* | ||
| 2121 | * Helper function for placing a buffer in a kexec segment. This assumes | ||
| 2122 | * that kexec_mutex is held. | ||
| 2123 | */ | ||
| 2124 | int kexec_add_buffer(struct kimage *image, char *buffer, unsigned long bufsz, | ||
| 2125 | unsigned long memsz, unsigned long buf_align, | ||
| 2126 | unsigned long buf_min, unsigned long buf_max, | ||
| 2127 | bool top_down, unsigned long *load_addr) | ||
| 2128 | { | ||
| 2129 | |||
| 2130 | struct kexec_segment *ksegment; | ||
| 2131 | struct kexec_buf buf, *kbuf; | ||
| 2132 | int ret; | ||
| 2133 | |||
| 2134 | /* Currently adding segment this way is allowed only in file mode */ | ||
| 2135 | if (!image->file_mode) | ||
| 2136 | return -EINVAL; | ||
| 2137 | |||
| 2138 | if (image->nr_segments >= KEXEC_SEGMENT_MAX) | ||
| 2139 | return -EINVAL; | ||
| 2140 | |||
| 2141 | /* | ||
| 2142 | * Make sure we are not trying to add buffer after allocating | ||
| 2143 | * control pages. All segments need to be placed first before | ||
| 2144 | * any control pages are allocated. As control page allocation | ||
| 2145 | * logic goes through list of segments to make sure there are | ||
| 2146 | * no destination overlaps. | ||
| 2147 | */ | ||
| 2148 | if (!list_empty(&image->control_pages)) { | ||
| 2149 | WARN_ON(1); | ||
| 2150 | return -EINVAL; | ||
| 2151 | } | ||
| 2152 | |||
| 2153 | memset(&buf, 0, sizeof(struct kexec_buf)); | ||
| 2154 | kbuf = &buf; | ||
| 2155 | kbuf->image = image; | ||
| 2156 | kbuf->buffer = buffer; | ||
| 2157 | kbuf->bufsz = bufsz; | ||
| 2158 | |||
| 2159 | kbuf->memsz = ALIGN(memsz, PAGE_SIZE); | ||
| 2160 | kbuf->buf_align = max(buf_align, PAGE_SIZE); | ||
| 2161 | kbuf->buf_min = buf_min; | ||
| 2162 | kbuf->buf_max = buf_max; | ||
| 2163 | kbuf->top_down = top_down; | ||
| 2164 | |||
| 2165 | /* Walk the RAM ranges and allocate a suitable range for the buffer */ | ||
| 2166 | if (image->type == KEXEC_TYPE_CRASH) | ||
| 2167 | ret = walk_iomem_res("Crash kernel", | ||
| 2168 | IORESOURCE_MEM | IORESOURCE_BUSY, | ||
| 2169 | crashk_res.start, crashk_res.end, kbuf, | ||
| 2170 | locate_mem_hole_callback); | ||
| 2171 | else | ||
| 2172 | ret = walk_system_ram_res(0, -1, kbuf, | ||
| 2173 | locate_mem_hole_callback); | ||
| 2174 | if (ret != 1) { | ||
| 2175 | /* A suitable memory range could not be found for buffer */ | ||
| 2176 | return -EADDRNOTAVAIL; | ||
| 2177 | } | ||
| 2178 | |||
| 2179 | /* Found a suitable memory range */ | ||
| 2180 | ksegment = &image->segment[image->nr_segments - 1]; | ||
| 2181 | *load_addr = ksegment->mem; | ||
| 2182 | return 0; | ||
| 2183 | } | ||
| 2184 | |||
| 2185 | /* Calculate and store the digest of segments */ | ||
| 2186 | static int kexec_calculate_store_digests(struct kimage *image) | ||
| 2187 | { | ||
| 2188 | struct crypto_shash *tfm; | ||
| 2189 | struct shash_desc *desc; | ||
| 2190 | int ret = 0, i, j, zero_buf_sz, sha_region_sz; | ||
| 2191 | size_t desc_size, nullsz; | ||
| 2192 | char *digest; | ||
| 2193 | void *zero_buf; | ||
| 2194 | struct kexec_sha_region *sha_regions; | ||
| 2195 | struct purgatory_info *pi = &image->purgatory_info; | ||
| 2196 | |||
| 2197 | zero_buf = __va(page_to_pfn(ZERO_PAGE(0)) << PAGE_SHIFT); | ||
| 2198 | zero_buf_sz = PAGE_SIZE; | ||
| 2199 | |||
| 2200 | tfm = crypto_alloc_shash("sha256", 0, 0); | ||
| 2201 | if (IS_ERR(tfm)) { | ||
| 2202 | ret = PTR_ERR(tfm); | ||
| 2203 | goto out; | ||
| 2204 | } | ||
| 2205 | |||
| 2206 | desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); | ||
| 2207 | desc = kzalloc(desc_size, GFP_KERNEL); | ||
| 2208 | if (!desc) { | ||
| 2209 | ret = -ENOMEM; | ||
| 2210 | goto out_free_tfm; | ||
| 2211 | } | ||
| 2212 | |||
| 2213 | sha_region_sz = KEXEC_SEGMENT_MAX * sizeof(struct kexec_sha_region); | ||
| 2214 | sha_regions = vzalloc(sha_region_sz); | ||
| 2215 | if (!sha_regions) | ||
| 2216 | goto out_free_desc; | ||
| 2217 | |||
| 2218 | desc->tfm = tfm; | ||
| 2219 | desc->flags = 0; | ||
| 2220 | |||
| 2221 | ret = crypto_shash_init(desc); | ||
| 2222 | if (ret < 0) | ||
| 2223 | goto out_free_sha_regions; | ||
| 2224 | |||
| 2225 | digest = kzalloc(SHA256_DIGEST_SIZE, GFP_KERNEL); | ||
| 2226 | if (!digest) { | ||
| 2227 | ret = -ENOMEM; | ||
| 2228 | goto out_free_sha_regions; | ||
| 2229 | } | ||
| 2230 | |||
| 2231 | for (j = i = 0; i < image->nr_segments; i++) { | ||
| 2232 | struct kexec_segment *ksegment; | ||
| 2233 | |||
| 2234 | ksegment = &image->segment[i]; | ||
| 2235 | /* | ||
| 2236 | * Skip purgatory as it will be modified once we put digest | ||
| 2237 | * info in purgatory. | ||
| 2238 | */ | ||
| 2239 | if (ksegment->kbuf == pi->purgatory_buf) | ||
| 2240 | continue; | ||
| 2241 | |||
| 2242 | ret = crypto_shash_update(desc, ksegment->kbuf, | ||
| 2243 | ksegment->bufsz); | ||
| 2244 | if (ret) | ||
| 2245 | break; | ||
| 2246 | |||
| 2247 | /* | ||
| 2248 | * Assume rest of the buffer is filled with zero and | ||
| 2249 | * update digest accordingly. | ||
| 2250 | */ | ||
| 2251 | nullsz = ksegment->memsz - ksegment->bufsz; | ||
| 2252 | while (nullsz) { | ||
| 2253 | unsigned long bytes = nullsz; | ||
| 2254 | |||
| 2255 | if (bytes > zero_buf_sz) | ||
| 2256 | bytes = zero_buf_sz; | ||
| 2257 | ret = crypto_shash_update(desc, zero_buf, bytes); | ||
| 2258 | if (ret) | ||
| 2259 | break; | ||
| 2260 | nullsz -= bytes; | ||
| 2261 | } | ||
| 2262 | |||
| 2263 | if (ret) | ||
| 2264 | break; | ||
| 2265 | |||
| 2266 | sha_regions[j].start = ksegment->mem; | ||
| 2267 | sha_regions[j].len = ksegment->memsz; | ||
| 2268 | j++; | ||
| 2269 | } | ||
| 2270 | |||
| 2271 | if (!ret) { | ||
| 2272 | ret = crypto_shash_final(desc, digest); | ||
| 2273 | if (ret) | ||
| 2274 | goto out_free_digest; | ||
| 2275 | ret = kexec_purgatory_get_set_symbol(image, "sha_regions", | ||
| 2276 | sha_regions, sha_region_sz, 0); | ||
| 2277 | if (ret) | ||
| 2278 | goto out_free_digest; | ||
| 2279 | |||
| 2280 | ret = kexec_purgatory_get_set_symbol(image, "sha256_digest", | ||
| 2281 | digest, SHA256_DIGEST_SIZE, 0); | ||
| 2282 | if (ret) | ||
| 2283 | goto out_free_digest; | ||
| 2284 | } | ||
| 2285 | |||
| 2286 | out_free_digest: | ||
| 2287 | kfree(digest); | ||
| 2288 | out_free_sha_regions: | ||
| 2289 | vfree(sha_regions); | ||
| 2290 | out_free_desc: | ||
| 2291 | kfree(desc); | ||
| 2292 | out_free_tfm: | ||
| 2293 | kfree(tfm); | ||
| 2294 | out: | ||
| 2295 | return ret; | ||
| 2296 | } | ||
| 2297 | |||
| 2298 | /* Actually load purgatory. Lot of code taken from kexec-tools */ | ||
| 2299 | static int __kexec_load_purgatory(struct kimage *image, unsigned long min, | ||
| 2300 | unsigned long max, int top_down) | ||
| 2301 | { | ||
| 2302 | struct purgatory_info *pi = &image->purgatory_info; | ||
| 2303 | unsigned long align, buf_align, bss_align, buf_sz, bss_sz, bss_pad; | ||
| 2304 | unsigned long memsz, entry, load_addr, curr_load_addr, bss_addr, offset; | ||
| 2305 | unsigned char *buf_addr, *src; | ||
| 2306 | int i, ret = 0, entry_sidx = -1; | ||
| 2307 | const Elf_Shdr *sechdrs_c; | ||
| 2308 | Elf_Shdr *sechdrs = NULL; | ||
| 2309 | void *purgatory_buf = NULL; | ||
| 2310 | |||
| 2311 | /* | ||
| 2312 | * sechdrs_c points to section headers in purgatory and are read | ||
| 2313 | * only. No modifications allowed. | ||
| 2314 | */ | ||
| 2315 | sechdrs_c = (void *)pi->ehdr + pi->ehdr->e_shoff; | ||
| 2316 | |||
| 2317 | /* | ||
| 2318 | * We can not modify sechdrs_c[] and its fields. It is read only. | ||
| 2319 | * Copy it over to a local copy where one can store some temporary | ||
| 2320 | * data and free it at the end. We need to modify ->sh_addr and | ||
| 2321 | * ->sh_offset fields to keep track of permanent and temporary | ||
| 2322 | * locations of sections. | ||
| 2323 | */ | ||
| 2324 | sechdrs = vzalloc(pi->ehdr->e_shnum * sizeof(Elf_Shdr)); | ||
| 2325 | if (!sechdrs) | ||
| 2326 | return -ENOMEM; | ||
| 2327 | |||
| 2328 | memcpy(sechdrs, sechdrs_c, pi->ehdr->e_shnum * sizeof(Elf_Shdr)); | ||
| 2329 | |||
| 2330 | /* | ||
| 2331 | * We seem to have multiple copies of sections. First copy is which | ||
| 2332 | * is embedded in kernel in read only section. Some of these sections | ||
| 2333 | * will be copied to a temporary buffer and relocated. And these | ||
| 2334 | * sections will finally be copied to their final destination at | ||
| 2335 | * segment load time. | ||
| 2336 | * | ||
| 2337 | * Use ->sh_offset to reflect section address in memory. It will | ||
| 2338 | * point to original read only copy if section is not allocatable. | ||
| 2339 | * Otherwise it will point to temporary copy which will be relocated. | ||
| 2340 | * | ||
| 2341 | * Use ->sh_addr to contain final address of the section where it | ||
| 2342 | * will go during execution time. | ||
| 2343 | */ | ||
| 2344 | for (i = 0; i < pi->ehdr->e_shnum; i++) { | ||
| 2345 | if (sechdrs[i].sh_type == SHT_NOBITS) | ||
| 2346 | continue; | ||
| 2347 | |||
| 2348 | sechdrs[i].sh_offset = (unsigned long)pi->ehdr + | ||
| 2349 | sechdrs[i].sh_offset; | ||
| 2350 | } | ||
| 2351 | |||
| 2352 | /* | ||
| 2353 | * Identify entry point section and make entry relative to section | ||
| 2354 | * start. | ||
| 2355 | */ | ||
| 2356 | entry = pi->ehdr->e_entry; | ||
| 2357 | for (i = 0; i < pi->ehdr->e_shnum; i++) { | ||
| 2358 | if (!(sechdrs[i].sh_flags & SHF_ALLOC)) | ||
| 2359 | continue; | ||
| 2360 | |||
| 2361 | if (!(sechdrs[i].sh_flags & SHF_EXECINSTR)) | ||
| 2362 | continue; | ||
| 2363 | |||
| 2364 | /* Make entry section relative */ | ||
| 2365 | if (sechdrs[i].sh_addr <= pi->ehdr->e_entry && | ||
| 2366 | ((sechdrs[i].sh_addr + sechdrs[i].sh_size) > | ||
| 2367 | pi->ehdr->e_entry)) { | ||
| 2368 | entry_sidx = i; | ||
| 2369 | entry -= sechdrs[i].sh_addr; | ||
| 2370 | break; | ||
| 2371 | } | ||
| 2372 | } | ||
| 2373 | |||
| 2374 | /* Determine how much memory is needed to load relocatable object. */ | ||
| 2375 | buf_align = 1; | ||
| 2376 | bss_align = 1; | ||
| 2377 | buf_sz = 0; | ||
| 2378 | bss_sz = 0; | ||
| 2379 | |||
| 2380 | for (i = 0; i < pi->ehdr->e_shnum; i++) { | ||
| 2381 | if (!(sechdrs[i].sh_flags & SHF_ALLOC)) | ||
| 2382 | continue; | ||
| 2383 | |||
| 2384 | align = sechdrs[i].sh_addralign; | ||
| 2385 | if (sechdrs[i].sh_type != SHT_NOBITS) { | ||
| 2386 | if (buf_align < align) | ||
| 2387 | buf_align = align; | ||
| 2388 | buf_sz = ALIGN(buf_sz, align); | ||
| 2389 | buf_sz += sechdrs[i].sh_size; | ||
| 2390 | } else { | ||
| 2391 | /* bss section */ | ||
| 2392 | if (bss_align < align) | ||
| 2393 | bss_align = align; | ||
| 2394 | bss_sz = ALIGN(bss_sz, align); | ||
| 2395 | bss_sz += sechdrs[i].sh_size; | ||
| 2396 | } | ||
| 2397 | } | ||
| 2398 | |||
| 2399 | /* Determine the bss padding required to align bss properly */ | ||
| 2400 | bss_pad = 0; | ||
| 2401 | if (buf_sz & (bss_align - 1)) | ||
| 2402 | bss_pad = bss_align - (buf_sz & (bss_align - 1)); | ||
| 2403 | |||
| 2404 | memsz = buf_sz + bss_pad + bss_sz; | ||
| 2405 | |||
| 2406 | /* Allocate buffer for purgatory */ | ||
| 2407 | purgatory_buf = vzalloc(buf_sz); | ||
| 2408 | if (!purgatory_buf) { | ||
| 2409 | ret = -ENOMEM; | ||
| 2410 | goto out; | ||
| 2411 | } | ||
| 2412 | |||
| 2413 | if (buf_align < bss_align) | ||
| 2414 | buf_align = bss_align; | ||
| 2415 | |||
| 2416 | /* Add buffer to segment list */ | ||
| 2417 | ret = kexec_add_buffer(image, purgatory_buf, buf_sz, memsz, | ||
| 2418 | buf_align, min, max, top_down, | ||
| 2419 | &pi->purgatory_load_addr); | ||
| 2420 | if (ret) | ||
| 2421 | goto out; | ||
| 2422 | |||
| 2423 | /* Load SHF_ALLOC sections */ | ||
| 2424 | buf_addr = purgatory_buf; | ||
| 2425 | load_addr = curr_load_addr = pi->purgatory_load_addr; | ||
| 2426 | bss_addr = load_addr + buf_sz + bss_pad; | ||
| 2427 | |||
| 2428 | for (i = 0; i < pi->ehdr->e_shnum; i++) { | ||
| 2429 | if (!(sechdrs[i].sh_flags & SHF_ALLOC)) | ||
| 2430 | continue; | ||
| 2431 | |||
| 2432 | align = sechdrs[i].sh_addralign; | ||
| 2433 | if (sechdrs[i].sh_type != SHT_NOBITS) { | ||
| 2434 | curr_load_addr = ALIGN(curr_load_addr, align); | ||
| 2435 | offset = curr_load_addr - load_addr; | ||
| 2436 | /* We already modifed ->sh_offset to keep src addr */ | ||
| 2437 | src = (char *) sechdrs[i].sh_offset; | ||
| 2438 | memcpy(buf_addr + offset, src, sechdrs[i].sh_size); | ||
| 2439 | |||
| 2440 | /* Store load address and source address of section */ | ||
| 2441 | sechdrs[i].sh_addr = curr_load_addr; | ||
| 2442 | |||
| 2443 | /* | ||
| 2444 | * This section got copied to temporary buffer. Update | ||
| 2445 | * ->sh_offset accordingly. | ||
| 2446 | */ | ||
| 2447 | sechdrs[i].sh_offset = (unsigned long)(buf_addr + offset); | ||
| 2448 | |||
| 2449 | /* Advance to the next address */ | ||
| 2450 | curr_load_addr += sechdrs[i].sh_size; | ||
| 2451 | } else { | ||
| 2452 | bss_addr = ALIGN(bss_addr, align); | ||
| 2453 | sechdrs[i].sh_addr = bss_addr; | ||
| 2454 | bss_addr += sechdrs[i].sh_size; | ||
| 2455 | } | ||
| 2456 | } | ||
| 2457 | |||
| 2458 | /* Update entry point based on load address of text section */ | ||
| 2459 | if (entry_sidx >= 0) | ||
| 2460 | entry += sechdrs[entry_sidx].sh_addr; | ||
| 2461 | |||
| 2462 | /* Make kernel jump to purgatory after shutdown */ | ||
| 2463 | image->start = entry; | ||
| 2464 | |||
| 2465 | /* Used later to get/set symbol values */ | ||
| 2466 | pi->sechdrs = sechdrs; | ||
| 2467 | |||
| 2468 | /* | ||
| 2469 | * Used later to identify which section is purgatory and skip it | ||
| 2470 | * from checksumming. | ||
| 2471 | */ | ||
| 2472 | pi->purgatory_buf = purgatory_buf; | ||
| 2473 | return ret; | ||
| 2474 | out: | ||
| 2475 | vfree(sechdrs); | ||
| 2476 | vfree(purgatory_buf); | ||
| 2477 | return ret; | ||
| 2478 | } | ||
| 2479 | |||
| 2480 | static int kexec_apply_relocations(struct kimage *image) | ||
| 2481 | { | ||
| 2482 | int i, ret; | ||
| 2483 | struct purgatory_info *pi = &image->purgatory_info; | ||
| 2484 | Elf_Shdr *sechdrs = pi->sechdrs; | ||
| 2485 | |||
| 2486 | /* Apply relocations */ | ||
| 2487 | for (i = 0; i < pi->ehdr->e_shnum; i++) { | ||
| 2488 | Elf_Shdr *section, *symtab; | ||
| 2489 | |||
| 2490 | if (sechdrs[i].sh_type != SHT_RELA && | ||
| 2491 | sechdrs[i].sh_type != SHT_REL) | ||
| 2492 | continue; | ||
| 2493 | |||
| 2494 | /* | ||
| 2495 | * For section of type SHT_RELA/SHT_REL, | ||
| 2496 | * ->sh_link contains section header index of associated | ||
| 2497 | * symbol table. And ->sh_info contains section header | ||
| 2498 | * index of section to which relocations apply. | ||
| 2499 | */ | ||
| 2500 | if (sechdrs[i].sh_info >= pi->ehdr->e_shnum || | ||
| 2501 | sechdrs[i].sh_link >= pi->ehdr->e_shnum) | ||
| 2502 | return -ENOEXEC; | ||
| 2503 | |||
| 2504 | section = &sechdrs[sechdrs[i].sh_info]; | ||
| 2505 | symtab = &sechdrs[sechdrs[i].sh_link]; | ||
| 2506 | |||
| 2507 | if (!(section->sh_flags & SHF_ALLOC)) | ||
| 2508 | continue; | ||
| 2509 | |||
| 2510 | /* | ||
| 2511 | * symtab->sh_link contain section header index of associated | ||
| 2512 | * string table. | ||
| 2513 | */ | ||
| 2514 | if (symtab->sh_link >= pi->ehdr->e_shnum) | ||
| 2515 | /* Invalid section number? */ | ||
| 2516 | continue; | ||
| 2517 | |||
| 2518 | /* | ||
| 2519 | * Respective archicture needs to provide support for applying | ||
| 2520 | * relocations of type SHT_RELA/SHT_REL. | ||
| 2521 | */ | ||
| 2522 | if (sechdrs[i].sh_type == SHT_RELA) | ||
| 2523 | ret = arch_kexec_apply_relocations_add(pi->ehdr, | ||
| 2524 | sechdrs, i); | ||
| 2525 | else if (sechdrs[i].sh_type == SHT_REL) | ||
| 2526 | ret = arch_kexec_apply_relocations(pi->ehdr, | ||
| 2527 | sechdrs, i); | ||
| 2528 | if (ret) | ||
| 2529 | return ret; | ||
| 2530 | } | ||
| 2531 | |||
| 2532 | return 0; | ||
| 2533 | } | ||
| 2534 | |||
| 2535 | /* Load relocatable purgatory object and relocate it appropriately */ | ||
| 2536 | int kexec_load_purgatory(struct kimage *image, unsigned long min, | ||
| 2537 | unsigned long max, int top_down, | ||
| 2538 | unsigned long *load_addr) | ||
| 2539 | { | ||
| 2540 | struct purgatory_info *pi = &image->purgatory_info; | ||
| 2541 | int ret; | ||
| 2542 | |||
| 2543 | if (kexec_purgatory_size <= 0) | ||
| 2544 | return -EINVAL; | ||
| 2545 | |||
| 2546 | if (kexec_purgatory_size < sizeof(Elf_Ehdr)) | ||
| 2547 | return -ENOEXEC; | ||
| 2548 | |||
| 2549 | pi->ehdr = (Elf_Ehdr *)kexec_purgatory; | ||
| 2550 | |||
| 2551 | if (memcmp(pi->ehdr->e_ident, ELFMAG, SELFMAG) != 0 | ||
| 2552 | || pi->ehdr->e_type != ET_REL | ||
| 2553 | || !elf_check_arch(pi->ehdr) | ||
| 2554 | || pi->ehdr->e_shentsize != sizeof(Elf_Shdr)) | ||
| 2555 | return -ENOEXEC; | ||
| 2556 | |||
| 2557 | if (pi->ehdr->e_shoff >= kexec_purgatory_size | ||
| 2558 | || (pi->ehdr->e_shnum * sizeof(Elf_Shdr) > | ||
| 2559 | kexec_purgatory_size - pi->ehdr->e_shoff)) | ||
| 2560 | return -ENOEXEC; | ||
| 2561 | |||
| 2562 | ret = __kexec_load_purgatory(image, min, max, top_down); | ||
| 2563 | if (ret) | ||
| 2564 | return ret; | ||
| 2565 | |||
| 2566 | ret = kexec_apply_relocations(image); | ||
| 2567 | if (ret) | ||
| 2568 | goto out; | ||
| 2569 | |||
| 2570 | *load_addr = pi->purgatory_load_addr; | ||
| 2571 | return 0; | ||
| 2572 | out: | ||
| 2573 | vfree(pi->sechdrs); | ||
| 2574 | vfree(pi->purgatory_buf); | ||
| 2575 | return ret; | ||
| 2576 | } | ||
| 2577 | |||
| 2578 | static Elf_Sym *kexec_purgatory_find_symbol(struct purgatory_info *pi, | ||
| 2579 | const char *name) | ||
| 2580 | { | ||
| 2581 | Elf_Sym *syms; | ||
| 2582 | Elf_Shdr *sechdrs; | ||
| 2583 | Elf_Ehdr *ehdr; | ||
| 2584 | int i, k; | ||
| 2585 | const char *strtab; | ||
| 2586 | |||
| 2587 | if (!pi->sechdrs || !pi->ehdr) | ||
| 2588 | return NULL; | ||
| 2589 | |||
| 2590 | sechdrs = pi->sechdrs; | ||
| 2591 | ehdr = pi->ehdr; | ||
| 2592 | |||
| 2593 | for (i = 0; i < ehdr->e_shnum; i++) { | ||
| 2594 | if (sechdrs[i].sh_type != SHT_SYMTAB) | ||
| 2595 | continue; | ||
| 2596 | |||
| 2597 | if (sechdrs[i].sh_link >= ehdr->e_shnum) | ||
| 2598 | /* Invalid strtab section number */ | ||
| 2599 | continue; | ||
| 2600 | strtab = (char *)sechdrs[sechdrs[i].sh_link].sh_offset; | ||
| 2601 | syms = (Elf_Sym *)sechdrs[i].sh_offset; | ||
| 2602 | |||
| 2603 | /* Go through symbols for a match */ | ||
| 2604 | for (k = 0; k < sechdrs[i].sh_size/sizeof(Elf_Sym); k++) { | ||
| 2605 | if (ELF_ST_BIND(syms[k].st_info) != STB_GLOBAL) | ||
| 2606 | continue; | ||
| 2607 | |||
| 2608 | if (strcmp(strtab + syms[k].st_name, name) != 0) | ||
| 2609 | continue; | ||
| 2610 | |||
| 2611 | if (syms[k].st_shndx == SHN_UNDEF || | ||
| 2612 | syms[k].st_shndx >= ehdr->e_shnum) { | ||
| 2613 | pr_debug("Symbol: %s has bad section index %d.\n", | ||
| 2614 | name, syms[k].st_shndx); | ||
| 2615 | return NULL; | ||
| 2616 | } | ||
| 2617 | |||
| 2618 | /* Found the symbol we are looking for */ | ||
| 2619 | return &syms[k]; | ||
| 2620 | } | ||
| 2621 | } | ||
| 2622 | |||
| 2623 | return NULL; | ||
| 2624 | } | ||
| 2625 | |||
| 2626 | void *kexec_purgatory_get_symbol_addr(struct kimage *image, const char *name) | ||
| 2627 | { | ||
| 2628 | struct purgatory_info *pi = &image->purgatory_info; | ||
| 2629 | Elf_Sym *sym; | ||
| 2630 | Elf_Shdr *sechdr; | ||
| 2631 | |||
| 2632 | sym = kexec_purgatory_find_symbol(pi, name); | ||
| 2633 | if (!sym) | ||
| 2634 | return ERR_PTR(-EINVAL); | ||
| 2635 | |||
| 2636 | sechdr = &pi->sechdrs[sym->st_shndx]; | ||
| 2637 | |||
| 2638 | /* | ||
| 2639 | * Returns the address where symbol will finally be loaded after | ||
| 2640 | * kexec_load_segment() | ||
| 2641 | */ | ||
| 2642 | return (void *)(sechdr->sh_addr + sym->st_value); | ||
| 2643 | } | ||
| 2644 | |||
| 2645 | /* | ||
| 2646 | * Get or set value of a symbol. If "get_value" is true, symbol value is | ||
| 2647 | * returned in buf otherwise symbol value is set based on value in buf. | ||
| 2648 | */ | ||
| 2649 | int kexec_purgatory_get_set_symbol(struct kimage *image, const char *name, | ||
| 2650 | void *buf, unsigned int size, bool get_value) | ||
| 2651 | { | ||
| 2652 | Elf_Sym *sym; | ||
| 2653 | Elf_Shdr *sechdrs; | ||
| 2654 | struct purgatory_info *pi = &image->purgatory_info; | ||
| 2655 | char *sym_buf; | ||
| 2656 | |||
| 2657 | sym = kexec_purgatory_find_symbol(pi, name); | ||
| 2658 | if (!sym) | ||
| 2659 | return -EINVAL; | ||
| 2660 | |||
| 2661 | if (sym->st_size != size) { | ||
| 2662 | pr_err("symbol %s size mismatch: expected %lu actual %u\n", | ||
| 2663 | name, (unsigned long)sym->st_size, size); | ||
| 2664 | return -EINVAL; | ||
| 2665 | } | ||
| 2666 | |||
| 2667 | sechdrs = pi->sechdrs; | ||
| 2668 | |||
| 2669 | if (sechdrs[sym->st_shndx].sh_type == SHT_NOBITS) { | ||
| 2670 | pr_err("symbol %s is in a bss section. Cannot %s\n", name, | ||
| 2671 | get_value ? "get" : "set"); | ||
| 2672 | return -EINVAL; | ||
| 2673 | } | ||
| 2674 | |||
| 2675 | sym_buf = (unsigned char *)sechdrs[sym->st_shndx].sh_offset + | ||
| 2676 | sym->st_value; | ||
| 2677 | |||
| 2678 | if (get_value) | ||
| 2679 | memcpy((void *)buf, sym_buf, size); | ||
| 2680 | else | ||
| 2681 | memcpy((void *)sym_buf, buf, size); | ||
| 2682 | |||
| 2683 | return 0; | ||
| 2684 | } | ||
| 2685 | |||
| 1635 | /* | 2686 | /* |
| 1636 | * Move into place and start executing a preloaded standalone | 2687 | * Move into place and start executing a preloaded standalone |
| 1637 | * executable. If nothing was preloaded return an error. | 2688 | * executable. If nothing was preloaded return an error. |
diff --git a/kernel/panic.c b/kernel/panic.c index 62e16cef9cc2..d09dc5c32c67 100644 --- a/kernel/panic.c +++ b/kernel/panic.c | |||
| @@ -224,6 +224,7 @@ static const struct tnt tnts[] = { | |||
| 224 | { TAINT_FIRMWARE_WORKAROUND, 'I', ' ' }, | 224 | { TAINT_FIRMWARE_WORKAROUND, 'I', ' ' }, |
| 225 | { TAINT_OOT_MODULE, 'O', ' ' }, | 225 | { TAINT_OOT_MODULE, 'O', ' ' }, |
| 226 | { TAINT_UNSIGNED_MODULE, 'E', ' ' }, | 226 | { TAINT_UNSIGNED_MODULE, 'E', ' ' }, |
| 227 | { TAINT_SOFTLOCKUP, 'L', ' ' }, | ||
| 227 | }; | 228 | }; |
| 228 | 229 | ||
| 229 | /** | 230 | /** |
diff --git a/kernel/resource.c b/kernel/resource.c index 3c2237ac32db..da14b8d09296 100644 --- a/kernel/resource.c +++ b/kernel/resource.c | |||
| @@ -59,10 +59,12 @@ static DEFINE_RWLOCK(resource_lock); | |||
| 59 | static struct resource *bootmem_resource_free; | 59 | static struct resource *bootmem_resource_free; |
| 60 | static DEFINE_SPINLOCK(bootmem_resource_lock); | 60 | static DEFINE_SPINLOCK(bootmem_resource_lock); |
| 61 | 61 | ||
| 62 | static void *r_next(struct seq_file *m, void *v, loff_t *pos) | 62 | static struct resource *next_resource(struct resource *p, bool sibling_only) |
| 63 | { | 63 | { |
| 64 | struct resource *p = v; | 64 | /* Caller wants to traverse through siblings only */ |
| 65 | (*pos)++; | 65 | if (sibling_only) |
| 66 | return p->sibling; | ||
| 67 | |||
| 66 | if (p->child) | 68 | if (p->child) |
| 67 | return p->child; | 69 | return p->child; |
| 68 | while (!p->sibling && p->parent) | 70 | while (!p->sibling && p->parent) |
| @@ -70,6 +72,13 @@ static void *r_next(struct seq_file *m, void *v, loff_t *pos) | |||
| 70 | return p->sibling; | 72 | return p->sibling; |
| 71 | } | 73 | } |
| 72 | 74 | ||
| 75 | static void *r_next(struct seq_file *m, void *v, loff_t *pos) | ||
| 76 | { | ||
| 77 | struct resource *p = v; | ||
| 78 | (*pos)++; | ||
| 79 | return (void *)next_resource(p, false); | ||
| 80 | } | ||
| 81 | |||
| 73 | #ifdef CONFIG_PROC_FS | 82 | #ifdef CONFIG_PROC_FS |
| 74 | 83 | ||
| 75 | enum { MAX_IORES_LEVEL = 5 }; | 84 | enum { MAX_IORES_LEVEL = 5 }; |
| @@ -322,16 +331,19 @@ int release_resource(struct resource *old) | |||
| 322 | 331 | ||
| 323 | EXPORT_SYMBOL(release_resource); | 332 | EXPORT_SYMBOL(release_resource); |
| 324 | 333 | ||
| 325 | #if !defined(CONFIG_ARCH_HAS_WALK_MEMORY) | ||
| 326 | /* | 334 | /* |
| 327 | * Finds the lowest memory reosurce exists within [res->start.res->end) | 335 | * Finds the lowest iomem reosurce exists with-in [res->start.res->end) |
| 328 | * the caller must specify res->start, res->end, res->flags and "name". | 336 | * the caller must specify res->start, res->end, res->flags and "name". |
| 329 | * If found, returns 0, res is overwritten, if not found, returns -1. | 337 | * If found, returns 0, res is overwritten, if not found, returns -1. |
| 338 | * This walks through whole tree and not just first level children | ||
| 339 | * until and unless first_level_children_only is true. | ||
| 330 | */ | 340 | */ |
| 331 | static int find_next_system_ram(struct resource *res, char *name) | 341 | static int find_next_iomem_res(struct resource *res, char *name, |
| 342 | bool first_level_children_only) | ||
| 332 | { | 343 | { |
| 333 | resource_size_t start, end; | 344 | resource_size_t start, end; |
| 334 | struct resource *p; | 345 | struct resource *p; |
| 346 | bool sibling_only = false; | ||
| 335 | 347 | ||
| 336 | BUG_ON(!res); | 348 | BUG_ON(!res); |
| 337 | 349 | ||
| @@ -340,8 +352,14 @@ static int find_next_system_ram(struct resource *res, char *name) | |||
| 340 | BUG_ON(start >= end); | 352 | BUG_ON(start >= end); |
| 341 | 353 | ||
| 342 | read_lock(&resource_lock); | 354 | read_lock(&resource_lock); |
| 343 | for (p = iomem_resource.child; p ; p = p->sibling) { | 355 | |
| 344 | /* system ram is just marked as IORESOURCE_MEM */ | 356 | if (first_level_children_only) { |
| 357 | p = iomem_resource.child; | ||
| 358 | sibling_only = true; | ||
| 359 | } else | ||
| 360 | p = &iomem_resource; | ||
| 361 | |||
| 362 | while ((p = next_resource(p, sibling_only))) { | ||
| 345 | if (p->flags != res->flags) | 363 | if (p->flags != res->flags) |
| 346 | continue; | 364 | continue; |
| 347 | if (name && strcmp(p->name, name)) | 365 | if (name && strcmp(p->name, name)) |
| @@ -353,6 +371,7 @@ static int find_next_system_ram(struct resource *res, char *name) | |||
| 353 | if ((p->end >= start) && (p->start < end)) | 371 | if ((p->end >= start) && (p->start < end)) |
| 354 | break; | 372 | break; |
| 355 | } | 373 | } |
| 374 | |||
| 356 | read_unlock(&resource_lock); | 375 | read_unlock(&resource_lock); |
| 357 | if (!p) | 376 | if (!p) |
| 358 | return -1; | 377 | return -1; |
| @@ -365,6 +384,70 @@ static int find_next_system_ram(struct resource *res, char *name) | |||
| 365 | } | 384 | } |
| 366 | 385 | ||
| 367 | /* | 386 | /* |
| 387 | * Walks through iomem resources and calls func() with matching resource | ||
| 388 | * ranges. This walks through whole tree and not just first level children. | ||
| 389 | * All the memory ranges which overlap start,end and also match flags and | ||
| 390 | * name are valid candidates. | ||
| 391 | * | ||
| 392 | * @name: name of resource | ||
| 393 | * @flags: resource flags | ||
| 394 | * @start: start addr | ||
| 395 | * @end: end addr | ||
| 396 | */ | ||
| 397 | int walk_iomem_res(char *name, unsigned long flags, u64 start, u64 end, | ||
| 398 | void *arg, int (*func)(u64, u64, void *)) | ||
| 399 | { | ||
| 400 | struct resource res; | ||
| 401 | u64 orig_end; | ||
| 402 | int ret = -1; | ||
| 403 | |||
| 404 | res.start = start; | ||
| 405 | res.end = end; | ||
| 406 | res.flags = flags; | ||
| 407 | orig_end = res.end; | ||
| 408 | while ((res.start < res.end) && | ||
| 409 | (!find_next_iomem_res(&res, name, false))) { | ||
| 410 | ret = (*func)(res.start, res.end, arg); | ||
| 411 | if (ret) | ||
| 412 | break; | ||
| 413 | res.start = res.end + 1; | ||
| 414 | res.end = orig_end; | ||
| 415 | } | ||
| 416 | return ret; | ||
| 417 | } | ||
| 418 | |||
| 419 | /* | ||
| 420 | * This function calls callback against all memory range of "System RAM" | ||
| 421 | * which are marked as IORESOURCE_MEM and IORESOUCE_BUSY. | ||
| 422 | * Now, this function is only for "System RAM". This function deals with | ||
| 423 | * full ranges and not pfn. If resources are not pfn aligned, dealing | ||
| 424 | * with pfn can truncate ranges. | ||
| 425 | */ | ||
| 426 | int walk_system_ram_res(u64 start, u64 end, void *arg, | ||
| 427 | int (*func)(u64, u64, void *)) | ||
| 428 | { | ||
| 429 | struct resource res; | ||
| 430 | u64 orig_end; | ||
| 431 | int ret = -1; | ||
| 432 | |||
| 433 | res.start = start; | ||
| 434 | res.end = end; | ||
| 435 | res.flags = IORESOURCE_MEM | IORESOURCE_BUSY; | ||
| 436 | orig_end = res.end; | ||
| 437 | while ((res.start < res.end) && | ||
| 438 | (!find_next_iomem_res(&res, "System RAM", true))) { | ||
| 439 | ret = (*func)(res.start, res.end, arg); | ||
| 440 | if (ret) | ||
| 441 | break; | ||
| 442 | res.start = res.end + 1; | ||
| 443 | res.end = orig_end; | ||
| 444 | } | ||
| 445 | return ret; | ||
| 446 | } | ||
| 447 | |||
| 448 | #if !defined(CONFIG_ARCH_HAS_WALK_MEMORY) | ||
| 449 | |||
| 450 | /* | ||
| 368 | * This function calls callback against all memory range of "System RAM" | 451 | * This function calls callback against all memory range of "System RAM" |
| 369 | * which are marked as IORESOURCE_MEM and IORESOUCE_BUSY. | 452 | * which are marked as IORESOURCE_MEM and IORESOUCE_BUSY. |
| 370 | * Now, this function is only for "System RAM". | 453 | * Now, this function is only for "System RAM". |
| @@ -382,7 +465,7 @@ int walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages, | |||
| 382 | res.flags = IORESOURCE_MEM | IORESOURCE_BUSY; | 465 | res.flags = IORESOURCE_MEM | IORESOURCE_BUSY; |
| 383 | orig_end = res.end; | 466 | orig_end = res.end; |
| 384 | while ((res.start < res.end) && | 467 | while ((res.start < res.end) && |
| 385 | (find_next_system_ram(&res, "System RAM") >= 0)) { | 468 | (find_next_iomem_res(&res, "System RAM", true) >= 0)) { |
| 386 | pfn = (res.start + PAGE_SIZE - 1) >> PAGE_SHIFT; | 469 | pfn = (res.start + PAGE_SIZE - 1) >> PAGE_SHIFT; |
| 387 | end_pfn = (res.end + 1) >> PAGE_SHIFT; | 470 | end_pfn = (res.end + 1) >> PAGE_SHIFT; |
| 388 | if (end_pfn > pfn) | 471 | if (end_pfn > pfn) |
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c index 2904a2105914..391d4ddb6f4b 100644 --- a/kernel/sys_ni.c +++ b/kernel/sys_ni.c | |||
| @@ -25,6 +25,7 @@ cond_syscall(sys_swapon); | |||
| 25 | cond_syscall(sys_swapoff); | 25 | cond_syscall(sys_swapoff); |
| 26 | cond_syscall(sys_kexec_load); | 26 | cond_syscall(sys_kexec_load); |
| 27 | cond_syscall(compat_sys_kexec_load); | 27 | cond_syscall(compat_sys_kexec_load); |
| 28 | cond_syscall(sys_kexec_file_load); | ||
| 28 | cond_syscall(sys_init_module); | 29 | cond_syscall(sys_init_module); |
| 29 | cond_syscall(sys_finit_module); | 30 | cond_syscall(sys_finit_module); |
| 30 | cond_syscall(sys_delete_module); | 31 | cond_syscall(sys_delete_module); |
| @@ -197,6 +198,7 @@ cond_syscall(compat_sys_timerfd_settime); | |||
| 197 | cond_syscall(compat_sys_timerfd_gettime); | 198 | cond_syscall(compat_sys_timerfd_gettime); |
| 198 | cond_syscall(sys_eventfd); | 199 | cond_syscall(sys_eventfd); |
| 199 | cond_syscall(sys_eventfd2); | 200 | cond_syscall(sys_eventfd2); |
| 201 | cond_syscall(sys_memfd_create); | ||
| 200 | 202 | ||
| 201 | /* performance counters: */ | 203 | /* performance counters: */ |
| 202 | cond_syscall(sys_perf_event_open); | 204 | cond_syscall(sys_perf_event_open); |
diff --git a/kernel/test_kprobes.c b/kernel/test_kprobes.c index 12d6ebbfdd83..0dbab6d1acb4 100644 --- a/kernel/test_kprobes.c +++ b/kernel/test_kprobes.c | |||
| @@ -14,6 +14,8 @@ | |||
| 14 | * the GNU General Public License for more details. | 14 | * the GNU General Public License for more details. |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | #define pr_fmt(fmt) "Kprobe smoke test: " fmt | ||
| 18 | |||
| 17 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
| 18 | #include <linux/kprobes.h> | 20 | #include <linux/kprobes.h> |
| 19 | #include <linux/random.h> | 21 | #include <linux/random.h> |
| @@ -41,8 +43,7 @@ static void kp_post_handler(struct kprobe *p, struct pt_regs *regs, | |||
| 41 | { | 43 | { |
| 42 | if (preh_val != (rand1 / div_factor)) { | 44 | if (preh_val != (rand1 / div_factor)) { |
| 43 | handler_errors++; | 45 | handler_errors++; |
| 44 | printk(KERN_ERR "Kprobe smoke test failed: " | 46 | pr_err("incorrect value in post_handler\n"); |
| 45 | "incorrect value in post_handler\n"); | ||
| 46 | } | 47 | } |
| 47 | posth_val = preh_val + div_factor; | 48 | posth_val = preh_val + div_factor; |
| 48 | } | 49 | } |
| @@ -59,8 +60,7 @@ static int test_kprobe(void) | |||
| 59 | 60 | ||
| 60 | ret = register_kprobe(&kp); | 61 | ret = register_kprobe(&kp); |
| 61 | if (ret < 0) { | 62 | if (ret < 0) { |
| 62 | printk(KERN_ERR "Kprobe smoke test failed: " | 63 | pr_err("register_kprobe returned %d\n", ret); |
| 63 | "register_kprobe returned %d\n", ret); | ||
| 64 | return ret; | 64 | return ret; |
| 65 | } | 65 | } |
| 66 | 66 | ||
| @@ -68,14 +68,12 @@ static int test_kprobe(void) | |||
| 68 | unregister_kprobe(&kp); | 68 | unregister_kprobe(&kp); |
| 69 | 69 | ||
| 70 | if (preh_val == 0) { | 70 | if (preh_val == 0) { |
| 71 | printk(KERN_ERR "Kprobe smoke test failed: " | 71 | pr_err("kprobe pre_handler not called\n"); |
| 72 | "kprobe pre_handler not called\n"); | ||
| 73 | handler_errors++; | 72 | handler_errors++; |
| 74 | } | 73 | } |
| 75 | 74 | ||
| 76 | if (posth_val == 0) { | 75 | if (posth_val == 0) { |
| 77 | printk(KERN_ERR "Kprobe smoke test failed: " | 76 | pr_err("kprobe post_handler not called\n"); |
| 78 | "kprobe post_handler not called\n"); | ||
| 79 | handler_errors++; | 77 | handler_errors++; |
| 80 | } | 78 | } |
| 81 | 79 | ||
| @@ -98,8 +96,7 @@ static void kp_post_handler2(struct kprobe *p, struct pt_regs *regs, | |||
| 98 | { | 96 | { |
| 99 | if (preh_val != (rand1 / div_factor) + 1) { | 97 | if (preh_val != (rand1 / div_factor) + 1) { |
| 100 | handler_errors++; | 98 | handler_errors++; |
| 101 | printk(KERN_ERR "Kprobe smoke test failed: " | 99 | pr_err("incorrect value in post_handler2\n"); |
| 102 | "incorrect value in post_handler2\n"); | ||
| 103 | } | 100 | } |
| 104 | posth_val = preh_val + div_factor; | 101 | posth_val = preh_val + div_factor; |
| 105 | } | 102 | } |
| @@ -120,8 +117,7 @@ static int test_kprobes(void) | |||
| 120 | kp.flags = 0; | 117 | kp.flags = 0; |
| 121 | ret = register_kprobes(kps, 2); | 118 | ret = register_kprobes(kps, 2); |
| 122 | if (ret < 0) { | 119 | if (ret < 0) { |
| 123 | printk(KERN_ERR "Kprobe smoke test failed: " | 120 | pr_err("register_kprobes returned %d\n", ret); |
| 124 | "register_kprobes returned %d\n", ret); | ||
| 125 | return ret; | 121 | return ret; |
| 126 | } | 122 | } |
| 127 | 123 | ||
| @@ -130,14 +126,12 @@ static int test_kprobes(void) | |||
| 130 | ret = target(rand1); | 126 | ret = target(rand1); |
| 131 | 127 | ||
| 132 | if (preh_val == 0) { | 128 | if (preh_val == 0) { |
| 133 | printk(KERN_ERR "Kprobe smoke test failed: " | 129 | pr_err("kprobe pre_handler not called\n"); |
| 134 | "kprobe pre_handler not called\n"); | ||
| 135 | handler_errors++; | 130 | handler_errors++; |
| 136 | } | 131 | } |
| 137 | 132 | ||
| 138 | if (posth_val == 0) { | 133 | if (posth_val == 0) { |
| 139 | printk(KERN_ERR "Kprobe smoke test failed: " | 134 | pr_err("kprobe post_handler not called\n"); |
| 140 | "kprobe post_handler not called\n"); | ||
| 141 | handler_errors++; | 135 | handler_errors++; |
| 142 | } | 136 | } |
| 143 | 137 | ||
| @@ -146,14 +140,12 @@ static int test_kprobes(void) | |||
| 146 | ret = target2(rand1); | 140 | ret = target2(rand1); |
| 147 | 141 | ||
| 148 | if (preh_val == 0) { | 142 | if (preh_val == 0) { |
| 149 | printk(KERN_ERR "Kprobe smoke test failed: " | 143 | pr_err("kprobe pre_handler2 not called\n"); |
| 150 | "kprobe pre_handler2 not called\n"); | ||
| 151 | handler_errors++; | 144 | handler_errors++; |
| 152 | } | 145 | } |
| 153 | 146 | ||
| 154 | if (posth_val == 0) { | 147 | if (posth_val == 0) { |
| 155 | printk(KERN_ERR "Kprobe smoke test failed: " | 148 | pr_err("kprobe post_handler2 not called\n"); |
| 156 | "kprobe post_handler2 not called\n"); | ||
| 157 | handler_errors++; | 149 | handler_errors++; |
| 158 | } | 150 | } |
| 159 | 151 | ||
| @@ -166,8 +158,7 @@ static u32 j_kprobe_target(u32 value) | |||
| 166 | { | 158 | { |
| 167 | if (value != rand1) { | 159 | if (value != rand1) { |
| 168 | handler_errors++; | 160 | handler_errors++; |
| 169 | printk(KERN_ERR "Kprobe smoke test failed: " | 161 | pr_err("incorrect value in jprobe handler\n"); |
| 170 | "incorrect value in jprobe handler\n"); | ||
| 171 | } | 162 | } |
| 172 | 163 | ||
| 173 | jph_val = rand1; | 164 | jph_val = rand1; |
| @@ -186,16 +177,14 @@ static int test_jprobe(void) | |||
| 186 | 177 | ||
| 187 | ret = register_jprobe(&jp); | 178 | ret = register_jprobe(&jp); |
| 188 | if (ret < 0) { | 179 | if (ret < 0) { |
| 189 | printk(KERN_ERR "Kprobe smoke test failed: " | 180 | pr_err("register_jprobe returned %d\n", ret); |
| 190 | "register_jprobe returned %d\n", ret); | ||
| 191 | return ret; | 181 | return ret; |
| 192 | } | 182 | } |
| 193 | 183 | ||
| 194 | ret = target(rand1); | 184 | ret = target(rand1); |
| 195 | unregister_jprobe(&jp); | 185 | unregister_jprobe(&jp); |
| 196 | if (jph_val == 0) { | 186 | if (jph_val == 0) { |
| 197 | printk(KERN_ERR "Kprobe smoke test failed: " | 187 | pr_err("jprobe handler not called\n"); |
| 198 | "jprobe handler not called\n"); | ||
| 199 | handler_errors++; | 188 | handler_errors++; |
| 200 | } | 189 | } |
| 201 | 190 | ||
| @@ -217,24 +206,21 @@ static int test_jprobes(void) | |||
| 217 | jp.kp.flags = 0; | 206 | jp.kp.flags = 0; |
| 218 | ret = register_jprobes(jps, 2); | 207 | ret = register_jprobes(jps, 2); |
| 219 | if (ret < 0) { | 208 | if (ret < 0) { |
| 220 | printk(KERN_ERR "Kprobe smoke test failed: " | 209 | pr_err("register_jprobes returned %d\n", ret); |
| 221 | "register_jprobes returned %d\n", ret); | ||
| 222 | return ret; | 210 | return ret; |
| 223 | } | 211 | } |
| 224 | 212 | ||
| 225 | jph_val = 0; | 213 | jph_val = 0; |
| 226 | ret = target(rand1); | 214 | ret = target(rand1); |
| 227 | if (jph_val == 0) { | 215 | if (jph_val == 0) { |
| 228 | printk(KERN_ERR "Kprobe smoke test failed: " | 216 | pr_err("jprobe handler not called\n"); |
| 229 | "jprobe handler not called\n"); | ||
| 230 | handler_errors++; | 217 | handler_errors++; |
| 231 | } | 218 | } |
| 232 | 219 | ||
| 233 | jph_val = 0; | 220 | jph_val = 0; |
| 234 | ret = target2(rand1); | 221 | ret = target2(rand1); |
| 235 | if (jph_val == 0) { | 222 | if (jph_val == 0) { |
| 236 | printk(KERN_ERR "Kprobe smoke test failed: " | 223 | pr_err("jprobe handler2 not called\n"); |
| 237 | "jprobe handler2 not called\n"); | ||
| 238 | handler_errors++; | 224 | handler_errors++; |
| 239 | } | 225 | } |
| 240 | unregister_jprobes(jps, 2); | 226 | unregister_jprobes(jps, 2); |
| @@ -256,13 +242,11 @@ static int return_handler(struct kretprobe_instance *ri, struct pt_regs *regs) | |||
| 256 | 242 | ||
| 257 | if (ret != (rand1 / div_factor)) { | 243 | if (ret != (rand1 / div_factor)) { |
| 258 | handler_errors++; | 244 | handler_errors++; |
| 259 | printk(KERN_ERR "Kprobe smoke test failed: " | 245 | pr_err("incorrect value in kretprobe handler\n"); |
| 260 | "incorrect value in kretprobe handler\n"); | ||
| 261 | } | 246 | } |
| 262 | if (krph_val == 0) { | 247 | if (krph_val == 0) { |
| 263 | handler_errors++; | 248 | handler_errors++; |
| 264 | printk(KERN_ERR "Kprobe smoke test failed: " | 249 | pr_err("call to kretprobe entry handler failed\n"); |
| 265 | "call to kretprobe entry handler failed\n"); | ||
| 266 | } | 250 | } |
| 267 | 251 | ||
| 268 | krph_val = rand1; | 252 | krph_val = rand1; |
| @@ -281,16 +265,14 @@ static int test_kretprobe(void) | |||
| 281 | 265 | ||
| 282 | ret = register_kretprobe(&rp); | 266 | ret = register_kretprobe(&rp); |
| 283 | if (ret < 0) { | 267 | if (ret < 0) { |
| 284 | printk(KERN_ERR "Kprobe smoke test failed: " | 268 | pr_err("register_kretprobe returned %d\n", ret); |
| 285 | "register_kretprobe returned %d\n", ret); | ||
| 286 | return ret; | 269 | return ret; |
| 287 | } | 270 | } |
| 288 | 271 | ||
| 289 | ret = target(rand1); | 272 | ret = target(rand1); |
| 290 | unregister_kretprobe(&rp); | 273 | unregister_kretprobe(&rp); |
| 291 | if (krph_val != rand1) { | 274 | if (krph_val != rand1) { |
| 292 | printk(KERN_ERR "Kprobe smoke test failed: " | 275 | pr_err("kretprobe handler not called\n"); |
| 293 | "kretprobe handler not called\n"); | ||
| 294 | handler_errors++; | 276 | handler_errors++; |
| 295 | } | 277 | } |
| 296 | 278 | ||
| @@ -303,13 +285,11 @@ static int return_handler2(struct kretprobe_instance *ri, struct pt_regs *regs) | |||
| 303 | 285 | ||
| 304 | if (ret != (rand1 / div_factor) + 1) { | 286 | if (ret != (rand1 / div_factor) + 1) { |
| 305 | handler_errors++; | 287 | handler_errors++; |
| 306 | printk(KERN_ERR "Kprobe smoke test failed: " | 288 | pr_err("incorrect value in kretprobe handler2\n"); |
| 307 | "incorrect value in kretprobe handler2\n"); | ||
| 308 | } | 289 | } |
| 309 | if (krph_val == 0) { | 290 | if (krph_val == 0) { |
| 310 | handler_errors++; | 291 | handler_errors++; |
| 311 | printk(KERN_ERR "Kprobe smoke test failed: " | 292 | pr_err("call to kretprobe entry handler failed\n"); |
| 312 | "call to kretprobe entry handler failed\n"); | ||
| 313 | } | 293 | } |
| 314 | 294 | ||
| 315 | krph_val = rand1; | 295 | krph_val = rand1; |
| @@ -332,24 +312,21 @@ static int test_kretprobes(void) | |||
| 332 | rp.kp.flags = 0; | 312 | rp.kp.flags = 0; |
| 333 | ret = register_kretprobes(rps, 2); | 313 | ret = register_kretprobes(rps, 2); |
| 334 | if (ret < 0) { | 314 | if (ret < 0) { |
| 335 | printk(KERN_ERR "Kprobe smoke test failed: " | 315 | pr_err("register_kretprobe returned %d\n", ret); |
| 336 | "register_kretprobe returned %d\n", ret); | ||
| 337 | return ret; | 316 | return ret; |
| 338 | } | 317 | } |
| 339 | 318 | ||
| 340 | krph_val = 0; | 319 | krph_val = 0; |
| 341 | ret = target(rand1); | 320 | ret = target(rand1); |
| 342 | if (krph_val != rand1) { | 321 | if (krph_val != rand1) { |
| 343 | printk(KERN_ERR "Kprobe smoke test failed: " | 322 | pr_err("kretprobe handler not called\n"); |
| 344 | "kretprobe handler not called\n"); | ||
| 345 | handler_errors++; | 323 | handler_errors++; |
| 346 | } | 324 | } |
| 347 | 325 | ||
| 348 | krph_val = 0; | 326 | krph_val = 0; |
| 349 | ret = target2(rand1); | 327 | ret = target2(rand1); |
| 350 | if (krph_val != rand1) { | 328 | if (krph_val != rand1) { |
| 351 | printk(KERN_ERR "Kprobe smoke test failed: " | 329 | pr_err("kretprobe handler2 not called\n"); |
| 352 | "kretprobe handler2 not called\n"); | ||
| 353 | handler_errors++; | 330 | handler_errors++; |
| 354 | } | 331 | } |
| 355 | unregister_kretprobes(rps, 2); | 332 | unregister_kretprobes(rps, 2); |
| @@ -368,7 +345,7 @@ int init_test_probes(void) | |||
| 368 | rand1 = prandom_u32(); | 345 | rand1 = prandom_u32(); |
| 369 | } while (rand1 <= div_factor); | 346 | } while (rand1 <= div_factor); |
| 370 | 347 | ||
| 371 | printk(KERN_INFO "Kprobe smoke test started\n"); | 348 | pr_info("started\n"); |
| 372 | num_tests++; | 349 | num_tests++; |
| 373 | ret = test_kprobe(); | 350 | ret = test_kprobe(); |
| 374 | if (ret < 0) | 351 | if (ret < 0) |
| @@ -402,13 +379,11 @@ int init_test_probes(void) | |||
| 402 | #endif /* CONFIG_KRETPROBES */ | 379 | #endif /* CONFIG_KRETPROBES */ |
| 403 | 380 | ||
| 404 | if (errors) | 381 | if (errors) |
| 405 | printk(KERN_ERR "BUG: Kprobe smoke test: %d out of " | 382 | pr_err("BUG: %d out of %d tests failed\n", errors, num_tests); |
| 406 | "%d tests failed\n", errors, num_tests); | ||
| 407 | else if (handler_errors) | 383 | else if (handler_errors) |
| 408 | printk(KERN_ERR "BUG: Kprobe smoke test: %d error(s) " | 384 | pr_err("BUG: %d error(s) running handlers\n", handler_errors); |
| 409 | "running handlers\n", handler_errors); | ||
| 410 | else | 385 | else |
| 411 | printk(KERN_INFO "Kprobe smoke test passed successfully\n"); | 386 | pr_info("passed successfully\n"); |
| 412 | 387 | ||
| 413 | return 0; | 388 | return 0; |
| 414 | } | 389 | } |
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index fcc02560fd6b..aa312b0dc3ec 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c | |||
| @@ -526,21 +526,21 @@ static void m_stop(struct seq_file *seq, void *v) | |||
| 526 | return; | 526 | return; |
| 527 | } | 527 | } |
| 528 | 528 | ||
| 529 | struct seq_operations proc_uid_seq_operations = { | 529 | const struct seq_operations proc_uid_seq_operations = { |
| 530 | .start = uid_m_start, | 530 | .start = uid_m_start, |
| 531 | .stop = m_stop, | 531 | .stop = m_stop, |
| 532 | .next = m_next, | 532 | .next = m_next, |
| 533 | .show = uid_m_show, | 533 | .show = uid_m_show, |
| 534 | }; | 534 | }; |
| 535 | 535 | ||
| 536 | struct seq_operations proc_gid_seq_operations = { | 536 | const struct seq_operations proc_gid_seq_operations = { |
| 537 | .start = gid_m_start, | 537 | .start = gid_m_start, |
| 538 | .stop = m_stop, | 538 | .stop = m_stop, |
| 539 | .next = m_next, | 539 | .next = m_next, |
| 540 | .show = gid_m_show, | 540 | .show = gid_m_show, |
| 541 | }; | 541 | }; |
| 542 | 542 | ||
| 543 | struct seq_operations proc_projid_seq_operations = { | 543 | const struct seq_operations proc_projid_seq_operations = { |
| 544 | .start = projid_m_start, | 544 | .start = projid_m_start, |
| 545 | .stop = m_stop, | 545 | .stop = m_stop, |
| 546 | .next = m_next, | 546 | .next = m_next, |
diff --git a/kernel/watchdog.c b/kernel/watchdog.c index 51b29e9d2ba6..a8d6914030fe 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c | |||
| @@ -368,6 +368,7 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) | |||
| 368 | smp_mb__after_atomic(); | 368 | smp_mb__after_atomic(); |
| 369 | } | 369 | } |
| 370 | 370 | ||
| 371 | add_taint(TAINT_SOFTLOCKUP, LOCKDEP_STILL_OK); | ||
| 371 | if (softlockup_panic) | 372 | if (softlockup_panic) |
| 372 | panic("softlockup: hung tasks"); | 373 | panic("softlockup: hung tasks"); |
| 373 | __this_cpu_write(soft_watchdog_warn, true); | 374 | __this_cpu_write(soft_watchdog_warn, true); |
diff --git a/lib/Kconfig b/lib/Kconfig index df872659ddd3..a5ce0c7f6c30 100644 --- a/lib/Kconfig +++ b/lib/Kconfig | |||
| @@ -508,4 +508,11 @@ config UCS2_STRING | |||
| 508 | 508 | ||
| 509 | source "lib/fonts/Kconfig" | 509 | source "lib/fonts/Kconfig" |
| 510 | 510 | ||
| 511 | # | ||
| 512 | # sg chaining option | ||
| 513 | # | ||
| 514 | |||
| 515 | config ARCH_HAS_SG_CHAIN | ||
| 516 | def_bool n | ||
| 517 | |||
| 511 | endmenu | 518 | endmenu |
diff --git a/lib/decompress.c b/lib/decompress.c index 86069d74c062..37f3c786348f 100644 --- a/lib/decompress.c +++ b/lib/decompress.c | |||
| @@ -54,7 +54,7 @@ static const struct compress_format compressed_formats[] __initconst = { | |||
| 54 | { {0, 0}, NULL, NULL } | 54 | { {0, 0}, NULL, NULL } |
| 55 | }; | 55 | }; |
| 56 | 56 | ||
| 57 | decompress_fn __init decompress_method(const unsigned char *inbuf, int len, | 57 | decompress_fn __init decompress_method(const unsigned char *inbuf, long len, |
| 58 | const char **name) | 58 | const char **name) |
| 59 | { | 59 | { |
| 60 | const struct compress_format *cf; | 60 | const struct compress_format *cf; |
diff --git a/lib/decompress_bunzip2.c b/lib/decompress_bunzip2.c index 31c5f7675fbf..8290e0bef7ea 100644 --- a/lib/decompress_bunzip2.c +++ b/lib/decompress_bunzip2.c | |||
| @@ -92,8 +92,8 @@ struct bunzip_data { | |||
| 92 | /* State for interrupting output loop */ | 92 | /* State for interrupting output loop */ |
| 93 | int writeCopies, writePos, writeRunCountdown, writeCount, writeCurrent; | 93 | int writeCopies, writePos, writeRunCountdown, writeCount, writeCurrent; |
| 94 | /* I/O tracking data (file handles, buffers, positions, etc.) */ | 94 | /* I/O tracking data (file handles, buffers, positions, etc.) */ |
| 95 | int (*fill)(void*, unsigned int); | 95 | long (*fill)(void*, unsigned long); |
| 96 | int inbufCount, inbufPos /*, outbufPos*/; | 96 | long inbufCount, inbufPos /*, outbufPos*/; |
| 97 | unsigned char *inbuf /*,*outbuf*/; | 97 | unsigned char *inbuf /*,*outbuf*/; |
| 98 | unsigned int inbufBitCount, inbufBits; | 98 | unsigned int inbufBitCount, inbufBits; |
| 99 | /* The CRC values stored in the block header and calculated from the | 99 | /* The CRC values stored in the block header and calculated from the |
| @@ -617,7 +617,7 @@ decode_next_byte: | |||
| 617 | goto decode_next_byte; | 617 | goto decode_next_byte; |
| 618 | } | 618 | } |
| 619 | 619 | ||
| 620 | static int INIT nofill(void *buf, unsigned int len) | 620 | static long INIT nofill(void *buf, unsigned long len) |
| 621 | { | 621 | { |
| 622 | return -1; | 622 | return -1; |
| 623 | } | 623 | } |
| @@ -625,8 +625,8 @@ static int INIT nofill(void *buf, unsigned int len) | |||
| 625 | /* Allocate the structure, read file header. If in_fd ==-1, inbuf must contain | 625 | /* Allocate the structure, read file header. If in_fd ==-1, inbuf must contain |
| 626 | a complete bunzip file (len bytes long). If in_fd!=-1, inbuf and len are | 626 | a complete bunzip file (len bytes long). If in_fd!=-1, inbuf and len are |
| 627 | ignored, and data is read from file handle into temporary buffer. */ | 627 | ignored, and data is read from file handle into temporary buffer. */ |
| 628 | static int INIT start_bunzip(struct bunzip_data **bdp, void *inbuf, int len, | 628 | static int INIT start_bunzip(struct bunzip_data **bdp, void *inbuf, long len, |
| 629 | int (*fill)(void*, unsigned int)) | 629 | long (*fill)(void*, unsigned long)) |
| 630 | { | 630 | { |
| 631 | struct bunzip_data *bd; | 631 | struct bunzip_data *bd; |
| 632 | unsigned int i, j, c; | 632 | unsigned int i, j, c; |
| @@ -675,11 +675,11 @@ static int INIT start_bunzip(struct bunzip_data **bdp, void *inbuf, int len, | |||
| 675 | 675 | ||
| 676 | /* Example usage: decompress src_fd to dst_fd. (Stops at end of bzip2 data, | 676 | /* Example usage: decompress src_fd to dst_fd. (Stops at end of bzip2 data, |
| 677 | not end of file.) */ | 677 | not end of file.) */ |
| 678 | STATIC int INIT bunzip2(unsigned char *buf, int len, | 678 | STATIC int INIT bunzip2(unsigned char *buf, long len, |
| 679 | int(*fill)(void*, unsigned int), | 679 | long (*fill)(void*, unsigned long), |
| 680 | int(*flush)(void*, unsigned int), | 680 | long (*flush)(void*, unsigned long), |
| 681 | unsigned char *outbuf, | 681 | unsigned char *outbuf, |
| 682 | int *pos, | 682 | long *pos, |
| 683 | void(*error)(char *x)) | 683 | void(*error)(char *x)) |
| 684 | { | 684 | { |
| 685 | struct bunzip_data *bd; | 685 | struct bunzip_data *bd; |
| @@ -743,11 +743,11 @@ exit_0: | |||
| 743 | } | 743 | } |
| 744 | 744 | ||
| 745 | #ifdef PREBOOT | 745 | #ifdef PREBOOT |
| 746 | STATIC int INIT decompress(unsigned char *buf, int len, | 746 | STATIC int INIT decompress(unsigned char *buf, long len, |
| 747 | int(*fill)(void*, unsigned int), | 747 | long (*fill)(void*, unsigned long), |
| 748 | int(*flush)(void*, unsigned int), | 748 | long (*flush)(void*, unsigned long), |
| 749 | unsigned char *outbuf, | 749 | unsigned char *outbuf, |
| 750 | int *pos, | 750 | long *pos, |
| 751 | void(*error)(char *x)) | 751 | void(*error)(char *x)) |
| 752 | { | 752 | { |
| 753 | return bunzip2(buf, len - 4, fill, flush, outbuf, pos, error); | 753 | return bunzip2(buf, len - 4, fill, flush, outbuf, pos, error); |
diff --git a/lib/decompress_inflate.c b/lib/decompress_inflate.c index 0edfd742a154..d4c7891635ec 100644 --- a/lib/decompress_inflate.c +++ b/lib/decompress_inflate.c | |||
| @@ -27,17 +27,17 @@ | |||
| 27 | 27 | ||
| 28 | #define GZIP_IOBUF_SIZE (16*1024) | 28 | #define GZIP_IOBUF_SIZE (16*1024) |
| 29 | 29 | ||
| 30 | static int INIT nofill(void *buffer, unsigned int len) | 30 | static long INIT nofill(void *buffer, unsigned long len) |
| 31 | { | 31 | { |
| 32 | return -1; | 32 | return -1; |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | /* Included from initramfs et al code */ | 35 | /* Included from initramfs et al code */ |
| 36 | STATIC int INIT gunzip(unsigned char *buf, int len, | 36 | STATIC int INIT gunzip(unsigned char *buf, long len, |
| 37 | int(*fill)(void*, unsigned int), | 37 | long (*fill)(void*, unsigned long), |
| 38 | int(*flush)(void*, unsigned int), | 38 | long (*flush)(void*, unsigned long), |
| 39 | unsigned char *out_buf, | 39 | unsigned char *out_buf, |
| 40 | int *pos, | 40 | long *pos, |
| 41 | void(*error)(char *x)) { | 41 | void(*error)(char *x)) { |
| 42 | u8 *zbuf; | 42 | u8 *zbuf; |
| 43 | struct z_stream_s *strm; | 43 | struct z_stream_s *strm; |
| @@ -142,7 +142,7 @@ STATIC int INIT gunzip(unsigned char *buf, int len, | |||
| 142 | 142 | ||
| 143 | /* Write any data generated */ | 143 | /* Write any data generated */ |
| 144 | if (flush && strm->next_out > out_buf) { | 144 | if (flush && strm->next_out > out_buf) { |
| 145 | int l = strm->next_out - out_buf; | 145 | long l = strm->next_out - out_buf; |
| 146 | if (l != flush(out_buf, l)) { | 146 | if (l != flush(out_buf, l)) { |
| 147 | rc = -1; | 147 | rc = -1; |
| 148 | error("write error"); | 148 | error("write error"); |
diff --git a/lib/decompress_unlz4.c b/lib/decompress_unlz4.c index 7d1e83caf8ad..40f66ebe57b7 100644 --- a/lib/decompress_unlz4.c +++ b/lib/decompress_unlz4.c | |||
| @@ -31,10 +31,10 @@ | |||
| 31 | #define LZ4_DEFAULT_UNCOMPRESSED_CHUNK_SIZE (8 << 20) | 31 | #define LZ4_DEFAULT_UNCOMPRESSED_CHUNK_SIZE (8 << 20) |
| 32 | #define ARCHIVE_MAGICNUMBER 0x184C2102 | 32 | #define ARCHIVE_MAGICNUMBER 0x184C2102 |
| 33 | 33 | ||
| 34 | STATIC inline int INIT unlz4(u8 *input, int in_len, | 34 | STATIC inline int INIT unlz4(u8 *input, long in_len, |
| 35 | int (*fill) (void *, unsigned int), | 35 | long (*fill)(void *, unsigned long), |
| 36 | int (*flush) (void *, unsigned int), | 36 | long (*flush)(void *, unsigned long), |
| 37 | u8 *output, int *posp, | 37 | u8 *output, long *posp, |
| 38 | void (*error) (char *x)) | 38 | void (*error) (char *x)) |
| 39 | { | 39 | { |
| 40 | int ret = -1; | 40 | int ret = -1; |
| @@ -43,7 +43,7 @@ STATIC inline int INIT unlz4(u8 *input, int in_len, | |||
| 43 | u8 *inp; | 43 | u8 *inp; |
| 44 | u8 *inp_start; | 44 | u8 *inp_start; |
| 45 | u8 *outp; | 45 | u8 *outp; |
| 46 | int size = in_len; | 46 | long size = in_len; |
| 47 | #ifdef PREBOOT | 47 | #ifdef PREBOOT |
| 48 | size_t out_len = get_unaligned_le32(input + in_len); | 48 | size_t out_len = get_unaligned_le32(input + in_len); |
| 49 | #endif | 49 | #endif |
| @@ -83,13 +83,20 @@ STATIC inline int INIT unlz4(u8 *input, int in_len, | |||
| 83 | if (posp) | 83 | if (posp) |
| 84 | *posp = 0; | 84 | *posp = 0; |
| 85 | 85 | ||
| 86 | if (fill) | 86 | if (fill) { |
| 87 | fill(inp, 4); | 87 | size = fill(inp, 4); |
| 88 | if (size < 4) { | ||
| 89 | error("data corrupted"); | ||
| 90 | goto exit_2; | ||
| 91 | } | ||
| 92 | } | ||
| 88 | 93 | ||
| 89 | chunksize = get_unaligned_le32(inp); | 94 | chunksize = get_unaligned_le32(inp); |
| 90 | if (chunksize == ARCHIVE_MAGICNUMBER) { | 95 | if (chunksize == ARCHIVE_MAGICNUMBER) { |
| 91 | inp += 4; | 96 | if (!fill) { |
| 92 | size -= 4; | 97 | inp += 4; |
| 98 | size -= 4; | ||
| 99 | } | ||
| 93 | } else { | 100 | } else { |
| 94 | error("invalid header"); | 101 | error("invalid header"); |
| 95 | goto exit_2; | 102 | goto exit_2; |
| @@ -100,29 +107,44 @@ STATIC inline int INIT unlz4(u8 *input, int in_len, | |||
| 100 | 107 | ||
| 101 | for (;;) { | 108 | for (;;) { |
| 102 | 109 | ||
| 103 | if (fill) | 110 | if (fill) { |
| 104 | fill(inp, 4); | 111 | size = fill(inp, 4); |
| 112 | if (size == 0) | ||
| 113 | break; | ||
| 114 | if (size < 4) { | ||
| 115 | error("data corrupted"); | ||
| 116 | goto exit_2; | ||
| 117 | } | ||
| 118 | } | ||
| 105 | 119 | ||
| 106 | chunksize = get_unaligned_le32(inp); | 120 | chunksize = get_unaligned_le32(inp); |
| 107 | if (chunksize == ARCHIVE_MAGICNUMBER) { | 121 | if (chunksize == ARCHIVE_MAGICNUMBER) { |
| 108 | inp += 4; | 122 | if (!fill) { |
| 109 | size -= 4; | 123 | inp += 4; |
| 124 | size -= 4; | ||
| 125 | } | ||
| 110 | if (posp) | 126 | if (posp) |
| 111 | *posp += 4; | 127 | *posp += 4; |
| 112 | continue; | 128 | continue; |
| 113 | } | 129 | } |
| 114 | inp += 4; | 130 | |
| 115 | size -= 4; | ||
| 116 | 131 | ||
| 117 | if (posp) | 132 | if (posp) |
| 118 | *posp += 4; | 133 | *posp += 4; |
| 119 | 134 | ||
| 120 | if (fill) { | 135 | if (!fill) { |
| 136 | inp += 4; | ||
| 137 | size -= 4; | ||
| 138 | } else { | ||
| 121 | if (chunksize > lz4_compressbound(uncomp_chunksize)) { | 139 | if (chunksize > lz4_compressbound(uncomp_chunksize)) { |
| 122 | error("chunk length is longer than allocated"); | 140 | error("chunk length is longer than allocated"); |
| 123 | goto exit_2; | 141 | goto exit_2; |
| 124 | } | 142 | } |
| 125 | fill(inp, chunksize); | 143 | size = fill(inp, chunksize); |
| 144 | if (size < chunksize) { | ||
| 145 | error("data corrupted"); | ||
| 146 | goto exit_2; | ||
| 147 | } | ||
| 126 | } | 148 | } |
| 127 | #ifdef PREBOOT | 149 | #ifdef PREBOOT |
| 128 | if (out_len >= uncomp_chunksize) { | 150 | if (out_len >= uncomp_chunksize) { |
| @@ -149,18 +171,17 @@ STATIC inline int INIT unlz4(u8 *input, int in_len, | |||
| 149 | if (posp) | 171 | if (posp) |
| 150 | *posp += chunksize; | 172 | *posp += chunksize; |
| 151 | 173 | ||
| 152 | size -= chunksize; | 174 | if (!fill) { |
| 175 | size -= chunksize; | ||
| 153 | 176 | ||
| 154 | if (size == 0) | 177 | if (size == 0) |
| 155 | break; | 178 | break; |
| 156 | else if (size < 0) { | 179 | else if (size < 0) { |
| 157 | error("data corrupted"); | 180 | error("data corrupted"); |
| 158 | goto exit_2; | 181 | goto exit_2; |
| 182 | } | ||
| 183 | inp += chunksize; | ||
| 159 | } | 184 | } |
| 160 | |||
| 161 | inp += chunksize; | ||
| 162 | if (fill) | ||
| 163 | inp = inp_start; | ||
| 164 | } | 185 | } |
| 165 | 186 | ||
| 166 | ret = 0; | 187 | ret = 0; |
| @@ -175,11 +196,11 @@ exit_0: | |||
| 175 | } | 196 | } |
| 176 | 197 | ||
| 177 | #ifdef PREBOOT | 198 | #ifdef PREBOOT |
| 178 | STATIC int INIT decompress(unsigned char *buf, int in_len, | 199 | STATIC int INIT decompress(unsigned char *buf, long in_len, |
| 179 | int(*fill)(void*, unsigned int), | 200 | long (*fill)(void*, unsigned long), |
| 180 | int(*flush)(void*, unsigned int), | 201 | long (*flush)(void*, unsigned long), |
| 181 | unsigned char *output, | 202 | unsigned char *output, |
| 182 | int *posp, | 203 | long *posp, |
| 183 | void(*error)(char *x) | 204 | void(*error)(char *x) |
| 184 | ) | 205 | ) |
| 185 | { | 206 | { |
diff --git a/lib/decompress_unlzma.c b/lib/decompress_unlzma.c index 32adb73a9038..0be83af62b88 100644 --- a/lib/decompress_unlzma.c +++ b/lib/decompress_unlzma.c | |||
| @@ -65,11 +65,11 @@ static long long INIT read_int(unsigned char *ptr, int size) | |||
| 65 | #define LZMA_IOBUF_SIZE 0x10000 | 65 | #define LZMA_IOBUF_SIZE 0x10000 |
| 66 | 66 | ||
| 67 | struct rc { | 67 | struct rc { |
| 68 | int (*fill)(void*, unsigned int); | 68 | long (*fill)(void*, unsigned long); |
| 69 | uint8_t *ptr; | 69 | uint8_t *ptr; |
| 70 | uint8_t *buffer; | 70 | uint8_t *buffer; |
| 71 | uint8_t *buffer_end; | 71 | uint8_t *buffer_end; |
| 72 | int buffer_size; | 72 | long buffer_size; |
| 73 | uint32_t code; | 73 | uint32_t code; |
| 74 | uint32_t range; | 74 | uint32_t range; |
| 75 | uint32_t bound; | 75 | uint32_t bound; |
| @@ -82,7 +82,7 @@ struct rc { | |||
| 82 | #define RC_MODEL_TOTAL_BITS 11 | 82 | #define RC_MODEL_TOTAL_BITS 11 |
| 83 | 83 | ||
| 84 | 84 | ||
| 85 | static int INIT nofill(void *buffer, unsigned int len) | 85 | static long INIT nofill(void *buffer, unsigned long len) |
| 86 | { | 86 | { |
| 87 | return -1; | 87 | return -1; |
| 88 | } | 88 | } |
| @@ -99,8 +99,8 @@ static void INIT rc_read(struct rc *rc) | |||
| 99 | 99 | ||
| 100 | /* Called once */ | 100 | /* Called once */ |
| 101 | static inline void INIT rc_init(struct rc *rc, | 101 | static inline void INIT rc_init(struct rc *rc, |
| 102 | int (*fill)(void*, unsigned int), | 102 | long (*fill)(void*, unsigned long), |
| 103 | char *buffer, int buffer_size) | 103 | char *buffer, long buffer_size) |
| 104 | { | 104 | { |
| 105 | if (fill) | 105 | if (fill) |
| 106 | rc->fill = fill; | 106 | rc->fill = fill; |
| @@ -280,7 +280,7 @@ struct writer { | |||
| 280 | size_t buffer_pos; | 280 | size_t buffer_pos; |
| 281 | int bufsize; | 281 | int bufsize; |
| 282 | size_t global_pos; | 282 | size_t global_pos; |
| 283 | int(*flush)(void*, unsigned int); | 283 | long (*flush)(void*, unsigned long); |
| 284 | struct lzma_header *header; | 284 | struct lzma_header *header; |
| 285 | }; | 285 | }; |
| 286 | 286 | ||
| @@ -534,11 +534,11 @@ static inline int INIT process_bit1(struct writer *wr, struct rc *rc, | |||
| 534 | 534 | ||
| 535 | 535 | ||
| 536 | 536 | ||
| 537 | STATIC inline int INIT unlzma(unsigned char *buf, int in_len, | 537 | STATIC inline int INIT unlzma(unsigned char *buf, long in_len, |
| 538 | int(*fill)(void*, unsigned int), | 538 | long (*fill)(void*, unsigned long), |
| 539 | int(*flush)(void*, unsigned int), | 539 | long (*flush)(void*, unsigned long), |
| 540 | unsigned char *output, | 540 | unsigned char *output, |
| 541 | int *posp, | 541 | long *posp, |
| 542 | void(*error)(char *x) | 542 | void(*error)(char *x) |
| 543 | ) | 543 | ) |
| 544 | { | 544 | { |
| @@ -667,11 +667,11 @@ exit_0: | |||
| 667 | } | 667 | } |
| 668 | 668 | ||
| 669 | #ifdef PREBOOT | 669 | #ifdef PREBOOT |
| 670 | STATIC int INIT decompress(unsigned char *buf, int in_len, | 670 | STATIC int INIT decompress(unsigned char *buf, long in_len, |
| 671 | int(*fill)(void*, unsigned int), | 671 | long (*fill)(void*, unsigned long), |
| 672 | int(*flush)(void*, unsigned int), | 672 | long (*flush)(void*, unsigned long), |
| 673 | unsigned char *output, | 673 | unsigned char *output, |
| 674 | int *posp, | 674 | long *posp, |
| 675 | void(*error)(char *x) | 675 | void(*error)(char *x) |
| 676 | ) | 676 | ) |
| 677 | { | 677 | { |
diff --git a/lib/decompress_unlzo.c b/lib/decompress_unlzo.c index 960183d4258f..b94a31bdd87d 100644 --- a/lib/decompress_unlzo.c +++ b/lib/decompress_unlzo.c | |||
| @@ -51,7 +51,7 @@ static const unsigned char lzop_magic[] = { | |||
| 51 | #define HEADER_SIZE_MIN (9 + 7 + 4 + 8 + 1 + 4) | 51 | #define HEADER_SIZE_MIN (9 + 7 + 4 + 8 + 1 + 4) |
| 52 | #define HEADER_SIZE_MAX (9 + 7 + 1 + 8 + 8 + 4 + 1 + 255 + 4) | 52 | #define HEADER_SIZE_MAX (9 + 7 + 1 + 8 + 8 + 4 + 1 + 255 + 4) |
| 53 | 53 | ||
| 54 | STATIC inline int INIT parse_header(u8 *input, int *skip, int in_len) | 54 | STATIC inline long INIT parse_header(u8 *input, long *skip, long in_len) |
| 55 | { | 55 | { |
| 56 | int l; | 56 | int l; |
| 57 | u8 *parse = input; | 57 | u8 *parse = input; |
| @@ -108,14 +108,14 @@ STATIC inline int INIT parse_header(u8 *input, int *skip, int in_len) | |||
| 108 | return 1; | 108 | return 1; |
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | STATIC inline int INIT unlzo(u8 *input, int in_len, | 111 | STATIC int INIT unlzo(u8 *input, long in_len, |
| 112 | int (*fill) (void *, unsigned int), | 112 | long (*fill)(void *, unsigned long), |
| 113 | int (*flush) (void *, unsigned int), | 113 | long (*flush)(void *, unsigned long), |
| 114 | u8 *output, int *posp, | 114 | u8 *output, long *posp, |
| 115 | void (*error) (char *x)) | 115 | void (*error) (char *x)) |
| 116 | { | 116 | { |
| 117 | u8 r = 0; | 117 | u8 r = 0; |
| 118 | int skip = 0; | 118 | long skip = 0; |
| 119 | u32 src_len, dst_len; | 119 | u32 src_len, dst_len; |
| 120 | size_t tmp; | 120 | size_t tmp; |
| 121 | u8 *in_buf, *in_buf_save, *out_buf; | 121 | u8 *in_buf, *in_buf_save, *out_buf; |
diff --git a/lib/decompress_unxz.c b/lib/decompress_unxz.c index 9f34eb56854d..b07a78340e9d 100644 --- a/lib/decompress_unxz.c +++ b/lib/decompress_unxz.c | |||
| @@ -248,10 +248,10 @@ void *memmove(void *dest, const void *src, size_t size) | |||
| 248 | * both input and output buffers are available as a single chunk, i.e. when | 248 | * both input and output buffers are available as a single chunk, i.e. when |
| 249 | * fill() and flush() won't be used. | 249 | * fill() and flush() won't be used. |
| 250 | */ | 250 | */ |
| 251 | STATIC int INIT unxz(unsigned char *in, int in_size, | 251 | STATIC int INIT unxz(unsigned char *in, long in_size, |
| 252 | int (*fill)(void *dest, unsigned int size), | 252 | long (*fill)(void *dest, unsigned long size), |
| 253 | int (*flush)(void *src, unsigned int size), | 253 | long (*flush)(void *src, unsigned long size), |
| 254 | unsigned char *out, int *in_used, | 254 | unsigned char *out, long *in_used, |
| 255 | void (*error)(char *x)) | 255 | void (*error)(char *x)) |
| 256 | { | 256 | { |
| 257 | struct xz_buf b; | 257 | struct xz_buf b; |
| @@ -329,7 +329,7 @@ STATIC int INIT unxz(unsigned char *in, int in_size, | |||
| 329 | * returned by xz_dec_run(), but probably | 329 | * returned by xz_dec_run(), but probably |
| 330 | * it's not too bad. | 330 | * it's not too bad. |
| 331 | */ | 331 | */ |
| 332 | if (flush(b.out, b.out_pos) != (int)b.out_pos) | 332 | if (flush(b.out, b.out_pos) != (long)b.out_pos) |
| 333 | ret = XZ_BUF_ERROR; | 333 | ret = XZ_BUF_ERROR; |
| 334 | 334 | ||
| 335 | b.out_pos = 0; | 335 | b.out_pos = 0; |
| @@ -590,26 +590,27 @@ static void __idr_remove_all(struct idr *idp) | |||
| 590 | struct idr_layer **paa = &pa[0]; | 590 | struct idr_layer **paa = &pa[0]; |
| 591 | 591 | ||
| 592 | n = idp->layers * IDR_BITS; | 592 | n = idp->layers * IDR_BITS; |
| 593 | p = idp->top; | 593 | *paa = idp->top; |
| 594 | RCU_INIT_POINTER(idp->top, NULL); | 594 | RCU_INIT_POINTER(idp->top, NULL); |
| 595 | max = idr_max(idp->layers); | 595 | max = idr_max(idp->layers); |
| 596 | 596 | ||
| 597 | id = 0; | 597 | id = 0; |
| 598 | while (id >= 0 && id <= max) { | 598 | while (id >= 0 && id <= max) { |
| 599 | p = *paa; | ||
| 599 | while (n > IDR_BITS && p) { | 600 | while (n > IDR_BITS && p) { |
| 600 | n -= IDR_BITS; | 601 | n -= IDR_BITS; |
| 601 | *paa++ = p; | ||
| 602 | p = p->ary[(id >> n) & IDR_MASK]; | 602 | p = p->ary[(id >> n) & IDR_MASK]; |
| 603 | *++paa = p; | ||
| 603 | } | 604 | } |
| 604 | 605 | ||
| 605 | bt_mask = id; | 606 | bt_mask = id; |
| 606 | id += 1 << n; | 607 | id += 1 << n; |
| 607 | /* Get the highest bit that the above add changed from 0->1. */ | 608 | /* Get the highest bit that the above add changed from 0->1. */ |
| 608 | while (n < fls(id ^ bt_mask)) { | 609 | while (n < fls(id ^ bt_mask)) { |
| 609 | if (p) | 610 | if (*paa) |
| 610 | free_layer(idp, p); | 611 | free_layer(idp, *paa); |
| 611 | n += IDR_BITS; | 612 | n += IDR_BITS; |
| 612 | p = *--paa; | 613 | --paa; |
| 613 | } | 614 | } |
| 614 | } | 615 | } |
| 615 | idp->layers = 0; | 616 | idp->layers = 0; |
| @@ -692,15 +693,16 @@ int idr_for_each(struct idr *idp, | |||
| 692 | struct idr_layer **paa = &pa[0]; | 693 | struct idr_layer **paa = &pa[0]; |
| 693 | 694 | ||
| 694 | n = idp->layers * IDR_BITS; | 695 | n = idp->layers * IDR_BITS; |
| 695 | p = rcu_dereference_raw(idp->top); | 696 | *paa = rcu_dereference_raw(idp->top); |
| 696 | max = idr_max(idp->layers); | 697 | max = idr_max(idp->layers); |
| 697 | 698 | ||
| 698 | id = 0; | 699 | id = 0; |
| 699 | while (id >= 0 && id <= max) { | 700 | while (id >= 0 && id <= max) { |
| 701 | p = *paa; | ||
| 700 | while (n > 0 && p) { | 702 | while (n > 0 && p) { |
| 701 | n -= IDR_BITS; | 703 | n -= IDR_BITS; |
| 702 | *paa++ = p; | ||
| 703 | p = rcu_dereference_raw(p->ary[(id >> n) & IDR_MASK]); | 704 | p = rcu_dereference_raw(p->ary[(id >> n) & IDR_MASK]); |
| 705 | *++paa = p; | ||
| 704 | } | 706 | } |
| 705 | 707 | ||
| 706 | if (p) { | 708 | if (p) { |
| @@ -712,7 +714,7 @@ int idr_for_each(struct idr *idp, | |||
| 712 | id += 1 << n; | 714 | id += 1 << n; |
| 713 | while (n < fls(id)) { | 715 | while (n < fls(id)) { |
| 714 | n += IDR_BITS; | 716 | n += IDR_BITS; |
| 715 | p = *--paa; | 717 | --paa; |
| 716 | } | 718 | } |
| 717 | } | 719 | } |
| 718 | 720 | ||
| @@ -740,17 +742,18 @@ void *idr_get_next(struct idr *idp, int *nextidp) | |||
| 740 | int n, max; | 742 | int n, max; |
| 741 | 743 | ||
| 742 | /* find first ent */ | 744 | /* find first ent */ |
| 743 | p = rcu_dereference_raw(idp->top); | 745 | p = *paa = rcu_dereference_raw(idp->top); |
| 744 | if (!p) | 746 | if (!p) |
| 745 | return NULL; | 747 | return NULL; |
| 746 | n = (p->layer + 1) * IDR_BITS; | 748 | n = (p->layer + 1) * IDR_BITS; |
| 747 | max = idr_max(p->layer + 1); | 749 | max = idr_max(p->layer + 1); |
| 748 | 750 | ||
| 749 | while (id >= 0 && id <= max) { | 751 | while (id >= 0 && id <= max) { |
| 752 | p = *paa; | ||
| 750 | while (n > 0 && p) { | 753 | while (n > 0 && p) { |
| 751 | n -= IDR_BITS; | 754 | n -= IDR_BITS; |
| 752 | *paa++ = p; | ||
| 753 | p = rcu_dereference_raw(p->ary[(id >> n) & IDR_MASK]); | 755 | p = rcu_dereference_raw(p->ary[(id >> n) & IDR_MASK]); |
| 756 | *++paa = p; | ||
| 754 | } | 757 | } |
| 755 | 758 | ||
| 756 | if (p) { | 759 | if (p) { |
| @@ -768,7 +771,7 @@ void *idr_get_next(struct idr *idp, int *nextidp) | |||
| 768 | id = round_up(id + 1, 1 << n); | 771 | id = round_up(id + 1, 1 << n); |
| 769 | while (n < fls(id)) { | 772 | while (n < fls(id)) { |
| 770 | n += IDR_BITS; | 773 | n += IDR_BITS; |
| 771 | p = *--paa; | 774 | --paa; |
| 772 | } | 775 | } |
| 773 | } | 776 | } |
| 774 | return NULL; | 777 | return NULL; |
diff --git a/lib/kfifo.c b/lib/kfifo.c index d79b9d222065..90ba1eb1df06 100644 --- a/lib/kfifo.c +++ b/lib/kfifo.c | |||
| @@ -561,8 +561,7 @@ EXPORT_SYMBOL(__kfifo_to_user_r); | |||
| 561 | unsigned int __kfifo_dma_in_prepare_r(struct __kfifo *fifo, | 561 | unsigned int __kfifo_dma_in_prepare_r(struct __kfifo *fifo, |
| 562 | struct scatterlist *sgl, int nents, unsigned int len, size_t recsize) | 562 | struct scatterlist *sgl, int nents, unsigned int len, size_t recsize) |
| 563 | { | 563 | { |
| 564 | if (!nents) | 564 | BUG_ON(!nents); |
| 565 | BUG(); | ||
| 566 | 565 | ||
| 567 | len = __kfifo_max_r(len, recsize); | 566 | len = __kfifo_max_r(len, recsize); |
| 568 | 567 | ||
| @@ -585,8 +584,7 @@ EXPORT_SYMBOL(__kfifo_dma_in_finish_r); | |||
| 585 | unsigned int __kfifo_dma_out_prepare_r(struct __kfifo *fifo, | 584 | unsigned int __kfifo_dma_out_prepare_r(struct __kfifo *fifo, |
| 586 | struct scatterlist *sgl, int nents, unsigned int len, size_t recsize) | 585 | struct scatterlist *sgl, int nents, unsigned int len, size_t recsize) |
| 587 | { | 586 | { |
| 588 | if (!nents) | 587 | BUG_ON(!nents); |
| 589 | BUG(); | ||
| 590 | 588 | ||
| 591 | len = __kfifo_max_r(len, recsize); | 589 | len = __kfifo_max_r(len, recsize); |
| 592 | 590 | ||
diff --git a/lib/rbtree.c b/lib/rbtree.c index 65f4effd117f..c16c81a3d430 100644 --- a/lib/rbtree.c +++ b/lib/rbtree.c | |||
| @@ -101,7 +101,7 @@ __rb_insert(struct rb_node *node, struct rb_root *root, | |||
| 101 | * / \ / \ | 101 | * / \ / \ |
| 102 | * p u --> P U | 102 | * p u --> P U |
| 103 | * / / | 103 | * / / |
| 104 | * n N | 104 | * n n |
| 105 | * | 105 | * |
| 106 | * However, since g's parent might be red, and | 106 | * However, since g's parent might be red, and |
| 107 | * 4) does not allow this, we need to recurse | 107 | * 4) does not allow this, we need to recurse |
diff --git a/lib/scatterlist.c b/lib/scatterlist.c index b4415fceb7e7..9cdf62f8accd 100644 --- a/lib/scatterlist.c +++ b/lib/scatterlist.c | |||
| @@ -73,7 +73,7 @@ EXPORT_SYMBOL(sg_nents); | |||
| 73 | **/ | 73 | **/ |
| 74 | struct scatterlist *sg_last(struct scatterlist *sgl, unsigned int nents) | 74 | struct scatterlist *sg_last(struct scatterlist *sgl, unsigned int nents) |
| 75 | { | 75 | { |
| 76 | #ifndef ARCH_HAS_SG_CHAIN | 76 | #ifndef CONFIG_ARCH_HAS_SG_CHAIN |
| 77 | struct scatterlist *ret = &sgl[nents - 1]; | 77 | struct scatterlist *ret = &sgl[nents - 1]; |
| 78 | #else | 78 | #else |
| 79 | struct scatterlist *sg, *ret = NULL; | 79 | struct scatterlist *sg, *ret = NULL; |
| @@ -255,7 +255,7 @@ int __sg_alloc_table(struct sg_table *table, unsigned int nents, | |||
| 255 | 255 | ||
| 256 | if (nents == 0) | 256 | if (nents == 0) |
| 257 | return -EINVAL; | 257 | return -EINVAL; |
| 258 | #ifndef ARCH_HAS_SG_CHAIN | 258 | #ifndef CONFIG_ARCH_HAS_SG_CHAIN |
| 259 | if (WARN_ON_ONCE(nents > max_ents)) | 259 | if (WARN_ON_ONCE(nents > max_ents)) |
| 260 | return -EINVAL; | 260 | return -EINVAL; |
| 261 | #endif | 261 | #endif |
diff --git a/mm/filemap.c b/mm/filemap.c index af19a6b079f5..f501b56ec2c6 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include <linux/security.h> | 31 | #include <linux/security.h> |
| 32 | #include <linux/cpuset.h> | 32 | #include <linux/cpuset.h> |
| 33 | #include <linux/hardirq.h> /* for BUG_ON(!in_atomic()) only */ | 33 | #include <linux/hardirq.h> /* for BUG_ON(!in_atomic()) only */ |
| 34 | #include <linux/hugetlb.h> | ||
| 34 | #include <linux/memcontrol.h> | 35 | #include <linux/memcontrol.h> |
| 35 | #include <linux/cleancache.h> | 36 | #include <linux/cleancache.h> |
| 36 | #include <linux/rmap.h> | 37 | #include <linux/rmap.h> |
| @@ -233,7 +234,6 @@ void delete_from_page_cache(struct page *page) | |||
| 233 | spin_lock_irq(&mapping->tree_lock); | 234 | spin_lock_irq(&mapping->tree_lock); |
| 234 | __delete_from_page_cache(page, NULL); | 235 | __delete_from_page_cache(page, NULL); |
| 235 | spin_unlock_irq(&mapping->tree_lock); | 236 | spin_unlock_irq(&mapping->tree_lock); |
| 236 | mem_cgroup_uncharge_cache_page(page); | ||
| 237 | 237 | ||
| 238 | if (freepage) | 238 | if (freepage) |
| 239 | freepage(page); | 239 | freepage(page); |
| @@ -489,8 +489,7 @@ int replace_page_cache_page(struct page *old, struct page *new, gfp_t gfp_mask) | |||
| 489 | if (PageSwapBacked(new)) | 489 | if (PageSwapBacked(new)) |
| 490 | __inc_zone_page_state(new, NR_SHMEM); | 490 | __inc_zone_page_state(new, NR_SHMEM); |
| 491 | spin_unlock_irq(&mapping->tree_lock); | 491 | spin_unlock_irq(&mapping->tree_lock); |
| 492 | /* mem_cgroup codes must not be called under tree_lock */ | 492 | mem_cgroup_migrate(old, new, true); |
| 493 | mem_cgroup_replace_page_cache(old, new); | ||
| 494 | radix_tree_preload_end(); | 493 | radix_tree_preload_end(); |
| 495 | if (freepage) | 494 | if (freepage) |
| 496 | freepage(old); | 495 | freepage(old); |
| @@ -548,19 +547,24 @@ static int __add_to_page_cache_locked(struct page *page, | |||
| 548 | pgoff_t offset, gfp_t gfp_mask, | 547 | pgoff_t offset, gfp_t gfp_mask, |
| 549 | void **shadowp) | 548 | void **shadowp) |
| 550 | { | 549 | { |
| 550 | int huge = PageHuge(page); | ||
| 551 | struct mem_cgroup *memcg; | ||
| 551 | int error; | 552 | int error; |
| 552 | 553 | ||
| 553 | VM_BUG_ON_PAGE(!PageLocked(page), page); | 554 | VM_BUG_ON_PAGE(!PageLocked(page), page); |
| 554 | VM_BUG_ON_PAGE(PageSwapBacked(page), page); | 555 | VM_BUG_ON_PAGE(PageSwapBacked(page), page); |
| 555 | 556 | ||
| 556 | error = mem_cgroup_charge_file(page, current->mm, | 557 | if (!huge) { |
| 557 | gfp_mask & GFP_RECLAIM_MASK); | 558 | error = mem_cgroup_try_charge(page, current->mm, |
| 558 | if (error) | 559 | gfp_mask, &memcg); |
| 559 | return error; | 560 | if (error) |
| 561 | return error; | ||
| 562 | } | ||
| 560 | 563 | ||
| 561 | error = radix_tree_maybe_preload(gfp_mask & ~__GFP_HIGHMEM); | 564 | error = radix_tree_maybe_preload(gfp_mask & ~__GFP_HIGHMEM); |
| 562 | if (error) { | 565 | if (error) { |
| 563 | mem_cgroup_uncharge_cache_page(page); | 566 | if (!huge) |
| 567 | mem_cgroup_cancel_charge(page, memcg); | ||
| 564 | return error; | 568 | return error; |
| 565 | } | 569 | } |
| 566 | 570 | ||
| @@ -575,13 +579,16 @@ static int __add_to_page_cache_locked(struct page *page, | |||
| 575 | goto err_insert; | 579 | goto err_insert; |
| 576 | __inc_zone_page_state(page, NR_FILE_PAGES); | 580 | __inc_zone_page_state(page, NR_FILE_PAGES); |
| 577 | spin_unlock_irq(&mapping->tree_lock); | 581 | spin_unlock_irq(&mapping->tree_lock); |
| 582 | if (!huge) | ||
| 583 | mem_cgroup_commit_charge(page, memcg, false); | ||
| 578 | trace_mm_filemap_add_to_page_cache(page); | 584 | trace_mm_filemap_add_to_page_cache(page); |
| 579 | return 0; | 585 | return 0; |
| 580 | err_insert: | 586 | err_insert: |
| 581 | page->mapping = NULL; | 587 | page->mapping = NULL; |
| 582 | /* Leave page->index set: truncation relies upon it */ | 588 | /* Leave page->index set: truncation relies upon it */ |
| 583 | spin_unlock_irq(&mapping->tree_lock); | 589 | spin_unlock_irq(&mapping->tree_lock); |
| 584 | mem_cgroup_uncharge_cache_page(page); | 590 | if (!huge) |
| 591 | mem_cgroup_cancel_charge(page, memcg); | ||
| 585 | page_cache_release(page); | 592 | page_cache_release(page); |
| 586 | return error; | 593 | return error; |
| 587 | } | 594 | } |
diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 3630d577e987..d9a21d06b862 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c | |||
| @@ -715,13 +715,20 @@ static int __do_huge_pmd_anonymous_page(struct mm_struct *mm, | |||
| 715 | unsigned long haddr, pmd_t *pmd, | 715 | unsigned long haddr, pmd_t *pmd, |
| 716 | struct page *page) | 716 | struct page *page) |
| 717 | { | 717 | { |
| 718 | struct mem_cgroup *memcg; | ||
| 718 | pgtable_t pgtable; | 719 | pgtable_t pgtable; |
| 719 | spinlock_t *ptl; | 720 | spinlock_t *ptl; |
| 720 | 721 | ||
| 721 | VM_BUG_ON_PAGE(!PageCompound(page), page); | 722 | VM_BUG_ON_PAGE(!PageCompound(page), page); |
| 723 | |||
| 724 | if (mem_cgroup_try_charge(page, mm, GFP_TRANSHUGE, &memcg)) | ||
| 725 | return VM_FAULT_OOM; | ||
| 726 | |||
| 722 | pgtable = pte_alloc_one(mm, haddr); | 727 | pgtable = pte_alloc_one(mm, haddr); |
| 723 | if (unlikely(!pgtable)) | 728 | if (unlikely(!pgtable)) { |
| 729 | mem_cgroup_cancel_charge(page, memcg); | ||
| 724 | return VM_FAULT_OOM; | 730 | return VM_FAULT_OOM; |
| 731 | } | ||
| 725 | 732 | ||
| 726 | clear_huge_page(page, haddr, HPAGE_PMD_NR); | 733 | clear_huge_page(page, haddr, HPAGE_PMD_NR); |
| 727 | /* | 734 | /* |
| @@ -734,7 +741,7 @@ static int __do_huge_pmd_anonymous_page(struct mm_struct *mm, | |||
| 734 | ptl = pmd_lock(mm, pmd); | 741 | ptl = pmd_lock(mm, pmd); |
| 735 | if (unlikely(!pmd_none(*pmd))) { | 742 | if (unlikely(!pmd_none(*pmd))) { |
| 736 | spin_unlock(ptl); | 743 | spin_unlock(ptl); |
| 737 | mem_cgroup_uncharge_page(page); | 744 | mem_cgroup_cancel_charge(page, memcg); |
| 738 | put_page(page); | 745 | put_page(page); |
| 739 | pte_free(mm, pgtable); | 746 | pte_free(mm, pgtable); |
| 740 | } else { | 747 | } else { |
| @@ -742,6 +749,8 @@ static int __do_huge_pmd_anonymous_page(struct mm_struct *mm, | |||
| 742 | entry = mk_huge_pmd(page, vma->vm_page_prot); | 749 | entry = mk_huge_pmd(page, vma->vm_page_prot); |
| 743 | entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma); | 750 | entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma); |
| 744 | page_add_new_anon_rmap(page, vma, haddr); | 751 | page_add_new_anon_rmap(page, vma, haddr); |
| 752 | mem_cgroup_commit_charge(page, memcg, false); | ||
| 753 | lru_cache_add_active_or_unevictable(page, vma); | ||
| 745 | pgtable_trans_huge_deposit(mm, pmd, pgtable); | 754 | pgtable_trans_huge_deposit(mm, pmd, pgtable); |
| 746 | set_pmd_at(mm, haddr, pmd, entry); | 755 | set_pmd_at(mm, haddr, pmd, entry); |
| 747 | add_mm_counter(mm, MM_ANONPAGES, HPAGE_PMD_NR); | 756 | add_mm_counter(mm, MM_ANONPAGES, HPAGE_PMD_NR); |
| @@ -827,13 +836,7 @@ int do_huge_pmd_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 827 | count_vm_event(THP_FAULT_FALLBACK); | 836 | count_vm_event(THP_FAULT_FALLBACK); |
| 828 | return VM_FAULT_FALLBACK; | 837 | return VM_FAULT_FALLBACK; |
| 829 | } | 838 | } |
| 830 | if (unlikely(mem_cgroup_charge_anon(page, mm, GFP_TRANSHUGE))) { | ||
| 831 | put_page(page); | ||
| 832 | count_vm_event(THP_FAULT_FALLBACK); | ||
| 833 | return VM_FAULT_FALLBACK; | ||
| 834 | } | ||
| 835 | if (unlikely(__do_huge_pmd_anonymous_page(mm, vma, haddr, pmd, page))) { | 839 | if (unlikely(__do_huge_pmd_anonymous_page(mm, vma, haddr, pmd, page))) { |
| 836 | mem_cgroup_uncharge_page(page); | ||
| 837 | put_page(page); | 840 | put_page(page); |
| 838 | count_vm_event(THP_FAULT_FALLBACK); | 841 | count_vm_event(THP_FAULT_FALLBACK); |
| 839 | return VM_FAULT_FALLBACK; | 842 | return VM_FAULT_FALLBACK; |
| @@ -979,6 +982,7 @@ static int do_huge_pmd_wp_page_fallback(struct mm_struct *mm, | |||
| 979 | struct page *page, | 982 | struct page *page, |
| 980 | unsigned long haddr) | 983 | unsigned long haddr) |
| 981 | { | 984 | { |
| 985 | struct mem_cgroup *memcg; | ||
| 982 | spinlock_t *ptl; | 986 | spinlock_t *ptl; |
| 983 | pgtable_t pgtable; | 987 | pgtable_t pgtable; |
| 984 | pmd_t _pmd; | 988 | pmd_t _pmd; |
| @@ -999,20 +1003,21 @@ static int do_huge_pmd_wp_page_fallback(struct mm_struct *mm, | |||
| 999 | __GFP_OTHER_NODE, | 1003 | __GFP_OTHER_NODE, |
| 1000 | vma, address, page_to_nid(page)); | 1004 | vma, address, page_to_nid(page)); |
| 1001 | if (unlikely(!pages[i] || | 1005 | if (unlikely(!pages[i] || |
| 1002 | mem_cgroup_charge_anon(pages[i], mm, | 1006 | mem_cgroup_try_charge(pages[i], mm, GFP_KERNEL, |
| 1003 | GFP_KERNEL))) { | 1007 | &memcg))) { |
| 1004 | if (pages[i]) | 1008 | if (pages[i]) |
| 1005 | put_page(pages[i]); | 1009 | put_page(pages[i]); |
| 1006 | mem_cgroup_uncharge_start(); | ||
| 1007 | while (--i >= 0) { | 1010 | while (--i >= 0) { |
| 1008 | mem_cgroup_uncharge_page(pages[i]); | 1011 | memcg = (void *)page_private(pages[i]); |
| 1012 | set_page_private(pages[i], 0); | ||
| 1013 | mem_cgroup_cancel_charge(pages[i], memcg); | ||
| 1009 | put_page(pages[i]); | 1014 | put_page(pages[i]); |
| 1010 | } | 1015 | } |
| 1011 | mem_cgroup_uncharge_end(); | ||
| 1012 | kfree(pages); | 1016 | kfree(pages); |
| 1013 | ret |= VM_FAULT_OOM; | 1017 | ret |= VM_FAULT_OOM; |
| 1014 | goto out; | 1018 | goto out; |
| 1015 | } | 1019 | } |
| 1020 | set_page_private(pages[i], (unsigned long)memcg); | ||
| 1016 | } | 1021 | } |
| 1017 | 1022 | ||
| 1018 | for (i = 0; i < HPAGE_PMD_NR; i++) { | 1023 | for (i = 0; i < HPAGE_PMD_NR; i++) { |
| @@ -1041,7 +1046,11 @@ static int do_huge_pmd_wp_page_fallback(struct mm_struct *mm, | |||
| 1041 | pte_t *pte, entry; | 1046 | pte_t *pte, entry; |
| 1042 | entry = mk_pte(pages[i], vma->vm_page_prot); | 1047 | entry = mk_pte(pages[i], vma->vm_page_prot); |
| 1043 | entry = maybe_mkwrite(pte_mkdirty(entry), vma); | 1048 | entry = maybe_mkwrite(pte_mkdirty(entry), vma); |
| 1049 | memcg = (void *)page_private(pages[i]); | ||
| 1050 | set_page_private(pages[i], 0); | ||
| 1044 | page_add_new_anon_rmap(pages[i], vma, haddr); | 1051 | page_add_new_anon_rmap(pages[i], vma, haddr); |
| 1052 | mem_cgroup_commit_charge(pages[i], memcg, false); | ||
| 1053 | lru_cache_add_active_or_unevictable(pages[i], vma); | ||
| 1045 | pte = pte_offset_map(&_pmd, haddr); | 1054 | pte = pte_offset_map(&_pmd, haddr); |
| 1046 | VM_BUG_ON(!pte_none(*pte)); | 1055 | VM_BUG_ON(!pte_none(*pte)); |
| 1047 | set_pte_at(mm, haddr, pte, entry); | 1056 | set_pte_at(mm, haddr, pte, entry); |
| @@ -1065,12 +1074,12 @@ out: | |||
| 1065 | out_free_pages: | 1074 | out_free_pages: |
| 1066 | spin_unlock(ptl); | 1075 | spin_unlock(ptl); |
| 1067 | mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end); | 1076 | mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end); |
| 1068 | mem_cgroup_uncharge_start(); | ||
| 1069 | for (i = 0; i < HPAGE_PMD_NR; i++) { | 1077 | for (i = 0; i < HPAGE_PMD_NR; i++) { |
| 1070 | mem_cgroup_uncharge_page(pages[i]); | 1078 | memcg = (void *)page_private(pages[i]); |
| 1079 | set_page_private(pages[i], 0); | ||
| 1080 | mem_cgroup_cancel_charge(pages[i], memcg); | ||
| 1071 | put_page(pages[i]); | 1081 | put_page(pages[i]); |
| 1072 | } | 1082 | } |
| 1073 | mem_cgroup_uncharge_end(); | ||
| 1074 | kfree(pages); | 1083 | kfree(pages); |
| 1075 | goto out; | 1084 | goto out; |
| 1076 | } | 1085 | } |
| @@ -1081,6 +1090,7 @@ int do_huge_pmd_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 1081 | spinlock_t *ptl; | 1090 | spinlock_t *ptl; |
| 1082 | int ret = 0; | 1091 | int ret = 0; |
| 1083 | struct page *page = NULL, *new_page; | 1092 | struct page *page = NULL, *new_page; |
| 1093 | struct mem_cgroup *memcg; | ||
| 1084 | unsigned long haddr; | 1094 | unsigned long haddr; |
| 1085 | unsigned long mmun_start; /* For mmu_notifiers */ | 1095 | unsigned long mmun_start; /* For mmu_notifiers */ |
| 1086 | unsigned long mmun_end; /* For mmu_notifiers */ | 1096 | unsigned long mmun_end; /* For mmu_notifiers */ |
| @@ -1132,7 +1142,8 @@ alloc: | |||
| 1132 | goto out; | 1142 | goto out; |
| 1133 | } | 1143 | } |
| 1134 | 1144 | ||
| 1135 | if (unlikely(mem_cgroup_charge_anon(new_page, mm, GFP_TRANSHUGE))) { | 1145 | if (unlikely(mem_cgroup_try_charge(new_page, mm, |
| 1146 | GFP_TRANSHUGE, &memcg))) { | ||
| 1136 | put_page(new_page); | 1147 | put_page(new_page); |
| 1137 | if (page) { | 1148 | if (page) { |
| 1138 | split_huge_page(page); | 1149 | split_huge_page(page); |
| @@ -1161,7 +1172,7 @@ alloc: | |||
| 1161 | put_user_huge_page(page); | 1172 | put_user_huge_page(page); |
| 1162 | if (unlikely(!pmd_same(*pmd, orig_pmd))) { | 1173 | if (unlikely(!pmd_same(*pmd, orig_pmd))) { |
| 1163 | spin_unlock(ptl); | 1174 | spin_unlock(ptl); |
| 1164 | mem_cgroup_uncharge_page(new_page); | 1175 | mem_cgroup_cancel_charge(new_page, memcg); |
| 1165 | put_page(new_page); | 1176 | put_page(new_page); |
| 1166 | goto out_mn; | 1177 | goto out_mn; |
| 1167 | } else { | 1178 | } else { |
| @@ -1170,6 +1181,8 @@ alloc: | |||
| 1170 | entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma); | 1181 | entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma); |
| 1171 | pmdp_clear_flush(vma, haddr, pmd); | 1182 | pmdp_clear_flush(vma, haddr, pmd); |
| 1172 | page_add_new_anon_rmap(new_page, vma, haddr); | 1183 | page_add_new_anon_rmap(new_page, vma, haddr); |
| 1184 | mem_cgroup_commit_charge(new_page, memcg, false); | ||
| 1185 | lru_cache_add_active_or_unevictable(new_page, vma); | ||
| 1173 | set_pmd_at(mm, haddr, pmd, entry); | 1186 | set_pmd_at(mm, haddr, pmd, entry); |
| 1174 | update_mmu_cache_pmd(vma, address, pmd); | 1187 | update_mmu_cache_pmd(vma, address, pmd); |
| 1175 | if (!page) { | 1188 | if (!page) { |
| @@ -2413,6 +2426,7 @@ static void collapse_huge_page(struct mm_struct *mm, | |||
| 2413 | spinlock_t *pmd_ptl, *pte_ptl; | 2426 | spinlock_t *pmd_ptl, *pte_ptl; |
| 2414 | int isolated; | 2427 | int isolated; |
| 2415 | unsigned long hstart, hend; | 2428 | unsigned long hstart, hend; |
| 2429 | struct mem_cgroup *memcg; | ||
| 2416 | unsigned long mmun_start; /* For mmu_notifiers */ | 2430 | unsigned long mmun_start; /* For mmu_notifiers */ |
| 2417 | unsigned long mmun_end; /* For mmu_notifiers */ | 2431 | unsigned long mmun_end; /* For mmu_notifiers */ |
| 2418 | 2432 | ||
| @@ -2423,7 +2437,8 @@ static void collapse_huge_page(struct mm_struct *mm, | |||
| 2423 | if (!new_page) | 2437 | if (!new_page) |
| 2424 | return; | 2438 | return; |
| 2425 | 2439 | ||
| 2426 | if (unlikely(mem_cgroup_charge_anon(new_page, mm, GFP_TRANSHUGE))) | 2440 | if (unlikely(mem_cgroup_try_charge(new_page, mm, |
| 2441 | GFP_TRANSHUGE, &memcg))) | ||
| 2427 | return; | 2442 | return; |
| 2428 | 2443 | ||
| 2429 | /* | 2444 | /* |
| @@ -2510,6 +2525,8 @@ static void collapse_huge_page(struct mm_struct *mm, | |||
| 2510 | spin_lock(pmd_ptl); | 2525 | spin_lock(pmd_ptl); |
| 2511 | BUG_ON(!pmd_none(*pmd)); | 2526 | BUG_ON(!pmd_none(*pmd)); |
| 2512 | page_add_new_anon_rmap(new_page, vma, address); | 2527 | page_add_new_anon_rmap(new_page, vma, address); |
| 2528 | mem_cgroup_commit_charge(new_page, memcg, false); | ||
| 2529 | lru_cache_add_active_or_unevictable(new_page, vma); | ||
| 2513 | pgtable_trans_huge_deposit(mm, pmd, pgtable); | 2530 | pgtable_trans_huge_deposit(mm, pmd, pgtable); |
| 2514 | set_pmd_at(mm, address, pmd, _pmd); | 2531 | set_pmd_at(mm, address, pmd, _pmd); |
| 2515 | update_mmu_cache_pmd(vma, address, pmd); | 2532 | update_mmu_cache_pmd(vma, address, pmd); |
| @@ -2523,7 +2540,7 @@ out_up_write: | |||
| 2523 | return; | 2540 | return; |
| 2524 | 2541 | ||
| 2525 | out: | 2542 | out: |
| 2526 | mem_cgroup_uncharge_page(new_page); | 2543 | mem_cgroup_cancel_charge(new_page, memcg); |
| 2527 | goto out_up_write; | 2544 | goto out_up_write; |
| 2528 | } | 2545 | } |
| 2529 | 2546 | ||
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 90dc501eaf3f..ec4dcf1b9562 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
| @@ -754,9 +754,11 @@ static void __mem_cgroup_remove_exceeded(struct mem_cgroup_per_zone *mz, | |||
| 754 | static void mem_cgroup_remove_exceeded(struct mem_cgroup_per_zone *mz, | 754 | static void mem_cgroup_remove_exceeded(struct mem_cgroup_per_zone *mz, |
| 755 | struct mem_cgroup_tree_per_zone *mctz) | 755 | struct mem_cgroup_tree_per_zone *mctz) |
| 756 | { | 756 | { |
| 757 | spin_lock(&mctz->lock); | 757 | unsigned long flags; |
| 758 | |||
| 759 | spin_lock_irqsave(&mctz->lock, flags); | ||
| 758 | __mem_cgroup_remove_exceeded(mz, mctz); | 760 | __mem_cgroup_remove_exceeded(mz, mctz); |
| 759 | spin_unlock(&mctz->lock); | 761 | spin_unlock_irqrestore(&mctz->lock, flags); |
| 760 | } | 762 | } |
| 761 | 763 | ||
| 762 | 764 | ||
| @@ -779,7 +781,9 @@ static void mem_cgroup_update_tree(struct mem_cgroup *memcg, struct page *page) | |||
| 779 | * mem is over its softlimit. | 781 | * mem is over its softlimit. |
| 780 | */ | 782 | */ |
| 781 | if (excess || mz->on_tree) { | 783 | if (excess || mz->on_tree) { |
| 782 | spin_lock(&mctz->lock); | 784 | unsigned long flags; |
| 785 | |||
| 786 | spin_lock_irqsave(&mctz->lock, flags); | ||
| 783 | /* if on-tree, remove it */ | 787 | /* if on-tree, remove it */ |
| 784 | if (mz->on_tree) | 788 | if (mz->on_tree) |
| 785 | __mem_cgroup_remove_exceeded(mz, mctz); | 789 | __mem_cgroup_remove_exceeded(mz, mctz); |
| @@ -788,7 +792,7 @@ static void mem_cgroup_update_tree(struct mem_cgroup *memcg, struct page *page) | |||
| 788 | * If excess is 0, no tree ops. | 792 | * If excess is 0, no tree ops. |
| 789 | */ | 793 | */ |
| 790 | __mem_cgroup_insert_exceeded(mz, mctz, excess); | 794 | __mem_cgroup_insert_exceeded(mz, mctz, excess); |
| 791 | spin_unlock(&mctz->lock); | 795 | spin_unlock_irqrestore(&mctz->lock, flags); |
| 792 | } | 796 | } |
| 793 | } | 797 | } |
| 794 | } | 798 | } |
| @@ -839,9 +843,9 @@ mem_cgroup_largest_soft_limit_node(struct mem_cgroup_tree_per_zone *mctz) | |||
| 839 | { | 843 | { |
| 840 | struct mem_cgroup_per_zone *mz; | 844 | struct mem_cgroup_per_zone *mz; |
| 841 | 845 | ||
| 842 | spin_lock(&mctz->lock); | 846 | spin_lock_irq(&mctz->lock); |
| 843 | mz = __mem_cgroup_largest_soft_limit_node(mctz); | 847 | mz = __mem_cgroup_largest_soft_limit_node(mctz); |
| 844 | spin_unlock(&mctz->lock); | 848 | spin_unlock_irq(&mctz->lock); |
| 845 | return mz; | 849 | return mz; |
| 846 | } | 850 | } |
| 847 | 851 | ||
| @@ -882,13 +886,6 @@ static long mem_cgroup_read_stat(struct mem_cgroup *memcg, | |||
| 882 | return val; | 886 | return val; |
| 883 | } | 887 | } |
| 884 | 888 | ||
| 885 | static void mem_cgroup_swap_statistics(struct mem_cgroup *memcg, | ||
| 886 | bool charge) | ||
| 887 | { | ||
| 888 | int val = (charge) ? 1 : -1; | ||
| 889 | this_cpu_add(memcg->stat->count[MEM_CGROUP_STAT_SWAP], val); | ||
| 890 | } | ||
| 891 | |||
| 892 | static unsigned long mem_cgroup_read_events(struct mem_cgroup *memcg, | 889 | static unsigned long mem_cgroup_read_events(struct mem_cgroup *memcg, |
| 893 | enum mem_cgroup_events_index idx) | 890 | enum mem_cgroup_events_index idx) |
| 894 | { | 891 | { |
| @@ -909,13 +906,13 @@ static unsigned long mem_cgroup_read_events(struct mem_cgroup *memcg, | |||
| 909 | 906 | ||
| 910 | static void mem_cgroup_charge_statistics(struct mem_cgroup *memcg, | 907 | static void mem_cgroup_charge_statistics(struct mem_cgroup *memcg, |
| 911 | struct page *page, | 908 | struct page *page, |
| 912 | bool anon, int nr_pages) | 909 | int nr_pages) |
| 913 | { | 910 | { |
| 914 | /* | 911 | /* |
| 915 | * Here, RSS means 'mapped anon' and anon's SwapCache. Shmem/tmpfs is | 912 | * Here, RSS means 'mapped anon' and anon's SwapCache. Shmem/tmpfs is |
| 916 | * counted as CACHE even if it's on ANON LRU. | 913 | * counted as CACHE even if it's on ANON LRU. |
| 917 | */ | 914 | */ |
| 918 | if (anon) | 915 | if (PageAnon(page)) |
| 919 | __this_cpu_add(memcg->stat->count[MEM_CGROUP_STAT_RSS], | 916 | __this_cpu_add(memcg->stat->count[MEM_CGROUP_STAT_RSS], |
| 920 | nr_pages); | 917 | nr_pages); |
| 921 | else | 918 | else |
| @@ -1013,7 +1010,6 @@ static bool mem_cgroup_event_ratelimit(struct mem_cgroup *memcg, | |||
| 1013 | */ | 1010 | */ |
| 1014 | static void memcg_check_events(struct mem_cgroup *memcg, struct page *page) | 1011 | static void memcg_check_events(struct mem_cgroup *memcg, struct page *page) |
| 1015 | { | 1012 | { |
| 1016 | preempt_disable(); | ||
| 1017 | /* threshold event is triggered in finer grain than soft limit */ | 1013 | /* threshold event is triggered in finer grain than soft limit */ |
| 1018 | if (unlikely(mem_cgroup_event_ratelimit(memcg, | 1014 | if (unlikely(mem_cgroup_event_ratelimit(memcg, |
| 1019 | MEM_CGROUP_TARGET_THRESH))) { | 1015 | MEM_CGROUP_TARGET_THRESH))) { |
| @@ -1026,8 +1022,6 @@ static void memcg_check_events(struct mem_cgroup *memcg, struct page *page) | |||
| 1026 | do_numainfo = mem_cgroup_event_ratelimit(memcg, | 1022 | do_numainfo = mem_cgroup_event_ratelimit(memcg, |
| 1027 | MEM_CGROUP_TARGET_NUMAINFO); | 1023 | MEM_CGROUP_TARGET_NUMAINFO); |
| 1028 | #endif | 1024 | #endif |
| 1029 | preempt_enable(); | ||
| 1030 | |||
| 1031 | mem_cgroup_threshold(memcg); | 1025 | mem_cgroup_threshold(memcg); |
| 1032 | if (unlikely(do_softlimit)) | 1026 | if (unlikely(do_softlimit)) |
| 1033 | mem_cgroup_update_tree(memcg, page); | 1027 | mem_cgroup_update_tree(memcg, page); |
| @@ -1035,8 +1029,7 @@ static void memcg_check_events(struct mem_cgroup *memcg, struct page *page) | |||
| 1035 | if (unlikely(do_numainfo)) | 1029 | if (unlikely(do_numainfo)) |
| 1036 | atomic_inc(&memcg->numainfo_events); | 1030 | atomic_inc(&memcg->numainfo_events); |
| 1037 | #endif | 1031 | #endif |
| 1038 | } else | 1032 | } |
| 1039 | preempt_enable(); | ||
| 1040 | } | 1033 | } |
| 1041 | 1034 | ||
| 1042 | struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p) | 1035 | struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p) |
| @@ -1347,20 +1340,6 @@ out: | |||
| 1347 | return lruvec; | 1340 | return lruvec; |
| 1348 | } | 1341 | } |
| 1349 | 1342 | ||
| 1350 | /* | ||
| 1351 | * Following LRU functions are allowed to be used without PCG_LOCK. | ||
| 1352 | * Operations are called by routine of global LRU independently from memcg. | ||
| 1353 | * What we have to take care of here is validness of pc->mem_cgroup. | ||
| 1354 | * | ||
| 1355 | * Changes to pc->mem_cgroup happens when | ||
| 1356 | * 1. charge | ||
| 1357 | * 2. moving account | ||
| 1358 | * In typical case, "charge" is done before add-to-lru. Exception is SwapCache. | ||
| 1359 | * It is added to LRU before charge. | ||
| 1360 | * If PCG_USED bit is not set, page_cgroup is not added to this private LRU. | ||
| 1361 | * When moving account, the page is not on LRU. It's isolated. | ||
| 1362 | */ | ||
| 1363 | |||
| 1364 | /** | 1343 | /** |
| 1365 | * mem_cgroup_page_lruvec - return lruvec for adding an lru page | 1344 | * mem_cgroup_page_lruvec - return lruvec for adding an lru page |
| 1366 | * @page: the page | 1345 | * @page: the page |
| @@ -2261,22 +2240,14 @@ cleanup: | |||
| 2261 | * | 2240 | * |
| 2262 | * Notes: Race condition | 2241 | * Notes: Race condition |
| 2263 | * | 2242 | * |
| 2264 | * We usually use lock_page_cgroup() for accessing page_cgroup member but | 2243 | * Charging occurs during page instantiation, while the page is |
| 2265 | * it tends to be costly. But considering some conditions, we doesn't need | 2244 | * unmapped and locked in page migration, or while the page table is |
| 2266 | * to do so _always_. | 2245 | * locked in THP migration. No race is possible. |
| 2267 | * | ||
| 2268 | * Considering "charge", lock_page_cgroup() is not required because all | ||
| 2269 | * file-stat operations happen after a page is attached to radix-tree. There | ||
| 2270 | * are no race with "charge". | ||
| 2271 | * | 2246 | * |
| 2272 | * Considering "uncharge", we know that memcg doesn't clear pc->mem_cgroup | 2247 | * Uncharge happens to pages with zero references, no race possible. |
| 2273 | * at "uncharge" intentionally. So, we always see valid pc->mem_cgroup even | ||
| 2274 | * if there are race with "uncharge". Statistics itself is properly handled | ||
| 2275 | * by flags. | ||
| 2276 | * | 2248 | * |
| 2277 | * Considering "move", this is an only case we see a race. To make the race | 2249 | * Charge moving between groups is protected by checking mm->moving |
| 2278 | * small, we check memcg->moving_account and detect there are possibility | 2250 | * account and taking the move_lock in the slowpath. |
| 2279 | * of race or not. If there is, we take a lock. | ||
| 2280 | */ | 2251 | */ |
| 2281 | 2252 | ||
| 2282 | void __mem_cgroup_begin_update_page_stat(struct page *page, | 2253 | void __mem_cgroup_begin_update_page_stat(struct page *page, |
| @@ -2551,17 +2522,8 @@ static int memcg_cpu_hotplug_callback(struct notifier_block *nb, | |||
| 2551 | return NOTIFY_OK; | 2522 | return NOTIFY_OK; |
| 2552 | } | 2523 | } |
| 2553 | 2524 | ||
| 2554 | /** | 2525 | static int try_charge(struct mem_cgroup *memcg, gfp_t gfp_mask, |
| 2555 | * mem_cgroup_try_charge - try charging a memcg | 2526 | unsigned int nr_pages) |
| 2556 | * @memcg: memcg to charge | ||
| 2557 | * @nr_pages: number of pages to charge | ||
| 2558 | * | ||
| 2559 | * Returns 0 if @memcg was charged successfully, -EINTR if the charge | ||
| 2560 | * was bypassed to root_mem_cgroup, and -ENOMEM if the charge failed. | ||
| 2561 | */ | ||
| 2562 | static int mem_cgroup_try_charge(struct mem_cgroup *memcg, | ||
| 2563 | gfp_t gfp_mask, | ||
| 2564 | unsigned int nr_pages) | ||
| 2565 | { | 2527 | { |
| 2566 | unsigned int batch = max(CHARGE_BATCH, nr_pages); | 2528 | unsigned int batch = max(CHARGE_BATCH, nr_pages); |
| 2567 | int nr_retries = MEM_CGROUP_RECLAIM_RETRIES; | 2529 | int nr_retries = MEM_CGROUP_RECLAIM_RETRIES; |
| @@ -2660,41 +2622,7 @@ done: | |||
| 2660 | return ret; | 2622 | return ret; |
| 2661 | } | 2623 | } |
| 2662 | 2624 | ||
| 2663 | /** | 2625 | static void cancel_charge(struct mem_cgroup *memcg, unsigned int nr_pages) |
| 2664 | * mem_cgroup_try_charge_mm - try charging a mm | ||
| 2665 | * @mm: mm_struct to charge | ||
| 2666 | * @nr_pages: number of pages to charge | ||
| 2667 | * @oom: trigger OOM if reclaim fails | ||
| 2668 | * | ||
| 2669 | * Returns the charged mem_cgroup associated with the given mm_struct or | ||
| 2670 | * NULL the charge failed. | ||
| 2671 | */ | ||
| 2672 | static struct mem_cgroup *mem_cgroup_try_charge_mm(struct mm_struct *mm, | ||
| 2673 | gfp_t gfp_mask, | ||
| 2674 | unsigned int nr_pages) | ||
| 2675 | |||
| 2676 | { | ||
| 2677 | struct mem_cgroup *memcg; | ||
| 2678 | int ret; | ||
| 2679 | |||
| 2680 | memcg = get_mem_cgroup_from_mm(mm); | ||
| 2681 | ret = mem_cgroup_try_charge(memcg, gfp_mask, nr_pages); | ||
| 2682 | css_put(&memcg->css); | ||
| 2683 | if (ret == -EINTR) | ||
| 2684 | memcg = root_mem_cgroup; | ||
| 2685 | else if (ret) | ||
| 2686 | memcg = NULL; | ||
| 2687 | |||
| 2688 | return memcg; | ||
| 2689 | } | ||
| 2690 | |||
| 2691 | /* | ||
| 2692 | * Somemtimes we have to undo a charge we got by try_charge(). | ||
| 2693 | * This function is for that and do uncharge, put css's refcnt. | ||
| 2694 | * gotten by try_charge(). | ||
| 2695 | */ | ||
| 2696 | static void __mem_cgroup_cancel_charge(struct mem_cgroup *memcg, | ||
| 2697 | unsigned int nr_pages) | ||
| 2698 | { | 2626 | { |
| 2699 | unsigned long bytes = nr_pages * PAGE_SIZE; | 2627 | unsigned long bytes = nr_pages * PAGE_SIZE; |
| 2700 | 2628 | ||
| @@ -2732,6 +2660,16 @@ static struct mem_cgroup *mem_cgroup_lookup(unsigned short id) | |||
| 2732 | return mem_cgroup_from_id(id); | 2660 | return mem_cgroup_from_id(id); |
| 2733 | } | 2661 | } |
| 2734 | 2662 | ||
| 2663 | /* | ||
| 2664 | * try_get_mem_cgroup_from_page - look up page's memcg association | ||
| 2665 | * @page: the page | ||
| 2666 | * | ||
| 2667 | * Look up, get a css reference, and return the memcg that owns @page. | ||
| 2668 | * | ||
| 2669 | * The page must be locked to prevent racing with swap-in and page | ||
| 2670 | * cache charges. If coming from an unlocked page table, the caller | ||
| 2671 | * must ensure the page is on the LRU or this can race with charging. | ||
| 2672 | */ | ||
| 2735 | struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page) | 2673 | struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page) |
| 2736 | { | 2674 | { |
| 2737 | struct mem_cgroup *memcg = NULL; | 2675 | struct mem_cgroup *memcg = NULL; |
| @@ -2742,7 +2680,6 @@ struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page) | |||
| 2742 | VM_BUG_ON_PAGE(!PageLocked(page), page); | 2680 | VM_BUG_ON_PAGE(!PageLocked(page), page); |
| 2743 | 2681 | ||
| 2744 | pc = lookup_page_cgroup(page); | 2682 | pc = lookup_page_cgroup(page); |
| 2745 | lock_page_cgroup(pc); | ||
| 2746 | if (PageCgroupUsed(pc)) { | 2683 | if (PageCgroupUsed(pc)) { |
| 2747 | memcg = pc->mem_cgroup; | 2684 | memcg = pc->mem_cgroup; |
| 2748 | if (memcg && !css_tryget_online(&memcg->css)) | 2685 | if (memcg && !css_tryget_online(&memcg->css)) |
| @@ -2756,23 +2693,46 @@ struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page) | |||
| 2756 | memcg = NULL; | 2693 | memcg = NULL; |
| 2757 | rcu_read_unlock(); | 2694 | rcu_read_unlock(); |
| 2758 | } | 2695 | } |
| 2759 | unlock_page_cgroup(pc); | ||
| 2760 | return memcg; | 2696 | return memcg; |
| 2761 | } | 2697 | } |
| 2762 | 2698 | ||
| 2763 | static void __mem_cgroup_commit_charge(struct mem_cgroup *memcg, | 2699 | static void lock_page_lru(struct page *page, int *isolated) |
| 2764 | struct page *page, | 2700 | { |
| 2765 | unsigned int nr_pages, | 2701 | struct zone *zone = page_zone(page); |
| 2766 | enum charge_type ctype, | 2702 | |
| 2767 | bool lrucare) | 2703 | spin_lock_irq(&zone->lru_lock); |
| 2704 | if (PageLRU(page)) { | ||
| 2705 | struct lruvec *lruvec; | ||
| 2706 | |||
| 2707 | lruvec = mem_cgroup_page_lruvec(page, zone); | ||
| 2708 | ClearPageLRU(page); | ||
| 2709 | del_page_from_lru_list(page, lruvec, page_lru(page)); | ||
| 2710 | *isolated = 1; | ||
| 2711 | } else | ||
| 2712 | *isolated = 0; | ||
| 2713 | } | ||
| 2714 | |||
| 2715 | static void unlock_page_lru(struct page *page, int isolated) | ||
| 2716 | { | ||
| 2717 | struct zone *zone = page_zone(page); | ||
| 2718 | |||
| 2719 | if (isolated) { | ||
| 2720 | struct lruvec *lruvec; | ||
| 2721 | |||
| 2722 | lruvec = mem_cgroup_page_lruvec(page, zone); | ||
| 2723 | VM_BUG_ON_PAGE(PageLRU(page), page); | ||
| 2724 | SetPageLRU(page); | ||
| 2725 | add_page_to_lru_list(page, lruvec, page_lru(page)); | ||
| 2726 | } | ||
| 2727 | spin_unlock_irq(&zone->lru_lock); | ||
| 2728 | } | ||
| 2729 | |||
| 2730 | static void commit_charge(struct page *page, struct mem_cgroup *memcg, | ||
| 2731 | bool lrucare) | ||
| 2768 | { | 2732 | { |
| 2769 | struct page_cgroup *pc = lookup_page_cgroup(page); | 2733 | struct page_cgroup *pc = lookup_page_cgroup(page); |
| 2770 | struct zone *uninitialized_var(zone); | 2734 | int isolated; |
| 2771 | struct lruvec *lruvec; | ||
| 2772 | bool was_on_lru = false; | ||
| 2773 | bool anon; | ||
| 2774 | 2735 | ||
| 2775 | lock_page_cgroup(pc); | ||
| 2776 | VM_BUG_ON_PAGE(PageCgroupUsed(pc), page); | 2736 | VM_BUG_ON_PAGE(PageCgroupUsed(pc), page); |
| 2777 | /* | 2737 | /* |
| 2778 | * we don't need page_cgroup_lock about tail pages, becase they are not | 2738 | * we don't need page_cgroup_lock about tail pages, becase they are not |
| @@ -2783,44 +2743,28 @@ static void __mem_cgroup_commit_charge(struct mem_cgroup *memcg, | |||
| 2783 | * In some cases, SwapCache and FUSE(splice_buf->radixtree), the page | 2743 | * In some cases, SwapCache and FUSE(splice_buf->radixtree), the page |
| 2784 | * may already be on some other mem_cgroup's LRU. Take care of it. | 2744 | * may already be on some other mem_cgroup's LRU. Take care of it. |
| 2785 | */ | 2745 | */ |
| 2786 | if (lrucare) { | 2746 | if (lrucare) |
| 2787 | zone = page_zone(page); | 2747 | lock_page_lru(page, &isolated); |
| 2788 | spin_lock_irq(&zone->lru_lock); | ||
| 2789 | if (PageLRU(page)) { | ||
| 2790 | lruvec = mem_cgroup_zone_lruvec(zone, pc->mem_cgroup); | ||
| 2791 | ClearPageLRU(page); | ||
| 2792 | del_page_from_lru_list(page, lruvec, page_lru(page)); | ||
| 2793 | was_on_lru = true; | ||
| 2794 | } | ||
| 2795 | } | ||
| 2796 | |||
| 2797 | pc->mem_cgroup = memcg; | ||
| 2798 | SetPageCgroupUsed(pc); | ||
| 2799 | |||
| 2800 | if (lrucare) { | ||
| 2801 | if (was_on_lru) { | ||
| 2802 | lruvec = mem_cgroup_zone_lruvec(zone, pc->mem_cgroup); | ||
| 2803 | VM_BUG_ON_PAGE(PageLRU(page), page); | ||
| 2804 | SetPageLRU(page); | ||
| 2805 | add_page_to_lru_list(page, lruvec, page_lru(page)); | ||
| 2806 | } | ||
| 2807 | spin_unlock_irq(&zone->lru_lock); | ||
| 2808 | } | ||
| 2809 | |||
| 2810 | if (ctype == MEM_CGROUP_CHARGE_TYPE_ANON) | ||
| 2811 | anon = true; | ||
| 2812 | else | ||
| 2813 | anon = false; | ||
| 2814 | |||
| 2815 | mem_cgroup_charge_statistics(memcg, page, anon, nr_pages); | ||
| 2816 | unlock_page_cgroup(pc); | ||
| 2817 | 2748 | ||
| 2818 | /* | 2749 | /* |
| 2819 | * "charge_statistics" updated event counter. Then, check it. | 2750 | * Nobody should be changing or seriously looking at |
| 2820 | * Insert ancestor (and ancestor's ancestors), to softlimit RB-tree. | 2751 | * pc->mem_cgroup and pc->flags at this point: |
| 2821 | * if they exceeds softlimit. | 2752 | * |
| 2753 | * - the page is uncharged | ||
| 2754 | * | ||
| 2755 | * - the page is off-LRU | ||
| 2756 | * | ||
| 2757 | * - an anonymous fault has exclusive page access, except for | ||
| 2758 | * a locked page table | ||
| 2759 | * | ||
| 2760 | * - a page cache insertion, a swapin fault, or a migration | ||
| 2761 | * have the page locked | ||
| 2822 | */ | 2762 | */ |
| 2823 | memcg_check_events(memcg, page); | 2763 | pc->mem_cgroup = memcg; |
| 2764 | pc->flags = PCG_USED | PCG_MEM | (do_swap_account ? PCG_MEMSW : 0); | ||
| 2765 | |||
| 2766 | if (lrucare) | ||
| 2767 | unlock_page_lru(page, isolated); | ||
| 2824 | } | 2768 | } |
| 2825 | 2769 | ||
| 2826 | static DEFINE_MUTEX(set_limit_mutex); | 2770 | static DEFINE_MUTEX(set_limit_mutex); |
| @@ -2882,21 +2826,21 @@ static int memcg_charge_kmem(struct mem_cgroup *memcg, gfp_t gfp, u64 size) | |||
| 2882 | if (ret) | 2826 | if (ret) |
| 2883 | return ret; | 2827 | return ret; |
| 2884 | 2828 | ||
| 2885 | ret = mem_cgroup_try_charge(memcg, gfp, size >> PAGE_SHIFT); | 2829 | ret = try_charge(memcg, gfp, size >> PAGE_SHIFT); |
| 2886 | if (ret == -EINTR) { | 2830 | if (ret == -EINTR) { |
| 2887 | /* | 2831 | /* |
| 2888 | * mem_cgroup_try_charge() chosed to bypass to root due to | 2832 | * try_charge() chose to bypass to root due to OOM kill or |
| 2889 | * OOM kill or fatal signal. Since our only options are to | 2833 | * fatal signal. Since our only options are to either fail |
| 2890 | * either fail the allocation or charge it to this cgroup, do | 2834 | * the allocation or charge it to this cgroup, do it as a |
| 2891 | * it as a temporary condition. But we can't fail. From a | 2835 | * temporary condition. But we can't fail. From a kmem/slab |
| 2892 | * kmem/slab perspective, the cache has already been selected, | 2836 | * perspective, the cache has already been selected, by |
| 2893 | * by mem_cgroup_kmem_get_cache(), so it is too late to change | 2837 | * mem_cgroup_kmem_get_cache(), so it is too late to change |
| 2894 | * our minds. | 2838 | * our minds. |
| 2895 | * | 2839 | * |
| 2896 | * This condition will only trigger if the task entered | 2840 | * This condition will only trigger if the task entered |
| 2897 | * memcg_charge_kmem in a sane state, but was OOM-killed during | 2841 | * memcg_charge_kmem in a sane state, but was OOM-killed |
| 2898 | * mem_cgroup_try_charge() above. Tasks that were already | 2842 | * during try_charge() above. Tasks that were already dying |
| 2899 | * dying when the allocation triggers should have been already | 2843 | * when the allocation triggers should have been already |
| 2900 | * directed to the root cgroup in memcontrol.h | 2844 | * directed to the root cgroup in memcontrol.h |
| 2901 | */ | 2845 | */ |
| 2902 | res_counter_charge_nofail(&memcg->res, size, &fail_res); | 2846 | res_counter_charge_nofail(&memcg->res, size, &fail_res); |
| @@ -3447,7 +3391,6 @@ static inline void memcg_unregister_all_caches(struct mem_cgroup *memcg) | |||
| 3447 | 3391 | ||
| 3448 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | 3392 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE |
| 3449 | 3393 | ||
| 3450 | #define PCGF_NOCOPY_AT_SPLIT (1 << PCG_LOCK | 1 << PCG_MIGRATION) | ||
| 3451 | /* | 3394 | /* |
| 3452 | * Because tail pages are not marked as "used", set it. We're under | 3395 | * Because tail pages are not marked as "used", set it. We're under |
| 3453 | * zone->lru_lock, 'splitting on pmd' and compound_lock. | 3396 | * zone->lru_lock, 'splitting on pmd' and compound_lock. |
| @@ -3468,7 +3411,7 @@ void mem_cgroup_split_huge_fixup(struct page *head) | |||
| 3468 | for (i = 1; i < HPAGE_PMD_NR; i++) { | 3411 | for (i = 1; i < HPAGE_PMD_NR; i++) { |
| 3469 | pc = head_pc + i; | 3412 | pc = head_pc + i; |
| 3470 | pc->mem_cgroup = memcg; | 3413 | pc->mem_cgroup = memcg; |
| 3471 | pc->flags = head_pc->flags & ~PCGF_NOCOPY_AT_SPLIT; | 3414 | pc->flags = head_pc->flags; |
| 3472 | } | 3415 | } |
| 3473 | __this_cpu_sub(memcg->stat->count[MEM_CGROUP_STAT_RSS_HUGE], | 3416 | __this_cpu_sub(memcg->stat->count[MEM_CGROUP_STAT_RSS_HUGE], |
| 3474 | HPAGE_PMD_NR); | 3417 | HPAGE_PMD_NR); |
| @@ -3498,7 +3441,6 @@ static int mem_cgroup_move_account(struct page *page, | |||
| 3498 | { | 3441 | { |
| 3499 | unsigned long flags; | 3442 | unsigned long flags; |
| 3500 | int ret; | 3443 | int ret; |
| 3501 | bool anon = PageAnon(page); | ||
| 3502 | 3444 | ||
| 3503 | VM_BUG_ON(from == to); | 3445 | VM_BUG_ON(from == to); |
| 3504 | VM_BUG_ON_PAGE(PageLRU(page), page); | 3446 | VM_BUG_ON_PAGE(PageLRU(page), page); |
| @@ -3512,15 +3454,21 @@ static int mem_cgroup_move_account(struct page *page, | |||
| 3512 | if (nr_pages > 1 && !PageTransHuge(page)) | 3454 | if (nr_pages > 1 && !PageTransHuge(page)) |
| 3513 | goto out; | 3455 | goto out; |
| 3514 | 3456 | ||
| 3515 | lock_page_cgroup(pc); | 3457 | /* |
| 3458 | * Prevent mem_cgroup_migrate() from looking at pc->mem_cgroup | ||
| 3459 | * of its source page while we change it: page migration takes | ||
| 3460 | * both pages off the LRU, but page cache replacement doesn't. | ||
| 3461 | */ | ||
| 3462 | if (!trylock_page(page)) | ||
| 3463 | goto out; | ||
| 3516 | 3464 | ||
| 3517 | ret = -EINVAL; | 3465 | ret = -EINVAL; |
| 3518 | if (!PageCgroupUsed(pc) || pc->mem_cgroup != from) | 3466 | if (!PageCgroupUsed(pc) || pc->mem_cgroup != from) |
| 3519 | goto unlock; | 3467 | goto out_unlock; |
| 3520 | 3468 | ||
| 3521 | move_lock_mem_cgroup(from, &flags); | 3469 | move_lock_mem_cgroup(from, &flags); |
| 3522 | 3470 | ||
| 3523 | if (!anon && page_mapped(page)) { | 3471 | if (!PageAnon(page) && page_mapped(page)) { |
| 3524 | __this_cpu_sub(from->stat->count[MEM_CGROUP_STAT_FILE_MAPPED], | 3472 | __this_cpu_sub(from->stat->count[MEM_CGROUP_STAT_FILE_MAPPED], |
| 3525 | nr_pages); | 3473 | nr_pages); |
| 3526 | __this_cpu_add(to->stat->count[MEM_CGROUP_STAT_FILE_MAPPED], | 3474 | __this_cpu_add(to->stat->count[MEM_CGROUP_STAT_FILE_MAPPED], |
| @@ -3534,20 +3482,25 @@ static int mem_cgroup_move_account(struct page *page, | |||
| 3534 | nr_pages); | 3482 | nr_pages); |
| 3535 | } | 3483 | } |
| 3536 | 3484 | ||
| 3537 | mem_cgroup_charge_statistics(from, page, anon, -nr_pages); | 3485 | /* |
| 3486 | * It is safe to change pc->mem_cgroup here because the page | ||
| 3487 | * is referenced, charged, and isolated - we can't race with | ||
| 3488 | * uncharging, charging, migration, or LRU putback. | ||
| 3489 | */ | ||
| 3538 | 3490 | ||
| 3539 | /* caller should have done css_get */ | 3491 | /* caller should have done css_get */ |
| 3540 | pc->mem_cgroup = to; | 3492 | pc->mem_cgroup = to; |
| 3541 | mem_cgroup_charge_statistics(to, page, anon, nr_pages); | ||
| 3542 | move_unlock_mem_cgroup(from, &flags); | 3493 | move_unlock_mem_cgroup(from, &flags); |
| 3543 | ret = 0; | 3494 | ret = 0; |
| 3544 | unlock: | 3495 | |
| 3545 | unlock_page_cgroup(pc); | 3496 | local_irq_disable(); |
| 3546 | /* | 3497 | mem_cgroup_charge_statistics(to, page, nr_pages); |
| 3547 | * check events | ||
| 3548 | */ | ||
| 3549 | memcg_check_events(to, page); | 3498 | memcg_check_events(to, page); |
| 3499 | mem_cgroup_charge_statistics(from, page, -nr_pages); | ||
| 3550 | memcg_check_events(from, page); | 3500 | memcg_check_events(from, page); |
| 3501 | local_irq_enable(); | ||
| 3502 | out_unlock: | ||
| 3503 | unlock_page(page); | ||
| 3551 | out: | 3504 | out: |
| 3552 | return ret; | 3505 | return ret; |
| 3553 | } | 3506 | } |
| @@ -3618,449 +3571,12 @@ out: | |||
| 3618 | return ret; | 3571 | return ret; |
| 3619 | } | 3572 | } |
| 3620 | 3573 | ||
| 3621 | int mem_cgroup_charge_anon(struct page *page, | ||
| 3622 | struct mm_struct *mm, gfp_t gfp_mask) | ||
| 3623 | { | ||
| 3624 | unsigned int nr_pages = 1; | ||
| 3625 | struct mem_cgroup *memcg; | ||
| 3626 | |||
| 3627 | if (mem_cgroup_disabled()) | ||
| 3628 | return 0; | ||
| 3629 | |||
| 3630 | VM_BUG_ON_PAGE(page_mapped(page), page); | ||
| 3631 | VM_BUG_ON_PAGE(page->mapping && !PageAnon(page), page); | ||
| 3632 | VM_BUG_ON(!mm); | ||
| 3633 | |||
| 3634 | if (PageTransHuge(page)) { | ||
| 3635 | nr_pages <<= compound_order(page); | ||
| 3636 | VM_BUG_ON_PAGE(!PageTransHuge(page), page); | ||
| 3637 | } | ||
| 3638 | |||
| 3639 | memcg = mem_cgroup_try_charge_mm(mm, gfp_mask, nr_pages); | ||
| 3640 | if (!memcg) | ||
| 3641 | return -ENOMEM; | ||
| 3642 | __mem_cgroup_commit_charge(memcg, page, nr_pages, | ||
| 3643 | MEM_CGROUP_CHARGE_TYPE_ANON, false); | ||
| 3644 | return 0; | ||
| 3645 | } | ||
| 3646 | |||
| 3647 | /* | ||
| 3648 | * While swap-in, try_charge -> commit or cancel, the page is locked. | ||
| 3649 | * And when try_charge() successfully returns, one refcnt to memcg without | ||
| 3650 | * struct page_cgroup is acquired. This refcnt will be consumed by | ||
| 3651 | * "commit()" or removed by "cancel()" | ||
| 3652 | */ | ||
| 3653 | static int __mem_cgroup_try_charge_swapin(struct mm_struct *mm, | ||
| 3654 | struct page *page, | ||
| 3655 | gfp_t mask, | ||
| 3656 | struct mem_cgroup **memcgp) | ||
| 3657 | { | ||
| 3658 | struct mem_cgroup *memcg = NULL; | ||
| 3659 | struct page_cgroup *pc; | ||
| 3660 | int ret; | ||
| 3661 | |||
| 3662 | pc = lookup_page_cgroup(page); | ||
| 3663 | /* | ||
| 3664 | * Every swap fault against a single page tries to charge the | ||
| 3665 | * page, bail as early as possible. shmem_unuse() encounters | ||
| 3666 | * already charged pages, too. The USED bit is protected by | ||
| 3667 | * the page lock, which serializes swap cache removal, which | ||
| 3668 | * in turn serializes uncharging. | ||
| 3669 | */ | ||
| 3670 | if (PageCgroupUsed(pc)) | ||
| 3671 | goto out; | ||
| 3672 | if (do_swap_account) | ||
| 3673 | memcg = try_get_mem_cgroup_from_page(page); | ||
| 3674 | if (!memcg) | ||
| 3675 | memcg = get_mem_cgroup_from_mm(mm); | ||
| 3676 | ret = mem_cgroup_try_charge(memcg, mask, 1); | ||
| 3677 | css_put(&memcg->css); | ||
| 3678 | if (ret == -EINTR) | ||
| 3679 | memcg = root_mem_cgroup; | ||
| 3680 | else if (ret) | ||
| 3681 | return ret; | ||
| 3682 | out: | ||
| 3683 | *memcgp = memcg; | ||
| 3684 | return 0; | ||
| 3685 | } | ||
| 3686 | |||
| 3687 | int mem_cgroup_try_charge_swapin(struct mm_struct *mm, struct page *page, | ||
| 3688 | gfp_t gfp_mask, struct mem_cgroup **memcgp) | ||
| 3689 | { | ||
| 3690 | if (mem_cgroup_disabled()) { | ||
| 3691 | *memcgp = NULL; | ||
| 3692 | return 0; | ||
| 3693 | } | ||
| 3694 | /* | ||
| 3695 | * A racing thread's fault, or swapoff, may have already | ||
| 3696 | * updated the pte, and even removed page from swap cache: in | ||
| 3697 | * those cases unuse_pte()'s pte_same() test will fail; but | ||
| 3698 | * there's also a KSM case which does need to charge the page. | ||
| 3699 | */ | ||
| 3700 | if (!PageSwapCache(page)) { | ||
| 3701 | struct mem_cgroup *memcg; | ||
| 3702 | |||
| 3703 | memcg = mem_cgroup_try_charge_mm(mm, gfp_mask, 1); | ||
| 3704 | if (!memcg) | ||
| 3705 | return -ENOMEM; | ||
| 3706 | *memcgp = memcg; | ||
| 3707 | return 0; | ||
| 3708 | } | ||
| 3709 | return __mem_cgroup_try_charge_swapin(mm, page, gfp_mask, memcgp); | ||
| 3710 | } | ||
| 3711 | |||
| 3712 | void mem_cgroup_cancel_charge_swapin(struct mem_cgroup *memcg) | ||
| 3713 | { | ||
| 3714 | if (mem_cgroup_disabled()) | ||
| 3715 | return; | ||
| 3716 | if (!memcg) | ||
| 3717 | return; | ||
| 3718 | __mem_cgroup_cancel_charge(memcg, 1); | ||
| 3719 | } | ||
| 3720 | |||
| 3721 | static void | ||
| 3722 | __mem_cgroup_commit_charge_swapin(struct page *page, struct mem_cgroup *memcg, | ||
| 3723 | enum charge_type ctype) | ||
| 3724 | { | ||
| 3725 | if (mem_cgroup_disabled()) | ||
| 3726 | return; | ||
| 3727 | if (!memcg) | ||
| 3728 | return; | ||
| 3729 | |||
| 3730 | __mem_cgroup_commit_charge(memcg, page, 1, ctype, true); | ||
| 3731 | /* | ||
| 3732 | * Now swap is on-memory. This means this page may be | ||
| 3733 | * counted both as mem and swap....double count. | ||
| 3734 | * Fix it by uncharging from memsw. Basically, this SwapCache is stable | ||
| 3735 | * under lock_page(). But in do_swap_page()::memory.c, reuse_swap_page() | ||
| 3736 | * may call delete_from_swap_cache() before reach here. | ||
| 3737 | */ | ||
| 3738 | if (do_swap_account && PageSwapCache(page)) { | ||
| 3739 | swp_entry_t ent = {.val = page_private(page)}; | ||
| 3740 | mem_cgroup_uncharge_swap(ent); | ||
| 3741 | } | ||
| 3742 | } | ||
| 3743 | |||
| 3744 | void mem_cgroup_commit_charge_swapin(struct page *page, | ||
| 3745 | struct mem_cgroup *memcg) | ||
| 3746 | { | ||
| 3747 | __mem_cgroup_commit_charge_swapin(page, memcg, | ||
| 3748 | MEM_CGROUP_CHARGE_TYPE_ANON); | ||
| 3749 | } | ||
| 3750 | |||
| 3751 | int mem_cgroup_charge_file(struct page *page, struct mm_struct *mm, | ||
| 3752 | gfp_t gfp_mask) | ||
| 3753 | { | ||
| 3754 | enum charge_type type = MEM_CGROUP_CHARGE_TYPE_CACHE; | ||
| 3755 | struct mem_cgroup *memcg; | ||
| 3756 | int ret; | ||
| 3757 | |||
| 3758 | if (mem_cgroup_disabled()) | ||
| 3759 | return 0; | ||
| 3760 | if (PageCompound(page)) | ||
| 3761 | return 0; | ||
| 3762 | |||
| 3763 | if (PageSwapCache(page)) { /* shmem */ | ||
| 3764 | ret = __mem_cgroup_try_charge_swapin(mm, page, | ||
| 3765 | gfp_mask, &memcg); | ||
| 3766 | if (ret) | ||
| 3767 | return ret; | ||
| 3768 | __mem_cgroup_commit_charge_swapin(page, memcg, type); | ||
| 3769 | return 0; | ||
| 3770 | } | ||
| 3771 | |||
| 3772 | memcg = mem_cgroup_try_charge_mm(mm, gfp_mask, 1); | ||
| 3773 | if (!memcg) | ||
| 3774 | return -ENOMEM; | ||
| 3775 | __mem_cgroup_commit_charge(memcg, page, 1, type, false); | ||
| 3776 | return 0; | ||
| 3777 | } | ||
| 3778 | |||
| 3779 | static void mem_cgroup_do_uncharge(struct mem_cgroup *memcg, | ||
| 3780 | unsigned int nr_pages, | ||
| 3781 | const enum charge_type ctype) | ||
| 3782 | { | ||
| 3783 | struct memcg_batch_info *batch = NULL; | ||
| 3784 | bool uncharge_memsw = true; | ||
| 3785 | |||
| 3786 | /* If swapout, usage of swap doesn't decrease */ | ||
| 3787 | if (!do_swap_account || ctype == MEM_CGROUP_CHARGE_TYPE_SWAPOUT) | ||
| 3788 | uncharge_memsw = false; | ||
| 3789 | |||
| 3790 | batch = ¤t->memcg_batch; | ||
| 3791 | /* | ||
| 3792 | * In usual, we do css_get() when we remember memcg pointer. | ||
| 3793 | * But in this case, we keep res->usage until end of a series of | ||
| 3794 | * uncharges. Then, it's ok to ignore memcg's refcnt. | ||
| 3795 | */ | ||
| 3796 | if (!batch->memcg) | ||
| 3797 | batch->memcg = memcg; | ||
| 3798 | /* | ||
| 3799 | * do_batch > 0 when unmapping pages or inode invalidate/truncate. | ||
| 3800 | * In those cases, all pages freed continuously can be expected to be in | ||
| 3801 | * the same cgroup and we have chance to coalesce uncharges. | ||
| 3802 | * But we do uncharge one by one if this is killed by OOM(TIF_MEMDIE) | ||
| 3803 | * because we want to do uncharge as soon as possible. | ||
| 3804 | */ | ||
| 3805 | |||
| 3806 | if (!batch->do_batch || test_thread_flag(TIF_MEMDIE)) | ||
| 3807 | goto direct_uncharge; | ||
| 3808 | |||
| 3809 | if (nr_pages > 1) | ||
| 3810 | goto direct_uncharge; | ||
| 3811 | |||
| 3812 | /* | ||
| 3813 | * In typical case, batch->memcg == mem. This means we can | ||
| 3814 | * merge a series of uncharges to an uncharge of res_counter. | ||
| 3815 | * If not, we uncharge res_counter ony by one. | ||
| 3816 | */ | ||
| 3817 | if (batch->memcg != memcg) | ||
| 3818 | goto direct_uncharge; | ||
| 3819 | /* remember freed charge and uncharge it later */ | ||
| 3820 | batch->nr_pages++; | ||
| 3821 | if (uncharge_memsw) | ||
| 3822 | batch->memsw_nr_pages++; | ||
| 3823 | return; | ||
| 3824 | direct_uncharge: | ||
| 3825 | res_counter_uncharge(&memcg->res, nr_pages * PAGE_SIZE); | ||
| 3826 | if (uncharge_memsw) | ||
| 3827 | res_counter_uncharge(&memcg->memsw, nr_pages * PAGE_SIZE); | ||
| 3828 | if (unlikely(batch->memcg != memcg)) | ||
| 3829 | memcg_oom_recover(memcg); | ||
| 3830 | } | ||
| 3831 | |||
| 3832 | /* | ||
| 3833 | * uncharge if !page_mapped(page) | ||
| 3834 | */ | ||
| 3835 | static struct mem_cgroup * | ||
| 3836 | __mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype, | ||
| 3837 | bool end_migration) | ||
| 3838 | { | ||
| 3839 | struct mem_cgroup *memcg = NULL; | ||
| 3840 | unsigned int nr_pages = 1; | ||
| 3841 | struct page_cgroup *pc; | ||
| 3842 | bool anon; | ||
| 3843 | |||
| 3844 | if (mem_cgroup_disabled()) | ||
| 3845 | return NULL; | ||
| 3846 | |||
| 3847 | if (PageTransHuge(page)) { | ||
| 3848 | nr_pages <<= compound_order(page); | ||
| 3849 | VM_BUG_ON_PAGE(!PageTransHuge(page), page); | ||
| 3850 | } | ||
| 3851 | /* | ||
| 3852 | * Check if our page_cgroup is valid | ||
| 3853 | */ | ||
| 3854 | pc = lookup_page_cgroup(page); | ||
| 3855 | if (unlikely(!PageCgroupUsed(pc))) | ||
| 3856 | return NULL; | ||
| 3857 | |||
| 3858 | lock_page_cgroup(pc); | ||
| 3859 | |||
| 3860 | memcg = pc->mem_cgroup; | ||
| 3861 | |||
| 3862 | if (!PageCgroupUsed(pc)) | ||
| 3863 | goto unlock_out; | ||
| 3864 | |||
| 3865 | anon = PageAnon(page); | ||
| 3866 | |||
| 3867 | switch (ctype) { | ||
| 3868 | case MEM_CGROUP_CHARGE_TYPE_ANON: | ||
| 3869 | /* | ||
| 3870 | * Generally PageAnon tells if it's the anon statistics to be | ||
| 3871 | * updated; but sometimes e.g. mem_cgroup_uncharge_page() is | ||
| 3872 | * used before page reached the stage of being marked PageAnon. | ||
| 3873 | */ | ||
| 3874 | anon = true; | ||
| 3875 | /* fallthrough */ | ||
| 3876 | case MEM_CGROUP_CHARGE_TYPE_DROP: | ||
| 3877 | /* See mem_cgroup_prepare_migration() */ | ||
| 3878 | if (page_mapped(page)) | ||
| 3879 | goto unlock_out; | ||
| 3880 | /* | ||
| 3881 | * Pages under migration may not be uncharged. But | ||
| 3882 | * end_migration() /must/ be the one uncharging the | ||
| 3883 | * unused post-migration page and so it has to call | ||
| 3884 | * here with the migration bit still set. See the | ||
| 3885 | * res_counter handling below. | ||
| 3886 | */ | ||
| 3887 | if (!end_migration && PageCgroupMigration(pc)) | ||
| 3888 | goto unlock_out; | ||
| 3889 | break; | ||
| 3890 | case MEM_CGROUP_CHARGE_TYPE_SWAPOUT: | ||
| 3891 | if (!PageAnon(page)) { /* Shared memory */ | ||
| 3892 | if (page->mapping && !page_is_file_cache(page)) | ||
| 3893 | goto unlock_out; | ||
| 3894 | } else if (page_mapped(page)) /* Anon */ | ||
| 3895 | goto unlock_out; | ||
| 3896 | break; | ||
| 3897 | default: | ||
| 3898 | break; | ||
| 3899 | } | ||
| 3900 | |||
| 3901 | mem_cgroup_charge_statistics(memcg, page, anon, -nr_pages); | ||
| 3902 | |||
| 3903 | ClearPageCgroupUsed(pc); | ||
| 3904 | /* | ||
| 3905 | * pc->mem_cgroup is not cleared here. It will be accessed when it's | ||
| 3906 | * freed from LRU. This is safe because uncharged page is expected not | ||
| 3907 | * to be reused (freed soon). Exception is SwapCache, it's handled by | ||
| 3908 | * special functions. | ||
| 3909 | */ | ||
| 3910 | |||
| 3911 | unlock_page_cgroup(pc); | ||
| 3912 | /* | ||
| 3913 | * even after unlock, we have memcg->res.usage here and this memcg | ||
| 3914 | * will never be freed, so it's safe to call css_get(). | ||
| 3915 | */ | ||
| 3916 | memcg_check_events(memcg, page); | ||
| 3917 | if (do_swap_account && ctype == MEM_CGROUP_CHARGE_TYPE_SWAPOUT) { | ||
| 3918 | mem_cgroup_swap_statistics(memcg, true); | ||
| 3919 | css_get(&memcg->css); | ||
| 3920 | } | ||
| 3921 | /* | ||
| 3922 | * Migration does not charge the res_counter for the | ||
| 3923 | * replacement page, so leave it alone when phasing out the | ||
| 3924 | * page that is unused after the migration. | ||
| 3925 | */ | ||
| 3926 | if (!end_migration) | ||
| 3927 | mem_cgroup_do_uncharge(memcg, nr_pages, ctype); | ||
| 3928 | |||
| 3929 | return memcg; | ||
| 3930 | |||
| 3931 | unlock_out: | ||
| 3932 | unlock_page_cgroup(pc); | ||
| 3933 | return NULL; | ||
| 3934 | } | ||
| 3935 | |||
| 3936 | void mem_cgroup_uncharge_page(struct page *page) | ||
| 3937 | { | ||
| 3938 | /* early check. */ | ||
| 3939 | if (page_mapped(page)) | ||
| 3940 | return; | ||
| 3941 | VM_BUG_ON_PAGE(page->mapping && !PageAnon(page), page); | ||
| 3942 | /* | ||
| 3943 | * If the page is in swap cache, uncharge should be deferred | ||
| 3944 | * to the swap path, which also properly accounts swap usage | ||
| 3945 | * and handles memcg lifetime. | ||
| 3946 | * | ||
| 3947 | * Note that this check is not stable and reclaim may add the | ||
| 3948 | * page to swap cache at any time after this. However, if the | ||
| 3949 | * page is not in swap cache by the time page->mapcount hits | ||
| 3950 | * 0, there won't be any page table references to the swap | ||
| 3951 | * slot, and reclaim will free it and not actually write the | ||
| 3952 | * page to disk. | ||
| 3953 | */ | ||
| 3954 | if (PageSwapCache(page)) | ||
| 3955 | return; | ||
| 3956 | __mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_ANON, false); | ||
| 3957 | } | ||
| 3958 | |||
| 3959 | void mem_cgroup_uncharge_cache_page(struct page *page) | ||
| 3960 | { | ||
| 3961 | VM_BUG_ON_PAGE(page_mapped(page), page); | ||
| 3962 | VM_BUG_ON_PAGE(page->mapping, page); | ||
| 3963 | __mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_CACHE, false); | ||
| 3964 | } | ||
| 3965 | |||
| 3966 | /* | ||
| 3967 | * Batch_start/batch_end is called in unmap_page_range/invlidate/trucate. | ||
| 3968 | * In that cases, pages are freed continuously and we can expect pages | ||
| 3969 | * are in the same memcg. All these calls itself limits the number of | ||
| 3970 | * pages freed at once, then uncharge_start/end() is called properly. | ||
| 3971 | * This may be called prural(2) times in a context, | ||
| 3972 | */ | ||
| 3973 | |||
| 3974 | void mem_cgroup_uncharge_start(void) | ||
| 3975 | { | ||
| 3976 | current->memcg_batch.do_batch++; | ||
| 3977 | /* We can do nest. */ | ||
| 3978 | if (current->memcg_batch.do_batch == 1) { | ||
| 3979 | current->memcg_batch.memcg = NULL; | ||
| 3980 | current->memcg_batch.nr_pages = 0; | ||
| 3981 | current->memcg_batch.memsw_nr_pages = 0; | ||
| 3982 | } | ||
| 3983 | } | ||
| 3984 | |||
| 3985 | void mem_cgroup_uncharge_end(void) | ||
| 3986 | { | ||
| 3987 | struct memcg_batch_info *batch = ¤t->memcg_batch; | ||
| 3988 | |||
| 3989 | if (!batch->do_batch) | ||
| 3990 | return; | ||
| 3991 | |||
| 3992 | batch->do_batch--; | ||
| 3993 | if (batch->do_batch) /* If stacked, do nothing. */ | ||
| 3994 | return; | ||
| 3995 | |||
| 3996 | if (!batch->memcg) | ||
| 3997 | return; | ||
| 3998 | /* | ||
| 3999 | * This "batch->memcg" is valid without any css_get/put etc... | ||
| 4000 | * bacause we hide charges behind us. | ||
| 4001 | */ | ||
| 4002 | if (batch->nr_pages) | ||
| 4003 | res_counter_uncharge(&batch->memcg->res, | ||
| 4004 | batch->nr_pages * PAGE_SIZE); | ||
| 4005 | if (batch->memsw_nr_pages) | ||
| 4006 | res_counter_uncharge(&batch->memcg->memsw, | ||
| 4007 | batch->memsw_nr_pages * PAGE_SIZE); | ||
| 4008 | memcg_oom_recover(batch->memcg); | ||
| 4009 | /* forget this pointer (for sanity check) */ | ||
| 4010 | batch->memcg = NULL; | ||
| 4011 | } | ||
| 4012 | |||
| 4013 | #ifdef CONFIG_SWAP | ||
| 4014 | /* | ||
| 4015 | * called after __delete_from_swap_cache() and drop "page" account. | ||
| 4016 | * memcg information is recorded to swap_cgroup of "ent" | ||
| 4017 | */ | ||
| 4018 | void | ||
| 4019 | mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout) | ||
| 4020 | { | ||
| 4021 | struct mem_cgroup *memcg; | ||
| 4022 | int ctype = MEM_CGROUP_CHARGE_TYPE_SWAPOUT; | ||
| 4023 | |||
| 4024 | if (!swapout) /* this was a swap cache but the swap is unused ! */ | ||
| 4025 | ctype = MEM_CGROUP_CHARGE_TYPE_DROP; | ||
| 4026 | |||
| 4027 | memcg = __mem_cgroup_uncharge_common(page, ctype, false); | ||
| 4028 | |||
| 4029 | /* | ||
| 4030 | * record memcg information, if swapout && memcg != NULL, | ||
| 4031 | * css_get() was called in uncharge(). | ||
| 4032 | */ | ||
| 4033 | if (do_swap_account && swapout && memcg) | ||
| 4034 | swap_cgroup_record(ent, mem_cgroup_id(memcg)); | ||
| 4035 | } | ||
| 4036 | #endif | ||
| 4037 | |||
| 4038 | #ifdef CONFIG_MEMCG_SWAP | 3574 | #ifdef CONFIG_MEMCG_SWAP |
| 4039 | /* | 3575 | static void mem_cgroup_swap_statistics(struct mem_cgroup *memcg, |
| 4040 | * called from swap_entry_free(). remove record in swap_cgroup and | 3576 | bool charge) |
| 4041 | * uncharge "memsw" account. | ||
| 4042 | */ | ||
| 4043 | void mem_cgroup_uncharge_swap(swp_entry_t ent) | ||
| 4044 | { | 3577 | { |
| 4045 | struct mem_cgroup *memcg; | 3578 | int val = (charge) ? 1 : -1; |
| 4046 | unsigned short id; | 3579 | this_cpu_add(memcg->stat->count[MEM_CGROUP_STAT_SWAP], val); |
| 4047 | |||
| 4048 | if (!do_swap_account) | ||
| 4049 | return; | ||
| 4050 | |||
| 4051 | id = swap_cgroup_record(ent, 0); | ||
| 4052 | rcu_read_lock(); | ||
| 4053 | memcg = mem_cgroup_lookup(id); | ||
| 4054 | if (memcg) { | ||
| 4055 | /* | ||
| 4056 | * We uncharge this because swap is freed. This memcg can | ||
| 4057 | * be obsolete one. We avoid calling css_tryget_online(). | ||
| 4058 | */ | ||
| 4059 | res_counter_uncharge(&memcg->memsw, PAGE_SIZE); | ||
| 4060 | mem_cgroup_swap_statistics(memcg, false); | ||
| 4061 | css_put(&memcg->css); | ||
| 4062 | } | ||
| 4063 | rcu_read_unlock(); | ||
| 4064 | } | 3580 | } |
| 4065 | 3581 | ||
| 4066 | /** | 3582 | /** |
| @@ -4112,175 +3628,6 @@ static inline int mem_cgroup_move_swap_account(swp_entry_t entry, | |||
| 4112 | } | 3628 | } |
| 4113 | #endif | 3629 | #endif |
| 4114 | 3630 | ||
| 4115 | /* | ||
| 4116 | * Before starting migration, account PAGE_SIZE to mem_cgroup that the old | ||
| 4117 | * page belongs to. | ||
| 4118 | */ | ||
| 4119 | void mem_cgroup_prepare_migration(struct page *page, struct page *newpage, | ||
| 4120 | struct mem_cgroup **memcgp) | ||
| 4121 | { | ||
| 4122 | struct mem_cgroup *memcg = NULL; | ||
| 4123 | unsigned int nr_pages = 1; | ||
| 4124 | struct page_cgroup *pc; | ||
| 4125 | enum charge_type ctype; | ||
| 4126 | |||
| 4127 | *memcgp = NULL; | ||
| 4128 | |||
| 4129 | if (mem_cgroup_disabled()) | ||
| 4130 | return; | ||
| 4131 | |||
| 4132 | if (PageTransHuge(page)) | ||
| 4133 | nr_pages <<= compound_order(page); | ||
| 4134 | |||
| 4135 | pc = lookup_page_cgroup(page); | ||
| 4136 | lock_page_cgroup(pc); | ||
| 4137 | if (PageCgroupUsed(pc)) { | ||
| 4138 | memcg = pc->mem_cgroup; | ||
| 4139 | css_get(&memcg->css); | ||
| 4140 | /* | ||
| 4141 | * At migrating an anonymous page, its mapcount goes down | ||
| 4142 | * to 0 and uncharge() will be called. But, even if it's fully | ||
| 4143 | * unmapped, migration may fail and this page has to be | ||
| 4144 | * charged again. We set MIGRATION flag here and delay uncharge | ||
| 4145 | * until end_migration() is called | ||
| 4146 | * | ||
| 4147 | * Corner Case Thinking | ||
| 4148 | * A) | ||
| 4149 | * When the old page was mapped as Anon and it's unmap-and-freed | ||
| 4150 | * while migration was ongoing. | ||
| 4151 | * If unmap finds the old page, uncharge() of it will be delayed | ||
| 4152 | * until end_migration(). If unmap finds a new page, it's | ||
| 4153 | * uncharged when it make mapcount to be 1->0. If unmap code | ||
| 4154 | * finds swap_migration_entry, the new page will not be mapped | ||
| 4155 | * and end_migration() will find it(mapcount==0). | ||
| 4156 | * | ||
| 4157 | * B) | ||
| 4158 | * When the old page was mapped but migraion fails, the kernel | ||
| 4159 | * remaps it. A charge for it is kept by MIGRATION flag even | ||
| 4160 | * if mapcount goes down to 0. We can do remap successfully | ||
| 4161 | * without charging it again. | ||
| 4162 | * | ||
| 4163 | * C) | ||
| 4164 | * The "old" page is under lock_page() until the end of | ||
| 4165 | * migration, so, the old page itself will not be swapped-out. | ||
| 4166 | * If the new page is swapped out before end_migraton, our | ||
| 4167 | * hook to usual swap-out path will catch the event. | ||
| 4168 | */ | ||
| 4169 | if (PageAnon(page)) | ||
| 4170 | SetPageCgroupMigration(pc); | ||
| 4171 | } | ||
| 4172 | unlock_page_cgroup(pc); | ||
| 4173 | /* | ||
| 4174 | * If the page is not charged at this point, | ||
| 4175 | * we return here. | ||
| 4176 | */ | ||
| 4177 | if (!memcg) | ||
| 4178 | return; | ||
| 4179 | |||
| 4180 | *memcgp = memcg; | ||
| 4181 | /* | ||
| 4182 | * We charge new page before it's used/mapped. So, even if unlock_page() | ||
| 4183 | * is called before end_migration, we can catch all events on this new | ||
| 4184 | * page. In the case new page is migrated but not remapped, new page's | ||
| 4185 | * mapcount will be finally 0 and we call uncharge in end_migration(). | ||
| 4186 | */ | ||
| 4187 | if (PageAnon(page)) | ||
| 4188 | ctype = MEM_CGROUP_CHARGE_TYPE_ANON; | ||
| 4189 | else | ||
| 4190 | ctype = MEM_CGROUP_CHARGE_TYPE_CACHE; | ||
| 4191 | /* | ||
| 4192 | * The page is committed to the memcg, but it's not actually | ||
| 4193 | * charged to the res_counter since we plan on replacing the | ||
| 4194 | * old one and only one page is going to be left afterwards. | ||
| 4195 | */ | ||
| 4196 | __mem_cgroup_commit_charge(memcg, newpage, nr_pages, ctype, false); | ||
| 4197 | } | ||
| 4198 | |||
| 4199 | /* remove redundant charge if migration failed*/ | ||
| 4200 | void mem_cgroup_end_migration(struct mem_cgroup *memcg, | ||
| 4201 | struct page *oldpage, struct page *newpage, bool migration_ok) | ||
| 4202 | { | ||
| 4203 | struct page *used, *unused; | ||
| 4204 | struct page_cgroup *pc; | ||
| 4205 | bool anon; | ||
| 4206 | |||
| 4207 | if (!memcg) | ||
| 4208 | return; | ||
| 4209 | |||
| 4210 | if (!migration_ok) { | ||
| 4211 | used = oldpage; | ||
| 4212 | unused = newpage; | ||
| 4213 | } else { | ||
| 4214 | used = newpage; | ||
| 4215 | unused = oldpage; | ||
| 4216 | } | ||
| 4217 | anon = PageAnon(used); | ||
| 4218 | __mem_cgroup_uncharge_common(unused, | ||
| 4219 | anon ? MEM_CGROUP_CHARGE_TYPE_ANON | ||
| 4220 | : MEM_CGROUP_CHARGE_TYPE_CACHE, | ||
| 4221 | true); | ||
| 4222 | css_put(&memcg->css); | ||
| 4223 | /* | ||
| 4224 | * We disallowed uncharge of pages under migration because mapcount | ||
| 4225 | * of the page goes down to zero, temporarly. | ||
| 4226 | * Clear the flag and check the page should be charged. | ||
| 4227 | */ | ||
| 4228 | pc = lookup_page_cgroup(oldpage); | ||
| 4229 | lock_page_cgroup(pc); | ||
| 4230 | ClearPageCgroupMigration(pc); | ||
| 4231 | unlock_page_cgroup(pc); | ||
| 4232 | |||
| 4233 | /* | ||
| 4234 | * If a page is a file cache, radix-tree replacement is very atomic | ||
| 4235 | * and we can skip this check. When it was an Anon page, its mapcount | ||
| 4236 | * goes down to 0. But because we added MIGRATION flage, it's not | ||
| 4237 | * uncharged yet. There are several case but page->mapcount check | ||
| 4238 | * and USED bit check in mem_cgroup_uncharge_page() will do enough | ||
| 4239 | * check. (see prepare_charge() also) | ||
| 4240 | */ | ||
| 4241 | if (anon) | ||
| 4242 | mem_cgroup_uncharge_page(used); | ||
| 4243 | } | ||
| 4244 | |||
| 4245 | /* | ||
| 4246 | * At replace page cache, newpage is not under any memcg but it's on | ||
| 4247 | * LRU. So, this function doesn't touch res_counter but handles LRU | ||
| 4248 | * in correct way. Both pages are locked so we cannot race with uncharge. | ||
| 4249 | */ | ||
| 4250 | void mem_cgroup_replace_page_cache(struct page *oldpage, | ||
| 4251 | struct page *newpage) | ||
| 4252 | { | ||
| 4253 | struct mem_cgroup *memcg = NULL; | ||
| 4254 | struct page_cgroup *pc; | ||
| 4255 | enum charge_type type = MEM_CGROUP_CHARGE_TYPE_CACHE; | ||
| 4256 | |||
| 4257 | if (mem_cgroup_disabled()) | ||
| 4258 | return; | ||
| 4259 | |||
| 4260 | pc = lookup_page_cgroup(oldpage); | ||
| 4261 | /* fix accounting on old pages */ | ||
| 4262 | lock_page_cgroup(pc); | ||
| 4263 | if (PageCgroupUsed(pc)) { | ||
| 4264 | memcg = pc->mem_cgroup; | ||
| 4265 | mem_cgroup_charge_statistics(memcg, oldpage, false, -1); | ||
| 4266 | ClearPageCgroupUsed(pc); | ||
| 4267 | } | ||
| 4268 | unlock_page_cgroup(pc); | ||
| 4269 | |||
| 4270 | /* | ||
| 4271 | * When called from shmem_replace_page(), in some cases the | ||
| 4272 | * oldpage has already been charged, and in some cases not. | ||
| 4273 | */ | ||
| 4274 | if (!memcg) | ||
| 4275 | return; | ||
| 4276 | /* | ||
| 4277 | * Even if newpage->mapping was NULL before starting replacement, | ||
| 4278 | * the newpage may be on LRU(or pagevec for LRU) already. We lock | ||
| 4279 | * LRU while we overwrite pc->mem_cgroup. | ||
| 4280 | */ | ||
| 4281 | __mem_cgroup_commit_charge(memcg, newpage, 1, type, true); | ||
| 4282 | } | ||
| 4283 | |||
| 4284 | #ifdef CONFIG_DEBUG_VM | 3631 | #ifdef CONFIG_DEBUG_VM |
| 4285 | static struct page_cgroup *lookup_page_cgroup_used(struct page *page) | 3632 | static struct page_cgroup *lookup_page_cgroup_used(struct page *page) |
| 4286 | { | 3633 | { |
| @@ -4479,7 +3826,7 @@ unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order, | |||
| 4479 | gfp_mask, &nr_scanned); | 3826 | gfp_mask, &nr_scanned); |
| 4480 | nr_reclaimed += reclaimed; | 3827 | nr_reclaimed += reclaimed; |
| 4481 | *total_scanned += nr_scanned; | 3828 | *total_scanned += nr_scanned; |
| 4482 | spin_lock(&mctz->lock); | 3829 | spin_lock_irq(&mctz->lock); |
| 4483 | 3830 | ||
| 4484 | /* | 3831 | /* |
| 4485 | * If we failed to reclaim anything from this memory cgroup | 3832 | * If we failed to reclaim anything from this memory cgroup |
| @@ -4519,7 +3866,7 @@ unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order, | |||
| 4519 | */ | 3866 | */ |
| 4520 | /* If excess == 0, no tree ops */ | 3867 | /* If excess == 0, no tree ops */ |
| 4521 | __mem_cgroup_insert_exceeded(mz, mctz, excess); | 3868 | __mem_cgroup_insert_exceeded(mz, mctz, excess); |
| 4522 | spin_unlock(&mctz->lock); | 3869 | spin_unlock_irq(&mctz->lock); |
| 4523 | css_put(&mz->memcg->css); | 3870 | css_put(&mz->memcg->css); |
| 4524 | loop++; | 3871 | loop++; |
| 4525 | /* | 3872 | /* |
| @@ -6319,20 +5666,19 @@ static int mem_cgroup_do_precharge(unsigned long count) | |||
| 6319 | int ret; | 5666 | int ret; |
| 6320 | 5667 | ||
| 6321 | /* Try a single bulk charge without reclaim first */ | 5668 | /* Try a single bulk charge without reclaim first */ |
| 6322 | ret = mem_cgroup_try_charge(mc.to, GFP_KERNEL & ~__GFP_WAIT, count); | 5669 | ret = try_charge(mc.to, GFP_KERNEL & ~__GFP_WAIT, count); |
| 6323 | if (!ret) { | 5670 | if (!ret) { |
| 6324 | mc.precharge += count; | 5671 | mc.precharge += count; |
| 6325 | return ret; | 5672 | return ret; |
| 6326 | } | 5673 | } |
| 6327 | if (ret == -EINTR) { | 5674 | if (ret == -EINTR) { |
| 6328 | __mem_cgroup_cancel_charge(root_mem_cgroup, count); | 5675 | cancel_charge(root_mem_cgroup, count); |
| 6329 | return ret; | 5676 | return ret; |
| 6330 | } | 5677 | } |
| 6331 | 5678 | ||
| 6332 | /* Try charges one by one with reclaim */ | 5679 | /* Try charges one by one with reclaim */ |
| 6333 | while (count--) { | 5680 | while (count--) { |
| 6334 | ret = mem_cgroup_try_charge(mc.to, | 5681 | ret = try_charge(mc.to, GFP_KERNEL & ~__GFP_NORETRY, 1); |
| 6335 | GFP_KERNEL & ~__GFP_NORETRY, 1); | ||
| 6336 | /* | 5682 | /* |
| 6337 | * In case of failure, any residual charges against | 5683 | * In case of failure, any residual charges against |
| 6338 | * mc.to will be dropped by mem_cgroup_clear_mc() | 5684 | * mc.to will be dropped by mem_cgroup_clear_mc() |
| @@ -6340,7 +5686,7 @@ static int mem_cgroup_do_precharge(unsigned long count) | |||
| 6340 | * bypassed to root right away or they'll be lost. | 5686 | * bypassed to root right away or they'll be lost. |
| 6341 | */ | 5687 | */ |
| 6342 | if (ret == -EINTR) | 5688 | if (ret == -EINTR) |
| 6343 | __mem_cgroup_cancel_charge(root_mem_cgroup, 1); | 5689 | cancel_charge(root_mem_cgroup, 1); |
| 6344 | if (ret) | 5690 | if (ret) |
| 6345 | return ret; | 5691 | return ret; |
| 6346 | mc.precharge++; | 5692 | mc.precharge++; |
| @@ -6482,9 +5828,9 @@ static enum mc_target_type get_mctgt_type(struct vm_area_struct *vma, | |||
| 6482 | if (page) { | 5828 | if (page) { |
| 6483 | pc = lookup_page_cgroup(page); | 5829 | pc = lookup_page_cgroup(page); |
| 6484 | /* | 5830 | /* |
| 6485 | * Do only loose check w/o page_cgroup lock. | 5831 | * Do only loose check w/o serialization. |
| 6486 | * mem_cgroup_move_account() checks the pc is valid or not under | 5832 | * mem_cgroup_move_account() checks the pc is valid or |
| 6487 | * the lock. | 5833 | * not under LRU exclusion. |
| 6488 | */ | 5834 | */ |
| 6489 | if (PageCgroupUsed(pc) && pc->mem_cgroup == mc.from) { | 5835 | if (PageCgroupUsed(pc) && pc->mem_cgroup == mc.from) { |
| 6490 | ret = MC_TARGET_PAGE; | 5836 | ret = MC_TARGET_PAGE; |
| @@ -6609,7 +5955,7 @@ static void __mem_cgroup_clear_mc(void) | |||
| 6609 | 5955 | ||
| 6610 | /* we must uncharge all the leftover precharges from mc.to */ | 5956 | /* we must uncharge all the leftover precharges from mc.to */ |
| 6611 | if (mc.precharge) { | 5957 | if (mc.precharge) { |
| 6612 | __mem_cgroup_cancel_charge(mc.to, mc.precharge); | 5958 | cancel_charge(mc.to, mc.precharge); |
| 6613 | mc.precharge = 0; | 5959 | mc.precharge = 0; |
| 6614 | } | 5960 | } |
| 6615 | /* | 5961 | /* |
| @@ -6617,7 +5963,7 @@ static void __mem_cgroup_clear_mc(void) | |||
| 6617 | * we must uncharge here. | 5963 | * we must uncharge here. |
| 6618 | */ | 5964 | */ |
| 6619 | if (mc.moved_charge) { | 5965 | if (mc.moved_charge) { |
| 6620 | __mem_cgroup_cancel_charge(mc.from, mc.moved_charge); | 5966 | cancel_charge(mc.from, mc.moved_charge); |
| 6621 | mc.moved_charge = 0; | 5967 | mc.moved_charge = 0; |
| 6622 | } | 5968 | } |
| 6623 | /* we must fixup refcnts and charges */ | 5969 | /* we must fixup refcnts and charges */ |
| @@ -6946,6 +6292,398 @@ static void __init enable_swap_cgroup(void) | |||
| 6946 | } | 6292 | } |
| 6947 | #endif | 6293 | #endif |
| 6948 | 6294 | ||
| 6295 | #ifdef CONFIG_MEMCG_SWAP | ||
| 6296 | /** | ||
| 6297 | * mem_cgroup_swapout - transfer a memsw charge to swap | ||
| 6298 | * @page: page whose memsw charge to transfer | ||
| 6299 | * @entry: swap entry to move the charge to | ||
| 6300 | * | ||
| 6301 | * Transfer the memsw charge of @page to @entry. | ||
| 6302 | */ | ||
| 6303 | void mem_cgroup_swapout(struct page *page, swp_entry_t entry) | ||
| 6304 | { | ||
| 6305 | struct page_cgroup *pc; | ||
| 6306 | unsigned short oldid; | ||
| 6307 | |||
| 6308 | VM_BUG_ON_PAGE(PageLRU(page), page); | ||
| 6309 | VM_BUG_ON_PAGE(page_count(page), page); | ||
| 6310 | |||
| 6311 | if (!do_swap_account) | ||
| 6312 | return; | ||
| 6313 | |||
| 6314 | pc = lookup_page_cgroup(page); | ||
| 6315 | |||
| 6316 | /* Readahead page, never charged */ | ||
| 6317 | if (!PageCgroupUsed(pc)) | ||
| 6318 | return; | ||
| 6319 | |||
| 6320 | VM_BUG_ON_PAGE(!(pc->flags & PCG_MEMSW), page); | ||
| 6321 | |||
| 6322 | oldid = swap_cgroup_record(entry, mem_cgroup_id(pc->mem_cgroup)); | ||
| 6323 | VM_BUG_ON_PAGE(oldid, page); | ||
| 6324 | |||
| 6325 | pc->flags &= ~PCG_MEMSW; | ||
| 6326 | css_get(&pc->mem_cgroup->css); | ||
| 6327 | mem_cgroup_swap_statistics(pc->mem_cgroup, true); | ||
| 6328 | } | ||
| 6329 | |||
| 6330 | /** | ||
| 6331 | * mem_cgroup_uncharge_swap - uncharge a swap entry | ||
| 6332 | * @entry: swap entry to uncharge | ||
| 6333 | * | ||
| 6334 | * Drop the memsw charge associated with @entry. | ||
| 6335 | */ | ||
| 6336 | void mem_cgroup_uncharge_swap(swp_entry_t entry) | ||
| 6337 | { | ||
| 6338 | struct mem_cgroup *memcg; | ||
| 6339 | unsigned short id; | ||
| 6340 | |||
| 6341 | if (!do_swap_account) | ||
| 6342 | return; | ||
| 6343 | |||
| 6344 | id = swap_cgroup_record(entry, 0); | ||
| 6345 | rcu_read_lock(); | ||
| 6346 | memcg = mem_cgroup_lookup(id); | ||
| 6347 | if (memcg) { | ||
| 6348 | res_counter_uncharge(&memcg->memsw, PAGE_SIZE); | ||
| 6349 | mem_cgroup_swap_statistics(memcg, false); | ||
| 6350 | css_put(&memcg->css); | ||
| 6351 | } | ||
| 6352 | rcu_read_unlock(); | ||
| 6353 | } | ||
| 6354 | #endif | ||
| 6355 | |||
| 6356 | /** | ||
| 6357 | * mem_cgroup_try_charge - try charging a page | ||
| 6358 | * @page: page to charge | ||
| 6359 | * @mm: mm context of the victim | ||
| 6360 | * @gfp_mask: reclaim mode | ||
| 6361 | * @memcgp: charged memcg return | ||
| 6362 | * | ||
| 6363 | * Try to charge @page to the memcg that @mm belongs to, reclaiming | ||
| 6364 | * pages according to @gfp_mask if necessary. | ||
| 6365 | * | ||
| 6366 | * Returns 0 on success, with *@memcgp pointing to the charged memcg. | ||
| 6367 | * Otherwise, an error code is returned. | ||
| 6368 | * | ||
| 6369 | * After page->mapping has been set up, the caller must finalize the | ||
| 6370 | * charge with mem_cgroup_commit_charge(). Or abort the transaction | ||
| 6371 | * with mem_cgroup_cancel_charge() in case page instantiation fails. | ||
| 6372 | */ | ||
| 6373 | int mem_cgroup_try_charge(struct page *page, struct mm_struct *mm, | ||
| 6374 | gfp_t gfp_mask, struct mem_cgroup **memcgp) | ||
| 6375 | { | ||
| 6376 | struct mem_cgroup *memcg = NULL; | ||
| 6377 | unsigned int nr_pages = 1; | ||
| 6378 | int ret = 0; | ||
| 6379 | |||
| 6380 | if (mem_cgroup_disabled()) | ||
| 6381 | goto out; | ||
| 6382 | |||
| 6383 | if (PageSwapCache(page)) { | ||
| 6384 | struct page_cgroup *pc = lookup_page_cgroup(page); | ||
| 6385 | /* | ||
| 6386 | * Every swap fault against a single page tries to charge the | ||
| 6387 | * page, bail as early as possible. shmem_unuse() encounters | ||
| 6388 | * already charged pages, too. The USED bit is protected by | ||
| 6389 | * the page lock, which serializes swap cache removal, which | ||
| 6390 | * in turn serializes uncharging. | ||
| 6391 | */ | ||
| 6392 | if (PageCgroupUsed(pc)) | ||
| 6393 | goto out; | ||
| 6394 | } | ||
| 6395 | |||
| 6396 | if (PageTransHuge(page)) { | ||
| 6397 | nr_pages <<= compound_order(page); | ||
| 6398 | VM_BUG_ON_PAGE(!PageTransHuge(page), page); | ||
| 6399 | } | ||
| 6400 | |||
| 6401 | if (do_swap_account && PageSwapCache(page)) | ||
| 6402 | memcg = try_get_mem_cgroup_from_page(page); | ||
| 6403 | if (!memcg) | ||
| 6404 | memcg = get_mem_cgroup_from_mm(mm); | ||
| 6405 | |||
| 6406 | ret = try_charge(memcg, gfp_mask, nr_pages); | ||
| 6407 | |||
| 6408 | css_put(&memcg->css); | ||
| 6409 | |||
| 6410 | if (ret == -EINTR) { | ||
| 6411 | memcg = root_mem_cgroup; | ||
| 6412 | ret = 0; | ||
| 6413 | } | ||
| 6414 | out: | ||
| 6415 | *memcgp = memcg; | ||
| 6416 | return ret; | ||
| 6417 | } | ||
| 6418 | |||
| 6419 | /** | ||
| 6420 | * mem_cgroup_commit_charge - commit a page charge | ||
| 6421 | * @page: page to charge | ||
| 6422 | * @memcg: memcg to charge the page to | ||
| 6423 | * @lrucare: page might be on LRU already | ||
| 6424 | * | ||
| 6425 | * Finalize a charge transaction started by mem_cgroup_try_charge(), | ||
| 6426 | * after page->mapping has been set up. This must happen atomically | ||
| 6427 | * as part of the page instantiation, i.e. under the page table lock | ||
| 6428 | * for anonymous pages, under the page lock for page and swap cache. | ||
| 6429 | * | ||
| 6430 | * In addition, the page must not be on the LRU during the commit, to | ||
| 6431 | * prevent racing with task migration. If it might be, use @lrucare. | ||
| 6432 | * | ||
| 6433 | * Use mem_cgroup_cancel_charge() to cancel the transaction instead. | ||
| 6434 | */ | ||
| 6435 | void mem_cgroup_commit_charge(struct page *page, struct mem_cgroup *memcg, | ||
| 6436 | bool lrucare) | ||
| 6437 | { | ||
| 6438 | unsigned int nr_pages = 1; | ||
| 6439 | |||
| 6440 | VM_BUG_ON_PAGE(!page->mapping, page); | ||
| 6441 | VM_BUG_ON_PAGE(PageLRU(page) && !lrucare, page); | ||
| 6442 | |||
| 6443 | if (mem_cgroup_disabled()) | ||
| 6444 | return; | ||
| 6445 | /* | ||
| 6446 | * Swap faults will attempt to charge the same page multiple | ||
| 6447 | * times. But reuse_swap_page() might have removed the page | ||
| 6448 | * from swapcache already, so we can't check PageSwapCache(). | ||
| 6449 | */ | ||
| 6450 | if (!memcg) | ||
| 6451 | return; | ||
| 6452 | |||
| 6453 | commit_charge(page, memcg, lrucare); | ||
| 6454 | |||
| 6455 | if (PageTransHuge(page)) { | ||
| 6456 | nr_pages <<= compound_order(page); | ||
| 6457 | VM_BUG_ON_PAGE(!PageTransHuge(page), page); | ||
| 6458 | } | ||
| 6459 | |||
| 6460 | local_irq_disable(); | ||
| 6461 | mem_cgroup_charge_statistics(memcg, page, nr_pages); | ||
| 6462 | memcg_check_events(memcg, page); | ||
| 6463 | local_irq_enable(); | ||
| 6464 | |||
| 6465 | if (do_swap_account && PageSwapCache(page)) { | ||
| 6466 | swp_entry_t entry = { .val = page_private(page) }; | ||
| 6467 | /* | ||
| 6468 | * The swap entry might not get freed for a long time, | ||
| 6469 | * let's not wait for it. The page already received a | ||
| 6470 | * memory+swap charge, drop the swap entry duplicate. | ||
| 6471 | */ | ||
| 6472 | mem_cgroup_uncharge_swap(entry); | ||
| 6473 | } | ||
| 6474 | } | ||
| 6475 | |||
| 6476 | /** | ||
| 6477 | * mem_cgroup_cancel_charge - cancel a page charge | ||
| 6478 | * @page: page to charge | ||
| 6479 | * @memcg: memcg to charge the page to | ||
| 6480 | * | ||
| 6481 | * Cancel a charge transaction started by mem_cgroup_try_charge(). | ||
| 6482 | */ | ||
| 6483 | void mem_cgroup_cancel_charge(struct page *page, struct mem_cgroup *memcg) | ||
| 6484 | { | ||
| 6485 | unsigned int nr_pages = 1; | ||
| 6486 | |||
| 6487 | if (mem_cgroup_disabled()) | ||
| 6488 | return; | ||
| 6489 | /* | ||
| 6490 | * Swap faults will attempt to charge the same page multiple | ||
| 6491 | * times. But reuse_swap_page() might have removed the page | ||
| 6492 | * from swapcache already, so we can't check PageSwapCache(). | ||
| 6493 | */ | ||
| 6494 | if (!memcg) | ||
| 6495 | return; | ||
| 6496 | |||
| 6497 | if (PageTransHuge(page)) { | ||
| 6498 | nr_pages <<= compound_order(page); | ||
| 6499 | VM_BUG_ON_PAGE(!PageTransHuge(page), page); | ||
| 6500 | } | ||
| 6501 | |||
| 6502 | cancel_charge(memcg, nr_pages); | ||
| 6503 | } | ||
| 6504 | |||
| 6505 | static void uncharge_batch(struct mem_cgroup *memcg, unsigned long pgpgout, | ||
| 6506 | unsigned long nr_mem, unsigned long nr_memsw, | ||
| 6507 | unsigned long nr_anon, unsigned long nr_file, | ||
| 6508 | unsigned long nr_huge, struct page *dummy_page) | ||
| 6509 | { | ||
| 6510 | unsigned long flags; | ||
| 6511 | |||
| 6512 | if (nr_mem) | ||
| 6513 | res_counter_uncharge(&memcg->res, nr_mem * PAGE_SIZE); | ||
| 6514 | if (nr_memsw) | ||
| 6515 | res_counter_uncharge(&memcg->memsw, nr_memsw * PAGE_SIZE); | ||
| 6516 | |||
| 6517 | memcg_oom_recover(memcg); | ||
| 6518 | |||
| 6519 | local_irq_save(flags); | ||
| 6520 | __this_cpu_sub(memcg->stat->count[MEM_CGROUP_STAT_RSS], nr_anon); | ||
| 6521 | __this_cpu_sub(memcg->stat->count[MEM_CGROUP_STAT_CACHE], nr_file); | ||
| 6522 | __this_cpu_sub(memcg->stat->count[MEM_CGROUP_STAT_RSS_HUGE], nr_huge); | ||
| 6523 | __this_cpu_add(memcg->stat->events[MEM_CGROUP_EVENTS_PGPGOUT], pgpgout); | ||
| 6524 | __this_cpu_add(memcg->stat->nr_page_events, nr_anon + nr_file); | ||
| 6525 | memcg_check_events(memcg, dummy_page); | ||
| 6526 | local_irq_restore(flags); | ||
| 6527 | } | ||
| 6528 | |||
| 6529 | static void uncharge_list(struct list_head *page_list) | ||
| 6530 | { | ||
| 6531 | struct mem_cgroup *memcg = NULL; | ||
| 6532 | unsigned long nr_memsw = 0; | ||
| 6533 | unsigned long nr_anon = 0; | ||
| 6534 | unsigned long nr_file = 0; | ||
| 6535 | unsigned long nr_huge = 0; | ||
| 6536 | unsigned long pgpgout = 0; | ||
| 6537 | unsigned long nr_mem = 0; | ||
| 6538 | struct list_head *next; | ||
| 6539 | struct page *page; | ||
| 6540 | |||
| 6541 | next = page_list->next; | ||
| 6542 | do { | ||
| 6543 | unsigned int nr_pages = 1; | ||
| 6544 | struct page_cgroup *pc; | ||
| 6545 | |||
| 6546 | page = list_entry(next, struct page, lru); | ||
| 6547 | next = page->lru.next; | ||
| 6548 | |||
| 6549 | VM_BUG_ON_PAGE(PageLRU(page), page); | ||
| 6550 | VM_BUG_ON_PAGE(page_count(page), page); | ||
| 6551 | |||
| 6552 | pc = lookup_page_cgroup(page); | ||
| 6553 | if (!PageCgroupUsed(pc)) | ||
| 6554 | continue; | ||
| 6555 | |||
| 6556 | /* | ||
| 6557 | * Nobody should be changing or seriously looking at | ||
| 6558 | * pc->mem_cgroup and pc->flags at this point, we have | ||
| 6559 | * fully exclusive access to the page. | ||
| 6560 | */ | ||
| 6561 | |||
| 6562 | if (memcg != pc->mem_cgroup) { | ||
| 6563 | if (memcg) { | ||
| 6564 | uncharge_batch(memcg, pgpgout, nr_mem, nr_memsw, | ||
| 6565 | nr_anon, nr_file, nr_huge, page); | ||
| 6566 | pgpgout = nr_mem = nr_memsw = 0; | ||
| 6567 | nr_anon = nr_file = nr_huge = 0; | ||
| 6568 | } | ||
| 6569 | memcg = pc->mem_cgroup; | ||
| 6570 | } | ||
| 6571 | |||
| 6572 | if (PageTransHuge(page)) { | ||
| 6573 | nr_pages <<= compound_order(page); | ||
| 6574 | VM_BUG_ON_PAGE(!PageTransHuge(page), page); | ||
| 6575 | nr_huge += nr_pages; | ||
| 6576 | } | ||
| 6577 | |||
| 6578 | if (PageAnon(page)) | ||
| 6579 | nr_anon += nr_pages; | ||
| 6580 | else | ||
| 6581 | nr_file += nr_pages; | ||
| 6582 | |||
| 6583 | if (pc->flags & PCG_MEM) | ||
| 6584 | nr_mem += nr_pages; | ||
| 6585 | if (pc->flags & PCG_MEMSW) | ||
| 6586 | nr_memsw += nr_pages; | ||
| 6587 | pc->flags = 0; | ||
| 6588 | |||
| 6589 | pgpgout++; | ||
| 6590 | } while (next != page_list); | ||
| 6591 | |||
| 6592 | if (memcg) | ||
| 6593 | uncharge_batch(memcg, pgpgout, nr_mem, nr_memsw, | ||
| 6594 | nr_anon, nr_file, nr_huge, page); | ||
| 6595 | } | ||
| 6596 | |||
| 6597 | /** | ||
| 6598 | * mem_cgroup_uncharge - uncharge a page | ||
| 6599 | * @page: page to uncharge | ||
| 6600 | * | ||
| 6601 | * Uncharge a page previously charged with mem_cgroup_try_charge() and | ||
| 6602 | * mem_cgroup_commit_charge(). | ||
| 6603 | */ | ||
| 6604 | void mem_cgroup_uncharge(struct page *page) | ||
| 6605 | { | ||
| 6606 | struct page_cgroup *pc; | ||
| 6607 | |||
| 6608 | if (mem_cgroup_disabled()) | ||
| 6609 | return; | ||
| 6610 | |||
| 6611 | /* Don't touch page->lru of any random page, pre-check: */ | ||
| 6612 | pc = lookup_page_cgroup(page); | ||
| 6613 | if (!PageCgroupUsed(pc)) | ||
| 6614 | return; | ||
| 6615 | |||
| 6616 | INIT_LIST_HEAD(&page->lru); | ||
| 6617 | uncharge_list(&page->lru); | ||
| 6618 | } | ||
| 6619 | |||
| 6620 | /** | ||
| 6621 | * mem_cgroup_uncharge_list - uncharge a list of page | ||
| 6622 | * @page_list: list of pages to uncharge | ||
| 6623 | * | ||
| 6624 | * Uncharge a list of pages previously charged with | ||
| 6625 | * mem_cgroup_try_charge() and mem_cgroup_commit_charge(). | ||
| 6626 | */ | ||
| 6627 | void mem_cgroup_uncharge_list(struct list_head *page_list) | ||
| 6628 | { | ||
| 6629 | if (mem_cgroup_disabled()) | ||
| 6630 | return; | ||
| 6631 | |||
| 6632 | if (!list_empty(page_list)) | ||
| 6633 | uncharge_list(page_list); | ||
| 6634 | } | ||
| 6635 | |||
| 6636 | /** | ||
| 6637 | * mem_cgroup_migrate - migrate a charge to another page | ||
| 6638 | * @oldpage: currently charged page | ||
| 6639 | * @newpage: page to transfer the charge to | ||
| 6640 | * @lrucare: both pages might be on the LRU already | ||
| 6641 | * | ||
| 6642 | * Migrate the charge from @oldpage to @newpage. | ||
| 6643 | * | ||
| 6644 | * Both pages must be locked, @newpage->mapping must be set up. | ||
| 6645 | */ | ||
| 6646 | void mem_cgroup_migrate(struct page *oldpage, struct page *newpage, | ||
| 6647 | bool lrucare) | ||
| 6648 | { | ||
| 6649 | struct page_cgroup *pc; | ||
| 6650 | int isolated; | ||
| 6651 | |||
| 6652 | VM_BUG_ON_PAGE(!PageLocked(oldpage), oldpage); | ||
| 6653 | VM_BUG_ON_PAGE(!PageLocked(newpage), newpage); | ||
| 6654 | VM_BUG_ON_PAGE(!lrucare && PageLRU(oldpage), oldpage); | ||
| 6655 | VM_BUG_ON_PAGE(!lrucare && PageLRU(newpage), newpage); | ||
| 6656 | VM_BUG_ON_PAGE(PageAnon(oldpage) != PageAnon(newpage), newpage); | ||
| 6657 | VM_BUG_ON_PAGE(PageTransHuge(oldpage) != PageTransHuge(newpage), | ||
| 6658 | newpage); | ||
| 6659 | |||
| 6660 | if (mem_cgroup_disabled()) | ||
| 6661 | return; | ||
| 6662 | |||
| 6663 | /* Page cache replacement: new page already charged? */ | ||
| 6664 | pc = lookup_page_cgroup(newpage); | ||
| 6665 | if (PageCgroupUsed(pc)) | ||
| 6666 | return; | ||
| 6667 | |||
| 6668 | /* Re-entrant migration: old page already uncharged? */ | ||
| 6669 | pc = lookup_page_cgroup(oldpage); | ||
| 6670 | if (!PageCgroupUsed(pc)) | ||
| 6671 | return; | ||
| 6672 | |||
| 6673 | VM_BUG_ON_PAGE(!(pc->flags & PCG_MEM), oldpage); | ||
| 6674 | VM_BUG_ON_PAGE(do_swap_account && !(pc->flags & PCG_MEMSW), oldpage); | ||
| 6675 | |||
| 6676 | if (lrucare) | ||
| 6677 | lock_page_lru(oldpage, &isolated); | ||
| 6678 | |||
| 6679 | pc->flags = 0; | ||
| 6680 | |||
| 6681 | if (lrucare) | ||
| 6682 | unlock_page_lru(oldpage, isolated); | ||
| 6683 | |||
| 6684 | commit_charge(newpage, pc->mem_cgroup, lrucare); | ||
| 6685 | } | ||
| 6686 | |||
| 6949 | /* | 6687 | /* |
| 6950 | * subsys_initcall() for memory controller. | 6688 | * subsys_initcall() for memory controller. |
| 6951 | * | 6689 | * |
diff --git a/mm/memory.c b/mm/memory.c index 5c55270729f7..ab3537bcfed2 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
| @@ -1292,7 +1292,6 @@ static void unmap_page_range(struct mmu_gather *tlb, | |||
| 1292 | details = NULL; | 1292 | details = NULL; |
| 1293 | 1293 | ||
| 1294 | BUG_ON(addr >= end); | 1294 | BUG_ON(addr >= end); |
| 1295 | mem_cgroup_uncharge_start(); | ||
| 1296 | tlb_start_vma(tlb, vma); | 1295 | tlb_start_vma(tlb, vma); |
| 1297 | pgd = pgd_offset(vma->vm_mm, addr); | 1296 | pgd = pgd_offset(vma->vm_mm, addr); |
| 1298 | do { | 1297 | do { |
| @@ -1302,7 +1301,6 @@ static void unmap_page_range(struct mmu_gather *tlb, | |||
| 1302 | next = zap_pud_range(tlb, vma, pgd, addr, next, details); | 1301 | next = zap_pud_range(tlb, vma, pgd, addr, next, details); |
| 1303 | } while (pgd++, addr = next, addr != end); | 1302 | } while (pgd++, addr = next, addr != end); |
| 1304 | tlb_end_vma(tlb, vma); | 1303 | tlb_end_vma(tlb, vma); |
| 1305 | mem_cgroup_uncharge_end(); | ||
| 1306 | } | 1304 | } |
| 1307 | 1305 | ||
| 1308 | 1306 | ||
| @@ -2049,6 +2047,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 2049 | struct page *dirty_page = NULL; | 2047 | struct page *dirty_page = NULL; |
| 2050 | unsigned long mmun_start = 0; /* For mmu_notifiers */ | 2048 | unsigned long mmun_start = 0; /* For mmu_notifiers */ |
| 2051 | unsigned long mmun_end = 0; /* For mmu_notifiers */ | 2049 | unsigned long mmun_end = 0; /* For mmu_notifiers */ |
| 2050 | struct mem_cgroup *memcg; | ||
| 2052 | 2051 | ||
| 2053 | old_page = vm_normal_page(vma, address, orig_pte); | 2052 | old_page = vm_normal_page(vma, address, orig_pte); |
| 2054 | if (!old_page) { | 2053 | if (!old_page) { |
| @@ -2204,7 +2203,7 @@ gotten: | |||
| 2204 | } | 2203 | } |
| 2205 | __SetPageUptodate(new_page); | 2204 | __SetPageUptodate(new_page); |
| 2206 | 2205 | ||
| 2207 | if (mem_cgroup_charge_anon(new_page, mm, GFP_KERNEL)) | 2206 | if (mem_cgroup_try_charge(new_page, mm, GFP_KERNEL, &memcg)) |
| 2208 | goto oom_free_new; | 2207 | goto oom_free_new; |
| 2209 | 2208 | ||
| 2210 | mmun_start = address & PAGE_MASK; | 2209 | mmun_start = address & PAGE_MASK; |
| @@ -2234,6 +2233,8 @@ gotten: | |||
| 2234 | */ | 2233 | */ |
| 2235 | ptep_clear_flush(vma, address, page_table); | 2234 | ptep_clear_flush(vma, address, page_table); |
| 2236 | page_add_new_anon_rmap(new_page, vma, address); | 2235 | page_add_new_anon_rmap(new_page, vma, address); |
| 2236 | mem_cgroup_commit_charge(new_page, memcg, false); | ||
| 2237 | lru_cache_add_active_or_unevictable(new_page, vma); | ||
| 2237 | /* | 2238 | /* |
| 2238 | * We call the notify macro here because, when using secondary | 2239 | * We call the notify macro here because, when using secondary |
| 2239 | * mmu page tables (such as kvm shadow page tables), we want the | 2240 | * mmu page tables (such as kvm shadow page tables), we want the |
| @@ -2271,7 +2272,7 @@ gotten: | |||
| 2271 | new_page = old_page; | 2272 | new_page = old_page; |
| 2272 | ret |= VM_FAULT_WRITE; | 2273 | ret |= VM_FAULT_WRITE; |
| 2273 | } else | 2274 | } else |
| 2274 | mem_cgroup_uncharge_page(new_page); | 2275 | mem_cgroup_cancel_charge(new_page, memcg); |
| 2275 | 2276 | ||
| 2276 | if (new_page) | 2277 | if (new_page) |
| 2277 | page_cache_release(new_page); | 2278 | page_cache_release(new_page); |
| @@ -2410,10 +2411,10 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 2410 | { | 2411 | { |
| 2411 | spinlock_t *ptl; | 2412 | spinlock_t *ptl; |
| 2412 | struct page *page, *swapcache; | 2413 | struct page *page, *swapcache; |
| 2414 | struct mem_cgroup *memcg; | ||
| 2413 | swp_entry_t entry; | 2415 | swp_entry_t entry; |
| 2414 | pte_t pte; | 2416 | pte_t pte; |
| 2415 | int locked; | 2417 | int locked; |
| 2416 | struct mem_cgroup *ptr; | ||
| 2417 | int exclusive = 0; | 2418 | int exclusive = 0; |
| 2418 | int ret = 0; | 2419 | int ret = 0; |
| 2419 | 2420 | ||
| @@ -2489,7 +2490,7 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 2489 | goto out_page; | 2490 | goto out_page; |
| 2490 | } | 2491 | } |
| 2491 | 2492 | ||
| 2492 | if (mem_cgroup_try_charge_swapin(mm, page, GFP_KERNEL, &ptr)) { | 2493 | if (mem_cgroup_try_charge(page, mm, GFP_KERNEL, &memcg)) { |
| 2493 | ret = VM_FAULT_OOM; | 2494 | ret = VM_FAULT_OOM; |
| 2494 | goto out_page; | 2495 | goto out_page; |
| 2495 | } | 2496 | } |
| @@ -2514,10 +2515,6 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 2514 | * while the page is counted on swap but not yet in mapcount i.e. | 2515 | * while the page is counted on swap but not yet in mapcount i.e. |
| 2515 | * before page_add_anon_rmap() and swap_free(); try_to_free_swap() | 2516 | * before page_add_anon_rmap() and swap_free(); try_to_free_swap() |
| 2516 | * must be called after the swap_free(), or it will never succeed. | 2517 | * must be called after the swap_free(), or it will never succeed. |
| 2517 | * Because delete_from_swap_page() may be called by reuse_swap_page(), | ||
| 2518 | * mem_cgroup_commit_charge_swapin() may not be able to find swp_entry | ||
| 2519 | * in page->private. In this case, a record in swap_cgroup is silently | ||
| 2520 | * discarded at swap_free(). | ||
| 2521 | */ | 2518 | */ |
| 2522 | 2519 | ||
| 2523 | inc_mm_counter_fast(mm, MM_ANONPAGES); | 2520 | inc_mm_counter_fast(mm, MM_ANONPAGES); |
| @@ -2533,12 +2530,14 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 2533 | if (pte_swp_soft_dirty(orig_pte)) | 2530 | if (pte_swp_soft_dirty(orig_pte)) |
| 2534 | pte = pte_mksoft_dirty(pte); | 2531 | pte = pte_mksoft_dirty(pte); |
| 2535 | set_pte_at(mm, address, page_table, pte); | 2532 | set_pte_at(mm, address, page_table, pte); |
| 2536 | if (page == swapcache) | 2533 | if (page == swapcache) { |
| 2537 | do_page_add_anon_rmap(page, vma, address, exclusive); | 2534 | do_page_add_anon_rmap(page, vma, address, exclusive); |
| 2538 | else /* ksm created a completely new copy */ | 2535 | mem_cgroup_commit_charge(page, memcg, true); |
| 2536 | } else { /* ksm created a completely new copy */ | ||
| 2539 | page_add_new_anon_rmap(page, vma, address); | 2537 | page_add_new_anon_rmap(page, vma, address); |
| 2540 | /* It's better to call commit-charge after rmap is established */ | 2538 | mem_cgroup_commit_charge(page, memcg, false); |
| 2541 | mem_cgroup_commit_charge_swapin(page, ptr); | 2539 | lru_cache_add_active_or_unevictable(page, vma); |
| 2540 | } | ||
| 2542 | 2541 | ||
| 2543 | swap_free(entry); | 2542 | swap_free(entry); |
| 2544 | if (vm_swap_full() || (vma->vm_flags & VM_LOCKED) || PageMlocked(page)) | 2543 | if (vm_swap_full() || (vma->vm_flags & VM_LOCKED) || PageMlocked(page)) |
| @@ -2571,7 +2570,7 @@ unlock: | |||
| 2571 | out: | 2570 | out: |
| 2572 | return ret; | 2571 | return ret; |
| 2573 | out_nomap: | 2572 | out_nomap: |
| 2574 | mem_cgroup_cancel_charge_swapin(ptr); | 2573 | mem_cgroup_cancel_charge(page, memcg); |
| 2575 | pte_unmap_unlock(page_table, ptl); | 2574 | pte_unmap_unlock(page_table, ptl); |
| 2576 | out_page: | 2575 | out_page: |
| 2577 | unlock_page(page); | 2576 | unlock_page(page); |
| @@ -2627,6 +2626,7 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 2627 | unsigned long address, pte_t *page_table, pmd_t *pmd, | 2626 | unsigned long address, pte_t *page_table, pmd_t *pmd, |
| 2628 | unsigned int flags) | 2627 | unsigned int flags) |
| 2629 | { | 2628 | { |
| 2629 | struct mem_cgroup *memcg; | ||
| 2630 | struct page *page; | 2630 | struct page *page; |
| 2631 | spinlock_t *ptl; | 2631 | spinlock_t *ptl; |
| 2632 | pte_t entry; | 2632 | pte_t entry; |
| @@ -2660,7 +2660,7 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 2660 | */ | 2660 | */ |
| 2661 | __SetPageUptodate(page); | 2661 | __SetPageUptodate(page); |
| 2662 | 2662 | ||
| 2663 | if (mem_cgroup_charge_anon(page, mm, GFP_KERNEL)) | 2663 | if (mem_cgroup_try_charge(page, mm, GFP_KERNEL, &memcg)) |
| 2664 | goto oom_free_page; | 2664 | goto oom_free_page; |
| 2665 | 2665 | ||
| 2666 | entry = mk_pte(page, vma->vm_page_prot); | 2666 | entry = mk_pte(page, vma->vm_page_prot); |
| @@ -2673,6 +2673,8 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 2673 | 2673 | ||
| 2674 | inc_mm_counter_fast(mm, MM_ANONPAGES); | 2674 | inc_mm_counter_fast(mm, MM_ANONPAGES); |
| 2675 | page_add_new_anon_rmap(page, vma, address); | 2675 | page_add_new_anon_rmap(page, vma, address); |
| 2676 | mem_cgroup_commit_charge(page, memcg, false); | ||
| 2677 | lru_cache_add_active_or_unevictable(page, vma); | ||
| 2676 | setpte: | 2678 | setpte: |
| 2677 | set_pte_at(mm, address, page_table, entry); | 2679 | set_pte_at(mm, address, page_table, entry); |
| 2678 | 2680 | ||
| @@ -2682,7 +2684,7 @@ unlock: | |||
| 2682 | pte_unmap_unlock(page_table, ptl); | 2684 | pte_unmap_unlock(page_table, ptl); |
| 2683 | return 0; | 2685 | return 0; |
| 2684 | release: | 2686 | release: |
| 2685 | mem_cgroup_uncharge_page(page); | 2687 | mem_cgroup_cancel_charge(page, memcg); |
| 2686 | page_cache_release(page); | 2688 | page_cache_release(page); |
| 2687 | goto unlock; | 2689 | goto unlock; |
| 2688 | oom_free_page: | 2690 | oom_free_page: |
| @@ -2919,6 +2921,7 @@ static int do_cow_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 2919 | pgoff_t pgoff, unsigned int flags, pte_t orig_pte) | 2921 | pgoff_t pgoff, unsigned int flags, pte_t orig_pte) |
| 2920 | { | 2922 | { |
| 2921 | struct page *fault_page, *new_page; | 2923 | struct page *fault_page, *new_page; |
| 2924 | struct mem_cgroup *memcg; | ||
| 2922 | spinlock_t *ptl; | 2925 | spinlock_t *ptl; |
| 2923 | pte_t *pte; | 2926 | pte_t *pte; |
| 2924 | int ret; | 2927 | int ret; |
| @@ -2930,7 +2933,7 @@ static int do_cow_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 2930 | if (!new_page) | 2933 | if (!new_page) |
| 2931 | return VM_FAULT_OOM; | 2934 | return VM_FAULT_OOM; |
| 2932 | 2935 | ||
| 2933 | if (mem_cgroup_charge_anon(new_page, mm, GFP_KERNEL)) { | 2936 | if (mem_cgroup_try_charge(new_page, mm, GFP_KERNEL, &memcg)) { |
| 2934 | page_cache_release(new_page); | 2937 | page_cache_release(new_page); |
| 2935 | return VM_FAULT_OOM; | 2938 | return VM_FAULT_OOM; |
| 2936 | } | 2939 | } |
| @@ -2950,12 +2953,14 @@ static int do_cow_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 2950 | goto uncharge_out; | 2953 | goto uncharge_out; |
| 2951 | } | 2954 | } |
| 2952 | do_set_pte(vma, address, new_page, pte, true, true); | 2955 | do_set_pte(vma, address, new_page, pte, true, true); |
| 2956 | mem_cgroup_commit_charge(new_page, memcg, false); | ||
| 2957 | lru_cache_add_active_or_unevictable(new_page, vma); | ||
| 2953 | pte_unmap_unlock(pte, ptl); | 2958 | pte_unmap_unlock(pte, ptl); |
| 2954 | unlock_page(fault_page); | 2959 | unlock_page(fault_page); |
| 2955 | page_cache_release(fault_page); | 2960 | page_cache_release(fault_page); |
| 2956 | return ret; | 2961 | return ret; |
| 2957 | uncharge_out: | 2962 | uncharge_out: |
| 2958 | mem_cgroup_uncharge_page(new_page); | 2963 | mem_cgroup_cancel_charge(new_page, memcg); |
| 2959 | page_cache_release(new_page); | 2964 | page_cache_release(new_page); |
| 2960 | return ret; | 2965 | return ret; |
| 2961 | } | 2966 | } |
| @@ -3425,44 +3430,6 @@ int __pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address) | |||
| 3425 | } | 3430 | } |
| 3426 | #endif /* __PAGETABLE_PMD_FOLDED */ | 3431 | #endif /* __PAGETABLE_PMD_FOLDED */ |
| 3427 | 3432 | ||
| 3428 | #if !defined(__HAVE_ARCH_GATE_AREA) | ||
| 3429 | |||
| 3430 | #if defined(AT_SYSINFO_EHDR) | ||
| 3431 | static struct vm_area_struct gate_vma; | ||
| 3432 | |||
| 3433 | static int __init gate_vma_init(void) | ||
| 3434 | { | ||
| 3435 | gate_vma.vm_mm = NULL; | ||
| 3436 | gate_vma.vm_start = FIXADDR_USER_START; | ||
| 3437 | gate_vma.vm_end = FIXADDR_USER_END; | ||
| 3438 | gate_vma.vm_flags = VM_READ | VM_MAYREAD | VM_EXEC | VM_MAYEXEC; | ||
| 3439 | gate_vma.vm_page_prot = __P101; | ||
| 3440 | |||
| 3441 | return 0; | ||
| 3442 | } | ||
| 3443 | __initcall(gate_vma_init); | ||
| 3444 | #endif | ||
| 3445 | |||
| 3446 | struct vm_area_struct *get_gate_vma(struct mm_struct *mm) | ||
| 3447 | { | ||
| 3448 | #ifdef AT_SYSINFO_EHDR | ||
| 3449 | return &gate_vma; | ||
| 3450 | #else | ||
| 3451 | return NULL; | ||
| 3452 | #endif | ||
| 3453 | } | ||
| 3454 | |||
| 3455 | int in_gate_area_no_mm(unsigned long addr) | ||
| 3456 | { | ||
| 3457 | #ifdef AT_SYSINFO_EHDR | ||
| 3458 | if ((addr >= FIXADDR_USER_START) && (addr < FIXADDR_USER_END)) | ||
| 3459 | return 1; | ||
| 3460 | #endif | ||
| 3461 | return 0; | ||
| 3462 | } | ||
| 3463 | |||
| 3464 | #endif /* __HAVE_ARCH_GATE_AREA */ | ||
| 3465 | |||
| 3466 | static int __follow_pte(struct mm_struct *mm, unsigned long address, | 3433 | static int __follow_pte(struct mm_struct *mm, unsigned long address, |
| 3467 | pte_t **ptepp, spinlock_t **ptlp) | 3434 | pte_t **ptepp, spinlock_t **ptlp) |
| 3468 | { | 3435 | { |
diff --git a/mm/migrate.c b/mm/migrate.c index be6dbf995c0c..f78ec9bd454d 100644 --- a/mm/migrate.c +++ b/mm/migrate.c | |||
| @@ -780,6 +780,7 @@ static int move_to_new_page(struct page *newpage, struct page *page, | |||
| 780 | if (rc != MIGRATEPAGE_SUCCESS) { | 780 | if (rc != MIGRATEPAGE_SUCCESS) { |
| 781 | newpage->mapping = NULL; | 781 | newpage->mapping = NULL; |
| 782 | } else { | 782 | } else { |
| 783 | mem_cgroup_migrate(page, newpage, false); | ||
| 783 | if (remap_swapcache) | 784 | if (remap_swapcache) |
| 784 | remove_migration_ptes(page, newpage); | 785 | remove_migration_ptes(page, newpage); |
| 785 | page->mapping = NULL; | 786 | page->mapping = NULL; |
| @@ -795,7 +796,6 @@ static int __unmap_and_move(struct page *page, struct page *newpage, | |||
| 795 | { | 796 | { |
| 796 | int rc = -EAGAIN; | 797 | int rc = -EAGAIN; |
| 797 | int remap_swapcache = 1; | 798 | int remap_swapcache = 1; |
| 798 | struct mem_cgroup *mem; | ||
| 799 | struct anon_vma *anon_vma = NULL; | 799 | struct anon_vma *anon_vma = NULL; |
| 800 | 800 | ||
| 801 | if (!trylock_page(page)) { | 801 | if (!trylock_page(page)) { |
| @@ -821,9 +821,6 @@ static int __unmap_and_move(struct page *page, struct page *newpage, | |||
| 821 | lock_page(page); | 821 | lock_page(page); |
| 822 | } | 822 | } |
| 823 | 823 | ||
| 824 | /* charge against new page */ | ||
| 825 | mem_cgroup_prepare_migration(page, newpage, &mem); | ||
| 826 | |||
| 827 | if (PageWriteback(page)) { | 824 | if (PageWriteback(page)) { |
| 828 | /* | 825 | /* |
| 829 | * Only in the case of a full synchronous migration is it | 826 | * Only in the case of a full synchronous migration is it |
| @@ -833,10 +830,10 @@ static int __unmap_and_move(struct page *page, struct page *newpage, | |||
| 833 | */ | 830 | */ |
| 834 | if (mode != MIGRATE_SYNC) { | 831 | if (mode != MIGRATE_SYNC) { |
| 835 | rc = -EBUSY; | 832 | rc = -EBUSY; |
| 836 | goto uncharge; | 833 | goto out_unlock; |
| 837 | } | 834 | } |
| 838 | if (!force) | 835 | if (!force) |
| 839 | goto uncharge; | 836 | goto out_unlock; |
| 840 | wait_on_page_writeback(page); | 837 | wait_on_page_writeback(page); |
| 841 | } | 838 | } |
| 842 | /* | 839 | /* |
| @@ -872,7 +869,7 @@ static int __unmap_and_move(struct page *page, struct page *newpage, | |||
| 872 | */ | 869 | */ |
| 873 | remap_swapcache = 0; | 870 | remap_swapcache = 0; |
| 874 | } else { | 871 | } else { |
| 875 | goto uncharge; | 872 | goto out_unlock; |
| 876 | } | 873 | } |
| 877 | } | 874 | } |
| 878 | 875 | ||
| @@ -885,7 +882,7 @@ static int __unmap_and_move(struct page *page, struct page *newpage, | |||
| 885 | * the page migration right away (proteced by page lock). | 882 | * the page migration right away (proteced by page lock). |
| 886 | */ | 883 | */ |
| 887 | rc = balloon_page_migrate(newpage, page, mode); | 884 | rc = balloon_page_migrate(newpage, page, mode); |
| 888 | goto uncharge; | 885 | goto out_unlock; |
| 889 | } | 886 | } |
| 890 | 887 | ||
| 891 | /* | 888 | /* |
| @@ -904,7 +901,7 @@ static int __unmap_and_move(struct page *page, struct page *newpage, | |||
| 904 | VM_BUG_ON_PAGE(PageAnon(page), page); | 901 | VM_BUG_ON_PAGE(PageAnon(page), page); |
| 905 | if (page_has_private(page)) { | 902 | if (page_has_private(page)) { |
| 906 | try_to_free_buffers(page); | 903 | try_to_free_buffers(page); |
| 907 | goto uncharge; | 904 | goto out_unlock; |
| 908 | } | 905 | } |
| 909 | goto skip_unmap; | 906 | goto skip_unmap; |
| 910 | } | 907 | } |
| @@ -923,10 +920,7 @@ skip_unmap: | |||
| 923 | if (anon_vma) | 920 | if (anon_vma) |
| 924 | put_anon_vma(anon_vma); | 921 | put_anon_vma(anon_vma); |
| 925 | 922 | ||
| 926 | uncharge: | 923 | out_unlock: |
| 927 | mem_cgroup_end_migration(mem, page, newpage, | ||
| 928 | (rc == MIGRATEPAGE_SUCCESS || | ||
| 929 | rc == MIGRATEPAGE_BALLOON_SUCCESS)); | ||
| 930 | unlock_page(page); | 924 | unlock_page(page); |
| 931 | out: | 925 | out: |
| 932 | return rc; | 926 | return rc; |
| @@ -1786,7 +1780,6 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm, | |||
| 1786 | pg_data_t *pgdat = NODE_DATA(node); | 1780 | pg_data_t *pgdat = NODE_DATA(node); |
| 1787 | int isolated = 0; | 1781 | int isolated = 0; |
| 1788 | struct page *new_page = NULL; | 1782 | struct page *new_page = NULL; |
| 1789 | struct mem_cgroup *memcg = NULL; | ||
| 1790 | int page_lru = page_is_file_cache(page); | 1783 | int page_lru = page_is_file_cache(page); |
| 1791 | unsigned long mmun_start = address & HPAGE_PMD_MASK; | 1784 | unsigned long mmun_start = address & HPAGE_PMD_MASK; |
| 1792 | unsigned long mmun_end = mmun_start + HPAGE_PMD_SIZE; | 1785 | unsigned long mmun_end = mmun_start + HPAGE_PMD_SIZE; |
| @@ -1852,15 +1845,6 @@ fail_putback: | |||
| 1852 | goto out_unlock; | 1845 | goto out_unlock; |
| 1853 | } | 1846 | } |
| 1854 | 1847 | ||
| 1855 | /* | ||
| 1856 | * Traditional migration needs to prepare the memcg charge | ||
| 1857 | * transaction early to prevent the old page from being | ||
| 1858 | * uncharged when installing migration entries. Here we can | ||
| 1859 | * save the potential rollback and start the charge transfer | ||
| 1860 | * only when migration is already known to end successfully. | ||
| 1861 | */ | ||
| 1862 | mem_cgroup_prepare_migration(page, new_page, &memcg); | ||
| 1863 | |||
| 1864 | orig_entry = *pmd; | 1848 | orig_entry = *pmd; |
| 1865 | entry = mk_pmd(new_page, vma->vm_page_prot); | 1849 | entry = mk_pmd(new_page, vma->vm_page_prot); |
| 1866 | entry = pmd_mkhuge(entry); | 1850 | entry = pmd_mkhuge(entry); |
| @@ -1888,14 +1872,10 @@ fail_putback: | |||
| 1888 | goto fail_putback; | 1872 | goto fail_putback; |
| 1889 | } | 1873 | } |
| 1890 | 1874 | ||
| 1875 | mem_cgroup_migrate(page, new_page, false); | ||
| 1876 | |||
| 1891 | page_remove_rmap(page); | 1877 | page_remove_rmap(page); |
| 1892 | 1878 | ||
| 1893 | /* | ||
| 1894 | * Finish the charge transaction under the page table lock to | ||
| 1895 | * prevent split_huge_page() from dividing up the charge | ||
| 1896 | * before it's fully transferred to the new page. | ||
| 1897 | */ | ||
| 1898 | mem_cgroup_end_migration(memcg, page, new_page, true); | ||
| 1899 | spin_unlock(ptl); | 1879 | spin_unlock(ptl); |
| 1900 | mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end); | 1880 | mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end); |
| 1901 | 1881 | ||
| @@ -221,7 +221,7 @@ static void __remove_shared_vm_struct(struct vm_area_struct *vma, | |||
| 221 | if (vma->vm_flags & VM_DENYWRITE) | 221 | if (vma->vm_flags & VM_DENYWRITE) |
| 222 | atomic_inc(&file_inode(file)->i_writecount); | 222 | atomic_inc(&file_inode(file)->i_writecount); |
| 223 | if (vma->vm_flags & VM_SHARED) | 223 | if (vma->vm_flags & VM_SHARED) |
| 224 | mapping->i_mmap_writable--; | 224 | mapping_unmap_writable(mapping); |
| 225 | 225 | ||
| 226 | flush_dcache_mmap_lock(mapping); | 226 | flush_dcache_mmap_lock(mapping); |
| 227 | if (unlikely(vma->vm_flags & VM_NONLINEAR)) | 227 | if (unlikely(vma->vm_flags & VM_NONLINEAR)) |
| @@ -622,7 +622,7 @@ static void __vma_link_file(struct vm_area_struct *vma) | |||
| 622 | if (vma->vm_flags & VM_DENYWRITE) | 622 | if (vma->vm_flags & VM_DENYWRITE) |
| 623 | atomic_dec(&file_inode(file)->i_writecount); | 623 | atomic_dec(&file_inode(file)->i_writecount); |
| 624 | if (vma->vm_flags & VM_SHARED) | 624 | if (vma->vm_flags & VM_SHARED) |
| 625 | mapping->i_mmap_writable++; | 625 | atomic_inc(&mapping->i_mmap_writable); |
| 626 | 626 | ||
| 627 | flush_dcache_mmap_lock(mapping); | 627 | flush_dcache_mmap_lock(mapping); |
| 628 | if (unlikely(vma->vm_flags & VM_NONLINEAR)) | 628 | if (unlikely(vma->vm_flags & VM_NONLINEAR)) |
| @@ -1577,6 +1577,17 @@ munmap_back: | |||
| 1577 | if (error) | 1577 | if (error) |
| 1578 | goto free_vma; | 1578 | goto free_vma; |
| 1579 | } | 1579 | } |
| 1580 | if (vm_flags & VM_SHARED) { | ||
| 1581 | error = mapping_map_writable(file->f_mapping); | ||
| 1582 | if (error) | ||
| 1583 | goto allow_write_and_free_vma; | ||
| 1584 | } | ||
| 1585 | |||
| 1586 | /* ->mmap() can change vma->vm_file, but must guarantee that | ||
| 1587 | * vma_link() below can deny write-access if VM_DENYWRITE is set | ||
| 1588 | * and map writably if VM_SHARED is set. This usually means the | ||
| 1589 | * new file must not have been exposed to user-space, yet. | ||
| 1590 | */ | ||
| 1580 | vma->vm_file = get_file(file); | 1591 | vma->vm_file = get_file(file); |
| 1581 | error = file->f_op->mmap(file, vma); | 1592 | error = file->f_op->mmap(file, vma); |
| 1582 | if (error) | 1593 | if (error) |
| @@ -1616,8 +1627,12 @@ munmap_back: | |||
| 1616 | 1627 | ||
| 1617 | vma_link(mm, vma, prev, rb_link, rb_parent); | 1628 | vma_link(mm, vma, prev, rb_link, rb_parent); |
| 1618 | /* Once vma denies write, undo our temporary denial count */ | 1629 | /* Once vma denies write, undo our temporary denial count */ |
| 1619 | if (vm_flags & VM_DENYWRITE) | 1630 | if (file) { |
| 1620 | allow_write_access(file); | 1631 | if (vm_flags & VM_SHARED) |
| 1632 | mapping_unmap_writable(file->f_mapping); | ||
| 1633 | if (vm_flags & VM_DENYWRITE) | ||
| 1634 | allow_write_access(file); | ||
| 1635 | } | ||
| 1621 | file = vma->vm_file; | 1636 | file = vma->vm_file; |
| 1622 | out: | 1637 | out: |
| 1623 | perf_event_mmap(vma); | 1638 | perf_event_mmap(vma); |
| @@ -1646,14 +1661,17 @@ out: | |||
| 1646 | return addr; | 1661 | return addr; |
| 1647 | 1662 | ||
| 1648 | unmap_and_free_vma: | 1663 | unmap_and_free_vma: |
| 1649 | if (vm_flags & VM_DENYWRITE) | ||
| 1650 | allow_write_access(file); | ||
| 1651 | vma->vm_file = NULL; | 1664 | vma->vm_file = NULL; |
| 1652 | fput(file); | 1665 | fput(file); |
| 1653 | 1666 | ||
| 1654 | /* Undo any partial mapping done by a device driver. */ | 1667 | /* Undo any partial mapping done by a device driver. */ |
| 1655 | unmap_region(mm, vma, prev, vma->vm_start, vma->vm_end); | 1668 | unmap_region(mm, vma, prev, vma->vm_start, vma->vm_end); |
| 1656 | charged = 0; | 1669 | charged = 0; |
| 1670 | if (vm_flags & VM_SHARED) | ||
| 1671 | mapping_unmap_writable(file->f_mapping); | ||
| 1672 | allow_write_and_free_vma: | ||
| 1673 | if (vm_flags & VM_DENYWRITE) | ||
| 1674 | allow_write_access(file); | ||
| 1657 | free_vma: | 1675 | free_vma: |
| 1658 | kmem_cache_free(vm_area_cachep, vma); | 1676 | kmem_cache_free(vm_area_cachep, vma); |
| 1659 | unacct_error: | 1677 | unacct_error: |
diff --git a/mm/nommu.c b/mm/nommu.c index 4a852f6c5709..a881d9673c6b 100644 --- a/mm/nommu.c +++ b/mm/nommu.c | |||
| @@ -1981,11 +1981,6 @@ error: | |||
| 1981 | return -ENOMEM; | 1981 | return -ENOMEM; |
| 1982 | } | 1982 | } |
| 1983 | 1983 | ||
| 1984 | int in_gate_area_no_mm(unsigned long addr) | ||
| 1985 | { | ||
| 1986 | return 0; | ||
| 1987 | } | ||
| 1988 | |||
| 1989 | int filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | 1984 | int filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf) |
| 1990 | { | 1985 | { |
| 1991 | BUG(); | 1986 | BUG(); |
| @@ -1032,25 +1032,6 @@ void page_add_new_anon_rmap(struct page *page, | |||
| 1032 | __mod_zone_page_state(page_zone(page), NR_ANON_PAGES, | 1032 | __mod_zone_page_state(page_zone(page), NR_ANON_PAGES, |
| 1033 | hpage_nr_pages(page)); | 1033 | hpage_nr_pages(page)); |
| 1034 | __page_set_anon_rmap(page, vma, address, 1); | 1034 | __page_set_anon_rmap(page, vma, address, 1); |
| 1035 | |||
| 1036 | VM_BUG_ON_PAGE(PageLRU(page), page); | ||
| 1037 | if (likely((vma->vm_flags & (VM_LOCKED | VM_SPECIAL)) != VM_LOCKED)) { | ||
| 1038 | SetPageActive(page); | ||
| 1039 | lru_cache_add(page); | ||
| 1040 | return; | ||
| 1041 | } | ||
| 1042 | |||
| 1043 | if (!TestSetPageMlocked(page)) { | ||
| 1044 | /* | ||
| 1045 | * We use the irq-unsafe __mod_zone_page_stat because this | ||
| 1046 | * counter is not modified from interrupt context, and the pte | ||
| 1047 | * lock is held(spinlock), which implies preemption disabled. | ||
| 1048 | */ | ||
| 1049 | __mod_zone_page_state(page_zone(page), NR_MLOCK, | ||
| 1050 | hpage_nr_pages(page)); | ||
| 1051 | count_vm_event(UNEVICTABLE_PGMLOCKED); | ||
| 1052 | } | ||
| 1053 | add_page_to_unevictable_list(page); | ||
| 1054 | } | 1035 | } |
| 1055 | 1036 | ||
| 1056 | /** | 1037 | /** |
| @@ -1108,7 +1089,6 @@ void page_remove_rmap(struct page *page) | |||
| 1108 | if (unlikely(PageHuge(page))) | 1089 | if (unlikely(PageHuge(page))) |
| 1109 | goto out; | 1090 | goto out; |
| 1110 | if (anon) { | 1091 | if (anon) { |
| 1111 | mem_cgroup_uncharge_page(page); | ||
| 1112 | if (PageTransHuge(page)) | 1092 | if (PageTransHuge(page)) |
| 1113 | __dec_zone_page_state(page, | 1093 | __dec_zone_page_state(page, |
| 1114 | NR_ANON_TRANSPARENT_HUGEPAGES); | 1094 | NR_ANON_TRANSPARENT_HUGEPAGES); |
diff --git a/mm/shmem.c b/mm/shmem.c index 302d1cf7ad07..a42add14331c 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
| @@ -66,6 +66,9 @@ static struct vfsmount *shm_mnt; | |||
| 66 | #include <linux/highmem.h> | 66 | #include <linux/highmem.h> |
| 67 | #include <linux/seq_file.h> | 67 | #include <linux/seq_file.h> |
| 68 | #include <linux/magic.h> | 68 | #include <linux/magic.h> |
| 69 | #include <linux/syscalls.h> | ||
| 70 | #include <linux/fcntl.h> | ||
| 71 | #include <uapi/linux/memfd.h> | ||
| 69 | 72 | ||
| 70 | #include <asm/uaccess.h> | 73 | #include <asm/uaccess.h> |
| 71 | #include <asm/pgtable.h> | 74 | #include <asm/pgtable.h> |
| @@ -419,7 +422,6 @@ static void shmem_undo_range(struct inode *inode, loff_t lstart, loff_t lend, | |||
| 419 | pvec.pages, indices); | 422 | pvec.pages, indices); |
| 420 | if (!pvec.nr) | 423 | if (!pvec.nr) |
| 421 | break; | 424 | break; |
| 422 | mem_cgroup_uncharge_start(); | ||
| 423 | for (i = 0; i < pagevec_count(&pvec); i++) { | 425 | for (i = 0; i < pagevec_count(&pvec); i++) { |
| 424 | struct page *page = pvec.pages[i]; | 426 | struct page *page = pvec.pages[i]; |
| 425 | 427 | ||
| @@ -447,7 +449,6 @@ static void shmem_undo_range(struct inode *inode, loff_t lstart, loff_t lend, | |||
| 447 | } | 449 | } |
| 448 | pagevec_remove_exceptionals(&pvec); | 450 | pagevec_remove_exceptionals(&pvec); |
| 449 | pagevec_release(&pvec); | 451 | pagevec_release(&pvec); |
| 450 | mem_cgroup_uncharge_end(); | ||
| 451 | cond_resched(); | 452 | cond_resched(); |
| 452 | index++; | 453 | index++; |
| 453 | } | 454 | } |
| @@ -495,7 +496,6 @@ static void shmem_undo_range(struct inode *inode, loff_t lstart, loff_t lend, | |||
| 495 | index = start; | 496 | index = start; |
| 496 | continue; | 497 | continue; |
| 497 | } | 498 | } |
| 498 | mem_cgroup_uncharge_start(); | ||
| 499 | for (i = 0; i < pagevec_count(&pvec); i++) { | 499 | for (i = 0; i < pagevec_count(&pvec); i++) { |
| 500 | struct page *page = pvec.pages[i]; | 500 | struct page *page = pvec.pages[i]; |
| 501 | 501 | ||
| @@ -531,7 +531,6 @@ static void shmem_undo_range(struct inode *inode, loff_t lstart, loff_t lend, | |||
| 531 | } | 531 | } |
| 532 | pagevec_remove_exceptionals(&pvec); | 532 | pagevec_remove_exceptionals(&pvec); |
| 533 | pagevec_release(&pvec); | 533 | pagevec_release(&pvec); |
| 534 | mem_cgroup_uncharge_end(); | ||
| 535 | index++; | 534 | index++; |
| 536 | } | 535 | } |
| 537 | 536 | ||
| @@ -551,6 +550,7 @@ EXPORT_SYMBOL_GPL(shmem_truncate_range); | |||
| 551 | static int shmem_setattr(struct dentry *dentry, struct iattr *attr) | 550 | static int shmem_setattr(struct dentry *dentry, struct iattr *attr) |
| 552 | { | 551 | { |
| 553 | struct inode *inode = dentry->d_inode; | 552 | struct inode *inode = dentry->d_inode; |
| 553 | struct shmem_inode_info *info = SHMEM_I(inode); | ||
| 554 | int error; | 554 | int error; |
| 555 | 555 | ||
| 556 | error = inode_change_ok(inode, attr); | 556 | error = inode_change_ok(inode, attr); |
| @@ -561,6 +561,11 @@ static int shmem_setattr(struct dentry *dentry, struct iattr *attr) | |||
| 561 | loff_t oldsize = inode->i_size; | 561 | loff_t oldsize = inode->i_size; |
| 562 | loff_t newsize = attr->ia_size; | 562 | loff_t newsize = attr->ia_size; |
| 563 | 563 | ||
| 564 | /* protected by i_mutex */ | ||
| 565 | if ((newsize < oldsize && (info->seals & F_SEAL_SHRINK)) || | ||
| 566 | (newsize > oldsize && (info->seals & F_SEAL_GROW))) | ||
| 567 | return -EPERM; | ||
| 568 | |||
| 564 | if (newsize != oldsize) { | 569 | if (newsize != oldsize) { |
| 565 | error = shmem_reacct_size(SHMEM_I(inode)->flags, | 570 | error = shmem_reacct_size(SHMEM_I(inode)->flags, |
| 566 | oldsize, newsize); | 571 | oldsize, newsize); |
| @@ -621,7 +626,7 @@ static int shmem_unuse_inode(struct shmem_inode_info *info, | |||
| 621 | radswap = swp_to_radix_entry(swap); | 626 | radswap = swp_to_radix_entry(swap); |
| 622 | index = radix_tree_locate_item(&mapping->page_tree, radswap); | 627 | index = radix_tree_locate_item(&mapping->page_tree, radswap); |
| 623 | if (index == -1) | 628 | if (index == -1) |
| 624 | return 0; | 629 | return -EAGAIN; /* tell shmem_unuse we found nothing */ |
| 625 | 630 | ||
| 626 | /* | 631 | /* |
| 627 | * Move _head_ to start search for next from here. | 632 | * Move _head_ to start search for next from here. |
| @@ -680,7 +685,6 @@ static int shmem_unuse_inode(struct shmem_inode_info *info, | |||
| 680 | spin_unlock(&info->lock); | 685 | spin_unlock(&info->lock); |
| 681 | swap_free(swap); | 686 | swap_free(swap); |
| 682 | } | 687 | } |
| 683 | error = 1; /* not an error, but entry was found */ | ||
| 684 | } | 688 | } |
| 685 | return error; | 689 | return error; |
| 686 | } | 690 | } |
| @@ -692,7 +696,7 @@ int shmem_unuse(swp_entry_t swap, struct page *page) | |||
| 692 | { | 696 | { |
| 693 | struct list_head *this, *next; | 697 | struct list_head *this, *next; |
| 694 | struct shmem_inode_info *info; | 698 | struct shmem_inode_info *info; |
| 695 | int found = 0; | 699 | struct mem_cgroup *memcg; |
| 696 | int error = 0; | 700 | int error = 0; |
| 697 | 701 | ||
| 698 | /* | 702 | /* |
| @@ -707,26 +711,32 @@ int shmem_unuse(swp_entry_t swap, struct page *page) | |||
| 707 | * the shmem_swaplist_mutex which might hold up shmem_writepage(). | 711 | * the shmem_swaplist_mutex which might hold up shmem_writepage(). |
| 708 | * Charged back to the user (not to caller) when swap account is used. | 712 | * Charged back to the user (not to caller) when swap account is used. |
| 709 | */ | 713 | */ |
| 710 | error = mem_cgroup_charge_file(page, current->mm, GFP_KERNEL); | 714 | error = mem_cgroup_try_charge(page, current->mm, GFP_KERNEL, &memcg); |
| 711 | if (error) | 715 | if (error) |
| 712 | goto out; | 716 | goto out; |
| 713 | /* No radix_tree_preload: swap entry keeps a place for page in tree */ | 717 | /* No radix_tree_preload: swap entry keeps a place for page in tree */ |
| 718 | error = -EAGAIN; | ||
| 714 | 719 | ||
| 715 | mutex_lock(&shmem_swaplist_mutex); | 720 | mutex_lock(&shmem_swaplist_mutex); |
| 716 | list_for_each_safe(this, next, &shmem_swaplist) { | 721 | list_for_each_safe(this, next, &shmem_swaplist) { |
| 717 | info = list_entry(this, struct shmem_inode_info, swaplist); | 722 | info = list_entry(this, struct shmem_inode_info, swaplist); |
| 718 | if (info->swapped) | 723 | if (info->swapped) |
| 719 | found = shmem_unuse_inode(info, swap, &page); | 724 | error = shmem_unuse_inode(info, swap, &page); |
| 720 | else | 725 | else |
| 721 | list_del_init(&info->swaplist); | 726 | list_del_init(&info->swaplist); |
| 722 | cond_resched(); | 727 | cond_resched(); |
| 723 | if (found) | 728 | if (error != -EAGAIN) |
| 724 | break; | 729 | break; |
| 730 | /* found nothing in this: move on to search the next */ | ||
| 725 | } | 731 | } |
| 726 | mutex_unlock(&shmem_swaplist_mutex); | 732 | mutex_unlock(&shmem_swaplist_mutex); |
| 727 | 733 | ||
| 728 | if (found < 0) | 734 | if (error) { |
| 729 | error = found; | 735 | if (error != -ENOMEM) |
| 736 | error = 0; | ||
| 737 | mem_cgroup_cancel_charge(page, memcg); | ||
| 738 | } else | ||
| 739 | mem_cgroup_commit_charge(page, memcg, true); | ||
| 730 | out: | 740 | out: |
| 731 | unlock_page(page); | 741 | unlock_page(page); |
| 732 | page_cache_release(page); | 742 | page_cache_release(page); |
| @@ -830,7 +840,7 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc) | |||
| 830 | } | 840 | } |
| 831 | 841 | ||
| 832 | mutex_unlock(&shmem_swaplist_mutex); | 842 | mutex_unlock(&shmem_swaplist_mutex); |
| 833 | swapcache_free(swap, NULL); | 843 | swapcache_free(swap); |
| 834 | redirty: | 844 | redirty: |
| 835 | set_page_dirty(page); | 845 | set_page_dirty(page); |
| 836 | if (wbc->for_reclaim) | 846 | if (wbc->for_reclaim) |
| @@ -1003,7 +1013,7 @@ static int shmem_replace_page(struct page **pagep, gfp_t gfp, | |||
| 1003 | */ | 1013 | */ |
| 1004 | oldpage = newpage; | 1014 | oldpage = newpage; |
| 1005 | } else { | 1015 | } else { |
| 1006 | mem_cgroup_replace_page_cache(oldpage, newpage); | 1016 | mem_cgroup_migrate(oldpage, newpage, false); |
| 1007 | lru_cache_add_anon(newpage); | 1017 | lru_cache_add_anon(newpage); |
| 1008 | *pagep = newpage; | 1018 | *pagep = newpage; |
| 1009 | } | 1019 | } |
| @@ -1030,6 +1040,7 @@ static int shmem_getpage_gfp(struct inode *inode, pgoff_t index, | |||
| 1030 | struct address_space *mapping = inode->i_mapping; | 1040 | struct address_space *mapping = inode->i_mapping; |
| 1031 | struct shmem_inode_info *info; | 1041 | struct shmem_inode_info *info; |
| 1032 | struct shmem_sb_info *sbinfo; | 1042 | struct shmem_sb_info *sbinfo; |
| 1043 | struct mem_cgroup *memcg; | ||
| 1033 | struct page *page; | 1044 | struct page *page; |
| 1034 | swp_entry_t swap; | 1045 | swp_entry_t swap; |
| 1035 | int error; | 1046 | int error; |
| @@ -1108,8 +1119,7 @@ repeat: | |||
| 1108 | goto failed; | 1119 | goto failed; |
| 1109 | } | 1120 | } |
| 1110 | 1121 | ||
| 1111 | error = mem_cgroup_charge_file(page, current->mm, | 1122 | error = mem_cgroup_try_charge(page, current->mm, gfp, &memcg); |
| 1112 | gfp & GFP_RECLAIM_MASK); | ||
| 1113 | if (!error) { | 1123 | if (!error) { |
| 1114 | error = shmem_add_to_page_cache(page, mapping, index, | 1124 | error = shmem_add_to_page_cache(page, mapping, index, |
| 1115 | swp_to_radix_entry(swap)); | 1125 | swp_to_radix_entry(swap)); |
| @@ -1125,12 +1135,16 @@ repeat: | |||
| 1125 | * Reset swap.val? No, leave it so "failed" goes back to | 1135 | * Reset swap.val? No, leave it so "failed" goes back to |
| 1126 | * "repeat": reading a hole and writing should succeed. | 1136 | * "repeat": reading a hole and writing should succeed. |
| 1127 | */ | 1137 | */ |
| 1128 | if (error) | 1138 | if (error) { |
| 1139 | mem_cgroup_cancel_charge(page, memcg); | ||
| 1129 | delete_from_swap_cache(page); | 1140 | delete_from_swap_cache(page); |
| 1141 | } | ||
| 1130 | } | 1142 | } |
| 1131 | if (error) | 1143 | if (error) |
| 1132 | goto failed; | 1144 | goto failed; |
| 1133 | 1145 | ||
| 1146 | mem_cgroup_commit_charge(page, memcg, true); | ||
| 1147 | |||
| 1134 | spin_lock(&info->lock); | 1148 | spin_lock(&info->lock); |
| 1135 | info->swapped--; | 1149 | info->swapped--; |
| 1136 | shmem_recalc_inode(inode); | 1150 | shmem_recalc_inode(inode); |
| @@ -1168,8 +1182,7 @@ repeat: | |||
| 1168 | if (sgp == SGP_WRITE) | 1182 | if (sgp == SGP_WRITE) |
| 1169 | __SetPageReferenced(page); | 1183 | __SetPageReferenced(page); |
| 1170 | 1184 | ||
| 1171 | error = mem_cgroup_charge_file(page, current->mm, | 1185 | error = mem_cgroup_try_charge(page, current->mm, gfp, &memcg); |
| 1172 | gfp & GFP_RECLAIM_MASK); | ||
| 1173 | if (error) | 1186 | if (error) |
| 1174 | goto decused; | 1187 | goto decused; |
| 1175 | error = radix_tree_maybe_preload(gfp & GFP_RECLAIM_MASK); | 1188 | error = radix_tree_maybe_preload(gfp & GFP_RECLAIM_MASK); |
| @@ -1179,9 +1192,10 @@ repeat: | |||
| 1179 | radix_tree_preload_end(); | 1192 | radix_tree_preload_end(); |
| 1180 | } | 1193 | } |
| 1181 | if (error) { | 1194 | if (error) { |
| 1182 | mem_cgroup_uncharge_cache_page(page); | 1195 | mem_cgroup_cancel_charge(page, memcg); |
| 1183 | goto decused; | 1196 | goto decused; |
| 1184 | } | 1197 | } |
| 1198 | mem_cgroup_commit_charge(page, memcg, false); | ||
| 1185 | lru_cache_add_anon(page); | 1199 | lru_cache_add_anon(page); |
| 1186 | 1200 | ||
| 1187 | spin_lock(&info->lock); | 1201 | spin_lock(&info->lock); |
| @@ -1407,6 +1421,7 @@ static struct inode *shmem_get_inode(struct super_block *sb, const struct inode | |||
| 1407 | info = SHMEM_I(inode); | 1421 | info = SHMEM_I(inode); |
| 1408 | memset(info, 0, (char *)inode - (char *)info); | 1422 | memset(info, 0, (char *)inode - (char *)info); |
| 1409 | spin_lock_init(&info->lock); | 1423 | spin_lock_init(&info->lock); |
| 1424 | info->seals = F_SEAL_SEAL; | ||
| 1410 | info->flags = flags & VM_NORESERVE; | 1425 | info->flags = flags & VM_NORESERVE; |
| 1411 | INIT_LIST_HEAD(&info->swaplist); | 1426 | INIT_LIST_HEAD(&info->swaplist); |
| 1412 | simple_xattrs_init(&info->xattrs); | 1427 | simple_xattrs_init(&info->xattrs); |
| @@ -1465,7 +1480,17 @@ shmem_write_begin(struct file *file, struct address_space *mapping, | |||
| 1465 | struct page **pagep, void **fsdata) | 1480 | struct page **pagep, void **fsdata) |
| 1466 | { | 1481 | { |
| 1467 | struct inode *inode = mapping->host; | 1482 | struct inode *inode = mapping->host; |
| 1483 | struct shmem_inode_info *info = SHMEM_I(inode); | ||
| 1468 | pgoff_t index = pos >> PAGE_CACHE_SHIFT; | 1484 | pgoff_t index = pos >> PAGE_CACHE_SHIFT; |
| 1485 | |||
| 1486 | /* i_mutex is held by caller */ | ||
| 1487 | if (unlikely(info->seals)) { | ||
| 1488 | if (info->seals & F_SEAL_WRITE) | ||
| 1489 | return -EPERM; | ||
| 1490 | if ((info->seals & F_SEAL_GROW) && pos + len > inode->i_size) | ||
| 1491 | return -EPERM; | ||
| 1492 | } | ||
| 1493 | |||
| 1469 | return shmem_getpage(inode, index, pagep, SGP_WRITE, NULL); | 1494 | return shmem_getpage(inode, index, pagep, SGP_WRITE, NULL); |
| 1470 | } | 1495 | } |
| 1471 | 1496 | ||
| @@ -1803,11 +1828,233 @@ static loff_t shmem_file_llseek(struct file *file, loff_t offset, int whence) | |||
| 1803 | return offset; | 1828 | return offset; |
| 1804 | } | 1829 | } |
| 1805 | 1830 | ||
| 1831 | /* | ||
| 1832 | * We need a tag: a new tag would expand every radix_tree_node by 8 bytes, | ||
| 1833 | * so reuse a tag which we firmly believe is never set or cleared on shmem. | ||
| 1834 | */ | ||
| 1835 | #define SHMEM_TAG_PINNED PAGECACHE_TAG_TOWRITE | ||
| 1836 | #define LAST_SCAN 4 /* about 150ms max */ | ||
| 1837 | |||
| 1838 | static void shmem_tag_pins(struct address_space *mapping) | ||
| 1839 | { | ||
| 1840 | struct radix_tree_iter iter; | ||
| 1841 | void **slot; | ||
| 1842 | pgoff_t start; | ||
| 1843 | struct page *page; | ||
| 1844 | |||
| 1845 | lru_add_drain(); | ||
| 1846 | start = 0; | ||
| 1847 | rcu_read_lock(); | ||
| 1848 | |||
| 1849 | restart: | ||
| 1850 | radix_tree_for_each_slot(slot, &mapping->page_tree, &iter, start) { | ||
| 1851 | page = radix_tree_deref_slot(slot); | ||
| 1852 | if (!page || radix_tree_exception(page)) { | ||
| 1853 | if (radix_tree_deref_retry(page)) | ||
| 1854 | goto restart; | ||
| 1855 | } else if (page_count(page) - page_mapcount(page) > 1) { | ||
| 1856 | spin_lock_irq(&mapping->tree_lock); | ||
| 1857 | radix_tree_tag_set(&mapping->page_tree, iter.index, | ||
| 1858 | SHMEM_TAG_PINNED); | ||
| 1859 | spin_unlock_irq(&mapping->tree_lock); | ||
| 1860 | } | ||
| 1861 | |||
| 1862 | if (need_resched()) { | ||
| 1863 | cond_resched_rcu(); | ||
| 1864 | start = iter.index + 1; | ||
| 1865 | goto restart; | ||
| 1866 | } | ||
| 1867 | } | ||
| 1868 | rcu_read_unlock(); | ||
| 1869 | } | ||
| 1870 | |||
| 1871 | /* | ||
| 1872 | * Setting SEAL_WRITE requires us to verify there's no pending writer. However, | ||
| 1873 | * via get_user_pages(), drivers might have some pending I/O without any active | ||
| 1874 | * user-space mappings (eg., direct-IO, AIO). Therefore, we look at all pages | ||
| 1875 | * and see whether it has an elevated ref-count. If so, we tag them and wait for | ||
| 1876 | * them to be dropped. | ||
| 1877 | * The caller must guarantee that no new user will acquire writable references | ||
| 1878 | * to those pages to avoid races. | ||
| 1879 | */ | ||
| 1880 | static int shmem_wait_for_pins(struct address_space *mapping) | ||
| 1881 | { | ||
| 1882 | struct radix_tree_iter iter; | ||
| 1883 | void **slot; | ||
| 1884 | pgoff_t start; | ||
| 1885 | struct page *page; | ||
| 1886 | int error, scan; | ||
| 1887 | |||
| 1888 | shmem_tag_pins(mapping); | ||
| 1889 | |||
| 1890 | error = 0; | ||
| 1891 | for (scan = 0; scan <= LAST_SCAN; scan++) { | ||
| 1892 | if (!radix_tree_tagged(&mapping->page_tree, SHMEM_TAG_PINNED)) | ||
| 1893 | break; | ||
| 1894 | |||
| 1895 | if (!scan) | ||
| 1896 | lru_add_drain_all(); | ||
| 1897 | else if (schedule_timeout_killable((HZ << scan) / 200)) | ||
| 1898 | scan = LAST_SCAN; | ||
| 1899 | |||
| 1900 | start = 0; | ||
| 1901 | rcu_read_lock(); | ||
| 1902 | restart: | ||
| 1903 | radix_tree_for_each_tagged(slot, &mapping->page_tree, &iter, | ||
| 1904 | start, SHMEM_TAG_PINNED) { | ||
| 1905 | |||
| 1906 | page = radix_tree_deref_slot(slot); | ||
| 1907 | if (radix_tree_exception(page)) { | ||
| 1908 | if (radix_tree_deref_retry(page)) | ||
| 1909 | goto restart; | ||
| 1910 | |||
| 1911 | page = NULL; | ||
| 1912 | } | ||
| 1913 | |||
| 1914 | if (page && | ||
| 1915 | page_count(page) - page_mapcount(page) != 1) { | ||
| 1916 | if (scan < LAST_SCAN) | ||
| 1917 | goto continue_resched; | ||
| 1918 | |||
| 1919 | /* | ||
| 1920 | * On the last scan, we clean up all those tags | ||
| 1921 | * we inserted; but make a note that we still | ||
| 1922 | * found pages pinned. | ||
| 1923 | */ | ||
| 1924 | error = -EBUSY; | ||
| 1925 | } | ||
| 1926 | |||
| 1927 | spin_lock_irq(&mapping->tree_lock); | ||
| 1928 | radix_tree_tag_clear(&mapping->page_tree, | ||
| 1929 | iter.index, SHMEM_TAG_PINNED); | ||
| 1930 | spin_unlock_irq(&mapping->tree_lock); | ||
| 1931 | continue_resched: | ||
| 1932 | if (need_resched()) { | ||
| 1933 | cond_resched_rcu(); | ||
| 1934 | start = iter.index + 1; | ||
| 1935 | goto restart; | ||
| 1936 | } | ||
| 1937 | } | ||
| 1938 | rcu_read_unlock(); | ||
| 1939 | } | ||
| 1940 | |||
| 1941 | return error; | ||
| 1942 | } | ||
| 1943 | |||
| 1944 | #define F_ALL_SEALS (F_SEAL_SEAL | \ | ||
| 1945 | F_SEAL_SHRINK | \ | ||
| 1946 | F_SEAL_GROW | \ | ||
| 1947 | F_SEAL_WRITE) | ||
| 1948 | |||
| 1949 | int shmem_add_seals(struct file *file, unsigned int seals) | ||
| 1950 | { | ||
| 1951 | struct inode *inode = file_inode(file); | ||
| 1952 | struct shmem_inode_info *info = SHMEM_I(inode); | ||
| 1953 | int error; | ||
| 1954 | |||
| 1955 | /* | ||
| 1956 | * SEALING | ||
| 1957 | * Sealing allows multiple parties to share a shmem-file but restrict | ||
| 1958 | * access to a specific subset of file operations. Seals can only be | ||
| 1959 | * added, but never removed. This way, mutually untrusted parties can | ||
| 1960 | * share common memory regions with a well-defined policy. A malicious | ||
| 1961 | * peer can thus never perform unwanted operations on a shared object. | ||
| 1962 | * | ||
| 1963 | * Seals are only supported on special shmem-files and always affect | ||
| 1964 | * the whole underlying inode. Once a seal is set, it may prevent some | ||
| 1965 | * kinds of access to the file. Currently, the following seals are | ||
| 1966 | * defined: | ||
| 1967 | * SEAL_SEAL: Prevent further seals from being set on this file | ||
| 1968 | * SEAL_SHRINK: Prevent the file from shrinking | ||
| 1969 | * SEAL_GROW: Prevent the file from growing | ||
| 1970 | * SEAL_WRITE: Prevent write access to the file | ||
| 1971 | * | ||
| 1972 | * As we don't require any trust relationship between two parties, we | ||
| 1973 | * must prevent seals from being removed. Therefore, sealing a file | ||
| 1974 | * only adds a given set of seals to the file, it never touches | ||
| 1975 | * existing seals. Furthermore, the "setting seals"-operation can be | ||
| 1976 | * sealed itself, which basically prevents any further seal from being | ||
| 1977 | * added. | ||
| 1978 | * | ||
| 1979 | * Semantics of sealing are only defined on volatile files. Only | ||
| 1980 | * anonymous shmem files support sealing. More importantly, seals are | ||
| 1981 | * never written to disk. Therefore, there's no plan to support it on | ||
| 1982 | * other file types. | ||
| 1983 | */ | ||
| 1984 | |||
| 1985 | if (file->f_op != &shmem_file_operations) | ||
| 1986 | return -EINVAL; | ||
| 1987 | if (!(file->f_mode & FMODE_WRITE)) | ||
| 1988 | return -EPERM; | ||
| 1989 | if (seals & ~(unsigned int)F_ALL_SEALS) | ||
| 1990 | return -EINVAL; | ||
| 1991 | |||
| 1992 | mutex_lock(&inode->i_mutex); | ||
| 1993 | |||
| 1994 | if (info->seals & F_SEAL_SEAL) { | ||
| 1995 | error = -EPERM; | ||
| 1996 | goto unlock; | ||
| 1997 | } | ||
| 1998 | |||
| 1999 | if ((seals & F_SEAL_WRITE) && !(info->seals & F_SEAL_WRITE)) { | ||
| 2000 | error = mapping_deny_writable(file->f_mapping); | ||
| 2001 | if (error) | ||
| 2002 | goto unlock; | ||
| 2003 | |||
| 2004 | error = shmem_wait_for_pins(file->f_mapping); | ||
| 2005 | if (error) { | ||
| 2006 | mapping_allow_writable(file->f_mapping); | ||
| 2007 | goto unlock; | ||
| 2008 | } | ||
| 2009 | } | ||
| 2010 | |||
| 2011 | info->seals |= seals; | ||
| 2012 | error = 0; | ||
| 2013 | |||
| 2014 | unlock: | ||
| 2015 | mutex_unlock(&inode->i_mutex); | ||
| 2016 | return error; | ||
| 2017 | } | ||
| 2018 | EXPORT_SYMBOL_GPL(shmem_add_seals); | ||
| 2019 | |||
| 2020 | int shmem_get_seals(struct file *file) | ||
| 2021 | { | ||
| 2022 | if (file->f_op != &shmem_file_operations) | ||
| 2023 | return -EINVAL; | ||
| 2024 | |||
| 2025 | return SHMEM_I(file_inode(file))->seals; | ||
| 2026 | } | ||
| 2027 | EXPORT_SYMBOL_GPL(shmem_get_seals); | ||
| 2028 | |||
| 2029 | long shmem_fcntl(struct file *file, unsigned int cmd, unsigned long arg) | ||
| 2030 | { | ||
| 2031 | long error; | ||
| 2032 | |||
| 2033 | switch (cmd) { | ||
| 2034 | case F_ADD_SEALS: | ||
| 2035 | /* disallow upper 32bit */ | ||
| 2036 | if (arg > UINT_MAX) | ||
| 2037 | return -EINVAL; | ||
| 2038 | |||
| 2039 | error = shmem_add_seals(file, arg); | ||
| 2040 | break; | ||
| 2041 | case F_GET_SEALS: | ||
| 2042 | error = shmem_get_seals(file); | ||
| 2043 | break; | ||
| 2044 | default: | ||
| 2045 | error = -EINVAL; | ||
| 2046 | break; | ||
| 2047 | } | ||
| 2048 | |||
| 2049 | return error; | ||
| 2050 | } | ||
| 2051 | |||
| 1806 | static long shmem_fallocate(struct file *file, int mode, loff_t offset, | 2052 | static long shmem_fallocate(struct file *file, int mode, loff_t offset, |
| 1807 | loff_t len) | 2053 | loff_t len) |
| 1808 | { | 2054 | { |
| 1809 | struct inode *inode = file_inode(file); | 2055 | struct inode *inode = file_inode(file); |
| 1810 | struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb); | 2056 | struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb); |
| 2057 | struct shmem_inode_info *info = SHMEM_I(inode); | ||
| 1811 | struct shmem_falloc shmem_falloc; | 2058 | struct shmem_falloc shmem_falloc; |
| 1812 | pgoff_t start, index, end; | 2059 | pgoff_t start, index, end; |
| 1813 | int error; | 2060 | int error; |
| @@ -1823,6 +2070,12 @@ static long shmem_fallocate(struct file *file, int mode, loff_t offset, | |||
| 1823 | loff_t unmap_end = round_down(offset + len, PAGE_SIZE) - 1; | 2070 | loff_t unmap_end = round_down(offset + len, PAGE_SIZE) - 1; |
| 1824 | DECLARE_WAIT_QUEUE_HEAD_ONSTACK(shmem_falloc_waitq); | 2071 | DECLARE_WAIT_QUEUE_HEAD_ONSTACK(shmem_falloc_waitq); |
| 1825 | 2072 | ||
| 2073 | /* protected by i_mutex */ | ||
| 2074 | if (info->seals & F_SEAL_WRITE) { | ||
| 2075 | error = -EPERM; | ||
| 2076 | goto out; | ||
| 2077 | } | ||
| 2078 | |||
| 1826 | shmem_falloc.waitq = &shmem_falloc_waitq; | 2079 | shmem_falloc.waitq = &shmem_falloc_waitq; |
| 1827 | shmem_falloc.start = unmap_start >> PAGE_SHIFT; | 2080 | shmem_falloc.start = unmap_start >> PAGE_SHIFT; |
| 1828 | shmem_falloc.next = (unmap_end + 1) >> PAGE_SHIFT; | 2081 | shmem_falloc.next = (unmap_end + 1) >> PAGE_SHIFT; |
| @@ -1849,6 +2102,11 @@ static long shmem_fallocate(struct file *file, int mode, loff_t offset, | |||
| 1849 | if (error) | 2102 | if (error) |
| 1850 | goto out; | 2103 | goto out; |
| 1851 | 2104 | ||
| 2105 | if ((info->seals & F_SEAL_GROW) && offset + len > inode->i_size) { | ||
| 2106 | error = -EPERM; | ||
| 2107 | goto out; | ||
| 2108 | } | ||
| 2109 | |||
| 1852 | start = offset >> PAGE_CACHE_SHIFT; | 2110 | start = offset >> PAGE_CACHE_SHIFT; |
| 1853 | end = (offset + len + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | 2111 | end = (offset + len + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; |
| 1854 | /* Try to avoid a swapstorm if len is impossible to satisfy */ | 2112 | /* Try to avoid a swapstorm if len is impossible to satisfy */ |
| @@ -2584,6 +2842,77 @@ static int shmem_show_options(struct seq_file *seq, struct dentry *root) | |||
| 2584 | shmem_show_mpol(seq, sbinfo->mpol); | 2842 | shmem_show_mpol(seq, sbinfo->mpol); |
| 2585 | return 0; | 2843 | return 0; |
| 2586 | } | 2844 | } |
| 2845 | |||
| 2846 | #define MFD_NAME_PREFIX "memfd:" | ||
| 2847 | #define MFD_NAME_PREFIX_LEN (sizeof(MFD_NAME_PREFIX) - 1) | ||
| 2848 | #define MFD_NAME_MAX_LEN (NAME_MAX - MFD_NAME_PREFIX_LEN) | ||
| 2849 | |||
| 2850 | #define MFD_ALL_FLAGS (MFD_CLOEXEC | MFD_ALLOW_SEALING) | ||
| 2851 | |||
| 2852 | SYSCALL_DEFINE2(memfd_create, | ||
| 2853 | const char __user *, uname, | ||
| 2854 | unsigned int, flags) | ||
| 2855 | { | ||
| 2856 | struct shmem_inode_info *info; | ||
| 2857 | struct file *file; | ||
| 2858 | int fd, error; | ||
| 2859 | char *name; | ||
| 2860 | long len; | ||
| 2861 | |||
| 2862 | if (flags & ~(unsigned int)MFD_ALL_FLAGS) | ||
| 2863 | return -EINVAL; | ||
| 2864 | |||
| 2865 | /* length includes terminating zero */ | ||
| 2866 | len = strnlen_user(uname, MFD_NAME_MAX_LEN + 1); | ||
| 2867 | if (len <= 0) | ||
| 2868 | return -EFAULT; | ||
| 2869 | if (len > MFD_NAME_MAX_LEN + 1) | ||
| 2870 | return -EINVAL; | ||
| 2871 | |||
| 2872 | name = kmalloc(len + MFD_NAME_PREFIX_LEN, GFP_TEMPORARY); | ||
| 2873 | if (!name) | ||
| 2874 | return -ENOMEM; | ||
| 2875 | |||
| 2876 | strcpy(name, MFD_NAME_PREFIX); | ||
| 2877 | if (copy_from_user(&name[MFD_NAME_PREFIX_LEN], uname, len)) { | ||
| 2878 | error = -EFAULT; | ||
| 2879 | goto err_name; | ||
| 2880 | } | ||
| 2881 | |||
| 2882 | /* terminating-zero may have changed after strnlen_user() returned */ | ||
| 2883 | if (name[len + MFD_NAME_PREFIX_LEN - 1]) { | ||
| 2884 | error = -EFAULT; | ||
| 2885 | goto err_name; | ||
| 2886 | } | ||
| 2887 | |||
| 2888 | fd = get_unused_fd_flags((flags & MFD_CLOEXEC) ? O_CLOEXEC : 0); | ||
| 2889 | if (fd < 0) { | ||
| 2890 | error = fd; | ||
| 2891 | goto err_name; | ||
| 2892 | } | ||
| 2893 | |||
| 2894 | file = shmem_file_setup(name, 0, VM_NORESERVE); | ||
| 2895 | if (IS_ERR(file)) { | ||
| 2896 | error = PTR_ERR(file); | ||
| 2897 | goto err_fd; | ||
| 2898 | } | ||
| 2899 | info = SHMEM_I(file_inode(file)); | ||
| 2900 | file->f_mode |= FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE; | ||
| 2901 | file->f_flags |= O_RDWR | O_LARGEFILE; | ||
| 2902 | if (flags & MFD_ALLOW_SEALING) | ||
| 2903 | info->seals &= ~F_SEAL_SEAL; | ||
| 2904 | |||
| 2905 | fd_install(fd, file); | ||
| 2906 | kfree(name); | ||
| 2907 | return fd; | ||
| 2908 | |||
| 2909 | err_fd: | ||
| 2910 | put_unused_fd(fd); | ||
| 2911 | err_name: | ||
| 2912 | kfree(name); | ||
| 2913 | return error; | ||
| 2914 | } | ||
| 2915 | |||
| 2587 | #endif /* CONFIG_TMPFS */ | 2916 | #endif /* CONFIG_TMPFS */ |
| 2588 | 2917 | ||
| 2589 | static void shmem_put_super(struct super_block *sb) | 2918 | static void shmem_put_super(struct super_block *sb) |
| @@ -470,6 +470,8 @@ static struct kmem_cache kmem_cache_boot = { | |||
| 470 | .name = "kmem_cache", | 470 | .name = "kmem_cache", |
| 471 | }; | 471 | }; |
| 472 | 472 | ||
| 473 | #define BAD_ALIEN_MAGIC 0x01020304ul | ||
| 474 | |||
| 473 | static DEFINE_PER_CPU(struct delayed_work, slab_reap_work); | 475 | static DEFINE_PER_CPU(struct delayed_work, slab_reap_work); |
| 474 | 476 | ||
| 475 | static inline struct array_cache *cpu_cache_get(struct kmem_cache *cachep) | 477 | static inline struct array_cache *cpu_cache_get(struct kmem_cache *cachep) |
| @@ -836,7 +838,7 @@ static int transfer_objects(struct array_cache *to, | |||
| 836 | static inline struct alien_cache **alloc_alien_cache(int node, | 838 | static inline struct alien_cache **alloc_alien_cache(int node, |
| 837 | int limit, gfp_t gfp) | 839 | int limit, gfp_t gfp) |
| 838 | { | 840 | { |
| 839 | return NULL; | 841 | return (struct alien_cache **)BAD_ALIEN_MAGIC; |
| 840 | } | 842 | } |
| 841 | 843 | ||
| 842 | static inline void free_alien_cache(struct alien_cache **ac_ptr) | 844 | static inline void free_alien_cache(struct alien_cache **ac_ptr) |
| @@ -62,6 +62,7 @@ static void __page_cache_release(struct page *page) | |||
| 62 | del_page_from_lru_list(page, lruvec, page_off_lru(page)); | 62 | del_page_from_lru_list(page, lruvec, page_off_lru(page)); |
| 63 | spin_unlock_irqrestore(&zone->lru_lock, flags); | 63 | spin_unlock_irqrestore(&zone->lru_lock, flags); |
| 64 | } | 64 | } |
| 65 | mem_cgroup_uncharge(page); | ||
| 65 | } | 66 | } |
| 66 | 67 | ||
| 67 | static void __put_single_page(struct page *page) | 68 | static void __put_single_page(struct page *page) |
| @@ -687,6 +688,40 @@ void add_page_to_unevictable_list(struct page *page) | |||
| 687 | spin_unlock_irq(&zone->lru_lock); | 688 | spin_unlock_irq(&zone->lru_lock); |
| 688 | } | 689 | } |
| 689 | 690 | ||
| 691 | /** | ||
| 692 | * lru_cache_add_active_or_unevictable | ||
| 693 | * @page: the page to be added to LRU | ||
| 694 | * @vma: vma in which page is mapped for determining reclaimability | ||
| 695 | * | ||
| 696 | * Place @page on the active or unevictable LRU list, depending on its | ||
| 697 | * evictability. Note that if the page is not evictable, it goes | ||
| 698 | * directly back onto it's zone's unevictable list, it does NOT use a | ||
| 699 | * per cpu pagevec. | ||
| 700 | */ | ||
| 701 | void lru_cache_add_active_or_unevictable(struct page *page, | ||
| 702 | struct vm_area_struct *vma) | ||
| 703 | { | ||
| 704 | VM_BUG_ON_PAGE(PageLRU(page), page); | ||
| 705 | |||
| 706 | if (likely((vma->vm_flags & (VM_LOCKED | VM_SPECIAL)) != VM_LOCKED)) { | ||
| 707 | SetPageActive(page); | ||
| 708 | lru_cache_add(page); | ||
| 709 | return; | ||
| 710 | } | ||
| 711 | |||
| 712 | if (!TestSetPageMlocked(page)) { | ||
| 713 | /* | ||
| 714 | * We use the irq-unsafe __mod_zone_page_stat because this | ||
| 715 | * counter is not modified from interrupt context, and the pte | ||
| 716 | * lock is held(spinlock), which implies preemption disabled. | ||
| 717 | */ | ||
| 718 | __mod_zone_page_state(page_zone(page), NR_MLOCK, | ||
| 719 | hpage_nr_pages(page)); | ||
| 720 | count_vm_event(UNEVICTABLE_PGMLOCKED); | ||
| 721 | } | ||
| 722 | add_page_to_unevictable_list(page); | ||
| 723 | } | ||
| 724 | |||
| 690 | /* | 725 | /* |
| 691 | * If the page can not be invalidated, it is moved to the | 726 | * If the page can not be invalidated, it is moved to the |
| 692 | * inactive list to speed up its reclaim. It is moved to the | 727 | * inactive list to speed up its reclaim. It is moved to the |
| @@ -913,6 +948,7 @@ void release_pages(struct page **pages, int nr, bool cold) | |||
| 913 | if (zone) | 948 | if (zone) |
| 914 | spin_unlock_irqrestore(&zone->lru_lock, flags); | 949 | spin_unlock_irqrestore(&zone->lru_lock, flags); |
| 915 | 950 | ||
| 951 | mem_cgroup_uncharge_list(&pages_to_free); | ||
| 916 | free_hot_cold_page_list(&pages_to_free, cold); | 952 | free_hot_cold_page_list(&pages_to_free, cold); |
| 917 | } | 953 | } |
| 918 | EXPORT_SYMBOL(release_pages); | 954 | EXPORT_SYMBOL(release_pages); |
diff --git a/mm/swap_state.c b/mm/swap_state.c index 2972eee184a4..3e0ec83d000c 100644 --- a/mm/swap_state.c +++ b/mm/swap_state.c | |||
| @@ -39,6 +39,7 @@ static struct backing_dev_info swap_backing_dev_info = { | |||
| 39 | struct address_space swapper_spaces[MAX_SWAPFILES] = { | 39 | struct address_space swapper_spaces[MAX_SWAPFILES] = { |
| 40 | [0 ... MAX_SWAPFILES - 1] = { | 40 | [0 ... MAX_SWAPFILES - 1] = { |
| 41 | .page_tree = RADIX_TREE_INIT(GFP_ATOMIC|__GFP_NOWARN), | 41 | .page_tree = RADIX_TREE_INIT(GFP_ATOMIC|__GFP_NOWARN), |
| 42 | .i_mmap_writable = ATOMIC_INIT(0), | ||
| 42 | .a_ops = &swap_aops, | 43 | .a_ops = &swap_aops, |
| 43 | .backing_dev_info = &swap_backing_dev_info, | 44 | .backing_dev_info = &swap_backing_dev_info, |
| 44 | } | 45 | } |
| @@ -176,7 +177,7 @@ int add_to_swap(struct page *page, struct list_head *list) | |||
| 176 | 177 | ||
| 177 | if (unlikely(PageTransHuge(page))) | 178 | if (unlikely(PageTransHuge(page))) |
| 178 | if (unlikely(split_huge_page_to_list(page, list))) { | 179 | if (unlikely(split_huge_page_to_list(page, list))) { |
| 179 | swapcache_free(entry, NULL); | 180 | swapcache_free(entry); |
| 180 | return 0; | 181 | return 0; |
| 181 | } | 182 | } |
| 182 | 183 | ||
| @@ -202,7 +203,7 @@ int add_to_swap(struct page *page, struct list_head *list) | |||
| 202 | * add_to_swap_cache() doesn't return -EEXIST, so we can safely | 203 | * add_to_swap_cache() doesn't return -EEXIST, so we can safely |
| 203 | * clear SWAP_HAS_CACHE flag. | 204 | * clear SWAP_HAS_CACHE flag. |
| 204 | */ | 205 | */ |
| 205 | swapcache_free(entry, NULL); | 206 | swapcache_free(entry); |
| 206 | return 0; | 207 | return 0; |
| 207 | } | 208 | } |
| 208 | } | 209 | } |
| @@ -225,7 +226,7 @@ void delete_from_swap_cache(struct page *page) | |||
| 225 | __delete_from_swap_cache(page); | 226 | __delete_from_swap_cache(page); |
| 226 | spin_unlock_irq(&address_space->tree_lock); | 227 | spin_unlock_irq(&address_space->tree_lock); |
| 227 | 228 | ||
| 228 | swapcache_free(entry, page); | 229 | swapcache_free(entry); |
| 229 | page_cache_release(page); | 230 | page_cache_release(page); |
| 230 | } | 231 | } |
| 231 | 232 | ||
| @@ -386,7 +387,7 @@ struct page *read_swap_cache_async(swp_entry_t entry, gfp_t gfp_mask, | |||
| 386 | * add_to_swap_cache() doesn't return -EEXIST, so we can safely | 387 | * add_to_swap_cache() doesn't return -EEXIST, so we can safely |
| 387 | * clear SWAP_HAS_CACHE flag. | 388 | * clear SWAP_HAS_CACHE flag. |
| 388 | */ | 389 | */ |
| 389 | swapcache_free(entry, NULL); | 390 | swapcache_free(entry); |
| 390 | } while (err != -ENOMEM); | 391 | } while (err != -ENOMEM); |
| 391 | 392 | ||
| 392 | if (new_page) | 393 | if (new_page) |
diff --git a/mm/swapfile.c b/mm/swapfile.c index 4c524f7bd0bf..8798b2e0ac59 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c | |||
| @@ -843,16 +843,13 @@ void swap_free(swp_entry_t entry) | |||
| 843 | /* | 843 | /* |
| 844 | * Called after dropping swapcache to decrease refcnt to swap entries. | 844 | * Called after dropping swapcache to decrease refcnt to swap entries. |
| 845 | */ | 845 | */ |
| 846 | void swapcache_free(swp_entry_t entry, struct page *page) | 846 | void swapcache_free(swp_entry_t entry) |
| 847 | { | 847 | { |
| 848 | struct swap_info_struct *p; | 848 | struct swap_info_struct *p; |
| 849 | unsigned char count; | ||
| 850 | 849 | ||
| 851 | p = swap_info_get(entry); | 850 | p = swap_info_get(entry); |
| 852 | if (p) { | 851 | if (p) { |
| 853 | count = swap_entry_free(p, entry, SWAP_HAS_CACHE); | 852 | swap_entry_free(p, entry, SWAP_HAS_CACHE); |
| 854 | if (page) | ||
| 855 | mem_cgroup_uncharge_swapcache(page, entry, count != 0); | ||
| 856 | spin_unlock(&p->lock); | 853 | spin_unlock(&p->lock); |
| 857 | } | 854 | } |
| 858 | } | 855 | } |
| @@ -1106,15 +1103,14 @@ static int unuse_pte(struct vm_area_struct *vma, pmd_t *pmd, | |||
| 1106 | if (unlikely(!page)) | 1103 | if (unlikely(!page)) |
| 1107 | return -ENOMEM; | 1104 | return -ENOMEM; |
| 1108 | 1105 | ||
| 1109 | if (mem_cgroup_try_charge_swapin(vma->vm_mm, page, | 1106 | if (mem_cgroup_try_charge(page, vma->vm_mm, GFP_KERNEL, &memcg)) { |
| 1110 | GFP_KERNEL, &memcg)) { | ||
| 1111 | ret = -ENOMEM; | 1107 | ret = -ENOMEM; |
| 1112 | goto out_nolock; | 1108 | goto out_nolock; |
| 1113 | } | 1109 | } |
| 1114 | 1110 | ||
| 1115 | pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); | 1111 | pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); |
| 1116 | if (unlikely(!maybe_same_pte(*pte, swp_entry_to_pte(entry)))) { | 1112 | if (unlikely(!maybe_same_pte(*pte, swp_entry_to_pte(entry)))) { |
| 1117 | mem_cgroup_cancel_charge_swapin(memcg); | 1113 | mem_cgroup_cancel_charge(page, memcg); |
| 1118 | ret = 0; | 1114 | ret = 0; |
| 1119 | goto out; | 1115 | goto out; |
| 1120 | } | 1116 | } |
| @@ -1124,11 +1120,14 @@ static int unuse_pte(struct vm_area_struct *vma, pmd_t *pmd, | |||
| 1124 | get_page(page); | 1120 | get_page(page); |
| 1125 | set_pte_at(vma->vm_mm, addr, pte, | 1121 | set_pte_at(vma->vm_mm, addr, pte, |
| 1126 | pte_mkold(mk_pte(page, vma->vm_page_prot))); | 1122 | pte_mkold(mk_pte(page, vma->vm_page_prot))); |
| 1127 | if (page == swapcache) | 1123 | if (page == swapcache) { |
| 1128 | page_add_anon_rmap(page, vma, addr); | 1124 | page_add_anon_rmap(page, vma, addr); |
| 1129 | else /* ksm created a completely new copy */ | 1125 | mem_cgroup_commit_charge(page, memcg, true); |
| 1126 | } else { /* ksm created a completely new copy */ | ||
| 1130 | page_add_new_anon_rmap(page, vma, addr); | 1127 | page_add_new_anon_rmap(page, vma, addr); |
| 1131 | mem_cgroup_commit_charge_swapin(page, memcg); | 1128 | mem_cgroup_commit_charge(page, memcg, false); |
| 1129 | lru_cache_add_active_or_unevictable(page, vma); | ||
| 1130 | } | ||
| 1132 | swap_free(entry); | 1131 | swap_free(entry); |
| 1133 | /* | 1132 | /* |
| 1134 | * Move the page to the active list so it is not | 1133 | * Move the page to the active list so it is not |
diff --git a/mm/truncate.c b/mm/truncate.c index eda247307164..96d167372d89 100644 --- a/mm/truncate.c +++ b/mm/truncate.c | |||
| @@ -281,7 +281,6 @@ void truncate_inode_pages_range(struct address_space *mapping, | |||
| 281 | while (index < end && pagevec_lookup_entries(&pvec, mapping, index, | 281 | while (index < end && pagevec_lookup_entries(&pvec, mapping, index, |
| 282 | min(end - index, (pgoff_t)PAGEVEC_SIZE), | 282 | min(end - index, (pgoff_t)PAGEVEC_SIZE), |
| 283 | indices)) { | 283 | indices)) { |
| 284 | mem_cgroup_uncharge_start(); | ||
| 285 | for (i = 0; i < pagevec_count(&pvec); i++) { | 284 | for (i = 0; i < pagevec_count(&pvec); i++) { |
| 286 | struct page *page = pvec.pages[i]; | 285 | struct page *page = pvec.pages[i]; |
| 287 | 286 | ||
| @@ -307,7 +306,6 @@ void truncate_inode_pages_range(struct address_space *mapping, | |||
| 307 | } | 306 | } |
| 308 | pagevec_remove_exceptionals(&pvec); | 307 | pagevec_remove_exceptionals(&pvec); |
| 309 | pagevec_release(&pvec); | 308 | pagevec_release(&pvec); |
| 310 | mem_cgroup_uncharge_end(); | ||
| 311 | cond_resched(); | 309 | cond_resched(); |
| 312 | index++; | 310 | index++; |
| 313 | } | 311 | } |
| @@ -369,7 +367,6 @@ void truncate_inode_pages_range(struct address_space *mapping, | |||
| 369 | pagevec_release(&pvec); | 367 | pagevec_release(&pvec); |
| 370 | break; | 368 | break; |
| 371 | } | 369 | } |
| 372 | mem_cgroup_uncharge_start(); | ||
| 373 | for (i = 0; i < pagevec_count(&pvec); i++) { | 370 | for (i = 0; i < pagevec_count(&pvec); i++) { |
| 374 | struct page *page = pvec.pages[i]; | 371 | struct page *page = pvec.pages[i]; |
| 375 | 372 | ||
| @@ -394,7 +391,6 @@ void truncate_inode_pages_range(struct address_space *mapping, | |||
| 394 | } | 391 | } |
| 395 | pagevec_remove_exceptionals(&pvec); | 392 | pagevec_remove_exceptionals(&pvec); |
| 396 | pagevec_release(&pvec); | 393 | pagevec_release(&pvec); |
| 397 | mem_cgroup_uncharge_end(); | ||
| 398 | index++; | 394 | index++; |
| 399 | } | 395 | } |
| 400 | cleancache_invalidate_inode(mapping); | 396 | cleancache_invalidate_inode(mapping); |
| @@ -493,7 +489,6 @@ unsigned long invalidate_mapping_pages(struct address_space *mapping, | |||
| 493 | while (index <= end && pagevec_lookup_entries(&pvec, mapping, index, | 489 | while (index <= end && pagevec_lookup_entries(&pvec, mapping, index, |
| 494 | min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1, | 490 | min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1, |
| 495 | indices)) { | 491 | indices)) { |
| 496 | mem_cgroup_uncharge_start(); | ||
| 497 | for (i = 0; i < pagevec_count(&pvec); i++) { | 492 | for (i = 0; i < pagevec_count(&pvec); i++) { |
| 498 | struct page *page = pvec.pages[i]; | 493 | struct page *page = pvec.pages[i]; |
| 499 | 494 | ||
| @@ -522,7 +517,6 @@ unsigned long invalidate_mapping_pages(struct address_space *mapping, | |||
| 522 | } | 517 | } |
| 523 | pagevec_remove_exceptionals(&pvec); | 518 | pagevec_remove_exceptionals(&pvec); |
| 524 | pagevec_release(&pvec); | 519 | pagevec_release(&pvec); |
| 525 | mem_cgroup_uncharge_end(); | ||
| 526 | cond_resched(); | 520 | cond_resched(); |
| 527 | index++; | 521 | index++; |
| 528 | } | 522 | } |
| @@ -553,7 +547,6 @@ invalidate_complete_page2(struct address_space *mapping, struct page *page) | |||
| 553 | BUG_ON(page_has_private(page)); | 547 | BUG_ON(page_has_private(page)); |
| 554 | __delete_from_page_cache(page, NULL); | 548 | __delete_from_page_cache(page, NULL); |
| 555 | spin_unlock_irq(&mapping->tree_lock); | 549 | spin_unlock_irq(&mapping->tree_lock); |
| 556 | mem_cgroup_uncharge_cache_page(page); | ||
| 557 | 550 | ||
| 558 | if (mapping->a_ops->freepage) | 551 | if (mapping->a_ops->freepage) |
| 559 | mapping->a_ops->freepage(page); | 552 | mapping->a_ops->freepage(page); |
| @@ -602,7 +595,6 @@ int invalidate_inode_pages2_range(struct address_space *mapping, | |||
| 602 | while (index <= end && pagevec_lookup_entries(&pvec, mapping, index, | 595 | while (index <= end && pagevec_lookup_entries(&pvec, mapping, index, |
| 603 | min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1, | 596 | min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1, |
| 604 | indices)) { | 597 | indices)) { |
| 605 | mem_cgroup_uncharge_start(); | ||
| 606 | for (i = 0; i < pagevec_count(&pvec); i++) { | 598 | for (i = 0; i < pagevec_count(&pvec); i++) { |
| 607 | struct page *page = pvec.pages[i]; | 599 | struct page *page = pvec.pages[i]; |
| 608 | 600 | ||
| @@ -655,7 +647,6 @@ int invalidate_inode_pages2_range(struct address_space *mapping, | |||
| 655 | } | 647 | } |
| 656 | pagevec_remove_exceptionals(&pvec); | 648 | pagevec_remove_exceptionals(&pvec); |
| 657 | pagevec_release(&pvec); | 649 | pagevec_release(&pvec); |
| 658 | mem_cgroup_uncharge_end(); | ||
| 659 | cond_resched(); | 650 | cond_resched(); |
| 660 | index++; | 651 | index++; |
| 661 | } | 652 | } |
| @@ -183,17 +183,14 @@ pid_t vm_is_stack(struct task_struct *task, | |||
| 183 | 183 | ||
| 184 | if (in_group) { | 184 | if (in_group) { |
| 185 | struct task_struct *t; | 185 | struct task_struct *t; |
| 186 | rcu_read_lock(); | ||
| 187 | if (!pid_alive(task)) | ||
| 188 | goto done; | ||
| 189 | 186 | ||
| 190 | t = task; | 187 | rcu_read_lock(); |
| 191 | do { | 188 | for_each_thread(task, t) { |
| 192 | if (vm_is_stack_for_task(t, vma)) { | 189 | if (vm_is_stack_for_task(t, vma)) { |
| 193 | ret = t->pid; | 190 | ret = t->pid; |
| 194 | goto done; | 191 | goto done; |
| 195 | } | 192 | } |
| 196 | } while_each_thread(task, t); | 193 | } |
| 197 | done: | 194 | done: |
| 198 | rcu_read_unlock(); | 195 | rcu_read_unlock(); |
| 199 | } | 196 | } |
diff --git a/mm/vmscan.c b/mm/vmscan.c index d2f65c856350..2836b5373b2e 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
| @@ -577,9 +577,10 @@ static int __remove_mapping(struct address_space *mapping, struct page *page, | |||
| 577 | 577 | ||
| 578 | if (PageSwapCache(page)) { | 578 | if (PageSwapCache(page)) { |
| 579 | swp_entry_t swap = { .val = page_private(page) }; | 579 | swp_entry_t swap = { .val = page_private(page) }; |
| 580 | mem_cgroup_swapout(page, swap); | ||
| 580 | __delete_from_swap_cache(page); | 581 | __delete_from_swap_cache(page); |
| 581 | spin_unlock_irq(&mapping->tree_lock); | 582 | spin_unlock_irq(&mapping->tree_lock); |
| 582 | swapcache_free(swap, page); | 583 | swapcache_free(swap); |
| 583 | } else { | 584 | } else { |
| 584 | void (*freepage)(struct page *); | 585 | void (*freepage)(struct page *); |
| 585 | void *shadow = NULL; | 586 | void *shadow = NULL; |
| @@ -600,7 +601,6 @@ static int __remove_mapping(struct address_space *mapping, struct page *page, | |||
| 600 | shadow = workingset_eviction(mapping, page); | 601 | shadow = workingset_eviction(mapping, page); |
| 601 | __delete_from_page_cache(page, shadow); | 602 | __delete_from_page_cache(page, shadow); |
| 602 | spin_unlock_irq(&mapping->tree_lock); | 603 | spin_unlock_irq(&mapping->tree_lock); |
| 603 | mem_cgroup_uncharge_cache_page(page); | ||
| 604 | 604 | ||
| 605 | if (freepage != NULL) | 605 | if (freepage != NULL) |
| 606 | freepage(page); | 606 | freepage(page); |
| @@ -822,7 +822,6 @@ static unsigned long shrink_page_list(struct list_head *page_list, | |||
| 822 | 822 | ||
| 823 | cond_resched(); | 823 | cond_resched(); |
| 824 | 824 | ||
| 825 | mem_cgroup_uncharge_start(); | ||
| 826 | while (!list_empty(page_list)) { | 825 | while (!list_empty(page_list)) { |
| 827 | struct address_space *mapping; | 826 | struct address_space *mapping; |
| 828 | struct page *page; | 827 | struct page *page; |
| @@ -1133,11 +1132,12 @@ keep: | |||
| 1133 | VM_BUG_ON_PAGE(PageLRU(page) || PageUnevictable(page), page); | 1132 | VM_BUG_ON_PAGE(PageLRU(page) || PageUnevictable(page), page); |
| 1134 | } | 1133 | } |
| 1135 | 1134 | ||
| 1135 | mem_cgroup_uncharge_list(&free_pages); | ||
| 1136 | free_hot_cold_page_list(&free_pages, true); | 1136 | free_hot_cold_page_list(&free_pages, true); |
| 1137 | 1137 | ||
| 1138 | list_splice(&ret_pages, page_list); | 1138 | list_splice(&ret_pages, page_list); |
| 1139 | count_vm_events(PGACTIVATE, pgactivate); | 1139 | count_vm_events(PGACTIVATE, pgactivate); |
| 1140 | mem_cgroup_uncharge_end(); | 1140 | |
| 1141 | *ret_nr_dirty += nr_dirty; | 1141 | *ret_nr_dirty += nr_dirty; |
| 1142 | *ret_nr_congested += nr_congested; | 1142 | *ret_nr_congested += nr_congested; |
| 1143 | *ret_nr_unqueued_dirty += nr_unqueued_dirty; | 1143 | *ret_nr_unqueued_dirty += nr_unqueued_dirty; |
| @@ -1437,6 +1437,7 @@ putback_inactive_pages(struct lruvec *lruvec, struct list_head *page_list) | |||
| 1437 | 1437 | ||
| 1438 | if (unlikely(PageCompound(page))) { | 1438 | if (unlikely(PageCompound(page))) { |
| 1439 | spin_unlock_irq(&zone->lru_lock); | 1439 | spin_unlock_irq(&zone->lru_lock); |
| 1440 | mem_cgroup_uncharge(page); | ||
| 1440 | (*get_compound_page_dtor(page))(page); | 1441 | (*get_compound_page_dtor(page))(page); |
| 1441 | spin_lock_irq(&zone->lru_lock); | 1442 | spin_lock_irq(&zone->lru_lock); |
| 1442 | } else | 1443 | } else |
| @@ -1544,6 +1545,7 @@ shrink_inactive_list(unsigned long nr_to_scan, struct lruvec *lruvec, | |||
| 1544 | 1545 | ||
| 1545 | spin_unlock_irq(&zone->lru_lock); | 1546 | spin_unlock_irq(&zone->lru_lock); |
| 1546 | 1547 | ||
| 1548 | mem_cgroup_uncharge_list(&page_list); | ||
| 1547 | free_hot_cold_page_list(&page_list, true); | 1549 | free_hot_cold_page_list(&page_list, true); |
| 1548 | 1550 | ||
| 1549 | /* | 1551 | /* |
| @@ -1658,6 +1660,7 @@ static void move_active_pages_to_lru(struct lruvec *lruvec, | |||
| 1658 | 1660 | ||
| 1659 | if (unlikely(PageCompound(page))) { | 1661 | if (unlikely(PageCompound(page))) { |
| 1660 | spin_unlock_irq(&zone->lru_lock); | 1662 | spin_unlock_irq(&zone->lru_lock); |
| 1663 | mem_cgroup_uncharge(page); | ||
| 1661 | (*get_compound_page_dtor(page))(page); | 1664 | (*get_compound_page_dtor(page))(page); |
| 1662 | spin_lock_irq(&zone->lru_lock); | 1665 | spin_lock_irq(&zone->lru_lock); |
| 1663 | } else | 1666 | } else |
| @@ -1765,6 +1768,7 @@ static void shrink_active_list(unsigned long nr_to_scan, | |||
| 1765 | __mod_zone_page_state(zone, NR_ISOLATED_ANON + file, -nr_taken); | 1768 | __mod_zone_page_state(zone, NR_ISOLATED_ANON + file, -nr_taken); |
| 1766 | spin_unlock_irq(&zone->lru_lock); | 1769 | spin_unlock_irq(&zone->lru_lock); |
| 1767 | 1770 | ||
| 1771 | mem_cgroup_uncharge_list(&l_hold); | ||
| 1768 | free_hot_cold_page_list(&l_hold, true); | 1772 | free_hot_cold_page_list(&l_hold, true); |
| 1769 | } | 1773 | } |
| 1770 | 1774 | ||
diff --git a/mm/zswap.c b/mm/zswap.c index 032c21eeab2b..ea064c1a09ba 100644 --- a/mm/zswap.c +++ b/mm/zswap.c | |||
| @@ -212,7 +212,7 @@ static int zswap_entry_cache_create(void) | |||
| 212 | return zswap_entry_cache == NULL; | 212 | return zswap_entry_cache == NULL; |
| 213 | } | 213 | } |
| 214 | 214 | ||
| 215 | static void zswap_entry_cache_destory(void) | 215 | static void __init zswap_entry_cache_destroy(void) |
| 216 | { | 216 | { |
| 217 | kmem_cache_destroy(zswap_entry_cache); | 217 | kmem_cache_destroy(zswap_entry_cache); |
| 218 | } | 218 | } |
| @@ -507,7 +507,7 @@ static int zswap_get_swap_cache_page(swp_entry_t entry, | |||
| 507 | * add_to_swap_cache() doesn't return -EEXIST, so we can safely | 507 | * add_to_swap_cache() doesn't return -EEXIST, so we can safely |
| 508 | * clear SWAP_HAS_CACHE flag. | 508 | * clear SWAP_HAS_CACHE flag. |
| 509 | */ | 509 | */ |
| 510 | swapcache_free(entry, NULL); | 510 | swapcache_free(entry); |
| 511 | } while (err != -ENOMEM); | 511 | } while (err != -ENOMEM); |
| 512 | 512 | ||
| 513 | if (new_page) | 513 | if (new_page) |
| @@ -941,7 +941,7 @@ static int __init init_zswap(void) | |||
| 941 | pcpufail: | 941 | pcpufail: |
| 942 | zswap_comp_exit(); | 942 | zswap_comp_exit(); |
| 943 | compfail: | 943 | compfail: |
| 944 | zswap_entry_cache_destory(); | 944 | zswap_entry_cache_destroy(); |
| 945 | cachefail: | 945 | cachefail: |
| 946 | zpool_destroy_pool(zswap_pool); | 946 | zpool_destroy_pool(zswap_pool); |
| 947 | error: | 947 | error: |
diff --git a/scripts/.gitignore b/scripts/.gitignore index fb070fa1038f..5ecfe93f2028 100644 --- a/scripts/.gitignore +++ b/scripts/.gitignore | |||
| @@ -4,7 +4,6 @@ | |||
| 4 | conmakehash | 4 | conmakehash |
| 5 | kallsyms | 5 | kallsyms |
| 6 | pnmtologo | 6 | pnmtologo |
| 7 | bin2c | ||
| 8 | unifdef | 7 | unifdef |
| 9 | ihex2fw | 8 | ihex2fw |
| 10 | recordmcount | 9 | recordmcount |
diff --git a/scripts/Makefile b/scripts/Makefile index 890df5c6adfb..72902b5f2721 100644 --- a/scripts/Makefile +++ b/scripts/Makefile | |||
| @@ -13,7 +13,6 @@ HOST_EXTRACFLAGS += -I$(srctree)/tools/include | |||
| 13 | hostprogs-$(CONFIG_KALLSYMS) += kallsyms | 13 | hostprogs-$(CONFIG_KALLSYMS) += kallsyms |
| 14 | hostprogs-$(CONFIG_LOGO) += pnmtologo | 14 | hostprogs-$(CONFIG_LOGO) += pnmtologo |
| 15 | hostprogs-$(CONFIG_VT) += conmakehash | 15 | hostprogs-$(CONFIG_VT) += conmakehash |
| 16 | hostprogs-$(CONFIG_IKCONFIG) += bin2c | ||
| 17 | hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount | 16 | hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount |
| 18 | hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable | 17 | hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable |
| 19 | hostprogs-$(CONFIG_ASN1) += asn1_compiler | 18 | hostprogs-$(CONFIG_ASN1) += asn1_compiler |
diff --git a/scripts/basic/.gitignore b/scripts/basic/.gitignore index a776371a3502..9528ec9e5adc 100644 --- a/scripts/basic/.gitignore +++ b/scripts/basic/.gitignore | |||
| @@ -1 +1,2 @@ | |||
| 1 | fixdep | 1 | fixdep |
| 2 | bin2c | ||
diff --git a/scripts/basic/Makefile b/scripts/basic/Makefile index 4fcef87bb875..ec10d9345bc2 100644 --- a/scripts/basic/Makefile +++ b/scripts/basic/Makefile | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | # fixdep: Used to generate dependency information during build process | 9 | # fixdep: Used to generate dependency information during build process |
| 10 | 10 | ||
| 11 | hostprogs-y := fixdep | 11 | hostprogs-y := fixdep |
| 12 | hostprogs-$(CONFIG_BUILD_BIN2C) += bin2c | ||
| 12 | always := $(hostprogs-y) | 13 | always := $(hostprogs-y) |
| 13 | 14 | ||
| 14 | # fixdep is needed to compile other host programs | 15 | # fixdep is needed to compile other host programs |
diff --git a/scripts/bin2c.c b/scripts/basic/bin2c.c index 96dd2bcbb407..af187e695345 100644 --- a/scripts/bin2c.c +++ b/scripts/basic/bin2c.c | |||
| @@ -11,7 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | int main(int argc, char *argv[]) | 12 | int main(int argc, char *argv[]) |
| 13 | { | 13 | { |
| 14 | int ch, total=0; | 14 | int ch, total = 0; |
| 15 | 15 | ||
| 16 | if (argc > 1) | 16 | if (argc > 1) |
| 17 | printf("const char %s[] %s=\n", | 17 | printf("const char %s[] %s=\n", |
| @@ -19,10 +19,9 @@ int main(int argc, char *argv[]) | |||
| 19 | 19 | ||
| 20 | do { | 20 | do { |
| 21 | printf("\t\""); | 21 | printf("\t\""); |
| 22 | while ((ch = getchar()) != EOF) | 22 | while ((ch = getchar()) != EOF) { |
| 23 | { | ||
| 24 | total++; | 23 | total++; |
| 25 | printf("\\x%02x",ch); | 24 | printf("\\x%02x", ch); |
| 26 | if (total % 16 == 0) | 25 | if (total % 16 == 0) |
| 27 | break; | 26 | break; |
| 28 | } | 27 | } |
diff --git a/scripts/checkstack.pl b/scripts/checkstack.pl index c05d586b1fee..899b4230320e 100755 --- a/scripts/checkstack.pl +++ b/scripts/checkstack.pl | |||
| @@ -52,14 +52,12 @@ my (@stack, $re, $dre, $x, $xs, $funcre); | |||
| 52 | #8000008a: 20 1d sub sp,4 | 52 | #8000008a: 20 1d sub sp,4 |
| 53 | #80000ca8: fa cd 05 b0 sub sp,sp,1456 | 53 | #80000ca8: fa cd 05 b0 sub sp,sp,1456 |
| 54 | $re = qr/^.*sub.*sp.*,([0-9]{1,8})/o; | 54 | $re = qr/^.*sub.*sp.*,([0-9]{1,8})/o; |
| 55 | } elsif ($arch =~ /^i[3456]86$/) { | 55 | } elsif ($arch =~ /^x86(_64)?$/ || $arch =~ /^i[3456]86$/) { |
| 56 | #c0105234: 81 ec ac 05 00 00 sub $0x5ac,%esp | 56 | #c0105234: 81 ec ac 05 00 00 sub $0x5ac,%esp |
| 57 | $re = qr/^.*[as][du][db] \$(0x$x{1,8}),\%esp$/o; | 57 | # or |
| 58 | $dre = qr/^.*[as][du][db] (%.*),\%esp$/o; | 58 | # 2f60: 48 81 ec e8 05 00 00 sub $0x5e8,%rsp |
| 59 | } elsif ($arch eq 'x86_64') { | 59 | $re = qr/^.*[as][du][db] \$(0x$x{1,8}),\%(e|r)sp$/o; |
| 60 | # 2f60: 48 81 ec e8 05 00 00 sub $0x5e8,%rsp | 60 | $dre = qr/^.*[as][du][db] (%.*),\%(e|r)sp$/o; |
| 61 | $re = qr/^.*[as][du][db] \$(0x$x{1,8}),\%rsp$/o; | ||
| 62 | $dre = qr/^.*[as][du][db] (\%.*),\%rsp$/o; | ||
| 63 | } elsif ($arch eq 'ia64') { | 61 | } elsif ($arch eq 'ia64') { |
| 64 | #e0000000044011fc: 01 0f fc 8c adds r12=-384,r12 | 62 | #e0000000044011fc: 01 0f fc 8c adds r12=-384,r12 |
| 65 | $re = qr/.*adds.*r12=-(([0-9]{2}|[3-9])[0-9]{2}),r12/o; | 63 | $re = qr/.*adds.*r12=-(([0-9]{2}|[3-9])[0-9]{2}),r12/o; |
diff --git a/scripts/coccinelle/free/ifnullfree.cocci b/scripts/coccinelle/free/ifnullfree.cocci new file mode 100644 index 000000000000..a42d70bf88b3 --- /dev/null +++ b/scripts/coccinelle/free/ifnullfree.cocci | |||
| @@ -0,0 +1,53 @@ | |||
| 1 | /// NULL check before some freeing functions is not needed. | ||
| 2 | /// | ||
| 3 | /// Based on checkpatch warning | ||
| 4 | /// "kfree(NULL) is safe this check is probably not required" | ||
| 5 | /// and kfreeaddr.cocci by Julia Lawall. | ||
| 6 | /// | ||
| 7 | // Copyright: (C) 2014 Fabian Frederick. GPLv2. | ||
| 8 | // Comments: - | ||
| 9 | // Options: --no-includes --include-headers | ||
| 10 | |||
| 11 | virtual patch | ||
| 12 | virtual org | ||
| 13 | virtual report | ||
| 14 | virtual context | ||
| 15 | |||
| 16 | @r2 depends on patch@ | ||
| 17 | expression E; | ||
| 18 | @@ | ||
| 19 | - if (E) | ||
| 20 | ( | ||
| 21 | - kfree(E); | ||
| 22 | + kfree(E); | ||
| 23 | | | ||
| 24 | - debugfs_remove(E); | ||
| 25 | + debugfs_remove(E); | ||
| 26 | | | ||
| 27 | - debugfs_remove_recursive(E); | ||
| 28 | + debugfs_remove_recursive(E); | ||
| 29 | | | ||
| 30 | - usb_free_urb(E); | ||
| 31 | + usb_free_urb(E); | ||
| 32 | ) | ||
| 33 | |||
| 34 | @r depends on context || report || org @ | ||
| 35 | expression E; | ||
| 36 | position p; | ||
| 37 | @@ | ||
| 38 | |||
| 39 | * if (E) | ||
| 40 | * \(kfree@p\|debugfs_remove@p\|debugfs_remove_recursive@p\|usb_free_urb\)(E); | ||
| 41 | |||
| 42 | @script:python depends on org@ | ||
| 43 | p << r.p; | ||
| 44 | @@ | ||
| 45 | |||
| 46 | cocci.print_main("NULL check before that freeing function is not needed", p) | ||
| 47 | |||
| 48 | @script:python depends on report@ | ||
| 49 | p << r.p; | ||
| 50 | @@ | ||
| 51 | |||
| 52 | msg = "WARNING: NULL check before freeing functions like kfree, debugfs_remove, debugfs_remove_recursive or usb_free_urb is not needed. Maybe consider reorganizing relevant code to avoid passing NULL values." | ||
| 53 | coccilib.report.print_report(p[0], msg) | ||
diff --git a/scripts/tags.sh b/scripts/tags.sh index e6b011fe1d0d..cbfd269a6011 100755 --- a/scripts/tags.sh +++ b/scripts/tags.sh | |||
| @@ -168,6 +168,7 @@ exuberant() | |||
| 168 | --extra=+f --c-kinds=+px \ | 168 | --extra=+f --c-kinds=+px \ |
| 169 | --regex-asm='/^(ENTRY|_GLOBAL)\(([^)]*)\).*/\2/' \ | 169 | --regex-asm='/^(ENTRY|_GLOBAL)\(([^)]*)\).*/\2/' \ |
| 170 | --regex-c='/^SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/sys_\1/' \ | 170 | --regex-c='/^SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/sys_\1/' \ |
| 171 | --regex-c='/^COMPAT_SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/compat_sys_\1/' \ | ||
| 171 | --regex-c++='/^TRACE_EVENT\(([^,)]*).*/trace_\1/' \ | 172 | --regex-c++='/^TRACE_EVENT\(([^,)]*).*/trace_\1/' \ |
| 172 | --regex-c++='/^DEFINE_EVENT\([^,)]*, *([^,)]*).*/trace_\1/' \ | 173 | --regex-c++='/^DEFINE_EVENT\([^,)]*, *([^,)]*).*/trace_\1/' \ |
| 173 | --regex-c++='/PAGEFLAG\(([^,)]*).*/Page\1/' \ | 174 | --regex-c++='/PAGEFLAG\(([^,)]*).*/Page\1/' \ |
| @@ -231,6 +232,7 @@ emacs() | |||
| 231 | all_target_sources | xargs $1 -a \ | 232 | all_target_sources | xargs $1 -a \ |
| 232 | --regex='/^\(ENTRY\|_GLOBAL\)(\([^)]*\)).*/\2/' \ | 233 | --regex='/^\(ENTRY\|_GLOBAL\)(\([^)]*\)).*/\2/' \ |
| 233 | --regex='/^SYSCALL_DEFINE[0-9]?(\([^,)]*\).*/sys_\1/' \ | 234 | --regex='/^SYSCALL_DEFINE[0-9]?(\([^,)]*\).*/sys_\1/' \ |
| 235 | --regex='/^COMPAT_SYSCALL_DEFINE[0-9]?(\([^,)]*\).*/compat_sys_\1/' \ | ||
| 234 | --regex='/^TRACE_EVENT(\([^,)]*\).*/trace_\1/' \ | 236 | --regex='/^TRACE_EVENT(\([^,)]*\).*/trace_\1/' \ |
| 235 | --regex='/^DEFINE_EVENT([^,)]*, *\([^,)]*\).*/trace_\1/' \ | 237 | --regex='/^DEFINE_EVENT([^,)]*, *\([^,)]*\).*/trace_\1/' \ |
| 236 | --regex='/PAGEFLAG(\([^,)]*\).*/Page\1/' \ | 238 | --regex='/PAGEFLAG(\([^,)]*\).*/Page\1/' \ |
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index d10f95ce2ea4..6fd2a4402069 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile | |||
| @@ -2,6 +2,7 @@ TARGETS = breakpoints | |||
| 2 | TARGETS += cpu-hotplug | 2 | TARGETS += cpu-hotplug |
| 3 | TARGETS += efivarfs | 3 | TARGETS += efivarfs |
| 4 | TARGETS += kcmp | 4 | TARGETS += kcmp |
| 5 | TARGETS += memfd | ||
| 5 | TARGETS += memory-hotplug | 6 | TARGETS += memory-hotplug |
| 6 | TARGETS += mqueue | 7 | TARGETS += mqueue |
| 7 | TARGETS += net | 8 | TARGETS += net |
diff --git a/tools/testing/selftests/memfd/.gitignore b/tools/testing/selftests/memfd/.gitignore new file mode 100644 index 000000000000..afe87c40ac80 --- /dev/null +++ b/tools/testing/selftests/memfd/.gitignore | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | fuse_mnt | ||
| 2 | fuse_test | ||
| 3 | memfd_test | ||
| 4 | memfd-test-file | ||
diff --git a/tools/testing/selftests/memfd/Makefile b/tools/testing/selftests/memfd/Makefile new file mode 100644 index 000000000000..6816c491c5ff --- /dev/null +++ b/tools/testing/selftests/memfd/Makefile | |||
| @@ -0,0 +1,41 @@ | |||
| 1 | uname_M := $(shell uname -m 2>/dev/null || echo not) | ||
| 2 | ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/) | ||
| 3 | ifeq ($(ARCH),i386) | ||
| 4 | ARCH := X86 | ||
| 5 | endif | ||
| 6 | ifeq ($(ARCH),x86_64) | ||
| 7 | ARCH := X86 | ||
| 8 | endif | ||
| 9 | |||
| 10 | CFLAGS += -D_FILE_OFFSET_BITS=64 | ||
| 11 | CFLAGS += -I../../../../arch/x86/include/generated/uapi/ | ||
| 12 | CFLAGS += -I../../../../arch/x86/include/uapi/ | ||
| 13 | CFLAGS += -I../../../../include/uapi/ | ||
| 14 | CFLAGS += -I../../../../include/ | ||
| 15 | |||
| 16 | all: | ||
| 17 | ifeq ($(ARCH),X86) | ||
| 18 | gcc $(CFLAGS) memfd_test.c -o memfd_test | ||
| 19 | else | ||
| 20 | echo "Not an x86 target, can't build memfd selftest" | ||
| 21 | endif | ||
| 22 | |||
| 23 | run_tests: all | ||
| 24 | ifeq ($(ARCH),X86) | ||
| 25 | gcc $(CFLAGS) memfd_test.c -o memfd_test | ||
| 26 | endif | ||
| 27 | @./memfd_test || echo "memfd_test: [FAIL]" | ||
| 28 | |||
| 29 | build_fuse: | ||
| 30 | ifeq ($(ARCH),X86) | ||
| 31 | gcc $(CFLAGS) fuse_mnt.c `pkg-config fuse --cflags --libs` -o fuse_mnt | ||
| 32 | gcc $(CFLAGS) fuse_test.c -o fuse_test | ||
| 33 | else | ||
| 34 | echo "Not an x86 target, can't build memfd selftest" | ||
| 35 | endif | ||
| 36 | |||
| 37 | run_fuse: build_fuse | ||
| 38 | @./run_fuse_test.sh || echo "fuse_test: [FAIL]" | ||
| 39 | |||
| 40 | clean: | ||
| 41 | $(RM) memfd_test fuse_test | ||
diff --git a/tools/testing/selftests/memfd/fuse_mnt.c b/tools/testing/selftests/memfd/fuse_mnt.c new file mode 100644 index 000000000000..feacf1280fcd --- /dev/null +++ b/tools/testing/selftests/memfd/fuse_mnt.c | |||
| @@ -0,0 +1,110 @@ | |||
| 1 | /* | ||
| 2 | * memfd test file-system | ||
| 3 | * This file uses FUSE to create a dummy file-system with only one file /memfd. | ||
| 4 | * This file is read-only and takes 1s per read. | ||
| 5 | * | ||
| 6 | * This file-system is used by the memfd test-cases to force the kernel to pin | ||
| 7 | * pages during reads(). Due to the 1s delay of this file-system, this is a | ||
| 8 | * nice way to test race-conditions against get_user_pages() in the kernel. | ||
| 9 | * | ||
| 10 | * We use direct_io==1 to force the kernel to use direct-IO for this | ||
| 11 | * file-system. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #define FUSE_USE_VERSION 26 | ||
| 15 | |||
| 16 | #include <fuse.h> | ||
| 17 | #include <stdio.h> | ||
| 18 | #include <string.h> | ||
| 19 | #include <errno.h> | ||
| 20 | #include <fcntl.h> | ||
| 21 | #include <unistd.h> | ||
| 22 | |||
| 23 | static const char memfd_content[] = "memfd-example-content"; | ||
| 24 | static const char memfd_path[] = "/memfd"; | ||
| 25 | |||
| 26 | static int memfd_getattr(const char *path, struct stat *st) | ||
| 27 | { | ||
| 28 | memset(st, 0, sizeof(*st)); | ||
| 29 | |||
| 30 | if (!strcmp(path, "/")) { | ||
| 31 | st->st_mode = S_IFDIR | 0755; | ||
| 32 | st->st_nlink = 2; | ||
| 33 | } else if (!strcmp(path, memfd_path)) { | ||
| 34 | st->st_mode = S_IFREG | 0444; | ||
| 35 | st->st_nlink = 1; | ||
| 36 | st->st_size = strlen(memfd_content); | ||
| 37 | } else { | ||
| 38 | return -ENOENT; | ||
| 39 | } | ||
| 40 | |||
| 41 | return 0; | ||
| 42 | } | ||
| 43 | |||
| 44 | static int memfd_readdir(const char *path, | ||
| 45 | void *buf, | ||
| 46 | fuse_fill_dir_t filler, | ||
| 47 | off_t offset, | ||
| 48 | struct fuse_file_info *fi) | ||
| 49 | { | ||
| 50 | if (strcmp(path, "/")) | ||
| 51 | return -ENOENT; | ||
| 52 | |||
| 53 | filler(buf, ".", NULL, 0); | ||
| 54 | filler(buf, "..", NULL, 0); | ||
| 55 | filler(buf, memfd_path + 1, NULL, 0); | ||
| 56 | |||
| 57 | return 0; | ||
| 58 | } | ||
| 59 | |||
| 60 | static int memfd_open(const char *path, struct fuse_file_info *fi) | ||
| 61 | { | ||
| 62 | if (strcmp(path, memfd_path)) | ||
| 63 | return -ENOENT; | ||
| 64 | |||
| 65 | if ((fi->flags & 3) != O_RDONLY) | ||
| 66 | return -EACCES; | ||
| 67 | |||
| 68 | /* force direct-IO */ | ||
| 69 | fi->direct_io = 1; | ||
| 70 | |||
| 71 | return 0; | ||
| 72 | } | ||
| 73 | |||
| 74 | static int memfd_read(const char *path, | ||
| 75 | char *buf, | ||
| 76 | size_t size, | ||
| 77 | off_t offset, | ||
| 78 | struct fuse_file_info *fi) | ||
| 79 | { | ||
| 80 | size_t len; | ||
| 81 | |||
| 82 | if (strcmp(path, memfd_path) != 0) | ||
| 83 | return -ENOENT; | ||
| 84 | |||
| 85 | sleep(1); | ||
| 86 | |||
| 87 | len = strlen(memfd_content); | ||
| 88 | if (offset < len) { | ||
| 89 | if (offset + size > len) | ||
| 90 | size = len - offset; | ||
| 91 | |||
| 92 | memcpy(buf, memfd_content + offset, size); | ||
| 93 | } else { | ||
| 94 | size = 0; | ||
| 95 | } | ||
| 96 | |||
| 97 | return size; | ||
| 98 | } | ||
| 99 | |||
| 100 | static struct fuse_operations memfd_ops = { | ||
| 101 | .getattr = memfd_getattr, | ||
| 102 | .readdir = memfd_readdir, | ||
| 103 | .open = memfd_open, | ||
| 104 | .read = memfd_read, | ||
| 105 | }; | ||
| 106 | |||
| 107 | int main(int argc, char *argv[]) | ||
| 108 | { | ||
| 109 | return fuse_main(argc, argv, &memfd_ops, NULL); | ||
| 110 | } | ||
diff --git a/tools/testing/selftests/memfd/fuse_test.c b/tools/testing/selftests/memfd/fuse_test.c new file mode 100644 index 000000000000..67908b18f035 --- /dev/null +++ b/tools/testing/selftests/memfd/fuse_test.c | |||
| @@ -0,0 +1,311 @@ | |||
| 1 | /* | ||
| 2 | * memfd GUP test-case | ||
| 3 | * This tests memfd interactions with get_user_pages(). We require the | ||
| 4 | * fuse_mnt.c program to provide a fake direct-IO FUSE mount-point for us. This | ||
| 5 | * file-system delays _all_ reads by 1s and forces direct-IO. This means, any | ||
| 6 | * read() on files in that file-system will pin the receive-buffer pages for at | ||
| 7 | * least 1s via get_user_pages(). | ||
| 8 | * | ||
| 9 | * We use this trick to race ADD_SEALS against a write on a memfd object. The | ||
| 10 | * ADD_SEALS must fail if the memfd pages are still pinned. Note that we use | ||
| 11 | * the read() syscall with our memory-mapped memfd object as receive buffer to | ||
| 12 | * force the kernel to write into our memfd object. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #define _GNU_SOURCE | ||
| 16 | #define __EXPORTED_HEADERS__ | ||
| 17 | |||
| 18 | #include <errno.h> | ||
| 19 | #include <inttypes.h> | ||
| 20 | #include <limits.h> | ||
| 21 | #include <linux/falloc.h> | ||
| 22 | #include <linux/fcntl.h> | ||
| 23 | #include <linux/memfd.h> | ||
| 24 | #include <sched.h> | ||
| 25 | #include <stdio.h> | ||
| 26 | #include <stdlib.h> | ||
| 27 | #include <signal.h> | ||
| 28 | #include <string.h> | ||
| 29 | #include <sys/mman.h> | ||
| 30 | #include <sys/stat.h> | ||
| 31 | #include <sys/syscall.h> | ||
| 32 | #include <sys/wait.h> | ||
| 33 | #include <unistd.h> | ||
| 34 | |||
| 35 | #define MFD_DEF_SIZE 8192 | ||
| 36 | #define STACK_SIZE 65535 | ||
| 37 | |||
| 38 | static int sys_memfd_create(const char *name, | ||
| 39 | unsigned int flags) | ||
| 40 | { | ||
| 41 | return syscall(__NR_memfd_create, name, flags); | ||
| 42 | } | ||
| 43 | |||
| 44 | static int mfd_assert_new(const char *name, loff_t sz, unsigned int flags) | ||
| 45 | { | ||
| 46 | int r, fd; | ||
| 47 | |||
| 48 | fd = sys_memfd_create(name, flags); | ||
| 49 | if (fd < 0) { | ||
| 50 | printf("memfd_create(\"%s\", %u) failed: %m\n", | ||
| 51 | name, flags); | ||
| 52 | abort(); | ||
| 53 | } | ||
| 54 | |||
| 55 | r = ftruncate(fd, sz); | ||
| 56 | if (r < 0) { | ||
| 57 | printf("ftruncate(%llu) failed: %m\n", (unsigned long long)sz); | ||
| 58 | abort(); | ||
| 59 | } | ||
| 60 | |||
| 61 | return fd; | ||
| 62 | } | ||
| 63 | |||
| 64 | static __u64 mfd_assert_get_seals(int fd) | ||
| 65 | { | ||
| 66 | long r; | ||
| 67 | |||
| 68 | r = fcntl(fd, F_GET_SEALS); | ||
| 69 | if (r < 0) { | ||
| 70 | printf("GET_SEALS(%d) failed: %m\n", fd); | ||
| 71 | abort(); | ||
| 72 | } | ||
| 73 | |||
| 74 | return r; | ||
| 75 | } | ||
| 76 | |||
| 77 | static void mfd_assert_has_seals(int fd, __u64 seals) | ||
| 78 | { | ||
| 79 | __u64 s; | ||
| 80 | |||
| 81 | s = mfd_assert_get_seals(fd); | ||
| 82 | if (s != seals) { | ||
| 83 | printf("%llu != %llu = GET_SEALS(%d)\n", | ||
| 84 | (unsigned long long)seals, (unsigned long long)s, fd); | ||
| 85 | abort(); | ||
| 86 | } | ||
| 87 | } | ||
| 88 | |||
| 89 | static void mfd_assert_add_seals(int fd, __u64 seals) | ||
| 90 | { | ||
| 91 | long r; | ||
| 92 | __u64 s; | ||
| 93 | |||
| 94 | s = mfd_assert_get_seals(fd); | ||
| 95 | r = fcntl(fd, F_ADD_SEALS, seals); | ||
| 96 | if (r < 0) { | ||
| 97 | printf("ADD_SEALS(%d, %llu -> %llu) failed: %m\n", | ||
| 98 | fd, (unsigned long long)s, (unsigned long long)seals); | ||
| 99 | abort(); | ||
| 100 | } | ||
| 101 | } | ||
| 102 | |||
| 103 | static int mfd_busy_add_seals(int fd, __u64 seals) | ||
| 104 | { | ||
| 105 | long r; | ||
| 106 | __u64 s; | ||
| 107 | |||
| 108 | r = fcntl(fd, F_GET_SEALS); | ||
| 109 | if (r < 0) | ||
| 110 | s = 0; | ||
| 111 | else | ||
| 112 | s = r; | ||
| 113 | |||
| 114 | r = fcntl(fd, F_ADD_SEALS, seals); | ||
| 115 | if (r < 0 && errno != EBUSY) { | ||
| 116 | printf("ADD_SEALS(%d, %llu -> %llu) didn't fail as expected with EBUSY: %m\n", | ||
| 117 | fd, (unsigned long long)s, (unsigned long long)seals); | ||
| 118 | abort(); | ||
| 119 | } | ||
| 120 | |||
| 121 | return r; | ||
| 122 | } | ||
| 123 | |||
| 124 | static void *mfd_assert_mmap_shared(int fd) | ||
| 125 | { | ||
| 126 | void *p; | ||
| 127 | |||
| 128 | p = mmap(NULL, | ||
| 129 | MFD_DEF_SIZE, | ||
| 130 | PROT_READ | PROT_WRITE, | ||
| 131 | MAP_SHARED, | ||
| 132 | fd, | ||
| 133 | 0); | ||
| 134 | if (p == MAP_FAILED) { | ||
| 135 | printf("mmap() failed: %m\n"); | ||
| 136 | abort(); | ||
| 137 | } | ||
| 138 | |||
| 139 | return p; | ||
| 140 | } | ||
| 141 | |||
| 142 | static void *mfd_assert_mmap_private(int fd) | ||
| 143 | { | ||
| 144 | void *p; | ||
| 145 | |||
| 146 | p = mmap(NULL, | ||
| 147 | MFD_DEF_SIZE, | ||
| 148 | PROT_READ | PROT_WRITE, | ||
| 149 | MAP_PRIVATE, | ||
| 150 | fd, | ||
| 151 | 0); | ||
| 152 | if (p == MAP_FAILED) { | ||
| 153 | printf("mmap() failed: %m\n"); | ||
| 154 | abort(); | ||
| 155 | } | ||
| 156 | |||
| 157 | return p; | ||
| 158 | } | ||
| 159 | |||
| 160 | static int global_mfd = -1; | ||
| 161 | static void *global_p = NULL; | ||
| 162 | |||
| 163 | static int sealing_thread_fn(void *arg) | ||
| 164 | { | ||
| 165 | int sig, r; | ||
| 166 | |||
| 167 | /* | ||
| 168 | * This thread first waits 200ms so any pending operation in the parent | ||
| 169 | * is correctly started. After that, it tries to seal @global_mfd as | ||
| 170 | * SEAL_WRITE. This _must_ fail as the parent thread has a read() into | ||
| 171 | * that memory mapped object still ongoing. | ||
| 172 | * We then wait one more second and try sealing again. This time it | ||
| 173 | * must succeed as there shouldn't be anyone else pinning the pages. | ||
| 174 | */ | ||
| 175 | |||
| 176 | /* wait 200ms for FUSE-request to be active */ | ||
| 177 | usleep(200000); | ||
| 178 | |||
| 179 | /* unmount mapping before sealing to avoid i_mmap_writable failures */ | ||
| 180 | munmap(global_p, MFD_DEF_SIZE); | ||
| 181 | |||
| 182 | /* Try sealing the global file; expect EBUSY or success. Current | ||
| 183 | * kernels will never succeed, but in the future, kernels might | ||
| 184 | * implement page-replacements or other fancy ways to avoid racing | ||
| 185 | * writes. */ | ||
| 186 | r = mfd_busy_add_seals(global_mfd, F_SEAL_WRITE); | ||
| 187 | if (r >= 0) { | ||
| 188 | printf("HURRAY! This kernel fixed GUP races!\n"); | ||
| 189 | } else { | ||
| 190 | /* wait 1s more so the FUSE-request is done */ | ||
| 191 | sleep(1); | ||
| 192 | |||
| 193 | /* try sealing the global file again */ | ||
| 194 | mfd_assert_add_seals(global_mfd, F_SEAL_WRITE); | ||
| 195 | } | ||
| 196 | |||
| 197 | return 0; | ||
| 198 | } | ||
| 199 | |||
| 200 | static pid_t spawn_sealing_thread(void) | ||
| 201 | { | ||
| 202 | uint8_t *stack; | ||
| 203 | pid_t pid; | ||
| 204 | |||
| 205 | stack = malloc(STACK_SIZE); | ||
| 206 | if (!stack) { | ||
| 207 | printf("malloc(STACK_SIZE) failed: %m\n"); | ||
| 208 | abort(); | ||
| 209 | } | ||
| 210 | |||
| 211 | pid = clone(sealing_thread_fn, | ||
| 212 | stack + STACK_SIZE, | ||
| 213 | SIGCHLD | CLONE_FILES | CLONE_FS | CLONE_VM, | ||
| 214 | NULL); | ||
| 215 | if (pid < 0) { | ||
| 216 | printf("clone() failed: %m\n"); | ||
| 217 | abort(); | ||
| 218 | } | ||
| 219 | |||
| 220 | return pid; | ||
| 221 | } | ||
| 222 | |||
| 223 | static void join_sealing_thread(pid_t pid) | ||
| 224 | { | ||
| 225 | waitpid(pid, NULL, 0); | ||
| 226 | } | ||
| 227 | |||
| 228 | int main(int argc, char **argv) | ||
| 229 | { | ||
| 230 | static const char zero[MFD_DEF_SIZE]; | ||
| 231 | int fd, mfd, r; | ||
| 232 | void *p; | ||
| 233 | int was_sealed; | ||
| 234 | pid_t pid; | ||
| 235 | |||
| 236 | if (argc < 2) { | ||
| 237 | printf("error: please pass path to file in fuse_mnt mount-point\n"); | ||
| 238 | abort(); | ||
| 239 | } | ||
| 240 | |||
| 241 | /* open FUSE memfd file for GUP testing */ | ||
| 242 | printf("opening: %s\n", argv[1]); | ||
| 243 | fd = open(argv[1], O_RDONLY | O_CLOEXEC); | ||
| 244 | if (fd < 0) { | ||
| 245 | printf("cannot open(\"%s\"): %m\n", argv[1]); | ||
| 246 | abort(); | ||
| 247 | } | ||
| 248 | |||
| 249 | /* create new memfd-object */ | ||
| 250 | mfd = mfd_assert_new("kern_memfd_fuse", | ||
| 251 | MFD_DEF_SIZE, | ||
| 252 | MFD_CLOEXEC | MFD_ALLOW_SEALING); | ||
| 253 | |||
| 254 | /* mmap memfd-object for writing */ | ||
| 255 | p = mfd_assert_mmap_shared(mfd); | ||
| 256 | |||
| 257 | /* pass mfd+mapping to a separate sealing-thread which tries to seal | ||
| 258 | * the memfd objects with SEAL_WRITE while we write into it */ | ||
| 259 | global_mfd = mfd; | ||
| 260 | global_p = p; | ||
| 261 | pid = spawn_sealing_thread(); | ||
| 262 | |||
| 263 | /* Use read() on the FUSE file to read into our memory-mapped memfd | ||
| 264 | * object. This races the other thread which tries to seal the | ||
| 265 | * memfd-object. | ||
| 266 | * If @fd is on the memfd-fake-FUSE-FS, the read() is delayed by 1s. | ||
| 267 | * This guarantees that the receive-buffer is pinned for 1s until the | ||
| 268 | * data is written into it. The racing ADD_SEALS should thus fail as | ||
| 269 | * the pages are still pinned. */ | ||
| 270 | r = read(fd, p, MFD_DEF_SIZE); | ||
| 271 | if (r < 0) { | ||
| 272 | printf("read() failed: %m\n"); | ||
| 273 | abort(); | ||
| 274 | } else if (!r) { | ||
| 275 | printf("unexpected EOF on read()\n"); | ||
| 276 | abort(); | ||
| 277 | } | ||
| 278 | |||
| 279 | was_sealed = mfd_assert_get_seals(mfd) & F_SEAL_WRITE; | ||
| 280 | |||
| 281 | /* Wait for sealing-thread to finish and verify that it | ||
| 282 | * successfully sealed the file after the second try. */ | ||
| 283 | join_sealing_thread(pid); | ||
| 284 | mfd_assert_has_seals(mfd, F_SEAL_WRITE); | ||
| 285 | |||
| 286 | /* *IF* the memfd-object was sealed at the time our read() returned, | ||
| 287 | * then the kernel did a page-replacement or canceled the read() (or | ||
| 288 | * whatever magic it did..). In that case, the memfd object is still | ||
| 289 | * all zero. | ||
| 290 | * In case the memfd-object was *not* sealed, the read() was successfull | ||
| 291 | * and the memfd object must *not* be all zero. | ||
| 292 | * Note that in real scenarios, there might be a mixture of both, but | ||
| 293 | * in this test-cases, we have explicit 200ms delays which should be | ||
| 294 | * enough to avoid any in-flight writes. */ | ||
| 295 | |||
| 296 | p = mfd_assert_mmap_private(mfd); | ||
| 297 | if (was_sealed && memcmp(p, zero, MFD_DEF_SIZE)) { | ||
| 298 | printf("memfd sealed during read() but data not discarded\n"); | ||
| 299 | abort(); | ||
| 300 | } else if (!was_sealed && !memcmp(p, zero, MFD_DEF_SIZE)) { | ||
| 301 | printf("memfd sealed after read() but data discarded\n"); | ||
| 302 | abort(); | ||
| 303 | } | ||
| 304 | |||
| 305 | close(mfd); | ||
| 306 | close(fd); | ||
| 307 | |||
| 308 | printf("fuse: DONE\n"); | ||
| 309 | |||
| 310 | return 0; | ||
| 311 | } | ||
diff --git a/tools/testing/selftests/memfd/memfd_test.c b/tools/testing/selftests/memfd/memfd_test.c new file mode 100644 index 000000000000..3634c909b1b0 --- /dev/null +++ b/tools/testing/selftests/memfd/memfd_test.c | |||
| @@ -0,0 +1,913 @@ | |||
| 1 | #define _GNU_SOURCE | ||
| 2 | #define __EXPORTED_HEADERS__ | ||
| 3 | |||
| 4 | #include <errno.h> | ||
| 5 | #include <inttypes.h> | ||
| 6 | #include <limits.h> | ||
| 7 | #include <linux/falloc.h> | ||
| 8 | #include <linux/fcntl.h> | ||
| 9 | #include <linux/memfd.h> | ||
| 10 | #include <sched.h> | ||
| 11 | #include <stdio.h> | ||
| 12 | #include <stdlib.h> | ||
| 13 | #include <signal.h> | ||
| 14 | #include <string.h> | ||
| 15 | #include <sys/mman.h> | ||
| 16 | #include <sys/stat.h> | ||
| 17 | #include <sys/syscall.h> | ||
| 18 | #include <unistd.h> | ||
| 19 | |||
| 20 | #define MFD_DEF_SIZE 8192 | ||
| 21 | #define STACK_SIZE 65535 | ||
| 22 | |||
| 23 | static int sys_memfd_create(const char *name, | ||
| 24 | unsigned int flags) | ||
| 25 | { | ||
| 26 | return syscall(__NR_memfd_create, name, flags); | ||
| 27 | } | ||
| 28 | |||
| 29 | static int mfd_assert_new(const char *name, loff_t sz, unsigned int flags) | ||
| 30 | { | ||
| 31 | int r, fd; | ||
| 32 | |||
| 33 | fd = sys_memfd_create(name, flags); | ||
| 34 | if (fd < 0) { | ||
| 35 | printf("memfd_create(\"%s\", %u) failed: %m\n", | ||
| 36 | name, flags); | ||
| 37 | abort(); | ||
| 38 | } | ||
| 39 | |||
| 40 | r = ftruncate(fd, sz); | ||
| 41 | if (r < 0) { | ||
| 42 | printf("ftruncate(%llu) failed: %m\n", (unsigned long long)sz); | ||
| 43 | abort(); | ||
| 44 | } | ||
| 45 | |||
| 46 | return fd; | ||
| 47 | } | ||
| 48 | |||
| 49 | static void mfd_fail_new(const char *name, unsigned int flags) | ||
| 50 | { | ||
| 51 | int r; | ||
| 52 | |||
| 53 | r = sys_memfd_create(name, flags); | ||
| 54 | if (r >= 0) { | ||
| 55 | printf("memfd_create(\"%s\", %u) succeeded, but failure expected\n", | ||
| 56 | name, flags); | ||
| 57 | close(r); | ||
| 58 | abort(); | ||
| 59 | } | ||
| 60 | } | ||
| 61 | |||
| 62 | static __u64 mfd_assert_get_seals(int fd) | ||
| 63 | { | ||
| 64 | long r; | ||
| 65 | |||
| 66 | r = fcntl(fd, F_GET_SEALS); | ||
| 67 | if (r < 0) { | ||
| 68 | printf("GET_SEALS(%d) failed: %m\n", fd); | ||
| 69 | abort(); | ||
| 70 | } | ||
| 71 | |||
| 72 | return r; | ||
| 73 | } | ||
| 74 | |||
| 75 | static void mfd_assert_has_seals(int fd, __u64 seals) | ||
| 76 | { | ||
| 77 | __u64 s; | ||
| 78 | |||
| 79 | s = mfd_assert_get_seals(fd); | ||
| 80 | if (s != seals) { | ||
| 81 | printf("%llu != %llu = GET_SEALS(%d)\n", | ||
| 82 | (unsigned long long)seals, (unsigned long long)s, fd); | ||
| 83 | abort(); | ||
| 84 | } | ||
| 85 | } | ||
| 86 | |||
| 87 | static void mfd_assert_add_seals(int fd, __u64 seals) | ||
| 88 | { | ||
| 89 | long r; | ||
| 90 | __u64 s; | ||
| 91 | |||
| 92 | s = mfd_assert_get_seals(fd); | ||
| 93 | r = fcntl(fd, F_ADD_SEALS, seals); | ||
| 94 | if (r < 0) { | ||
| 95 | printf("ADD_SEALS(%d, %llu -> %llu) failed: %m\n", | ||
| 96 | fd, (unsigned long long)s, (unsigned long long)seals); | ||
| 97 | abort(); | ||
| 98 | } | ||
| 99 | } | ||
| 100 | |||
| 101 | static void mfd_fail_add_seals(int fd, __u64 seals) | ||
| 102 | { | ||
| 103 | long r; | ||
| 104 | __u64 s; | ||
| 105 | |||
| 106 | r = fcntl(fd, F_GET_SEALS); | ||
| 107 | if (r < 0) | ||
| 108 | s = 0; | ||
| 109 | else | ||
| 110 | s = r; | ||
| 111 | |||
| 112 | r = fcntl(fd, F_ADD_SEALS, seals); | ||
| 113 | if (r >= 0) { | ||
| 114 | printf("ADD_SEALS(%d, %llu -> %llu) didn't fail as expected\n", | ||
| 115 | fd, (unsigned long long)s, (unsigned long long)seals); | ||
| 116 | abort(); | ||
| 117 | } | ||
| 118 | } | ||
| 119 | |||
| 120 | static void mfd_assert_size(int fd, size_t size) | ||
| 121 | { | ||
| 122 | struct stat st; | ||
| 123 | int r; | ||
| 124 | |||
| 125 | r = fstat(fd, &st); | ||
| 126 | if (r < 0) { | ||
| 127 | printf("fstat(%d) failed: %m\n", fd); | ||
| 128 | abort(); | ||
| 129 | } else if (st.st_size != size) { | ||
| 130 | printf("wrong file size %lld, but expected %lld\n", | ||
| 131 | (long long)st.st_size, (long long)size); | ||
| 132 | abort(); | ||
| 133 | } | ||
| 134 | } | ||
| 135 | |||
| 136 | static int mfd_assert_dup(int fd) | ||
| 137 | { | ||
| 138 | int r; | ||
| 139 | |||
| 140 | r = dup(fd); | ||
| 141 | if (r < 0) { | ||
| 142 | printf("dup(%d) failed: %m\n", fd); | ||
| 143 | abort(); | ||
| 144 | } | ||
| 145 | |||
| 146 | return r; | ||
| 147 | } | ||
| 148 | |||
| 149 | static void *mfd_assert_mmap_shared(int fd) | ||
| 150 | { | ||
| 151 | void *p; | ||
| 152 | |||
| 153 | p = mmap(NULL, | ||
| 154 | MFD_DEF_SIZE, | ||
| 155 | PROT_READ | PROT_WRITE, | ||
| 156 | MAP_SHARED, | ||
| 157 | fd, | ||
| 158 | 0); | ||
| 159 | if (p == MAP_FAILED) { | ||
| 160 | printf("mmap() failed: %m\n"); | ||
| 161 | abort(); | ||
| 162 | } | ||
| 163 | |||
| 164 | return p; | ||
| 165 | } | ||
| 166 | |||
| 167 | static void *mfd_assert_mmap_private(int fd) | ||
| 168 | { | ||
| 169 | void *p; | ||
| 170 | |||
| 171 | p = mmap(NULL, | ||
| 172 | MFD_DEF_SIZE, | ||
| 173 | PROT_READ, | ||
| 174 | MAP_PRIVATE, | ||
| 175 | fd, | ||
| 176 | 0); | ||
| 177 | if (p == MAP_FAILED) { | ||
| 178 | printf("mmap() failed: %m\n"); | ||
| 179 | abort(); | ||
| 180 | } | ||
| 181 | |||
| 182 | return p; | ||
| 183 | } | ||
| 184 | |||
| 185 | static int mfd_assert_open(int fd, int flags, mode_t mode) | ||
| 186 | { | ||
| 187 | char buf[512]; | ||
| 188 | int r; | ||
| 189 | |||
| 190 | sprintf(buf, "/proc/self/fd/%d", fd); | ||
| 191 | r = open(buf, flags, mode); | ||
| 192 | if (r < 0) { | ||
| 193 | printf("open(%s) failed: %m\n", buf); | ||
| 194 | abort(); | ||
| 195 | } | ||
| 196 | |||
| 197 | return r; | ||
| 198 | } | ||
| 199 | |||
| 200 | static void mfd_fail_open(int fd, int flags, mode_t mode) | ||
| 201 | { | ||
| 202 | char buf[512]; | ||
| 203 | int r; | ||
| 204 | |||
| 205 | sprintf(buf, "/proc/self/fd/%d", fd); | ||
| 206 | r = open(buf, flags, mode); | ||
| 207 | if (r >= 0) { | ||
| 208 | printf("open(%s) didn't fail as expected\n"); | ||
| 209 | abort(); | ||
| 210 | } | ||
| 211 | } | ||
| 212 | |||
| 213 | static void mfd_assert_read(int fd) | ||
| 214 | { | ||
| 215 | char buf[16]; | ||
| 216 | void *p; | ||
| 217 | ssize_t l; | ||
| 218 | |||
| 219 | l = read(fd, buf, sizeof(buf)); | ||
| 220 | if (l != sizeof(buf)) { | ||
| 221 | printf("read() failed: %m\n"); | ||
| 222 | abort(); | ||
| 223 | } | ||
| 224 | |||
| 225 | /* verify PROT_READ *is* allowed */ | ||
| 226 | p = mmap(NULL, | ||
| 227 | MFD_DEF_SIZE, | ||
| 228 | PROT_READ, | ||
| 229 | MAP_PRIVATE, | ||
| 230 | fd, | ||
| 231 | 0); | ||
| 232 | if (p == MAP_FAILED) { | ||
| 233 | printf("mmap() failed: %m\n"); | ||
| 234 | abort(); | ||
| 235 | } | ||
| 236 | munmap(p, MFD_DEF_SIZE); | ||
| 237 | |||
| 238 | /* verify MAP_PRIVATE is *always* allowed (even writable) */ | ||
| 239 | p = mmap(NULL, | ||
| 240 | MFD_DEF_SIZE, | ||
| 241 | PROT_READ | PROT_WRITE, | ||
| 242 | MAP_PRIVATE, | ||
| 243 | fd, | ||
| 244 | 0); | ||
| 245 | if (p == MAP_FAILED) { | ||
| 246 | printf("mmap() failed: %m\n"); | ||
| 247 | abort(); | ||
| 248 | } | ||
| 249 | munmap(p, MFD_DEF_SIZE); | ||
| 250 | } | ||
| 251 | |||
| 252 | static void mfd_assert_write(int fd) | ||
| 253 | { | ||
| 254 | ssize_t l; | ||
| 255 | void *p; | ||
| 256 | int r; | ||
| 257 | |||
| 258 | /* verify write() succeeds */ | ||
| 259 | l = write(fd, "\0\0\0\0", 4); | ||
| 260 | if (l != 4) { | ||
| 261 | printf("write() failed: %m\n"); | ||
| 262 | abort(); | ||
| 263 | } | ||
| 264 | |||
| 265 | /* verify PROT_READ | PROT_WRITE is allowed */ | ||
| 266 | p = mmap(NULL, | ||
| 267 | MFD_DEF_SIZE, | ||
| 268 | PROT_READ | PROT_WRITE, | ||
| 269 | MAP_SHARED, | ||
| 270 | fd, | ||
| 271 | 0); | ||
| 272 | if (p == MAP_FAILED) { | ||
| 273 | printf("mmap() failed: %m\n"); | ||
| 274 | abort(); | ||
| 275 | } | ||
| 276 | *(char *)p = 0; | ||
| 277 | munmap(p, MFD_DEF_SIZE); | ||
| 278 | |||
| 279 | /* verify PROT_WRITE is allowed */ | ||
| 280 | p = mmap(NULL, | ||
| 281 | MFD_DEF_SIZE, | ||
| 282 | PROT_WRITE, | ||
| 283 | MAP_SHARED, | ||
| 284 | fd, | ||
| 285 | 0); | ||
| 286 | if (p == MAP_FAILED) { | ||
| 287 | printf("mmap() failed: %m\n"); | ||
| 288 | abort(); | ||
| 289 | } | ||
| 290 | *(char *)p = 0; | ||
| 291 | munmap(p, MFD_DEF_SIZE); | ||
| 292 | |||
| 293 | /* verify PROT_READ with MAP_SHARED is allowed and a following | ||
| 294 | * mprotect(PROT_WRITE) allows writing */ | ||
| 295 | p = mmap(NULL, | ||
| 296 | MFD_DEF_SIZE, | ||
| 297 | PROT_READ, | ||
| 298 | MAP_SHARED, | ||
| 299 | fd, | ||
| 300 | 0); | ||
| 301 | if (p == MAP_FAILED) { | ||
| 302 | printf("mmap() failed: %m\n"); | ||
| 303 | abort(); | ||
| 304 | } | ||
| 305 | |||
| 306 | r = mprotect(p, MFD_DEF_SIZE, PROT_READ | PROT_WRITE); | ||
| 307 | if (r < 0) { | ||
| 308 | printf("mprotect() failed: %m\n"); | ||
| 309 | abort(); | ||
| 310 | } | ||
| 311 | |||
| 312 | *(char *)p = 0; | ||
| 313 | munmap(p, MFD_DEF_SIZE); | ||
| 314 | |||
| 315 | /* verify PUNCH_HOLE works */ | ||
| 316 | r = fallocate(fd, | ||
| 317 | FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, | ||
| 318 | 0, | ||
| 319 | MFD_DEF_SIZE); | ||
| 320 | if (r < 0) { | ||
| 321 | printf("fallocate(PUNCH_HOLE) failed: %m\n"); | ||
| 322 | abort(); | ||
| 323 | } | ||
| 324 | } | ||
| 325 | |||
| 326 | static void mfd_fail_write(int fd) | ||
| 327 | { | ||
| 328 | ssize_t l; | ||
| 329 | void *p; | ||
| 330 | int r; | ||
| 331 | |||
| 332 | /* verify write() fails */ | ||
| 333 | l = write(fd, "data", 4); | ||
| 334 | if (l != -EPERM) { | ||
| 335 | printf("expected EPERM on write(), but got %d: %m\n", (int)l); | ||
| 336 | abort(); | ||
| 337 | } | ||
| 338 | |||
| 339 | /* verify PROT_READ | PROT_WRITE is not allowed */ | ||
| 340 | p = mmap(NULL, | ||
| 341 | MFD_DEF_SIZE, | ||
| 342 | PROT_READ | PROT_WRITE, | ||
| 343 | MAP_SHARED, | ||
| 344 | fd, | ||
| 345 | 0); | ||
| 346 | if (p != MAP_FAILED) { | ||
| 347 | printf("mmap() didn't fail as expected\n"); | ||
| 348 | abort(); | ||
| 349 | } | ||
| 350 | |||
| 351 | /* verify PROT_WRITE is not allowed */ | ||
| 352 | p = mmap(NULL, | ||
| 353 | MFD_DEF_SIZE, | ||
| 354 | PROT_WRITE, | ||
| 355 | MAP_SHARED, | ||
| 356 | fd, | ||
| 357 | 0); | ||
| 358 | if (p != MAP_FAILED) { | ||
| 359 | printf("mmap() didn't fail as expected\n"); | ||
| 360 | abort(); | ||
| 361 | } | ||
| 362 | |||
| 363 | /* Verify PROT_READ with MAP_SHARED with a following mprotect is not | ||
| 364 | * allowed. Note that for r/w the kernel already prevents the mmap. */ | ||
| 365 | p = mmap(NULL, | ||
| 366 | MFD_DEF_SIZE, | ||
| 367 | PROT_READ, | ||
| 368 | MAP_SHARED, | ||
| 369 | fd, | ||
| 370 | 0); | ||
| 371 | if (p != MAP_FAILED) { | ||
| 372 | r = mprotect(p, MFD_DEF_SIZE, PROT_READ | PROT_WRITE); | ||
| 373 | if (r >= 0) { | ||
| 374 | printf("mmap()+mprotect() didn't fail as expected\n"); | ||
| 375 | abort(); | ||
| 376 | } | ||
| 377 | } | ||
| 378 | |||
| 379 | /* verify PUNCH_HOLE fails */ | ||
| 380 | r = fallocate(fd, | ||
| 381 | FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, | ||
| 382 | 0, | ||
| 383 | MFD_DEF_SIZE); | ||
| 384 | if (r >= 0) { | ||
| 385 | printf("fallocate(PUNCH_HOLE) didn't fail as expected\n"); | ||
| 386 | abort(); | ||
| 387 | } | ||
| 388 | } | ||
| 389 | |||
| 390 | static void mfd_assert_shrink(int fd) | ||
| 391 | { | ||
| 392 | int r, fd2; | ||
| 393 | |||
| 394 | r = ftruncate(fd, MFD_DEF_SIZE / 2); | ||
| 395 | if (r < 0) { | ||
| 396 | printf("ftruncate(SHRINK) failed: %m\n"); | ||
| 397 | abort(); | ||
| 398 | } | ||
| 399 | |||
| 400 | mfd_assert_size(fd, MFD_DEF_SIZE / 2); | ||
| 401 | |||
| 402 | fd2 = mfd_assert_open(fd, | ||
| 403 | O_RDWR | O_CREAT | O_TRUNC, | ||
| 404 | S_IRUSR | S_IWUSR); | ||
| 405 | close(fd2); | ||
| 406 | |||
| 407 | mfd_assert_size(fd, 0); | ||
| 408 | } | ||
| 409 | |||
| 410 | static void mfd_fail_shrink(int fd) | ||
| 411 | { | ||
| 412 | int r; | ||
| 413 | |||
| 414 | r = ftruncate(fd, MFD_DEF_SIZE / 2); | ||
| 415 | if (r >= 0) { | ||
| 416 | printf("ftruncate(SHRINK) didn't fail as expected\n"); | ||
| 417 | abort(); | ||
| 418 | } | ||
| 419 | |||
| 420 | mfd_fail_open(fd, | ||
| 421 | O_RDWR | O_CREAT | O_TRUNC, | ||
| 422 | S_IRUSR | S_IWUSR); | ||
| 423 | } | ||
| 424 | |||
| 425 | static void mfd_assert_grow(int fd) | ||
| 426 | { | ||
| 427 | int r; | ||
| 428 | |||
| 429 | r = ftruncate(fd, MFD_DEF_SIZE * 2); | ||
| 430 | if (r < 0) { | ||
| 431 | printf("ftruncate(GROW) failed: %m\n"); | ||
| 432 | abort(); | ||
| 433 | } | ||
| 434 | |||
| 435 | mfd_assert_size(fd, MFD_DEF_SIZE * 2); | ||
| 436 | |||
| 437 | r = fallocate(fd, | ||
| 438 | 0, | ||
| 439 | 0, | ||
| 440 | MFD_DEF_SIZE * 4); | ||
| 441 | if (r < 0) { | ||
| 442 | printf("fallocate(ALLOC) failed: %m\n"); | ||
| 443 | abort(); | ||
| 444 | } | ||
| 445 | |||
| 446 | mfd_assert_size(fd, MFD_DEF_SIZE * 4); | ||
| 447 | } | ||
| 448 | |||
| 449 | static void mfd_fail_grow(int fd) | ||
| 450 | { | ||
| 451 | int r; | ||
| 452 | |||
| 453 | r = ftruncate(fd, MFD_DEF_SIZE * 2); | ||
| 454 | if (r >= 0) { | ||
| 455 | printf("ftruncate(GROW) didn't fail as expected\n"); | ||
| 456 | abort(); | ||
| 457 | } | ||
| 458 | |||
| 459 | r = fallocate(fd, | ||
| 460 | 0, | ||
| 461 | 0, | ||
| 462 | MFD_DEF_SIZE * 4); | ||
| 463 | if (r >= 0) { | ||
| 464 | printf("fallocate(ALLOC) didn't fail as expected\n"); | ||
| 465 | abort(); | ||
| 466 | } | ||
| 467 | } | ||
| 468 | |||
| 469 | static void mfd_assert_grow_write(int fd) | ||
| 470 | { | ||
| 471 | static char buf[MFD_DEF_SIZE * 8]; | ||
| 472 | ssize_t l; | ||
| 473 | |||
| 474 | l = pwrite(fd, buf, sizeof(buf), 0); | ||
| 475 | if (l != sizeof(buf)) { | ||
| 476 | printf("pwrite() failed: %m\n"); | ||
| 477 | abort(); | ||
| 478 | } | ||
| 479 | |||
| 480 | mfd_assert_size(fd, MFD_DEF_SIZE * 8); | ||
| 481 | } | ||
| 482 | |||
| 483 | static void mfd_fail_grow_write(int fd) | ||
| 484 | { | ||
| 485 | static char buf[MFD_DEF_SIZE * 8]; | ||
| 486 | ssize_t l; | ||
| 487 | |||
| 488 | l = pwrite(fd, buf, sizeof(buf), 0); | ||
| 489 | if (l == sizeof(buf)) { | ||
| 490 | printf("pwrite() didn't fail as expected\n"); | ||
| 491 | abort(); | ||
| 492 | } | ||
| 493 | } | ||
| 494 | |||
| 495 | static int idle_thread_fn(void *arg) | ||
| 496 | { | ||
| 497 | sigset_t set; | ||
| 498 | int sig; | ||
| 499 | |||
| 500 | /* dummy waiter; SIGTERM terminates us anyway */ | ||
| 501 | sigemptyset(&set); | ||
| 502 | sigaddset(&set, SIGTERM); | ||
| 503 | sigwait(&set, &sig); | ||
| 504 | |||
| 505 | return 0; | ||
| 506 | } | ||
| 507 | |||
| 508 | static pid_t spawn_idle_thread(unsigned int flags) | ||
| 509 | { | ||
| 510 | uint8_t *stack; | ||
| 511 | pid_t pid; | ||
| 512 | |||
| 513 | stack = malloc(STACK_SIZE); | ||
| 514 | if (!stack) { | ||
| 515 | printf("malloc(STACK_SIZE) failed: %m\n"); | ||
| 516 | abort(); | ||
| 517 | } | ||
| 518 | |||
| 519 | pid = clone(idle_thread_fn, | ||
| 520 | stack + STACK_SIZE, | ||
| 521 | SIGCHLD | flags, | ||
| 522 | NULL); | ||
| 523 | if (pid < 0) { | ||
| 524 | printf("clone() failed: %m\n"); | ||
| 525 | abort(); | ||
| 526 | } | ||
| 527 | |||
| 528 | return pid; | ||
| 529 | } | ||
| 530 | |||
| 531 | static void join_idle_thread(pid_t pid) | ||
| 532 | { | ||
| 533 | kill(pid, SIGTERM); | ||
| 534 | waitpid(pid, NULL, 0); | ||
| 535 | } | ||
| 536 | |||
| 537 | /* | ||
| 538 | * Test memfd_create() syscall | ||
| 539 | * Verify syscall-argument validation, including name checks, flag validation | ||
| 540 | * and more. | ||
| 541 | */ | ||
| 542 | static void test_create(void) | ||
| 543 | { | ||
| 544 | char buf[2048]; | ||
| 545 | int fd; | ||
| 546 | |||
| 547 | /* test NULL name */ | ||
| 548 | mfd_fail_new(NULL, 0); | ||
| 549 | |||
| 550 | /* test over-long name (not zero-terminated) */ | ||
| 551 | memset(buf, 0xff, sizeof(buf)); | ||
| 552 | mfd_fail_new(buf, 0); | ||
| 553 | |||
| 554 | /* test over-long zero-terminated name */ | ||
| 555 | memset(buf, 0xff, sizeof(buf)); | ||
| 556 | buf[sizeof(buf) - 1] = 0; | ||
| 557 | mfd_fail_new(buf, 0); | ||
| 558 | |||
| 559 | /* verify "" is a valid name */ | ||
| 560 | fd = mfd_assert_new("", 0, 0); | ||
| 561 | close(fd); | ||
| 562 | |||
| 563 | /* verify invalid O_* open flags */ | ||
| 564 | mfd_fail_new("", 0x0100); | ||
| 565 | mfd_fail_new("", ~MFD_CLOEXEC); | ||
| 566 | mfd_fail_new("", ~MFD_ALLOW_SEALING); | ||
| 567 | mfd_fail_new("", ~0); | ||
| 568 | mfd_fail_new("", 0x80000000U); | ||
| 569 | |||
| 570 | /* verify MFD_CLOEXEC is allowed */ | ||
| 571 | fd = mfd_assert_new("", 0, MFD_CLOEXEC); | ||
| 572 | close(fd); | ||
| 573 | |||
| 574 | /* verify MFD_ALLOW_SEALING is allowed */ | ||
| 575 | fd = mfd_assert_new("", 0, MFD_ALLOW_SEALING); | ||
| 576 | close(fd); | ||
| 577 | |||
| 578 | /* verify MFD_ALLOW_SEALING | MFD_CLOEXEC is allowed */ | ||
| 579 | fd = mfd_assert_new("", 0, MFD_ALLOW_SEALING | MFD_CLOEXEC); | ||
| 580 | close(fd); | ||
| 581 | } | ||
| 582 | |||
| 583 | /* | ||
| 584 | * Test basic sealing | ||
| 585 | * A very basic sealing test to see whether setting/retrieving seals works. | ||
| 586 | */ | ||
| 587 | static void test_basic(void) | ||
| 588 | { | ||
| 589 | int fd; | ||
| 590 | |||
| 591 | fd = mfd_assert_new("kern_memfd_basic", | ||
| 592 | MFD_DEF_SIZE, | ||
| 593 | MFD_CLOEXEC | MFD_ALLOW_SEALING); | ||
| 594 | |||
| 595 | /* add basic seals */ | ||
| 596 | mfd_assert_has_seals(fd, 0); | ||
| 597 | mfd_assert_add_seals(fd, F_SEAL_SHRINK | | ||
| 598 | F_SEAL_WRITE); | ||
| 599 | mfd_assert_has_seals(fd, F_SEAL_SHRINK | | ||
| 600 | F_SEAL_WRITE); | ||
| 601 | |||
| 602 | /* add them again */ | ||
| 603 | mfd_assert_add_seals(fd, F_SEAL_SHRINK | | ||
| 604 | F_SEAL_WRITE); | ||
| 605 | mfd_assert_has_seals(fd, F_SEAL_SHRINK | | ||
| 606 | F_SEAL_WRITE); | ||
| 607 | |||
| 608 | /* add more seals and seal against sealing */ | ||
| 609 | mfd_assert_add_seals(fd, F_SEAL_GROW | F_SEAL_SEAL); | ||
| 610 | mfd_assert_has_seals(fd, F_SEAL_SHRINK | | ||
| 611 | F_SEAL_GROW | | ||
| 612 | F_SEAL_WRITE | | ||
| 613 | F_SEAL_SEAL); | ||
| 614 | |||
| 615 | /* verify that sealing no longer works */ | ||
| 616 | mfd_fail_add_seals(fd, F_SEAL_GROW); | ||
| 617 | mfd_fail_add_seals(fd, 0); | ||
| 618 | |||
| 619 | close(fd); | ||
| 620 | |||
| 621 | /* verify sealing does not work without MFD_ALLOW_SEALING */ | ||
| 622 | fd = mfd_assert_new("kern_memfd_basic", | ||
| 623 | MFD_DEF_SIZE, | ||
| 624 | MFD_CLOEXEC); | ||
| 625 | mfd_assert_has_seals(fd, F_SEAL_SEAL); | ||
| 626 | mfd_fail_add_seals(fd, F_SEAL_SHRINK | | ||
| 627 | F_SEAL_GROW | | ||
| 628 | F_SEAL_WRITE); | ||
| 629 | mfd_assert_has_seals(fd, F_SEAL_SEAL); | ||
| 630 | close(fd); | ||
| 631 | } | ||
| 632 | |||
| 633 | /* | ||
| 634 | * Test SEAL_WRITE | ||
| 635 | * Test whether SEAL_WRITE actually prevents modifications. | ||
| 636 | */ | ||
| 637 | static void test_seal_write(void) | ||
| 638 | { | ||
| 639 | int fd; | ||
| 640 | |||
| 641 | fd = mfd_assert_new("kern_memfd_seal_write", | ||
| 642 | MFD_DEF_SIZE, | ||
| 643 | MFD_CLOEXEC | MFD_ALLOW_SEALING); | ||
| 644 | mfd_assert_has_seals(fd, 0); | ||
| 645 | mfd_assert_add_seals(fd, F_SEAL_WRITE); | ||
| 646 | mfd_assert_has_seals(fd, F_SEAL_WRITE); | ||
| 647 | |||
| 648 | mfd_assert_read(fd); | ||
| 649 | mfd_fail_write(fd); | ||
| 650 | mfd_assert_shrink(fd); | ||
| 651 | mfd_assert_grow(fd); | ||
| 652 | mfd_fail_grow_write(fd); | ||
| 653 | |||
| 654 | close(fd); | ||
| 655 | } | ||
| 656 | |||
| 657 | /* | ||
| 658 | * Test SEAL_SHRINK | ||
| 659 | * Test whether SEAL_SHRINK actually prevents shrinking | ||
| 660 | */ | ||
| 661 | static void test_seal_shrink(void) | ||
| 662 | { | ||
| 663 | int fd; | ||
| 664 | |||
| 665 | fd = mfd_assert_new("kern_memfd_seal_shrink", | ||
| 666 | MFD_DEF_SIZE, | ||
| 667 | MFD_CLOEXEC | MFD_ALLOW_SEALING); | ||
| 668 | mfd_assert_has_seals(fd, 0); | ||
| 669 | mfd_assert_add_seals(fd, F_SEAL_SHRINK); | ||
| 670 | mfd_assert_has_seals(fd, F_SEAL_SHRINK); | ||
| 671 | |||
| 672 | mfd_assert_read(fd); | ||
| 673 | mfd_assert_write(fd); | ||
| 674 | mfd_fail_shrink(fd); | ||
| 675 | mfd_assert_grow(fd); | ||
| 676 | mfd_assert_grow_write(fd); | ||
| 677 | |||
| 678 | close(fd); | ||
| 679 | } | ||
| 680 | |||
| 681 | /* | ||
| 682 | * Test SEAL_GROW | ||
| 683 | * Test whether SEAL_GROW actually prevents growing | ||
| 684 | */ | ||
| 685 | static void test_seal_grow(void) | ||
| 686 | { | ||
| 687 | int fd; | ||
| 688 | |||
| 689 | fd = mfd_assert_new("kern_memfd_seal_grow", | ||
| 690 | MFD_DEF_SIZE, | ||
| 691 | MFD_CLOEXEC | MFD_ALLOW_SEALING); | ||
| 692 | mfd_assert_has_seals(fd, 0); | ||
| 693 | mfd_assert_add_seals(fd, F_SEAL_GROW); | ||
| 694 | mfd_assert_has_seals(fd, F_SEAL_GROW); | ||
| 695 | |||
| 696 | mfd_assert_read(fd); | ||
| 697 | mfd_assert_write(fd); | ||
| 698 | mfd_assert_shrink(fd); | ||
| 699 | mfd_fail_grow(fd); | ||
| 700 | mfd_fail_grow_write(fd); | ||
| 701 | |||
| 702 | close(fd); | ||
| 703 | } | ||
| 704 | |||
| 705 | /* | ||
| 706 | * Test SEAL_SHRINK | SEAL_GROW | ||
| 707 | * Test whether SEAL_SHRINK | SEAL_GROW actually prevents resizing | ||
| 708 | */ | ||
| 709 | static void test_seal_resize(void) | ||
| 710 | { | ||
| 711 | int fd; | ||
| 712 | |||
| 713 | fd = mfd_assert_new("kern_memfd_seal_resize", | ||
| 714 | MFD_DEF_SIZE, | ||
| 715 | MFD_CLOEXEC | MFD_ALLOW_SEALING); | ||
| 716 | mfd_assert_has_seals(fd, 0); | ||
| 717 | mfd_assert_add_seals(fd, F_SEAL_SHRINK | F_SEAL_GROW); | ||
| 718 | mfd_assert_has_seals(fd, F_SEAL_SHRINK | F_SEAL_GROW); | ||
| 719 | |||
| 720 | mfd_assert_read(fd); | ||
| 721 | mfd_assert_write(fd); | ||
| 722 | mfd_fail_shrink(fd); | ||
| 723 | mfd_fail_grow(fd); | ||
| 724 | mfd_fail_grow_write(fd); | ||
| 725 | |||
| 726 | close(fd); | ||
| 727 | } | ||
| 728 | |||
| 729 | /* | ||
| 730 | * Test sharing via dup() | ||
| 731 | * Test that seals are shared between dupped FDs and they're all equal. | ||
| 732 | */ | ||
| 733 | static void test_share_dup(void) | ||
| 734 | { | ||
| 735 | int fd, fd2; | ||
| 736 | |||
| 737 | fd = mfd_assert_new("kern_memfd_share_dup", | ||
| 738 | MFD_DEF_SIZE, | ||
| 739 | MFD_CLOEXEC | MFD_ALLOW_SEALING); | ||
| 740 | mfd_assert_has_seals(fd, 0); | ||
| 741 | |||
| 742 | fd2 = mfd_assert_dup(fd); | ||
| 743 | mfd_assert_has_seals(fd2, 0); | ||
| 744 | |||
| 745 | mfd_assert_add_seals(fd, F_SEAL_WRITE); | ||
| 746 | mfd_assert_has_seals(fd, F_SEAL_WRITE); | ||
| 747 | mfd_assert_has_seals(fd2, F_SEAL_WRITE); | ||
| 748 | |||
| 749 | mfd_assert_add_seals(fd2, F_SEAL_SHRINK); | ||
| 750 | mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK); | ||
| 751 | mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK); | ||
| 752 | |||
| 753 | mfd_assert_add_seals(fd, F_SEAL_SEAL); | ||
| 754 | mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL); | ||
| 755 | mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL); | ||
| 756 | |||
| 757 | mfd_fail_add_seals(fd, F_SEAL_GROW); | ||
| 758 | mfd_fail_add_seals(fd2, F_SEAL_GROW); | ||
| 759 | mfd_fail_add_seals(fd, F_SEAL_SEAL); | ||
| 760 | mfd_fail_add_seals(fd2, F_SEAL_SEAL); | ||
| 761 | |||
| 762 | close(fd2); | ||
| 763 | |||
| 764 | mfd_fail_add_seals(fd, F_SEAL_GROW); | ||
| 765 | close(fd); | ||
| 766 | } | ||
| 767 | |||
| 768 | /* | ||
| 769 | * Test sealing with active mmap()s | ||
| 770 | * Modifying seals is only allowed if no other mmap() refs exist. | ||
| 771 | */ | ||
| 772 | static void test_share_mmap(void) | ||
| 773 | { | ||
| 774 | int fd; | ||
| 775 | void *p; | ||
| 776 | |||
| 777 | fd = mfd_assert_new("kern_memfd_share_mmap", | ||
| 778 | MFD_DEF_SIZE, | ||
| 779 | MFD_CLOEXEC | MFD_ALLOW_SEALING); | ||
| 780 | mfd_assert_has_seals(fd, 0); | ||
| 781 | |||
| 782 | /* shared/writable ref prevents sealing WRITE, but allows others */ | ||
| 783 | p = mfd_assert_mmap_shared(fd); | ||
| 784 | mfd_fail_add_seals(fd, F_SEAL_WRITE); | ||
| 785 | mfd_assert_has_seals(fd, 0); | ||
| 786 | mfd_assert_add_seals(fd, F_SEAL_SHRINK); | ||
| 787 | mfd_assert_has_seals(fd, F_SEAL_SHRINK); | ||
| 788 | munmap(p, MFD_DEF_SIZE); | ||
| 789 | |||
| 790 | /* readable ref allows sealing */ | ||
| 791 | p = mfd_assert_mmap_private(fd); | ||
| 792 | mfd_assert_add_seals(fd, F_SEAL_WRITE); | ||
| 793 | mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK); | ||
| 794 | munmap(p, MFD_DEF_SIZE); | ||
| 795 | |||
| 796 | close(fd); | ||
| 797 | } | ||
| 798 | |||
| 799 | /* | ||
| 800 | * Test sealing with open(/proc/self/fd/%d) | ||
| 801 | * Via /proc we can get access to a separate file-context for the same memfd. | ||
| 802 | * This is *not* like dup(), but like a real separate open(). Make sure the | ||
| 803 | * semantics are as expected and we correctly check for RDONLY / WRONLY / RDWR. | ||
| 804 | */ | ||
| 805 | static void test_share_open(void) | ||
| 806 | { | ||
| 807 | int fd, fd2; | ||
| 808 | |||
| 809 | fd = mfd_assert_new("kern_memfd_share_open", | ||
| 810 | MFD_DEF_SIZE, | ||
| 811 | MFD_CLOEXEC | MFD_ALLOW_SEALING); | ||
| 812 | mfd_assert_has_seals(fd, 0); | ||
| 813 | |||
| 814 | fd2 = mfd_assert_open(fd, O_RDWR, 0); | ||
| 815 | mfd_assert_add_seals(fd, F_SEAL_WRITE); | ||
| 816 | mfd_assert_has_seals(fd, F_SEAL_WRITE); | ||
| 817 | mfd_assert_has_seals(fd2, F_SEAL_WRITE); | ||
| 818 | |||
| 819 | mfd_assert_add_seals(fd2, F_SEAL_SHRINK); | ||
| 820 | mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK); | ||
| 821 | mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK); | ||
| 822 | |||
| 823 | close(fd); | ||
| 824 | fd = mfd_assert_open(fd2, O_RDONLY, 0); | ||
| 825 | |||
| 826 | mfd_fail_add_seals(fd, F_SEAL_SEAL); | ||
| 827 | mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK); | ||
| 828 | mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK); | ||
| 829 | |||
| 830 | close(fd2); | ||
| 831 | fd2 = mfd_assert_open(fd, O_RDWR, 0); | ||
| 832 | |||
| 833 | mfd_assert_add_seals(fd2, F_SEAL_SEAL); | ||
| 834 | mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL); | ||
| 835 | mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL); | ||
| 836 | |||
| 837 | close(fd2); | ||
| 838 | close(fd); | ||
| 839 | } | ||
| 840 | |||
| 841 | /* | ||
| 842 | * Test sharing via fork() | ||
| 843 | * Test whether seal-modifications work as expected with forked childs. | ||
| 844 | */ | ||
| 845 | static void test_share_fork(void) | ||
| 846 | { | ||
| 847 | int fd; | ||
| 848 | pid_t pid; | ||
| 849 | |||
| 850 | fd = mfd_assert_new("kern_memfd_share_fork", | ||
| 851 | MFD_DEF_SIZE, | ||
| 852 | MFD_CLOEXEC | MFD_ALLOW_SEALING); | ||
| 853 | mfd_assert_has_seals(fd, 0); | ||
| 854 | |||
| 855 | pid = spawn_idle_thread(0); | ||
| 856 | mfd_assert_add_seals(fd, F_SEAL_SEAL); | ||
| 857 | mfd_assert_has_seals(fd, F_SEAL_SEAL); | ||
| 858 | |||
| 859 | mfd_fail_add_seals(fd, F_SEAL_WRITE); | ||
| 860 | mfd_assert_has_seals(fd, F_SEAL_SEAL); | ||
| 861 | |||
| 862 | join_idle_thread(pid); | ||
| 863 | |||
| 864 | mfd_fail_add_seals(fd, F_SEAL_WRITE); | ||
| 865 | mfd_assert_has_seals(fd, F_SEAL_SEAL); | ||
| 866 | |||
| 867 | close(fd); | ||
| 868 | } | ||
| 869 | |||
| 870 | int main(int argc, char **argv) | ||
| 871 | { | ||
| 872 | pid_t pid; | ||
| 873 | |||
| 874 | printf("memfd: CREATE\n"); | ||
| 875 | test_create(); | ||
| 876 | printf("memfd: BASIC\n"); | ||
| 877 | test_basic(); | ||
| 878 | |||
| 879 | printf("memfd: SEAL-WRITE\n"); | ||
| 880 | test_seal_write(); | ||
| 881 | printf("memfd: SEAL-SHRINK\n"); | ||
| 882 | test_seal_shrink(); | ||
| 883 | printf("memfd: SEAL-GROW\n"); | ||
| 884 | test_seal_grow(); | ||
| 885 | printf("memfd: SEAL-RESIZE\n"); | ||
| 886 | test_seal_resize(); | ||
| 887 | |||
| 888 | printf("memfd: SHARE-DUP\n"); | ||
| 889 | test_share_dup(); | ||
| 890 | printf("memfd: SHARE-MMAP\n"); | ||
| 891 | test_share_mmap(); | ||
| 892 | printf("memfd: SHARE-OPEN\n"); | ||
| 893 | test_share_open(); | ||
| 894 | printf("memfd: SHARE-FORK\n"); | ||
| 895 | test_share_fork(); | ||
| 896 | |||
| 897 | /* Run test-suite in a multi-threaded environment with a shared | ||
| 898 | * file-table. */ | ||
| 899 | pid = spawn_idle_thread(CLONE_FILES | CLONE_FS | CLONE_VM); | ||
| 900 | printf("memfd: SHARE-DUP (shared file-table)\n"); | ||
| 901 | test_share_dup(); | ||
| 902 | printf("memfd: SHARE-MMAP (shared file-table)\n"); | ||
| 903 | test_share_mmap(); | ||
| 904 | printf("memfd: SHARE-OPEN (shared file-table)\n"); | ||
| 905 | test_share_open(); | ||
| 906 | printf("memfd: SHARE-FORK (shared file-table)\n"); | ||
| 907 | test_share_fork(); | ||
| 908 | join_idle_thread(pid); | ||
| 909 | |||
| 910 | printf("memfd: DONE\n"); | ||
| 911 | |||
| 912 | return 0; | ||
| 913 | } | ||
diff --git a/tools/testing/selftests/memfd/run_fuse_test.sh b/tools/testing/selftests/memfd/run_fuse_test.sh new file mode 100644 index 000000000000..69b930e1e041 --- /dev/null +++ b/tools/testing/selftests/memfd/run_fuse_test.sh | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | #!/bin/sh | ||
| 2 | |||
| 3 | if test -d "./mnt" ; then | ||
| 4 | fusermount -u ./mnt | ||
| 5 | rmdir ./mnt | ||
| 6 | fi | ||
| 7 | |||
| 8 | set -e | ||
| 9 | |||
| 10 | mkdir mnt | ||
| 11 | ./fuse_mnt ./mnt | ||
| 12 | ./fuse_test ./mnt/memfd | ||
| 13 | fusermount -u ./mnt | ||
| 14 | rmdir ./mnt | ||
diff --git a/tools/testing/selftests/ptrace/peeksiginfo.c b/tools/testing/selftests/ptrace/peeksiginfo.c index d46558b1f58d..c34cd8ac8aaa 100644 --- a/tools/testing/selftests/ptrace/peeksiginfo.c +++ b/tools/testing/selftests/ptrace/peeksiginfo.c | |||
| @@ -31,6 +31,10 @@ static int sys_ptrace(int request, pid_t pid, void *addr, void *data) | |||
| 31 | #define TEST_SICODE_PRIV -1 | 31 | #define TEST_SICODE_PRIV -1 |
| 32 | #define TEST_SICODE_SHARE -2 | 32 | #define TEST_SICODE_SHARE -2 |
| 33 | 33 | ||
| 34 | #ifndef PAGE_SIZE | ||
| 35 | #define PAGE_SIZE sysconf(_SC_PAGESIZE) | ||
| 36 | #endif | ||
| 37 | |||
| 34 | #define err(fmt, ...) \ | 38 | #define err(fmt, ...) \ |
| 35 | fprintf(stderr, \ | 39 | fprintf(stderr, \ |
| 36 | "Error (%s:%d): " fmt, \ | 40 | "Error (%s:%d): " fmt, \ |
