diff options
| author | Thieu Le <thieule@chromium.org> | 2011-03-08 19:26:03 -0500 |
|---|---|---|
| committer | Tyler Hicks <tyhicks@linux.vnet.ibm.com> | 2011-03-28 02:47:45 -0400 |
| commit | 57db4e8d73ef2b5e94a3f412108dff2576670a8a (patch) | |
| tree | ab6eae8e879cfa41cdb3309d8e6a52de14746ca4 /fs | |
| parent | fed8859b3ab94274c986cbdf7d27130e0545f02c (diff) | |
ecryptfs: modify write path to encrypt page in writepage
Change the write path to encrypt the data only when the page is written to
disk in ecryptfs_writepage. Previously, ecryptfs encrypts the page in
ecryptfs_write_end which means that if there are multiple write requests to
the same page, ecryptfs ends up re-encrypting that page over and over again.
This patch minimizes the number of encryptions needed.
Signed-off-by: Thieu Le <thieule@chromium.org>
[tyhicks: Changed NULL .drop_inode sop pointer to generic_drop_inode]
Signed-off-by: Tyler Hicks <tyhicks@linux.vnet.ibm.com>
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/ecryptfs/ecryptfs_kernel.h | 1 | ||||
| -rw-r--r-- | fs/ecryptfs/file.c | 9 | ||||
| -rw-r--r-- | fs/ecryptfs/main.c | 2 | ||||
| -rw-r--r-- | fs/ecryptfs/mmap.c | 41 | ||||
| -rw-r--r-- | fs/ecryptfs/read_write.c | 12 | ||||
| -rw-r--r-- | fs/ecryptfs/super.c | 3 |
6 files changed, 38 insertions, 30 deletions
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index 427478e29760..3ef5b0030231 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h | |||
| @@ -296,7 +296,6 @@ struct ecryptfs_inode_info { | |||
| 296 | struct inode vfs_inode; | 296 | struct inode vfs_inode; |
| 297 | struct inode *wii_inode; | 297 | struct inode *wii_inode; |
| 298 | struct file *lower_file; | 298 | struct file *lower_file; |
| 299 | struct mutex lower_file_mutex; | ||
| 300 | struct ecryptfs_crypt_stat crypt_stat; | 299 | struct ecryptfs_crypt_stat crypt_stat; |
| 301 | }; | 300 | }; |
| 302 | 301 | ||
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index 7d1050e254f9..cedc913d11ba 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c | |||
| @@ -273,7 +273,14 @@ static int ecryptfs_release(struct inode *inode, struct file *file) | |||
| 273 | static int | 273 | static int |
| 274 | ecryptfs_fsync(struct file *file, int datasync) | 274 | ecryptfs_fsync(struct file *file, int datasync) |
| 275 | { | 275 | { |
| 276 | return vfs_fsync(ecryptfs_file_to_lower(file), datasync); | 276 | int rc = 0; |
| 277 | |||
| 278 | rc = generic_file_fsync(file, datasync); | ||
| 279 | if (rc) | ||
| 280 | goto out; | ||
| 281 | rc = vfs_fsync(ecryptfs_file_to_lower(file), datasync); | ||
| 282 | out: | ||
| 283 | return rc; | ||
| 277 | } | 284 | } |
| 278 | 285 | ||
| 279 | static int ecryptfs_fasync(int fd, struct file *file, int flag) | 286 | static int ecryptfs_fasync(int fd, struct file *file, int flag) |
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index 758323a0f09a..63e412cf0fa1 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c | |||
| @@ -122,7 +122,6 @@ int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry) | |||
| 122 | ecryptfs_inode_to_private(ecryptfs_dentry->d_inode); | 122 | ecryptfs_inode_to_private(ecryptfs_dentry->d_inode); |
| 123 | int rc = 0; | 123 | int rc = 0; |
| 124 | 124 | ||
| 125 | mutex_lock(&inode_info->lower_file_mutex); | ||
| 126 | if (!inode_info->lower_file) { | 125 | if (!inode_info->lower_file) { |
| 127 | struct dentry *lower_dentry; | 126 | struct dentry *lower_dentry; |
| 128 | struct vfsmount *lower_mnt = | 127 | struct vfsmount *lower_mnt = |
| @@ -138,7 +137,6 @@ int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry) | |||
| 138 | inode_info->lower_file = NULL; | 137 | inode_info->lower_file = NULL; |
| 139 | } | 138 | } |
| 140 | } | 139 | } |
| 141 | mutex_unlock(&inode_info->lower_file_mutex); | ||
| 142 | return rc; | 140 | return rc; |
| 143 | } | 141 | } |
| 144 | 142 | ||
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index 519af27db059..5e150131eb9d 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c | |||
| @@ -62,6 +62,18 @@ static int ecryptfs_writepage(struct page *page, struct writeback_control *wbc) | |||
| 62 | { | 62 | { |
| 63 | int rc; | 63 | int rc; |
| 64 | 64 | ||
| 65 | /* | ||
| 66 | * Refuse to write the page out if we are called from reclaim context | ||
| 67 | * since our writepage() path may potentially allocate memory when | ||
| 68 | * calling into the lower fs vfs_write() which may in turn invoke | ||
| 69 | * us again. | ||
| 70 | */ | ||
| 71 | if (current->flags & PF_MEMALLOC) { | ||
| 72 | redirty_page_for_writepage(wbc, page); | ||
| 73 | rc = 0; | ||
| 74 | goto out; | ||
| 75 | } | ||
| 76 | |||
| 65 | rc = ecryptfs_encrypt_page(page); | 77 | rc = ecryptfs_encrypt_page(page); |
| 66 | if (rc) { | 78 | if (rc) { |
| 67 | ecryptfs_printk(KERN_WARNING, "Error encrypting " | 79 | ecryptfs_printk(KERN_WARNING, "Error encrypting " |
| @@ -70,8 +82,8 @@ static int ecryptfs_writepage(struct page *page, struct writeback_control *wbc) | |||
| 70 | goto out; | 82 | goto out; |
| 71 | } | 83 | } |
| 72 | SetPageUptodate(page); | 84 | SetPageUptodate(page); |
| 73 | unlock_page(page); | ||
| 74 | out: | 85 | out: |
| 86 | unlock_page(page); | ||
| 75 | return rc; | 87 | return rc; |
| 76 | } | 88 | } |
| 77 | 89 | ||
| @@ -481,6 +493,7 @@ static int ecryptfs_write_end(struct file *file, | |||
| 481 | struct ecryptfs_crypt_stat *crypt_stat = | 493 | struct ecryptfs_crypt_stat *crypt_stat = |
| 482 | &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; | 494 | &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; |
| 483 | int rc; | 495 | int rc; |
| 496 | int need_unlock_page = 1; | ||
| 484 | 497 | ||
| 485 | ecryptfs_printk(KERN_DEBUG, "Calling fill_zeros_to_end_of_page" | 498 | ecryptfs_printk(KERN_DEBUG, "Calling fill_zeros_to_end_of_page" |
| 486 | "(page w/ index = [0x%.16lx], to = [%d])\n", index, to); | 499 | "(page w/ index = [0x%.16lx], to = [%d])\n", index, to); |
| @@ -501,26 +514,26 @@ static int ecryptfs_write_end(struct file *file, | |||
| 501 | "zeros in page with index = [0x%.16lx]\n", index); | 514 | "zeros in page with index = [0x%.16lx]\n", index); |
| 502 | goto out; | 515 | goto out; |
| 503 | } | 516 | } |
| 504 | rc = ecryptfs_encrypt_page(page); | 517 | set_page_dirty(page); |
| 505 | if (rc) { | 518 | unlock_page(page); |
| 506 | ecryptfs_printk(KERN_WARNING, "Error encrypting page (upper " | 519 | need_unlock_page = 0; |
| 507 | "index [0x%.16lx])\n", index); | ||
| 508 | goto out; | ||
| 509 | } | ||
| 510 | if (pos + copied > i_size_read(ecryptfs_inode)) { | 520 | if (pos + copied > i_size_read(ecryptfs_inode)) { |
| 511 | i_size_write(ecryptfs_inode, pos + copied); | 521 | i_size_write(ecryptfs_inode, pos + copied); |
| 512 | ecryptfs_printk(KERN_DEBUG, "Expanded file size to " | 522 | ecryptfs_printk(KERN_DEBUG, "Expanded file size to " |
| 513 | "[0x%.16llx]\n", | 523 | "[0x%.16llx]\n", |
| 514 | (unsigned long long)i_size_read(ecryptfs_inode)); | 524 | (unsigned long long)i_size_read(ecryptfs_inode)); |
| 525 | balance_dirty_pages_ratelimited(mapping); | ||
| 526 | rc = ecryptfs_write_inode_size_to_metadata(ecryptfs_inode); | ||
| 527 | if (rc) { | ||
| 528 | printk(KERN_ERR "Error writing inode size to metadata; " | ||
| 529 | "rc = [%d]\n", rc); | ||
| 530 | goto out; | ||
| 531 | } | ||
| 515 | } | 532 | } |
| 516 | rc = ecryptfs_write_inode_size_to_metadata(ecryptfs_inode); | 533 | rc = copied; |
| 517 | if (rc) | ||
| 518 | printk(KERN_ERR "Error writing inode size to metadata; " | ||
| 519 | "rc = [%d]\n", rc); | ||
| 520 | else | ||
| 521 | rc = copied; | ||
| 522 | out: | 534 | out: |
| 523 | unlock_page(page); | 535 | if (need_unlock_page) |
| 536 | unlock_page(page); | ||
| 524 | page_cache_release(page); | 537 | page_cache_release(page); |
| 525 | return rc; | 538 | return rc; |
| 526 | } | 539 | } |
diff --git a/fs/ecryptfs/read_write.c b/fs/ecryptfs/read_write.c index db184ef15d3d..85d430963116 100644 --- a/fs/ecryptfs/read_write.c +++ b/fs/ecryptfs/read_write.c | |||
| @@ -44,15 +44,11 @@ int ecryptfs_write_lower(struct inode *ecryptfs_inode, char *data, | |||
| 44 | ssize_t rc; | 44 | ssize_t rc; |
| 45 | 45 | ||
| 46 | inode_info = ecryptfs_inode_to_private(ecryptfs_inode); | 46 | inode_info = ecryptfs_inode_to_private(ecryptfs_inode); |
| 47 | mutex_lock(&inode_info->lower_file_mutex); | ||
| 48 | BUG_ON(!inode_info->lower_file); | 47 | BUG_ON(!inode_info->lower_file); |
| 49 | inode_info->lower_file->f_pos = offset; | ||
| 50 | fs_save = get_fs(); | 48 | fs_save = get_fs(); |
| 51 | set_fs(get_ds()); | 49 | set_fs(get_ds()); |
| 52 | rc = vfs_write(inode_info->lower_file, data, size, | 50 | rc = vfs_write(inode_info->lower_file, data, size, &offset); |
| 53 | &inode_info->lower_file->f_pos); | ||
| 54 | set_fs(fs_save); | 51 | set_fs(fs_save); |
| 55 | mutex_unlock(&inode_info->lower_file_mutex); | ||
| 56 | mark_inode_dirty_sync(ecryptfs_inode); | 52 | mark_inode_dirty_sync(ecryptfs_inode); |
| 57 | return rc; | 53 | return rc; |
| 58 | } | 54 | } |
| @@ -234,15 +230,11 @@ int ecryptfs_read_lower(char *data, loff_t offset, size_t size, | |||
| 234 | mm_segment_t fs_save; | 230 | mm_segment_t fs_save; |
| 235 | ssize_t rc; | 231 | ssize_t rc; |
| 236 | 232 | ||
| 237 | mutex_lock(&inode_info->lower_file_mutex); | ||
| 238 | BUG_ON(!inode_info->lower_file); | 233 | BUG_ON(!inode_info->lower_file); |
| 239 | inode_info->lower_file->f_pos = offset; | ||
| 240 | fs_save = get_fs(); | 234 | fs_save = get_fs(); |
| 241 | set_fs(get_ds()); | 235 | set_fs(get_ds()); |
| 242 | rc = vfs_read(inode_info->lower_file, data, size, | 236 | rc = vfs_read(inode_info->lower_file, data, size, &offset); |
| 243 | &inode_info->lower_file->f_pos); | ||
| 244 | set_fs(fs_save); | 237 | set_fs(fs_save); |
| 245 | mutex_unlock(&inode_info->lower_file_mutex); | ||
| 246 | return rc; | 238 | return rc; |
| 247 | } | 239 | } |
| 248 | 240 | ||
diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c index 3042fe123a34..bacc882e1ae4 100644 --- a/fs/ecryptfs/super.c +++ b/fs/ecryptfs/super.c | |||
| @@ -55,7 +55,6 @@ static struct inode *ecryptfs_alloc_inode(struct super_block *sb) | |||
| 55 | if (unlikely(!inode_info)) | 55 | if (unlikely(!inode_info)) |
| 56 | goto out; | 56 | goto out; |
| 57 | ecryptfs_init_crypt_stat(&inode_info->crypt_stat); | 57 | ecryptfs_init_crypt_stat(&inode_info->crypt_stat); |
| 58 | mutex_init(&inode_info->lower_file_mutex); | ||
| 59 | inode_info->lower_file = NULL; | 58 | inode_info->lower_file = NULL; |
| 60 | inode = &inode_info->vfs_inode; | 59 | inode = &inode_info->vfs_inode; |
| 61 | out: | 60 | out: |
| @@ -198,7 +197,7 @@ static int ecryptfs_show_options(struct seq_file *m, struct vfsmount *mnt) | |||
| 198 | const struct super_operations ecryptfs_sops = { | 197 | const struct super_operations ecryptfs_sops = { |
| 199 | .alloc_inode = ecryptfs_alloc_inode, | 198 | .alloc_inode = ecryptfs_alloc_inode, |
| 200 | .destroy_inode = ecryptfs_destroy_inode, | 199 | .destroy_inode = ecryptfs_destroy_inode, |
| 201 | .drop_inode = generic_delete_inode, | 200 | .drop_inode = generic_drop_inode, |
| 202 | .statfs = ecryptfs_statfs, | 201 | .statfs = ecryptfs_statfs, |
| 203 | .remount_fs = NULL, | 202 | .remount_fs = NULL, |
| 204 | .evict_inode = ecryptfs_evict_inode, | 203 | .evict_inode = ecryptfs_evict_inode, |
