From 53a2731f9310a66beaf55677229ab067c85ce4fa Mon Sep 17 00:00:00 2001 From: Michael Halcrow Date: Wed, 23 May 2007 13:58:15 -0700 Subject: 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 Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ecryptfs/mmap.c | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) (limited to 'fs/ecryptfs/mmap.c') diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index 88ea6697908..55cec98a84e 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c @@ -376,9 +376,31 @@ out: return 0; } +/** + * eCryptfs does not currently support holes. When writing after a + * seek past the end of the file, eCryptfs fills in 0's through to the + * current location. The code to fill in the 0's to all the + * intermediate pages calls ecryptfs_prepare_write_no_truncate(). + */ +static int +ecryptfs_prepare_write_no_truncate(struct file *file, struct page *page, + unsigned from, unsigned to) +{ + int rc = 0; + + if (from == 0 && to == PAGE_CACHE_SIZE) + goto out; /* If we are writing a full page, it will be + up to date. */ + if (!PageUptodate(page)) + rc = ecryptfs_do_readpage(file, page, page->index); +out: + return rc; +} + static int ecryptfs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to) { + loff_t pos; int rc = 0; if (from == 0 && to == PAGE_CACHE_SIZE) @@ -386,6 +408,16 @@ static int ecryptfs_prepare_write(struct file *file, struct page *page, up to date. */ if (!PageUptodate(page)) rc = ecryptfs_do_readpage(file, page, page->index); + pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to; + if (pos > i_size_read(page->mapping->host)) { + rc = ecryptfs_truncate(file->f_path.dentry, pos); + if (rc) { + printk(KERN_ERR "Error on attempt to " + "truncate to (higher) offset [%lld];" + " rc = [%d]\n", pos, rc); + goto out; + } + } out: return rc; } @@ -744,10 +776,10 @@ int write_zeros(struct file *file, pgoff_t index, int start, int num_zeros) rc = PTR_ERR(tmp_page); goto out; } - rc = ecryptfs_prepare_write(file, tmp_page, start, start + num_zeros); - if (rc) { + if ((rc = ecryptfs_prepare_write_no_truncate(file, tmp_page, start, + (start + num_zeros)))) { ecryptfs_printk(KERN_ERR, "Error preparing to write zero's " - "to remainder of page at index [0x%.16x]\n", + "to page at index [0x%.16x]\n", index); page_cache_release(tmp_page); goto out; -- cgit v1.2.3