systemd-213: regression with zram
Subsystems (3)
A message that is not in the archive (sent off-list or not yet received): [email protected]
A message that is not in the archive (sent off-list or not yet received): [email protected]
A message that is not in the archive (sent off-list or not yet received): [email protected]
A message that is not in the archive (sent off-list or not yet received): [email protected]
A message that is not in the archive (sent off-list or not yet received): [email protected]
A message that is not in the archive (sent off-list or not yet received): [email protected]
A message that is not in the archive (sent off-list or not yet received): [email protected]
Minchan Kim
maintainerQuoted 26 lines · Alexander E. Patrakov
Quoted 4 lines · Minchan Kim
Hello,
Sorry for the late response.
Better late than never.
Quoted 6 lines
If I parse your problem correctly, you meant that changing disksize is failed while someone opens
/dev/zram0?I tried test which opens "
/dev/zram0" withO_RDWRand sleep forever and then echo $((512<<20)) >/sys/block/zram0/disksizeis successful. IOW, it's okay with me.No, this is only a part of the problem. A valid test would be:
0. Reset the unused zram device.
1. Use a program that opens/dev/zram0withO_RDWRand sleeps until killed.
2. While that program sleeps, echo the correct value to/sys/block/zram0/disksize.
3. Verify (e.g. in/proc/partitions) that the disk size is applied correctly. It is.
4. While that program still sleeps, attempt to mkswap/dev/zram0. This fails:
Quoted 3 lines
mkswap: error: swap area needs to be at least 40 KiB
There is nothing in dmesg.
Thanks. I could reproduce.
When I read strace result, fstat access closed fd which seem to be a culprit.
Cced util-linux.
<snip>
open("/dev/zram0", O_RDONLY) = 4uname({sys="Linux", node="bboxv", ...}) = 0ioctl(4, BLKGETSIZE64, 0x7fffa2384888) = 0
close(4) = 0open("/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 4fstat(4, {st_mode=S_IFREG|0644, st_size=2570, ...}) = 0mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f8a058ea000 read(4, "# Locale name alias data base.\n#"..., 4096) = 2570
read(4, "", 4096) = 0 close(4) = 0 munmap(0x7f8a058ea000, 4096) = 0
open("/usr/share/locale/en_US/LC_MESSAGES/util-linux.mo", O_RDONLY) = -1 ENOENT (No such file or directory) open("/usr/share/locale/en/LC_MESSAGES/util-linux.mo", O_RDONLY) = -1 ENOENT (No such file or directory) open("/usr/share/locale-langpack/en_US/LC_MESSAGES/util-linux.mo", O_RDONLY) = -1 ENOENT (No such file or directory) open("/usr/share/locale-langpack/en/LC_MESSAGES/util-linux.mo", O_RDONLY) = -1 ENOENT (No such file or directory)write(2, "mkswap: ", 8mkswap: ) = 8write(2, "error: swap area needs to be at "..., 44error: swap area needs to be at least 40 KiB) = 44 write(2, "\n", 1
) = 1
write(2, "\nUsage:\n mkswap [options] device"..., 40
Usage:
mkswap [options] device [size]
) = 40
write(2, "\nOptions:\n -c, --check "..., 479
Options:
-c, --check check bad blocks before creating the swap area -f, --force allow swap size area be larger than device -p, --pagesize SIZE specify page size in bytes -L, --label LABEL specify label -v, --swapversion NUM specify swap-space version number -U, --uuid UUID specify the uuid to use -V, --version output version information and exit -h, --help display this help and exit
) = 479exit_group(1) = ?
But when it was successful, it was as follows via stat("/dev/zram0").
<snip>
open("/dev/zram0", O_RDONLY) = 4uname({sys="Linux", node="bboxv", ...}) = 0ioctl(4, BLKGETSIZE64, 0x7fff85926088) = 0
close(4) = 0stat("/dev/zram0", {st_mode=S_IFBLK|0660, st_rdev=makedev(252, 0), ...}) = 0open("/dev/zram0", O_RDWR|O_EXCL) = 4open("/etc/mtab", O_RDONLY|O_CLOEXEC) = 5fstat(5, {st_mode=S_IFREG|0644, st_size=725, ...}) = 0mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f984f537000 read(5, "/dev/vda1 / ext4 rw,errors=remou"..., 4096) = 725
read(5, "", 4096) = 0
close(5) = 0
munmap(0x7f984f537000, 4096) = 0
ioctl(4, BLKALIGNOFF, 0x7fff85925fcc) = 0
lseek(4, 0, SEEK_SET) = 0
ioctl(4, 0x301, 0x7fff85925fc0) = -1 ENOTTY (Inappropriate ioctl for device)
fadvise64(4, 0, 0, POSIX_FADV_RANDOM) = 0
fstat(4, {st_mode=S_IFBLK|0660, st_rdev=makedev(252, 0), ...}) = 0
uname({sys="Linux", node="bboxv", ...}) = 0
ioctl(4, BLKGETSIZE64, 0x15f72b0) = 0
ioctl(4, CDROM_GET_CAPABILITY, 0) = -1 ENOTTY (Inappropriate ioctl for device)
lseek(4, 0, SEEK_SET) = 0read(4, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024ioctl(4, BLKSSZGET, 0x15f72c8) = 0lseek(4, 15872, SEEK_SET) = 15872read(4, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 512) = 512lseek(4, 28672, SEEK_SET) = 28672read(4, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024lseek(4, 0, SEEK_SET) = 0write(4, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024 open("/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 5fstat(5, {st_mode=S_IFREG|0644, st_size=2570, ...}) = 0mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f984f537000 read(5, "# Locale name alias data base.\n#"..., 4096) = 2570
read(5, "", 4096) = 0 close(5) = 0 munmap(0x7f984f537000, 4096) = 0
open("/usr/share/locale/en_US/LC_MESSAGES/util-linux.mo", O_RDONLY) = -1 ENOENT (No such file or directory) open("/usr/share/locale/en/LC_MESSAGES/util-linux.mo", O_RDONLY) = -1 ENOENT (No such file or directory) open("/usr/share/locale-langpack/en_US/LC_MESSAGES/util-linux.mo", O_RDONLY) = -1 ENOENT (No such file or directory) open("/usr/share/locale-langpack/en/LC_MESSAGES/util-linux.mo", O_RDONLY) = -1 ENOENT (No such file or directory) fstat(1, {st_mode=S_IFREG|0644, st_size=8472, ...}) = 0mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f984f537000lseek(4, 1024, SEEK_SET) = 1024
write(4, "\1\0\0\0\377\377\0\0\0\0\0\0\205\236:\36b\377N\324\255\224\5\341CH(\376\0\0\0\0"..., 3072) = 3072
fsync(4) = 0
write(1, "Setting up swapspace version 1, "..., 102Setting up swapspace version 1, size = 262140 KiB no label, UUID=859e3a1e-62ff-4ed4-ad94-05e1434828fe
) = 102exit_group(0) = ?
Quoted 3 lines
Signature · 2 lines
-- Alexander E. Patrakov
_______________________________________________
systemd-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Minchan Kim
maintainerQuoted 29 lines · Minchan Kim
Quoted 28 lines · Alexander E. Patrakov
Quoted 4 lines · Minchan Kim
Hello,
Sorry for the late response.
Better late than never.
Quoted 6 lines
If I parse your problem correctly, you meant that changing disksize is failed while someone opens
/dev/zram0?I tried test which opens "
/dev/zram0" withO_RDWRand sleep forever and then echo $((512<<20)) >/sys/block/zram0/disksizeis successful. IOW, it's okay with me.No, this is only a part of the problem. A valid test would be:
0. Reset the unused zram device.
1. Use a program that opens/dev/zram0withO_RDWRand sleeps until killed.
2. While that program sleeps, echo the correct value to/sys/block/zram0/disksize.
3. Verify (e.g. in/proc/partitions) that the disk size is applied correctly. It is.
4. While that program still sleeps, attempt to mkswap/dev/zram0. This fails:mkswap: error: swap area needs to be at least 40 KiB
Quoted 7 lines
Quoted 1 line
There is nothing in dmesg.
Thanks. I could reproduce.
When I read strace result, fstat access closed fd which seem to be a culprit.Cced util-linux.
When I read disk-utils/mkswap.c, it's not a problem of mkswap. The problem is ioctl(fd, BLKGETSIZE64, bytes) is not work in your scenario. IOW, kernel fault.
Hmm,, will investgate it.
Thanks for the report!
_______________________________________________
systemd-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Minchan Kim
maintainerHello Alexander,
Quoted 36 lines · Minchan Kim
Quoted 35 lines · Minchan Kim
Quoted 26 lines · Alexander E. Patrakov
Quoted 4 lines · Minchan Kim
Hello,
Sorry for the late response.
Better late than never.
Quoted 6 lines
If I parse your problem correctly, you meant that changing disksize is failed while someone opens
/dev/zram0?I tried test which opens "
/dev/zram0" withO_RDWRand sleep forever and then echo $((512<<20)) >/sys/block/zram0/disksizeis successful. IOW, it's okay with me.No, this is only a part of the problem. A valid test would be:
0. Reset the unused zram device.
1. Use a program that opens/dev/zram0withO_RDWRand sleeps until killed.
2. While that program sleeps, echo the correct value to/sys/block/zram0/disksize.
3. Verify (e.g. in/proc/partitions) that the disk size is applied correctly. It is.
4. While that program still sleeps, attempt to mkswap/dev/zram0. This fails:Quoted 3 lines
mkswap: error: swap area needs to be at least 40 KiB
There is nothing in dmesg.
Thanks. I could reproduce.
When I read strace result, fstat access closed fd which seem to be a culprit.
Quoted 8 lines
Quoted 1 line
Cced util-linux.
When I read
disk-utils/mkswap.c, it's not a problem of mkswap. The problem isioctl(fd, BLKGETSIZE64, bytes)is not work in your scenario. IOW, kernel fault.
Hmm,, will investgate it.Thanks for the report!
Could you test this patch? It passed my test.
Thanks!
Quoted 1 line
From
4ab4931c3fa7e6527e3a849d5e4c4f727143e66cMon Sep 17 00:00:00 2001
From: Minchan Kim <[email protected]>
Date: Wed, 25 Jun 2014 09:20:24 +0900
Subject: [PATCH] zram: revalidate disk after capacity change
Alexander reported mkswap on /dev/zram0 is failed if other process is opening the block device file.
Step is as follows,
0. Reset the unused zram device.
1. Use a program that opens /dev/zram0 with O_RDWR and sleeps until killed.
2. While that program sleeps, echo the correct value to /sys/block/zram0/disksize.
3. Verify (e.g. in /proc/partitions) that the disk size is applied correctly. It is.
4. While that program still sleeps, attempt to mkswap /dev/zram0. This fails:
result: mkswap: error: swap area needs to be at least 40 KiB
When I investigated, the size get by ioctl(fd, BLKGETSIZE64) on mkswap to get a size of blockdev was zero although zram0 has right size by 2.
The reason is zram didn't revalidate disk after changing capacity so that size of blockdev's inode is not uptodate until all of file is close.
This patch should fix the problem.
--- drivers/block/zram/zram_drv.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/block/zram/zram_drv.c +4 -1
@@ -622,8 +622,10 @@ static void zram_reset_device(struct zram *zram, bool reset_capacity)memset (&zram->stats,0 ,sizeof (zram->stats)); zram->disksize =0 ; -if (reset_capacity) +if (reset_capacity) {set_capacity (zram->disk,0 ); +revalidate_disk (zram->disk); + }up_write (&zram->init_lock); }
@@ -664,6 +666,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);up_write (&zram->init_lock);return len;
Signature · 6 lines
2.0.0 _______________________________________________ systemd-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Alexander E. Patrakov
Tested-byQuoted 24 lines · Minchan Kim
Could you test this patch? It passed my test.
Thanks!From
4ab4931c3fa7e6527e3a849d5e4c4f727143e66cMon Sep 17 00:00:00 2001
From: Minchan Kim <[email protected]>
Date: Wed, 25 Jun 2014 09:20:24 +0900
Subject: [PATCH] zram: revalidate disk after capacity changeAlexander reported mkswap on
/dev/zram0is failed if other process is opening the block device file.Step is as follows,
0. Reset the unused zram device.
1. Use a program that opens/dev/zram0withO_RDWRand sleeps until killed.
2. While that program sleeps, echo the correct value to/sys/block/zram0/disksize.
3. Verify (e.g. in/proc/partitions) that the disk size is applied correctly. It is.
4. While that program still sleeps, attempt to mkswap/dev/zram0. This fails:
result: mkswap: error: swap area needs to be at least 40 KiBWhen I investigated, the size get by
ioctl(fd, BLKGETSIZE64)on mkswap to get a size of blockdev was zero although zram0 has right size by 2.
Quoted 7 lines
The reason is zram didn't revalidate disk after changing capacity so that size of blockdev's inode is not uptodate until all of file is close.
This patch should fix the problem.
Reported-by Alexander E. Patrakov <[email protected]>Signed-off-by Minchan Kim <[email protected]>
It indeed fixes the problem.
Quoted 29 lines
--- drivers/block/zram/zram_drv.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)drivers/block/zram/zram_drv.c +4
-1@@ -622,8 +622,10 @@ static void zram_reset_device(struct zram *zram, bool reset_capacity)memset (&zram->stats,0 ,sizeof (zram->stats)); zram->disksize =0 ; -if (reset_capacity) +if (reset_capacity) {set_capacity (zram->disk,0 ); +revalidate_disk (zram->disk); + }up_write (&zram->init_lock); }@@ -664,6 +666,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);up_write (&zram->init_lock);return len;
Signature · 1 line
Alexander E. Patrakov