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 | |
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>
-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, |