diff options
Diffstat (limited to 'fs/ecryptfs/mmap.c')
| -rw-r--r-- | fs/ecryptfs/mmap.c | 102 |
1 files changed, 76 insertions, 26 deletions
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index dc74b186145d..6df1debdccce 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c | |||
| @@ -263,52 +263,102 @@ out: | |||
| 263 | return 0; | 263 | return 0; |
| 264 | } | 264 | } |
| 265 | 265 | ||
| 266 | /* This function must zero any hole we create */ | 266 | /** |
| 267 | * ecryptfs_prepare_write | ||
| 268 | * @file: The eCryptfs file | ||
| 269 | * @page: The eCryptfs page | ||
| 270 | * @from: The start byte from which we will write | ||
| 271 | * @to: The end byte to which we will write | ||
| 272 | * | ||
| 273 | * This function must zero any hole we create | ||
| 274 | * | ||
| 275 | * Returns zero on success; non-zero otherwise | ||
| 276 | */ | ||
| 267 | static int ecryptfs_prepare_write(struct file *file, struct page *page, | 277 | static int ecryptfs_prepare_write(struct file *file, struct page *page, |
| 268 | unsigned from, unsigned to) | 278 | unsigned from, unsigned to) |
| 269 | { | 279 | { |
| 270 | int rc = 0; | ||
| 271 | loff_t prev_page_end_size; | 280 | loff_t prev_page_end_size; |
| 281 | int rc = 0; | ||
| 272 | 282 | ||
| 273 | if (!PageUptodate(page)) { | 283 | if (!PageUptodate(page)) { |
| 274 | rc = ecryptfs_read_lower_page_segment(page, page->index, 0, | 284 | struct ecryptfs_crypt_stat *crypt_stat = |
| 275 | PAGE_CACHE_SIZE, | 285 | &ecryptfs_inode_to_private( |
| 276 | page->mapping->host); | 286 | file->f_path.dentry->d_inode)->crypt_stat; |
| 277 | if (rc) { | 287 | |
| 278 | printk(KERN_ERR "%s: Error attemping to read lower " | 288 | if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED) |
| 279 | "page segment; rc = [%d]\n", __FUNCTION__, rc); | 289 | || (crypt_stat->flags & ECRYPTFS_NEW_FILE)) { |
| 280 | ClearPageUptodate(page); | 290 | rc = ecryptfs_read_lower_page_segment( |
| 281 | goto out; | 291 | page, page->index, 0, PAGE_CACHE_SIZE, |
| 282 | } else | 292 | page->mapping->host); |
| 293 | if (rc) { | ||
| 294 | printk(KERN_ERR "%s: Error attemping to read " | ||
| 295 | "lower page segment; rc = [%d]\n", | ||
| 296 | __FUNCTION__, rc); | ||
| 297 | ClearPageUptodate(page); | ||
| 298 | goto out; | ||
| 299 | } else | ||
| 300 | SetPageUptodate(page); | ||
| 301 | } else if (crypt_stat->flags & ECRYPTFS_VIEW_AS_ENCRYPTED) { | ||
| 302 | if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) { | ||
| 303 | rc = ecryptfs_copy_up_encrypted_with_header( | ||
| 304 | page, crypt_stat); | ||
| 305 | if (rc) { | ||
| 306 | printk(KERN_ERR "%s: Error attempting " | ||
| 307 | "to copy the encrypted content " | ||
| 308 | "from the lower file whilst " | ||
| 309 | "inserting the metadata from " | ||
| 310 | "the xattr into the header; rc " | ||
| 311 | "= [%d]\n", __FUNCTION__, rc); | ||
| 312 | ClearPageUptodate(page); | ||
| 313 | goto out; | ||
| 314 | } | ||
| 315 | SetPageUptodate(page); | ||
| 316 | } else { | ||
| 317 | rc = ecryptfs_read_lower_page_segment( | ||
| 318 | page, page->index, 0, PAGE_CACHE_SIZE, | ||
| 319 | page->mapping->host); | ||
| 320 | if (rc) { | ||
| 321 | printk(KERN_ERR "%s: Error reading " | ||
| 322 | "page; rc = [%d]\n", | ||
| 323 | __FUNCTION__, rc); | ||
| 324 | ClearPageUptodate(page); | ||
| 325 | goto out; | ||
| 326 | } | ||
| 327 | SetPageUptodate(page); | ||
| 328 | } | ||
| 329 | } else { | ||
| 330 | rc = ecryptfs_decrypt_page(page); | ||
| 331 | if (rc) { | ||
| 332 | printk(KERN_ERR "%s: Error decrypting page " | ||
| 333 | "at index [%ld]; rc = [%d]\n", | ||
| 334 | __FUNCTION__, page->index, rc); | ||
| 335 | ClearPageUptodate(page); | ||
| 336 | goto out; | ||
| 337 | } | ||
| 283 | SetPageUptodate(page); | 338 | SetPageUptodate(page); |
| 339 | } | ||
| 284 | } | 340 | } |
| 285 | |||
| 286 | prev_page_end_size = ((loff_t)page->index << PAGE_CACHE_SHIFT); | 341 | prev_page_end_size = ((loff_t)page->index << PAGE_CACHE_SHIFT); |
| 287 | 342 | /* If creating a page or more of holes, zero them out via truncate. | |
| 288 | /* | 343 | * Note, this will increase i_size. */ |
| 289 | * If creating a page or more of holes, zero them out via truncate. | ||
| 290 | * Note, this will increase i_size. | ||
| 291 | */ | ||
| 292 | if (page->index != 0) { | 344 | if (page->index != 0) { |
| 293 | if (prev_page_end_size > i_size_read(page->mapping->host)) { | 345 | if (prev_page_end_size > i_size_read(page->mapping->host)) { |
| 294 | rc = ecryptfs_truncate(file->f_path.dentry, | 346 | rc = ecryptfs_truncate(file->f_path.dentry, |
| 295 | prev_page_end_size); | 347 | prev_page_end_size); |
| 296 | if (rc) { | 348 | if (rc) { |
| 297 | printk(KERN_ERR "Error on attempt to " | 349 | printk(KERN_ERR "%s: Error on attempt to " |
| 298 | "truncate to (higher) offset [%lld];" | 350 | "truncate to (higher) offset [%lld];" |
| 299 | " rc = [%d]\n", prev_page_end_size, rc); | 351 | " rc = [%d]\n", __FUNCTION__, |
| 352 | prev_page_end_size, rc); | ||
| 300 | goto out; | 353 | goto out; |
| 301 | } | 354 | } |
| 302 | } | 355 | } |
| 303 | } | 356 | } |
| 304 | /* | 357 | /* Writing to a new page, and creating a small hole from start |
| 305 | * Writing to a new page, and creating a small hole from start of page? | 358 | * of page? Zero it out. */ |
| 306 | * Zero it out. | 359 | if ((i_size_read(page->mapping->host) == prev_page_end_size) |
| 307 | */ | 360 | && (from != 0)) |
| 308 | if ((i_size_read(page->mapping->host) == prev_page_end_size) && | ||
| 309 | (from != 0)) { | ||
| 310 | zero_user(page, 0, PAGE_CACHE_SIZE); | 361 | zero_user(page, 0, PAGE_CACHE_SIZE); |
| 311 | } | ||
| 312 | out: | 362 | out: |
| 313 | return rc; | 363 | return rc; |
| 314 | } | 364 | } |
