@@ -40,4 +40,5 @@ int zcomp_decompress(struct zcomp_strm *zstrm,
const void *src, unsigned int src_len, void *dst);
bool zcomp_set_max_streams(struct zcomp *comp, int num_strm);
+int get_zram_major(void);
#endif /* _ZCOMP_H_ */
@@ -59,6 +59,10 @@ static void zram_free_page(struct zram *zram, size_t index);
static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec,
u32 index, int offset, struct bio *bio);
+int get_zram_major(void)
+{
+ return zram_major;
+}
static int zram_slot_trylock(struct zram *zram, u32 index)
{
@@ -1040,6 +1044,19 @@ static ssize_t compact_store(struct device *dev,
return len;
}
+static ssize_t min_compr_ratio_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct zram *zram = dev_to_zram(dev);
+ ssize_t ret;
+
+ down_read(&zram->init_lock);
+ ret = scnprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&zram->stats.min_compr_ratio));
+ up_read(&zram->init_lock);
+
+ return ret;
+}
+
static ssize_t io_stat_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -1132,6 +1149,7 @@ static ssize_t debug_stat_show(struct device *dev,
return ret;
}
+static DEVICE_ATTR_RO(min_compr_ratio);
static DEVICE_ATTR_RO(io_stat);
static DEVICE_ATTR_RO(mm_stat);
#ifdef CONFIG_ZRAM_WRITEBACK
@@ -1859,6 +1877,7 @@ static struct attribute *zram_disk_attrs[] = {
&dev_attr_idle.attr,
&dev_attr_max_comp_streams.attr,
&dev_attr_comp_algorithm.attr,
+ &dev_attr_min_compr_ratio.attr,
#ifdef CONFIG_ZRAM_WRITEBACK
&dev_attr_backing_dev.attr,
&dev_attr_writeback.attr,
@@ -88,6 +88,7 @@ struct zram_stats {
atomic64_t bd_reads; /* no. of reads from backing device */
atomic64_t bd_writes; /* no. of writes from backing device */
#endif
+ atomic_t min_compr_ratio;
};
struct zram {
@@ -86,6 +86,7 @@ static int meminfo_proc_show(struct seq_file *m, void *v)
show_val_kb(m, "SwapTotal: ", i.totalswap);
show_val_kb(m, "SwapFree: ", i.freeswap);
+ show_val_kb(m, "SwapAvailable: ", count_avail_swaps());
show_val_kb(m, "Dirty: ",
global_node_page_state(NR_FILE_DIRTY));
show_val_kb(m, "Writeback: ",
@@ -515,6 +515,8 @@ extern int init_swap_address_space(unsigned int type, unsigned long nr_pages);
extern void exit_swap_address_space(unsigned int type);
extern struct swap_info_struct *get_swap_device(swp_entry_t entry);
sector_t swap_page_sector(struct page *page);
+extern void update_zram_zstats(void);
+extern u64 count_avail_swaps(void);
static inline void put_swap_device(struct swap_info_struct *si)
{
@@ -689,6 +691,14 @@ static inline swp_entry_t get_swap_page(struct page *page)
return entry;
}
+void update_zram_zstats(void)
+{
+}
+
+u64 count_avail_swaps(void)
+{
+}
+
#endif /* CONFIG_SWAP */
#ifdef CONFIG_THP_SWAP
@@ -44,6 +44,7 @@
#include <asm/tlbflush.h>
#include <linux/swapops.h>
#include <linux/swap_cgroup.h>
+#include "../drivers/block/zram/zram_drv.h"
static bool swap_count_continued(struct swap_info_struct *, pgoff_t,
unsigned char);
@@ -3387,6 +3388,100 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
return error;
}
+u64 count_avail_swap(struct swap_info_struct *si)
+{
+ u64 result;
+ struct zram *z;
+ unsigned int free;
+ unsigned int ratio;
+
+ result = 0;
+ if (!si)
+ return 0;
+
+ //zram calculate available mem
+ if (si->flags & SWP_USED && si->swap_map) {
+ if (si->bdev->bd_disk->major == get_zram_major()) {
+ z = (struct zram *)si->bdev->bd_disk->private_data;
+ down_read(&z->init_lock);
+ ratio = atomic_read(&z->stats.min_compr_ratio);
+ free = (si->pages << (PAGE_SHIFT - 10))
+ - (si->inuse_pages << (PAGE_SHIFT - 10));
+ if (!ratio)
+ result += free / 2;
+ else
+ result = free * (100 - 10000 / ratio) / 100;
+ up_read(&z->init_lock);
+ }
+ } else
+ result += (si->pages << (PAGE_SHIFT - 10))
+ - (si->inuse_pages << (PAGE_SHIFT - 10));
+
+ return result;
+}
+
+u64 count_avail_swaps(void)
+{
+ int type;
+ u64 result;
+ struct swap_info_struct *si;
+
+ result = 0;
+ spin_lock(&swap_lock);
+ for (type = 0; type < nr_swapfiles; type++) {
+ si = swap_info[type];
+ spin_lock(&si->lock);
+ result += count_avail_swap(si);
+ spin_unlock(&si->lock);
+ }
+ spin_unlock(&swap_lock);
+
+ return result;
+}
+
+void update_zram_zstat(struct swap_info_struct *si)
+{
+ struct zram *z;
+ struct zram_stats *stat;
+ int ratio;
+ u64 orig_size, compr_data_size;
+
+ if (!si)
+ return;
+
+ //update zram min compress ratio
+ if (si->flags & SWP_USED && si->swap_map) {
+ if (si->bdev->bd_disk->major == get_zram_major()) {
+ z = (struct zram *)si->bdev->bd_disk->private_data;
+ down_read(&z->init_lock);
+ stat = &z->stats;
+ ratio = atomic_read(&stat->min_compr_ratio);
+ orig_size = atomic64_read(&stat->pages_stored) << PAGE_SHIFT;
+ compr_data_size = atomic64_read(&stat->compr_data_size);
+ if (compr_data_size && (!ratio
+ || ((orig_size * 100) / compr_data_size < ratio)))
+ atomic_set(&stat->min_compr_ratio,
+ (orig_size * 100) / compr_data_size);
+ up_read(&z->init_lock);
+ }
+ }
+}
+
+void update_zram_zstats(void)
+{
+ int type;
+ struct swap_info_struct *si;
+
+ spin_lock(&swap_lock);
+ for (type = 0; type < nr_swapfiles; type++) {
+ si = swap_info[type];
+ spin_lock(&si->lock);
+ update_zram_zstat(si);
+ spin_unlock(&si->lock);
+ }
+ spin_unlock(&swap_lock);
+}
+
void si_swapinfo(struct sysinfo *val)
{
unsigned int type;
@@ -4159,6 +4159,7 @@ static int kswapd(void *p)
alloc_order);
reclaim_order = balance_pgdat(pgdat, alloc_order,
highest_zoneidx);
+ update_zram_zstats();
if (reclaim_order < alloc_order)
goto kswapd_try_sleep;
}