#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/blktrans.h>
#include <linux/rbtree.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/blkdev.h>
#include <linux/swap.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/device.h>
#include <linux/math64.h>
#define MTDSWAP_PREFIX …
#define CLEAN_BLOCK_THRESHOLD …
#define LOW_FRAG_GC_THRESHOLD …
#define MAX_ERASE_DIFF …
#define COLLECT_NONDIRTY_BASE …
#define COLLECT_NONDIRTY_FREQ1 …
#define COLLECT_NONDIRTY_FREQ2 …
#define PAGE_UNDEF …
#define BLOCK_UNDEF …
#define BLOCK_ERROR …
#define BLOCK_MAX …
#define EBLOCK_BAD …
#define EBLOCK_NOMAGIC …
#define EBLOCK_BITFLIP …
#define EBLOCK_FAILED …
#define EBLOCK_READERR …
#define EBLOCK_IDX_SHIFT …
struct swap_eb { … };
#define MTDSWAP_ECNT_MIN(rbroot) …
#define MTDSWAP_ECNT_MAX(rbroot) …
struct mtdswap_tree { … };
enum { … };
struct mtdswap_dev { … };
struct mtdswap_oobdata { … } __packed;
#define MTDSWAP_MAGIC_CLEAN …
#define MTDSWAP_MAGIC_DIRTY …
#define MTDSWAP_TYPE_CLEAN …
#define MTDSWAP_TYPE_DIRTY …
#define MTDSWAP_OOBSIZE …
#define MTDSWAP_ERASE_RETRIES …
#define MTDSWAP_IO_RETRIES …
enum { … };
#define MIN_SPARE_EBLOCKS …
#define MIN_ERASE_BLOCKS …
#define TREE_ROOT(d, name) …
#define TREE_EMPTY(d, name) …
#define TREE_NONEMPTY(d, name) …
#define TREE_COUNT(d, name) …
#define MTDSWAP_MBD_TO_MTDSWAP(dev) …
static char partitions[128] = …;
module_param_string(…);
MODULE_PARM_DESC(…) …;
static unsigned int spare_eblocks = …;
module_param(spare_eblocks, uint, 0444);
MODULE_PARM_DESC(…) …;
static bool header;
module_param(header, bool, 0444);
MODULE_PARM_DESC(…) …;
static int mtdswap_gc(struct mtdswap_dev *d, unsigned int background);
static loff_t mtdswap_eb_offset(struct mtdswap_dev *d, struct swap_eb *eb)
{ … }
static void mtdswap_eb_detach(struct mtdswap_dev *d, struct swap_eb *eb)
{ … }
static void __mtdswap_rb_add(struct rb_root *root, struct swap_eb *eb)
{ … }
static void mtdswap_rb_add(struct mtdswap_dev *d, struct swap_eb *eb, int idx)
{ … }
static struct rb_node *mtdswap_rb_index(struct rb_root *root, unsigned int idx)
{ … }
static int mtdswap_handle_badblock(struct mtdswap_dev *d, struct swap_eb *eb)
{ … }
static int mtdswap_handle_write_error(struct mtdswap_dev *d, struct swap_eb *eb)
{ … }
static int mtdswap_read_oob(struct mtdswap_dev *d, loff_t from,
struct mtd_oob_ops *ops)
{ … }
static int mtdswap_read_markers(struct mtdswap_dev *d, struct swap_eb *eb)
{ … }
static int mtdswap_write_marker(struct mtdswap_dev *d, struct swap_eb *eb,
u16 marker)
{ … }
static void mtdswap_check_counts(struct mtdswap_dev *d)
{ … }
static void mtdswap_scan_eblks(struct mtdswap_dev *d)
{ … }
static void mtdswap_store_eb(struct mtdswap_dev *d, struct swap_eb *eb)
{ … }
static int mtdswap_erase_block(struct mtdswap_dev *d, struct swap_eb *eb)
{ … }
static int mtdswap_map_free_block(struct mtdswap_dev *d, unsigned int page,
unsigned int *block)
{ … }
static unsigned int mtdswap_free_page_cnt(struct mtdswap_dev *d)
{ … }
static unsigned int mtdswap_enough_free_pages(struct mtdswap_dev *d)
{ … }
static int mtdswap_write_block(struct mtdswap_dev *d, char *buf,
unsigned int page, unsigned int *bp, int gc_context)
{ … }
static int mtdswap_move_block(struct mtdswap_dev *d, unsigned int oldblock,
unsigned int *newblock)
{ … }
static int mtdswap_gc_eblock(struct mtdswap_dev *d, struct swap_eb *eb)
{ … }
static int __mtdswap_choose_gc_tree(struct mtdswap_dev *d)
{ … }
static int mtdswap_wlfreq(unsigned int maxdiff)
{ … }
static int mtdswap_choose_wl_tree(struct mtdswap_dev *d)
{ … }
static int mtdswap_choose_gc_tree(struct mtdswap_dev *d,
unsigned int background)
{ … }
static struct swap_eb *mtdswap_pick_gc_eblk(struct mtdswap_dev *d,
unsigned int background)
{ … }
static unsigned int mtdswap_test_patt(unsigned int i)
{ … }
static unsigned int mtdswap_eblk_passes(struct mtdswap_dev *d,
struct swap_eb *eb)
{ … }
static int mtdswap_gc(struct mtdswap_dev *d, unsigned int background)
{ … }
static void mtdswap_background(struct mtd_blktrans_dev *dev)
{ … }
static void mtdswap_cleanup(struct mtdswap_dev *d)
{ … }
static int mtdswap_flush(struct mtd_blktrans_dev *dev)
{ … }
static unsigned int mtdswap_badblocks(struct mtd_info *mtd, uint64_t size)
{ … }
static int mtdswap_writesect(struct mtd_blktrans_dev *dev,
unsigned long page, char *buf)
{ … }
static int mtdswap_auto_header(struct mtdswap_dev *d, char *buf)
{ … }
static int mtdswap_readsect(struct mtd_blktrans_dev *dev,
unsigned long page, char *buf)
{ … }
static int mtdswap_discard(struct mtd_blktrans_dev *dev, unsigned long first,
unsigned nr_pages)
{ … }
static int mtdswap_show(struct seq_file *s, void *data)
{ … }
DEFINE_SHOW_ATTRIBUTE(…);
static int mtdswap_add_debugfs(struct mtdswap_dev *d)
{ … }
static int mtdswap_init(struct mtdswap_dev *d, unsigned int eblocks,
unsigned int spare_cnt)
{ … }
static void mtdswap_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
{ … }
static void mtdswap_remove_dev(struct mtd_blktrans_dev *dev)
{ … }
static struct mtd_blktrans_ops mtdswap_ops = …;
module_mtd_blktrans(…);
MODULE_LICENSE(…) …;
MODULE_AUTHOR(…) …;
MODULE_DESCRIPTION(…) …;