diff options
author | Michael Halcrow <mhalcrow@us.ibm.com> | 2007-10-16 04:28:11 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-16 12:43:12 -0400 |
commit | bf12be1cc851cface331b0e74713a6bb1cb046b0 (patch) | |
tree | c20afee72af830fce2bf8255d63aed59a6db3c4e /fs | |
parent | 2ed92554abc5c40d4450f9869c9565a1919a9242 (diff) |
eCryptfs: convert mmap functions to use persistent file
Convert readpage, prepare_write, and commit_write to use read_write.c
routines. Remove sync_page; I cannot think of a good reason for implementing
that in eCryptfs.
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>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ecryptfs/mmap.c | 199 |
1 files changed, 103 insertions, 96 deletions
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index 60e635eddc77..9bc707df3b60 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c | |||
@@ -267,9 +267,78 @@ static void set_header_info(char *page_virt, | |||
267 | } | 267 | } |
268 | 268 | ||
269 | /** | 269 | /** |
270 | * ecryptfs_copy_up_encrypted_with_header | ||
271 | * @page: Sort of a ``virtual'' representation of the encrypted lower | ||
272 | * file. The actual lower file does not have the metadata in | ||
273 | * the header. This is locked. | ||
274 | * @crypt_stat: The eCryptfs inode's cryptographic context | ||
275 | * | ||
276 | * The ``view'' is the version of the file that userspace winds up | ||
277 | * seeing, with the header information inserted. | ||
278 | */ | ||
279 | static int | ||
280 | ecryptfs_copy_up_encrypted_with_header(struct page *page, | ||
281 | struct ecryptfs_crypt_stat *crypt_stat) | ||
282 | { | ||
283 | loff_t extent_num_in_page = 0; | ||
284 | loff_t num_extents_per_page = (PAGE_CACHE_SIZE | ||
285 | / crypt_stat->extent_size); | ||
286 | int rc = 0; | ||
287 | |||
288 | while (extent_num_in_page < num_extents_per_page) { | ||
289 | loff_t view_extent_num = ((page->index * num_extents_per_page) | ||
290 | + extent_num_in_page); | ||
291 | |||
292 | if (view_extent_num < crypt_stat->num_header_extents_at_front) { | ||
293 | /* This is a header extent */ | ||
294 | char *page_virt; | ||
295 | |||
296 | page_virt = kmap_atomic(page, KM_USER0); | ||
297 | memset(page_virt, 0, PAGE_CACHE_SIZE); | ||
298 | /* TODO: Support more than one header extent */ | ||
299 | if (view_extent_num == 0) { | ||
300 | rc = ecryptfs_read_xattr_region( | ||
301 | page_virt, page->mapping->host); | ||
302 | set_header_info(page_virt, crypt_stat); | ||
303 | } | ||
304 | kunmap_atomic(page_virt, KM_USER0); | ||
305 | flush_dcache_page(page); | ||
306 | if (rc) { | ||
307 | ClearPageUptodate(page); | ||
308 | printk(KERN_ERR "%s: Error reading xattr " | ||
309 | "region; rc = [%d]\n", __FUNCTION__, rc); | ||
310 | goto out; | ||
311 | } | ||
312 | SetPageUptodate(page); | ||
313 | } else { | ||
314 | /* This is an encrypted data extent */ | ||
315 | loff_t lower_offset = | ||
316 | ((view_extent_num - | ||
317 | crypt_stat->num_header_extents_at_front) | ||
318 | * crypt_stat->extent_size); | ||
319 | |||
320 | rc = ecryptfs_read_lower_page_segment( | ||
321 | page, (lower_offset >> PAGE_CACHE_SHIFT), | ||
322 | (lower_offset & ~PAGE_CACHE_MASK), | ||
323 | crypt_stat->extent_size, page->mapping->host); | ||
324 | if (rc) { | ||
325 | printk(KERN_ERR "%s: Error attempting to read " | ||
326 | "extent at offset [%lld] in the lower " | ||
327 | "file; rc = [%d]\n", __FUNCTION__, | ||
328 | lower_offset, rc); | ||
329 | goto out; | ||
330 | } | ||
331 | } | ||
332 | extent_num_in_page++; | ||
333 | } | ||
334 | out: | ||
335 | return rc; | ||
336 | } | ||
337 | |||
338 | /** | ||
270 | * ecryptfs_readpage | 339 | * ecryptfs_readpage |
271 | * @file: This is an ecryptfs file | 340 | * @file: An eCryptfs file |
272 | * @page: ecryptfs associated page to stick the read data into | 341 | * @page: Page from eCryptfs inode mapping into which to stick the read data |
273 | * | 342 | * |
274 | * Read in a page, decrypting if necessary. | 343 | * Read in a page, decrypting if necessary. |
275 | * | 344 | * |
@@ -277,59 +346,35 @@ static void set_header_info(char *page_virt, | |||
277 | */ | 346 | */ |
278 | static int ecryptfs_readpage(struct file *file, struct page *page) | 347 | static int ecryptfs_readpage(struct file *file, struct page *page) |
279 | { | 348 | { |
349 | struct ecryptfs_crypt_stat *crypt_stat = | ||
350 | &ecryptfs_inode_to_private(file->f_path.dentry->d_inode)->crypt_stat; | ||
280 | int rc = 0; | 351 | int rc = 0; |
281 | struct ecryptfs_crypt_stat *crypt_stat; | ||
282 | 352 | ||
283 | BUG_ON(!(file && file->f_path.dentry && file->f_path.dentry->d_inode)); | ||
284 | crypt_stat = &ecryptfs_inode_to_private(file->f_path.dentry->d_inode) | ||
285 | ->crypt_stat; | ||
286 | if (!crypt_stat | 353 | if (!crypt_stat |
287 | || !(crypt_stat->flags & ECRYPTFS_ENCRYPTED) | 354 | || !(crypt_stat->flags & ECRYPTFS_ENCRYPTED) |
288 | || (crypt_stat->flags & ECRYPTFS_NEW_FILE)) { | 355 | || (crypt_stat->flags & ECRYPTFS_NEW_FILE)) { |
289 | ecryptfs_printk(KERN_DEBUG, | 356 | ecryptfs_printk(KERN_DEBUG, |
290 | "Passing through unencrypted page\n"); | 357 | "Passing through unencrypted page\n"); |
291 | rc = ecryptfs_do_readpage(file, page, page->index); | 358 | rc = ecryptfs_read_lower_page_segment(page, page->index, 0, |
292 | if (rc) { | 359 | PAGE_CACHE_SIZE, |
293 | ecryptfs_printk(KERN_ERR, "Error reading page; rc = " | 360 | page->mapping->host); |
294 | "[%d]\n", rc); | ||
295 | goto out; | ||
296 | } | ||
297 | } else if (crypt_stat->flags & ECRYPTFS_VIEW_AS_ENCRYPTED) { | 361 | } else if (crypt_stat->flags & ECRYPTFS_VIEW_AS_ENCRYPTED) { |
298 | if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) { | 362 | if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) { |
299 | int num_pages_in_header_region = | 363 | rc = ecryptfs_copy_up_encrypted_with_header(page, |
300 | (crypt_stat->extent_size | 364 | crypt_stat); |
301 | / PAGE_CACHE_SIZE); | 365 | if (rc) { |
302 | 366 | printk(KERN_ERR "%s: Error attempting to copy " | |
303 | if (page->index < num_pages_in_header_region) { | 367 | "the encrypted content from the lower " |
304 | char *page_virt; | 368 | "file whilst inserting the metadata " |
305 | 369 | "from the xattr into the header; rc = " | |
306 | page_virt = kmap_atomic(page, KM_USER0); | 370 | "[%d]\n", __FUNCTION__, rc); |
307 | memset(page_virt, 0, PAGE_CACHE_SIZE); | 371 | goto out; |
308 | if (page->index == 0) { | ||
309 | rc = ecryptfs_read_xattr_region( | ||
310 | page_virt, page->mapping->host); | ||
311 | set_header_info(page_virt, crypt_stat); | ||
312 | } | ||
313 | kunmap_atomic(page_virt, KM_USER0); | ||
314 | flush_dcache_page(page); | ||
315 | if (rc) { | ||
316 | printk(KERN_ERR "Error reading xattr " | ||
317 | "region\n"); | ||
318 | goto out; | ||
319 | } | ||
320 | } else { | ||
321 | rc = ecryptfs_do_readpage( | ||
322 | file, page, | ||
323 | (page->index | ||
324 | - num_pages_in_header_region)); | ||
325 | if (rc) { | ||
326 | printk(KERN_ERR "Error reading page; " | ||
327 | "rc = [%d]\n", rc); | ||
328 | goto out; | ||
329 | } | ||
330 | } | 372 | } |
373 | |||
331 | } else { | 374 | } else { |
332 | rc = ecryptfs_do_readpage(file, page, page->index); | 375 | rc = ecryptfs_read_lower_page_segment( |
376 | page, page->index, 0, PAGE_CACHE_SIZE, | ||
377 | page->mapping->host); | ||
333 | if (rc) { | 378 | if (rc) { |
334 | printk(KERN_ERR "Error reading page; rc = " | 379 | printk(KERN_ERR "Error reading page; rc = " |
335 | "[%d]\n", rc); | 380 | "[%d]\n", rc); |
@@ -344,10 +389,7 @@ static int ecryptfs_readpage(struct file *file, struct page *page) | |||
344 | goto out; | 389 | goto out; |
345 | } | 390 | } |
346 | } | 391 | } |
347 | SetPageUptodate(page); | ||
348 | out: | 392 | out: |
349 | if (rc) | ||
350 | ClearPageUptodate(page); | ||
351 | ecryptfs_printk(KERN_DEBUG, "Unlocking page with index = [0x%.16x]\n", | 393 | ecryptfs_printk(KERN_DEBUG, "Unlocking page with index = [0x%.16x]\n", |
352 | page->index); | 394 | page->index); |
353 | unlock_page(page); | 395 | unlock_page(page); |
@@ -403,9 +445,12 @@ static int ecryptfs_prepare_write(struct file *file, struct page *page, | |||
403 | goto out; /* If we are writing a full page, it will be | 445 | goto out; /* If we are writing a full page, it will be |
404 | up to date. */ | 446 | up to date. */ |
405 | if (!PageUptodate(page)) | 447 | if (!PageUptodate(page)) |
406 | rc = ecryptfs_do_readpage(file, page, page->index); | 448 | rc = ecryptfs_read_lower_page_segment(page, page->index, 0, |
449 | PAGE_CACHE_SIZE, | ||
450 | page->mapping->host); | ||
407 | if (page->index != 0) { | 451 | if (page->index != 0) { |
408 | loff_t end_of_prev_pg_pos = page_offset(page) - 1; | 452 | loff_t end_of_prev_pg_pos = |
453 | (((loff_t)page->index << PAGE_CACHE_SHIFT) - 1); | ||
409 | 454 | ||
410 | if (end_of_prev_pg_pos > i_size_read(page->mapping->host)) { | 455 | if (end_of_prev_pg_pos > i_size_read(page->mapping->host)) { |
411 | rc = ecryptfs_truncate(file->f_path.dentry, | 456 | rc = ecryptfs_truncate(file->f_path.dentry, |
@@ -633,18 +678,11 @@ static int ecryptfs_commit_write(struct file *file, struct page *page, | |||
633 | unsigned from, unsigned to) | 678 | unsigned from, unsigned to) |
634 | { | 679 | { |
635 | loff_t pos; | 680 | loff_t pos; |
636 | struct inode *inode; | 681 | struct inode *ecryptfs_inode = page->mapping->host; |
637 | struct inode *lower_inode; | 682 | struct ecryptfs_crypt_stat *crypt_stat = |
638 | struct file *lower_file; | 683 | &ecryptfs_inode_to_private(file->f_path.dentry->d_inode)->crypt_stat; |
639 | struct ecryptfs_crypt_stat *crypt_stat; | ||
640 | int rc; | 684 | int rc; |
641 | 685 | ||
642 | inode = page->mapping->host; | ||
643 | lower_inode = ecryptfs_inode_to_lower(inode); | ||
644 | lower_file = ecryptfs_file_to_lower(file); | ||
645 | mutex_lock(&lower_inode->i_mutex); | ||
646 | crypt_stat = &ecryptfs_inode_to_private(file->f_path.dentry->d_inode) | ||
647 | ->crypt_stat; | ||
648 | if (crypt_stat->flags & ECRYPTFS_NEW_FILE) { | 686 | if (crypt_stat->flags & ECRYPTFS_NEW_FILE) { |
649 | ecryptfs_printk(KERN_DEBUG, "ECRYPTFS_NEW_FILE flag set in " | 687 | ecryptfs_printk(KERN_DEBUG, "ECRYPTFS_NEW_FILE flag set in " |
650 | "crypt_stat at memory location [%p]\n", crypt_stat); | 688 | "crypt_stat at memory location [%p]\n", crypt_stat); |
@@ -654,6 +692,7 @@ static int ecryptfs_commit_write(struct file *file, struct page *page, | |||
654 | ecryptfs_printk(KERN_DEBUG, "Calling fill_zeros_to_end_of_page" | 692 | ecryptfs_printk(KERN_DEBUG, "Calling fill_zeros_to_end_of_page" |
655 | "(page w/ index = [0x%.16x], to = [%d])\n", page->index, | 693 | "(page w/ index = [0x%.16x], to = [%d])\n", page->index, |
656 | to); | 694 | to); |
695 | /* Fills in zeros if 'to' goes beyond inode size */ | ||
657 | rc = fill_zeros_to_end_of_page(page, to); | 696 | rc = fill_zeros_to_end_of_page(page, to); |
658 | if (rc) { | 697 | if (rc) { |
659 | ecryptfs_printk(KERN_WARNING, "Error attempting to fill " | 698 | ecryptfs_printk(KERN_WARNING, "Error attempting to fill " |
@@ -667,25 +706,17 @@ static int ecryptfs_commit_write(struct file *file, struct page *page, | |||
667 | "index [0x%.16x])\n", page->index); | 706 | "index [0x%.16x])\n", page->index); |
668 | goto out; | 707 | goto out; |
669 | } | 708 | } |
670 | inode->i_blocks = lower_inode->i_blocks; | 709 | pos = (page->index << PAGE_CACHE_SHIFT) + to; |
671 | pos = page_offset(page) + to; | 710 | if (pos > i_size_read(ecryptfs_inode)) { |
672 | if (pos > i_size_read(inode)) { | 711 | i_size_write(ecryptfs_inode, pos); |
673 | i_size_write(inode, pos); | ||
674 | ecryptfs_printk(KERN_DEBUG, "Expanded file size to " | 712 | ecryptfs_printk(KERN_DEBUG, "Expanded file size to " |
675 | "[0x%.16x]\n", i_size_read(inode)); | 713 | "[0x%.16x]\n", i_size_read(ecryptfs_inode)); |
676 | } | 714 | } |
677 | rc = ecryptfs_write_inode_size_to_metadata(inode); | 715 | rc = ecryptfs_write_inode_size_to_metadata(ecryptfs_inode); |
678 | if (rc) | 716 | if (rc) |
679 | printk(KERN_ERR "Error writing inode size to metadata; " | 717 | printk(KERN_ERR "Error writing inode size to metadata; " |
680 | "rc = [%d]\n", rc); | 718 | "rc = [%d]\n", rc); |
681 | lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME; | ||
682 | mark_inode_dirty_sync(inode); | ||
683 | out: | 719 | out: |
684 | if (rc < 0) | ||
685 | ClearPageUptodate(page); | ||
686 | else | ||
687 | SetPageUptodate(page); | ||
688 | mutex_unlock(&lower_inode->i_mutex); | ||
689 | return rc; | 720 | return rc; |
690 | } | 721 | } |
691 | 722 | ||
@@ -751,34 +782,10 @@ static sector_t ecryptfs_bmap(struct address_space *mapping, sector_t block) | |||
751 | return rc; | 782 | return rc; |
752 | } | 783 | } |
753 | 784 | ||
754 | static void ecryptfs_sync_page(struct page *page) | ||
755 | { | ||
756 | struct inode *inode; | ||
757 | struct inode *lower_inode; | ||
758 | struct page *lower_page; | ||
759 | |||
760 | inode = page->mapping->host; | ||
761 | lower_inode = ecryptfs_inode_to_lower(inode); | ||
762 | /* NOTE: Recently swapped with grab_cache_page(), since | ||
763 | * sync_page() just makes sure that pending I/O gets done. */ | ||
764 | lower_page = find_lock_page(lower_inode->i_mapping, page->index); | ||
765 | if (!lower_page) { | ||
766 | ecryptfs_printk(KERN_DEBUG, "find_lock_page failed\n"); | ||
767 | return; | ||
768 | } | ||
769 | if (lower_page->mapping->a_ops->sync_page) | ||
770 | lower_page->mapping->a_ops->sync_page(lower_page); | ||
771 | ecryptfs_printk(KERN_DEBUG, "Unlocking page with index = [0x%.16x]\n", | ||
772 | lower_page->index); | ||
773 | unlock_page(lower_page); | ||
774 | page_cache_release(lower_page); | ||
775 | } | ||
776 | |||
777 | struct address_space_operations ecryptfs_aops = { | 785 | struct address_space_operations ecryptfs_aops = { |
778 | .writepage = ecryptfs_writepage, | 786 | .writepage = ecryptfs_writepage, |
779 | .readpage = ecryptfs_readpage, | 787 | .readpage = ecryptfs_readpage, |
780 | .prepare_write = ecryptfs_prepare_write, | 788 | .prepare_write = ecryptfs_prepare_write, |
781 | .commit_write = ecryptfs_commit_write, | 789 | .commit_write = ecryptfs_commit_write, |
782 | .bmap = ecryptfs_bmap, | 790 | .bmap = ecryptfs_bmap, |
783 | .sync_page = ecryptfs_sync_page, | ||
784 | }; | 791 | }; |