diff options
author | Michael Halcrow <mhalcrow@us.ibm.com> | 2007-02-28 23:12:16 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-03-01 17:53:37 -0500 |
commit | ae73fc093a8cae4d92e22ab8b635e3590e80785d (patch) | |
tree | d593f88dd5ab406bc785b7acaf137d7fb67d07b2 /fs/ecryptfs/mmap.c | |
parent | 05fb6bf0b29552b64dc86f405a484de2514e0ac2 (diff) |
[PATCH] eCryptfs: resolve lower page unlocking problem
eCryptfs lower file handling code has several issues:
- Retval from prepare_write()/commit_write() wasn't checked to equality
to AOP_TRUNCATED_PAGE.
- In some places page wasn't unmapped and unlocked after error.
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/ecryptfs/mmap.c')
-rw-r--r-- | fs/ecryptfs/mmap.c | 28 |
1 files changed, 23 insertions, 5 deletions
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index 3a6f65c3f14f..82bdbed658d7 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c | |||
@@ -422,9 +422,11 @@ out: | |||
422 | return rc; | 422 | return rc; |
423 | } | 423 | } |
424 | 424 | ||
425 | static void ecryptfs_release_lower_page(struct page *lower_page) | 425 | static |
426 | void ecryptfs_release_lower_page(struct page *lower_page, int page_locked) | ||
426 | { | 427 | { |
427 | unlock_page(lower_page); | 428 | if (page_locked) |
429 | unlock_page(lower_page); | ||
428 | page_cache_release(lower_page); | 430 | page_cache_release(lower_page); |
429 | } | 431 | } |
430 | 432 | ||
@@ -454,6 +456,13 @@ static int ecryptfs_write_inode_size_to_header(struct file *lower_file, | |||
454 | } | 456 | } |
455 | lower_a_ops = lower_inode->i_mapping->a_ops; | 457 | lower_a_ops = lower_inode->i_mapping->a_ops; |
456 | rc = lower_a_ops->prepare_write(lower_file, header_page, 0, 8); | 458 | rc = lower_a_ops->prepare_write(lower_file, header_page, 0, 8); |
459 | if (rc) { | ||
460 | if (rc == AOP_TRUNCATED_PAGE) | ||
461 | ecryptfs_release_lower_page(header_page, 0); | ||
462 | else | ||
463 | ecryptfs_release_lower_page(header_page, 1); | ||
464 | goto out; | ||
465 | } | ||
457 | file_size = (u64)i_size_read(inode); | 466 | file_size = (u64)i_size_read(inode); |
458 | ecryptfs_printk(KERN_DEBUG, "Writing size: [0x%.16x]\n", file_size); | 467 | ecryptfs_printk(KERN_DEBUG, "Writing size: [0x%.16x]\n", file_size); |
459 | file_size = cpu_to_be64(file_size); | 468 | file_size = cpu_to_be64(file_size); |
@@ -465,7 +474,10 @@ static int ecryptfs_write_inode_size_to_header(struct file *lower_file, | |||
465 | if (rc < 0) | 474 | if (rc < 0) |
466 | ecryptfs_printk(KERN_ERR, "Error commiting header page " | 475 | ecryptfs_printk(KERN_ERR, "Error commiting header page " |
467 | "write\n"); | 476 | "write\n"); |
468 | ecryptfs_release_lower_page(header_page); | 477 | if (rc == AOP_TRUNCATED_PAGE) |
478 | ecryptfs_release_lower_page(header_page, 0); | ||
479 | else | ||
480 | ecryptfs_release_lower_page(header_page, 1); | ||
469 | lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME; | 481 | lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME; |
470 | mark_inode_dirty_sync(inode); | 482 | mark_inode_dirty_sync(inode); |
471 | out: | 483 | out: |
@@ -572,7 +584,10 @@ int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode, | |||
572 | } | 584 | } |
573 | out: | 585 | out: |
574 | if (rc && (*lower_page)) { | 586 | if (rc && (*lower_page)) { |
575 | ecryptfs_release_lower_page(*lower_page); | 587 | if (rc == AOP_TRUNCATED_PAGE) |
588 | ecryptfs_release_lower_page(*lower_page, 0); | ||
589 | else | ||
590 | ecryptfs_release_lower_page(*lower_page, 1); | ||
576 | (*lower_page) = NULL; | 591 | (*lower_page) = NULL; |
577 | } | 592 | } |
578 | return rc; | 593 | return rc; |
@@ -588,16 +603,19 @@ ecryptfs_commit_lower_page(struct page *lower_page, struct inode *lower_inode, | |||
588 | struct file *lower_file, int byte_offset, | 603 | struct file *lower_file, int byte_offset, |
589 | int region_size) | 604 | int region_size) |
590 | { | 605 | { |
606 | int page_locked = 1; | ||
591 | int rc = 0; | 607 | int rc = 0; |
592 | 608 | ||
593 | rc = lower_inode->i_mapping->a_ops->commit_write( | 609 | rc = lower_inode->i_mapping->a_ops->commit_write( |
594 | lower_file, lower_page, byte_offset, region_size); | 610 | lower_file, lower_page, byte_offset, region_size); |
611 | if (rc == AOP_TRUNCATED_PAGE) | ||
612 | page_locked = 0; | ||
595 | if (rc < 0) { | 613 | if (rc < 0) { |
596 | ecryptfs_printk(KERN_ERR, | 614 | ecryptfs_printk(KERN_ERR, |
597 | "Error committing write; rc = [%d]\n", rc); | 615 | "Error committing write; rc = [%d]\n", rc); |
598 | } else | 616 | } else |
599 | rc = 0; | 617 | rc = 0; |
600 | ecryptfs_release_lower_page(lower_page); | 618 | ecryptfs_release_lower_page(lower_page, page_locked); |
601 | return rc; | 619 | return rc; |
602 | } | 620 | } |
603 | 621 | ||