diff options
Diffstat (limited to 'fs/ecryptfs/mmap.c')
-rw-r--r-- | fs/ecryptfs/mmap.c | 31 |
1 files changed, 20 insertions, 11 deletions
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index 16a7a555f39..32c5711d79a 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c | |||
@@ -263,14 +263,13 @@ out: | |||
263 | return 0; | 263 | return 0; |
264 | } | 264 | } |
265 | 265 | ||
266 | /* This function must zero any hole we create */ | ||
266 | static int ecryptfs_prepare_write(struct file *file, struct page *page, | 267 | static int ecryptfs_prepare_write(struct file *file, struct page *page, |
267 | unsigned from, unsigned to) | 268 | unsigned from, unsigned to) |
268 | { | 269 | { |
269 | int rc = 0; | 270 | int rc = 0; |
271 | loff_t prev_page_end_size; | ||
270 | 272 | ||
271 | if (from == 0 && to == PAGE_CACHE_SIZE) | ||
272 | goto out; /* If we are writing a full page, it will be | ||
273 | up to date. */ | ||
274 | if (!PageUptodate(page)) { | 273 | if (!PageUptodate(page)) { |
275 | rc = ecryptfs_read_lower_page_segment(page, page->index, 0, | 274 | rc = ecryptfs_read_lower_page_segment(page, page->index, 0, |
276 | PAGE_CACHE_SIZE, | 275 | PAGE_CACHE_SIZE, |
@@ -283,22 +282,32 @@ static int ecryptfs_prepare_write(struct file *file, struct page *page, | |||
283 | } else | 282 | } else |
284 | SetPageUptodate(page); | 283 | SetPageUptodate(page); |
285 | } | 284 | } |
286 | if (page->index != 0) { | ||
287 | loff_t end_of_prev_pg_pos = | ||
288 | (((loff_t)page->index << PAGE_CACHE_SHIFT) - 1); | ||
289 | 285 | ||
290 | if (end_of_prev_pg_pos > i_size_read(page->mapping->host)) { | 286 | prev_page_end_size = ((loff_t)page->index << PAGE_CACHE_SHIFT); |
287 | |||
288 | /* | ||
289 | * If creating a page or more of holes, zero them out via truncate. | ||
290 | * Note, this will increase i_size. | ||
291 | */ | ||
292 | if (page->index != 0) { | ||
293 | if (prev_page_end_size > i_size_read(page->mapping->host)) { | ||
291 | rc = ecryptfs_truncate(file->f_path.dentry, | 294 | rc = ecryptfs_truncate(file->f_path.dentry, |
292 | end_of_prev_pg_pos); | 295 | prev_page_end_size); |
293 | if (rc) { | 296 | if (rc) { |
294 | printk(KERN_ERR "Error on attempt to " | 297 | printk(KERN_ERR "Error on attempt to " |
295 | "truncate to (higher) offset [%lld];" | 298 | "truncate to (higher) offset [%lld];" |
296 | " rc = [%d]\n", end_of_prev_pg_pos, rc); | 299 | " rc = [%d]\n", prev_page_end_size, rc); |
297 | goto out; | 300 | goto out; |
298 | } | 301 | } |
299 | } | 302 | } |
300 | if (end_of_prev_pg_pos + 1 > i_size_read(page->mapping->host)) | 303 | } |
301 | zero_user_page(page, 0, PAGE_CACHE_SIZE, KM_USER0); | 304 | /* |
305 | * Writing to a new page, and creating a small hole from start of page? | ||
306 | * Zero it out. | ||
307 | */ | ||
308 | if ((i_size_read(page->mapping->host) == prev_page_end_size) && | ||
309 | (from != 0)) { | ||
310 | zero_user_page(page, 0, PAGE_CACHE_SIZE, KM_USER0); | ||
302 | } | 311 | } |
303 | out: | 312 | out: |
304 | return rc; | 313 | return rc; |