Commit | Line | Data |
---|---|---|
306b0c95 | 1 | /* |
f1e3cfff | 2 | * Compressed RAM block device |
306b0c95 | 3 | * |
1130ebba | 4 | * Copyright (C) 2008, 2009, 2010 Nitin Gupta |
306b0c95 NG |
5 | * |
6 | * This code is released using a dual license strategy: BSD/GPL | |
7 | * You can choose the licence that better fits your requirements. | |
8 | * | |
9 | * Released under the terms of 3-clause BSD License | |
10 | * Released under the terms of GNU General Public License Version 2.0 | |
11 | * | |
12 | * Project home: http://compcache.googlecode.com | |
13 | */ | |
14 | ||
f1e3cfff NG |
15 | #ifndef _ZRAM_DRV_H_ |
16 | #define _ZRAM_DRV_H_ | |
306b0c95 | 17 | |
6a907728 NG |
18 | #include <linux/spinlock.h> |
19 | #include <linux/mutex.h> | |
20 | ||
fd1a30de | 21 | #include "../zsmalloc/zsmalloc.h" |
306b0c95 NG |
22 | |
23 | /* | |
24 | * Some arbitrary value. This is just to catch | |
25 | * invalid value for num_devices module parameter. | |
26 | */ | |
27 | static const unsigned max_num_devices = 32; | |
28 | ||
306b0c95 NG |
29 | /*-- Configurable parameters */ |
30 | ||
6fa3eb70 S |
31 | /* Default zram disk size: 50% of total RAM */ |
32 | static const unsigned default_disksize_perc_ram = 50; /* 25 */ | |
33 | /* Let disk size be DISKSIZE_ALIGNMENT */ | |
34 | #define DISKSIZE_ALIGNMENT 0x2000000 /* 32MB */ | |
35 | /* Is totalram_pages less than SUPPOSED_TOTALRAM? */ | |
36 | #define SUPPOSED_TOTALRAM 0x20000 /* 512MB */ | |
37 | ||
306b0c95 | 38 | /* |
306b0c95 NG |
39 | * Pages that compress to size greater than this are stored |
40 | * uncompressed in memory. | |
41 | */ | |
2ccbec05 | 42 | static const size_t max_zpage_size = PAGE_SIZE / 4 * 3; |
306b0c95 NG |
43 | |
44 | /* | |
97a06382 | 45 | * NOTE: max_zpage_size must be less than or equal to: |
55dcbbb1 MK |
46 | * ZS_MAX_ALLOC_SIZE. Otherwise, zs_malloc() would |
47 | * always return failure. | |
306b0c95 NG |
48 | */ |
49 | ||
50 | /*-- End of configurable params */ | |
51 | ||
52 | #define SECTOR_SHIFT 9 | |
53 | #define SECTOR_SIZE (1 << SECTOR_SHIFT) | |
54 | #define SECTORS_PER_PAGE_SHIFT (PAGE_SHIFT - SECTOR_SHIFT) | |
55 | #define SECTORS_PER_PAGE (1 << SECTORS_PER_PAGE_SHIFT) | |
924bd88d JM |
56 | #define ZRAM_LOGICAL_BLOCK_SHIFT 12 |
57 | #define ZRAM_LOGICAL_BLOCK_SIZE (1 << ZRAM_LOGICAL_BLOCK_SHIFT) | |
58 | #define ZRAM_SECTOR_PER_LOGICAL_BLOCK \ | |
59 | (1 << (ZRAM_LOGICAL_BLOCK_SHIFT - SECTOR_SHIFT)) | |
306b0c95 | 60 | |
f1e3cfff NG |
61 | /* Flags for zram pages (table[page_no].flags) */ |
62 | enum zram_pageflags { | |
306b0c95 | 63 | /* Page consists entirely of zeros */ |
f1e3cfff | 64 | ZRAM_ZERO, |
306b0c95 | 65 | |
f1e3cfff | 66 | __NR_ZRAM_PAGEFLAGS, |
6fa3eb70 S |
67 | #ifdef CONFIG_ZSM |
68 | ZRAM_FIRST_NODE , | |
69 | ZRAM_RB_NODE | |
70 | #endif | |
306b0c95 NG |
71 | }; |
72 | ||
73 | /*-- Data structures */ | |
74 | ||
f1e3cfff | 75 | /* Allocated for each disk page */ |
306b0c95 | 76 | struct table { |
c2344348 | 77 | unsigned long handle; |
fd1a30de | 78 | u16 size; /* object size (excluding header) */ |
306b0c95 NG |
79 | u8 count; /* object ref count (not yet used) */ |
80 | u8 flags; | |
6fa3eb70 S |
81 | #if CONFIG_ZSM |
82 | struct rb_node node; | |
83 | struct list_head head; | |
84 | u32 copy_count; | |
85 | u32 next_index; | |
86 | u32 copy_index; | |
87 | u32 checksum; | |
88 | #endif | |
80677c25 | 89 | } __aligned(4); |
306b0c95 | 90 | |
f1e3cfff | 91 | struct zram_stats { |
33863c21 | 92 | u64 compr_size; /* compressed size of pages stored */ |
306b0c95 NG |
93 | u64 num_reads; /* failed + successful */ |
94 | u64 num_writes; /* --do-- */ | |
ef4ffb7a | 95 | u64 failed_reads; /* should NEVER! happen */ |
96 | u64 failed_writes; /* can happen when memory is too low */ | |
f1e3cfff | 97 | u64 invalid_io; /* non-page-aligned I/O requests */ |
6a907728 | 98 | u64 notify_free; /* no. of swap slot free notifications */ |
6fa3eb70 S |
99 | #ifdef CONFIG_ZSM |
100 | u64 zsm_saved; /* saved physical size*/ | |
101 | u64 zsm_saved4k; | |
102 | #endif | |
306b0c95 NG |
103 | u32 pages_zero; /* no. of zero filled pages */ |
104 | u32 pages_stored; /* no. of pages currently stored */ | |
105 | u32 good_compress; /* % of pages with compression ratio<=50% */ | |
130f315a | 106 | u32 bad_compress; /* % of pages with compression ratio>=75% */ |
306b0c95 NG |
107 | }; |
108 | ||
8b3cc3ed | 109 | struct zram_meta { |
306b0c95 NG |
110 | void *compress_workmem; |
111 | void *compress_buffer; | |
112 | struct table *table; | |
8b3cc3ed MK |
113 | struct zs_pool *mem_pool; |
114 | }; | |
115 | ||
116 | struct zram { | |
117 | struct zram_meta *meta; | |
6a907728 | 118 | spinlock_t stat64_lock; /* protect 64-bit stats */ |
6349a112 JL |
119 | struct rw_semaphore lock; /* protect compression buffers, table, |
120 | * 32bit stat counters against concurrent | |
121 | * notifications, reads and writes */ | |
306b0c95 NG |
122 | struct request_queue *queue; |
123 | struct gendisk *disk; | |
124 | int init_done; | |
0900beae JM |
125 | /* Prevent concurrent execution of device init, reset and R/W request */ |
126 | struct rw_semaphore init_lock; | |
306b0c95 | 127 | /* |
f1e3cfff NG |
128 | * This is the limit on amount of *uncompressed* worth of data |
129 | * we can store in a disk. | |
306b0c95 | 130 | */ |
33863c21 | 131 | u64 disksize; /* bytes */ |
306b0c95 | 132 | |
f1e3cfff | 133 | struct zram_stats stats; |
306b0c95 NG |
134 | }; |
135 | ||
43801f6e | 136 | extern struct zram *zram_devices; |
5fa5a901 | 137 | unsigned int zram_get_num_devices(void); |
33863c21 NG |
138 | #ifdef CONFIG_SYSFS |
139 | extern struct attribute_group zram_disk_attr_group; | |
140 | #endif | |
141 | ||
0231c403 | 142 | extern void zram_reset_device(struct zram *zram); |
8b3cc3ed MK |
143 | extern struct zram_meta *zram_meta_alloc(u64 disksize); |
144 | extern void zram_meta_free(struct zram_meta *meta); | |
145 | extern void zram_init_device(struct zram *zram, struct zram_meta *meta); | |
306b0c95 | 146 | |
6fa3eb70 S |
147 | /* Type for zram compression/decompression hooks */ |
148 | #ifdef CONFIG_ZSM | |
149 | typedef int (*comp_hook) (const unsigned char *, size_t , unsigned char *, size_t *, void *, int *); | |
150 | #else | |
151 | typedef int (*comp_hook) (const unsigned char *, size_t , unsigned char *, size_t *, void *); | |
152 | #endif | |
153 | typedef int (*decomp_hook) (const unsigned char *, size_t , unsigned char *, size_t *); | |
154 | ||
6a907728 | 155 | #endif |