diff options
| -rw-r--r-- | Documentation/blockdev/zram.txt (renamed from drivers/staging/zram/zram.txt) | 6 | ||||
| -rw-r--r-- | Documentation/filesystems/proc.txt | 4 | ||||
| -rw-r--r-- | Documentation/filesystems/vfs.txt | 12 | ||||
| -rw-r--r-- | MAINTAINERS | 16 | ||||
| -rw-r--r-- | arch/x86/include/asm/pgtable_types.h | 3 | ||||
| -rw-r--r-- | drivers/block/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/block/Makefile | 1 | ||||
| -rw-r--r-- | drivers/block/zram/Kconfig (renamed from drivers/staging/zram/Kconfig) | 1 | ||||
| -rw-r--r-- | drivers/block/zram/Makefile (renamed from drivers/staging/zram/Makefile) | 0 | ||||
| -rw-r--r-- | drivers/block/zram/zram_drv.c (renamed from drivers/staging/zram/zram_drv.c) | 128 | ||||
| -rw-r--r-- | drivers/block/zram/zram_drv.h (renamed from drivers/staging/zram/zram_drv.h) | 32 | ||||
| -rw-r--r-- | drivers/net/phy/mdio_bus.c | 1 | ||||
| -rw-r--r-- | drivers/staging/Kconfig | 4 | ||||
| -rw-r--r-- | drivers/staging/Makefile | 2 | ||||
| -rw-r--r-- | drivers/staging/zsmalloc/Kconfig | 24 | ||||
| -rw-r--r-- | drivers/staging/zsmalloc/Makefile | 3 | ||||
| -rw-r--r-- | drivers/video/backlight/lcd.c | 2 | ||||
| -rw-r--r-- | include/linux/blkdev.h | 5 | ||||
| -rw-r--r-- | include/linux/bootmem.h | 4 | ||||
| -rw-r--r-- | include/linux/smp.h | 6 | ||||
| -rw-r--r-- | include/linux/zsmalloc.h (renamed from drivers/staging/zsmalloc/zsmalloc.h) | 1 | ||||
| -rw-r--r-- | kernel/smp.c | 68 | ||||
| -rw-r--r-- | mm/Kconfig | 25 | ||||
| -rw-r--r-- | mm/Makefile | 1 | ||||
| -rw-r--r-- | mm/memcontrol.c | 7 | ||||
| -rw-r--r-- | mm/mempolicy.c | 2 | ||||
| -rw-r--r-- | mm/oom_kill.c | 2 | ||||
| -rw-r--r-- | mm/slub.c | 19 | ||||
| -rw-r--r-- | mm/zsmalloc.c (renamed from drivers/staging/zsmalloc/zsmalloc-main.c) | 4 |
29 files changed, 154 insertions, 231 deletions
diff --git a/drivers/staging/zram/zram.txt b/Documentation/blockdev/zram.txt index 765d790ae831..2eccddffa6c8 100644 --- a/drivers/staging/zram/zram.txt +++ b/Documentation/blockdev/zram.txt | |||
| @@ -1,8 +1,6 @@ | |||
| 1 | zram: Compressed RAM based block devices | 1 | zram: Compressed RAM based block devices |
| 2 | ---------------------------------------- | 2 | ---------------------------------------- |
| 3 | 3 | ||
| 4 | Project home: http://compcache.googlecode.com/ | ||
| 5 | |||
| 6 | * Introduction | 4 | * Introduction |
| 7 | 5 | ||
| 8 | The zram module creates RAM based block devices named /dev/zram<id> | 6 | The zram module creates RAM based block devices named /dev/zram<id> |
| @@ -69,9 +67,5 @@ Following shows a typical sequence of steps for using zram. | |||
| 69 | resets the disksize to zero. You must set the disksize again | 67 | resets the disksize to zero. You must set the disksize again |
| 70 | before reusing the device. | 68 | before reusing the device. |
| 71 | 69 | ||
| 72 | Please report any problems at: | ||
| 73 | - Mailing list: linux-mm-cc at laptop dot org | ||
| 74 | - Issue tracker: http://code.google.com/p/compcache/issues/list | ||
| 75 | |||
| 76 | Nitin Gupta | 70 | Nitin Gupta |
| 77 | ngupta@vflare.org | 71 | ngupta@vflare.org |
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index 31f76178c987..f00bee144add 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt | |||
| @@ -1386,8 +1386,8 @@ may allocate from based on an estimation of its current memory and swap use. | |||
| 1386 | For example, if a task is using all allowed memory, its badness score will be | 1386 | For example, if a task is using all allowed memory, its badness score will be |
| 1387 | 1000. If it is using half of its allowed memory, its score will be 500. | 1387 | 1000. If it is using half of its allowed memory, its score will be 500. |
| 1388 | 1388 | ||
| 1389 | There is an additional factor included in the badness score: root | 1389 | There is an additional factor included in the badness score: the current memory |
| 1390 | processes are given 3% extra memory over other tasks. | 1390 | and swap usage is discounted by 3% for root processes. |
| 1391 | 1391 | ||
| 1392 | The amount of "allowed" memory depends on the context in which the oom killer | 1392 | The amount of "allowed" memory depends on the context in which the oom killer |
| 1393 | was called. If it is due to the memory assigned to the allocating task's cpuset | 1393 | was called. If it is due to the memory assigned to the allocating task's cpuset |
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index deb48b5fd883..c53784c119c8 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt | |||
| @@ -782,7 +782,7 @@ struct file_operations | |||
| 782 | ---------------------- | 782 | ---------------------- |
| 783 | 783 | ||
| 784 | This describes how the VFS can manipulate an open file. As of kernel | 784 | This describes how the VFS can manipulate an open file. As of kernel |
| 785 | 3.5, the following members are defined: | 785 | 3.12, the following members are defined: |
| 786 | 786 | ||
| 787 | struct file_operations { | 787 | struct file_operations { |
| 788 | struct module *owner; | 788 | struct module *owner; |
| @@ -803,9 +803,6 @@ struct file_operations { | |||
| 803 | int (*aio_fsync) (struct kiocb *, int datasync); | 803 | int (*aio_fsync) (struct kiocb *, int datasync); |
| 804 | int (*fasync) (int, struct file *, int); | 804 | int (*fasync) (int, struct file *, int); |
| 805 | int (*lock) (struct file *, int, struct file_lock *); | 805 | int (*lock) (struct file *, int, struct file_lock *); |
| 806 | ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *); | ||
| 807 | ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *); | ||
| 808 | ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void *); | ||
| 809 | ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); | 806 | ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); |
| 810 | unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); | 807 | unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); |
| 811 | int (*check_flags)(int); | 808 | int (*check_flags)(int); |
| @@ -814,6 +811,7 @@ struct file_operations { | |||
| 814 | ssize_t (*splice_read)(struct file *, struct pipe_inode_info *, size_t, unsigned int); | 811 | ssize_t (*splice_read)(struct file *, struct pipe_inode_info *, size_t, unsigned int); |
| 815 | int (*setlease)(struct file *, long arg, struct file_lock **); | 812 | int (*setlease)(struct file *, long arg, struct file_lock **); |
| 816 | long (*fallocate)(struct file *, int mode, loff_t offset, loff_t len); | 813 | long (*fallocate)(struct file *, int mode, loff_t offset, loff_t len); |
| 814 | int (*show_fdinfo)(struct seq_file *m, struct file *f); | ||
| 817 | }; | 815 | }; |
| 818 | 816 | ||
| 819 | Again, all methods are called without any locks being held, unless | 817 | Again, all methods are called without any locks being held, unless |
| @@ -864,12 +862,6 @@ otherwise noted. | |||
| 864 | lock: called by the fcntl(2) system call for F_GETLK, F_SETLK, and F_SETLKW | 862 | lock: called by the fcntl(2) system call for F_GETLK, F_SETLK, and F_SETLKW |
| 865 | commands | 863 | commands |
| 866 | 864 | ||
| 867 | readv: called by the readv(2) system call | ||
| 868 | |||
| 869 | writev: called by the writev(2) system call | ||
| 870 | |||
| 871 | sendfile: called by the sendfile(2) system call | ||
| 872 | |||
| 873 | get_unmapped_area: called by the mmap(2) system call | 865 | get_unmapped_area: called by the mmap(2) system call |
| 874 | 866 | ||
| 875 | check_flags: called by the fcntl(2) system call for F_SETFL command | 867 | check_flags: called by the fcntl(2) system call for F_SETFL command |
diff --git a/MAINTAINERS b/MAINTAINERS index a31a6e3e199f..b5795f031b3e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -9740,11 +9740,27 @@ T: Mercurial http://linuxtv.org/hg/v4l-dvb | |||
| 9740 | S: Odd Fixes | 9740 | S: Odd Fixes |
| 9741 | F: drivers/media/pci/zoran/ | 9741 | F: drivers/media/pci/zoran/ |
| 9742 | 9742 | ||
| 9743 | ZRAM COMPRESSED RAM BLOCK DEVICE DRVIER | ||
| 9744 | M: Minchan Kim <minchan@kernel.org> | ||
| 9745 | M: Nitin Gupta <ngupta@vflare.org> | ||
| 9746 | L: linux-kernel@vger.kernel.org | ||
| 9747 | S: Maintained | ||
| 9748 | F: drivers/block/zram/ | ||
| 9749 | F: Documentation/blockdev/zram.txt | ||
| 9750 | |||
| 9743 | ZS DECSTATION Z85C30 SERIAL DRIVER | 9751 | ZS DECSTATION Z85C30 SERIAL DRIVER |
| 9744 | M: "Maciej W. Rozycki" <macro@linux-mips.org> | 9752 | M: "Maciej W. Rozycki" <macro@linux-mips.org> |
| 9745 | S: Maintained | 9753 | S: Maintained |
| 9746 | F: drivers/tty/serial/zs.* | 9754 | F: drivers/tty/serial/zs.* |
| 9747 | 9755 | ||
| 9756 | ZSMALLOC COMPRESSED SLAB MEMORY ALLOCATOR | ||
| 9757 | M: Minchan Kim <minchan@kernel.org> | ||
| 9758 | M: Nitin Gupta <ngupta@vflare.org> | ||
| 9759 | L: linux-mm@kvack.org | ||
| 9760 | S: Maintained | ||
| 9761 | F: mm/zsmalloc.c | ||
| 9762 | F: include/linux/zsmalloc.h | ||
| 9763 | |||
| 9748 | ZSWAP COMPRESSED SWAP CACHING | 9764 | ZSWAP COMPRESSED SWAP CACHING |
| 9749 | M: Seth Jennings <sjenning@linux.vnet.ibm.com> | 9765 | M: Seth Jennings <sjenning@linux.vnet.ibm.com> |
| 9750 | L: linux-mm@kvack.org | 9766 | L: linux-mm@kvack.org |
diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h index a83aa44bb1fb..1aa9ccd43223 100644 --- a/arch/x86/include/asm/pgtable_types.h +++ b/arch/x86/include/asm/pgtable_types.h | |||
| @@ -121,7 +121,8 @@ | |||
| 121 | 121 | ||
| 122 | /* Set of bits not changed in pte_modify */ | 122 | /* Set of bits not changed in pte_modify */ |
| 123 | #define _PAGE_CHG_MASK (PTE_PFN_MASK | _PAGE_PCD | _PAGE_PWT | \ | 123 | #define _PAGE_CHG_MASK (PTE_PFN_MASK | _PAGE_PCD | _PAGE_PWT | \ |
| 124 | _PAGE_SPECIAL | _PAGE_ACCESSED | _PAGE_DIRTY) | 124 | _PAGE_SPECIAL | _PAGE_ACCESSED | _PAGE_DIRTY | \ |
| 125 | _PAGE_SOFT_DIRTY) | ||
| 125 | #define _HPAGE_CHG_MASK (_PAGE_CHG_MASK | _PAGE_PSE) | 126 | #define _HPAGE_CHG_MASK (_PAGE_CHG_MASK | _PAGE_PSE) |
| 126 | 127 | ||
| 127 | #define _PAGE_CACHE_MASK (_PAGE_PCD | _PAGE_PWT) | 128 | #define _PAGE_CACHE_MASK (_PAGE_PCD | _PAGE_PWT) |
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 9ffa90c6201c..014a1cfc41c5 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig | |||
| @@ -108,6 +108,8 @@ source "drivers/block/paride/Kconfig" | |||
| 108 | 108 | ||
| 109 | source "drivers/block/mtip32xx/Kconfig" | 109 | source "drivers/block/mtip32xx/Kconfig" |
| 110 | 110 | ||
| 111 | source "drivers/block/zram/Kconfig" | ||
| 112 | |||
| 111 | config BLK_CPQ_DA | 113 | config BLK_CPQ_DA |
| 112 | tristate "Compaq SMART2 support" | 114 | tristate "Compaq SMART2 support" |
| 113 | depends on PCI && VIRT_TO_BUS && 0 | 115 | depends on PCI && VIRT_TO_BUS && 0 |
diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 816d979c3266..02b688d1438d 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile | |||
| @@ -42,6 +42,7 @@ obj-$(CONFIG_BLK_DEV_PCIESSD_MTIP32XX) += mtip32xx/ | |||
| 42 | 42 | ||
| 43 | obj-$(CONFIG_BLK_DEV_RSXX) += rsxx/ | 43 | obj-$(CONFIG_BLK_DEV_RSXX) += rsxx/ |
| 44 | obj-$(CONFIG_BLK_DEV_NULL_BLK) += null_blk.o | 44 | obj-$(CONFIG_BLK_DEV_NULL_BLK) += null_blk.o |
| 45 | obj-$(CONFIG_ZRAM) += zram/ | ||
| 45 | 46 | ||
| 46 | nvme-y := nvme-core.o nvme-scsi.o | 47 | nvme-y := nvme-core.o nvme-scsi.o |
| 47 | skd-y := skd_main.o | 48 | skd-y := skd_main.o |
diff --git a/drivers/staging/zram/Kconfig b/drivers/block/zram/Kconfig index 983314c41349..3450be850399 100644 --- a/drivers/staging/zram/Kconfig +++ b/drivers/block/zram/Kconfig | |||
| @@ -14,7 +14,6 @@ config ZRAM | |||
| 14 | disks and maybe many more. | 14 | disks and maybe many more. |
| 15 | 15 | ||
| 16 | See zram.txt for more information. | 16 | See zram.txt for more information. |
| 17 | Project home: <https://compcache.googlecode.com/> | ||
| 18 | 17 | ||
| 19 | config ZRAM_DEBUG | 18 | config ZRAM_DEBUG |
| 20 | bool "Compressed RAM block device debug support" | 19 | bool "Compressed RAM block device debug support" |
diff --git a/drivers/staging/zram/Makefile b/drivers/block/zram/Makefile index cb0f9ced6a93..cb0f9ced6a93 100644 --- a/drivers/staging/zram/Makefile +++ b/drivers/block/zram/Makefile | |||
diff --git a/drivers/staging/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index 108f2733106d..011e55d820b1 100644 --- a/drivers/staging/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | * Compressed RAM block device | 2 | * Compressed RAM block device |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2008, 2009, 2010 Nitin Gupta | 4 | * Copyright (C) 2008, 2009, 2010 Nitin Gupta |
| 5 | * 2012, 2013 Minchan Kim | ||
| 5 | * | 6 | * |
| 6 | * This code is released using a dual license strategy: BSD/GPL | 7 | * This code is released using a dual license strategy: BSD/GPL |
| 7 | * You can choose the licence that better fits your requirements. | 8 | * You can choose the licence that better fits your requirements. |
| @@ -9,7 +10,6 @@ | |||
| 9 | * Released under the terms of 3-clause BSD License | 10 | * Released under the terms of 3-clause BSD License |
| 10 | * Released under the terms of GNU General Public License Version 2.0 | 11 | * Released under the terms of GNU General Public License Version 2.0 |
| 11 | * | 12 | * |
| 12 | * Project home: http://compcache.googlecode.com | ||
| 13 | */ | 13 | */ |
| 14 | 14 | ||
| 15 | #define KMSG_COMPONENT "zram" | 15 | #define KMSG_COMPONENT "zram" |
| @@ -104,7 +104,7 @@ static ssize_t zero_pages_show(struct device *dev, | |||
| 104 | { | 104 | { |
| 105 | struct zram *zram = dev_to_zram(dev); | 105 | struct zram *zram = dev_to_zram(dev); |
| 106 | 106 | ||
| 107 | return sprintf(buf, "%u\n", zram->stats.pages_zero); | 107 | return sprintf(buf, "%u\n", atomic_read(&zram->stats.pages_zero)); |
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | static ssize_t orig_data_size_show(struct device *dev, | 110 | static ssize_t orig_data_size_show(struct device *dev, |
| @@ -113,7 +113,7 @@ static ssize_t orig_data_size_show(struct device *dev, | |||
| 113 | struct zram *zram = dev_to_zram(dev); | 113 | struct zram *zram = dev_to_zram(dev); |
| 114 | 114 | ||
| 115 | return sprintf(buf, "%llu\n", | 115 | return sprintf(buf, "%llu\n", |
| 116 | (u64)(zram->stats.pages_stored) << PAGE_SHIFT); | 116 | (u64)(atomic_read(&zram->stats.pages_stored)) << PAGE_SHIFT); |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | static ssize_t compr_data_size_show(struct device *dev, | 119 | static ssize_t compr_data_size_show(struct device *dev, |
| @@ -140,6 +140,7 @@ static ssize_t mem_used_total_show(struct device *dev, | |||
| 140 | return sprintf(buf, "%llu\n", val); | 140 | return sprintf(buf, "%llu\n", val); |
| 141 | } | 141 | } |
| 142 | 142 | ||
| 143 | /* flag operations needs meta->tb_lock */ | ||
| 143 | static int zram_test_flag(struct zram_meta *meta, u32 index, | 144 | static int zram_test_flag(struct zram_meta *meta, u32 index, |
| 144 | enum zram_pageflags flag) | 145 | enum zram_pageflags flag) |
| 145 | { | 146 | { |
| @@ -228,6 +229,8 @@ static struct zram_meta *zram_meta_alloc(u64 disksize) | |||
| 228 | goto free_table; | 229 | goto free_table; |
| 229 | } | 230 | } |
| 230 | 231 | ||
| 232 | rwlock_init(&meta->tb_lock); | ||
| 233 | mutex_init(&meta->buffer_lock); | ||
| 231 | return meta; | 234 | return meta; |
| 232 | 235 | ||
| 233 | free_table: | 236 | free_table: |
| @@ -280,6 +283,7 @@ static void handle_zero_page(struct bio_vec *bvec) | |||
| 280 | flush_dcache_page(page); | 283 | flush_dcache_page(page); |
| 281 | } | 284 | } |
| 282 | 285 | ||
| 286 | /* NOTE: caller should hold meta->tb_lock with write-side */ | ||
| 283 | static void zram_free_page(struct zram *zram, size_t index) | 287 | static void zram_free_page(struct zram *zram, size_t index) |
| 284 | { | 288 | { |
| 285 | struct zram_meta *meta = zram->meta; | 289 | struct zram_meta *meta = zram->meta; |
| @@ -293,21 +297,21 @@ static void zram_free_page(struct zram *zram, size_t index) | |||
| 293 | */ | 297 | */ |
| 294 | if (zram_test_flag(meta, index, ZRAM_ZERO)) { | 298 | if (zram_test_flag(meta, index, ZRAM_ZERO)) { |
| 295 | zram_clear_flag(meta, index, ZRAM_ZERO); | 299 | zram_clear_flag(meta, index, ZRAM_ZERO); |
| 296 | zram->stats.pages_zero--; | 300 | atomic_dec(&zram->stats.pages_zero); |
| 297 | } | 301 | } |
| 298 | return; | 302 | return; |
| 299 | } | 303 | } |
| 300 | 304 | ||
| 301 | if (unlikely(size > max_zpage_size)) | 305 | if (unlikely(size > max_zpage_size)) |
| 302 | zram->stats.bad_compress--; | 306 | atomic_dec(&zram->stats.bad_compress); |
| 303 | 307 | ||
| 304 | zs_free(meta->mem_pool, handle); | 308 | zs_free(meta->mem_pool, handle); |
| 305 | 309 | ||
| 306 | if (size <= PAGE_SIZE / 2) | 310 | if (size <= PAGE_SIZE / 2) |
| 307 | zram->stats.good_compress--; | 311 | atomic_dec(&zram->stats.good_compress); |
| 308 | 312 | ||
| 309 | atomic64_sub(meta->table[index].size, &zram->stats.compr_size); | 313 | atomic64_sub(meta->table[index].size, &zram->stats.compr_size); |
| 310 | zram->stats.pages_stored--; | 314 | atomic_dec(&zram->stats.pages_stored); |
| 311 | 315 | ||
| 312 | meta->table[index].handle = 0; | 316 | meta->table[index].handle = 0; |
| 313 | meta->table[index].size = 0; | 317 | meta->table[index].size = 0; |
| @@ -319,20 +323,26 @@ static int zram_decompress_page(struct zram *zram, char *mem, u32 index) | |||
| 319 | size_t clen = PAGE_SIZE; | 323 | size_t clen = PAGE_SIZE; |
| 320 | unsigned char *cmem; | 324 | unsigned char *cmem; |
| 321 | struct zram_meta *meta = zram->meta; | 325 | struct zram_meta *meta = zram->meta; |
| 322 | unsigned long handle = meta->table[index].handle; | 326 | unsigned long handle; |
| 327 | u16 size; | ||
| 328 | |||
| 329 | read_lock(&meta->tb_lock); | ||
| 330 | handle = meta->table[index].handle; | ||
| 331 | size = meta->table[index].size; | ||
| 323 | 332 | ||
| 324 | if (!handle || zram_test_flag(meta, index, ZRAM_ZERO)) { | 333 | if (!handle || zram_test_flag(meta, index, ZRAM_ZERO)) { |
| 334 | read_unlock(&meta->tb_lock); | ||
| 325 | clear_page(mem); | 335 | clear_page(mem); |
| 326 | return 0; | 336 | return 0; |
| 327 | } | 337 | } |
| 328 | 338 | ||
| 329 | cmem = zs_map_object(meta->mem_pool, handle, ZS_MM_RO); | 339 | cmem = zs_map_object(meta->mem_pool, handle, ZS_MM_RO); |
| 330 | if (meta->table[index].size == PAGE_SIZE) | 340 | if (size == PAGE_SIZE) |
| 331 | copy_page(mem, cmem); | 341 | copy_page(mem, cmem); |
| 332 | else | 342 | else |
| 333 | ret = lzo1x_decompress_safe(cmem, meta->table[index].size, | 343 | ret = lzo1x_decompress_safe(cmem, size, mem, &clen); |
| 334 | mem, &clen); | ||
| 335 | zs_unmap_object(meta->mem_pool, handle); | 344 | zs_unmap_object(meta->mem_pool, handle); |
| 345 | read_unlock(&meta->tb_lock); | ||
| 336 | 346 | ||
| 337 | /* Should NEVER happen. Return bio error if it does. */ | 347 | /* Should NEVER happen. Return bio error if it does. */ |
| 338 | if (unlikely(ret != LZO_E_OK)) { | 348 | if (unlikely(ret != LZO_E_OK)) { |
| @@ -353,11 +363,14 @@ static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec, | |||
| 353 | struct zram_meta *meta = zram->meta; | 363 | struct zram_meta *meta = zram->meta; |
| 354 | page = bvec->bv_page; | 364 | page = bvec->bv_page; |
| 355 | 365 | ||
| 366 | read_lock(&meta->tb_lock); | ||
| 356 | if (unlikely(!meta->table[index].handle) || | 367 | if (unlikely(!meta->table[index].handle) || |
| 357 | zram_test_flag(meta, index, ZRAM_ZERO)) { | 368 | zram_test_flag(meta, index, ZRAM_ZERO)) { |
| 369 | read_unlock(&meta->tb_lock); | ||
| 358 | handle_zero_page(bvec); | 370 | handle_zero_page(bvec); |
| 359 | return 0; | 371 | return 0; |
| 360 | } | 372 | } |
| 373 | read_unlock(&meta->tb_lock); | ||
| 361 | 374 | ||
| 362 | if (is_partial_io(bvec)) | 375 | if (is_partial_io(bvec)) |
| 363 | /* Use a temporary buffer to decompress the page */ | 376 | /* Use a temporary buffer to decompress the page */ |
| @@ -400,6 +413,7 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, | |||
| 400 | struct page *page; | 413 | struct page *page; |
| 401 | unsigned char *user_mem, *cmem, *src, *uncmem = NULL; | 414 | unsigned char *user_mem, *cmem, *src, *uncmem = NULL; |
| 402 | struct zram_meta *meta = zram->meta; | 415 | struct zram_meta *meta = zram->meta; |
| 416 | bool locked = false; | ||
| 403 | 417 | ||
| 404 | page = bvec->bv_page; | 418 | page = bvec->bv_page; |
| 405 | src = meta->compress_buffer; | 419 | src = meta->compress_buffer; |
| @@ -419,6 +433,8 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, | |||
| 419 | goto out; | 433 | goto out; |
| 420 | } | 434 | } |
| 421 | 435 | ||
| 436 | mutex_lock(&meta->buffer_lock); | ||
| 437 | locked = true; | ||
| 422 | user_mem = kmap_atomic(page); | 438 | user_mem = kmap_atomic(page); |
| 423 | 439 | ||
| 424 | if (is_partial_io(bvec)) { | 440 | if (is_partial_io(bvec)) { |
| @@ -433,25 +449,18 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, | |||
| 433 | if (page_zero_filled(uncmem)) { | 449 | if (page_zero_filled(uncmem)) { |
| 434 | kunmap_atomic(user_mem); | 450 | kunmap_atomic(user_mem); |
| 435 | /* Free memory associated with this sector now. */ | 451 | /* Free memory associated with this sector now. */ |
| 452 | write_lock(&zram->meta->tb_lock); | ||
| 436 | zram_free_page(zram, index); | 453 | zram_free_page(zram, index); |
| 437 | |||
| 438 | zram->stats.pages_zero++; | ||
| 439 | zram_set_flag(meta, index, ZRAM_ZERO); | 454 | zram_set_flag(meta, index, ZRAM_ZERO); |
| 455 | write_unlock(&zram->meta->tb_lock); | ||
| 456 | |||
| 457 | atomic_inc(&zram->stats.pages_zero); | ||
| 440 | ret = 0; | 458 | ret = 0; |
| 441 | goto out; | 459 | goto out; |
| 442 | } | 460 | } |
| 443 | 461 | ||
| 444 | /* | ||
| 445 | * zram_slot_free_notify could miss free so that let's | ||
| 446 | * double check. | ||
| 447 | */ | ||
| 448 | if (unlikely(meta->table[index].handle || | ||
| 449 | zram_test_flag(meta, index, ZRAM_ZERO))) | ||
| 450 | zram_free_page(zram, index); | ||
| 451 | |||
| 452 | ret = lzo1x_1_compress(uncmem, PAGE_SIZE, src, &clen, | 462 | ret = lzo1x_1_compress(uncmem, PAGE_SIZE, src, &clen, |
| 453 | meta->compress_workmem); | 463 | meta->compress_workmem); |
| 454 | |||
| 455 | if (!is_partial_io(bvec)) { | 464 | if (!is_partial_io(bvec)) { |
| 456 | kunmap_atomic(user_mem); | 465 | kunmap_atomic(user_mem); |
| 457 | user_mem = NULL; | 466 | user_mem = NULL; |
| @@ -464,7 +473,7 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, | |||
| 464 | } | 473 | } |
| 465 | 474 | ||
| 466 | if (unlikely(clen > max_zpage_size)) { | 475 | if (unlikely(clen > max_zpage_size)) { |
| 467 | zram->stats.bad_compress++; | 476 | atomic_inc(&zram->stats.bad_compress); |
| 468 | clen = PAGE_SIZE; | 477 | clen = PAGE_SIZE; |
| 469 | src = NULL; | 478 | src = NULL; |
| 470 | if (is_partial_io(bvec)) | 479 | if (is_partial_io(bvec)) |
| @@ -494,18 +503,22 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, | |||
| 494 | * Free memory associated with this sector | 503 | * Free memory associated with this sector |
| 495 | * before overwriting unused sectors. | 504 | * before overwriting unused sectors. |
| 496 | */ | 505 | */ |
| 506 | write_lock(&zram->meta->tb_lock); | ||
| 497 | zram_free_page(zram, index); | 507 | zram_free_page(zram, index); |
| 498 | 508 | ||
| 499 | meta->table[index].handle = handle; | 509 | meta->table[index].handle = handle; |
| 500 | meta->table[index].size = clen; | 510 | meta->table[index].size = clen; |
| 511 | write_unlock(&zram->meta->tb_lock); | ||
| 501 | 512 | ||
| 502 | /* Update stats */ | 513 | /* Update stats */ |
| 503 | atomic64_add(clen, &zram->stats.compr_size); | 514 | atomic64_add(clen, &zram->stats.compr_size); |
| 504 | zram->stats.pages_stored++; | 515 | atomic_inc(&zram->stats.pages_stored); |
| 505 | if (clen <= PAGE_SIZE / 2) | 516 | if (clen <= PAGE_SIZE / 2) |
| 506 | zram->stats.good_compress++; | 517 | atomic_inc(&zram->stats.good_compress); |
| 507 | 518 | ||
| 508 | out: | 519 | out: |
| 520 | if (locked) | ||
| 521 | mutex_unlock(&meta->buffer_lock); | ||
| 509 | if (is_partial_io(bvec)) | 522 | if (is_partial_io(bvec)) |
| 510 | kfree(uncmem); | 523 | kfree(uncmem); |
| 511 | 524 | ||
| @@ -514,36 +527,15 @@ out: | |||
| 514 | return ret; | 527 | return ret; |
| 515 | } | 528 | } |
| 516 | 529 | ||
| 517 | static void handle_pending_slot_free(struct zram *zram) | ||
| 518 | { | ||
| 519 | struct zram_slot_free *free_rq; | ||
| 520 | |||
| 521 | spin_lock(&zram->slot_free_lock); | ||
| 522 | while (zram->slot_free_rq) { | ||
| 523 | free_rq = zram->slot_free_rq; | ||
| 524 | zram->slot_free_rq = free_rq->next; | ||
| 525 | zram_free_page(zram, free_rq->index); | ||
| 526 | kfree(free_rq); | ||
| 527 | } | ||
| 528 | spin_unlock(&zram->slot_free_lock); | ||
| 529 | } | ||
| 530 | |||
| 531 | static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index, | 530 | static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index, |
| 532 | int offset, struct bio *bio, int rw) | 531 | int offset, struct bio *bio, int rw) |
| 533 | { | 532 | { |
| 534 | int ret; | 533 | int ret; |
| 535 | 534 | ||
| 536 | if (rw == READ) { | 535 | if (rw == READ) |
| 537 | down_read(&zram->lock); | ||
| 538 | handle_pending_slot_free(zram); | ||
| 539 | ret = zram_bvec_read(zram, bvec, index, offset, bio); | 536 | ret = zram_bvec_read(zram, bvec, index, offset, bio); |
| 540 | up_read(&zram->lock); | 537 | else |
| 541 | } else { | ||
| 542 | down_write(&zram->lock); | ||
| 543 | handle_pending_slot_free(zram); | ||
| 544 | ret = zram_bvec_write(zram, bvec, index, offset); | 538 | ret = zram_bvec_write(zram, bvec, index, offset); |
| 545 | up_write(&zram->lock); | ||
| 546 | } | ||
| 547 | 539 | ||
| 548 | return ret; | 540 | return ret; |
| 549 | } | 541 | } |
| @@ -553,8 +545,6 @@ static void zram_reset_device(struct zram *zram, bool reset_capacity) | |||
| 553 | size_t index; | 545 | size_t index; |
| 554 | struct zram_meta *meta; | 546 | struct zram_meta *meta; |
| 555 | 547 | ||
| 556 | flush_work(&zram->free_work); | ||
| 557 | |||
| 558 | down_write(&zram->init_lock); | 548 | down_write(&zram->init_lock); |
| 559 | if (!zram->init_done) { | 549 | if (!zram->init_done) { |
| 560 | up_write(&zram->init_lock); | 550 | up_write(&zram->init_lock); |
| @@ -762,40 +752,19 @@ error: | |||
| 762 | bio_io_error(bio); | 752 | bio_io_error(bio); |
| 763 | } | 753 | } |
| 764 | 754 | ||
| 765 | static void zram_slot_free(struct work_struct *work) | ||
| 766 | { | ||
| 767 | struct zram *zram; | ||
| 768 | |||
| 769 | zram = container_of(work, struct zram, free_work); | ||
| 770 | down_write(&zram->lock); | ||
| 771 | handle_pending_slot_free(zram); | ||
| 772 | up_write(&zram->lock); | ||
| 773 | } | ||
| 774 | |||
| 775 | static void add_slot_free(struct zram *zram, struct zram_slot_free *free_rq) | ||
| 776 | { | ||
| 777 | spin_lock(&zram->slot_free_lock); | ||
| 778 | free_rq->next = zram->slot_free_rq; | ||
| 779 | zram->slot_free_rq = free_rq; | ||
| 780 | spin_unlock(&zram->slot_free_lock); | ||
| 781 | } | ||
| 782 | |||
| 783 | static void zram_slot_free_notify(struct block_device *bdev, | 755 | static void zram_slot_free_notify(struct block_device *bdev, |
| 784 | unsigned long index) | 756 | unsigned long index) |
| 785 | { | 757 | { |
| 786 | struct zram *zram; | 758 | struct zram *zram; |
| 787 | struct zram_slot_free *free_rq; | 759 | struct zram_meta *meta; |
| 788 | 760 | ||
| 789 | zram = bdev->bd_disk->private_data; | 761 | zram = bdev->bd_disk->private_data; |
| 790 | atomic64_inc(&zram->stats.notify_free); | 762 | meta = zram->meta; |
| 791 | |||
| 792 | free_rq = kmalloc(sizeof(struct zram_slot_free), GFP_ATOMIC); | ||
| 793 | if (!free_rq) | ||
| 794 | return; | ||
| 795 | 763 | ||
| 796 | free_rq->index = index; | 764 | write_lock(&meta->tb_lock); |
| 797 | add_slot_free(zram, free_rq); | 765 | zram_free_page(zram, index); |
| 798 | schedule_work(&zram->free_work); | 766 | write_unlock(&meta->tb_lock); |
| 767 | atomic64_inc(&zram->stats.notify_free); | ||
| 799 | } | 768 | } |
| 800 | 769 | ||
| 801 | static const struct block_device_operations zram_devops = { | 770 | static const struct block_device_operations zram_devops = { |
| @@ -839,13 +808,8 @@ static int create_device(struct zram *zram, int device_id) | |||
| 839 | { | 808 | { |
| 840 | int ret = -ENOMEM; | 809 | int ret = -ENOMEM; |
| 841 | 810 | ||
| 842 | init_rwsem(&zram->lock); | ||
| 843 | init_rwsem(&zram->init_lock); | 811 | init_rwsem(&zram->init_lock); |
| 844 | 812 | ||
| 845 | INIT_WORK(&zram->free_work, zram_slot_free); | ||
| 846 | spin_lock_init(&zram->slot_free_lock); | ||
| 847 | zram->slot_free_rq = NULL; | ||
| 848 | |||
| 849 | zram->queue = blk_alloc_queue(GFP_KERNEL); | 813 | zram->queue = blk_alloc_queue(GFP_KERNEL); |
| 850 | if (!zram->queue) { | 814 | if (!zram->queue) { |
| 851 | pr_err("Error allocating disk queue for device %d\n", | 815 | pr_err("Error allocating disk queue for device %d\n", |
diff --git a/drivers/staging/zram/zram_drv.h b/drivers/block/zram/zram_drv.h index 97a3acf6ab76..ad8aa35bae00 100644 --- a/drivers/staging/zram/zram_drv.h +++ b/drivers/block/zram/zram_drv.h | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | * Compressed RAM block device | 2 | * Compressed RAM block device |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2008, 2009, 2010 Nitin Gupta | 4 | * Copyright (C) 2008, 2009, 2010 Nitin Gupta |
| 5 | * 2012, 2013 Minchan Kim | ||
| 5 | * | 6 | * |
| 6 | * This code is released using a dual license strategy: BSD/GPL | 7 | * This code is released using a dual license strategy: BSD/GPL |
| 7 | * You can choose the licence that better fits your requirements. | 8 | * You can choose the licence that better fits your requirements. |
| @@ -9,7 +10,6 @@ | |||
| 9 | * Released under the terms of 3-clause BSD License | 10 | * Released under the terms of 3-clause BSD License |
| 10 | * Released under the terms of GNU General Public License Version 2.0 | 11 | * Released under the terms of GNU General Public License Version 2.0 |
| 11 | * | 12 | * |
| 12 | * Project home: http://compcache.googlecode.com | ||
| 13 | */ | 13 | */ |
| 14 | 14 | ||
| 15 | #ifndef _ZRAM_DRV_H_ | 15 | #ifndef _ZRAM_DRV_H_ |
| @@ -17,8 +17,7 @@ | |||
| 17 | 17 | ||
| 18 | #include <linux/spinlock.h> | 18 | #include <linux/spinlock.h> |
| 19 | #include <linux/mutex.h> | 19 | #include <linux/mutex.h> |
| 20 | 20 | #include <linux/zsmalloc.h> | |
| 21 | #include "../zsmalloc/zsmalloc.h" | ||
| 22 | 21 | ||
| 23 | /* | 22 | /* |
| 24 | * Some arbitrary value. This is just to catch | 23 | * Some arbitrary value. This is just to catch |
| @@ -69,10 +68,6 @@ struct table { | |||
| 69 | u8 flags; | 68 | u8 flags; |
| 70 | } __aligned(4); | 69 | } __aligned(4); |
| 71 | 70 | ||
| 72 | /* | ||
| 73 | * All 64bit fields should only be manipulated by 64bit atomic accessors. | ||
| 74 | * All modifications to 32bit counter should be protected by zram->lock. | ||
| 75 | */ | ||
| 76 | struct zram_stats { | 71 | struct zram_stats { |
| 77 | atomic64_t compr_size; /* compressed size of pages stored */ | 72 | atomic64_t compr_size; /* compressed size of pages stored */ |
| 78 | atomic64_t num_reads; /* failed + successful */ | 73 | atomic64_t num_reads; /* failed + successful */ |
| @@ -81,33 +76,23 @@ struct zram_stats { | |||
| 81 | atomic64_t failed_writes; /* can happen when memory is too low */ | 76 | atomic64_t failed_writes; /* can happen when memory is too low */ |
| 82 | atomic64_t invalid_io; /* non-page-aligned I/O requests */ | 77 | atomic64_t invalid_io; /* non-page-aligned I/O requests */ |
| 83 | atomic64_t notify_free; /* no. of swap slot free notifications */ | 78 | atomic64_t notify_free; /* no. of swap slot free notifications */ |
| 84 | u32 pages_zero; /* no. of zero filled pages */ | 79 | atomic_t pages_zero; /* no. of zero filled pages */ |
| 85 | u32 pages_stored; /* no. of pages currently stored */ | 80 | atomic_t pages_stored; /* no. of pages currently stored */ |
| 86 | u32 good_compress; /* % of pages with compression ratio<=50% */ | 81 | atomic_t good_compress; /* % of pages with compression ratio<=50% */ |
| 87 | u32 bad_compress; /* % of pages with compression ratio>=75% */ | 82 | atomic_t bad_compress; /* % of pages with compression ratio>=75% */ |
| 88 | }; | 83 | }; |
| 89 | 84 | ||
| 90 | struct zram_meta { | 85 | struct zram_meta { |
| 86 | rwlock_t tb_lock; /* protect table */ | ||
| 91 | void *compress_workmem; | 87 | void *compress_workmem; |
| 92 | void *compress_buffer; | 88 | void *compress_buffer; |
| 93 | struct table *table; | 89 | struct table *table; |
| 94 | struct zs_pool *mem_pool; | 90 | struct zs_pool *mem_pool; |
| 95 | }; | 91 | struct mutex buffer_lock; /* protect compress buffers */ |
| 96 | |||
| 97 | struct zram_slot_free { | ||
| 98 | unsigned long index; | ||
| 99 | struct zram_slot_free *next; | ||
| 100 | }; | 92 | }; |
| 101 | 93 | ||
| 102 | struct zram { | 94 | struct zram { |
| 103 | struct zram_meta *meta; | 95 | struct zram_meta *meta; |
| 104 | struct rw_semaphore lock; /* protect compression buffers, table, | ||
| 105 | * 32bit stat counters against concurrent | ||
| 106 | * notifications, reads and writes */ | ||
| 107 | |||
| 108 | struct work_struct free_work; /* handle pending free request */ | ||
| 109 | struct zram_slot_free *slot_free_rq; /* list head of free request */ | ||
| 110 | |||
| 111 | struct request_queue *queue; | 96 | struct request_queue *queue; |
| 112 | struct gendisk *disk; | 97 | struct gendisk *disk; |
| 113 | int init_done; | 98 | int init_done; |
| @@ -118,7 +103,6 @@ struct zram { | |||
| 118 | * we can store in a disk. | 103 | * we can store in a disk. |
| 119 | */ | 104 | */ |
| 120 | u64 disksize; /* bytes */ | 105 | u64 disksize; /* bytes */ |
| 121 | spinlock_t slot_free_lock; | ||
| 122 | 106 | ||
| 123 | struct zram_stats stats; | 107 | struct zram_stats stats; |
| 124 | }; | 108 | }; |
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 930694d3a13f..71e49000fbf3 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c | |||
| @@ -150,6 +150,7 @@ int mdiobus_register(struct mii_bus *bus) | |||
| 150 | err = device_register(&bus->dev); | 150 | err = device_register(&bus->dev); |
| 151 | if (err) { | 151 | if (err) { |
| 152 | pr_err("mii_bus %s failed to register\n", bus->id); | 152 | pr_err("mii_bus %s failed to register\n", bus->id); |
| 153 | put_device(&bus->dev); | ||
| 153 | return -EINVAL; | 154 | return -EINVAL; |
| 154 | } | 155 | } |
| 155 | 156 | ||
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 4bb6b11166b3..040a51525b42 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig | |||
| @@ -76,10 +76,6 @@ source "drivers/staging/sep/Kconfig" | |||
| 76 | 76 | ||
| 77 | source "drivers/staging/iio/Kconfig" | 77 | source "drivers/staging/iio/Kconfig" |
| 78 | 78 | ||
| 79 | source "drivers/staging/zsmalloc/Kconfig" | ||
| 80 | |||
| 81 | source "drivers/staging/zram/Kconfig" | ||
| 82 | |||
| 83 | source "drivers/staging/wlags49_h2/Kconfig" | 79 | source "drivers/staging/wlags49_h2/Kconfig" |
| 84 | 80 | ||
| 85 | source "drivers/staging/wlags49_h25/Kconfig" | 81 | source "drivers/staging/wlags49_h25/Kconfig" |
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 9f07e5e16094..dea056bf7ff2 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile | |||
| @@ -32,8 +32,6 @@ obj-$(CONFIG_VT6656) += vt6656/ | |||
| 32 | obj-$(CONFIG_VME_BUS) += vme/ | 32 | obj-$(CONFIG_VME_BUS) += vme/ |
| 33 | obj-$(CONFIG_DX_SEP) += sep/ | 33 | obj-$(CONFIG_DX_SEP) += sep/ |
| 34 | obj-$(CONFIG_IIO) += iio/ | 34 | obj-$(CONFIG_IIO) += iio/ |
| 35 | obj-$(CONFIG_ZRAM) += zram/ | ||
| 36 | obj-$(CONFIG_ZSMALLOC) += zsmalloc/ | ||
| 37 | obj-$(CONFIG_WLAGS49_H2) += wlags49_h2/ | 35 | obj-$(CONFIG_WLAGS49_H2) += wlags49_h2/ |
| 38 | obj-$(CONFIG_WLAGS49_H25) += wlags49_h25/ | 36 | obj-$(CONFIG_WLAGS49_H25) += wlags49_h25/ |
| 39 | obj-$(CONFIG_FB_SM7XX) += sm7xxfb/ | 37 | obj-$(CONFIG_FB_SM7XX) += sm7xxfb/ |
diff --git a/drivers/staging/zsmalloc/Kconfig b/drivers/staging/zsmalloc/Kconfig deleted file mode 100644 index 9d1f2a24ad62..000000000000 --- a/drivers/staging/zsmalloc/Kconfig +++ /dev/null | |||
| @@ -1,24 +0,0 @@ | |||
| 1 | config ZSMALLOC | ||
| 2 | bool "Memory allocator for compressed pages" | ||
| 3 | depends on MMU | ||
| 4 | default n | ||
| 5 | help | ||
| 6 | zsmalloc is a slab-based memory allocator designed to store | ||
| 7 | compressed RAM pages. zsmalloc uses virtual memory mapping | ||
| 8 | in order to reduce fragmentation. However, this results in a | ||
| 9 | non-standard allocator interface where a handle, not a pointer, is | ||
| 10 | returned by an alloc(). This handle must be mapped in order to | ||
| 11 | access the allocated space. | ||
| 12 | |||
| 13 | config PGTABLE_MAPPING | ||
| 14 | bool "Use page table mapping to access object in zsmalloc" | ||
| 15 | depends on ZSMALLOC | ||
| 16 | help | ||
| 17 | By default, zsmalloc uses a copy-based object mapping method to | ||
| 18 | access allocations that span two pages. However, if a particular | ||
| 19 | architecture (ex, ARM) performs VM mapping faster than copying, | ||
| 20 | then you should select this. This causes zsmalloc to use page table | ||
| 21 | mapping rather than copying for object mapping. | ||
| 22 | |||
| 23 | You can check speed with zsmalloc benchmark[1]. | ||
| 24 | [1] https://github.com/spartacus06/zsmalloc | ||
diff --git a/drivers/staging/zsmalloc/Makefile b/drivers/staging/zsmalloc/Makefile deleted file mode 100644 index b134848a590d..000000000000 --- a/drivers/staging/zsmalloc/Makefile +++ /dev/null | |||
| @@ -1,3 +0,0 @@ | |||
| 1 | zsmalloc-y := zsmalloc-main.o | ||
| 2 | |||
| 3 | obj-$(CONFIG_ZSMALLOC) += zsmalloc.o | ||
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c index 93cf15efc717..7de847df224f 100644 --- a/drivers/video/backlight/lcd.c +++ b/drivers/video/backlight/lcd.c | |||
| @@ -228,7 +228,7 @@ struct lcd_device *lcd_device_register(const char *name, struct device *parent, | |||
| 228 | 228 | ||
| 229 | rc = device_register(&new_ld->dev); | 229 | rc = device_register(&new_ld->dev); |
| 230 | if (rc) { | 230 | if (rc) { |
| 231 | kfree(new_ld); | 231 | put_device(&new_ld->dev); |
| 232 | return ERR_PTR(rc); | 232 | return ERR_PTR(rc); |
| 233 | } | 233 | } |
| 234 | 234 | ||
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 0375654adb28..8678c4322b44 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h | |||
| @@ -95,10 +95,7 @@ enum rq_cmd_type_bits { | |||
| 95 | * as well! | 95 | * as well! |
| 96 | */ | 96 | */ |
| 97 | struct request { | 97 | struct request { |
| 98 | union { | 98 | struct list_head queuelist; |
| 99 | struct list_head queuelist; | ||
| 100 | struct llist_node ll_list; | ||
| 101 | }; | ||
| 102 | union { | 99 | union { |
| 103 | struct call_single_data csd; | 100 | struct call_single_data csd; |
| 104 | struct work_struct mq_flush_data; | 101 | struct work_struct mq_flush_data; |
diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h index b388223bd4a9..db51fe4fe317 100644 --- a/include/linux/bootmem.h +++ b/include/linux/bootmem.h | |||
| @@ -264,7 +264,7 @@ static inline void * __init memblock_virt_alloc_low( | |||
| 264 | { | 264 | { |
| 265 | if (!align) | 265 | if (!align) |
| 266 | align = SMP_CACHE_BYTES; | 266 | align = SMP_CACHE_BYTES; |
| 267 | return __alloc_bootmem_low(size, align, BOOTMEM_LOW_LIMIT); | 267 | return __alloc_bootmem_low(size, align, 0); |
| 268 | } | 268 | } |
| 269 | 269 | ||
| 270 | static inline void * __init memblock_virt_alloc_low_nopanic( | 270 | static inline void * __init memblock_virt_alloc_low_nopanic( |
| @@ -272,7 +272,7 @@ static inline void * __init memblock_virt_alloc_low_nopanic( | |||
| 272 | { | 272 | { |
| 273 | if (!align) | 273 | if (!align) |
| 274 | align = SMP_CACHE_BYTES; | 274 | align = SMP_CACHE_BYTES; |
| 275 | return __alloc_bootmem_low_nopanic(size, align, BOOTMEM_LOW_LIMIT); | 275 | return __alloc_bootmem_low_nopanic(size, align, 0); |
| 276 | } | 276 | } |
| 277 | 277 | ||
| 278 | static inline void * __init memblock_virt_alloc_from_nopanic( | 278 | static inline void * __init memblock_virt_alloc_from_nopanic( |
diff --git a/include/linux/smp.h b/include/linux/smp.h index 5da22ee42e16..3834f43f9993 100644 --- a/include/linux/smp.h +++ b/include/linux/smp.h | |||
| @@ -11,12 +11,16 @@ | |||
| 11 | #include <linux/list.h> | 11 | #include <linux/list.h> |
| 12 | #include <linux/cpumask.h> | 12 | #include <linux/cpumask.h> |
| 13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
| 14 | #include <linux/llist.h> | ||
| 14 | 15 | ||
| 15 | extern void cpu_idle(void); | 16 | extern void cpu_idle(void); |
| 16 | 17 | ||
| 17 | typedef void (*smp_call_func_t)(void *info); | 18 | typedef void (*smp_call_func_t)(void *info); |
| 18 | struct call_single_data { | 19 | struct call_single_data { |
| 19 | struct list_head list; | 20 | union { |
| 21 | struct list_head list; | ||
| 22 | struct llist_node llist; | ||
| 23 | }; | ||
| 20 | smp_call_func_t func; | 24 | smp_call_func_t func; |
| 21 | void *info; | 25 | void *info; |
| 22 | u16 flags; | 26 | u16 flags; |
diff --git a/drivers/staging/zsmalloc/zsmalloc.h b/include/linux/zsmalloc.h index c2eb174b97ee..e44d634e7fb7 100644 --- a/drivers/staging/zsmalloc/zsmalloc.h +++ b/include/linux/zsmalloc.h | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | * zsmalloc memory allocator | 2 | * zsmalloc memory allocator |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2011 Nitin Gupta | 4 | * Copyright (C) 2011 Nitin Gupta |
| 5 | * Copyright (C) 2012, 2013 Minchan Kim | ||
| 5 | * | 6 | * |
| 6 | * This code is released using a dual license strategy: BSD/GPL | 7 | * This code is released using a dual license strategy: BSD/GPL |
| 7 | * You can choose the license that better fits your requirements. | 8 | * You can choose the license that better fits your requirements. |
diff --git a/kernel/smp.c b/kernel/smp.c index bd9f94028838..ffee35bef179 100644 --- a/kernel/smp.c +++ b/kernel/smp.c | |||
| @@ -23,17 +23,11 @@ enum { | |||
| 23 | struct call_function_data { | 23 | struct call_function_data { |
| 24 | struct call_single_data __percpu *csd; | 24 | struct call_single_data __percpu *csd; |
| 25 | cpumask_var_t cpumask; | 25 | cpumask_var_t cpumask; |
| 26 | cpumask_var_t cpumask_ipi; | ||
| 27 | }; | 26 | }; |
| 28 | 27 | ||
| 29 | static DEFINE_PER_CPU_SHARED_ALIGNED(struct call_function_data, cfd_data); | 28 | static DEFINE_PER_CPU_SHARED_ALIGNED(struct call_function_data, cfd_data); |
| 30 | 29 | ||
| 31 | struct call_single_queue { | 30 | static DEFINE_PER_CPU_SHARED_ALIGNED(struct llist_head, call_single_queue); |
| 32 | struct list_head list; | ||
| 33 | raw_spinlock_t lock; | ||
| 34 | }; | ||
| 35 | |||
| 36 | static DEFINE_PER_CPU_SHARED_ALIGNED(struct call_single_queue, call_single_queue); | ||
| 37 | 31 | ||
| 38 | static int | 32 | static int |
| 39 | hotplug_cfd(struct notifier_block *nfb, unsigned long action, void *hcpu) | 33 | hotplug_cfd(struct notifier_block *nfb, unsigned long action, void *hcpu) |
| @@ -47,14 +41,8 @@ hotplug_cfd(struct notifier_block *nfb, unsigned long action, void *hcpu) | |||
| 47 | if (!zalloc_cpumask_var_node(&cfd->cpumask, GFP_KERNEL, | 41 | if (!zalloc_cpumask_var_node(&cfd->cpumask, GFP_KERNEL, |
| 48 | cpu_to_node(cpu))) | 42 | cpu_to_node(cpu))) |
| 49 | return notifier_from_errno(-ENOMEM); | 43 | return notifier_from_errno(-ENOMEM); |
| 50 | if (!zalloc_cpumask_var_node(&cfd->cpumask_ipi, GFP_KERNEL, | ||
| 51 | cpu_to_node(cpu))) { | ||
| 52 | free_cpumask_var(cfd->cpumask); | ||
| 53 | return notifier_from_errno(-ENOMEM); | ||
| 54 | } | ||
| 55 | cfd->csd = alloc_percpu(struct call_single_data); | 44 | cfd->csd = alloc_percpu(struct call_single_data); |
| 56 | if (!cfd->csd) { | 45 | if (!cfd->csd) { |
| 57 | free_cpumask_var(cfd->cpumask_ipi); | ||
| 58 | free_cpumask_var(cfd->cpumask); | 46 | free_cpumask_var(cfd->cpumask); |
| 59 | return notifier_from_errno(-ENOMEM); | 47 | return notifier_from_errno(-ENOMEM); |
| 60 | } | 48 | } |
| @@ -67,7 +55,6 @@ hotplug_cfd(struct notifier_block *nfb, unsigned long action, void *hcpu) | |||
| 67 | case CPU_DEAD: | 55 | case CPU_DEAD: |
| 68 | case CPU_DEAD_FROZEN: | 56 | case CPU_DEAD_FROZEN: |
| 69 | free_cpumask_var(cfd->cpumask); | 57 | free_cpumask_var(cfd->cpumask); |
| 70 | free_cpumask_var(cfd->cpumask_ipi); | ||
| 71 | free_percpu(cfd->csd); | 58 | free_percpu(cfd->csd); |
| 72 | break; | 59 | break; |
| 73 | #endif | 60 | #endif |
| @@ -85,12 +72,8 @@ void __init call_function_init(void) | |||
| 85 | void *cpu = (void *)(long)smp_processor_id(); | 72 | void *cpu = (void *)(long)smp_processor_id(); |
| 86 | int i; | 73 | int i; |
| 87 | 74 | ||
| 88 | for_each_possible_cpu(i) { | 75 | for_each_possible_cpu(i) |
| 89 | struct call_single_queue *q = &per_cpu(call_single_queue, i); | 76 | init_llist_head(&per_cpu(call_single_queue, i)); |
| 90 | |||
| 91 | raw_spin_lock_init(&q->lock); | ||
| 92 | INIT_LIST_HEAD(&q->list); | ||
| 93 | } | ||
| 94 | 77 | ||
| 95 | hotplug_cfd(&hotplug_cfd_notifier, CPU_UP_PREPARE, cpu); | 78 | hotplug_cfd(&hotplug_cfd_notifier, CPU_UP_PREPARE, cpu); |
| 96 | register_cpu_notifier(&hotplug_cfd_notifier); | 79 | register_cpu_notifier(&hotplug_cfd_notifier); |
| @@ -141,18 +124,9 @@ static void csd_unlock(struct call_single_data *csd) | |||
| 141 | */ | 124 | */ |
| 142 | static void generic_exec_single(int cpu, struct call_single_data *csd, int wait) | 125 | static void generic_exec_single(int cpu, struct call_single_data *csd, int wait) |
| 143 | { | 126 | { |
| 144 | struct call_single_queue *dst = &per_cpu(call_single_queue, cpu); | ||
| 145 | unsigned long flags; | ||
| 146 | int ipi; | ||
| 147 | |||
| 148 | if (wait) | 127 | if (wait) |
| 149 | csd->flags |= CSD_FLAG_WAIT; | 128 | csd->flags |= CSD_FLAG_WAIT; |
| 150 | 129 | ||
| 151 | raw_spin_lock_irqsave(&dst->lock, flags); | ||
| 152 | ipi = list_empty(&dst->list); | ||
| 153 | list_add_tail(&csd->list, &dst->list); | ||
| 154 | raw_spin_unlock_irqrestore(&dst->lock, flags); | ||
| 155 | |||
| 156 | /* | 130 | /* |
| 157 | * The list addition should be visible before sending the IPI | 131 | * The list addition should be visible before sending the IPI |
| 158 | * handler locks the list to pull the entry off it because of | 132 | * handler locks the list to pull the entry off it because of |
| @@ -164,7 +138,7 @@ static void generic_exec_single(int cpu, struct call_single_data *csd, int wait) | |||
| 164 | * locking and barrier primitives. Generic code isn't really | 138 | * locking and barrier primitives. Generic code isn't really |
| 165 | * equipped to do the right thing... | 139 | * equipped to do the right thing... |
| 166 | */ | 140 | */ |
| 167 | if (ipi) | 141 | if (llist_add(&csd->llist, &per_cpu(call_single_queue, cpu))) |
| 168 | arch_send_call_function_single_ipi(cpu); | 142 | arch_send_call_function_single_ipi(cpu); |
| 169 | 143 | ||
| 170 | if (wait) | 144 | if (wait) |
| @@ -177,27 +151,26 @@ static void generic_exec_single(int cpu, struct call_single_data *csd, int wait) | |||
| 177 | */ | 151 | */ |
| 178 | void generic_smp_call_function_single_interrupt(void) | 152 | void generic_smp_call_function_single_interrupt(void) |
| 179 | { | 153 | { |
| 180 | struct call_single_queue *q = &__get_cpu_var(call_single_queue); | 154 | struct llist_node *entry, *next; |
| 181 | LIST_HEAD(list); | ||
| 182 | 155 | ||
| 183 | /* | 156 | /* |
| 184 | * Shouldn't receive this interrupt on a cpu that is not yet online. | 157 | * Shouldn't receive this interrupt on a cpu that is not yet online. |
| 185 | */ | 158 | */ |
| 186 | WARN_ON_ONCE(!cpu_online(smp_processor_id())); | 159 | WARN_ON_ONCE(!cpu_online(smp_processor_id())); |
| 187 | 160 | ||
| 188 | raw_spin_lock(&q->lock); | 161 | entry = llist_del_all(&__get_cpu_var(call_single_queue)); |
| 189 | list_replace_init(&q->list, &list); | 162 | entry = llist_reverse_order(entry); |
| 190 | raw_spin_unlock(&q->lock); | ||
| 191 | 163 | ||
| 192 | while (!list_empty(&list)) { | 164 | while (entry) { |
| 193 | struct call_single_data *csd; | 165 | struct call_single_data *csd; |
| 194 | 166 | ||
| 195 | csd = list_entry(list.next, struct call_single_data, list); | 167 | next = entry->next; |
| 196 | list_del(&csd->list); | ||
| 197 | 168 | ||
| 169 | csd = llist_entry(entry, struct call_single_data, llist); | ||
| 198 | csd->func(csd->info); | 170 | csd->func(csd->info); |
| 199 | |||
| 200 | csd_unlock(csd); | 171 | csd_unlock(csd); |
| 172 | |||
| 173 | entry = next; | ||
| 201 | } | 174 | } |
| 202 | } | 175 | } |
| 203 | 176 | ||
| @@ -402,30 +375,17 @@ void smp_call_function_many(const struct cpumask *mask, | |||
| 402 | if (unlikely(!cpumask_weight(cfd->cpumask))) | 375 | if (unlikely(!cpumask_weight(cfd->cpumask))) |
| 403 | return; | 376 | return; |
| 404 | 377 | ||
| 405 | /* | ||
| 406 | * After we put an entry into the list, cfd->cpumask may be cleared | ||
| 407 | * again when another CPU sends another IPI for a SMP function call, so | ||
| 408 | * cfd->cpumask will be zero. | ||
| 409 | */ | ||
| 410 | cpumask_copy(cfd->cpumask_ipi, cfd->cpumask); | ||
| 411 | |||
| 412 | for_each_cpu(cpu, cfd->cpumask) { | 378 | for_each_cpu(cpu, cfd->cpumask) { |
| 413 | struct call_single_data *csd = per_cpu_ptr(cfd->csd, cpu); | 379 | struct call_single_data *csd = per_cpu_ptr(cfd->csd, cpu); |
| 414 | struct call_single_queue *dst = | ||
| 415 | &per_cpu(call_single_queue, cpu); | ||
| 416 | unsigned long flags; | ||
| 417 | 380 | ||
| 418 | csd_lock(csd); | 381 | csd_lock(csd); |
| 419 | csd->func = func; | 382 | csd->func = func; |
| 420 | csd->info = info; | 383 | csd->info = info; |
| 421 | 384 | llist_add(&csd->llist, &per_cpu(call_single_queue, cpu)); | |
| 422 | raw_spin_lock_irqsave(&dst->lock, flags); | ||
| 423 | list_add_tail(&csd->list, &dst->list); | ||
| 424 | raw_spin_unlock_irqrestore(&dst->lock, flags); | ||
| 425 | } | 385 | } |
| 426 | 386 | ||
| 427 | /* Send a message to all CPUs in the map */ | 387 | /* Send a message to all CPUs in the map */ |
| 428 | arch_send_call_function_ipi_mask(cfd->cpumask_ipi); | 388 | arch_send_call_function_ipi_mask(cfd->cpumask); |
| 429 | 389 | ||
| 430 | if (wait) { | 390 | if (wait) { |
| 431 | for_each_cpu(cpu, cfd->cpumask) { | 391 | for_each_cpu(cpu, cfd->cpumask) { |
diff --git a/mm/Kconfig b/mm/Kconfig index 723bbe04a0b0..2d9f1504d75e 100644 --- a/mm/Kconfig +++ b/mm/Kconfig | |||
| @@ -552,3 +552,28 @@ config MEM_SOFT_DIRTY | |||
| 552 | it can be cleared by hands. | 552 | it can be cleared by hands. |
| 553 | 553 | ||
| 554 | See Documentation/vm/soft-dirty.txt for more details. | 554 | See Documentation/vm/soft-dirty.txt for more details. |
| 555 | |||
| 556 | config ZSMALLOC | ||
| 557 | bool "Memory allocator for compressed pages" | ||
| 558 | depends on MMU | ||
| 559 | default n | ||
| 560 | help | ||
| 561 | zsmalloc is a slab-based memory allocator designed to store | ||
| 562 | compressed RAM pages. zsmalloc uses virtual memory mapping | ||
| 563 | in order to reduce fragmentation. However, this results in a | ||
| 564 | non-standard allocator interface where a handle, not a pointer, is | ||
| 565 | returned by an alloc(). This handle must be mapped in order to | ||
| 566 | access the allocated space. | ||
| 567 | |||
| 568 | config PGTABLE_MAPPING | ||
| 569 | bool "Use page table mapping to access object in zsmalloc" | ||
| 570 | depends on ZSMALLOC | ||
| 571 | help | ||
| 572 | By default, zsmalloc uses a copy-based object mapping method to | ||
| 573 | access allocations that span two pages. However, if a particular | ||
| 574 | architecture (ex, ARM) performs VM mapping faster than copying, | ||
| 575 | then you should select this. This causes zsmalloc to use page table | ||
| 576 | mapping rather than copying for object mapping. | ||
| 577 | |||
| 578 | You can check speed with zsmalloc benchmark[1]. | ||
| 579 | [1] https://github.com/spartacus06/zsmalloc | ||
diff --git a/mm/Makefile b/mm/Makefile index 305d10acd081..310c90a09264 100644 --- a/mm/Makefile +++ b/mm/Makefile | |||
| @@ -60,3 +60,4 @@ obj-$(CONFIG_DEBUG_KMEMLEAK_TEST) += kmemleak-test.o | |||
| 60 | obj-$(CONFIG_CLEANCACHE) += cleancache.o | 60 | obj-$(CONFIG_CLEANCACHE) += cleancache.o |
| 61 | obj-$(CONFIG_MEMORY_ISOLATION) += page_isolation.o | 61 | obj-$(CONFIG_MEMORY_ISOLATION) += page_isolation.o |
| 62 | obj-$(CONFIG_ZBUD) += zbud.o | 62 | obj-$(CONFIG_ZBUD) += zbud.o |
| 63 | obj-$(CONFIG_ZSMALLOC) += zsmalloc.o | ||
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 19d5d4274e22..53385cd4e6f0 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
| @@ -3400,7 +3400,7 @@ void mem_cgroup_destroy_cache(struct kmem_cache *cachep) | |||
| 3400 | static struct kmem_cache *memcg_create_kmem_cache(struct mem_cgroup *memcg, | 3400 | static struct kmem_cache *memcg_create_kmem_cache(struct mem_cgroup *memcg, |
| 3401 | struct kmem_cache *s) | 3401 | struct kmem_cache *s) |
| 3402 | { | 3402 | { |
| 3403 | struct kmem_cache *new; | 3403 | struct kmem_cache *new = NULL; |
| 3404 | static char *tmp_name = NULL; | 3404 | static char *tmp_name = NULL; |
| 3405 | static DEFINE_MUTEX(mutex); /* protects tmp_name */ | 3405 | static DEFINE_MUTEX(mutex); /* protects tmp_name */ |
| 3406 | 3406 | ||
| @@ -3416,7 +3416,7 @@ static struct kmem_cache *memcg_create_kmem_cache(struct mem_cgroup *memcg, | |||
| 3416 | if (!tmp_name) { | 3416 | if (!tmp_name) { |
| 3417 | tmp_name = kmalloc(PATH_MAX, GFP_KERNEL); | 3417 | tmp_name = kmalloc(PATH_MAX, GFP_KERNEL); |
| 3418 | if (!tmp_name) | 3418 | if (!tmp_name) |
| 3419 | return NULL; | 3419 | goto out; |
| 3420 | } | 3420 | } |
| 3421 | 3421 | ||
| 3422 | rcu_read_lock(); | 3422 | rcu_read_lock(); |
| @@ -3426,12 +3426,11 @@ static struct kmem_cache *memcg_create_kmem_cache(struct mem_cgroup *memcg, | |||
| 3426 | 3426 | ||
| 3427 | new = kmem_cache_create_memcg(memcg, tmp_name, s->object_size, s->align, | 3427 | new = kmem_cache_create_memcg(memcg, tmp_name, s->object_size, s->align, |
| 3428 | (s->flags & ~SLAB_PANIC), s->ctor, s); | 3428 | (s->flags & ~SLAB_PANIC), s->ctor, s); |
| 3429 | |||
| 3430 | if (new) | 3429 | if (new) |
| 3431 | new->allocflags |= __GFP_KMEMCG; | 3430 | new->allocflags |= __GFP_KMEMCG; |
| 3432 | else | 3431 | else |
| 3433 | new = s; | 3432 | new = s; |
| 3434 | 3433 | out: | |
| 3435 | mutex_unlock(&mutex); | 3434 | mutex_unlock(&mutex); |
| 3436 | return new; | 3435 | return new; |
| 3437 | } | 3436 | } |
diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 873de7e542bc..ae3c8f3595d4 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c | |||
| @@ -2930,7 +2930,7 @@ void mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol) | |||
| 2930 | unsigned short mode = MPOL_DEFAULT; | 2930 | unsigned short mode = MPOL_DEFAULT; |
| 2931 | unsigned short flags = 0; | 2931 | unsigned short flags = 0; |
| 2932 | 2932 | ||
| 2933 | if (pol && pol != &default_policy) { | 2933 | if (pol && pol != &default_policy && !(pol->flags & MPOL_F_MORON)) { |
| 2934 | mode = pol->mode; | 2934 | mode = pol->mode; |
| 2935 | flags = pol->flags; | 2935 | flags = pol->flags; |
| 2936 | } | 2936 | } |
diff --git a/mm/oom_kill.c b/mm/oom_kill.c index 37b1b1903fb2..3291e82d4352 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c | |||
| @@ -178,7 +178,7 @@ unsigned long oom_badness(struct task_struct *p, struct mem_cgroup *memcg, | |||
| 178 | * implementation used by LSMs. | 178 | * implementation used by LSMs. |
| 179 | */ | 179 | */ |
| 180 | if (has_capability_noaudit(p, CAP_SYS_ADMIN)) | 180 | if (has_capability_noaudit(p, CAP_SYS_ADMIN)) |
| 181 | adj -= 30; | 181 | points -= (points * 3) / 100; |
| 182 | 182 | ||
| 183 | /* Normalize to oom_score_adj units */ | 183 | /* Normalize to oom_score_adj units */ |
| 184 | adj *= totalpages / 1000; | 184 | adj *= totalpages / 1000; |
| @@ -355,6 +355,21 @@ static __always_inline void slab_unlock(struct page *page) | |||
| 355 | __bit_spin_unlock(PG_locked, &page->flags); | 355 | __bit_spin_unlock(PG_locked, &page->flags); |
| 356 | } | 356 | } |
| 357 | 357 | ||
| 358 | static inline void set_page_slub_counters(struct page *page, unsigned long counters_new) | ||
| 359 | { | ||
| 360 | struct page tmp; | ||
| 361 | tmp.counters = counters_new; | ||
| 362 | /* | ||
| 363 | * page->counters can cover frozen/inuse/objects as well | ||
| 364 | * as page->_count. If we assign to ->counters directly | ||
| 365 | * we run the risk of losing updates to page->_count, so | ||
| 366 | * be careful and only assign to the fields we need. | ||
| 367 | */ | ||
| 368 | page->frozen = tmp.frozen; | ||
| 369 | page->inuse = tmp.inuse; | ||
| 370 | page->objects = tmp.objects; | ||
| 371 | } | ||
| 372 | |||
| 358 | /* Interrupts must be disabled (for the fallback code to work right) */ | 373 | /* Interrupts must be disabled (for the fallback code to work right) */ |
| 359 | static inline bool __cmpxchg_double_slab(struct kmem_cache *s, struct page *page, | 374 | static inline bool __cmpxchg_double_slab(struct kmem_cache *s, struct page *page, |
| 360 | void *freelist_old, unsigned long counters_old, | 375 | void *freelist_old, unsigned long counters_old, |
| @@ -376,7 +391,7 @@ static inline bool __cmpxchg_double_slab(struct kmem_cache *s, struct page *page | |||
| 376 | if (page->freelist == freelist_old && | 391 | if (page->freelist == freelist_old && |
| 377 | page->counters == counters_old) { | 392 | page->counters == counters_old) { |
| 378 | page->freelist = freelist_new; | 393 | page->freelist = freelist_new; |
| 379 | page->counters = counters_new; | 394 | set_page_slub_counters(page, counters_new); |
| 380 | slab_unlock(page); | 395 | slab_unlock(page); |
| 381 | return 1; | 396 | return 1; |
| 382 | } | 397 | } |
| @@ -415,7 +430,7 @@ static inline bool cmpxchg_double_slab(struct kmem_cache *s, struct page *page, | |||
| 415 | if (page->freelist == freelist_old && | 430 | if (page->freelist == freelist_old && |
| 416 | page->counters == counters_old) { | 431 | page->counters == counters_old) { |
| 417 | page->freelist = freelist_new; | 432 | page->freelist = freelist_new; |
| 418 | page->counters = counters_new; | 433 | set_page_slub_counters(page, counters_new); |
| 419 | slab_unlock(page); | 434 | slab_unlock(page); |
| 420 | local_irq_restore(flags); | 435 | local_irq_restore(flags); |
| 421 | return 1; | 436 | return 1; |
diff --git a/drivers/staging/zsmalloc/zsmalloc-main.c b/mm/zsmalloc.c index 7660c87d8b2a..c03ca5e9fe15 100644 --- a/drivers/staging/zsmalloc/zsmalloc-main.c +++ b/mm/zsmalloc.c | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | * zsmalloc memory allocator | 2 | * zsmalloc memory allocator |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2011 Nitin Gupta | 4 | * Copyright (C) 2011 Nitin Gupta |
| 5 | * Copyright (C) 2012, 2013 Minchan Kim | ||
| 5 | * | 6 | * |
| 6 | * This code is released using a dual license strategy: BSD/GPL | 7 | * This code is released using a dual license strategy: BSD/GPL |
| 7 | * You can choose the license that better fits your requirements. | 8 | * You can choose the license that better fits your requirements. |
| @@ -90,8 +91,7 @@ | |||
| 90 | #include <linux/hardirq.h> | 91 | #include <linux/hardirq.h> |
| 91 | #include <linux/spinlock.h> | 92 | #include <linux/spinlock.h> |
| 92 | #include <linux/types.h> | 93 | #include <linux/types.h> |
| 93 | 94 | #include <linux/zsmalloc.h> | |
| 94 | #include "zsmalloc.h" | ||
| 95 | 95 | ||
| 96 | /* | 96 | /* |
| 97 | * This must be power of 2 and greater than of equal to sizeof(link_free). | 97 | * This must be power of 2 and greater than of equal to sizeof(link_free). |
