aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Halcrow <mhalcrow@us.ibm.com>2007-05-23 16:58:15 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-23 23:14:15 -0400
commit53a2731f9310a66beaf55677229ab067c85ce4fa (patch)
tree6166f49b9205541a96696f648217c606cc9d9a0a
parent4acb3e2f97f41cf9b53182b494384467d3ceb304 (diff)
eCryptfs: delay writing 0's after llseek until write
Delay writing 0's out in eCryptfs after a seek past the end of the file until data is actually written. http://www.opengroup.org/onlinepubs/009695399/functions/lseek.html ``The lseek() function shall not, by itself, extend the size of a file.'' Without this fix, applications that lseek() past the end of the file without writing will experience unexpected behavior. Signed-off-by: Michael Halcrow <mhalcrow@us.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/ecryptfs/file.c59
-rw-r--r--fs/ecryptfs/mmap.c38
2 files changed, 36 insertions, 61 deletions
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index 9881b5c5de59..59288d817078 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -33,63 +33,6 @@
33#include "ecryptfs_kernel.h" 33#include "ecryptfs_kernel.h"
34 34
35/** 35/**
36 * ecryptfs_llseek
37 * @file: File we are seeking in
38 * @offset: The offset to seek to
39 * @origin: 2 - offset from i_size; 1 - offset from f_pos
40 *
41 * Returns the position we have seeked to, or negative on error
42 */
43static loff_t ecryptfs_llseek(struct file *file, loff_t offset, int origin)
44{
45 loff_t rv;
46 loff_t new_end_pos;
47 int rc;
48 int expanding_file = 0;
49 struct inode *inode = file->f_mapping->host;
50
51 /* If our offset is past the end of our file, we're going to
52 * need to grow it so we have a valid length of 0's */
53 new_end_pos = offset;
54 switch (origin) {
55 case 2:
56 new_end_pos += i_size_read(inode);
57 expanding_file = 1;
58 break;
59 case 1:
60 new_end_pos += file->f_pos;
61 if (new_end_pos > i_size_read(inode)) {
62 ecryptfs_printk(KERN_DEBUG, "new_end_pos(=[0x%.16x]) "
63 "> i_size_read(inode)(=[0x%.16x])\n",
64 new_end_pos, i_size_read(inode));
65 expanding_file = 1;
66 }
67 break;
68 default:
69 if (new_end_pos > i_size_read(inode)) {
70 ecryptfs_printk(KERN_DEBUG, "new_end_pos(=[0x%.16x]) "
71 "> i_size_read(inode)(=[0x%.16x])\n",
72 new_end_pos, i_size_read(inode));
73 expanding_file = 1;
74 }
75 }
76 ecryptfs_printk(KERN_DEBUG, "new_end_pos = [0x%.16x]\n", new_end_pos);
77 if (expanding_file) {
78 rc = ecryptfs_truncate(file->f_path.dentry, new_end_pos);
79 if (rc) {
80 rv = rc;
81 ecryptfs_printk(KERN_ERR, "Error on attempt to "
82 "truncate to (higher) offset [0x%.16x];"
83 " rc = [%d]\n", new_end_pos, rc);
84 goto out;
85 }
86 }
87 rv = generic_file_llseek(file, offset, origin);
88out:
89 return rv;
90}
91
92/**
93 * ecryptfs_read_update_atime 36 * ecryptfs_read_update_atime
94 * 37 *
95 * generic_file_read updates the atime of upper layer inode. But, it 38 * generic_file_read updates the atime of upper layer inode. But, it
@@ -425,7 +368,7 @@ const struct file_operations ecryptfs_dir_fops = {
425}; 368};
426 369
427const struct file_operations ecryptfs_main_fops = { 370const struct file_operations ecryptfs_main_fops = {
428 .llseek = ecryptfs_llseek, 371 .llseek = generic_file_llseek,
429 .read = do_sync_read, 372 .read = do_sync_read,
430 .aio_read = ecryptfs_read_update_atime, 373 .aio_read = ecryptfs_read_update_atime,
431 .write = do_sync_write, 374 .write = do_sync_write,
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index 88ea6697908f..55cec98a84e7 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -376,9 +376,31 @@ out:
376 return 0; 376 return 0;
377} 377}
378 378
379/**
380 * eCryptfs does not currently support holes. When writing after a
381 * seek past the end of the file, eCryptfs fills in 0's through to the
382 * current location. The code to fill in the 0's to all the
383 * intermediate pages calls ecryptfs_prepare_write_no_truncate().
384 */
385static int
386ecryptfs_prepare_write_no_truncate(struct file *file, struct page *page,
387 unsigned from, unsigned to)
388{
389 int rc = 0;
390
391 if (from == 0 && to == PAGE_CACHE_SIZE)
392 goto out; /* If we are writing a full page, it will be
393 up to date. */
394 if (!PageUptodate(page))
395 rc = ecryptfs_do_readpage(file, page, page->index);
396out:
397 return rc;
398}
399
379static int ecryptfs_prepare_write(struct file *file, struct page *page, 400static int ecryptfs_prepare_write(struct file *file, struct page *page,
380 unsigned from, unsigned to) 401 unsigned from, unsigned to)
381{ 402{
403 loff_t pos;
382 int rc = 0; 404 int rc = 0;
383 405
384 if (from == 0 && to == PAGE_CACHE_SIZE) 406 if (from == 0 && to == PAGE_CACHE_SIZE)
@@ -386,6 +408,16 @@ static int ecryptfs_prepare_write(struct file *file, struct page *page,
386 up to date. */ 408 up to date. */
387 if (!PageUptodate(page)) 409 if (!PageUptodate(page))
388 rc = ecryptfs_do_readpage(file, page, page->index); 410 rc = ecryptfs_do_readpage(file, page, page->index);
411 pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
412 if (pos > i_size_read(page->mapping->host)) {
413 rc = ecryptfs_truncate(file->f_path.dentry, pos);
414 if (rc) {
415 printk(KERN_ERR "Error on attempt to "
416 "truncate to (higher) offset [%lld];"
417 " rc = [%d]\n", pos, rc);
418 goto out;
419 }
420 }
389out: 421out:
390 return rc; 422 return rc;
391} 423}
@@ -744,10 +776,10 @@ int write_zeros(struct file *file, pgoff_t index, int start, int num_zeros)
744 rc = PTR_ERR(tmp_page); 776 rc = PTR_ERR(tmp_page);
745 goto out; 777 goto out;
746 } 778 }
747 rc = ecryptfs_prepare_write(file, tmp_page, start, start + num_zeros); 779 if ((rc = ecryptfs_prepare_write_no_truncate(file, tmp_page, start,
748 if (rc) { 780 (start + num_zeros)))) {
749 ecryptfs_printk(KERN_ERR, "Error preparing to write zero's " 781 ecryptfs_printk(KERN_ERR, "Error preparing to write zero's "
750 "to remainder of page at index [0x%.16x]\n", 782 "to page at index [0x%.16x]\n",
751 index); 783 index);
752 page_cache_release(tmp_page); 784 page_cache_release(tmp_page);
753 goto out; 785 goto out;