diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/libfs.c | 59 |
1 files changed, 35 insertions, 24 deletions
diff --git a/fs/libfs.c b/fs/libfs.c index 6e8d17e1dc4c..cd88abdcb436 100644 --- a/fs/libfs.c +++ b/fs/libfs.c | |||
@@ -370,40 +370,51 @@ int simple_write_begin(struct file *file, struct address_space *mapping, | |||
370 | return simple_prepare_write(file, page, from, from+len); | 370 | return simple_prepare_write(file, page, from, from+len); |
371 | } | 371 | } |
372 | 372 | ||
373 | static int simple_commit_write(struct file *file, struct page *page, | 373 | /** |
374 | unsigned from, unsigned to) | 374 | * simple_write_end - .write_end helper for non-block-device FSes |
375 | { | 375 | * @available: See .write_end of address_space_operations |
376 | struct inode *inode = page->mapping->host; | 376 | * @file: " |
377 | loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to; | 377 | * @mapping: " |
378 | 378 | * @pos: " | |
379 | if (!PageUptodate(page)) | 379 | * @len: " |
380 | SetPageUptodate(page); | 380 | * @copied: " |
381 | /* | 381 | * @page: " |
382 | * No need to use i_size_read() here, the i_size | 382 | * @fsdata: " |
383 | * cannot change under us because we hold the i_mutex. | 383 | * |
384 | */ | 384 | * simple_write_end does the minimum needed for updating a page after writing is |
385 | if (pos > inode->i_size) | 385 | * done. It has the same API signature as the .write_end of |
386 | i_size_write(inode, pos); | 386 | * address_space_operations vector. So it can just be set onto .write_end for |
387 | set_page_dirty(page); | 387 | * FSes that don't need any other processing. i_mutex is assumed to be held. |
388 | return 0; | 388 | * Block based filesystems should use generic_write_end(). |
389 | } | 389 | * NOTE: Even though i_size might get updated by this function, mark_inode_dirty |
390 | 390 | * is not called, so a filesystem that actually does store data in .write_inode | |
391 | * should extend on what's done here with a call to mark_inode_dirty() in the | ||
392 | * case that i_size has changed. | ||
393 | */ | ||
391 | int simple_write_end(struct file *file, struct address_space *mapping, | 394 | int simple_write_end(struct file *file, struct address_space *mapping, |
392 | loff_t pos, unsigned len, unsigned copied, | 395 | loff_t pos, unsigned len, unsigned copied, |
393 | struct page *page, void *fsdata) | 396 | struct page *page, void *fsdata) |
394 | { | 397 | { |
395 | unsigned from = pos & (PAGE_CACHE_SIZE - 1); | 398 | struct inode *inode = page->mapping->host; |
399 | loff_t last_pos = pos + copied; | ||
396 | 400 | ||
397 | /* zero the stale part of the page if we did a short copy */ | 401 | /* zero the stale part of the page if we did a short copy */ |
398 | if (copied < len) { | 402 | if (copied < len) { |
399 | void *kaddr = kmap_atomic(page, KM_USER0); | 403 | unsigned from = pos & (PAGE_CACHE_SIZE - 1); |
400 | memset(kaddr + from + copied, 0, len - copied); | 404 | |
401 | flush_dcache_page(page); | 405 | zero_user(page, from + copied, len - copied); |
402 | kunmap_atomic(kaddr, KM_USER0); | ||
403 | } | 406 | } |
404 | 407 | ||
405 | simple_commit_write(file, page, from, from+copied); | 408 | if (!PageUptodate(page)) |
409 | SetPageUptodate(page); | ||
410 | /* | ||
411 | * No need to use i_size_read() here, the i_size | ||
412 | * cannot change under us because we hold the i_mutex. | ||
413 | */ | ||
414 | if (last_pos > inode->i_size) | ||
415 | i_size_write(inode, last_pos); | ||
406 | 416 | ||
417 | set_page_dirty(page); | ||
407 | unlock_page(page); | 418 | unlock_page(page); |
408 | page_cache_release(page); | 419 | page_cache_release(page); |
409 | 420 | ||