diff options
Diffstat (limited to 'fs/block_dev.c')
-rw-r--r-- | fs/block_dev.c | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c index 800f666c75a9..182ed1f788ff 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
@@ -1919,6 +1919,7 @@ ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from) | |||
1919 | struct inode *bd_inode = bdev_file_inode(file); | 1919 | struct inode *bd_inode = bdev_file_inode(file); |
1920 | loff_t size = i_size_read(bd_inode); | 1920 | loff_t size = i_size_read(bd_inode); |
1921 | struct blk_plug plug; | 1921 | struct blk_plug plug; |
1922 | size_t shorted = 0; | ||
1922 | ssize_t ret; | 1923 | ssize_t ret; |
1923 | 1924 | ||
1924 | if (bdev_read_only(I_BDEV(bd_inode))) | 1925 | if (bdev_read_only(I_BDEV(bd_inode))) |
@@ -1936,12 +1937,17 @@ ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from) | |||
1936 | if ((iocb->ki_flags & (IOCB_NOWAIT | IOCB_DIRECT)) == IOCB_NOWAIT) | 1937 | if ((iocb->ki_flags & (IOCB_NOWAIT | IOCB_DIRECT)) == IOCB_NOWAIT) |
1937 | return -EOPNOTSUPP; | 1938 | return -EOPNOTSUPP; |
1938 | 1939 | ||
1939 | iov_iter_truncate(from, size - iocb->ki_pos); | 1940 | size -= iocb->ki_pos; |
1941 | if (iov_iter_count(from) > size) { | ||
1942 | shorted = iov_iter_count(from) - size; | ||
1943 | iov_iter_truncate(from, size); | ||
1944 | } | ||
1940 | 1945 | ||
1941 | blk_start_plug(&plug); | 1946 | blk_start_plug(&plug); |
1942 | ret = __generic_file_write_iter(iocb, from); | 1947 | ret = __generic_file_write_iter(iocb, from); |
1943 | if (ret > 0) | 1948 | if (ret > 0) |
1944 | ret = generic_write_sync(iocb, ret); | 1949 | ret = generic_write_sync(iocb, ret); |
1950 | iov_iter_reexpand(from, iov_iter_count(from) + shorted); | ||
1945 | blk_finish_plug(&plug); | 1951 | blk_finish_plug(&plug); |
1946 | return ret; | 1952 | return ret; |
1947 | } | 1953 | } |
@@ -1953,13 +1959,21 @@ ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to) | |||
1953 | struct inode *bd_inode = bdev_file_inode(file); | 1959 | struct inode *bd_inode = bdev_file_inode(file); |
1954 | loff_t size = i_size_read(bd_inode); | 1960 | loff_t size = i_size_read(bd_inode); |
1955 | loff_t pos = iocb->ki_pos; | 1961 | loff_t pos = iocb->ki_pos; |
1962 | size_t shorted = 0; | ||
1963 | ssize_t ret; | ||
1956 | 1964 | ||
1957 | if (pos >= size) | 1965 | if (pos >= size) |
1958 | return 0; | 1966 | return 0; |
1959 | 1967 | ||
1960 | size -= pos; | 1968 | size -= pos; |
1961 | iov_iter_truncate(to, size); | 1969 | if (iov_iter_count(to) > size) { |
1962 | return generic_file_read_iter(iocb, to); | 1970 | shorted = iov_iter_count(to) - size; |
1971 | iov_iter_truncate(to, size); | ||
1972 | } | ||
1973 | |||
1974 | ret = generic_file_read_iter(iocb, to); | ||
1975 | iov_iter_reexpand(to, iov_iter_count(to) + shorted); | ||
1976 | return ret; | ||
1963 | } | 1977 | } |
1964 | EXPORT_SYMBOL_GPL(blkdev_read_iter); | 1978 | EXPORT_SYMBOL_GPL(blkdev_read_iter); |
1965 | 1979 | ||