diff options
Diffstat (limited to 'fs/ecryptfs/mmap.c')
-rw-r--r-- | fs/ecryptfs/mmap.c | 44 |
1 files changed, 33 insertions, 11 deletions
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index 3a6f65c3f14f..b731b09499cb 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c | |||
@@ -238,7 +238,6 @@ int ecryptfs_do_readpage(struct file *file, struct page *page, | |||
238 | lower_page_data = kmap_atomic(lower_page, KM_USER1); | 238 | lower_page_data = kmap_atomic(lower_page, KM_USER1); |
239 | memcpy(page_data, lower_page_data, PAGE_CACHE_SIZE); | 239 | memcpy(page_data, lower_page_data, PAGE_CACHE_SIZE); |
240 | kunmap_atomic(lower_page_data, KM_USER1); | 240 | kunmap_atomic(lower_page_data, KM_USER1); |
241 | flush_dcache_page(lower_page); | ||
242 | kunmap_atomic(page_data, KM_USER0); | 241 | kunmap_atomic(page_data, KM_USER0); |
243 | flush_dcache_page(page); | 242 | flush_dcache_page(page); |
244 | rc = 0; | 243 | rc = 0; |
@@ -422,9 +421,11 @@ out: | |||
422 | return rc; | 421 | return rc; |
423 | } | 422 | } |
424 | 423 | ||
425 | static void ecryptfs_release_lower_page(struct page *lower_page) | 424 | static |
425 | void ecryptfs_release_lower_page(struct page *lower_page, int page_locked) | ||
426 | { | 426 | { |
427 | unlock_page(lower_page); | 427 | if (page_locked) |
428 | unlock_page(lower_page); | ||
428 | page_cache_release(lower_page); | 429 | page_cache_release(lower_page); |
429 | } | 430 | } |
430 | 431 | ||
@@ -445,6 +446,7 @@ static int ecryptfs_write_inode_size_to_header(struct file *lower_file, | |||
445 | const struct address_space_operations *lower_a_ops; | 446 | const struct address_space_operations *lower_a_ops; |
446 | u64 file_size; | 447 | u64 file_size; |
447 | 448 | ||
449 | retry: | ||
448 | header_page = grab_cache_page(lower_inode->i_mapping, 0); | 450 | header_page = grab_cache_page(lower_inode->i_mapping, 0); |
449 | if (!header_page) { | 451 | if (!header_page) { |
450 | ecryptfs_printk(KERN_ERR, "grab_cache_page for " | 452 | ecryptfs_printk(KERN_ERR, "grab_cache_page for " |
@@ -454,6 +456,14 @@ 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 | goto retry; | ||
463 | } else | ||
464 | ecryptfs_release_lower_page(header_page, 1); | ||
465 | goto out; | ||
466 | } | ||
457 | file_size = (u64)i_size_read(inode); | 467 | file_size = (u64)i_size_read(inode); |
458 | ecryptfs_printk(KERN_DEBUG, "Writing size: [0x%.16x]\n", file_size); | 468 | ecryptfs_printk(KERN_DEBUG, "Writing size: [0x%.16x]\n", file_size); |
459 | file_size = cpu_to_be64(file_size); | 469 | file_size = cpu_to_be64(file_size); |
@@ -465,7 +475,11 @@ static int ecryptfs_write_inode_size_to_header(struct file *lower_file, | |||
465 | if (rc < 0) | 475 | if (rc < 0) |
466 | ecryptfs_printk(KERN_ERR, "Error commiting header page " | 476 | ecryptfs_printk(KERN_ERR, "Error commiting header page " |
467 | "write\n"); | 477 | "write\n"); |
468 | ecryptfs_release_lower_page(header_page); | 478 | if (rc == AOP_TRUNCATED_PAGE) { |
479 | ecryptfs_release_lower_page(header_page, 0); | ||
480 | goto retry; | ||
481 | } else | ||
482 | ecryptfs_release_lower_page(header_page, 1); | ||
469 | lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME; | 483 | lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME; |
470 | mark_inode_dirty_sync(inode); | 484 | mark_inode_dirty_sync(inode); |
471 | out: | 485 | out: |
@@ -491,7 +505,8 @@ static int ecryptfs_write_inode_size_to_xattr(struct inode *lower_inode, | |||
491 | goto out; | 505 | goto out; |
492 | } | 506 | } |
493 | lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry); | 507 | lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry); |
494 | if (!lower_dentry->d_inode->i_op->getxattr) { | 508 | if (!lower_dentry->d_inode->i_op->getxattr || |
509 | !lower_dentry->d_inode->i_op->setxattr) { | ||
495 | printk(KERN_WARNING | 510 | printk(KERN_WARNING |
496 | "No support for setting xattr in lower filesystem\n"); | 511 | "No support for setting xattr in lower filesystem\n"); |
497 | rc = -ENOSYS; | 512 | rc = -ENOSYS; |
@@ -553,6 +568,7 @@ int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode, | |||
553 | { | 568 | { |
554 | int rc = 0; | 569 | int rc = 0; |
555 | 570 | ||
571 | retry: | ||
556 | *lower_page = grab_cache_page(lower_inode->i_mapping, lower_page_index); | 572 | *lower_page = grab_cache_page(lower_inode->i_mapping, lower_page_index); |
557 | if (!(*lower_page)) { | 573 | if (!(*lower_page)) { |
558 | rc = -EINVAL; | 574 | rc = -EINVAL; |
@@ -566,15 +582,18 @@ int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode, | |||
566 | byte_offset, | 582 | byte_offset, |
567 | region_bytes); | 583 | region_bytes); |
568 | if (rc) { | 584 | if (rc) { |
569 | ecryptfs_printk(KERN_ERR, "prepare_write for " | 585 | if (rc == AOP_TRUNCATED_PAGE) { |
586 | ecryptfs_release_lower_page(*lower_page, 0); | ||
587 | goto retry; | ||
588 | } else { | ||
589 | ecryptfs_printk(KERN_ERR, "prepare_write for " | ||
570 | "lower_page_index = [0x%.16x] failed; rc = " | 590 | "lower_page_index = [0x%.16x] failed; rc = " |
571 | "[%d]\n", lower_page_index, rc); | 591 | "[%d]\n", lower_page_index, rc); |
592 | ecryptfs_release_lower_page(*lower_page, 1); | ||
593 | (*lower_page) = NULL; | ||
594 | } | ||
572 | } | 595 | } |
573 | out: | 596 | out: |
574 | if (rc && (*lower_page)) { | ||
575 | ecryptfs_release_lower_page(*lower_page); | ||
576 | (*lower_page) = NULL; | ||
577 | } | ||
578 | return rc; | 597 | return rc; |
579 | } | 598 | } |
580 | 599 | ||
@@ -588,16 +607,19 @@ ecryptfs_commit_lower_page(struct page *lower_page, struct inode *lower_inode, | |||
588 | struct file *lower_file, int byte_offset, | 607 | struct file *lower_file, int byte_offset, |
589 | int region_size) | 608 | int region_size) |
590 | { | 609 | { |
610 | int page_locked = 1; | ||
591 | int rc = 0; | 611 | int rc = 0; |
592 | 612 | ||
593 | rc = lower_inode->i_mapping->a_ops->commit_write( | 613 | rc = lower_inode->i_mapping->a_ops->commit_write( |
594 | lower_file, lower_page, byte_offset, region_size); | 614 | lower_file, lower_page, byte_offset, region_size); |
615 | if (rc == AOP_TRUNCATED_PAGE) | ||
616 | page_locked = 0; | ||
595 | if (rc < 0) { | 617 | if (rc < 0) { |
596 | ecryptfs_printk(KERN_ERR, | 618 | ecryptfs_printk(KERN_ERR, |
597 | "Error committing write; rc = [%d]\n", rc); | 619 | "Error committing write; rc = [%d]\n", rc); |
598 | } else | 620 | } else |
599 | rc = 0; | 621 | rc = 0; |
600 | ecryptfs_release_lower_page(lower_page); | 622 | ecryptfs_release_lower_page(lower_page, page_locked); |
601 | return rc; | 623 | return rc; |
602 | } | 624 | } |
603 | 625 | ||