zram: kang from v5.15
Signed-off-by: Juhyung Park <qkrwngud825@gmail.com> Change-Id: I2f2356060285aa9e934f23c17ea6057fba094343 Signed-off-by: UtsavBalar1231 <utsavbalar1231@gmail.com>
This commit is contained in:
parent
0caa07422e
commit
709083fe3e
@ -1,20 +1,24 @@
|
||||
zram: Compressed RAM based block devices
|
||||
----------------------------------------
|
||||
========================================
|
||||
zram: Compressed RAM-based block devices
|
||||
========================================
|
||||
|
||||
* Introduction
|
||||
Introduction
|
||||
============
|
||||
|
||||
The zram module creates RAM based block devices named /dev/zram<id>
|
||||
The zram module creates RAM-based block devices named /dev/zram<id>
|
||||
(<id> = 0, 1, ...). Pages written to these disks are compressed and stored
|
||||
in memory itself. These disks allow very fast I/O and compression provides
|
||||
good amounts of memory savings. Some of the usecases include /tmp storage,
|
||||
use as swap disks, various caches under /var and maybe many more :)
|
||||
good amounts of memory savings. Some of the use cases include /tmp storage,
|
||||
use as swap disks, various caches under /var and maybe many more. :)
|
||||
|
||||
Statistics for individual zram devices are exported through sysfs nodes at
|
||||
/sys/block/zram<id>/
|
||||
|
||||
* Usage
|
||||
Usage
|
||||
=====
|
||||
|
||||
There are several ways to configure and manage zram device(-s):
|
||||
|
||||
a) using zram and zram_control sysfs attributes
|
||||
b) using zramctl utility, provided by util-linux (util-linux@vger.kernel.org).
|
||||
|
||||
@ -22,7 +26,7 @@ In this document we will describe only 'manual' zram configuration steps,
|
||||
IOW, zram and zram_control sysfs attributes.
|
||||
|
||||
In order to get a better idea about zramctl please consult util-linux
|
||||
documentation, zramctl man-page or `zramctl --help'. Please be informed
|
||||
documentation, zramctl man-page or `zramctl --help`. Please be informed
|
||||
that zram maintainers do not develop/maintain util-linux or zramctl, should
|
||||
you have any questions please contact util-linux@vger.kernel.org
|
||||
|
||||
@ -30,52 +34,67 @@ Following shows a typical sequence of steps for using zram.
|
||||
|
||||
WARNING
|
||||
=======
|
||||
|
||||
For the sake of simplicity we skip error checking parts in most of the
|
||||
examples below. However, it is your sole responsibility to handle errors.
|
||||
|
||||
zram sysfs attributes always return negative values in case of errors.
|
||||
The list of possible return codes:
|
||||
-EBUSY -- an attempt to modify an attribute that cannot be changed once
|
||||
the device has been initialised. Please reset device first;
|
||||
-ENOMEM -- zram was not able to allocate enough memory to fulfil your
|
||||
needs;
|
||||
-EINVAL -- invalid input has been provided.
|
||||
|
||||
If you use 'echo', the returned value that is changed by 'echo' utility,
|
||||
and, in general case, something like:
|
||||
======== =============================================================
|
||||
-EBUSY an attempt to modify an attribute that cannot be changed once
|
||||
the device has been initialised. Please reset device first.
|
||||
-ENOMEM zram was not able to allocate enough memory to fulfil your
|
||||
needs.
|
||||
-EINVAL invalid input has been provided.
|
||||
======== =============================================================
|
||||
|
||||
If you use 'echo', the returned value is set by the 'echo' utility,
|
||||
and, in general case, something like::
|
||||
|
||||
echo 3 > /sys/block/zram0/max_comp_streams
|
||||
if [ $? -ne 0 ];
|
||||
if [ $? -ne 0 ]; then
|
||||
handle_error
|
||||
fi
|
||||
|
||||
should suffice.
|
||||
|
||||
1) Load Module:
|
||||
1) Load Module
|
||||
==============
|
||||
|
||||
::
|
||||
|
||||
modprobe zram num_devices=4
|
||||
This creates 4 devices: /dev/zram{0,1,2,3}
|
||||
|
||||
This creates 4 devices: /dev/zram{0,1,2,3}
|
||||
|
||||
num_devices parameter is optional and tells zram how many devices should be
|
||||
pre-created. Default: 1.
|
||||
|
||||
2) Set max number of compression streams
|
||||
Regardless the value passed to this attribute, ZRAM will always
|
||||
allocate multiple compression streams - one per online CPUs - thus
|
||||
========================================
|
||||
|
||||
Regardless of the value passed to this attribute, ZRAM will always
|
||||
allocate multiple compression streams - one per online CPU - thus
|
||||
allowing several concurrent compression operations. The number of
|
||||
allocated compression streams goes down when some of the CPUs
|
||||
become offline. There is no single-compression-stream mode anymore,
|
||||
unless you are running a UP system or has only 1 CPU online.
|
||||
unless you are running a UP system or have only 1 CPU online.
|
||||
|
||||
To find out how many streams are currently available::
|
||||
|
||||
To find out how many streams are currently available:
|
||||
cat /sys/block/zram0/max_comp_streams
|
||||
|
||||
3) Select compression algorithm
|
||||
===============================
|
||||
|
||||
Using comp_algorithm device attribute one can see available and
|
||||
currently selected (shown in square brackets) compression algorithms,
|
||||
change selected compression algorithm (once the device is initialised
|
||||
or change the selected compression algorithm (once the device is initialised
|
||||
there is no way to change compression algorithm).
|
||||
|
||||
Examples:
|
||||
Examples::
|
||||
|
||||
#show supported compression algorithms
|
||||
cat /sys/block/zram0/comp_algorithm
|
||||
lzo [lz4]
|
||||
@ -83,20 +102,23 @@ Examples:
|
||||
#select lzo compression algorithm
|
||||
echo lzo > /sys/block/zram0/comp_algorithm
|
||||
|
||||
For the time being, the `comp_algorithm' content does not necessarily
|
||||
For the time being, the `comp_algorithm` content does not necessarily
|
||||
show every compression algorithm supported by the kernel. We keep this
|
||||
list primarily to simplify device configuration and one can configure
|
||||
a new device with a compression algorithm that is not listed in
|
||||
`comp_algorithm'. The thing is that, internally, ZRAM uses Crypto API
|
||||
`comp_algorithm`. The thing is that, internally, ZRAM uses Crypto API
|
||||
and, if some of the algorithms were built as modules, it's impossible
|
||||
to list all of them using, for instance, /proc/crypto or any other
|
||||
method. This, however, has an advantage of permitting the usage of
|
||||
custom crypto compression modules (implementing S/W or H/W compression).
|
||||
|
||||
4) Set Disksize
|
||||
===============
|
||||
|
||||
Set disk size by writing the value to sysfs node 'disksize'.
|
||||
The value can be either in bytes or you can use mem suffixes.
|
||||
Examples:
|
||||
Examples::
|
||||
|
||||
# Initialize /dev/zram0 with 50MB disksize
|
||||
echo $((50*1024*1024)) > /sys/block/zram0/disksize
|
||||
|
||||
@ -111,10 +133,13 @@ since we expect a 2:1 compression ratio. Note that zram uses about 0.1% of the
|
||||
size of the disk when not in use so a huge zram is wasteful.
|
||||
|
||||
5) Set memory limit: Optional
|
||||
=============================
|
||||
|
||||
Set memory limit by writing the value to sysfs node 'mem_limit'.
|
||||
The value can be either in bytes or you can use mem suffixes.
|
||||
In addition, you could change the value in runtime.
|
||||
Examples:
|
||||
Examples::
|
||||
|
||||
# limit /dev/zram0 with 50MB memory
|
||||
echo $((50*1024*1024)) > /sys/block/zram0/mem_limit
|
||||
|
||||
@ -126,7 +151,11 @@ Examples:
|
||||
# To disable memory limit
|
||||
echo 0 > /sys/block/zram0/mem_limit
|
||||
|
||||
6) Activate:
|
||||
6) Activate
|
||||
===========
|
||||
|
||||
::
|
||||
|
||||
mkswap /dev/zram0
|
||||
swapon /dev/zram0
|
||||
|
||||
@ -134,52 +163,60 @@ Examples:
|
||||
mount /dev/zram1 /tmp
|
||||
|
||||
7) Add/remove zram devices
|
||||
==========================
|
||||
|
||||
zram provides a control interface, which enables dynamic (on-demand) device
|
||||
addition and removal.
|
||||
|
||||
In order to add a new /dev/zramX device, perform read operation on hot_add
|
||||
attribute. This will return either new device's device id (meaning that you
|
||||
can use /dev/zram<id>) or error code.
|
||||
In order to add a new /dev/zramX device, perform a read operation on the hot_add
|
||||
attribute. This will return either the new device's device id (meaning that you
|
||||
can use /dev/zram<id>) or an error code.
|
||||
|
||||
Example::
|
||||
|
||||
Example:
|
||||
cat /sys/class/zram-control/hot_add
|
||||
1
|
||||
|
||||
To remove the existing /dev/zramX device (where X is a device id)
|
||||
execute
|
||||
execute::
|
||||
|
||||
echo X > /sys/class/zram-control/hot_remove
|
||||
|
||||
8) Stats:
|
||||
8) Stats
|
||||
========
|
||||
|
||||
Per-device statistics are exported as various nodes under /sys/block/zram<id>/
|
||||
|
||||
A brief description of exported device attributes. For more details please
|
||||
read Documentation/ABI/testing/sysfs-block-zram.
|
||||
A brief description of exported device attributes follows. For more details
|
||||
please read Documentation/ABI/testing/sysfs-block-zram.
|
||||
|
||||
====================== ====== ===============================================
|
||||
Name access description
|
||||
---- ------ -----------
|
||||
====================== ====== ===============================================
|
||||
disksize RW show and set the device's disk size
|
||||
initstate RO shows the initialization state of the device
|
||||
reset WO trigger device reset
|
||||
mem_used_max WO reset the `mem_used_max' counter (see later)
|
||||
mem_limit WO specifies the maximum amount of memory ZRAM can use
|
||||
to store the compressed data
|
||||
writeback_limit WO specifies the maximum amount of write IO zram can
|
||||
write out to backing device as 4KB unit
|
||||
mem_used_max WO reset the `mem_used_max` counter (see later)
|
||||
mem_limit WO specifies the maximum amount of memory ZRAM can
|
||||
use to store the compressed data
|
||||
writeback_limit WO specifies the maximum amount of write IO zram
|
||||
can write out to backing device as 4KB unit
|
||||
writeback_limit_enable RW show and set writeback_limit feature
|
||||
max_comp_streams RW the number of possible concurrent compress operations
|
||||
max_comp_streams RW the number of possible concurrent compress
|
||||
operations
|
||||
comp_algorithm RW show and change the compression algorithm
|
||||
compact WO trigger memory compaction
|
||||
debug_stat RO this file is used for zram debugging purposes
|
||||
backing_dev RW set up backend storage for zram to write out
|
||||
idle WO mark allocated slot as idle
|
||||
====================== ====== ===============================================
|
||||
|
||||
|
||||
User space is advised to use the following files to read the device statistics.
|
||||
|
||||
File /sys/block/zram<id>/stat
|
||||
|
||||
Represents block layer statistics. Read Documentation/block/stat.txt for
|
||||
Represents block layer statistics. Read Documentation/block/stat.rst for
|
||||
details.
|
||||
|
||||
File /sys/block/zram<id>/io_stat
|
||||
@ -188,26 +225,32 @@ The stat file represents device's I/O statistics not accounted by block
|
||||
layer and, thus, not available in zram<id>/stat file. It consists of a
|
||||
single line of text and contains the following stats separated by
|
||||
whitespace:
|
||||
failed_reads the number of failed reads
|
||||
failed_writes the number of failed writes
|
||||
invalid_io the number of non-page-size-aligned I/O requests
|
||||
|
||||
============= =============================================================
|
||||
failed_reads The number of failed reads
|
||||
failed_writes The number of failed writes
|
||||
invalid_io The number of non-page-size-aligned I/O requests
|
||||
notify_free Depending on device usage scenario it may account
|
||||
|
||||
a) the number of pages freed because of swap slot free
|
||||
notifications or b) the number of pages freed because of
|
||||
REQ_DISCARD requests sent by bio. The former ones are
|
||||
sent to a swap block device when a swap slot is freed,
|
||||
which implies that this disk is being used as a swap disk.
|
||||
notifications
|
||||
b) the number of pages freed because of
|
||||
REQ_OP_DISCARD requests sent by bio. The former ones are
|
||||
sent to a swap block device when a swap slot is freed,
|
||||
which implies that this disk is being used as a swap disk.
|
||||
|
||||
The latter ones are sent by filesystem mounted with
|
||||
discard option, whenever some data blocks are getting
|
||||
discarded.
|
||||
============= =============================================================
|
||||
|
||||
File /sys/block/zram<id>/mm_stat
|
||||
|
||||
The stat file represents device's mm statistics. It consists of a single
|
||||
The mm_stat file represents the device's mm statistics. It consists of a single
|
||||
line of text and contains the following stats separated by whitespace:
|
||||
|
||||
================ =============================================================
|
||||
orig_data_size uncompressed size of data stored in this disk.
|
||||
This excludes same-element-filled pages (same_pages) since
|
||||
no memory is allocated for them.
|
||||
Unit: bytes
|
||||
compr_data_size compressed size of data stored in this disk
|
||||
mem_used_total the amount of memory allocated for this disk. This
|
||||
@ -217,64 +260,78 @@ line of text and contains the following stats separated by whitespace:
|
||||
Unit: bytes
|
||||
mem_limit the maximum amount of memory ZRAM can use to store
|
||||
the compressed data
|
||||
mem_used_max the maximum amount of memory zram have consumed to
|
||||
mem_used_max the maximum amount of memory zram has consumed to
|
||||
store the data
|
||||
same_pages the number of same element filled pages written to this disk.
|
||||
No memory is allocated for such pages.
|
||||
pages_compacted the number of pages freed during compaction
|
||||
huge_pages the number of incompressible pages
|
||||
huge_pages_since the number of incompressible pages since zram set up
|
||||
================ =============================================================
|
||||
|
||||
File /sys/block/zram<id>/bd_stat
|
||||
|
||||
The stat file represents device's backing device statistics. It consists of
|
||||
The bd_stat file represents a device's backing device statistics. It consists of
|
||||
a single line of text and contains the following stats separated by whitespace:
|
||||
|
||||
============== =============================================================
|
||||
bd_count size of data written in backing device.
|
||||
Unit: 4K bytes
|
||||
bd_reads the number of reads from backing device
|
||||
Unit: 4K bytes
|
||||
bd_writes the number of writes to backing device
|
||||
Unit: 4K bytes
|
||||
============== =============================================================
|
||||
|
||||
9) Deactivate
|
||||
=============
|
||||
|
||||
::
|
||||
|
||||
9) Deactivate:
|
||||
swapoff /dev/zram0
|
||||
umount /dev/zram1
|
||||
|
||||
10) Reset:
|
||||
Write any positive value to 'reset' sysfs node
|
||||
echo 1 > /sys/block/zram0/reset
|
||||
echo 1 > /sys/block/zram1/reset
|
||||
10) Reset
|
||||
=========
|
||||
|
||||
Write any positive value to 'reset' sysfs node::
|
||||
|
||||
echo 1 > /sys/block/zram0/reset
|
||||
echo 1 > /sys/block/zram1/reset
|
||||
|
||||
This frees all the memory allocated for the given device and
|
||||
resets the disksize to zero. You must set the disksize again
|
||||
before reusing the device.
|
||||
|
||||
* Optional Feature
|
||||
Optional Feature
|
||||
================
|
||||
|
||||
= writeback
|
||||
writeback
|
||||
---------
|
||||
|
||||
With CONFIG_ZRAM_WRITEBACK, zram can write idle/incompressible page
|
||||
to backing storage rather than keeping it in memory.
|
||||
To use the feature, admin should set up backing device via
|
||||
To use the feature, admin should set up backing device via::
|
||||
|
||||
"echo /dev/sda5 > /sys/block/zramX/backing_dev"
|
||||
echo /dev/sda5 > /sys/block/zramX/backing_dev
|
||||
|
||||
before disksize setting. It supports only partition at this moment.
|
||||
If admin want to use incompressible page writeback, they could do via
|
||||
If admin wants to use incompressible page writeback, they could do via::
|
||||
|
||||
"echo huge > /sys/block/zramX/write"
|
||||
echo huge > /sys/block/zramX/writeback
|
||||
|
||||
To use idle page writeback, first, user need to declare zram pages
|
||||
as idle.
|
||||
as idle::
|
||||
|
||||
"echo all > /sys/block/zramX/idle"
|
||||
echo all > /sys/block/zramX/idle
|
||||
|
||||
From now on, any pages on zram are idle pages. The idle mark
|
||||
will be removed until someone request access of the block.
|
||||
will be removed until someone requests access of the block.
|
||||
IOW, unless there is access request, those pages are still idle pages.
|
||||
|
||||
Admin can request writeback of those idle pages at right timing via
|
||||
Admin can request writeback of those idle pages at right timing via::
|
||||
|
||||
"echo idle > /sys/block/zramX/writeback"
|
||||
echo idle > /sys/block/zramX/writeback
|
||||
|
||||
With the command, zram writeback idle pages from memory to the storage.
|
||||
|
||||
@ -289,19 +346,19 @@ to guarantee storage health for entire product life.
|
||||
|
||||
To overcome the concern, zram supports "writeback_limit" feature.
|
||||
The "writeback_limit_enable"'s default value is 0 so that it doesn't limit
|
||||
any writeback. IOW, if admin want to apply writeback budget, he should
|
||||
enable writeback_limit_enable via
|
||||
any writeback. IOW, if admin wants to apply writeback budget, he should
|
||||
enable writeback_limit_enable via::
|
||||
|
||||
$ echo 1 > /sys/block/zramX/writeback_limit_enable
|
||||
|
||||
Once writeback_limit_enable is set, zram doesn't allow any writeback
|
||||
until admin set the budget via /sys/block/zramX/writeback_limit.
|
||||
until admin sets the budget via /sys/block/zramX/writeback_limit.
|
||||
|
||||
(If admin doesn't enable writeback_limit_enable, writeback_limit's value
|
||||
assigned via /sys/block/zramX/writeback_limit is meaninless.)
|
||||
assigned via /sys/block/zramX/writeback_limit is meaningless.)
|
||||
|
||||
If admin want to limit writeback as per-day 400M, he could do it
|
||||
like below.
|
||||
like below::
|
||||
|
||||
$ MB_SHIFT=20
|
||||
$ 4K_SHIFT=12
|
||||
@ -309,47 +366,57 @@ like below.
|
||||
/sys/block/zram0/writeback_limit.
|
||||
$ echo 1 > /sys/block/zram0/writeback_limit_enable
|
||||
|
||||
If admin want to allow further write again once the bugdet is exausted,
|
||||
he could do it like below
|
||||
If admins want to allow further write again once the budget is exhausted,
|
||||
he could do it like below::
|
||||
|
||||
$ echo $((400<<MB_SHIFT>>4K_SHIFT)) > \
|
||||
/sys/block/zram0/writeback_limit
|
||||
|
||||
If admin want to see remaining writeback budget since he set,
|
||||
If admin wants to see remaining writeback budget since last set::
|
||||
|
||||
$ cat /sys/block/zramX/writeback_limit
|
||||
|
||||
If admin want to disable writeback limit, he could do
|
||||
If admin want to disable writeback limit, he could do::
|
||||
|
||||
$ echo 0 > /sys/block/zramX/writeback_limit_enable
|
||||
|
||||
The writeback_limit count will reset whenever you reset zram(e.g.,
|
||||
The writeback_limit count will reset whenever you reset zram (e.g.,
|
||||
system reboot, echo 1 > /sys/block/zramX/reset) so keeping how many of
|
||||
writeback happened until you reset the zram to allocate extra writeback
|
||||
budget in next setting is user's job.
|
||||
|
||||
If admin want to measure writeback count in a certain period, he could
|
||||
If admin wants to measure writeback count in a certain period, he could
|
||||
know it via /sys/block/zram0/bd_stat's 3rd column.
|
||||
|
||||
= memory tracking
|
||||
memory tracking
|
||||
===============
|
||||
|
||||
With CONFIG_ZRAM_MEMORY_TRACKING, user can know information of the
|
||||
zram block. It could be useful to catch cold or incompressible
|
||||
pages of the process with*pagemap.
|
||||
|
||||
If you enable the feature, you could see block state via
|
||||
/sys/kernel/debug/zram/zram0/block_state". The output is as follows,
|
||||
/sys/kernel/debug/zram/zram0/block_state". The output is as follows::
|
||||
|
||||
300 75.033841 .wh.
|
||||
301 63.806904 s...
|
||||
302 63.806919 ..hi
|
||||
|
||||
First column is zram's block index.
|
||||
Second column is access time since the system was booted
|
||||
Third column is state of the block.
|
||||
(s: same page
|
||||
w: written page to backing store
|
||||
h: huge page
|
||||
i: idle page)
|
||||
First column
|
||||
zram's block index.
|
||||
Second column
|
||||
access time since the system was booted
|
||||
Third column
|
||||
state of the block:
|
||||
|
||||
s:
|
||||
same page
|
||||
w:
|
||||
written page to backing store
|
||||
h:
|
||||
huge page
|
||||
i:
|
||||
idle page
|
||||
|
||||
First line of above example says 300th block is accessed at 75.033841sec
|
||||
and the block's state is huge so it is written back to the backing
|
||||
|
@ -3,7 +3,6 @@ config ZRAM
|
||||
tristate "Compressed RAM block device support"
|
||||
depends on BLOCK && SYSFS && ZSMALLOC && CRYPTO
|
||||
depends on CRYPTO_LZO || CRYPTO_ZSTD || CRYPTO_LZ4 || CRYPTO_LZ4HC || CRYPTO_842
|
||||
default n
|
||||
help
|
||||
Creates virtual block devices called /dev/zramX (X = 0, 1, ...).
|
||||
Pages written to these disks are compressed and stored in memory
|
||||
@ -58,7 +57,6 @@ config ZRAM_DEF_COMP
|
||||
config ZRAM_WRITEBACK
|
||||
bool "Write back incompressible or idle page to backing device"
|
||||
depends on ZRAM
|
||||
default n
|
||||
help
|
||||
With incompressible page, there is no memory saving to keep it
|
||||
in memory. Instead, write it out to backing device.
|
||||
|
@ -1,3 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
zram-y := zcomp.o zram_drv.o
|
||||
|
||||
obj-$(CONFIG_ZRAM) += zram.o
|
||||
|
@ -1,10 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (C) 2014 Sergey Senozhatsky.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
@ -115,12 +111,13 @@ ssize_t zcomp_available_show(const char *comp, char *buf)
|
||||
|
||||
struct zcomp_strm *zcomp_stream_get(struct zcomp *comp)
|
||||
{
|
||||
return get_cpu_ptr(comp->stream);
|
||||
local_lock(&comp->stream->lock);
|
||||
return this_cpu_ptr(comp->stream);
|
||||
}
|
||||
|
||||
void zcomp_stream_put(struct zcomp *comp)
|
||||
{
|
||||
put_cpu_ptr(comp->stream);
|
||||
local_unlock(&comp->stream->lock);
|
||||
}
|
||||
|
||||
int zcomp_compress(struct zcomp_strm *zstrm,
|
||||
@ -164,6 +161,8 @@ int zcomp_cpu_up_prepare(unsigned int cpu, struct hlist_node *node)
|
||||
int ret;
|
||||
|
||||
zstrm = per_cpu_ptr(comp->stream, cpu);
|
||||
local_lock_init(&zstrm->lock);
|
||||
|
||||
ret = zcomp_strm_init(zstrm, comp);
|
||||
if (ret)
|
||||
pr_err("Can't allocate a compression stream\n");
|
||||
|
@ -1,16 +1,15 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (C) 2014 Sergey Senozhatsky.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef _ZCOMP_H_
|
||||
#define _ZCOMP_H_
|
||||
#include <linux/local_lock.h>
|
||||
|
||||
struct zcomp_strm {
|
||||
/* The members ->buffer and ->tfm are protected by ->lock. */
|
||||
local_lock_t lock;
|
||||
/* compression/decompression buffer */
|
||||
void *buffer;
|
||||
struct crypto_comp *tfm;
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/cpuhotplug.h>
|
||||
#include <linux/part_stat.h>
|
||||
|
||||
#include "zram_drv.h"
|
||||
|
||||
@ -51,6 +52,9 @@ static unsigned int num_devices = 1;
|
||||
*/
|
||||
static size_t huge_class_size;
|
||||
|
||||
static const struct block_device_operations zram_devops;
|
||||
static const struct block_device_operations zram_wb_devops;
|
||||
|
||||
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);
|
||||
@ -207,14 +211,17 @@ static inline void zram_fill_page(void *ptr, unsigned long len,
|
||||
|
||||
static bool page_same_filled(void *ptr, unsigned long *element)
|
||||
{
|
||||
unsigned int pos;
|
||||
unsigned long *page;
|
||||
unsigned long val;
|
||||
unsigned int pos, last_pos = PAGE_SIZE / sizeof(*page) - 1;
|
||||
|
||||
page = (unsigned long *)ptr;
|
||||
val = page[0];
|
||||
|
||||
for (pos = 1; pos < PAGE_SIZE / sizeof(*page); pos++) {
|
||||
if (val != page[last_pos])
|
||||
return false;
|
||||
|
||||
for (pos = 1; pos < last_pos; pos++) {
|
||||
if (val != page[pos])
|
||||
return false;
|
||||
}
|
||||
@ -396,16 +403,12 @@ static void reset_bdev(struct zram *zram)
|
||||
return;
|
||||
|
||||
bdev = zram->bdev;
|
||||
if (zram->old_block_size)
|
||||
set_blocksize(bdev, zram->old_block_size);
|
||||
blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
|
||||
/* hope filp_close flush all of IO */
|
||||
filp_close(zram->backing_dev, NULL);
|
||||
zram->backing_dev = NULL;
|
||||
zram->old_block_size = 0;
|
||||
zram->bdev = NULL;
|
||||
zram->disk->queue->backing_dev_info->capabilities |=
|
||||
BDI_CAP_SYNCHRONOUS_IO;
|
||||
zram->disk->fops = &zram_devops;
|
||||
kvfree(zram->bitmap);
|
||||
zram->bitmap = NULL;
|
||||
}
|
||||
@ -448,7 +451,7 @@ static ssize_t backing_dev_store(struct device *dev,
|
||||
struct file *backing_dev = NULL;
|
||||
struct inode *inode;
|
||||
struct address_space *mapping;
|
||||
unsigned int bitmap_sz, old_block_size = 0;
|
||||
unsigned int bitmap_sz;
|
||||
unsigned long nr_pages, *bitmap = NULL;
|
||||
struct block_device *bdev = NULL;
|
||||
int err;
|
||||
@ -487,9 +490,10 @@ static ssize_t backing_dev_store(struct device *dev,
|
||||
goto out;
|
||||
}
|
||||
|
||||
bdev = bdgrab(I_BDEV(inode));
|
||||
err = blkdev_get(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL, zram);
|
||||
if (err < 0) {
|
||||
bdev = blkdev_get_by_dev(inode->i_rdev,
|
||||
FMODE_READ | FMODE_WRITE | FMODE_EXCL, zram);
|
||||
if (IS_ERR(bdev)) {
|
||||
err = PTR_ERR(bdev);
|
||||
bdev = NULL;
|
||||
goto out;
|
||||
}
|
||||
@ -502,14 +506,8 @@ static ssize_t backing_dev_store(struct device *dev,
|
||||
goto out;
|
||||
}
|
||||
|
||||
old_block_size = block_size(bdev);
|
||||
err = set_blocksize(bdev, PAGE_SIZE);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
reset_bdev(zram);
|
||||
|
||||
zram->old_block_size = old_block_size;
|
||||
zram->bdev = bdev;
|
||||
zram->backing_dev = backing_dev;
|
||||
zram->bitmap = bitmap;
|
||||
@ -524,8 +522,7 @@ static ssize_t backing_dev_store(struct device *dev,
|
||||
* freely but in fact, IO is going on so finally could cause
|
||||
* use-after-free when the IO is really done.
|
||||
*/
|
||||
zram->disk->queue->backing_dev_info->capabilities &=
|
||||
~BDI_CAP_SYNCHRONOUS_IO;
|
||||
zram->disk->fops = &zram_wb_devops;
|
||||
up_write(&zram->init_lock);
|
||||
|
||||
pr_info("setup backing device %s\n", file_name);
|
||||
@ -533,8 +530,7 @@ static ssize_t backing_dev_store(struct device *dev,
|
||||
|
||||
return len;
|
||||
out:
|
||||
if (bitmap)
|
||||
kvfree(bitmap);
|
||||
kvfree(bitmap);
|
||||
|
||||
if (bdev)
|
||||
blkdev_put(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
|
||||
@ -630,7 +626,7 @@ static ssize_t writeback_store(struct device *dev,
|
||||
struct bio bio;
|
||||
struct bio_vec bio_vec;
|
||||
struct page *page;
|
||||
ssize_t ret;
|
||||
ssize_t ret = len;
|
||||
int mode, err;
|
||||
unsigned long blk_idx = 0;
|
||||
|
||||
@ -780,7 +776,6 @@ next:
|
||||
|
||||
if (blk_idx)
|
||||
free_block_bdev(zram, blk_idx);
|
||||
ret = len;
|
||||
__free_page(page);
|
||||
release_init_lock:
|
||||
up_read(&zram->init_lock);
|
||||
@ -808,9 +803,9 @@ static void zram_sync_read(struct work_struct *work)
|
||||
}
|
||||
|
||||
/*
|
||||
* Block layer want one ->make_request_fn to be active at a time
|
||||
* so if we use chained IO with parent IO in same context,
|
||||
* it's a deadlock. To avoid, it, it uses worker thread context.
|
||||
* Block layer want one ->submit_bio to be active at a time, so if we use
|
||||
* chained IO with parent IO in same context, it's a deadlock. To avoid that,
|
||||
* use a worker thread context.
|
||||
*/
|
||||
static int read_from_bdev_sync(struct zram *zram, struct bio_vec *bvec,
|
||||
unsigned long entry, struct bio *bio)
|
||||
@ -915,7 +910,7 @@ static ssize_t read_block_state(struct file *file, char __user *buf,
|
||||
zram_test_flag(zram, index, ZRAM_HUGE) ? 'h' : '.',
|
||||
zram_test_flag(zram, index, ZRAM_IDLE) ? 'i' : '.');
|
||||
|
||||
if (count <= copied) {
|
||||
if (count < copied) {
|
||||
zram_slot_unlock(zram, index);
|
||||
break;
|
||||
}
|
||||
@ -1084,7 +1079,7 @@ static ssize_t mm_stat_show(struct device *dev,
|
||||
max_used = atomic_long_read(&zram->stats.max_used_pages);
|
||||
|
||||
ret = scnprintf(buf, PAGE_SIZE,
|
||||
"%8llu %8llu %8llu %8lu %8ld %8llu %8lu %8llu\n",
|
||||
"%8llu %8llu %8llu %8lu %8ld %8llu %8lu %8llu %8llu\n",
|
||||
orig_size << PAGE_SHIFT,
|
||||
(u64)atomic64_read(&zram->stats.compr_data_size),
|
||||
mem_used << PAGE_SHIFT,
|
||||
@ -1092,7 +1087,8 @@ static ssize_t mm_stat_show(struct device *dev,
|
||||
max_used << PAGE_SHIFT,
|
||||
(u64)atomic64_read(&zram->stats.same_pages),
|
||||
atomic_long_read(&pool_stats.pages_compacted),
|
||||
(u64)atomic64_read(&zram->stats.huge_pages));
|
||||
(u64)atomic64_read(&zram->stats.huge_pages),
|
||||
(u64)atomic64_read(&zram->stats.huge_pages_since));
|
||||
up_read(&zram->init_lock);
|
||||
|
||||
return ret;
|
||||
@ -1231,10 +1227,11 @@ out:
|
||||
static int __zram_bvec_read(struct zram *zram, struct page *page, u32 index,
|
||||
struct bio *bio, bool partial_io)
|
||||
{
|
||||
int ret;
|
||||
struct zcomp_strm *zstrm;
|
||||
unsigned long handle;
|
||||
unsigned int size;
|
||||
void *src, *dst;
|
||||
int ret;
|
||||
|
||||
zram_slot_lock(zram, index);
|
||||
if (zram_test_flag(zram, index, ZRAM_WB)) {
|
||||
@ -1265,6 +1262,9 @@ static int __zram_bvec_read(struct zram *zram, struct page *page, u32 index,
|
||||
|
||||
size = zram_get_obj_size(zram, index);
|
||||
|
||||
if (size != PAGE_SIZE)
|
||||
zstrm = zcomp_stream_get(zram->comp);
|
||||
|
||||
src = zs_map_object(zram->mem_pool, handle, ZS_MM_RO);
|
||||
if (size == PAGE_SIZE) {
|
||||
dst = kmap_atomic(page);
|
||||
@ -1272,8 +1272,6 @@ static int __zram_bvec_read(struct zram *zram, struct page *page, u32 index,
|
||||
kunmap_atomic(dst);
|
||||
ret = 0;
|
||||
} else {
|
||||
struct zcomp_strm *zstrm = zcomp_stream_get(zram->comp);
|
||||
|
||||
dst = kmap_atomic(page);
|
||||
ret = zcomp_decompress(zstrm, src, size, dst);
|
||||
kunmap_atomic(dst);
|
||||
@ -1283,7 +1281,7 @@ static int __zram_bvec_read(struct zram *zram, struct page *page, u32 index,
|
||||
zram_slot_unlock(zram, index);
|
||||
|
||||
/* Should NEVER happen. Return bio error if it does. */
|
||||
if (unlikely(ret))
|
||||
if (WARN_ON(ret))
|
||||
pr_err("Decompression failed! err=%d, page=%u\n", ret, index);
|
||||
|
||||
return ret;
|
||||
@ -1378,14 +1376,13 @@ compress_again:
|
||||
__GFP_KSWAPD_RECLAIM |
|
||||
__GFP_NOWARN |
|
||||
__GFP_HIGHMEM |
|
||||
__GFP_MOVABLE |
|
||||
__GFP_CMA);
|
||||
__GFP_MOVABLE);
|
||||
if (!handle) {
|
||||
zcomp_stream_put(zram->comp);
|
||||
atomic64_inc(&zram->stats.writestall);
|
||||
handle = zs_malloc(zram->mem_pool, comp_len,
|
||||
GFP_NOIO | __GFP_HIGHMEM |
|
||||
__GFP_MOVABLE | __GFP_CMA);
|
||||
__GFP_MOVABLE);
|
||||
if (handle)
|
||||
goto compress_again;
|
||||
return -ENOMEM;
|
||||
@ -1423,6 +1420,7 @@ out:
|
||||
if (comp_len == PAGE_SIZE) {
|
||||
zram_set_flag(zram, index, ZRAM_HUGE);
|
||||
atomic64_inc(&zram->stats.huge_pages);
|
||||
atomic64_inc(&zram->stats.huge_pages_since);
|
||||
}
|
||||
|
||||
if (flags) {
|
||||
@ -1526,13 +1524,8 @@ static void zram_bio_discard(struct zram *zram, u32 index,
|
||||
static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index,
|
||||
int offset, unsigned int op, struct bio *bio)
|
||||
{
|
||||
unsigned long start_time = jiffies;
|
||||
struct request_queue *q = zram->disk->queue;
|
||||
int ret;
|
||||
|
||||
generic_start_io_acct(q, op, bvec->bv_len >> SECTOR_SHIFT,
|
||||
&zram->disk->part0);
|
||||
|
||||
if (!op_is_write(op)) {
|
||||
atomic64_inc(&zram->stats.num_reads);
|
||||
ret = zram_bvec_read(zram, bvec, index, offset, bio);
|
||||
@ -1542,8 +1535,6 @@ static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index,
|
||||
ret = zram_bvec_write(zram, bvec, index, offset, bio);
|
||||
}
|
||||
|
||||
generic_end_io_acct(q, op, &zram->disk->part0, start_time);
|
||||
|
||||
zram_slot_lock(zram, index);
|
||||
zram_accessed(zram, index);
|
||||
zram_slot_unlock(zram, index);
|
||||
@ -1564,6 +1555,7 @@ static void __zram_make_request(struct zram *zram, struct bio *bio)
|
||||
u32 index;
|
||||
struct bio_vec bvec;
|
||||
struct bvec_iter iter;
|
||||
unsigned long start_time;
|
||||
|
||||
index = bio->bi_iter.bi_sector >> SECTORS_PER_PAGE_SHIFT;
|
||||
offset = (bio->bi_iter.bi_sector &
|
||||
@ -1579,6 +1571,7 @@ static void __zram_make_request(struct zram *zram, struct bio *bio)
|
||||
break;
|
||||
}
|
||||
|
||||
start_time = bio_start_io_acct(bio);
|
||||
bio_for_each_segment(bvec, bio, iter) {
|
||||
struct bio_vec bv = bvec;
|
||||
unsigned int unwritten = bvec.bv_len;
|
||||
@ -1587,8 +1580,10 @@ static void __zram_make_request(struct zram *zram, struct bio *bio)
|
||||
bv.bv_len = min_t(unsigned int, PAGE_SIZE - offset,
|
||||
unwritten);
|
||||
if (zram_bvec_rw(zram, &bv, index, offset,
|
||||
bio_op(bio), bio) < 0)
|
||||
goto out;
|
||||
bio_op(bio), bio) < 0) {
|
||||
bio->bi_status = BLK_STS_IOERR;
|
||||
break;
|
||||
}
|
||||
|
||||
bv.bv_offset += bv.bv_len;
|
||||
unwritten -= bv.bv_len;
|
||||
@ -1596,20 +1591,16 @@ static void __zram_make_request(struct zram *zram, struct bio *bio)
|
||||
update_position(&index, &offset, &bv);
|
||||
} while (unwritten);
|
||||
}
|
||||
|
||||
bio_end_io_acct(bio, start_time);
|
||||
bio_endio(bio);
|
||||
return;
|
||||
|
||||
out:
|
||||
bio_io_error(bio);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handler function for all zram I/O requests.
|
||||
*/
|
||||
static blk_qc_t zram_make_request(struct request_queue *queue, struct bio *bio)
|
||||
static blk_qc_t zram_submit_bio(struct bio *bio)
|
||||
{
|
||||
struct zram *zram = queue->queuedata;
|
||||
struct zram *zram = bio->bi_bdev->bd_disk->private_data;
|
||||
|
||||
if (!valid_io_request(zram, bio->bi_iter.bi_sector,
|
||||
bio->bi_iter.bi_size)) {
|
||||
@ -1649,6 +1640,7 @@ static int zram_rw_page(struct block_device *bdev, sector_t sector,
|
||||
u32 index;
|
||||
struct zram *zram;
|
||||
struct bio_vec bv;
|
||||
unsigned long start_time;
|
||||
|
||||
if (PageTransHuge(page))
|
||||
return -ENOTSUPP;
|
||||
@ -1667,7 +1659,9 @@ static int zram_rw_page(struct block_device *bdev, sector_t sector,
|
||||
bv.bv_len = PAGE_SIZE;
|
||||
bv.bv_offset = 0;
|
||||
|
||||
start_time = disk_start_io_acct(bdev->bd_disk, SECTORS_PER_PAGE, op);
|
||||
ret = zram_bvec_rw(zram, &bv, index, offset, op, NULL);
|
||||
disk_end_io_acct(bdev->bd_disk, op, start_time);
|
||||
out:
|
||||
/*
|
||||
* If I/O fails, just return error(ie, non-zero) without
|
||||
@ -1711,8 +1705,8 @@ static void zram_reset_device(struct zram *zram)
|
||||
disksize = zram->disksize;
|
||||
zram->disksize = 0;
|
||||
|
||||
set_capacity(zram->disk, 0);
|
||||
part_stat_set_all(&zram->disk->part0, 0);
|
||||
set_capacity_and_notify(zram->disk, 0);
|
||||
part_stat_set_all(zram->disk->part0, 0);
|
||||
|
||||
up_write(&zram->init_lock);
|
||||
/* I/O operation under all of CPU are done so let's free */
|
||||
@ -1757,9 +1751,7 @@ static ssize_t disksize_store(struct device *dev,
|
||||
|
||||
zram->comp = comp;
|
||||
zram->disksize = disksize;
|
||||
set_capacity(zram->disk, zram->disksize >> SECTOR_SHIFT);
|
||||
|
||||
revalidate_disk(zram->disk);
|
||||
set_capacity_and_notify(zram->disk, zram->disksize >> SECTOR_SHIFT);
|
||||
up_write(&zram->init_lock);
|
||||
|
||||
return len;
|
||||
@ -1787,31 +1779,26 @@ static ssize_t reset_store(struct device *dev,
|
||||
return -EINVAL;
|
||||
|
||||
zram = dev_to_zram(dev);
|
||||
bdev = bdget_disk(zram->disk, 0);
|
||||
if (!bdev)
|
||||
return -ENOMEM;
|
||||
bdev = zram->disk->part0;
|
||||
|
||||
mutex_lock(&bdev->bd_mutex);
|
||||
mutex_lock(&bdev->bd_disk->open_mutex);
|
||||
/* Do not reset an active device or claimed device */
|
||||
if (bdev->bd_openers || zram->claim) {
|
||||
mutex_unlock(&bdev->bd_mutex);
|
||||
bdput(bdev);
|
||||
mutex_unlock(&bdev->bd_disk->open_mutex);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* From now on, anyone can't open /dev/zram[0-9] */
|
||||
zram->claim = true;
|
||||
mutex_unlock(&bdev->bd_mutex);
|
||||
mutex_unlock(&bdev->bd_disk->open_mutex);
|
||||
|
||||
/* Make sure all the pending I/O are finished */
|
||||
fsync_bdev(bdev);
|
||||
zram_reset_device(zram);
|
||||
revalidate_disk(zram->disk);
|
||||
bdput(bdev);
|
||||
|
||||
mutex_lock(&bdev->bd_mutex);
|
||||
mutex_lock(&bdev->bd_disk->open_mutex);
|
||||
zram->claim = false;
|
||||
mutex_unlock(&bdev->bd_mutex);
|
||||
mutex_unlock(&bdev->bd_disk->open_mutex);
|
||||
|
||||
return len;
|
||||
}
|
||||
@ -1821,7 +1808,7 @@ static int zram_open(struct block_device *bdev, fmode_t mode)
|
||||
int ret = 0;
|
||||
struct zram *zram;
|
||||
|
||||
WARN_ON(!mutex_is_locked(&bdev->bd_mutex));
|
||||
WARN_ON(!mutex_is_locked(&bdev->bd_disk->open_mutex));
|
||||
|
||||
zram = bdev->bd_disk->private_data;
|
||||
/* zram was claimed to reset so open request fails */
|
||||
@ -1833,11 +1820,19 @@ static int zram_open(struct block_device *bdev, fmode_t mode)
|
||||
|
||||
static const struct block_device_operations zram_devops = {
|
||||
.open = zram_open,
|
||||
.submit_bio = zram_submit_bio,
|
||||
.swap_slot_free_notify = zram_slot_free_notify,
|
||||
.rw_page = zram_rw_page,
|
||||
.owner = THIS_MODULE
|
||||
};
|
||||
|
||||
static const struct block_device_operations zram_wb_devops = {
|
||||
.open = zram_open,
|
||||
.submit_bio = zram_submit_bio,
|
||||
.swap_slot_free_notify = zram_slot_free_notify,
|
||||
.owner = THIS_MODULE
|
||||
};
|
||||
|
||||
static DEVICE_ATTR_WO(compact);
|
||||
static DEVICE_ATTR_RW(disksize);
|
||||
static DEVICE_ATTR_RO(initstate);
|
||||
@ -1895,7 +1890,6 @@ static const struct attribute_group *zram_disk_attr_groups[] = {
|
||||
static int zram_add(void)
|
||||
{
|
||||
struct zram *zram;
|
||||
struct request_queue *queue;
|
||||
int ret, device_id;
|
||||
|
||||
zram = kzalloc(sizeof(struct zram), GFP_KERNEL);
|
||||
@ -1911,30 +1905,20 @@ static int zram_add(void)
|
||||
#ifdef CONFIG_ZRAM_WRITEBACK
|
||||
spin_lock_init(&zram->wb_limit_lock);
|
||||
#endif
|
||||
queue = blk_alloc_queue(GFP_KERNEL);
|
||||
if (!queue) {
|
||||
pr_err("Error allocating disk queue for device %d\n",
|
||||
|
||||
/* gendisk structure */
|
||||
zram->disk = blk_alloc_disk(NUMA_NO_NODE);
|
||||
if (!zram->disk) {
|
||||
pr_err("Error allocating disk structure for device %d\n",
|
||||
device_id);
|
||||
ret = -ENOMEM;
|
||||
goto out_free_idr;
|
||||
}
|
||||
|
||||
blk_queue_make_request(queue, zram_make_request);
|
||||
|
||||
/* gendisk structure */
|
||||
zram->disk = alloc_disk(1);
|
||||
if (!zram->disk) {
|
||||
pr_err("Error allocating disk structure for device %d\n",
|
||||
device_id);
|
||||
ret = -ENOMEM;
|
||||
goto out_free_queue;
|
||||
}
|
||||
|
||||
zram->disk->major = zram_major;
|
||||
zram->disk->first_minor = device_id;
|
||||
zram->disk->minors = 1;
|
||||
zram->disk->fops = &zram_devops;
|
||||
zram->disk->queue = queue;
|
||||
zram->disk->queue->queuedata = zram;
|
||||
zram->disk->private_data = zram;
|
||||
snprintf(zram->disk->disk_name, 16, "zram%d", device_id);
|
||||
|
||||
@ -1968,8 +1952,7 @@ static int zram_add(void)
|
||||
if (ZRAM_LOGICAL_BLOCK_SIZE == PAGE_SIZE)
|
||||
blk_queue_max_write_zeroes_sectors(zram->disk->queue, UINT_MAX);
|
||||
|
||||
zram->disk->queue->backing_dev_info->capabilities |=
|
||||
(BDI_CAP_STABLE_WRITES | BDI_CAP_SYNCHRONOUS_IO);
|
||||
blk_queue_flag_set(QUEUE_FLAG_STABLE_WRITES, zram->disk->queue);
|
||||
disk_to_dev(zram->disk)->groups = zram_disk_attr_groups;
|
||||
add_disk(zram->disk);
|
||||
|
||||
@ -1979,8 +1962,6 @@ static int zram_add(void)
|
||||
pr_info("Added device: %s\n", zram->disk->disk_name);
|
||||
return device_id;
|
||||
|
||||
out_free_queue:
|
||||
blk_cleanup_queue(queue);
|
||||
out_free_idr:
|
||||
idr_remove(&zram_index_idr, device_id);
|
||||
out_free_dev:
|
||||
@ -1990,33 +1971,26 @@ out_free_dev:
|
||||
|
||||
static int zram_remove(struct zram *zram)
|
||||
{
|
||||
struct block_device *bdev;
|
||||
struct block_device *bdev = zram->disk->part0;
|
||||
|
||||
bdev = bdget_disk(zram->disk, 0);
|
||||
if (!bdev)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_lock(&bdev->bd_mutex);
|
||||
mutex_lock(&bdev->bd_disk->open_mutex);
|
||||
if (bdev->bd_openers || zram->claim) {
|
||||
mutex_unlock(&bdev->bd_mutex);
|
||||
bdput(bdev);
|
||||
mutex_unlock(&bdev->bd_disk->open_mutex);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
zram->claim = true;
|
||||
mutex_unlock(&bdev->bd_mutex);
|
||||
mutex_unlock(&bdev->bd_disk->open_mutex);
|
||||
|
||||
zram_debugfs_unregister(zram);
|
||||
/* Make sure all the pending I/O are finished */
|
||||
fsync_bdev(bdev);
|
||||
zram_reset_device(zram);
|
||||
bdput(bdev);
|
||||
|
||||
pr_info("Removed device: %s\n", zram->disk->disk_name);
|
||||
|
||||
del_gendisk(zram->disk);
|
||||
blk_cleanup_queue(zram->disk->queue);
|
||||
put_disk(zram->disk);
|
||||
blk_cleanup_disk(zram->disk);
|
||||
kfree(zram);
|
||||
return 0;
|
||||
}
|
||||
|
@ -78,6 +78,7 @@ struct zram_stats {
|
||||
atomic64_t notify_free; /* no. of swap slot free notifications */
|
||||
atomic64_t same_pages; /* no. of same element filled pages */
|
||||
atomic64_t huge_pages; /* no. of huge pages */
|
||||
atomic64_t huge_pages_since; /* no. of huge pages since zram set up */
|
||||
atomic64_t pages_stored; /* no. of pages currently stored */
|
||||
atomic_long_t max_used_pages; /* no. of maximum pages stored */
|
||||
atomic64_t writestall; /* no. of write slow paths */
|
||||
@ -111,14 +112,13 @@ struct zram {
|
||||
/*
|
||||
* zram is claimed so open request will be failed
|
||||
*/
|
||||
bool claim; /* Protected by bdev->bd_mutex */
|
||||
bool claim; /* Protected by disk->open_mutex */
|
||||
#ifdef CONFIG_ZRAM_WRITEBACK
|
||||
struct file *backing_dev;
|
||||
spinlock_t wb_limit_lock;
|
||||
bool wb_limit_enable;
|
||||
u64 bd_wb_limit;
|
||||
struct block_device *bdev;
|
||||
unsigned int old_block_size;
|
||||
unsigned long *bitmap;
|
||||
unsigned long nr_pages;
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user