aboutsummaryrefslogtreecommitdiffstats
path: root/fs/libfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/libfs.c')
-rw-r--r--fs/libfs.c78
1 files changed, 40 insertions, 38 deletions
diff --git a/fs/libfs.c b/fs/libfs.c
index 6e8d17e1dc4c..ea9a6cc9b35c 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -5,6 +5,7 @@
5 5
6#include <linux/module.h> 6#include <linux/module.h>
7#include <linux/pagemap.h> 7#include <linux/pagemap.h>
8#include <linux/slab.h>
8#include <linux/mount.h> 9#include <linux/mount.h>
9#include <linux/vfs.h> 10#include <linux/vfs.h>
10#include <linux/mutex.h> 11#include <linux/mutex.h>
@@ -338,28 +339,14 @@ int simple_readpage(struct file *file, struct page *page)
338 return 0; 339 return 0;
339} 340}
340 341
341int simple_prepare_write(struct file *file, struct page *page,
342 unsigned from, unsigned to)
343{
344 if (!PageUptodate(page)) {
345 if (to - from != PAGE_CACHE_SIZE)
346 zero_user_segments(page,
347 0, from,
348 to, PAGE_CACHE_SIZE);
349 }
350 return 0;
351}
352
353int simple_write_begin(struct file *file, struct address_space *mapping, 342int simple_write_begin(struct file *file, struct address_space *mapping,
354 loff_t pos, unsigned len, unsigned flags, 343 loff_t pos, unsigned len, unsigned flags,
355 struct page **pagep, void **fsdata) 344 struct page **pagep, void **fsdata)
356{ 345{
357 struct page *page; 346 struct page *page;
358 pgoff_t index; 347 pgoff_t index;
359 unsigned from;
360 348
361 index = pos >> PAGE_CACHE_SHIFT; 349 index = pos >> PAGE_CACHE_SHIFT;
362 from = pos & (PAGE_CACHE_SIZE - 1);
363 350
364 page = grab_cache_page_write_begin(mapping, index, flags); 351 page = grab_cache_page_write_begin(mapping, index, flags);
365 if (!page) 352 if (!page)
@@ -367,43 +354,59 @@ int simple_write_begin(struct file *file, struct address_space *mapping,
367 354
368 *pagep = page; 355 *pagep = page;
369 356
370 return simple_prepare_write(file, page, from, from+len); 357 if (!PageUptodate(page) && (len != PAGE_CACHE_SIZE)) {
371} 358 unsigned from = pos & (PAGE_CACHE_SIZE - 1);
372 359
373static int simple_commit_write(struct file *file, struct page *page, 360 zero_user_segments(page, 0, from, from + len, PAGE_CACHE_SIZE);
374 unsigned from, unsigned to) 361 }
375{
376 struct inode *inode = page->mapping->host;
377 loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
378
379 if (!PageUptodate(page))
380 SetPageUptodate(page);
381 /*
382 * No need to use i_size_read() here, the i_size
383 * cannot change under us because we hold the i_mutex.
384 */
385 if (pos > inode->i_size)
386 i_size_write(inode, pos);
387 set_page_dirty(page);
388 return 0; 362 return 0;
389} 363}
390 364
365/**
366 * simple_write_end - .write_end helper for non-block-device FSes
367 * @available: See .write_end of address_space_operations
368 * @file: "
369 * @mapping: "
370 * @pos: "
371 * @len: "
372 * @copied: "
373 * @page: "
374 * @fsdata: "
375 *
376 * simple_write_end does the minimum needed for updating a page after writing is
377 * done. It has the same API signature as the .write_end of
378 * address_space_operations vector. So it can just be set onto .write_end for
379 * FSes that don't need any other processing. i_mutex is assumed to be held.
380 * Block based filesystems should use generic_write_end().
381 * NOTE: Even though i_size might get updated by this function, mark_inode_dirty
382 * is not called, so a filesystem that actually does store data in .write_inode
383 * should extend on what's done here with a call to mark_inode_dirty() in the
384 * case that i_size has changed.
385 */
391int simple_write_end(struct file *file, struct address_space *mapping, 386int simple_write_end(struct file *file, struct address_space *mapping,
392 loff_t pos, unsigned len, unsigned copied, 387 loff_t pos, unsigned len, unsigned copied,
393 struct page *page, void *fsdata) 388 struct page *page, void *fsdata)
394{ 389{
395 unsigned from = pos & (PAGE_CACHE_SIZE - 1); 390 struct inode *inode = page->mapping->host;
391 loff_t last_pos = pos + copied;
396 392
397 /* zero the stale part of the page if we did a short copy */ 393 /* zero the stale part of the page if we did a short copy */
398 if (copied < len) { 394 if (copied < len) {
399 void *kaddr = kmap_atomic(page, KM_USER0); 395 unsigned from = pos & (PAGE_CACHE_SIZE - 1);
400 memset(kaddr + from + copied, 0, len - copied); 396
401 flush_dcache_page(page); 397 zero_user(page, from + copied, len - copied);
402 kunmap_atomic(kaddr, KM_USER0);
403 } 398 }
404 399
405 simple_commit_write(file, page, from, from+copied); 400 if (!PageUptodate(page))
401 SetPageUptodate(page);
402 /*
403 * No need to use i_size_read() here, the i_size
404 * cannot change under us because we hold the i_mutex.
405 */
406 if (last_pos > inode->i_size)
407 i_size_write(inode, last_pos);
406 408
409 set_page_dirty(page);
407 unlock_page(page); 410 unlock_page(page);
408 page_cache_release(page); 411 page_cache_release(page);
409 412
@@ -853,7 +856,6 @@ EXPORT_SYMBOL(simple_getattr);
853EXPORT_SYMBOL(simple_link); 856EXPORT_SYMBOL(simple_link);
854EXPORT_SYMBOL(simple_lookup); 857EXPORT_SYMBOL(simple_lookup);
855EXPORT_SYMBOL(simple_pin_fs); 858EXPORT_SYMBOL(simple_pin_fs);
856EXPORT_UNUSED_SYMBOL(simple_prepare_write);
857EXPORT_SYMBOL(simple_readpage); 859EXPORT_SYMBOL(simple_readpage);
858EXPORT_SYMBOL(simple_release_fs); 860EXPORT_SYMBOL(simple_release_fs);
859EXPORT_SYMBOL(simple_rename); 861EXPORT_SYMBOL(simple_rename);