Merge branch 'for-3.18/drivers' of git://git.kernel.dk/linux-block
[firefly-linux-kernel-4.4.55.git] / drivers / block / zram / zram_drv.c
index 6dd2cef5b865e8f360add0c838068891cbe7e420..0e63e8aa8279a7993344f15d0d2f48b2536b497a 100644 (file)
@@ -103,10 +103,10 @@ static ssize_t mem_used_total_show(struct device *dev,
 
        down_read(&zram->init_lock);
        if (init_done(zram))
-               val = zs_get_total_size_bytes(meta->mem_pool);
+               val = zs_get_total_pages(meta->mem_pool);
        up_read(&zram->init_lock);
 
-       return scnprintf(buf, PAGE_SIZE, "%llu\n", val);
+       return scnprintf(buf, PAGE_SIZE, "%llu\n", val << PAGE_SHIFT);
 }
 
 static ssize_t max_comp_streams_show(struct device *dev,
@@ -122,6 +122,72 @@ static ssize_t max_comp_streams_show(struct device *dev,
        return scnprintf(buf, PAGE_SIZE, "%d\n", val);
 }
 
+static ssize_t mem_limit_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       u64 val;
+       struct zram *zram = dev_to_zram(dev);
+
+       down_read(&zram->init_lock);
+       val = zram->limit_pages;
+       up_read(&zram->init_lock);
+
+       return scnprintf(buf, PAGE_SIZE, "%llu\n", val << PAGE_SHIFT);
+}
+
+static ssize_t mem_limit_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t len)
+{
+       u64 limit;
+       char *tmp;
+       struct zram *zram = dev_to_zram(dev);
+
+       limit = memparse(buf, &tmp);
+       if (buf == tmp) /* no chars parsed, invalid input */
+               return -EINVAL;
+
+       down_write(&zram->init_lock);
+       zram->limit_pages = PAGE_ALIGN(limit) >> PAGE_SHIFT;
+       up_write(&zram->init_lock);
+
+       return len;
+}
+
+static ssize_t mem_used_max_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       u64 val = 0;
+       struct zram *zram = dev_to_zram(dev);
+
+       down_read(&zram->init_lock);
+       if (init_done(zram))
+               val = atomic_long_read(&zram->stats.max_used_pages);
+       up_read(&zram->init_lock);
+
+       return scnprintf(buf, PAGE_SIZE, "%llu\n", val << PAGE_SHIFT);
+}
+
+static ssize_t mem_used_max_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t len)
+{
+       int err;
+       unsigned long val;
+       struct zram *zram = dev_to_zram(dev);
+       struct zram_meta *meta = zram->meta;
+
+       err = kstrtoul(buf, 10, &val);
+       if (err || val != 0)
+               return -EINVAL;
+
+       down_read(&zram->init_lock);
+       if (init_done(zram))
+               atomic_long_set(&zram->stats.max_used_pages,
+                               zs_get_total_pages(meta->mem_pool));
+       up_read(&zram->init_lock);
+
+       return len;
+}
+
 static ssize_t max_comp_streams_store(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t len)
 {
@@ -378,7 +444,6 @@ static int zram_decompress_page(struct zram *zram, char *mem, u32 index)
        /* Should NEVER happen. Return bio error if it does. */
        if (unlikely(ret)) {
                pr_err("Decompression failed! err=%d, page=%u\n", ret, index);
-               atomic64_inc(&zram->stats.failed_reads);
                return ret;
        }
 
@@ -435,6 +500,21 @@ out_cleanup:
        return ret;
 }
 
+static inline void update_used_max(struct zram *zram,
+                                       const unsigned long pages)
+{
+       int old_max, cur_max;
+
+       old_max = atomic_long_read(&zram->stats.max_used_pages);
+
+       do {
+               cur_max = old_max;
+               if (pages > cur_max)
+                       old_max = atomic_long_cmpxchg(
+                               &zram->stats.max_used_pages, cur_max, pages);
+       } while (old_max != cur_max);
+}
+
 static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
                           int offset)
 {
@@ -446,6 +526,7 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
        struct zram_meta *meta = zram->meta;
        struct zcomp_strm *zstrm;
        bool locked = false;
+       unsigned long alloced_pages;
 
        page = bvec->bv_page;
        if (is_partial_io(bvec)) {
@@ -514,6 +595,16 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
                ret = -ENOMEM;
                goto out;
        }
+
+       alloced_pages = zs_get_total_pages(meta->mem_pool);
+       if (zram->limit_pages && alloced_pages > zram->limit_pages) {
+               zs_free(meta->mem_pool, handle);
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       update_used_max(zram, alloced_pages);
+
        cmem = zs_map_object(meta->mem_pool, handle, ZS_MM_WO);
 
        if ((clen == PAGE_SIZE) && !is_partial_io(bvec)) {
@@ -547,8 +638,6 @@ out:
                zcomp_strm_release(zram->comp, zstrm);
        if (is_partial_io(bvec))
                kfree(uncmem);
-       if (ret)
-               atomic64_inc(&zram->stats.failed_writes);
        return ret;
 }
 
@@ -566,6 +655,13 @@ static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index,
                ret = zram_bvec_write(zram, bvec, index, offset);
        }
 
+       if (unlikely(ret)) {
+               if (rw == READ)
+                       atomic64_inc(&zram->stats.failed_reads);
+               else
+                       atomic64_inc(&zram->stats.failed_writes);
+       }
+
        return ret;
 }
 
@@ -602,6 +698,7 @@ static void zram_bio_discard(struct zram *zram, u32 index,
                bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value);
                zram_free_page(zram, index);
                bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value);
+               atomic64_inc(&zram->stats.notify_free);
                index++;
                n -= PAGE_SIZE;
        }
@@ -613,6 +710,9 @@ static void zram_reset_device(struct zram *zram, bool reset_capacity)
        struct zram_meta *meta;
 
        down_write(&zram->init_lock);
+
+       zram->limit_pages = 0;
+
        if (!init_done(zram)) {
                up_write(&zram->init_lock);
                return;
@@ -853,6 +953,10 @@ static DEVICE_ATTR(initstate, S_IRUGO, initstate_show, NULL);
 static DEVICE_ATTR(reset, S_IWUSR, NULL, reset_store);
 static DEVICE_ATTR(orig_data_size, S_IRUGO, orig_data_size_show, NULL);
 static DEVICE_ATTR(mem_used_total, S_IRUGO, mem_used_total_show, NULL);
+static DEVICE_ATTR(mem_limit, S_IRUGO | S_IWUSR, mem_limit_show,
+               mem_limit_store);
+static DEVICE_ATTR(mem_used_max, S_IRUGO | S_IWUSR, mem_used_max_show,
+               mem_used_max_store);
 static DEVICE_ATTR(max_comp_streams, S_IRUGO | S_IWUSR,
                max_comp_streams_show, max_comp_streams_store);
 static DEVICE_ATTR(comp_algorithm, S_IRUGO | S_IWUSR,
@@ -881,6 +985,8 @@ static struct attribute *zram_disk_attrs[] = {
        &dev_attr_orig_data_size.attr,
        &dev_attr_compr_data_size.attr,
        &dev_attr_mem_used_total.attr,
+       &dev_attr_mem_limit.attr,
+       &dev_attr_mem_used_max.attr,
        &dev_attr_max_comp_streams.attr,
        &dev_attr_comp_algorithm.attr,
        NULL,