diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2015-04-09 12:55:47 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2015-04-11 22:30:21 -0400 |
commit | 3309dd04cbcd2cdad168485af5cf3576b5051e49 (patch) | |
tree | 3e01f865306dee01b31f34c9e7e819a5f42a4087 | |
parent | 90320251db0fe3d05f2b10686ec936c7d6ecd99a (diff) |
switch generic_write_checks() to iocb and iter
... returning -E... upon error and amount of data left in iter after
(possible) truncation upon success. Note, that normal case gives
a non-zero (positive) return value, so any tests for != 0 _must_ be
updated.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Conflicts:
fs/ext4/file.c
-rw-r--r-- | fs/9p/vfs_file.c | 26 | ||||
-rw-r--r-- | fs/btrfs/file.c | 24 | ||||
-rw-r--r-- | fs/ceph/file.c | 14 | ||||
-rw-r--r-- | fs/cifs/file.c | 26 | ||||
-rw-r--r-- | fs/ext4/file.c | 20 | ||||
-rw-r--r-- | fs/fuse/file.c | 22 | ||||
-rw-r--r-- | fs/ncpfs/file.c | 14 | ||||
-rw-r--r-- | fs/nfs/direct.c | 25 | ||||
-rw-r--r-- | fs/ntfs/file.c | 11 | ||||
-rw-r--r-- | fs/ocfs2/file.c | 19 | ||||
-rw-r--r-- | fs/udf/file.c | 10 | ||||
-rw-r--r-- | fs/xfs/xfs_file.c | 8 | ||||
-rw-r--r-- | include/linux/fs.h | 2 | ||||
-rw-r--r-- | mm/filemap.c | 44 |
14 files changed, 99 insertions, 166 deletions
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index b5b020ace1b3..2a9dd37dc426 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c | |||
@@ -404,21 +404,16 @@ static ssize_t | |||
404 | v9fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) | 404 | v9fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) |
405 | { | 405 | { |
406 | struct file *file = iocb->ki_filp; | 406 | struct file *file = iocb->ki_filp; |
407 | ssize_t retval = 0; | 407 | ssize_t retval; |
408 | loff_t origin = iocb->ki_pos; | 408 | loff_t origin; |
409 | size_t count = iov_iter_count(from); | ||
410 | int err = 0; | 409 | int err = 0; |
411 | 410 | ||
412 | retval = generic_write_checks(file, &origin, &count); | 411 | retval = generic_write_checks(iocb, from); |
413 | if (retval) | 412 | if (retval <= 0) |
414 | return retval; | 413 | return retval; |
415 | 414 | ||
416 | iov_iter_truncate(from, count); | 415 | origin = iocb->ki_pos; |
417 | 416 | retval = p9_client_write(file->private_data, iocb->ki_pos, from, &err); | |
418 | if (!count) | ||
419 | return 0; | ||
420 | |||
421 | retval = p9_client_write(file->private_data, origin, from, &err); | ||
422 | if (retval > 0) { | 417 | if (retval > 0) { |
423 | struct inode *inode = file_inode(file); | 418 | struct inode *inode = file_inode(file); |
424 | loff_t i_size; | 419 | loff_t i_size; |
@@ -428,12 +423,11 @@ v9fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) | |||
428 | if (inode->i_mapping && inode->i_mapping->nrpages) | 423 | if (inode->i_mapping && inode->i_mapping->nrpages) |
429 | invalidate_inode_pages2_range(inode->i_mapping, | 424 | invalidate_inode_pages2_range(inode->i_mapping, |
430 | pg_start, pg_end); | 425 | pg_start, pg_end); |
431 | origin += retval; | 426 | iocb->ki_pos += retval; |
432 | i_size = i_size_read(inode); | 427 | i_size = i_size_read(inode); |
433 | iocb->ki_pos = origin; | 428 | if (iocb->ki_pos > i_size) { |
434 | if (origin > i_size) { | 429 | inode_add_bytes(inode, iocb->ki_pos - i_size); |
435 | inode_add_bytes(inode, origin - i_size); | 430 | i_size_write(inode, iocb->ki_pos); |
436 | i_size_write(inode, origin); | ||
437 | } | 431 | } |
438 | return retval; | 432 | return retval; |
439 | } | 433 | } |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 691a84a81e09..c64d11c41eeb 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -1739,27 +1739,19 @@ static ssize_t btrfs_file_write_iter(struct kiocb *iocb, | |||
1739 | u64 start_pos; | 1739 | u64 start_pos; |
1740 | u64 end_pos; | 1740 | u64 end_pos; |
1741 | ssize_t num_written = 0; | 1741 | ssize_t num_written = 0; |
1742 | ssize_t err = 0; | ||
1743 | size_t count = iov_iter_count(from); | ||
1744 | bool sync = (file->f_flags & O_DSYNC) || IS_SYNC(file->f_mapping->host); | 1742 | bool sync = (file->f_flags & O_DSYNC) || IS_SYNC(file->f_mapping->host); |
1745 | loff_t pos = iocb->ki_pos; | 1743 | ssize_t err; |
1744 | loff_t pos; | ||
1745 | size_t count; | ||
1746 | 1746 | ||
1747 | mutex_lock(&inode->i_mutex); | 1747 | mutex_lock(&inode->i_mutex); |
1748 | 1748 | err = generic_write_checks(iocb, from); | |
1749 | current->backing_dev_info = inode_to_bdi(inode); | 1749 | if (err <= 0) { |
1750 | err = generic_write_checks(file, &pos, &count); | ||
1751 | if (err) { | ||
1752 | mutex_unlock(&inode->i_mutex); | 1750 | mutex_unlock(&inode->i_mutex); |
1753 | goto out; | 1751 | return err; |
1754 | } | ||
1755 | |||
1756 | if (count == 0) { | ||
1757 | mutex_unlock(&inode->i_mutex); | ||
1758 | goto out; | ||
1759 | } | 1752 | } |
1760 | 1753 | ||
1761 | iov_iter_truncate(from, count); | 1754 | current->backing_dev_info = inode_to_bdi(inode); |
1762 | |||
1763 | err = file_remove_suid(file); | 1755 | err = file_remove_suid(file); |
1764 | if (err) { | 1756 | if (err) { |
1765 | mutex_unlock(&inode->i_mutex); | 1757 | mutex_unlock(&inode->i_mutex); |
@@ -1786,6 +1778,8 @@ static ssize_t btrfs_file_write_iter(struct kiocb *iocb, | |||
1786 | */ | 1778 | */ |
1787 | update_time_for_write(inode); | 1779 | update_time_for_write(inode); |
1788 | 1780 | ||
1781 | pos = iocb->ki_pos; | ||
1782 | count = iov_iter_count(from); | ||
1789 | start_pos = round_down(pos, root->sectorsize); | 1783 | start_pos = round_down(pos, root->sectorsize); |
1790 | if (start_pos > i_size_read(inode)) { | 1784 | if (start_pos > i_size_read(inode)) { |
1791 | /* Expand hole size to cover write data, preventing empty gap */ | 1785 | /* Expand hole size to cover write data, preventing empty gap */ |
diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 761841903160..3f0b9339d823 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c | |||
@@ -941,9 +941,9 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from) | |||
941 | struct ceph_inode_info *ci = ceph_inode(inode); | 941 | struct ceph_inode_info *ci = ceph_inode(inode); |
942 | struct ceph_osd_client *osdc = | 942 | struct ceph_osd_client *osdc = |
943 | &ceph_sb_to_client(inode->i_sb)->client->osdc; | 943 | &ceph_sb_to_client(inode->i_sb)->client->osdc; |
944 | ssize_t count = iov_iter_count(from), written = 0; | 944 | ssize_t count, written = 0; |
945 | int err, want, got; | 945 | int err, want, got; |
946 | loff_t pos = iocb->ki_pos; | 946 | loff_t pos; |
947 | 947 | ||
948 | if (ceph_snap(inode) != CEPH_NOSNAP) | 948 | if (ceph_snap(inode) != CEPH_NOSNAP) |
949 | return -EROFS; | 949 | return -EROFS; |
@@ -953,14 +953,12 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from) | |||
953 | /* We can write back this queue in page reclaim */ | 953 | /* We can write back this queue in page reclaim */ |
954 | current->backing_dev_info = inode_to_bdi(inode); | 954 | current->backing_dev_info = inode_to_bdi(inode); |
955 | 955 | ||
956 | err = generic_write_checks(file, &pos, &count); | 956 | err = generic_write_checks(iocb, from); |
957 | if (err) | 957 | if (err <= 0) |
958 | goto out; | ||
959 | |||
960 | if (count == 0) | ||
961 | goto out; | 958 | goto out; |
962 | iov_iter_truncate(from, count); | ||
963 | 959 | ||
960 | pos = iocb->ki_pos; | ||
961 | count = iov_iter_count(from); | ||
964 | err = file_remove_suid(file); | 962 | err = file_remove_suid(file); |
965 | if (err) | 963 | if (err) |
966 | goto out; | 964 | goto out; |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 4202e74b2db5..ca2bc5406306 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -2563,7 +2563,6 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from, | |||
2563 | ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from) | 2563 | ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from) |
2564 | { | 2564 | { |
2565 | struct file *file = iocb->ki_filp; | 2565 | struct file *file = iocb->ki_filp; |
2566 | size_t len; | ||
2567 | ssize_t total_written = 0; | 2566 | ssize_t total_written = 0; |
2568 | struct cifsFileInfo *open_file; | 2567 | struct cifsFileInfo *open_file; |
2569 | struct cifs_tcon *tcon; | 2568 | struct cifs_tcon *tcon; |
@@ -2579,16 +2578,10 @@ ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from) | |||
2579 | * write request. | 2578 | * write request. |
2580 | */ | 2579 | */ |
2581 | 2580 | ||
2582 | len = iov_iter_count(from); | 2581 | rc = generic_write_checks(iocb, from); |
2583 | rc = generic_write_checks(file, &iocb->ki_pos, &len); | 2582 | if (rc <= 0) |
2584 | if (rc) | ||
2585 | return rc; | 2583 | return rc; |
2586 | 2584 | ||
2587 | if (!len) | ||
2588 | return 0; | ||
2589 | |||
2590 | iov_iter_truncate(from, len); | ||
2591 | |||
2592 | INIT_LIST_HEAD(&wdata_list); | 2585 | INIT_LIST_HEAD(&wdata_list); |
2593 | cifs_sb = CIFS_FILE_SB(file); | 2586 | cifs_sb = CIFS_FILE_SB(file); |
2594 | open_file = file->private_data; | 2587 | open_file = file->private_data; |
@@ -2599,8 +2592,8 @@ ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from) | |||
2599 | 2592 | ||
2600 | memcpy(&saved_from, from, sizeof(struct iov_iter)); | 2593 | memcpy(&saved_from, from, sizeof(struct iov_iter)); |
2601 | 2594 | ||
2602 | rc = cifs_write_from_iter(iocb->ki_pos, len, from, open_file, cifs_sb, | 2595 | rc = cifs_write_from_iter(iocb->ki_pos, iov_iter_count(from), from, |
2603 | &wdata_list); | 2596 | open_file, cifs_sb, &wdata_list); |
2604 | 2597 | ||
2605 | /* | 2598 | /* |
2606 | * If at least one write was successfully sent, then discard any rc | 2599 | * If at least one write was successfully sent, then discard any rc |
@@ -2674,7 +2667,6 @@ cifs_writev(struct kiocb *iocb, struct iov_iter *from) | |||
2674 | struct cifsInodeInfo *cinode = CIFS_I(inode); | 2667 | struct cifsInodeInfo *cinode = CIFS_I(inode); |
2675 | struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server; | 2668 | struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server; |
2676 | ssize_t rc; | 2669 | ssize_t rc; |
2677 | size_t count; | ||
2678 | 2670 | ||
2679 | /* | 2671 | /* |
2680 | * We need to hold the sem to be sure nobody modifies lock list | 2672 | * We need to hold the sem to be sure nobody modifies lock list |
@@ -2683,16 +2675,10 @@ cifs_writev(struct kiocb *iocb, struct iov_iter *from) | |||
2683 | down_read(&cinode->lock_sem); | 2675 | down_read(&cinode->lock_sem); |
2684 | mutex_lock(&inode->i_mutex); | 2676 | mutex_lock(&inode->i_mutex); |
2685 | 2677 | ||
2686 | count = iov_iter_count(from); | 2678 | rc = generic_write_checks(iocb, from); |
2687 | rc = generic_write_checks(file, &iocb->ki_pos, &count); | 2679 | if (rc <= 0) |
2688 | if (rc) | ||
2689 | goto out; | 2680 | goto out; |
2690 | 2681 | ||
2691 | if (count == 0) | ||
2692 | goto out; | ||
2693 | |||
2694 | iov_iter_truncate(from, count); | ||
2695 | |||
2696 | if (!cifs_find_lock_conflict(cfile, iocb->ki_pos, iov_iter_count(from), | 2682 | if (!cifs_find_lock_conflict(cfile, iocb->ki_pos, iov_iter_count(from), |
2697 | server->vals->exclusive_lock_type, NULL, | 2683 | server->vals->exclusive_lock_type, NULL, |
2698 | CIFS_WRITE_OP)) | 2684 | CIFS_WRITE_OP)) |
diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 42b1fa33a17a..c10785f10d1d 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c | |||
@@ -97,9 +97,7 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from) | |||
97 | struct blk_plug plug; | 97 | struct blk_plug plug; |
98 | int o_direct = io_is_direct(file); | 98 | int o_direct = io_is_direct(file); |
99 | int overwrite = 0; | 99 | int overwrite = 0; |
100 | size_t length = iov_iter_count(from); | ||
101 | ssize_t ret; | 100 | ssize_t ret; |
102 | loff_t pos; | ||
103 | 101 | ||
104 | /* | 102 | /* |
105 | * Unaligned direct AIO must be serialized; see comment above | 103 | * Unaligned direct AIO must be serialized; see comment above |
@@ -116,16 +114,10 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from) | |||
116 | } | 114 | } |
117 | 115 | ||
118 | mutex_lock(&inode->i_mutex); | 116 | mutex_lock(&inode->i_mutex); |
119 | ret = generic_write_checks(file, &iocb->ki_pos, &length); | 117 | ret = generic_write_checks(iocb, from); |
120 | if (ret) | 118 | if (ret <= 0) |
121 | goto out; | 119 | goto out; |
122 | 120 | ||
123 | if (length == 0) | ||
124 | goto out; | ||
125 | |||
126 | iov_iter_truncate(from, length); | ||
127 | pos = iocb->ki_pos; | ||
128 | |||
129 | /* | 121 | /* |
130 | * If we have encountered a bitmap-format file, the size limit | 122 | * If we have encountered a bitmap-format file, the size limit |
131 | * is smaller than s_maxbytes, which is for extent-mapped files. | 123 | * is smaller than s_maxbytes, which is for extent-mapped files. |
@@ -133,19 +125,19 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from) | |||
133 | if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) { | 125 | if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) { |
134 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); | 126 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); |
135 | 127 | ||
136 | if (pos >= sbi->s_bitmap_maxbytes) { | 128 | if (iocb->ki_pos >= sbi->s_bitmap_maxbytes) { |
137 | ret = -EFBIG; | 129 | ret = -EFBIG; |
138 | goto out; | 130 | goto out; |
139 | } | 131 | } |
140 | iov_iter_truncate(from, sbi->s_bitmap_maxbytes - pos); | 132 | iov_iter_truncate(from, sbi->s_bitmap_maxbytes - iocb->ki_pos); |
141 | } | 133 | } |
142 | 134 | ||
143 | iocb->private = &overwrite; | 135 | iocb->private = &overwrite; |
144 | if (o_direct) { | 136 | if (o_direct) { |
145 | length = iov_iter_count(from); | 137 | size_t length = iov_iter_count(from); |
138 | loff_t pos = iocb->ki_pos; | ||
146 | blk_start_plug(&plug); | 139 | blk_start_plug(&plug); |
147 | 140 | ||
148 | |||
149 | /* check whether we do a DIO overwrite or not */ | 141 | /* check whether we do a DIO overwrite or not */ |
150 | if (ext4_should_dioread_nolock(inode) && !aio_mutex && | 142 | if (ext4_should_dioread_nolock(inode) && !aio_mutex && |
151 | !file->f_mapping->nrpages && pos + length <= i_size_read(inode)) { | 143 | !file->f_mapping->nrpages && pos + length <= i_size_read(inode)) { |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 8c15d0a077e8..b86c8e08399a 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -1145,13 +1145,11 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from) | |||
1145 | { | 1145 | { |
1146 | struct file *file = iocb->ki_filp; | 1146 | struct file *file = iocb->ki_filp; |
1147 | struct address_space *mapping = file->f_mapping; | 1147 | struct address_space *mapping = file->f_mapping; |
1148 | size_t count = iov_iter_count(from); | ||
1149 | ssize_t written = 0; | 1148 | ssize_t written = 0; |
1150 | ssize_t written_buffered = 0; | 1149 | ssize_t written_buffered = 0; |
1151 | struct inode *inode = mapping->host; | 1150 | struct inode *inode = mapping->host; |
1152 | ssize_t err; | 1151 | ssize_t err; |
1153 | loff_t endbyte = 0; | 1152 | loff_t endbyte = 0; |
1154 | loff_t pos = iocb->ki_pos; | ||
1155 | 1153 | ||
1156 | if (get_fuse_conn(inode)->writeback_cache) { | 1154 | if (get_fuse_conn(inode)->writeback_cache) { |
1157 | /* Update size (EOF optimization) and mode (SUID clearing) */ | 1155 | /* Update size (EOF optimization) and mode (SUID clearing) */ |
@@ -1167,14 +1165,10 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from) | |||
1167 | /* We can write back this queue in page reclaim */ | 1165 | /* We can write back this queue in page reclaim */ |
1168 | current->backing_dev_info = inode_to_bdi(inode); | 1166 | current->backing_dev_info = inode_to_bdi(inode); |
1169 | 1167 | ||
1170 | err = generic_write_checks(file, &pos, &count); | 1168 | err = generic_write_checks(iocb, from); |
1171 | if (err) | 1169 | if (err <= 0) |
1172 | goto out; | ||
1173 | |||
1174 | if (count == 0) | ||
1175 | goto out; | 1170 | goto out; |
1176 | 1171 | ||
1177 | iov_iter_truncate(from, count); | ||
1178 | err = file_remove_suid(file); | 1172 | err = file_remove_suid(file); |
1179 | if (err) | 1173 | if (err) |
1180 | goto out; | 1174 | goto out; |
@@ -1184,6 +1178,7 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from) | |||
1184 | goto out; | 1178 | goto out; |
1185 | 1179 | ||
1186 | if (file->f_flags & O_DIRECT) { | 1180 | if (file->f_flags & O_DIRECT) { |
1181 | loff_t pos = iocb->ki_pos; | ||
1187 | written = generic_file_direct_write(iocb, from, pos); | 1182 | written = generic_file_direct_write(iocb, from, pos); |
1188 | if (written < 0 || !iov_iter_count(from)) | 1183 | if (written < 0 || !iov_iter_count(from)) |
1189 | goto out; | 1184 | goto out; |
@@ -1209,9 +1204,9 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from) | |||
1209 | written += written_buffered; | 1204 | written += written_buffered; |
1210 | iocb->ki_pos = pos + written_buffered; | 1205 | iocb->ki_pos = pos + written_buffered; |
1211 | } else { | 1206 | } else { |
1212 | written = fuse_perform_write(file, mapping, from, pos); | 1207 | written = fuse_perform_write(file, mapping, from, iocb->ki_pos); |
1213 | if (written >= 0) | 1208 | if (written >= 0) |
1214 | iocb->ki_pos = pos + written; | 1209 | iocb->ki_pos += written; |
1215 | } | 1210 | } |
1216 | out: | 1211 | out: |
1217 | current->backing_dev_info = NULL; | 1212 | current->backing_dev_info = NULL; |
@@ -1412,7 +1407,6 @@ static ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from) | |||
1412 | struct file *file = iocb->ki_filp; | 1407 | struct file *file = iocb->ki_filp; |
1413 | struct inode *inode = file_inode(file); | 1408 | struct inode *inode = file_inode(file); |
1414 | struct fuse_io_priv io = { .async = 0, .file = file }; | 1409 | struct fuse_io_priv io = { .async = 0, .file = file }; |
1415 | size_t count = iov_iter_count(from); | ||
1416 | ssize_t res; | 1410 | ssize_t res; |
1417 | 1411 | ||
1418 | if (is_bad_inode(inode)) | 1412 | if (is_bad_inode(inode)) |
@@ -1420,11 +1414,9 @@ static ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from) | |||
1420 | 1414 | ||
1421 | /* Don't allow parallel writes to the same file */ | 1415 | /* Don't allow parallel writes to the same file */ |
1422 | mutex_lock(&inode->i_mutex); | 1416 | mutex_lock(&inode->i_mutex); |
1423 | res = generic_write_checks(file, &iocb->ki_pos, &count); | 1417 | res = generic_write_checks(iocb, from); |
1424 | if (!res) { | 1418 | if (res > 0) |
1425 | iov_iter_truncate(from, count); | ||
1426 | res = fuse_direct_io(&io, from, &iocb->ki_pos, FUSE_DIO_WRITE); | 1419 | res = fuse_direct_io(&io, from, &iocb->ki_pos, FUSE_DIO_WRITE); |
1427 | } | ||
1428 | fuse_invalidate_attr(inode); | 1420 | fuse_invalidate_attr(inode); |
1429 | if (res > 0) | 1421 | if (res > 0) |
1430 | fuse_write_update_size(inode, iocb->ki_pos); | 1422 | fuse_write_update_size(inode, iocb->ki_pos); |
diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c index ab6363b16556..011324ce9df2 100644 --- a/fs/ncpfs/file.c +++ b/fs/ncpfs/file.c | |||
@@ -170,20 +170,15 @@ ncp_file_write_iter(struct kiocb *iocb, struct iov_iter *from) | |||
170 | struct file *file = iocb->ki_filp; | 170 | struct file *file = iocb->ki_filp; |
171 | struct inode *inode = file_inode(file); | 171 | struct inode *inode = file_inode(file); |
172 | size_t already_written = 0; | 172 | size_t already_written = 0; |
173 | loff_t pos = iocb->ki_pos; | ||
174 | size_t count = iov_iter_count(from); | ||
175 | size_t bufsize; | 173 | size_t bufsize; |
176 | int errno; | 174 | int errno; |
177 | void *bouncebuffer; | 175 | void *bouncebuffer; |
176 | off_t pos; | ||
178 | 177 | ||
179 | ncp_dbg(1, "enter %pD2\n", file); | 178 | ncp_dbg(1, "enter %pD2\n", file); |
180 | errno = generic_write_checks(file, &pos, &count); | 179 | errno = generic_write_checks(iocb, from); |
181 | if (errno) | 180 | if (errno <= 0) |
182 | return errno; | 181 | return errno; |
183 | iov_iter_truncate(from, count); | ||
184 | |||
185 | if (!count) | ||
186 | return 0; | ||
187 | 182 | ||
188 | errno = ncp_make_open(inode, O_WRONLY); | 183 | errno = ncp_make_open(inode, O_WRONLY); |
189 | if (errno) { | 184 | if (errno) { |
@@ -201,10 +196,11 @@ ncp_file_write_iter(struct kiocb *iocb, struct iov_iter *from) | |||
201 | errno = -EIO; /* -ENOMEM */ | 196 | errno = -EIO; /* -ENOMEM */ |
202 | goto outrel; | 197 | goto outrel; |
203 | } | 198 | } |
199 | pos = iocb->ki_pos; | ||
204 | while (iov_iter_count(from)) { | 200 | while (iov_iter_count(from)) { |
205 | int written_this_time; | 201 | int written_this_time; |
206 | size_t to_write = min_t(size_t, | 202 | size_t to_write = min_t(size_t, |
207 | bufsize - ((off_t)pos % bufsize), | 203 | bufsize - (pos % bufsize), |
208 | iov_iter_count(from)); | 204 | iov_iter_count(from)); |
209 | 205 | ||
210 | if (copy_from_iter(bouncebuffer, to_write, from) != to_write) { | 206 | if (copy_from_iter(bouncebuffer, to_write, from) != to_write) { |
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 5ddd77acb3f7..9634189b8545 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -969,24 +969,19 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter, | |||
969 | struct nfs_direct_req *dreq; | 969 | struct nfs_direct_req *dreq; |
970 | struct nfs_lock_context *l_ctx; | 970 | struct nfs_lock_context *l_ctx; |
971 | loff_t end; | 971 | loff_t end; |
972 | size_t count = iov_iter_count(iter); | ||
973 | end = (pos + count - 1) >> PAGE_CACHE_SHIFT; | ||
974 | |||
975 | nfs_add_stats(mapping->host, NFSIOS_DIRECTWRITTENBYTES, count); | ||
976 | 972 | ||
977 | dfprintk(FILE, "NFS: direct write(%pD2, %zd@%Ld)\n", | 973 | dfprintk(FILE, "NFS: direct write(%pD2, %zd@%Ld)\n", |
978 | file, count, (long long) pos); | 974 | file, iov_iter_count(iter), (long long) iocb->ki_pos); |
979 | 975 | ||
980 | result = generic_write_checks(file, &pos, &count); | 976 | result = generic_write_checks(iocb, iter); |
981 | if (result) | 977 | if (result <= 0) |
982 | goto out; | 978 | goto out; |
983 | 979 | ||
984 | result = -EINVAL; | 980 | nfs_add_stats(mapping->host, NFSIOS_DIRECTWRITTENBYTES, |
985 | if ((ssize_t) count < 0) | 981 | iov_iter_count(iter)); |
986 | goto out; | 982 | |
987 | result = 0; | 983 | pos = iocb->ki_pos; |
988 | if (!count) | 984 | end = (pos + iov_iter_count(iter) - 1) >> PAGE_CACHE_SHIFT; |
989 | goto out; | ||
990 | 985 | ||
991 | mutex_lock(&inode->i_mutex); | 986 | mutex_lock(&inode->i_mutex); |
992 | 987 | ||
@@ -1001,7 +996,7 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter, | |||
1001 | goto out_unlock; | 996 | goto out_unlock; |
1002 | } | 997 | } |
1003 | 998 | ||
1004 | task_io_account_write(count); | 999 | task_io_account_write(iov_iter_count(iter)); |
1005 | 1000 | ||
1006 | result = -ENOMEM; | 1001 | result = -ENOMEM; |
1007 | dreq = nfs_direct_req_alloc(); | 1002 | dreq = nfs_direct_req_alloc(); |
@@ -1009,7 +1004,7 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter, | |||
1009 | goto out_unlock; | 1004 | goto out_unlock; |
1010 | 1005 | ||
1011 | dreq->inode = inode; | 1006 | dreq->inode = inode; |
1012 | dreq->bytes_left = count; | 1007 | dreq->bytes_left = iov_iter_count(iter); |
1013 | dreq->io_start = pos; | 1008 | dreq->io_start = pos; |
1014 | dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp)); | 1009 | dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp)); |
1015 | l_ctx = nfs_get_lock_context(dreq->ctx); | 1010 | l_ctx = nfs_get_lock_context(dreq->ctx); |
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c index cec4ec3c1ede..7bb487e663b4 100644 --- a/fs/ntfs/file.c +++ b/fs/ntfs/file.c | |||
@@ -339,17 +339,14 @@ static ssize_t ntfs_prepare_file_for_write(struct kiocb *iocb, | |||
339 | struct inode *vi = file_inode(file); | 339 | struct inode *vi = file_inode(file); |
340 | ntfs_inode *base_ni, *ni = NTFS_I(vi); | 340 | ntfs_inode *base_ni, *ni = NTFS_I(vi); |
341 | ntfs_volume *vol = ni->vol; | 341 | ntfs_volume *vol = ni->vol; |
342 | size_t count = iov_iter_count(from); | ||
343 | 342 | ||
344 | ntfs_debug("Entering for i_ino 0x%lx, attribute type 0x%x, pos " | 343 | ntfs_debug("Entering for i_ino 0x%lx, attribute type 0x%x, pos " |
345 | "0x%llx, count 0x%zx.", vi->i_ino, | 344 | "0x%llx, count 0x%zx.", vi->i_ino, |
346 | (unsigned)le32_to_cpu(ni->type), | 345 | (unsigned)le32_to_cpu(ni->type), |
347 | (unsigned long long)iocb->ki_pos, count); | 346 | (unsigned long long)iocb->ki_pos, |
348 | err = generic_write_checks(file, &iocb->ki_pos, &count); | 347 | iov_iter_count(from)); |
349 | if (unlikely(err)) | 348 | err = generic_write_checks(iocb, from); |
350 | goto out; | 349 | if (unlikely(err <= 0)) |
351 | iov_iter_truncate(from, count); | ||
352 | if (count == 0) | ||
353 | goto out; | 350 | goto out; |
354 | /* | 351 | /* |
355 | * All checks have passed. Before we start doing any writing we want | 352 | * All checks have passed. Before we start doing any writing we want |
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index fc53ff065364..b93919f50f0f 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
@@ -2250,9 +2250,10 @@ out: | |||
2250 | static ssize_t ocfs2_file_write_iter(struct kiocb *iocb, | 2250 | static ssize_t ocfs2_file_write_iter(struct kiocb *iocb, |
2251 | struct iov_iter *from) | 2251 | struct iov_iter *from) |
2252 | { | 2252 | { |
2253 | int ret, direct_io, appending, rw_level, have_alloc_sem = 0; | 2253 | int direct_io, appending, rw_level, have_alloc_sem = 0; |
2254 | int can_do_direct, has_refcount = 0; | 2254 | int can_do_direct, has_refcount = 0; |
2255 | ssize_t written = 0; | 2255 | ssize_t written = 0; |
2256 | ssize_t ret; | ||
2256 | size_t count = iov_iter_count(from), orig_count; | 2257 | size_t count = iov_iter_count(from), orig_count; |
2257 | loff_t old_size; | 2258 | loff_t old_size; |
2258 | u32 old_clusters; | 2259 | u32 old_clusters; |
@@ -2319,13 +2320,14 @@ relock: | |||
2319 | ocfs2_inode_unlock(inode, 1); | 2320 | ocfs2_inode_unlock(inode, 1); |
2320 | } | 2321 | } |
2321 | 2322 | ||
2322 | orig_count = count; | 2323 | orig_count = iov_iter_count(from); |
2323 | ret = generic_write_checks(file, &iocb->ki_pos, &count); | 2324 | ret = generic_write_checks(iocb, from); |
2324 | if (ret < 0) { | 2325 | if (ret <= 0) { |
2325 | mlog_errno(ret); | 2326 | if (ret) |
2327 | mlog_errno(ret); | ||
2326 | goto out; | 2328 | goto out; |
2327 | } | 2329 | } |
2328 | iov_iter_truncate(from, count); | 2330 | count = ret; |
2329 | 2331 | ||
2330 | can_do_direct = direct_io; | 2332 | can_do_direct = direct_io; |
2331 | ret = ocfs2_prepare_inode_for_write(file, iocb->ki_pos, count, appending, | 2333 | ret = ocfs2_prepare_inode_for_write(file, iocb->ki_pos, count, appending, |
@@ -2349,7 +2351,7 @@ relock: | |||
2349 | rw_level = -1; | 2351 | rw_level = -1; |
2350 | 2352 | ||
2351 | direct_io = 0; | 2353 | direct_io = 0; |
2352 | iov_iter_reexpand(from, count = orig_count); | 2354 | iov_iter_reexpand(from, orig_count); |
2353 | goto relock; | 2355 | goto relock; |
2354 | } | 2356 | } |
2355 | 2357 | ||
@@ -2377,7 +2379,7 @@ relock: | |||
2377 | loff_t endbyte; | 2379 | loff_t endbyte; |
2378 | ssize_t written_buffered; | 2380 | ssize_t written_buffered; |
2379 | written = generic_file_direct_write(iocb, from, iocb->ki_pos); | 2381 | written = generic_file_direct_write(iocb, from, iocb->ki_pos); |
2380 | if (written < 0 || written == count) { | 2382 | if (written < 0 || !iov_iter_count(from)) { |
2381 | ret = written; | 2383 | ret = written; |
2382 | goto out_dio; | 2384 | goto out_dio; |
2383 | } | 2385 | } |
@@ -2385,7 +2387,6 @@ relock: | |||
2385 | /* | 2387 | /* |
2386 | * for completing the rest of the request. | 2388 | * for completing the rest of the request. |
2387 | */ | 2389 | */ |
2388 | count -= written; | ||
2389 | written_buffered = generic_perform_write(file, from, iocb->ki_pos); | 2390 | written_buffered = generic_perform_write(file, from, iocb->ki_pos); |
2390 | /* | 2391 | /* |
2391 | * If generic_file_buffered_write() returned a synchronous error | 2392 | * If generic_file_buffered_write() returned a synchronous error |
diff --git a/fs/udf/file.c b/fs/udf/file.c index ccab8b78e363..3de2edafff73 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c | |||
@@ -120,21 +120,15 @@ static ssize_t udf_file_write_iter(struct kiocb *iocb, struct iov_iter *from) | |||
120 | ssize_t retval; | 120 | ssize_t retval; |
121 | struct file *file = iocb->ki_filp; | 121 | struct file *file = iocb->ki_filp; |
122 | struct inode *inode = file_inode(file); | 122 | struct inode *inode = file_inode(file); |
123 | size_t count = iov_iter_count(from); | ||
124 | struct udf_inode_info *iinfo = UDF_I(inode); | 123 | struct udf_inode_info *iinfo = UDF_I(inode); |
125 | int err; | 124 | int err; |
126 | 125 | ||
127 | mutex_lock(&inode->i_mutex); | 126 | mutex_lock(&inode->i_mutex); |
128 | 127 | ||
129 | retval = generic_write_checks(file, &iocb->ki_pos, &count); | 128 | retval = generic_write_checks(iocb, from); |
130 | if (retval) | 129 | if (retval <= 0) |
131 | goto out; | 130 | goto out; |
132 | 131 | ||
133 | if (count == 0) | ||
134 | goto out; | ||
135 | |||
136 | iov_iter_truncate(from, count); | ||
137 | |||
138 | down_write(&iinfo->i_data_sem); | 132 | down_write(&iinfo->i_data_sem); |
139 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { | 133 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { |
140 | loff_t end = iocb->ki_pos + iov_iter_count(from); | 134 | loff_t end = iocb->ki_pos + iov_iter_count(from); |
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index ebde43e15dd9..28d157807b42 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c | |||
@@ -551,12 +551,12 @@ xfs_file_aio_write_checks( | |||
551 | struct file *file = iocb->ki_filp; | 551 | struct file *file = iocb->ki_filp; |
552 | struct inode *inode = file->f_mapping->host; | 552 | struct inode *inode = file->f_mapping->host; |
553 | struct xfs_inode *ip = XFS_I(inode); | 553 | struct xfs_inode *ip = XFS_I(inode); |
554 | int error = 0; | 554 | ssize_t error = 0; |
555 | size_t count = iov_iter_count(from); | 555 | size_t count = iov_iter_count(from); |
556 | 556 | ||
557 | restart: | 557 | restart: |
558 | error = generic_write_checks(file, &iocb->ki_pos, &count); | 558 | error = generic_write_checks(iocb, from); |
559 | if (error) | 559 | if (error <= 0) |
560 | return error; | 560 | return error; |
561 | 561 | ||
562 | error = xfs_break_layouts(inode, iolock); | 562 | error = xfs_break_layouts(inode, iolock); |
@@ -577,13 +577,13 @@ restart: | |||
577 | xfs_rw_iunlock(ip, *iolock); | 577 | xfs_rw_iunlock(ip, *iolock); |
578 | *iolock = XFS_IOLOCK_EXCL; | 578 | *iolock = XFS_IOLOCK_EXCL; |
579 | xfs_rw_ilock(ip, *iolock); | 579 | xfs_rw_ilock(ip, *iolock); |
580 | iov_iter_reexpand(from, count); | ||
580 | goto restart; | 581 | goto restart; |
581 | } | 582 | } |
582 | error = xfs_zero_eof(ip, iocb->ki_pos, i_size_read(inode), &zero); | 583 | error = xfs_zero_eof(ip, iocb->ki_pos, i_size_read(inode), &zero); |
583 | if (error) | 584 | if (error) |
584 | return error; | 585 | return error; |
585 | } | 586 | } |
586 | iov_iter_truncate(from, count); | ||
587 | 587 | ||
588 | /* | 588 | /* |
589 | * Updating the timestamps will grab the ilock again from | 589 | * Updating the timestamps will grab the ilock again from |
diff --git a/include/linux/fs.h b/include/linux/fs.h index c7b21db7782f..b4aa400ac723 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -2566,7 +2566,7 @@ extern int sb_min_blocksize(struct super_block *, int); | |||
2566 | 2566 | ||
2567 | extern int generic_file_mmap(struct file *, struct vm_area_struct *); | 2567 | extern int generic_file_mmap(struct file *, struct vm_area_struct *); |
2568 | extern int generic_file_readonly_mmap(struct file *, struct vm_area_struct *); | 2568 | extern int generic_file_readonly_mmap(struct file *, struct vm_area_struct *); |
2569 | int generic_write_checks(struct file *file, loff_t *pos, size_t *count); | 2569 | extern ssize_t generic_write_checks(struct kiocb *, struct iov_iter *); |
2570 | extern ssize_t generic_file_read_iter(struct kiocb *, struct iov_iter *); | 2570 | extern ssize_t generic_file_read_iter(struct kiocb *, struct iov_iter *); |
2571 | extern ssize_t __generic_file_write_iter(struct kiocb *, struct iov_iter *); | 2571 | extern ssize_t __generic_file_write_iter(struct kiocb *, struct iov_iter *); |
2572 | extern ssize_t generic_file_write_iter(struct kiocb *, struct iov_iter *); | 2572 | extern ssize_t generic_file_write_iter(struct kiocb *, struct iov_iter *); |
diff --git a/mm/filemap.c b/mm/filemap.c index dfc573c6ec25..243997a26e7c 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
@@ -2260,36 +2260,38 @@ EXPORT_SYMBOL(read_cache_page_gfp); | |||
2260 | * Returns appropriate error code that caller should return or | 2260 | * Returns appropriate error code that caller should return or |
2261 | * zero in case that write should be allowed. | 2261 | * zero in case that write should be allowed. |
2262 | */ | 2262 | */ |
2263 | inline int generic_write_checks(struct file *file, loff_t *pos, size_t *count) | 2263 | inline ssize_t generic_write_checks(struct kiocb *iocb, struct iov_iter *from) |
2264 | { | 2264 | { |
2265 | struct file *file = iocb->ki_filp; | ||
2265 | struct inode *inode = file->f_mapping->host; | 2266 | struct inode *inode = file->f_mapping->host; |
2266 | unsigned long limit = rlimit(RLIMIT_FSIZE); | 2267 | unsigned long limit = rlimit(RLIMIT_FSIZE); |
2268 | loff_t pos; | ||
2267 | 2269 | ||
2268 | if (unlikely(*pos < 0)) | 2270 | if (!iov_iter_count(from)) |
2269 | return -EINVAL; | 2271 | return 0; |
2270 | 2272 | ||
2271 | /* FIXME: this is for backwards compatibility with 2.4 */ | 2273 | /* FIXME: this is for backwards compatibility with 2.4 */ |
2272 | if (file->f_flags & O_APPEND) | 2274 | if (file->f_flags & O_APPEND) |
2273 | *pos = i_size_read(inode); | 2275 | iocb->ki_pos = i_size_read(inode); |
2276 | |||
2277 | pos = iocb->ki_pos; | ||
2274 | 2278 | ||
2275 | if (limit != RLIM_INFINITY) { | 2279 | if (limit != RLIM_INFINITY) { |
2276 | if (*pos >= limit) { | 2280 | if (iocb->ki_pos >= limit) { |
2277 | send_sig(SIGXFSZ, current, 0); | 2281 | send_sig(SIGXFSZ, current, 0); |
2278 | return -EFBIG; | 2282 | return -EFBIG; |
2279 | } | 2283 | } |
2280 | if (*count > limit - (typeof(limit))*pos) | 2284 | iov_iter_truncate(from, limit - (unsigned long)pos); |
2281 | *count = limit - (typeof(limit))*pos; | ||
2282 | } | 2285 | } |
2283 | 2286 | ||
2284 | /* | 2287 | /* |
2285 | * LFS rule | 2288 | * LFS rule |
2286 | */ | 2289 | */ |
2287 | if (unlikely(*pos + *count > MAX_NON_LFS && | 2290 | if (unlikely(pos + iov_iter_count(from) > MAX_NON_LFS && |
2288 | !(file->f_flags & O_LARGEFILE))) { | 2291 | !(file->f_flags & O_LARGEFILE))) { |
2289 | if (*pos >= MAX_NON_LFS) | 2292 | if (pos >= MAX_NON_LFS) |
2290 | return -EFBIG; | 2293 | return -EFBIG; |
2291 | if (*count > MAX_NON_LFS - (unsigned long)*pos) | 2294 | iov_iter_truncate(from, MAX_NON_LFS - (unsigned long)pos); |
2292 | *count = MAX_NON_LFS - (unsigned long)*pos; | ||
2293 | } | 2295 | } |
2294 | 2296 | ||
2295 | /* | 2297 | /* |
@@ -2299,16 +2301,11 @@ inline int generic_write_checks(struct file *file, loff_t *pos, size_t *count) | |||
2299 | * exceeded without writing data we send a signal and return EFBIG. | 2301 | * exceeded without writing data we send a signal and return EFBIG. |
2300 | * Linus frestrict idea will clean these up nicely.. | 2302 | * Linus frestrict idea will clean these up nicely.. |
2301 | */ | 2303 | */ |
2302 | if (unlikely(*pos >= inode->i_sb->s_maxbytes)) { | 2304 | if (unlikely(pos >= inode->i_sb->s_maxbytes)) |
2303 | if (*count || *pos > inode->i_sb->s_maxbytes) { | 2305 | return -EFBIG; |
2304 | return -EFBIG; | ||
2305 | } | ||
2306 | /* zero-length writes at ->s_maxbytes are OK */ | ||
2307 | } | ||
2308 | 2306 | ||
2309 | if (unlikely(*pos + *count > inode->i_sb->s_maxbytes)) | 2307 | iov_iter_truncate(from, inode->i_sb->s_maxbytes - pos); |
2310 | *count = inode->i_sb->s_maxbytes - *pos; | 2308 | return iov_iter_count(from); |
2311 | return 0; | ||
2312 | } | 2309 | } |
2313 | EXPORT_SYMBOL(generic_write_checks); | 2310 | EXPORT_SYMBOL(generic_write_checks); |
2314 | 2311 | ||
@@ -2618,14 +2615,11 @@ ssize_t generic_file_write_iter(struct kiocb *iocb, struct iov_iter *from) | |||
2618 | struct file *file = iocb->ki_filp; | 2615 | struct file *file = iocb->ki_filp; |
2619 | struct inode *inode = file->f_mapping->host; | 2616 | struct inode *inode = file->f_mapping->host; |
2620 | ssize_t ret; | 2617 | ssize_t ret; |
2621 | size_t count = iov_iter_count(from); | ||
2622 | 2618 | ||
2623 | mutex_lock(&inode->i_mutex); | 2619 | mutex_lock(&inode->i_mutex); |
2624 | ret = generic_write_checks(file, &iocb->ki_pos, &count); | 2620 | ret = generic_write_checks(iocb, from); |
2625 | if (!ret && count) { | 2621 | if (ret > 0) |
2626 | iov_iter_truncate(from, count); | ||
2627 | ret = __generic_file_write_iter(iocb, from); | 2622 | ret = __generic_file_write_iter(iocb, from); |
2628 | } | ||
2629 | mutex_unlock(&inode->i_mutex); | 2623 | mutex_unlock(&inode->i_mutex); |
2630 | 2624 | ||
2631 | if (ret > 0) { | 2625 | if (ret > 0) { |