aboutsummaryrefslogtreecommitdiffstats
path: root/fs/libfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/libfs.c')
-rw-r--r--fs/libfs.c59
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
373static 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 */
391int simple_write_end(struct file *file, struct address_space *mapping, 394int 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