diff options
-rw-r--r-- | drivers/staging/zram/Kconfig | 12 | ||||
-rw-r--r-- | drivers/staging/zram/Makefile | 2 | ||||
-rw-r--r-- | drivers/staging/zram/zram_drv.c | 186 | ||||
-rw-r--r-- | drivers/staging/zram/zram_drv.h | 55 | ||||
-rw-r--r-- | drivers/staging/zram/zram_ioctl.h | 41 | ||||
-rw-r--r-- | drivers/staging/zram/zram_sysfs.c | 242 |
6 files changed, 306 insertions, 232 deletions
diff --git a/drivers/staging/zram/Kconfig b/drivers/staging/zram/Kconfig index 4654ae2eb42e..da079f8d6e3d 100644 --- a/drivers/staging/zram/Kconfig +++ b/drivers/staging/zram/Kconfig | |||
@@ -15,15 +15,3 @@ config ZRAM | |||
15 | 15 | ||
16 | See zram.txt for more information. | 16 | See zram.txt for more information. |
17 | Project home: http://compcache.googlecode.com/ | 17 | Project home: http://compcache.googlecode.com/ |
18 | |||
19 | config ZRAM_STATS | ||
20 | bool "Enable statistics for compressed RAM disks" | ||
21 | depends on ZRAM | ||
22 | default y | ||
23 | help | ||
24 | Enable statistics collection for compressed RAM devices. Statistics | ||
25 | are exported through ioctl interface, so you have to use zramconfig | ||
26 | program to get them. This adds only a minimal overhead. | ||
27 | |||
28 | If unsure, say Y. | ||
29 | |||
diff --git a/drivers/staging/zram/Makefile b/drivers/staging/zram/Makefile index b2c087aa105e..c01160a98d10 100644 --- a/drivers/staging/zram/Makefile +++ b/drivers/staging/zram/Makefile | |||
@@ -1,3 +1,3 @@ | |||
1 | zram-objs := zram_drv.o xvmalloc.o | 1 | zram-objs := zram_drv.o zram_sysfs.o xvmalloc.o |
2 | 2 | ||
3 | obj-$(CONFIG_ZRAM) += zram.o | 3 | obj-$(CONFIG_ZRAM) += zram.o |
diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c index 77d4d715a789..3f698a5fc682 100644 --- a/drivers/staging/zram/zram_drv.c +++ b/drivers/staging/zram/zram_drv.c | |||
@@ -33,10 +33,39 @@ | |||
33 | 33 | ||
34 | /* Globals */ | 34 | /* Globals */ |
35 | static int zram_major; | 35 | static int zram_major; |
36 | static struct zram *devices; | 36 | struct zram *devices; |
37 | 37 | ||
38 | /* Module params (documentation at end) */ | 38 | /* Module params (documentation at end) */ |
39 | static unsigned int num_devices; | 39 | unsigned int num_devices; |
40 | |||
41 | static void zram_stat_inc(u32 *v) | ||
42 | { | ||
43 | *v = *v + 1; | ||
44 | } | ||
45 | |||
46 | static void zram_stat_dec(u32 *v) | ||
47 | { | ||
48 | *v = *v - 1; | ||
49 | } | ||
50 | |||
51 | static void zram_stat64_add(struct zram *zram, u64 *v, u64 inc) | ||
52 | { | ||
53 | spin_lock(&zram->stat64_lock); | ||
54 | *v = *v + inc; | ||
55 | spin_unlock(&zram->stat64_lock); | ||
56 | } | ||
57 | |||
58 | static void zram_stat64_sub(struct zram *zram, u64 *v, u64 dec) | ||
59 | { | ||
60 | spin_lock(&zram->stat64_lock); | ||
61 | *v = *v - dec; | ||
62 | spin_unlock(&zram->stat64_lock); | ||
63 | } | ||
64 | |||
65 | static void zram_stat64_inc(struct zram *zram, u64 *v) | ||
66 | { | ||
67 | zram_stat64_add(zram, v, 1); | ||
68 | } | ||
40 | 69 | ||
41 | static int zram_test_flag(struct zram *zram, u32 index, | 70 | static int zram_test_flag(struct zram *zram, u32 index, |
42 | enum zram_pageflags flag) | 71 | enum zram_pageflags flag) |
@@ -91,7 +120,7 @@ static void zram_set_disksize(struct zram *zram, size_t totalram_bytes) | |||
91 | "the disk when not in use so a huge zram is " | 120 | "the disk when not in use so a huge zram is " |
92 | "wasteful.\n" | 121 | "wasteful.\n" |
93 | "\tMemory Size: %zu kB\n" | 122 | "\tMemory Size: %zu kB\n" |
94 | "\tSize you selected: %zu kB\n" | 123 | "\tSize you selected: %llu kB\n" |
95 | "Continuing anyway ...\n", | 124 | "Continuing anyway ...\n", |
96 | totalram_bytes >> 10, zram->disksize | 125 | totalram_bytes >> 10, zram->disksize |
97 | ); | 126 | ); |
@@ -100,49 +129,6 @@ static void zram_set_disksize(struct zram *zram, size_t totalram_bytes) | |||
100 | zram->disksize &= PAGE_MASK; | 129 | zram->disksize &= PAGE_MASK; |
101 | } | 130 | } |
102 | 131 | ||
103 | static void zram_ioctl_get_stats(struct zram *zram, | ||
104 | struct zram_ioctl_stats *s) | ||
105 | { | ||
106 | s->disksize = zram->disksize; | ||
107 | |||
108 | #if defined(CONFIG_ZRAM_STATS) | ||
109 | { | ||
110 | struct zram_stats *rs = &zram->stats; | ||
111 | size_t succ_writes, mem_used; | ||
112 | unsigned int good_compress_perc = 0, no_compress_perc = 0; | ||
113 | |||
114 | mem_used = xv_get_total_size_bytes(zram->mem_pool) | ||
115 | + (rs->pages_expand << PAGE_SHIFT); | ||
116 | succ_writes = zram_stat64_read(zram, &rs->num_writes) - | ||
117 | zram_stat64_read(zram, &rs->failed_writes); | ||
118 | |||
119 | if (succ_writes && rs->pages_stored) { | ||
120 | good_compress_perc = rs->good_compress * 100 | ||
121 | / rs->pages_stored; | ||
122 | no_compress_perc = rs->pages_expand * 100 | ||
123 | / rs->pages_stored; | ||
124 | } | ||
125 | |||
126 | s->num_reads = zram_stat64_read(zram, &rs->num_reads); | ||
127 | s->num_writes = zram_stat64_read(zram, &rs->num_writes); | ||
128 | s->failed_reads = zram_stat64_read(zram, &rs->failed_reads); | ||
129 | s->failed_writes = zram_stat64_read(zram, &rs->failed_writes); | ||
130 | s->invalid_io = zram_stat64_read(zram, &rs->invalid_io); | ||
131 | s->notify_free = zram_stat64_read(zram, &rs->notify_free); | ||
132 | s->pages_zero = rs->pages_zero; | ||
133 | |||
134 | s->good_compress_pct = good_compress_perc; | ||
135 | s->pages_expand_pct = no_compress_perc; | ||
136 | |||
137 | s->pages_stored = rs->pages_stored; | ||
138 | s->pages_used = mem_used >> PAGE_SHIFT; | ||
139 | s->orig_data_size = rs->pages_stored << PAGE_SHIFT; | ||
140 | s->compr_data_size = rs->compr_size; | ||
141 | s->mem_used_total = mem_used; | ||
142 | } | ||
143 | #endif /* CONFIG_ZRAM_STATS */ | ||
144 | } | ||
145 | |||
146 | static void zram_free_page(struct zram *zram, size_t index) | 132 | static void zram_free_page(struct zram *zram, size_t index) |
147 | { | 133 | { |
148 | u32 clen; | 134 | u32 clen; |
@@ -180,7 +166,7 @@ static void zram_free_page(struct zram *zram, size_t index) | |||
180 | zram_stat_dec(&zram->stats.good_compress); | 166 | zram_stat_dec(&zram->stats.good_compress); |
181 | 167 | ||
182 | out: | 168 | out: |
183 | zram->stats.compr_size -= clen; | 169 | zram_stat64_sub(zram, &zram->stats.compr_size, clen); |
184 | zram_stat_dec(&zram->stats.pages_stored); | 170 | zram_stat_dec(&zram->stats.pages_stored); |
185 | 171 | ||
186 | zram->table[index].page = NULL; | 172 | zram->table[index].page = NULL; |
@@ -396,7 +382,7 @@ memstore: | |||
396 | kunmap_atomic(src, KM_USER0); | 382 | kunmap_atomic(src, KM_USER0); |
397 | 383 | ||
398 | /* Update stats */ | 384 | /* Update stats */ |
399 | zram->stats.compr_size += clen; | 385 | zram_stat64_add(zram, &zram->stats.compr_size, clen); |
400 | zram_stat_inc(&zram->stats.pages_stored); | 386 | zram_stat_inc(&zram->stats.pages_stored); |
401 | if (clen <= PAGE_SIZE / 2) | 387 | if (clen <= PAGE_SIZE / 2) |
402 | zram_stat_inc(&zram->stats.good_compress); | 388 | zram_stat_inc(&zram->stats.good_compress); |
@@ -463,7 +449,7 @@ static int zram_make_request(struct request_queue *queue, struct bio *bio) | |||
463 | return ret; | 449 | return ret; |
464 | } | 450 | } |
465 | 451 | ||
466 | static void reset_device(struct zram *zram) | 452 | void zram_reset_device(struct zram *zram) |
467 | { | 453 | { |
468 | size_t index; | 454 | size_t index; |
469 | 455 | ||
@@ -506,7 +492,7 @@ static void reset_device(struct zram *zram) | |||
506 | zram->disksize = 0; | 492 | zram->disksize = 0; |
507 | } | 493 | } |
508 | 494 | ||
509 | static int zram_ioctl_init_device(struct zram *zram) | 495 | int zram_init_device(struct zram *zram) |
510 | { | 496 | { |
511 | int ret; | 497 | int ret; |
512 | size_t num_pages; | 498 | size_t num_pages; |
@@ -561,91 +547,12 @@ static int zram_ioctl_init_device(struct zram *zram) | |||
561 | return 0; | 547 | return 0; |
562 | 548 | ||
563 | fail: | 549 | fail: |
564 | reset_device(zram); | 550 | zram_reset_device(zram); |
565 | 551 | ||
566 | pr_err("Initialization failed: err=%d\n", ret); | 552 | pr_err("Initialization failed: err=%d\n", ret); |
567 | return ret; | 553 | return ret; |
568 | } | 554 | } |
569 | 555 | ||
570 | static int zram_ioctl_reset_device(struct zram *zram) | ||
571 | { | ||
572 | if (zram->init_done) | ||
573 | reset_device(zram); | ||
574 | |||
575 | return 0; | ||
576 | } | ||
577 | |||
578 | static int zram_ioctl(struct block_device *bdev, fmode_t mode, | ||
579 | unsigned int cmd, unsigned long arg) | ||
580 | { | ||
581 | int ret = 0; | ||
582 | size_t disksize_kb; | ||
583 | |||
584 | struct zram *zram = bdev->bd_disk->private_data; | ||
585 | |||
586 | switch (cmd) { | ||
587 | case ZRAMIO_SET_DISKSIZE_KB: | ||
588 | if (zram->init_done) { | ||
589 | ret = -EBUSY; | ||
590 | goto out; | ||
591 | } | ||
592 | if (copy_from_user(&disksize_kb, (void *)arg, | ||
593 | _IOC_SIZE(cmd))) { | ||
594 | ret = -EFAULT; | ||
595 | goto out; | ||
596 | } | ||
597 | zram->disksize = disksize_kb << 10; | ||
598 | pr_info("Disk size set to %zu kB\n", disksize_kb); | ||
599 | break; | ||
600 | |||
601 | case ZRAMIO_GET_STATS: | ||
602 | { | ||
603 | struct zram_ioctl_stats *stats; | ||
604 | if (!zram->init_done) { | ||
605 | ret = -ENOTTY; | ||
606 | goto out; | ||
607 | } | ||
608 | stats = kzalloc(sizeof(*stats), GFP_KERNEL); | ||
609 | if (!stats) { | ||
610 | ret = -ENOMEM; | ||
611 | goto out; | ||
612 | } | ||
613 | zram_ioctl_get_stats(zram, stats); | ||
614 | if (copy_to_user((void *)arg, stats, sizeof(*stats))) { | ||
615 | kfree(stats); | ||
616 | ret = -EFAULT; | ||
617 | goto out; | ||
618 | } | ||
619 | kfree(stats); | ||
620 | break; | ||
621 | } | ||
622 | case ZRAMIO_INIT: | ||
623 | ret = zram_ioctl_init_device(zram); | ||
624 | break; | ||
625 | |||
626 | case ZRAMIO_RESET: | ||
627 | /* Do not reset an active device! */ | ||
628 | if (bdev->bd_holders) { | ||
629 | ret = -EBUSY; | ||
630 | goto out; | ||
631 | } | ||
632 | |||
633 | /* Make sure all pending I/O is finished */ | ||
634 | if (bdev) | ||
635 | fsync_bdev(bdev); | ||
636 | |||
637 | ret = zram_ioctl_reset_device(zram); | ||
638 | break; | ||
639 | |||
640 | default: | ||
641 | pr_info("Invalid ioctl %u\n", cmd); | ||
642 | ret = -ENOTTY; | ||
643 | } | ||
644 | |||
645 | out: | ||
646 | return ret; | ||
647 | } | ||
648 | |||
649 | void zram_slot_free_notify(struct block_device *bdev, unsigned long index) | 556 | void zram_slot_free_notify(struct block_device *bdev, unsigned long index) |
650 | { | 557 | { |
651 | struct zram *zram; | 558 | struct zram *zram; |
@@ -656,7 +563,6 @@ void zram_slot_free_notify(struct block_device *bdev, unsigned long index) | |||
656 | } | 563 | } |
657 | 564 | ||
658 | static const struct block_device_operations zram_devops = { | 565 | static const struct block_device_operations zram_devops = { |
659 | .ioctl = zram_ioctl, | ||
660 | .swap_slot_free_notify = zram_slot_free_notify, | 566 | .swap_slot_free_notify = zram_slot_free_notify, |
661 | .owner = THIS_MODULE | 567 | .owner = THIS_MODULE |
662 | }; | 568 | }; |
@@ -696,7 +602,7 @@ static int create_device(struct zram *zram, int device_id) | |||
696 | zram->disk->private_data = zram; | 602 | zram->disk->private_data = zram; |
697 | snprintf(zram->disk->disk_name, 16, "zram%d", device_id); | 603 | snprintf(zram->disk->disk_name, 16, "zram%d", device_id); |
698 | 604 | ||
699 | /* Actual capacity set using ZRAMIO_SET_DISKSIZE_KB ioctl */ | 605 | /* Actual capacity set using syfs (/sys/block/zram<id>/disksize */ |
700 | set_capacity(zram->disk, 0); | 606 | set_capacity(zram->disk, 0); |
701 | 607 | ||
702 | /* | 608 | /* |
@@ -710,6 +616,15 @@ static int create_device(struct zram *zram, int device_id) | |||
710 | 616 | ||
711 | add_disk(zram->disk); | 617 | add_disk(zram->disk); |
712 | 618 | ||
619 | #ifdef CONFIG_SYSFS | ||
620 | ret = sysfs_create_group(&disk_to_dev(zram->disk)->kobj, | ||
621 | &zram_disk_attr_group); | ||
622 | if (ret < 0) { | ||
623 | pr_warning("Error creating sysfs group"); | ||
624 | goto out; | ||
625 | } | ||
626 | #endif | ||
627 | |||
713 | zram->init_done = 0; | 628 | zram->init_done = 0; |
714 | 629 | ||
715 | out: | 630 | out: |
@@ -718,6 +633,11 @@ out: | |||
718 | 633 | ||
719 | static void destroy_device(struct zram *zram) | 634 | static void destroy_device(struct zram *zram) |
720 | { | 635 | { |
636 | #ifdef CONFIG_SYSFS | ||
637 | sysfs_remove_group(&disk_to_dev(zram->disk)->kobj, | ||
638 | &zram_disk_attr_group); | ||
639 | #endif | ||
640 | |||
721 | if (zram->disk) { | 641 | if (zram->disk) { |
722 | del_gendisk(zram->disk); | 642 | del_gendisk(zram->disk); |
723 | put_disk(zram->disk); | 643 | put_disk(zram->disk); |
@@ -785,7 +705,7 @@ static void __exit zram_exit(void) | |||
785 | 705 | ||
786 | destroy_device(zram); | 706 | destroy_device(zram); |
787 | if (zram->init_done) | 707 | if (zram->init_done) |
788 | reset_device(zram); | 708 | zram_reset_device(zram); |
789 | } | 709 | } |
790 | 710 | ||
791 | unregister_blkdev(zram_major, "zram"); | 711 | unregister_blkdev(zram_major, "zram"); |
diff --git a/drivers/staging/zram/zram_drv.h b/drivers/staging/zram/zram_drv.h index 945f9740442f..2ef93cc2024a 100644 --- a/drivers/staging/zram/zram_drv.h +++ b/drivers/staging/zram/zram_drv.h | |||
@@ -18,7 +18,6 @@ | |||
18 | #include <linux/spinlock.h> | 18 | #include <linux/spinlock.h> |
19 | #include <linux/mutex.h> | 19 | #include <linux/mutex.h> |
20 | 20 | ||
21 | #include "zram_ioctl.h" | ||
22 | #include "xvmalloc.h" | 21 | #include "xvmalloc.h" |
23 | 22 | ||
24 | /* | 23 | /* |
@@ -85,11 +84,7 @@ struct table { | |||
85 | } __attribute__((aligned(4))); | 84 | } __attribute__((aligned(4))); |
86 | 85 | ||
87 | struct zram_stats { | 86 | struct zram_stats { |
88 | /* basic stats */ | 87 | u64 compr_size; /* compressed size of pages stored */ |
89 | size_t compr_size; /* compressed size of pages stored - | ||
90 | * needed to enforce memlimit */ | ||
91 | /* more stats */ | ||
92 | #if defined(CONFIG_ZRAM_STATS) | ||
93 | u64 num_reads; /* failed + successful */ | 88 | u64 num_reads; /* failed + successful */ |
94 | u64 num_writes; /* --do-- */ | 89 | u64 num_writes; /* --do-- */ |
95 | u64 failed_reads; /* should NEVER! happen */ | 90 | u64 failed_reads; /* should NEVER! happen */ |
@@ -100,7 +95,6 @@ struct zram_stats { | |||
100 | u32 pages_stored; /* no. of pages currently stored */ | 95 | u32 pages_stored; /* no. of pages currently stored */ |
101 | u32 good_compress; /* % of pages with compression ratio<=50% */ | 96 | u32 good_compress; /* % of pages with compression ratio<=50% */ |
102 | u32 pages_expand; /* % of incompressible pages */ | 97 | u32 pages_expand; /* % of incompressible pages */ |
103 | #endif | ||
104 | }; | 98 | }; |
105 | 99 | ||
106 | struct zram { | 100 | struct zram { |
@@ -118,47 +112,18 @@ struct zram { | |||
118 | * This is the limit on amount of *uncompressed* worth of data | 112 | * This is the limit on amount of *uncompressed* worth of data |
119 | * we can store in a disk. | 113 | * we can store in a disk. |
120 | */ | 114 | */ |
121 | size_t disksize; /* bytes */ | 115 | u64 disksize; /* bytes */ |
122 | 116 | ||
123 | struct zram_stats stats; | 117 | struct zram_stats stats; |
124 | }; | 118 | }; |
125 | 119 | ||
126 | /*-- */ | 120 | extern struct zram *devices; |
127 | 121 | extern unsigned int num_devices; | |
128 | /* Debugging and Stats */ | 122 | #ifdef CONFIG_SYSFS |
129 | #if defined(CONFIG_ZRAM_STATS) | 123 | extern struct attribute_group zram_disk_attr_group; |
130 | static void zram_stat_inc(u32 *v) | 124 | #endif |
131 | { | 125 | |
132 | *v = *v + 1; | 126 | extern int zram_init_device(struct zram *zram); |
133 | } | 127 | extern void zram_reset_device(struct zram *zram); |
134 | |||
135 | static void zram_stat_dec(u32 *v) | ||
136 | { | ||
137 | *v = *v - 1; | ||
138 | } | ||
139 | |||
140 | static void zram_stat64_inc(struct zram *zram, u64 *v) | ||
141 | { | ||
142 | spin_lock(&zram->stat64_lock); | ||
143 | *v = *v + 1; | ||
144 | spin_unlock(&zram->stat64_lock); | ||
145 | } | ||
146 | |||
147 | static u64 zram_stat64_read(struct zram *zram, u64 *v) | ||
148 | { | ||
149 | u64 val; | ||
150 | |||
151 | spin_lock(&zram->stat64_lock); | ||
152 | val = *v; | ||
153 | spin_unlock(&zram->stat64_lock); | ||
154 | |||
155 | return val; | ||
156 | } | ||
157 | #else | ||
158 | #define zram_stat_inc(v) | ||
159 | #define zram_stat_dec(v) | ||
160 | #define zram_stat64_inc(r, v) | ||
161 | #define zram_stat64_read(r, v) | ||
162 | #endif /* CONFIG_ZRAM_STATS */ | ||
163 | 128 | ||
164 | #endif | 129 | #endif |
diff --git a/drivers/staging/zram/zram_ioctl.h b/drivers/staging/zram/zram_ioctl.h deleted file mode 100644 index 5c415fa4f17b..000000000000 --- a/drivers/staging/zram/zram_ioctl.h +++ /dev/null | |||
@@ -1,41 +0,0 @@ | |||
1 | /* | ||
2 | * Compressed RAM block device | ||
3 | * | ||
4 | * Copyright (C) 2008, 2009, 2010 Nitin Gupta | ||
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 | |||
15 | #ifndef _ZRAM_IOCTL_H_ | ||
16 | #define _ZRAM_IOCTL_H_ | ||
17 | |||
18 | struct zram_ioctl_stats { | ||
19 | u64 disksize; /* disksize in bytes (user specifies in KB) */ | ||
20 | u64 num_reads; /* failed + successful */ | ||
21 | u64 num_writes; /* --do-- */ | ||
22 | u64 failed_reads; /* should NEVER! happen */ | ||
23 | u64 failed_writes; /* can happen when memory is too low */ | ||
24 | u64 invalid_io; /* non-page-aligned I/O requests */ | ||
25 | u64 notify_free; /* no. of swap slot free notifications */ | ||
26 | u32 pages_zero; /* no. of zero filled pages */ | ||
27 | u32 good_compress_pct; /* no. of pages with compression ratio<=50% */ | ||
28 | u32 pages_expand_pct; /* no. of incompressible pages */ | ||
29 | u32 pages_stored; | ||
30 | u32 pages_used; | ||
31 | u64 orig_data_size; | ||
32 | u64 compr_data_size; | ||
33 | u64 mem_used_total; | ||
34 | } __attribute__ ((packed, aligned(4))); | ||
35 | |||
36 | #define ZRAMIO_SET_DISKSIZE_KB _IOW('z', 0, size_t) | ||
37 | #define ZRAMIO_GET_STATS _IOR('z', 1, struct zram_ioctl_stats) | ||
38 | #define ZRAMIO_INIT _IO('z', 2) | ||
39 | #define ZRAMIO_RESET _IO('z', 3) | ||
40 | |||
41 | #endif | ||
diff --git a/drivers/staging/zram/zram_sysfs.c b/drivers/staging/zram/zram_sysfs.c new file mode 100644 index 000000000000..b8dbaee8f171 --- /dev/null +++ b/drivers/staging/zram/zram_sysfs.c | |||
@@ -0,0 +1,242 @@ | |||
1 | /* | ||
2 | * Compressed RAM block device | ||
3 | * | ||
4 | * Copyright (C) 2008, 2009, 2010 Nitin Gupta | ||
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 | |||
15 | #include <linux/device.h> | ||
16 | #include <linux/genhd.h> | ||
17 | |||
18 | #include "zram_drv.h" | ||
19 | |||
20 | #ifdef CONFIG_SYSFS | ||
21 | |||
22 | static u64 zram_stat64_read(struct zram *zram, u64 *v) | ||
23 | { | ||
24 | u64 val; | ||
25 | |||
26 | spin_lock(&zram->stat64_lock); | ||
27 | val = *v; | ||
28 | spin_unlock(&zram->stat64_lock); | ||
29 | |||
30 | return val; | ||
31 | } | ||
32 | |||
33 | static struct zram *dev_to_zram(struct device *dev) | ||
34 | { | ||
35 | int i; | ||
36 | struct zram *zram = NULL; | ||
37 | |||
38 | for (i = 0; i < num_devices; i++) { | ||
39 | zram = &devices[i]; | ||
40 | if (disk_to_dev(zram->disk) == dev) | ||
41 | break; | ||
42 | } | ||
43 | |||
44 | return zram; | ||
45 | } | ||
46 | |||
47 | static ssize_t disksize_show(struct device *dev, | ||
48 | struct device_attribute *attr, char *buf) | ||
49 | { | ||
50 | struct zram *zram = dev_to_zram(dev); | ||
51 | |||
52 | return sprintf(buf, "%llu\n", zram->disksize); | ||
53 | } | ||
54 | |||
55 | static ssize_t disksize_store(struct device *dev, | ||
56 | struct device_attribute *attr, const char *buf, size_t len) | ||
57 | { | ||
58 | int ret; | ||
59 | struct zram *zram = dev_to_zram(dev); | ||
60 | |||
61 | if (zram->init_done) | ||
62 | return -EBUSY; | ||
63 | |||
64 | ret = strict_strtoull(buf, 10, &zram->disksize); | ||
65 | if (ret) | ||
66 | return ret; | ||
67 | |||
68 | zram->disksize &= PAGE_MASK; | ||
69 | set_capacity(zram->disk, zram->disksize >> SECTOR_SHIFT); | ||
70 | |||
71 | return len; | ||
72 | } | ||
73 | |||
74 | static ssize_t initstate_show(struct device *dev, | ||
75 | struct device_attribute *attr, char *buf) | ||
76 | { | ||
77 | struct zram *zram = dev_to_zram(dev); | ||
78 | |||
79 | return sprintf(buf, "%u\n", zram->init_done); | ||
80 | } | ||
81 | |||
82 | static ssize_t initstate_store(struct device *dev, | ||
83 | struct device_attribute *attr, const char *buf, size_t len) | ||
84 | { | ||
85 | int ret; | ||
86 | unsigned long do_init; | ||
87 | struct zram *zram = dev_to_zram(dev); | ||
88 | |||
89 | ret = strict_strtoul(buf, 10, &do_init); | ||
90 | if (ret) | ||
91 | return ret; | ||
92 | |||
93 | if (!do_init) | ||
94 | return -EINVAL; | ||
95 | |||
96 | zram_init_device(zram); | ||
97 | |||
98 | return len; | ||
99 | } | ||
100 | |||
101 | static ssize_t reset_store(struct device *dev, | ||
102 | struct device_attribute *attr, const char *buf, size_t len) | ||
103 | { | ||
104 | int ret; | ||
105 | unsigned long do_reset; | ||
106 | struct zram *zram; | ||
107 | struct block_device *bdev; | ||
108 | |||
109 | zram = dev_to_zram(dev); | ||
110 | bdev = bdget_disk(zram->disk, 0); | ||
111 | |||
112 | /* Do not reset an active device! */ | ||
113 | if (bdev->bd_holders) | ||
114 | return -EBUSY; | ||
115 | |||
116 | ret = strict_strtoul(buf, 10, &do_reset); | ||
117 | if (ret) | ||
118 | return ret; | ||
119 | |||
120 | if (!do_reset) | ||
121 | return -EINVAL; | ||
122 | |||
123 | /* Make sure all pending I/O is finished */ | ||
124 | if (bdev) | ||
125 | fsync_bdev(bdev); | ||
126 | |||
127 | if (zram->init_done) | ||
128 | zram_reset_device(zram); | ||
129 | |||
130 | return len; | ||
131 | } | ||
132 | |||
133 | static ssize_t num_reads_show(struct device *dev, | ||
134 | struct device_attribute *attr, char *buf) | ||
135 | { | ||
136 | struct zram *zram = dev_to_zram(dev); | ||
137 | |||
138 | return sprintf(buf, "%llu\n", | ||
139 | zram_stat64_read(zram, &zram->stats.num_reads)); | ||
140 | } | ||
141 | |||
142 | static ssize_t num_writes_show(struct device *dev, | ||
143 | struct device_attribute *attr, char *buf) | ||
144 | { | ||
145 | struct zram *zram = dev_to_zram(dev); | ||
146 | |||
147 | return sprintf(buf, "%llu\n", | ||
148 | zram_stat64_read(zram, &zram->stats.num_writes)); | ||
149 | } | ||
150 | |||
151 | static ssize_t invalid_io_show(struct device *dev, | ||
152 | struct device_attribute *attr, char *buf) | ||
153 | { | ||
154 | struct zram *zram = dev_to_zram(dev); | ||
155 | |||
156 | return sprintf(buf, "%llu\n", | ||
157 | zram_stat64_read(zram, &zram->stats.invalid_io)); | ||
158 | } | ||
159 | |||
160 | static ssize_t notify_free_show(struct device *dev, | ||
161 | struct device_attribute *attr, char *buf) | ||
162 | { | ||
163 | struct zram *zram = dev_to_zram(dev); | ||
164 | |||
165 | return sprintf(buf, "%llu\n", | ||
166 | zram_stat64_read(zram, &zram->stats.notify_free)); | ||
167 | } | ||
168 | |||
169 | static ssize_t zero_pages_show(struct device *dev, | ||
170 | struct device_attribute *attr, char *buf) | ||
171 | { | ||
172 | struct zram *zram = dev_to_zram(dev); | ||
173 | |||
174 | return sprintf(buf, "%u\n", zram->stats.pages_zero); | ||
175 | } | ||
176 | |||
177 | static ssize_t orig_data_size_show(struct device *dev, | ||
178 | struct device_attribute *attr, char *buf) | ||
179 | { | ||
180 | struct zram *zram = dev_to_zram(dev); | ||
181 | |||
182 | return sprintf(buf, "%llu\n", | ||
183 | (u64)(zram->stats.pages_stored) << PAGE_SHIFT); | ||
184 | } | ||
185 | |||
186 | static ssize_t compr_data_size_show(struct device *dev, | ||
187 | struct device_attribute *attr, char *buf) | ||
188 | { | ||
189 | struct zram *zram = dev_to_zram(dev); | ||
190 | |||
191 | return sprintf(buf, "%llu\n", | ||
192 | zram_stat64_read(zram, &zram->stats.compr_size)); | ||
193 | } | ||
194 | |||
195 | static ssize_t mem_used_total_show(struct device *dev, | ||
196 | struct device_attribute *attr, char *buf) | ||
197 | { | ||
198 | u64 val = 0; | ||
199 | struct zram *zram = dev_to_zram(dev); | ||
200 | |||
201 | if (zram->init_done) { | ||
202 | val = xv_get_total_size_bytes(zram->mem_pool) + | ||
203 | ((u64)(zram->stats.pages_expand) << PAGE_SHIFT); | ||
204 | } | ||
205 | |||
206 | return sprintf(buf, "%llu\n", val); | ||
207 | } | ||
208 | |||
209 | static DEVICE_ATTR(disksize, S_IRUGO | S_IWUGO, | ||
210 | disksize_show, disksize_store); | ||
211 | static DEVICE_ATTR(initstate, S_IRUGO | S_IWUGO, | ||
212 | initstate_show, initstate_store); | ||
213 | static DEVICE_ATTR(reset, S_IWUGO, NULL, reset_store); | ||
214 | static DEVICE_ATTR(num_reads, S_IRUGO, num_reads_show, NULL); | ||
215 | static DEVICE_ATTR(num_writes, S_IRUGO, num_writes_show, NULL); | ||
216 | static DEVICE_ATTR(invalid_io, S_IRUGO, invalid_io_show, NULL); | ||
217 | static DEVICE_ATTR(notify_free, S_IRUGO, notify_free_show, NULL); | ||
218 | static DEVICE_ATTR(zero_pages, S_IRUGO, zero_pages_show, NULL); | ||
219 | static DEVICE_ATTR(orig_data_size, S_IRUGO, orig_data_size_show, NULL); | ||
220 | static DEVICE_ATTR(compr_data_size, S_IRUGO, compr_data_size_show, NULL); | ||
221 | static DEVICE_ATTR(mem_used_total, S_IRUGO, mem_used_total_show, NULL); | ||
222 | |||
223 | static struct attribute *zram_disk_attrs[] = { | ||
224 | &dev_attr_disksize.attr, | ||
225 | &dev_attr_initstate.attr, | ||
226 | &dev_attr_reset.attr, | ||
227 | &dev_attr_num_reads.attr, | ||
228 | &dev_attr_num_writes.attr, | ||
229 | &dev_attr_invalid_io.attr, | ||
230 | &dev_attr_notify_free.attr, | ||
231 | &dev_attr_zero_pages.attr, | ||
232 | &dev_attr_orig_data_size.attr, | ||
233 | &dev_attr_compr_data_size.attr, | ||
234 | &dev_attr_mem_used_total.attr, | ||
235 | NULL, | ||
236 | }; | ||
237 | |||
238 | struct attribute_group zram_disk_attr_group = { | ||
239 | .attrs = zram_disk_attrs, | ||
240 | }; | ||
241 | |||
242 | #endif /* CONFIG_SYSFS */ | ||