drivers/char/mem: byte generating devices and poisoned mappings
Subsystems (3)
RFC PATCH 1/1 drivers/char/mem: byte generating devices and poisoned mappings
This patch adds 256 virtual character devices: /dev/byte0, ..., /dev/byte255. Each works like /dev/zero but generates memory filled with particular byte.
Features/use cases:
* handy source of non-zero bytes for 'dd' (dd if=/dev/byte1 ...)
* effective way for allocating poisoned memory (just mmap, without memset)
* /dev/byte42 is full of stars (*)
Memory filled by default with non-zero bytes might help optimize logic in some applications. For example (according to Yury Gribov) Address Sanitizer generates additional conditional jump for each memory access just to handle default zero byte as '0x8' to avoid memset`ing huge shadow memory map at the beginning. In this case allocating memory via mapping /dev/byte8 will reduce size and overhead of instrumented code without adding any memory usage overhead.
/dev/byteX devices have the same performance optimizations like /dev/zero. Shared read-only pages are allocated lazily at the first request and freed by the memory shrinker (design inspired by huge-zero-page). Private mappings are organized as normal anonymous mappings with special page-fault handler which allocates, initializes and installs pages like do_anonymous_page().
Unlike to /dev/zero shared ro-pages are installed into PTEs as normal pages and accounted into file-RSS: vm_normal_page() allows only zero-page to be installed as 'special'. This difference is fixable, but I don't see why it's matters.
This patch also (mostly) implements effective non-zero-filled shmem/tmpfs files, (they are used for shared mappings) but here is no interface for the userspace. This feature mught be exported as ioctl or fcntl call.
--- drivers/char/Kconfig | 7 + drivers/char/mem.c | 285 ++++++++++++++++++++++++++++++++++++++++++++++ include/linux/shmem_fs.h | 4 + mm/shmem.c | 58 ++++++++- 4 files changed, 346 insertions(+), 8 deletions(-)
drivers/char/Kconfig +7 -0
@@ -15,6 +15,13 @@ config DEVKMEM kind of kernel debugging operations. When in doubt, say "N". +config DEVBYTES + bool "Byte generating devices" + depends on SHMEM + help + This option adds 256 virual devices similar to /dev/zero, + one for each byte value: /dev/byte0, /dev/byte1, ..., /dev/byte255. + config SGI_SNSC bool "SGI Altix system controller communication support" depends on (IA64_SGI_SN2 || IA64_GENERIC)
drivers/char/mem.c +285 -0
303 lines not on this page · raw message
include/linux/shmem_fs.h +4 -0
@@ -11,6 +11,7 @@struct shmem_inode_info {spinlock_t lock; +unsigned char byte;/* byte for filling new pages */ unsigned long flags;unsigned long alloced;/* data pages alloced to file */ union {
@@ -57,6 +58,9 @@ extern struct page *shmem_read_mapping_page_gfp(struct address_space *mapping,extern void shmem_truncate_range (struct inode *inode,loff_t start,loff_t end);extern int shmem_unuse (swp_entry_t entry,struct page *page); +extern struct page *get_byte_page (unsigned char byte); +extern int shmem_byte_setup (struct vm_area_struct *vma,unsigned char byte); +static inline struct page *shmem_read_mapping_page (struct address_space *mapping,pgoff_t index) {
mm/shmem.c +50 -8
88 lines not on this page · raw message
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 2 lines · Konstantin Khlebnikov
This patch adds 256 virtual character devices:
/dev/byte0, ...,/dev/byte255. Each works like/dev/zerobut generates memory filled with particular byte.
Shouldn't /dev/byte0 be an alias for /dev/zero?
I see you reuse ZERO_PAGE(0) for that, but what about all these special cases /dev/zero has?
Quoted 18 lines
Features/use cases:
* handy source of non-zero bytes for 'dd' (dd if=/dev/byte1 ...)
* effective way for allocating poisoned memory (just mmap, without memset)
*/dev/byte42is full of stars (*)Memory filled by default with non-zero bytes might help optimize logic in some applications. For example (according to Yury Gribov) Address Sanitizer generates additional conditional jump for each memory access just to handle default zero byte as '
0x8' to avoid memset`ing huge shadow memory map at the beginning. In this case allocating memory via mapping/dev/byte8will reduce size and overhead of instrumented code without adding any memory usage overhead.
/dev/byteXdevices have the same performance optimizations like/dev/zero. Shared read-only pages are allocated lazily at the first request and freed by the memory shrinker (design inspired by huge-zero-page). Private mappings are organized as normal anonymous mappings with special page-fault handler which allocates, initializes and installs pages likedo_anonymous_page().
Quoted 3 lines
Unlike to
/dev/zeroshared ro-pages are installed into PTEs as normal pages and accounted into file-RSS:vm_normal_page()allows only zero-page to be installed as 'special'. This difference is fixable, but I don't see why it's matters.
One thing that could surprise is unexpectedly big core dump files caused by /dev/byteX mappings. We have special handling for FOLL_DUMP && zero_page. Not sure if /dev/byteX should be handled this way too.
Quoted 23 lines
This patch also (mostly) implements effective non-zero-filled shmem/tmpfs files, (they are used for shared mappings) but here is no interface for the userspace. This feature mught be exported as ioctl or fcntl call.
Signed-off-by Konstantin Khlebnikov <[email protected]>Cc Alexandr Andreev <[email protected]>Cc Vassili Karpov <[email protected]>Cc Yury Gribov <[email protected]>Cc Andrew Morton <[email protected]>Cc Hugh Dickins <[email protected]>Cc Kirill A. Shutemov <[email protected]>--- drivers/char/Kconfig | 7 + drivers/char/mem.c | 285 ++++++++++++++++++++++++++++++++++++++++++++++ include/linux/shmem_fs.h | 4 + mm/shmem.c | 58 ++++++++- 4 files changed, 346 insertions(+), 8 deletions(-)drivers/char/Kconfig +0
-0
drivers/char/Kconfig config DEVKMEM · line 18
Quoted 4 lines
drivers/char/Kconfig +1
-0@@ -15,6 +15,13 @@ config DEVKMEM kind of kernel debugging operations. When in doubt, say "N". +config DEVBYTES
I don't think we want new option for this.
Quoted 6 lines
drivers/char/Kconfig +6
-0+ bool "Byte generating devices" + depends on SHMEM + help + This option adds 256 virual devices similar to /dev/zero, + one for each byte value: /dev/byte0, /dev/byte1, ..., /dev/byte255. +
...
Quoted 17 lines
drivers/char/Kconfig +17
-0+static ssize_t byte_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + unsigned byte = (unsigned long)file->private_data; + size_t written; + + if (!count) + return 0; + + if (!access_ok(VERIFY_WRITE, buf, count)) + return -EFAULT; + + written = 0; + while (count) { + size_t chunk = min(count, PAGE_SIZE); + + if (__memset_user(buf, byte, chunk))
drivers/char/Kconfig
Quoted 10 lines
drivers/char/Kconfig +10
-0+ return -EFAULT; + if (signal_pending(current)) + return written ? written : -ERESTARTSYS; + written += chunk; + buf += chunk; + count -= chunk; + cond_resched(); + } + return written; +}
Shouldn't this code be shared with read_zero()?
Quoted 8 lines
drivers/char/Kconfig +8
-0+ +static ssize_t byte_aio_read(struct kiocb *iocb, const struct iovec *iov, + unsigned long nr_segs, loff_t pos) +{ + size_t written = 0; + unsigned long i; + ssize_t ret; +
drivers/char/Kconfig
Quoted 10 lines
drivers/char/Kconfig +10
-0+ for (i = 0; i < nr_segs; i++) { + ret = byte_read(iocb->ki_filp, iov[i].iov_base, iov[i].iov_len, + &pos); + if (ret < 0) + break; + written += ret; + } + + return written ? written : -EFAULT; +}
Ditto.
Quoted 8 lines
drivers/char/Kconfig +8
-0+ +static const struct file_operations byte_fops = { + .llseek = byte_lseek, + .read = byte_read, + .write = byte_write, + .aio_read = byte_aio_read, + .aio_write = byte_aio_write, + .open = byte_open,
drivers/char/Kconfig
Quoted 10 lines
drivers/char/Kconfig +10
-0+ .mmap = byte_mmap, +}; + +static int __init byte_init(void) +{ + int major, minor; + + major = __register_chrdev(0, 0, 256, "byte", &byte_fops); + if (major < 0) { + printk("unable to get major for byte devs\n");
Hm. Can we, instead of having 256 devnodes, have one /dev/byte? User can ask which byte it wants by write() byte to file descriptor before using it with zero by default.
Signature · 7 lines
Kirill A. Shutemov -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 7 lines · Kirill A. Shutemov
Quoted 2 lines · Konstantin Khlebnikov
This patch adds 256 virtual character devices:
/dev/byte0, ...,/dev/byte255. Each works like/dev/zerobut generates memory filled with particular byte.Shouldn't
/dev/byte0be an alias for/dev/zero?
I see you reuseZERO_PAGE(0)for that, but what about all these special cases/dev/zerohas?
What special cases? I found rss-accounting part, you've mentioned coredump.
Quoted 19 lines
Quoted 19 lines
Features/use cases:
* handy source of non-zero bytes for 'dd' (dd if=/dev/byte1 ...)
* effective way for allocating poisoned memory (just mmap, without memset)
*/dev/byte42is full of stars (*)Memory filled by default with non-zero bytes might help optimize logic in some applications. For example (according to Yury Gribov) Address Sanitizer generates additional conditional jump for each memory access just to handle default zero byte as '
0x8' to avoid memset`ing huge shadow memory map at the beginning. In this case allocating memory via mapping/dev/byte8will reduce size and overhead of instrumented code without adding any memory usage overhead.
/dev/byteXdevices have the same performance optimizations like/dev/zero. Shared read-only pages are allocated lazily at the first request and freed by the memory shrinker (design inspired by huge-zero-page). Private mappings are organized as normal anonymous mappings with special page-fault handler which allocates, initializes and installs pages likedo_anonymous_page().
Quoted 7 lines
Quoted 3 lines
Unlike to
/dev/zeroshared ro-pages are installed into PTEs as normal pages and accounted into file-RSS:vm_normal_page()allows only zero-page to be installed as 'special'. This difference is fixable, but I don't see why it's matters.One thing that could surprise is unexpectedly big core dump files caused by
/dev/byteXmappings. We have special handling forFOLL_DUMP&&zero_page. Not sure if/dev/byteXshould be handled this way too.
Seems like it should be. There is no reason for dumping it.
Quoted 61 lines
Quoted 24 lines
This patch also (mostly) implements effective non-zero-filled shmem/tmpfs files, (they are used for shared mappings) but here is no interface for the userspace. This feature mught be exported as ioctl or fcntl call.
Signed-off-by Konstantin Khlebnikov <[email protected]>Cc Alexandr Andreev <[email protected]>Cc Vassili Karpov <[email protected]>Cc Yury Gribov <[email protected]>Cc Andrew Morton <[email protected]>Cc Hugh Dickins <[email protected]>Cc Kirill A. Shutemov <[email protected]>--- drivers/char/Kconfig | 7 + drivers/char/mem.c | 285 ++++++++++++++++++++++++++++++++++++++++++++++ include/linux/shmem_fs.h | 4 + mm/shmem.c | 58 ++++++++- 4 files changed, 346 insertions(+), 8 deletions(-)drivers/char/Kconfig +0
-0drivers/char/Kconfig config DEVKMEM · line 18
Quoted 4 lines
drivers/char/Kconfig +1
-0@@ -15,6 +15,13 @@ config DEVKMEM kind of kernel debugging operations. When in doubt, say "N". +config DEVBYTESI don't think we want new option for this.
Quoted 6 lines
drivers/char/Kconfig +6
-0+ bool "Byte generating devices" + depends on SHMEM + help + This option adds 256 virual devices similar to /dev/zero, + one for each byte value: /dev/byte0, /dev/byte1, ..., /dev/byte255. +...
Quoted 21 lines
drivers/char/Kconfig +21
-0+static ssize_t byte_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + unsigned byte = (unsigned long)file->private_data; + size_t written; + + if (!count) + return 0; + + if (!access_ok(VERIFY_WRITE, buf, count)) + return -EFAULT; + + written = 0; + while (count) { + size_t chunk = min(count, PAGE_SIZE); + + if (__memset_user(buf, byte, chunk)) + return -EFAULT; + if (signal_pending(current)) + return written ? written : -ERESTARTSYS; + written += chunk;
Quoted 8 lines
drivers/char/Kconfig
Quoted 6 lines
drivers/char/Kconfig +6
-0+ buf += chunk; + count -= chunk; + cond_resched(); + } + return written; +}Shouldn't this code be shared with
read_zero()?
yep. it might be merged.
Quoted 36 lines
Quoted 9 lines
drivers/char/Kconfig +8
-0+ +static ssize_t byte_aio_read(struct kiocb *iocb, const struct iovec *iov, + unsigned long nr_segs, loff_t pos) +{ + size_t written = 0; + unsigned long i; + ssize_t ret; +drivers/char/Kconfig
Quoted 10 lines
drivers/char/Kconfig +10
-0+ for (i = 0; i < nr_segs; i++) { + ret = byte_read(iocb->ki_filp, iov[i].iov_base, iov[i].iov_len, + &pos); + if (ret < 0) + break; + written += ret; + } + + return written ? written : -EFAULT; +}Ditto.
Quoted 14 lines
drivers/char/Kconfig +14
-0+ +static const struct file_operations byte_fops = { + .llseek = byte_lseek, + .read = byte_read, + .write = byte_write, + .aio_read = byte_aio_read, + .aio_write = byte_aio_write, + .open = byte_open, + .mmap = byte_mmap, +}; + +static int __init byte_init(void) +{ + int major, minor;
Quoted 8 lines
drivers/char/Kconfig
Quoted 4 lines
drivers/char/Kconfig +4
-0+ + major = __register_chrdev(0, 0, 256, "byte", &byte_fops); + if (major < 0) { + printk("unable to get major for byte devs\n");Hm. Can we, instead of having 256 devnodes, have one
/dev/byte? User can ask which byte it wants bywrite()byte to file descriptor before using it with zero by default.
In this case it wouldn't be usable for "dd" =)
poisoned mmap could be be done without devices at all, mmap(MAP_ANONYMOUS) has plenty unused arguments. For example this might looks like:mmap(flags = MAP_ANONYMOUS | MAP_SHARED/PRIVATE | MAP_POISON, fd = poison)
Quoted 3 lines
--
Kirill A. Shutemov
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 10 lines · Konstantin Khlebnikov
Quoted 7 lines · Kirill A. Shutemov
Quoted 2 lines · Konstantin Khlebnikov
This patch adds 256 virtual character devices:
/dev/byte0, ...,/dev/byte255. Each works like/dev/zerobut generates memory filled with particular byte.Shouldn't
/dev/byte0be an alias for/dev/zero?
I see you reuseZERO_PAGE(0)for that, but what about all these special cases/dev/zerohas?What special cases? I found rss-accounting part, you've mentioned coredump.
I'm not sure what else is there. It's probably good idea to check all users of vm_normal_page().
One thing is zero page coloring which some archs have.
Signature · 7 lines
Kirill A. Shutemov -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 2 lines · On Tue, 01 Apr 2014 01:16:07 +0400 Konstantin Khlebnikov <[email protected]>…
This patch adds 256 virtual character devices:
/dev/byte0, ...,/dev/byte255. Each works like/dev/zerobut generates memory filled with particular byte.
More kernel code for an ultra-obscure corner case that can be done in user space
I don't see the point
Alan
Quoted 10 lines · One Thousand Gnomes
Quoted 2 lines · On Tue, 01 Apr 2014 01:16:07 +0400 Konstantin Khlebnikov <[email protected]>…
This patch adds 256 virtual character devices:
/dev/byte0, ...,/dev/byte255. Each works like/dev/zerobut generates memory filled with particular byte.More kernel code for an ultra-obscure corner case that can be done in user space
I don't see the point
True. That was a long-planned joke.
But at the final moment I've found practical usage for it and overall design became not such funny.
Currently I'm thinking about single-device model proposed by Kirill.
Let's call it /dev/poison. Application can open it, write a poison (up to a page size) and after that this instance will generate pages filled with this pattern. I don't see how this can be done in userspace without major memory/cpu overhead caused by initial memset.
Default poison might be for example 0xff, so it still will be useful for 'dd'.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>