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