Commit 3309dd04 authored by Al Viro's avatar Al Viro

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: default avatarAl Viro <viro@zeniv.linux.org.uk>

Conflicts:
	fs/ext4/file.c
parent 90320251
...@@ -404,21 +404,16 @@ static ssize_t ...@@ -404,21 +404,16 @@ static ssize_t
v9fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) v9fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
{ {
struct file *file = iocb->ki_filp; struct file *file = iocb->ki_filp;
ssize_t retval = 0; ssize_t retval;
loff_t origin = iocb->ki_pos; loff_t origin;
size_t count = iov_iter_count(from);
int err = 0; int err = 0;
retval = generic_write_checks(file, &origin, &count); retval = generic_write_checks(iocb, from);
if (retval) if (retval <= 0)
return retval; return retval;
iov_iter_truncate(from, count); origin = iocb->ki_pos;
retval = p9_client_write(file->private_data, iocb->ki_pos, from, &err);
if (!count)
return 0;
retval = p9_client_write(file->private_data, origin, from, &err);
if (retval > 0) { if (retval > 0) {
struct inode *inode = file_inode(file); struct inode *inode = file_inode(file);
loff_t i_size; loff_t i_size;
...@@ -428,12 +423,11 @@ v9fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) ...@@ -428,12 +423,11 @@ v9fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
if (inode->i_mapping && inode->i_mapping->nrpages) if (inode->i_mapping && inode->i_mapping->nrpages)
invalidate_inode_pages2_range(inode->i_mapping, invalidate_inode_pages2_range(inode->i_mapping,
pg_start, pg_end); pg_start, pg_end);
origin += retval; iocb->ki_pos += retval;
i_size = i_size_read(inode); i_size = i_size_read(inode);
iocb->ki_pos = origin; if (iocb->ki_pos > i_size) {
if (origin > i_size) { inode_add_bytes(inode, iocb->ki_pos - i_size);
inode_add_bytes(inode, origin - i_size); i_size_write(inode, iocb->ki_pos);
i_size_write(inode, origin);
} }
return retval; return retval;
} }
......
...@@ -1739,27 +1739,19 @@ static ssize_t btrfs_file_write_iter(struct kiocb *iocb, ...@@ -1739,27 +1739,19 @@ static ssize_t btrfs_file_write_iter(struct kiocb *iocb,
u64 start_pos; u64 start_pos;
u64 end_pos; u64 end_pos;
ssize_t num_written = 0; ssize_t num_written = 0;
ssize_t err = 0;
size_t count = iov_iter_count(from);
bool sync = (file->f_flags & O_DSYNC) || IS_SYNC(file->f_mapping->host); bool sync = (file->f_flags & O_DSYNC) || IS_SYNC(file->f_mapping->host);
loff_t pos = iocb->ki_pos; ssize_t err;
loff_t pos;
size_t count;
mutex_lock(&inode->i_mutex); mutex_lock(&inode->i_mutex);
err = generic_write_checks(iocb, from);
current->backing_dev_info = inode_to_bdi(inode); if (err <= 0) {
err = generic_write_checks(file, &pos, &count);
if (err) {
mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex);
goto out; return err;
}
if (count == 0) {
mutex_unlock(&inode->i_mutex);
goto out;
} }
iov_iter_truncate(from, count); current->backing_dev_info = inode_to_bdi(inode);
err = file_remove_suid(file); err = file_remove_suid(file);
if (err) { if (err) {
mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex);
...@@ -1786,6 +1778,8 @@ static ssize_t btrfs_file_write_iter(struct kiocb *iocb, ...@@ -1786,6 +1778,8 @@ static ssize_t btrfs_file_write_iter(struct kiocb *iocb,
*/ */
update_time_for_write(inode); update_time_for_write(inode);
pos = iocb->ki_pos;
count = iov_iter_count(from);
start_pos = round_down(pos, root->sectorsize); start_pos = round_down(pos, root->sectorsize);
if (start_pos > i_size_read(inode)) { if (start_pos > i_size_read(inode)) {
/* Expand hole size to cover write data, preventing empty gap */ /* Expand hole size to cover write data, preventing empty gap */
......
...@@ -941,9 +941,9 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from) ...@@ -941,9 +941,9 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
struct ceph_inode_info *ci = ceph_inode(inode); struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_osd_client *osdc = struct ceph_osd_client *osdc =
&ceph_sb_to_client(inode->i_sb)->client->osdc; &ceph_sb_to_client(inode->i_sb)->client->osdc;
ssize_t count = iov_iter_count(from), written = 0; ssize_t count, written = 0;
int err, want, got; int err, want, got;
loff_t pos = iocb->ki_pos; loff_t pos;
if (ceph_snap(inode) != CEPH_NOSNAP) if (ceph_snap(inode) != CEPH_NOSNAP)
return -EROFS; return -EROFS;
...@@ -953,14 +953,12 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from) ...@@ -953,14 +953,12 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
/* We can write back this queue in page reclaim */ /* We can write back this queue in page reclaim */
current->backing_dev_info = inode_to_bdi(inode); current->backing_dev_info = inode_to_bdi(inode);
err = generic_write_checks(file, &pos, &count); err = generic_write_checks(iocb, from);
if (err) if (err <= 0)
goto out;
if (count == 0)
goto out; goto out;
iov_iter_truncate(from, count);
pos = iocb->ki_pos;
count = iov_iter_count(from);
err = file_remove_suid(file); err = file_remove_suid(file);
if (err) if (err)
goto out; goto out;
......
...@@ -2563,7 +2563,6 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from, ...@@ -2563,7 +2563,6 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from,
ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from) ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from)
{ {
struct file *file = iocb->ki_filp; struct file *file = iocb->ki_filp;
size_t len;
ssize_t total_written = 0; ssize_t total_written = 0;
struct cifsFileInfo *open_file; struct cifsFileInfo *open_file;
struct cifs_tcon *tcon; struct cifs_tcon *tcon;
...@@ -2579,16 +2578,10 @@ ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from) ...@@ -2579,16 +2578,10 @@ ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from)
* write request. * write request.
*/ */
len = iov_iter_count(from); rc = generic_write_checks(iocb, from);
rc = generic_write_checks(file, &iocb->ki_pos, &len); if (rc <= 0)
if (rc)
return rc; return rc;
if (!len)
return 0;
iov_iter_truncate(from, len);
INIT_LIST_HEAD(&wdata_list); INIT_LIST_HEAD(&wdata_list);
cifs_sb = CIFS_FILE_SB(file); cifs_sb = CIFS_FILE_SB(file);
open_file = file->private_data; open_file = file->private_data;
...@@ -2599,8 +2592,8 @@ ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from) ...@@ -2599,8 +2592,8 @@ ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from)
memcpy(&saved_from, from, sizeof(struct iov_iter)); memcpy(&saved_from, from, sizeof(struct iov_iter));
rc = cifs_write_from_iter(iocb->ki_pos, len, from, open_file, cifs_sb, rc = cifs_write_from_iter(iocb->ki_pos, iov_iter_count(from), from,
&wdata_list); open_file, cifs_sb, &wdata_list);
/* /*
* If at least one write was successfully sent, then discard any rc * 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,7 +2667,6 @@ cifs_writev(struct kiocb *iocb, struct iov_iter *from)
struct cifsInodeInfo *cinode = CIFS_I(inode); struct cifsInodeInfo *cinode = CIFS_I(inode);
struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server; struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server;
ssize_t rc; ssize_t rc;
size_t count;
/* /*
* We need to hold the sem to be sure nobody modifies lock list * 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,16 +2675,10 @@ cifs_writev(struct kiocb *iocb, struct iov_iter *from)
down_read(&cinode->lock_sem); down_read(&cinode->lock_sem);
mutex_lock(&inode->i_mutex); mutex_lock(&inode->i_mutex);
count = iov_iter_count(from); rc = generic_write_checks(iocb, from);
rc = generic_write_checks(file, &iocb->ki_pos, &count); if (rc <= 0)
if (rc)
goto out; goto out;
if (count == 0)
goto out;
iov_iter_truncate(from, count);
if (!cifs_find_lock_conflict(cfile, iocb->ki_pos, iov_iter_count(from), if (!cifs_find_lock_conflict(cfile, iocb->ki_pos, iov_iter_count(from),
server->vals->exclusive_lock_type, NULL, server->vals->exclusive_lock_type, NULL,
CIFS_WRITE_OP)) CIFS_WRITE_OP))
......
...@@ -97,9 +97,7 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from) ...@@ -97,9 +97,7 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
struct blk_plug plug; struct blk_plug plug;
int o_direct = io_is_direct(file); int o_direct = io_is_direct(file);
int overwrite = 0; int overwrite = 0;
size_t length = iov_iter_count(from);
ssize_t ret; ssize_t ret;
loff_t pos;
/* /*
* Unaligned direct AIO must be serialized; see comment above * 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,16 +114,10 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
} }
mutex_lock(&inode->i_mutex); mutex_lock(&inode->i_mutex);
ret = generic_write_checks(file, &iocb->ki_pos, &length); ret = generic_write_checks(iocb, from);
if (ret) if (ret <= 0)
goto out; goto out;
if (length == 0)
goto out;
iov_iter_truncate(from, length);
pos = iocb->ki_pos;
/* /*
* If we have encountered a bitmap-format file, the size limit * If we have encountered a bitmap-format file, the size limit
* is smaller than s_maxbytes, which is for extent-mapped files. * 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,19 +125,19 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) { if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) {
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
if (pos >= sbi->s_bitmap_maxbytes) { if (iocb->ki_pos >= sbi->s_bitmap_maxbytes) {
ret = -EFBIG; ret = -EFBIG;
goto out; goto out;
} }
iov_iter_truncate(from, sbi->s_bitmap_maxbytes - pos); iov_iter_truncate(from, sbi->s_bitmap_maxbytes - iocb->ki_pos);
} }
iocb->private = &overwrite; iocb->private = &overwrite;
if (o_direct) { if (o_direct) {
length = iov_iter_count(from); size_t length = iov_iter_count(from);
loff_t pos = iocb->ki_pos;
blk_start_plug(&plug); blk_start_plug(&plug);
/* check whether we do a DIO overwrite or not */ /* check whether we do a DIO overwrite or not */
if (ext4_should_dioread_nolock(inode) && !aio_mutex && if (ext4_should_dioread_nolock(inode) && !aio_mutex &&
!file->f_mapping->nrpages && pos + length <= i_size_read(inode)) { !file->f_mapping->nrpages && pos + length <= i_size_read(inode)) {
......
...@@ -1145,13 +1145,11 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from) ...@@ -1145,13 +1145,11 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
{ {
struct file *file = iocb->ki_filp; struct file *file = iocb->ki_filp;
struct address_space *mapping = file->f_mapping; struct address_space *mapping = file->f_mapping;
size_t count = iov_iter_count(from);
ssize_t written = 0; ssize_t written = 0;
ssize_t written_buffered = 0; ssize_t written_buffered = 0;
struct inode *inode = mapping->host; struct inode *inode = mapping->host;
ssize_t err; ssize_t err;
loff_t endbyte = 0; loff_t endbyte = 0;
loff_t pos = iocb->ki_pos;
if (get_fuse_conn(inode)->writeback_cache) { if (get_fuse_conn(inode)->writeback_cache) {
/* Update size (EOF optimization) and mode (SUID clearing) */ /* 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,14 +1165,10 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
/* We can write back this queue in page reclaim */ /* We can write back this queue in page reclaim */
current->backing_dev_info = inode_to_bdi(inode); current->backing_dev_info = inode_to_bdi(inode);
err = generic_write_checks(file, &pos, &count); err = generic_write_checks(iocb, from);
if (err) if (err <= 0)
goto out;
if (count == 0)
goto out; goto out;
iov_iter_truncate(from, count);
err = file_remove_suid(file); err = file_remove_suid(file);
if (err) if (err)
goto out; goto out;
...@@ -1184,6 +1178,7 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from) ...@@ -1184,6 +1178,7 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
goto out; goto out;
if (file->f_flags & O_DIRECT) { if (file->f_flags & O_DIRECT) {
loff_t pos = iocb->ki_pos;
written = generic_file_direct_write(iocb, from, pos); written = generic_file_direct_write(iocb, from, pos);
if (written < 0 || !iov_iter_count(from)) if (written < 0 || !iov_iter_count(from))
goto out; goto out;
...@@ -1209,9 +1204,9 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from) ...@@ -1209,9 +1204,9 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
written += written_buffered; written += written_buffered;
iocb->ki_pos = pos + written_buffered; iocb->ki_pos = pos + written_buffered;
} else { } else {
written = fuse_perform_write(file, mapping, from, pos); written = fuse_perform_write(file, mapping, from, iocb->ki_pos);
if (written >= 0) if (written >= 0)
iocb->ki_pos = pos + written; iocb->ki_pos += written;
} }
out: out:
current->backing_dev_info = NULL; current->backing_dev_info = NULL;
...@@ -1412,7 +1407,6 @@ static ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from) ...@@ -1412,7 +1407,6 @@ static ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from)
struct file *file = iocb->ki_filp; struct file *file = iocb->ki_filp;
struct inode *inode = file_inode(file); struct inode *inode = file_inode(file);
struct fuse_io_priv io = { .async = 0, .file = file }; struct fuse_io_priv io = { .async = 0, .file = file };
size_t count = iov_iter_count(from);
ssize_t res; ssize_t res;
if (is_bad_inode(inode)) if (is_bad_inode(inode))
...@@ -1420,11 +1414,9 @@ static ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from) ...@@ -1420,11 +1414,9 @@ static ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from)
/* Don't allow parallel writes to the same file */ /* Don't allow parallel writes to the same file */
mutex_lock(&inode->i_mutex); mutex_lock(&inode->i_mutex);
res = generic_write_checks(file, &iocb->ki_pos, &count); res = generic_write_checks(iocb, from);
if (!res) { if (res > 0)
iov_iter_truncate(from, count);
res = fuse_direct_io(&io, from, &iocb->ki_pos, FUSE_DIO_WRITE); res = fuse_direct_io(&io, from, &iocb->ki_pos, FUSE_DIO_WRITE);
}
fuse_invalidate_attr(inode); fuse_invalidate_attr(inode);
if (res > 0) if (res > 0)
fuse_write_update_size(inode, iocb->ki_pos); fuse_write_update_size(inode, iocb->ki_pos);
......
...@@ -170,20 +170,15 @@ ncp_file_write_iter(struct kiocb *iocb, struct iov_iter *from) ...@@ -170,20 +170,15 @@ ncp_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
struct file *file = iocb->ki_filp; struct file *file = iocb->ki_filp;
struct inode *inode = file_inode(file); struct inode *inode = file_inode(file);
size_t already_written = 0; size_t already_written = 0;
loff_t pos = iocb->ki_pos;
size_t count = iov_iter_count(from);
size_t bufsize; size_t bufsize;
int errno; int errno;
void *bouncebuffer; void *bouncebuffer;
off_t pos;
ncp_dbg(1, "enter %pD2\n", file); ncp_dbg(1, "enter %pD2\n", file);
errno = generic_write_checks(file, &pos, &count); errno = generic_write_checks(iocb, from);
if (errno) if (errno <= 0)
return errno; return errno;
iov_iter_truncate(from, count);
if (!count)
return 0;
errno = ncp_make_open(inode, O_WRONLY); errno = ncp_make_open(inode, O_WRONLY);
if (errno) { if (errno) {
...@@ -201,10 +196,11 @@ ncp_file_write_iter(struct kiocb *iocb, struct iov_iter *from) ...@@ -201,10 +196,11 @@ ncp_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
errno = -EIO; /* -ENOMEM */ errno = -EIO; /* -ENOMEM */
goto outrel; goto outrel;
} }
pos = iocb->ki_pos;
while (iov_iter_count(from)) { while (iov_iter_count(from)) {
int written_this_time; int written_this_time;
size_t to_write = min_t(size_t, size_t to_write = min_t(size_t,
bufsize - ((off_t)pos % bufsize), bufsize - (pos % bufsize),
iov_iter_count(from)); iov_iter_count(from));
if (copy_from_iter(bouncebuffer, to_write, from) != to_write) { if (copy_from_iter(bouncebuffer, to_write, from) != to_write) {
......
...@@ -969,24 +969,19 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter, ...@@ -969,24 +969,19 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter,
struct nfs_direct_req *dreq; struct nfs_direct_req *dreq;
struct nfs_lock_context *l_ctx; struct nfs_lock_context *l_ctx;
loff_t end; loff_t end;
size_t count = iov_iter_count(iter);
end = (pos + count - 1) >> PAGE_CACHE_SHIFT;
nfs_add_stats(mapping->host, NFSIOS_DIRECTWRITTENBYTES, count);
dfprintk(FILE, "NFS: direct write(%pD2, %zd@%Ld)\n", dfprintk(FILE, "NFS: direct write(%pD2, %zd@%Ld)\n",
file, count, (long long) pos); file, iov_iter_count(iter), (long long) iocb->ki_pos);
result = generic_write_checks(file, &pos, &count); result = generic_write_checks(iocb, iter);
if (result) if (result <= 0)
goto out; goto out;
result = -EINVAL; nfs_add_stats(mapping->host, NFSIOS_DIRECTWRITTENBYTES,
if ((ssize_t) count < 0) iov_iter_count(iter));
goto out;
result = 0; pos = iocb->ki_pos;
if (!count) end = (pos + iov_iter_count(iter) - 1) >> PAGE_CACHE_SHIFT;
goto out;
mutex_lock(&inode->i_mutex); mutex_lock(&inode->i_mutex);
...@@ -1001,7 +996,7 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter, ...@@ -1001,7 +996,7 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter,
goto out_unlock; goto out_unlock;
} }
task_io_account_write(count); task_io_account_write(iov_iter_count(iter));
result = -ENOMEM; result = -ENOMEM;
dreq = nfs_direct_req_alloc(); dreq = nfs_direct_req_alloc();
...@@ -1009,7 +1004,7 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter, ...@@ -1009,7 +1004,7 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter,
goto out_unlock; goto out_unlock;
dreq->inode = inode; dreq->inode = inode;
dreq->bytes_left = count; dreq->bytes_left = iov_iter_count(iter);
dreq->io_start = pos; dreq->io_start = pos;
dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp)); dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp));
l_ctx = nfs_get_lock_context(dreq->ctx); l_ctx = nfs_get_lock_context(dreq->ctx);
......
...@@ -339,17 +339,14 @@ static ssize_t ntfs_prepare_file_for_write(struct kiocb *iocb, ...@@ -339,17 +339,14 @@ static ssize_t ntfs_prepare_file_for_write(struct kiocb *iocb,
struct inode *vi = file_inode(file); struct inode *vi = file_inode(file);
ntfs_inode *base_ni, *ni = NTFS_I(vi); ntfs_inode *base_ni, *ni = NTFS_I(vi);
ntfs_volume *vol = ni->vol; ntfs_volume *vol = ni->vol;
size_t count = iov_iter_count(from);
ntfs_debug("Entering for i_ino 0x%lx, attribute type 0x%x, pos " ntfs_debug("Entering for i_ino 0x%lx, attribute type 0x%x, pos "
"0x%llx, count 0x%zx.", vi->i_ino, "0x%llx, count 0x%zx.", vi->i_ino,
(unsigned)le32_to_cpu(ni->type), (unsigned)le32_to_cpu(ni->type),
(unsigned long long)iocb->ki_pos, count); (unsigned long long)iocb->ki_pos,
err = generic_write_checks(file, &iocb->ki_pos, &count); iov_iter_count(from));
if (unlikely(err)) err = generic_write_checks(iocb, from);
goto out; if (unlikely(err <= 0))
iov_iter_truncate(from, count);
if (count == 0)
goto out; goto out;
/* /*
* All checks have passed. Before we start doing any writing we want * All checks have passed. Before we start doing any writing we want
......
...@@ -2250,9 +2250,10 @@ static int ocfs2_prepare_inode_for_write(struct file *file, ...@@ -2250,9 +2250,10 @@ static int ocfs2_prepare_inode_for_write(struct file *file,
static ssize_t ocfs2_file_write_iter(struct kiocb *iocb, static ssize_t ocfs2_file_write_iter(struct kiocb *iocb,
struct iov_iter *from) struct iov_iter *from)
{ {
int ret, direct_io, appending, rw_level, have_alloc_sem = 0; int direct_io, appending, rw_level, have_alloc_sem = 0;
int can_do_direct, has_refcount = 0; int can_do_direct, has_refcount = 0;
ssize_t written = 0; ssize_t written = 0;
ssize_t ret;
size_t count = iov_iter_count(from), orig_count; size_t count = iov_iter_count(from), orig_count;
loff_t old_size; loff_t old_size;
u32 old_clusters; u32 old_clusters;
...@@ -2319,13 +2320,14 @@ static ssize_t ocfs2_file_write_iter(struct kiocb *iocb, ...@@ -2319,13 +2320,14 @@ static ssize_t ocfs2_file_write_iter(struct kiocb *iocb,
ocfs2_inode_unlock(inode, 1); ocfs2_inode_unlock(inode, 1);
} }
orig_count = count; orig_count = iov_iter_count(from);
ret = generic_write_checks(file, &iocb->ki_pos, &count); ret = generic_write_checks(iocb, from);
if (ret < 0) { if (ret <= 0) {
mlog_errno(ret); if (ret)
mlog_errno(ret);
goto out; goto out;
} }
iov_iter_truncate(from, count); count = ret;
can_do_direct = direct_io; can_do_direct = direct_io;
ret = ocfs2_prepare_inode_for_write(file, iocb->ki_pos, count, appending, ret = ocfs2_prepare_inode_for_write(file, iocb->ki_pos, count, appending,
...@@ -2349,7 +2351,7 @@ static ssize_t ocfs2_file_write_iter(struct kiocb *iocb, ...@@ -2349,7 +2351,7 @@ static ssize_t ocfs2_file_write_iter(struct kiocb *iocb,
rw_level = -1; rw_level = -1;
direct_io = 0; direct_io = 0;
iov_iter_reexpand(from, count = orig_count); iov_iter_reexpand(from, orig_count);
goto relock; goto relock;
} }
...@@ -2377,7 +2379,7 @@ static ssize_t ocfs2_file_write_iter(struct kiocb *iocb, ...@@ -2377,7 +2379,7 @@ static ssize_t ocfs2_file_write_iter(struct kiocb *iocb,
loff_t endbyte; loff_t endbyte;
ssize_t written_buffered; ssize_t written_buffered;
written = generic_file_direct_write(iocb, from, iocb->ki_pos); written = generic_file_direct_write(iocb, from, iocb->ki_pos);
if (written < 0 || written == count) { if (written < 0 || !iov_iter_count(from)) {
ret = written; ret = written;
goto out_dio; goto out_dio;
} }
...@@ -2385,7 +2387,6 @@ static ssize_t ocfs2_file_write_iter(struct kiocb *iocb, ...@@ -2385,7 +2387,6 @@ static ssize_t ocfs2_file_write_iter(struct kiocb *iocb,
/* /*
* for completing the rest of the request. * for completing the rest of the request.
*/ */
count -= written;
written_buffered = generic_perform_write(file, from, iocb->ki_pos); written_buffered = generic_perform_write(file, from, iocb->ki_pos);
/* /*
* If generic_file_buffered_write() returned a synchronous error * If generic_file_buffered_write() returned a synchronous error
......
...@@ -120,21 +120,15 @@ static ssize_t udf_file_write_iter(struct kiocb *iocb, struct iov_iter *from) ...@@ -120,21 +120,15 @@ static ssize_t udf_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
ssize_t retval; ssize_t retval;
struct file *file = iocb->ki_filp; struct file *file = iocb->ki_filp;
struct inode *inode = file_inode(file); struct inode *inode = file_inode(file);
size_t count = iov_iter_count(from);
struct udf_inode_info *iinfo = UDF_I(inode); struct udf_inode_info *iinfo = UDF_I(inode);
int err; int err;
mutex_lock(&inode->i_mutex); mutex_lock(&inode->i_mutex);
retval = generic_write_checks(file, &iocb->ki_pos, &count); retval = generic_write_checks(iocb, from);
if (retval) if (retval <= 0)
goto out; goto out;
if (count == 0)
goto out;
iov_iter_truncate(from, count);
down_write(&iinfo->i_data_sem); down_write(&iinfo->i_data_sem);
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
loff_t end = iocb->ki_pos + iov_iter_count(from); loff_t end = iocb->ki_pos + iov_iter_count(from);
......
...@@ -551,12 +551,12 @@ xfs_file_aio_write_checks( ...@@ -551,12 +551,12 @@ xfs_file_aio_write_checks(
struct file *file = iocb->ki_filp; struct file *file = iocb->ki_filp;
struct inode *inode = file->f_mapping->host; struct inode *inode = file->f_mapping->host;
struct xfs_inode *ip = XFS_I(inode); struct xfs_inode *ip = XFS_I(inode);
int error = 0; ssize_t error = 0;
size_t count = iov_iter_count(from); size_t count = iov_iter_count(from);
restart: restart:
error = generic_write_checks(file, &iocb->ki_pos, &count); error = generic_write_checks(iocb, from);
if (error) if (error <= 0)
return error; return error;
error = xfs_break_layouts(inode, iolock); error = xfs_break_layouts(inode, iolock);
...@@ -577,13 +577,13 @@ xfs_file_aio_write_checks( ...@@ -577,13 +577,13 @@ xfs_file_aio_write_checks(
xfs_rw_iunlock(ip, *iolock); xfs_rw_iunlock(ip, *iolock);
*iolock = XFS_IOLOCK_EXCL; *iolock = XFS_IOLOCK_EXCL;
xfs_rw_ilock(ip, *iolock); xfs_rw_ilock(ip, *iolock);
iov_iter_reexpand(from, count);
goto restart; goto restart;
} }
error = xfs_zero_eof(ip, iocb->ki_pos, i_size_read(inode), &zero); error = xfs_zero_eof(ip, iocb->ki_pos, i_size_read(inode), &zero);
if (error) if (error)
return error; return error;
} }
iov_iter_truncate(from, count);
/* /*
* Updating the timestamps will grab the ilock again from * Updating the timestamps will grab the ilock again from
......
...@@ -2566,7 +2566,7 @@ extern int sb_min_blocksize(struct super_block *, int); ...@@ -2566,7 +2566,7 @@ extern int sb_min_blocksize(struct super_block *, int);
extern int generic_file_mmap(struct file *, struct vm_area_struct *); extern int generic_file_mmap(struct file *, struct vm_area_struct *);
extern int generic_file_readonly_mmap(struct file *, struct vm_area_struct *); extern int generic_file_readonly_mmap(struct file *, struct vm_area_struct *);
int generic_write_checks(struct file *file, loff_t *pos, size_t *count); extern ssize_t generic_write_checks(struct kiocb *, struct iov_iter *);
extern ssize_t generic_file_read_iter(struct kiocb *, struct iov_iter *); extern ssize_t generic_file_read_iter(struct kiocb *, struct iov_iter *);
extern ssize_t __generic_file_write_iter(struct kiocb *, struct iov_iter *); extern ssize_t __generic_file_write_iter(struct kiocb *, struct iov_iter *);
extern ssize_t generic_file_write_iter(struct kiocb *, struct iov_iter *); extern ssize_t generic_file_write_iter(struct kiocb *, struct iov_iter *);
......
...@@ -2260,36 +2260,38 @@ EXPORT_SYMBOL(read_cache_page_gfp); ...@@ -2260,36 +2260,38 @@ EXPORT_SYMBOL(read_cache_page_gfp);
* Returns appropriate error code that caller should return or * Returns appropriate error code that caller should return or
* zero in case that write should be allowed. * zero in case that write should be allowed.
*/ */
inline int generic_write_checks(struct file *file, loff_t *pos, size_t *count) inline ssize_t generic_write_checks(struct kiocb *iocb, struct iov_iter *from)
{ {
struct file *file = iocb->ki_filp;
struct inode *inode = file->f_mapping->host; struct inode *inode = file->f_mapping->host;
unsigned long limit = rlimit(RLIMIT_FSIZE); unsigned long limit = rlimit(RLIMIT_FSIZE);
loff_t pos;
if (unlikely(*pos < 0)) if (!iov_iter_count(from))
return -EINVAL; return 0;
/* FIXME: this is for backwards compatibility with 2.4 */ /* FIXME: this is for backwards compatibility with 2.4 */
if (file->f_flags & O_APPEND) if (file->f_flags & O_APPEND)
*pos = i_size_read(inode); iocb->ki_pos = i_size_read(inode);
pos = iocb->ki_pos;
if (limit != RLIM_INFINITY) { if (limit != RLIM_INFINITY) {
if (*pos >= limit) { if (iocb->ki_pos >= limit) {
send_sig(SIGXFSZ, current, 0); send_sig(SIGXFSZ, current, 0);
return -EFBIG; return -EFBIG;
} }
if (*count > limit - (typeof(limit))*pos) iov_iter_truncate(from, limit - (unsigned long)pos);
*count = limit - (typeof(limit))*pos;
} }
/* /*
* LFS rule * LFS rule
*/ */
if (unlikely(*pos + *count > MAX_NON_LFS && if (unlikely(pos + iov_iter_count(from) > MAX_NON_LFS &&
!(file->f_flags & O_LARGEFILE))) { !(file->f_flags & O_LARGEFILE))) {
if (*pos >= MAX_NON_LFS) if (pos >= MAX_NON_LFS)
return -EFBIG; return -EFBIG;
if (*count > MAX_NON_LFS - (unsigned long)*pos) iov_iter_truncate(from, MAX_NON_LFS - (unsigned long)pos);
*count = MAX_NON_LFS - (unsigned long)*pos;
} }
/* /*
...@@ -2299,16 +2301,11 @@ inline int generic_write_checks(struct file *file, loff_t *pos, size_t *count) ...@@ -2299,16 +2301,11 @@ inline int generic_write_checks(struct file *file, loff_t *pos, size_t *count)
* exceeded without writing data we send a signal and return EFBIG. * exceeded without writing data we send a signal and return EFBIG.
* Linus frestrict idea will clean these up nicely.. * Linus frestrict idea will clean these up nicely..
*/ */
if (unlikely(*pos >= inode->i_sb->s_maxbytes)) { if (unlikely(pos >= inode->i_sb->s_maxbytes))
if (*count || *pos > inode->i_sb->s_maxbytes) { return -EFBIG;
return -EFBIG;
}
/* zero-length writes at ->s_maxbytes are OK */
}
if (unlikely(*pos + *count > inode->i_sb->s_maxbytes)) iov_iter_truncate(from, inode->i_sb->s_maxbytes - pos);
*count = inode->i_sb->s_maxbytes - *pos; return iov_iter_count(from);
return 0;
} }
EXPORT_SYMBOL(generic_write_checks); EXPORT_SYMBOL(generic_write_checks);
...@@ -2618,14 +2615,11 @@ ssize_t generic_file_write_iter(struct kiocb *iocb, struct iov_iter *from) ...@@ -2618,14 +2615,11 @@ ssize_t generic_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
struct file *file = iocb->ki_filp; struct file *file = iocb->ki_filp;
struct inode *inode = file->f_mapping->host; struct inode *inode = file->f_mapping->host;
ssize_t ret; ssize_t ret;
size_t count = iov_iter_count(from);
mutex_lock(&inode->i_mutex); mutex_lock(&inode->i_mutex);
ret = generic_write_checks(file, &iocb->ki_pos, &count); ret = generic_write_checks(iocb, from);
if (!ret && count) { if (ret > 0)
iov_iter_truncate(from, count);
ret = __generic_file_write_iter(iocb, from); ret = __generic_file_write_iter(iocb, from);
}
mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex);
if (ret > 0) { if (ret > 0) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment