diff options
Diffstat (limited to 'fs/ecryptfs/read_write.c')
-rw-r--r-- | fs/ecryptfs/read_write.c | 27 |
1 files changed, 21 insertions, 6 deletions
diff --git a/fs/ecryptfs/read_write.c b/fs/ecryptfs/read_write.c index 6b7474a4336a..948f57624c05 100644 --- a/fs/ecryptfs/read_write.c +++ b/fs/ecryptfs/read_write.c | |||
@@ -124,6 +124,10 @@ int ecryptfs_write(struct file *ecryptfs_file, char *data, loff_t offset, | |||
124 | loff_t pos; | 124 | loff_t pos; |
125 | int rc = 0; | 125 | int rc = 0; |
126 | 126 | ||
127 | /* | ||
128 | * if we are writing beyond current size, then start pos | ||
129 | * at the current size - we'll fill in zeros from there. | ||
130 | */ | ||
127 | if (offset > ecryptfs_file_size) | 131 | if (offset > ecryptfs_file_size) |
128 | pos = ecryptfs_file_size; | 132 | pos = ecryptfs_file_size; |
129 | else | 133 | else |
@@ -137,6 +141,7 @@ int ecryptfs_write(struct file *ecryptfs_file, char *data, loff_t offset, | |||
137 | if (num_bytes > total_remaining_bytes) | 141 | if (num_bytes > total_remaining_bytes) |
138 | num_bytes = total_remaining_bytes; | 142 | num_bytes = total_remaining_bytes; |
139 | if (pos < offset) { | 143 | if (pos < offset) { |
144 | /* remaining zeros to write, up to destination offset */ | ||
140 | size_t total_remaining_zeros = (offset - pos); | 145 | size_t total_remaining_zeros = (offset - pos); |
141 | 146 | ||
142 | if (num_bytes > total_remaining_zeros) | 147 | if (num_bytes > total_remaining_zeros) |
@@ -167,17 +172,27 @@ int ecryptfs_write(struct file *ecryptfs_file, char *data, loff_t offset, | |||
167 | } | 172 | } |
168 | } | 173 | } |
169 | ecryptfs_page_virt = kmap_atomic(ecryptfs_page, KM_USER0); | 174 | ecryptfs_page_virt = kmap_atomic(ecryptfs_page, KM_USER0); |
175 | |||
176 | /* | ||
177 | * pos: where we're now writing, offset: where the request was | ||
178 | * If current pos is before request, we are filling zeros | ||
179 | * If we are at or beyond request, we are writing the *data* | ||
180 | * If we're in a fresh page beyond eof, zero it in either case | ||
181 | */ | ||
182 | if (pos < offset || !start_offset_in_page) { | ||
183 | /* We are extending past the previous end of the file. | ||
184 | * Fill in zero values to the end of the page */ | ||
185 | memset(((char *)ecryptfs_page_virt | ||
186 | + start_offset_in_page), 0, | ||
187 | PAGE_CACHE_SIZE - start_offset_in_page); | ||
188 | } | ||
189 | |||
190 | /* pos >= offset, we are now writing the data request */ | ||
170 | if (pos >= offset) { | 191 | if (pos >= offset) { |
171 | memcpy(((char *)ecryptfs_page_virt | 192 | memcpy(((char *)ecryptfs_page_virt |
172 | + start_offset_in_page), | 193 | + start_offset_in_page), |
173 | (data + data_offset), num_bytes); | 194 | (data + data_offset), num_bytes); |
174 | data_offset += num_bytes; | 195 | data_offset += num_bytes; |
175 | } else { | ||
176 | /* We are extending past the previous end of the file. | ||
177 | * Fill in zero values up to the start of where we | ||
178 | * will be writing data. */ | ||
179 | memset(((char *)ecryptfs_page_virt | ||
180 | + start_offset_in_page), 0, num_bytes); | ||
181 | } | 196 | } |
182 | kunmap_atomic(ecryptfs_page_virt, KM_USER0); | 197 | kunmap_atomic(ecryptfs_page_virt, KM_USER0); |
183 | flush_dcache_page(ecryptfs_page); | 198 | flush_dcache_page(ecryptfs_page); |