0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/mman.h>
0014 #include <linux/swap.h>
0015 #include <linux/swapops.h>
0016 #include <linux/security.h>
0017 #include <linux/module.h>
0018 #include <linux/debugfs.h>
0019 #include <linux/frontswap.h>
0020 #include <linux/swapfile.h>
0021
0022 DEFINE_STATIC_KEY_FALSE(frontswap_enabled_key);
0023
0024
0025
0026
0027
0028
0029
0030 static const struct frontswap_ops *frontswap_ops __read_mostly;
0031
0032 #ifdef CONFIG_DEBUG_FS
0033
0034
0035
0036
0037
0038 static u64 frontswap_loads;
0039 static u64 frontswap_succ_stores;
0040 static u64 frontswap_failed_stores;
0041 static u64 frontswap_invalidates;
0042
0043 static inline void inc_frontswap_loads(void)
0044 {
0045 data_race(frontswap_loads++);
0046 }
0047 static inline void inc_frontswap_succ_stores(void)
0048 {
0049 data_race(frontswap_succ_stores++);
0050 }
0051 static inline void inc_frontswap_failed_stores(void)
0052 {
0053 data_race(frontswap_failed_stores++);
0054 }
0055 static inline void inc_frontswap_invalidates(void)
0056 {
0057 data_race(frontswap_invalidates++);
0058 }
0059 #else
0060 static inline void inc_frontswap_loads(void) { }
0061 static inline void inc_frontswap_succ_stores(void) { }
0062 static inline void inc_frontswap_failed_stores(void) { }
0063 static inline void inc_frontswap_invalidates(void) { }
0064 #endif
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097 int frontswap_register_ops(const struct frontswap_ops *ops)
0098 {
0099 if (frontswap_ops)
0100 return -EINVAL;
0101
0102 frontswap_ops = ops;
0103 static_branch_inc(&frontswap_enabled_key);
0104 return 0;
0105 }
0106
0107
0108
0109
0110 void frontswap_init(unsigned type, unsigned long *map)
0111 {
0112 struct swap_info_struct *sis = swap_info[type];
0113
0114 VM_BUG_ON(sis == NULL);
0115
0116
0117
0118
0119
0120 if (WARN_ON(!map))
0121 return;
0122
0123
0124
0125
0126
0127 frontswap_map_set(sis, map);
0128
0129 if (!frontswap_enabled())
0130 return;
0131 frontswap_ops->init(type);
0132 }
0133
0134 static bool __frontswap_test(struct swap_info_struct *sis,
0135 pgoff_t offset)
0136 {
0137 if (sis->frontswap_map)
0138 return test_bit(offset, sis->frontswap_map);
0139 return false;
0140 }
0141
0142 static inline void __frontswap_set(struct swap_info_struct *sis,
0143 pgoff_t offset)
0144 {
0145 set_bit(offset, sis->frontswap_map);
0146 atomic_inc(&sis->frontswap_pages);
0147 }
0148
0149 static inline void __frontswap_clear(struct swap_info_struct *sis,
0150 pgoff_t offset)
0151 {
0152 clear_bit(offset, sis->frontswap_map);
0153 atomic_dec(&sis->frontswap_pages);
0154 }
0155
0156
0157
0158
0159
0160
0161
0162
0163 int __frontswap_store(struct page *page)
0164 {
0165 int ret = -1;
0166 swp_entry_t entry = { .val = page_private(page), };
0167 int type = swp_type(entry);
0168 struct swap_info_struct *sis = swap_info[type];
0169 pgoff_t offset = swp_offset(entry);
0170
0171 VM_BUG_ON(!frontswap_ops);
0172 VM_BUG_ON(!PageLocked(page));
0173 VM_BUG_ON(sis == NULL);
0174
0175
0176
0177
0178
0179
0180
0181 if (__frontswap_test(sis, offset)) {
0182 __frontswap_clear(sis, offset);
0183 frontswap_ops->invalidate_page(type, offset);
0184 }
0185
0186 ret = frontswap_ops->store(type, offset, page);
0187 if (ret == 0) {
0188 __frontswap_set(sis, offset);
0189 inc_frontswap_succ_stores();
0190 } else {
0191 inc_frontswap_failed_stores();
0192 }
0193
0194 return ret;
0195 }
0196
0197
0198
0199
0200
0201
0202 int __frontswap_load(struct page *page)
0203 {
0204 int ret = -1;
0205 swp_entry_t entry = { .val = page_private(page), };
0206 int type = swp_type(entry);
0207 struct swap_info_struct *sis = swap_info[type];
0208 pgoff_t offset = swp_offset(entry);
0209
0210 VM_BUG_ON(!frontswap_ops);
0211 VM_BUG_ON(!PageLocked(page));
0212 VM_BUG_ON(sis == NULL);
0213
0214 if (!__frontswap_test(sis, offset))
0215 return -1;
0216
0217
0218 ret = frontswap_ops->load(type, offset, page);
0219 if (ret == 0)
0220 inc_frontswap_loads();
0221 return ret;
0222 }
0223
0224
0225
0226
0227
0228 void __frontswap_invalidate_page(unsigned type, pgoff_t offset)
0229 {
0230 struct swap_info_struct *sis = swap_info[type];
0231
0232 VM_BUG_ON(!frontswap_ops);
0233 VM_BUG_ON(sis == NULL);
0234
0235 if (!__frontswap_test(sis, offset))
0236 return;
0237
0238 frontswap_ops->invalidate_page(type, offset);
0239 __frontswap_clear(sis, offset);
0240 inc_frontswap_invalidates();
0241 }
0242
0243
0244
0245
0246
0247 void __frontswap_invalidate_area(unsigned type)
0248 {
0249 struct swap_info_struct *sis = swap_info[type];
0250
0251 VM_BUG_ON(!frontswap_ops);
0252 VM_BUG_ON(sis == NULL);
0253
0254 if (sis->frontswap_map == NULL)
0255 return;
0256
0257 frontswap_ops->invalidate_area(type);
0258 atomic_set(&sis->frontswap_pages, 0);
0259 bitmap_zero(sis->frontswap_map, sis->max);
0260 }
0261
0262 static int __init init_frontswap(void)
0263 {
0264 #ifdef CONFIG_DEBUG_FS
0265 struct dentry *root = debugfs_create_dir("frontswap", NULL);
0266 if (root == NULL)
0267 return -ENXIO;
0268 debugfs_create_u64("loads", 0444, root, &frontswap_loads);
0269 debugfs_create_u64("succ_stores", 0444, root, &frontswap_succ_stores);
0270 debugfs_create_u64("failed_stores", 0444, root,
0271 &frontswap_failed_stores);
0272 debugfs_create_u64("invalidates", 0444, root, &frontswap_invalidates);
0273 #endif
0274 return 0;
0275 }
0276
0277 module_init(init_frontswap);