Skip to content

Commit

Permalink
switch generic_write_checks() to iocb and iter
Browse files Browse the repository at this point in the history
... 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 <[email protected]>

Conflicts:
	fs/ext4/file.c
  • Loading branch information
Al Viro committed Apr 12, 2015
1 parent 9032025 commit 3309dd0
Show file tree
Hide file tree
Showing 14 changed files with 99 additions and 166 deletions.
26 changes: 10 additions & 16 deletions fs/9p/vfs_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -404,21 +404,16 @@ static ssize_t
v9fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
{
struct file *file = iocb->ki_filp;
ssize_t retval = 0;
loff_t origin = iocb->ki_pos;
size_t count = iov_iter_count(from);
ssize_t retval;
loff_t origin;
int err = 0;

retval = generic_write_checks(file, &origin, &count);
if (retval)
retval = generic_write_checks(iocb, from);
if (retval <= 0)
return retval;

iov_iter_truncate(from, count);

if (!count)
return 0;

retval = p9_client_write(file->private_data, origin, from, &err);
origin = iocb->ki_pos;
retval = p9_client_write(file->private_data, iocb->ki_pos, from, &err);
if (retval > 0) {
struct inode *inode = file_inode(file);
loff_t i_size;
Expand All @@ -428,12 +423,11 @@ v9fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
if (inode->i_mapping && inode->i_mapping->nrpages)
invalidate_inode_pages2_range(inode->i_mapping,
pg_start, pg_end);
origin += retval;
iocb->ki_pos += retval;
i_size = i_size_read(inode);
iocb->ki_pos = origin;
if (origin > i_size) {
inode_add_bytes(inode, origin - i_size);
i_size_write(inode, origin);
if (iocb->ki_pos > i_size) {
inode_add_bytes(inode, iocb->ki_pos - i_size);
i_size_write(inode, iocb->ki_pos);
}
return retval;
}
Expand Down
24 changes: 9 additions & 15 deletions fs/btrfs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -1739,27 +1739,19 @@ static ssize_t btrfs_file_write_iter(struct kiocb *iocb,
u64 start_pos;
u64 end_pos;
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);
loff_t pos = iocb->ki_pos;
ssize_t err;
loff_t pos;
size_t count;

mutex_lock(&inode->i_mutex);

current->backing_dev_info = inode_to_bdi(inode);
err = generic_write_checks(file, &pos, &count);
if (err) {
err = generic_write_checks(iocb, from);
if (err <= 0) {
mutex_unlock(&inode->i_mutex);
goto out;
}

if (count == 0) {
mutex_unlock(&inode->i_mutex);
goto out;
return err;
}

iov_iter_truncate(from, count);

current->backing_dev_info = inode_to_bdi(inode);
err = file_remove_suid(file);
if (err) {
mutex_unlock(&inode->i_mutex);
Expand All @@ -1786,6 +1778,8 @@ static ssize_t btrfs_file_write_iter(struct kiocb *iocb,
*/
update_time_for_write(inode);

pos = iocb->ki_pos;
count = iov_iter_count(from);
start_pos = round_down(pos, root->sectorsize);
if (start_pos > i_size_read(inode)) {
/* Expand hole size to cover write data, preventing empty gap */
Expand Down
14 changes: 6 additions & 8 deletions fs/ceph/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -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_osd_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;
loff_t pos = iocb->ki_pos;
loff_t pos;

if (ceph_snap(inode) != CEPH_NOSNAP)
return -EROFS;
Expand All @@ -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 */
current->backing_dev_info = inode_to_bdi(inode);

err = generic_write_checks(file, &pos, &count);
if (err)
goto out;

if (count == 0)
err = generic_write_checks(iocb, from);
if (err <= 0)
goto out;
iov_iter_truncate(from, count);

pos = iocb->ki_pos;
count = iov_iter_count(from);
err = file_remove_suid(file);
if (err)
goto out;
Expand Down
26 changes: 6 additions & 20 deletions fs/cifs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
struct file *file = iocb->ki_filp;
size_t len;
ssize_t total_written = 0;
struct cifsFileInfo *open_file;
struct cifs_tcon *tcon;
Expand All @@ -2579,16 +2578,10 @@ ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from)
* write request.
*/

len = iov_iter_count(from);
rc = generic_write_checks(file, &iocb->ki_pos, &len);
if (rc)
rc = generic_write_checks(iocb, from);
if (rc <= 0)
return rc;

if (!len)
return 0;

iov_iter_truncate(from, len);

INIT_LIST_HEAD(&wdata_list);
cifs_sb = CIFS_FILE_SB(file);
open_file = file->private_data;
Expand All @@ -2599,8 +2592,8 @@ ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from)

memcpy(&saved_from, from, sizeof(struct iov_iter));

rc = cifs_write_from_iter(iocb->ki_pos, len, from, open_file, cifs_sb,
&wdata_list);
rc = cifs_write_from_iter(iocb->ki_pos, iov_iter_count(from), from,
open_file, cifs_sb, &wdata_list);

/*
* If at least one write was successfully sent, then discard any rc
Expand Down Expand Up @@ -2674,7 +2667,6 @@ cifs_writev(struct kiocb *iocb, struct iov_iter *from)
struct cifsInodeInfo *cinode = CIFS_I(inode);
struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server;
ssize_t rc;
size_t count;

/*
* We need to hold the sem to be sure nobody modifies lock list
Expand All @@ -2683,16 +2675,10 @@ cifs_writev(struct kiocb *iocb, struct iov_iter *from)
down_read(&cinode->lock_sem);
mutex_lock(&inode->i_mutex);

count = iov_iter_count(from);
rc = generic_write_checks(file, &iocb->ki_pos, &count);
if (rc)
rc = generic_write_checks(iocb, from);
if (rc <= 0)
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),
server->vals->exclusive_lock_type, NULL,
CIFS_WRITE_OP))
Expand Down
20 changes: 6 additions & 14 deletions fs/ext4/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,7 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
struct blk_plug plug;
int o_direct = io_is_direct(file);
int overwrite = 0;
size_t length = iov_iter_count(from);
ssize_t ret;
loff_t pos;

/*
* Unaligned direct AIO must be serialized; see comment above
Expand All @@ -116,36 +114,30 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
}

mutex_lock(&inode->i_mutex);
ret = generic_write_checks(file, &iocb->ki_pos, &length);
if (ret)
ret = generic_write_checks(iocb, from);
if (ret <= 0)
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
* is smaller than s_maxbytes, which is for extent-mapped files.
*/
if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) {
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;
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;
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);


/* check whether we do a DIO overwrite or not */
if (ext4_should_dioread_nolock(inode) && !aio_mutex &&
!file->f_mapping->nrpages && pos + length <= i_size_read(inode)) {
Expand Down
22 changes: 7 additions & 15 deletions fs/fuse/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 address_space *mapping = file->f_mapping;
size_t count = iov_iter_count(from);
ssize_t written = 0;
ssize_t written_buffered = 0;
struct inode *inode = mapping->host;
ssize_t err;
loff_t endbyte = 0;
loff_t pos = iocb->ki_pos;

if (get_fuse_conn(inode)->writeback_cache) {
/* Update size (EOF optimization) and mode (SUID clearing) */
Expand All @@ -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 */
current->backing_dev_info = inode_to_bdi(inode);

err = generic_write_checks(file, &pos, &count);
if (err)
goto out;

if (count == 0)
err = generic_write_checks(iocb, from);
if (err <= 0)
goto out;

iov_iter_truncate(from, count);
err = file_remove_suid(file);
if (err)
goto out;
Expand All @@ -1184,6 +1178,7 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
goto out;

if (file->f_flags & O_DIRECT) {
loff_t pos = iocb->ki_pos;
written = generic_file_direct_write(iocb, from, pos);
if (written < 0 || !iov_iter_count(from))
goto out;
Expand All @@ -1209,9 +1204,9 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
written += written_buffered;
iocb->ki_pos = pos + written_buffered;
} else {
written = fuse_perform_write(file, mapping, from, pos);
written = fuse_perform_write(file, mapping, from, iocb->ki_pos);
if (written >= 0)
iocb->ki_pos = pos + written;
iocb->ki_pos += written;
}
out:
current->backing_dev_info = NULL;
Expand Down Expand Up @@ -1412,19 +1407,16 @@ static ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from)
struct file *file = iocb->ki_filp;
struct inode *inode = file_inode(file);
struct fuse_io_priv io = { .async = 0, .file = file };
size_t count = iov_iter_count(from);
ssize_t res;

if (is_bad_inode(inode))
return -EIO;

/* Don't allow parallel writes to the same file */
mutex_lock(&inode->i_mutex);
res = generic_write_checks(file, &iocb->ki_pos, &count);
if (!res) {
iov_iter_truncate(from, count);
res = generic_write_checks(iocb, from);
if (res > 0)
res = fuse_direct_io(&io, from, &iocb->ki_pos, FUSE_DIO_WRITE);
}
fuse_invalidate_attr(inode);
if (res > 0)
fuse_write_update_size(inode, iocb->ki_pos);
Expand Down
14 changes: 5 additions & 9 deletions fs/ncpfs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -170,20 +170,15 @@ ncp_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
struct file *file = iocb->ki_filp;
struct inode *inode = file_inode(file);
size_t already_written = 0;
loff_t pos = iocb->ki_pos;
size_t count = iov_iter_count(from);
size_t bufsize;
int errno;
void *bouncebuffer;
off_t pos;

ncp_dbg(1, "enter %pD2\n", file);
errno = generic_write_checks(file, &pos, &count);
if (errno)
errno = generic_write_checks(iocb, from);
if (errno <= 0)
return errno;
iov_iter_truncate(from, count);

if (!count)
return 0;

errno = ncp_make_open(inode, O_WRONLY);
if (errno) {
Expand All @@ -201,10 +196,11 @@ ncp_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
errno = -EIO; /* -ENOMEM */
goto outrel;
}
pos = iocb->ki_pos;
while (iov_iter_count(from)) {
int written_this_time;
size_t to_write = min_t(size_t,
bufsize - ((off_t)pos % bufsize),
bufsize - (pos % bufsize),
iov_iter_count(from));

if (copy_from_iter(bouncebuffer, to_write, from) != to_write) {
Expand Down
25 changes: 10 additions & 15 deletions fs/nfs/direct.c
Original file line number Diff line number Diff line change
Expand Up @@ -969,24 +969,19 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter,
struct nfs_direct_req *dreq;
struct nfs_lock_context *l_ctx;
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",
file, count, (long long) pos);
file, iov_iter_count(iter), (long long) iocb->ki_pos);

result = generic_write_checks(file, &pos, &count);
if (result)
result = generic_write_checks(iocb, iter);
if (result <= 0)
goto out;

result = -EINVAL;
if ((ssize_t) count < 0)
goto out;
result = 0;
if (!count)
goto out;
nfs_add_stats(mapping->host, NFSIOS_DIRECTWRITTENBYTES,
iov_iter_count(iter));

pos = iocb->ki_pos;
end = (pos + iov_iter_count(iter) - 1) >> PAGE_CACHE_SHIFT;

mutex_lock(&inode->i_mutex);

Expand All @@ -1001,15 +996,15 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter,
goto out_unlock;
}

task_io_account_write(count);
task_io_account_write(iov_iter_count(iter));

result = -ENOMEM;
dreq = nfs_direct_req_alloc();
if (!dreq)
goto out_unlock;

dreq->inode = inode;
dreq->bytes_left = count;
dreq->bytes_left = iov_iter_count(iter);
dreq->io_start = pos;
dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp));
l_ctx = nfs_get_lock_context(dreq->ctx);
Expand Down
Loading

0 comments on commit 3309dd0

Please sign in to comment.