diff options
author | Jens Axboe <axboe@suse.de> | 2006-05-03 04:35:10 -0400 |
---|---|---|
committer | Jens Axboe <axboe@nelson.home.kernel.dk> | 2006-05-04 00:55:12 -0400 |
commit | bfc4ee39fdbb2deb8864785d5e5bc5cdd3b31a69 (patch) | |
tree | 6f5f678cd07a4c65c1e7ea78f911fdd0932b0c7e /fs | |
parent | 5dea5176e5c32ef9f0d1a41d28427b3bf6881b3a (diff) |
[PATCH] splice: fix unlocking of page on error ->prepare_write()
Looking at generic_file_buffered_write(), we need to unlock_page() if
prepare write fails and it isn't due to racing with truncate().
Also trim the size if ->prepare_write() fails, if we have to.
Signed-off-by: Jens Axboe <axboe@suse.de>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/splice.c | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/fs/splice.c b/fs/splice.c index 7fb04970c72d..27f5e3738a7b 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
@@ -647,11 +647,24 @@ find_page: | |||
647 | } | 647 | } |
648 | 648 | ||
649 | ret = mapping->a_ops->prepare_write(file, page, offset, offset+this_len); | 649 | ret = mapping->a_ops->prepare_write(file, page, offset, offset+this_len); |
650 | if (ret == AOP_TRUNCATED_PAGE) { | 650 | if (unlikely(ret)) { |
651 | loff_t isize = i_size_read(mapping->host); | ||
652 | |||
653 | if (ret != AOP_TRUNCATED_PAGE) | ||
654 | unlock_page(page); | ||
651 | page_cache_release(page); | 655 | page_cache_release(page); |
652 | goto find_page; | 656 | if (ret == AOP_TRUNCATED_PAGE) |
653 | } else if (ret) | 657 | goto find_page; |
658 | |||
659 | /* | ||
660 | * prepare_write() may have instantiated a few blocks | ||
661 | * outside i_size. Trim these off again. | ||
662 | */ | ||
663 | if (sd->pos + this_len > isize) | ||
664 | vmtruncate(mapping->host, isize); | ||
665 | |||
654 | goto out; | 666 | goto out; |
667 | } | ||
655 | 668 | ||
656 | if (buf->page != page) { | 669 | if (buf->page != page) { |
657 | /* | 670 | /* |