diff options
Diffstat (limited to 'fs/libfs.c')
-rw-r--r-- | fs/libfs.c | 78 |
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 | ||
341 | int 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 | |||
353 | int simple_write_begin(struct file *file, struct address_space *mapping, | 342 | int 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 | ||
373 | static 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 | */ | ||
391 | int simple_write_end(struct file *file, struct address_space *mapping, | 386 | int 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); | |||
853 | EXPORT_SYMBOL(simple_link); | 856 | EXPORT_SYMBOL(simple_link); |
854 | EXPORT_SYMBOL(simple_lookup); | 857 | EXPORT_SYMBOL(simple_lookup); |
855 | EXPORT_SYMBOL(simple_pin_fs); | 858 | EXPORT_SYMBOL(simple_pin_fs); |
856 | EXPORT_UNUSED_SYMBOL(simple_prepare_write); | ||
857 | EXPORT_SYMBOL(simple_readpage); | 859 | EXPORT_SYMBOL(simple_readpage); |
858 | EXPORT_SYMBOL(simple_release_fs); | 860 | EXPORT_SYMBOL(simple_release_fs); |
859 | EXPORT_SYMBOL(simple_rename); | 861 | EXPORT_SYMBOL(simple_rename); |