1
- From 859e9756eb70cfc8cf4fb4f0870908e55521cc7f Mon Sep 17 00:00:00 2001
1
+ From 50edda43ef63a1026f59f3cf7ebe80a810a65927 Mon Sep 17 00:00:00 2001
2
2
From: Nikita Kalyazin <
[email protected] >
3
3
Date: Mon, 3 Mar 2025 13:08:37 +0000
4
- Subject: [PATCH 39/46 ] KVM: guest_memfd: add generic population via write
4
+ Subject: [PATCH 1/2 ] KVM: guest_memfd: add generic population via write
5
5
6
6
write syscall populates guest_memfd with user-supplied data in a generic
7
7
way, ie no vendor-specific preparation is performed. This is supposed
@@ -18,109 +18,89 @@ The following behaviour is implemented:
18
18
19
19
Signed-off-by: Nikita Kalyazin <
[email protected] >
20
20
---
21
- virt/kvm/guest_memfd.c | 88 +++++++++++++++++++++++++++++++++++++++++-
22
- 1 file changed, 87 insertions(+), 1 deletion(-)
21
+ virt/kvm/guest_memfd.c | 55 +++++++++++++++++++++++++++++++++++++++++-
22
+ 1 file changed, 54 insertions(+), 1 deletion(-)
23
23
24
24
diff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c
25
- index d70ee66bb96d..809da2a2fb37 100644
25
+ index d70ee66bb96d..81eb05028d0b 100644
26
26
--- a/virt/kvm/guest_memfd.c
27
27
+++ b/virt/kvm/guest_memfd.c
28
- @@ -392,8 +392,93 @@ static int kvm_gmem_mmap(struct file *file, struct vm_area_struct *vma)
29
- return 0;
28
+ @@ -393,7 +393,9 @@ static int kvm_gmem_mmap(struct file *file, struct vm_area_struct *vma)
30
29
}
31
30
32
- + static ssize_t kvm_kmem_gmem_write(struct file *file, const char __user *buf,
33
- + size_t count, loff_t *offset)
31
+ static struct file_operations kvm_gmem_fops = {
32
+ - .mmap = kvm_gmem_mmap,
33
+ + .mmap = kvm_gmem_mmap,
34
+ + .llseek = default_llseek,
35
+ + .write_iter = generic_perform_write,
36
+ .open = generic_file_open,
37
+ .release = kvm_gmem_release,
38
+ .fallocate = kvm_gmem_fallocate,
39
+ @@ -404,6 +406,54 @@ void kvm_gmem_init(struct module *module)
40
+ kvm_gmem_fops.owner = module;
41
+ }
42
+
43
+ + static int kvm_kmem_gmem_write_begin(struct file *file, struct address_space *mapping,
44
+ + loff_t pos, unsigned len, struct folio **foliop,
45
+ + void **fsdata)
34
46
+ {
35
- + pgoff_t start, end, index ;
36
- + ssize_t ret = 0 ;
47
+ + pgoff_t index = pos >> PAGE_SHIFT ;
48
+ + struct folio *folio ;
37
49
+
38
- + if (!PAGE_ALIGNED(*offset ) || !PAGE_ALIGNED(count) )
50
+ + if (!PAGE_ALIGNED(pos ) || len != PAGE_SIZE )
39
51
+ return -EINVAL;
40
52
+
41
- + if (*offset + count > i_size_read(file_inode(file)))
53
+ + if (pos + len > i_size_read(file_inode(file)))
42
54
+ return -EINVAL;
43
55
+
44
- + if (!buf)
45
- + return -EINVAL;
46
- +
47
- + start = *offset >> PAGE_SHIFT;
48
- + end = (*offset + count) >> PAGE_SHIFT;
49
- +
50
- + filemap_invalidate_lock_shared(file->f_mapping);
51
- +
52
- + for (index = start; index < end; ) {
53
- + struct folio *folio;
54
- + void *vaddr;
55
- + pgoff_t buf_offset = (index - start) << PAGE_SHIFT;
56
- +
57
- + if (signal_pending(current)) {
58
- + ret = -EINTR;
59
- + goto out;
60
- + }
56
+ + folio = kvm_gmem_get_folio(file_inode(file), index);
57
+ + if (IS_ERR(folio))
58
+ + return -EFAULT;
61
59
+
62
- + folio = kvm_gmem_get_folio(file_inode(file), index);
63
- + if (IS_ERR(folio)) {
64
- + ret = -EFAULT;
65
- + goto out;
66
- + }
67
- +
68
- + if (folio_test_hwpoison(folio)) {
69
- + folio_unlock(folio);
70
- + folio_put(folio);
71
- + ret = -EFAULT;
72
- + goto out;
73
- + }
74
- +
75
- + /* No support for huge pages. */
76
- + if (WARN_ON_ONCE(folio_test_large(folio))) {
77
- + folio_unlock(folio);
78
- + folio_put(folio);
79
- + ret = -EFAULT;
80
- + goto out;
81
- + }
82
- +
83
- + if (folio_test_uptodate(folio)) {
84
- + folio_unlock(folio);
85
- + folio_put(folio);
86
- + ret = -ENOSPC;
87
- + goto out;
88
- + }
60
+ + if (WARN_ON_ONCE(folio_test_large(folio))) {
61
+ + folio_unlock(folio);
62
+ + folio_put(folio);
63
+ + return -EFAULT;
64
+ + }
89
65
+
66
+ + if (folio_test_uptodate(folio)) {
90
67
+ folio_unlock(folio);
68
+ + folio_put(folio);
69
+ + return -ENOSPC;
70
+ + }
91
71
+
92
- + vaddr = kmap_local_folio(folio, 0);
93
- + ret = copy_from_user(vaddr, buf + buf_offset, PAGE_SIZE);
94
- + kunmap_local(vaddr);
95
- + if (ret) {
96
- + ret = -EINVAL;
97
- + folio_put(folio);
98
- + goto out;
99
- + }
72
+ + *foliop = folio;
73
+ + return 0;
74
+ + }
100
75
+
76
+ + static int kvm_kmem_gmem_write_end(struct file *file, struct address_space *mapping,
77
+ + loff_t pos, unsigned len, unsigned copied,
78
+ + struct folio *folio, void *fsdata)
79
+ + {
80
+ + if (copied == len)
101
81
+ kvm_gmem_mark_prepared(folio);
102
- + folio_put(folio);
103
- +
104
- + index = folio_next_index(folio);
105
- + *offset += PAGE_SIZE;
106
- + }
82
+ + else
83
+ + filemap_remove_folio(folio);
107
84
+
108
- + out:
109
- + filemap_invalidate_unlock_shared(file->f_mapping );
85
+ + folio_unlock(folio);
86
+ + folio_put(folio );
110
87
+
111
- + return ret && start == (*offset >> PAGE_SHIFT) ?
112
- + ret : *offset - (start << PAGE_SHIFT);
88
+ + return copied;
113
89
+ }
114
90
+
115
- static struct file_operations kvm_gmem_fops = {
116
- - .mmap = kvm_gmem_mmap,
117
- + .mmap = kvm_gmem_mmap,
118
- + .llseek = default_llseek,
119
- + .write = kvm_kmem_gmem_write,
120
- .open = generic_file_open,
121
- .release = kvm_gmem_release,
122
- .fallocate = kvm_gmem_fallocate,
123
- @@ -514,6 +599,7 @@ static int __kvm_gmem_create(struct kvm *kvm, loff_t size, u64 flags)
91
+ static int kvm_gmem_migrate_folio(struct address_space *mapping,
92
+ struct folio *dst, struct folio *src,
93
+ enum migrate_mode mode)
94
+ @@ -463,6 +513,8 @@ static void kvm_gmem_free_folio(struct address_space *mapping,
95
+
96
+ static const struct address_space_operations kvm_gmem_aops = {
97
+ .dirty_folio = noop_dirty_folio,
98
+ + .write_begin = kvm_kmem_gmem_write_begin,
99
+ + .write_end = kvm_kmem_gmem_write_end,
100
+ .migrate_folio = kvm_gmem_migrate_folio,
101
+ .error_remove_folio = kvm_gmem_error_folio,
102
+ .free_folio = kvm_gmem_free_folio,
103
+ @@ -514,6 +566,7 @@ static int __kvm_gmem_create(struct kvm *kvm, loff_t size, u64 flags)
124
104
}
125
105
126
106
file->f_flags |= O_LARGEFILE;
0 commit comments