diff options
Diffstat (limited to 'fs/ecryptfs/read_write.c')
| -rw-r--r-- | fs/ecryptfs/read_write.c | 100 |
1 files changed, 18 insertions, 82 deletions
diff --git a/fs/ecryptfs/read_write.c b/fs/ecryptfs/read_write.c index 3745f7c2b9c2..b2a34a192f4f 100644 --- a/fs/ecryptfs/read_write.c +++ b/fs/ecryptfs/read_write.c | |||
| @@ -130,13 +130,18 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset, | |||
| 130 | pgoff_t ecryptfs_page_idx = (pos >> PAGE_CACHE_SHIFT); | 130 | pgoff_t ecryptfs_page_idx = (pos >> PAGE_CACHE_SHIFT); |
| 131 | size_t start_offset_in_page = (pos & ~PAGE_CACHE_MASK); | 131 | size_t start_offset_in_page = (pos & ~PAGE_CACHE_MASK); |
| 132 | size_t num_bytes = (PAGE_CACHE_SIZE - start_offset_in_page); | 132 | size_t num_bytes = (PAGE_CACHE_SIZE - start_offset_in_page); |
| 133 | size_t total_remaining_bytes = ((offset + size) - pos); | 133 | loff_t total_remaining_bytes = ((offset + size) - pos); |
| 134 | |||
| 135 | if (fatal_signal_pending(current)) { | ||
| 136 | rc = -EINTR; | ||
| 137 | break; | ||
| 138 | } | ||
| 134 | 139 | ||
| 135 | if (num_bytes > total_remaining_bytes) | 140 | if (num_bytes > total_remaining_bytes) |
| 136 | num_bytes = total_remaining_bytes; | 141 | num_bytes = total_remaining_bytes; |
| 137 | if (pos < offset) { | 142 | if (pos < offset) { |
| 138 | /* remaining zeros to write, up to destination offset */ | 143 | /* remaining zeros to write, up to destination offset */ |
| 139 | size_t total_remaining_zeros = (offset - pos); | 144 | loff_t total_remaining_zeros = (offset - pos); |
| 140 | 145 | ||
| 141 | if (num_bytes > total_remaining_zeros) | 146 | if (num_bytes > total_remaining_zeros) |
| 142 | num_bytes = total_remaining_zeros; | 147 | num_bytes = total_remaining_zeros; |
| @@ -151,7 +156,7 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset, | |||
| 151 | ecryptfs_page_idx, rc); | 156 | ecryptfs_page_idx, rc); |
| 152 | goto out; | 157 | goto out; |
| 153 | } | 158 | } |
| 154 | ecryptfs_page_virt = kmap_atomic(ecryptfs_page, KM_USER0); | 159 | ecryptfs_page_virt = kmap_atomic(ecryptfs_page); |
| 155 | 160 | ||
| 156 | /* | 161 | /* |
| 157 | * pos: where we're now writing, offset: where the request was | 162 | * pos: where we're now writing, offset: where the request was |
| @@ -174,7 +179,7 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset, | |||
| 174 | (data + data_offset), num_bytes); | 179 | (data + data_offset), num_bytes); |
| 175 | data_offset += num_bytes; | 180 | data_offset += num_bytes; |
| 176 | } | 181 | } |
| 177 | kunmap_atomic(ecryptfs_page_virt, KM_USER0); | 182 | kunmap_atomic(ecryptfs_page_virt); |
| 178 | flush_dcache_page(ecryptfs_page); | 183 | flush_dcache_page(ecryptfs_page); |
| 179 | SetPageUptodate(ecryptfs_page); | 184 | SetPageUptodate(ecryptfs_page); |
| 180 | unlock_page(ecryptfs_page); | 185 | unlock_page(ecryptfs_page); |
| @@ -193,15 +198,19 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset, | |||
| 193 | } | 198 | } |
| 194 | pos += num_bytes; | 199 | pos += num_bytes; |
| 195 | } | 200 | } |
| 196 | if ((offset + size) > ecryptfs_file_size) { | 201 | if (pos > ecryptfs_file_size) { |
| 197 | i_size_write(ecryptfs_inode, (offset + size)); | 202 | i_size_write(ecryptfs_inode, pos); |
| 198 | if (crypt_stat->flags & ECRYPTFS_ENCRYPTED) { | 203 | if (crypt_stat->flags & ECRYPTFS_ENCRYPTED) { |
| 199 | rc = ecryptfs_write_inode_size_to_metadata( | 204 | int rc2; |
| 205 | |||
| 206 | rc2 = ecryptfs_write_inode_size_to_metadata( | ||
| 200 | ecryptfs_inode); | 207 | ecryptfs_inode); |
| 201 | if (rc) { | 208 | if (rc2) { |
| 202 | printk(KERN_ERR "Problem with " | 209 | printk(KERN_ERR "Problem with " |
| 203 | "ecryptfs_write_inode_size_to_metadata; " | 210 | "ecryptfs_write_inode_size_to_metadata; " |
| 204 | "rc = [%d]\n", rc); | 211 | "rc = [%d]\n", rc2); |
| 212 | if (!rc) | ||
| 213 | rc = rc2; | ||
| 205 | goto out; | 214 | goto out; |
| 206 | } | 215 | } |
| 207 | } | 216 | } |
| @@ -273,76 +282,3 @@ int ecryptfs_read_lower_page_segment(struct page *page_for_ecryptfs, | |||
| 273 | flush_dcache_page(page_for_ecryptfs); | 282 | flush_dcache_page(page_for_ecryptfs); |
| 274 | return rc; | 283 | return rc; |
| 275 | } | 284 | } |
| 276 | |||
| 277 | #if 0 | ||
| 278 | /** | ||
| 279 | * ecryptfs_read | ||
| 280 | * @data: The virtual address into which to write the data read (and | ||
| 281 | * possibly decrypted) from the lower file | ||
| 282 | * @offset: The offset in the decrypted view of the file from which to | ||
| 283 | * read into @data | ||
| 284 | * @size: The number of bytes to read into @data | ||
| 285 | * @ecryptfs_file: The eCryptfs file from which to read | ||
| 286 | * | ||
| 287 | * Read an arbitrary amount of data from an arbitrary location in the | ||
| 288 | * eCryptfs page cache. This is done on an extent-by-extent basis; | ||
| 289 | * individual extents are decrypted and read from the lower page | ||
| 290 | * cache (via VFS reads). This function takes care of all the | ||
| 291 | * address translation to locations in the lower filesystem. | ||
| 292 | * | ||
| 293 | * Returns zero on success; non-zero otherwise | ||
| 294 | */ | ||
| 295 | int ecryptfs_read(char *data, loff_t offset, size_t size, | ||
| 296 | struct file *ecryptfs_file) | ||
| 297 | { | ||
| 298 | struct inode *ecryptfs_inode = ecryptfs_file->f_dentry->d_inode; | ||
| 299 | struct page *ecryptfs_page; | ||
| 300 | char *ecryptfs_page_virt; | ||
| 301 | loff_t ecryptfs_file_size = i_size_read(ecryptfs_inode); | ||
| 302 | loff_t data_offset = 0; | ||
| 303 | loff_t pos; | ||
| 304 | int rc = 0; | ||
| 305 | |||
| 306 | if ((offset + size) > ecryptfs_file_size) { | ||
| 307 | rc = -EINVAL; | ||
| 308 | printk(KERN_ERR "%s: Attempt to read data past the end of the " | ||
| 309 | "file; offset = [%lld]; size = [%td]; " | ||
| 310 | "ecryptfs_file_size = [%lld]\n", | ||
| 311 | __func__, offset, size, ecryptfs_file_size); | ||
| 312 | goto out; | ||
| 313 | } | ||
| 314 | pos = offset; | ||
| 315 | while (pos < (offset + size)) { | ||
| 316 | pgoff_t ecryptfs_page_idx = (pos >> PAGE_CACHE_SHIFT); | ||
| 317 | size_t start_offset_in_page = (pos & ~PAGE_CACHE_MASK); | ||
| 318 | size_t num_bytes = (PAGE_CACHE_SIZE - start_offset_in_page); | ||
| 319 | size_t total_remaining_bytes = ((offset + size) - pos); | ||
| 320 | |||
| 321 | if (num_bytes > total_remaining_bytes) | ||
| 322 | num_bytes = total_remaining_bytes; | ||
| 323 | ecryptfs_page = ecryptfs_get_locked_page(ecryptfs_inode, | ||
| 324 | ecryptfs_page_idx); | ||
| 325 | if (IS_ERR(ecryptfs_page)) { | ||
| 326 | rc = PTR_ERR(ecryptfs_page); | ||
| 327 | printk(KERN_ERR "%s: Error getting page at " | ||
| 328 | "index [%ld] from eCryptfs inode " | ||
| 329 | "mapping; rc = [%d]\n", __func__, | ||
| 330 | ecryptfs_page_idx, rc); | ||
| 331 | goto out; | ||
| 332 | } | ||
| 333 | ecryptfs_page_virt = kmap_atomic(ecryptfs_page, KM_USER0); | ||
| 334 | memcpy((data + data_offset), | ||
| 335 | ((char *)ecryptfs_page_virt + start_offset_in_page), | ||
| 336 | num_bytes); | ||
| 337 | kunmap_atomic(ecryptfs_page_virt, KM_USER0); | ||
| 338 | flush_dcache_page(ecryptfs_page); | ||
| 339 | SetPageUptodate(ecryptfs_page); | ||
| 340 | unlock_page(ecryptfs_page); | ||
| 341 | page_cache_release(ecryptfs_page); | ||
| 342 | pos += num_bytes; | ||
| 343 | data_offset += num_bytes; | ||
| 344 | } | ||
| 345 | out: | ||
| 346 | return rc; | ||
| 347 | } | ||
| 348 | #endif /* 0 */ | ||
