ntfs: move iov_iter_truncate() closer to generic_write_checks()

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Al Viro 2015-04-05 14:06:24 -04:00
parent f765b134c0
commit ccca26835d

View file

@ -328,26 +328,29 @@ err_out:
return err; return err;
} }
static ssize_t ntfs_prepare_file_for_write(struct file *file, loff_t *ppos, static ssize_t ntfs_prepare_file_for_write(struct kiocb *iocb,
size_t *count) struct iov_iter *from)
{ {
loff_t pos; loff_t pos;
s64 end, ll; s64 end, ll;
ssize_t err; ssize_t err;
unsigned long flags; unsigned long flags;
struct file *file = iocb->ki_filp;
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%lx.", 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)*ppos, (unsigned long)*count); (unsigned long long)iocb->ki_pos, count);
/* We can write back this queue in page reclaim. */ err = generic_write_checks(file, &iocb->ki_pos, &count, S_ISBLK(vi->i_mode));
current->backing_dev_info = inode_to_bdi(vi);
err = generic_write_checks(file, ppos, count, S_ISBLK(vi->i_mode));
if (unlikely(err)) if (unlikely(err))
goto out; goto out;
iov_iter_truncate(from, count);
if (count == 0)
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
* to abort any totally illegal writes. * to abort any totally illegal writes.
@ -379,8 +382,6 @@ static ssize_t ntfs_prepare_file_for_write(struct file *file, loff_t *ppos,
err = -EOPNOTSUPP; err = -EOPNOTSUPP;
goto out; goto out;
} }
if (*count == 0)
goto out;
base_ni = ni; base_ni = ni;
if (NInoAttr(ni)) if (NInoAttr(ni))
base_ni = ni->ext.base_ntfs_ino; base_ni = ni->ext.base_ntfs_ino;
@ -392,9 +393,9 @@ static ssize_t ntfs_prepare_file_for_write(struct file *file, loff_t *ppos,
* cannot fail either so there is no need to check the return code. * cannot fail either so there is no need to check the return code.
*/ */
file_update_time(file); file_update_time(file);
pos = *ppos; pos = iocb->ki_pos;
/* The first byte after the last cluster being written to. */ /* The first byte after the last cluster being written to. */
end = (pos + *count + vol->cluster_size_mask) & end = (pos + iov_iter_count(from) + vol->cluster_size_mask) &
~(u64)vol->cluster_size_mask; ~(u64)vol->cluster_size_mask;
/* /*
* If the write goes beyond the allocated size, extend the allocation * If the write goes beyond the allocated size, extend the allocation
@ -422,7 +423,7 @@ static ssize_t ntfs_prepare_file_for_write(struct file *file, loff_t *ppos,
"partially extended.", "partially extended.",
vi->i_ino, (unsigned) vi->i_ino, (unsigned)
le32_to_cpu(ni->type)); le32_to_cpu(ni->type));
*count = ll - pos; iov_iter_truncate(from, ll - pos);
} }
} else { } else {
err = ll; err = ll;
@ -438,7 +439,7 @@ static ssize_t ntfs_prepare_file_for_write(struct file *file, loff_t *ppos,
vi->i_ino, (unsigned) vi->i_ino, (unsigned)
le32_to_cpu(ni->type), le32_to_cpu(ni->type),
(int)-err); (int)-err);
*count = ll - pos; iov_iter_truncate(from, ll - pos);
} else { } else {
if (err != -ENOSPC) if (err != -ENOSPC)
ntfs_error(vi->i_sb, "Cannot perform " ntfs_error(vi->i_sb, "Cannot perform "
@ -1929,61 +1930,37 @@ again:
return written ? written : status; return written ? written : status;
} }
/**
* ntfs_file_write_iter_nolock - write data to a file
* @iocb: IO state structure (file, offset, etc.)
* @from: iov_iter with data to write
*
* Basically the same as __generic_file_write_iter() except that it ends
* up calling ntfs_perform_write() instead of generic_perform_write() and that
* O_DIRECT is not implemented.
*/
static ssize_t ntfs_file_write_iter_nolock(struct kiocb *iocb,
struct iov_iter *from)
{
struct file *file = iocb->ki_filp;
loff_t pos = iocb->ki_pos;
ssize_t written = 0;
ssize_t err;
size_t count = iov_iter_count(from);
err = ntfs_prepare_file_for_write(file, &pos, &count);
if (count && !err) {
iov_iter_truncate(from, count);
written = ntfs_perform_write(file, from, pos);
if (likely(written >= 0))
iocb->ki_pos = pos + written;
}
current->backing_dev_info = NULL;
return written ? written : err;
}
/** /**
* ntfs_file_write_iter - simple wrapper for ntfs_file_write_iter_nolock() * ntfs_file_write_iter - simple wrapper for ntfs_file_write_iter_nolock()
* @iocb: IO state structure * @iocb: IO state structure
* @from: iov_iter with data to write * @from: iov_iter with data to write
* *
* Basically the same as generic_file_write_iter() except that it ends up * Basically the same as generic_file_write_iter() except that it ends up
* calling ntfs_file_write_iter_nolock() instead of * up calling ntfs_perform_write() instead of generic_perform_write() and that
* __generic_file_write_iter(). * O_DIRECT is not implemented.
*/ */
static ssize_t ntfs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) static ssize_t ntfs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
{ {
struct file *file = iocb->ki_filp; struct file *file = iocb->ki_filp;
struct inode *vi = file_inode(file); struct inode *vi = file_inode(file);
ssize_t ret; ssize_t written = 0;
mutex_lock(&vi->i_mutex);
ret = ntfs_file_write_iter_nolock(iocb, from);
mutex_unlock(&vi->i_mutex);
if (ret > 0) {
ssize_t err; ssize_t err;
err = generic_write_sync(file, iocb->ki_pos - ret, ret); mutex_lock(&vi->i_mutex);
/* We can write back this queue in page reclaim. */
current->backing_dev_info = inode_to_bdi(vi);
err = ntfs_prepare_file_for_write(iocb, from);
if (iov_iter_count(from) && !err)
written = ntfs_perform_write(file, from, iocb->ki_pos);
current->backing_dev_info = NULL;
mutex_unlock(&vi->i_mutex);
if (likely(written > 0)) {
err = generic_write_sync(file, iocb->ki_pos, written);
if (err < 0) if (err < 0)
ret = err; written = 0;
} }
return ret; iocb->ki_pos += written;
return written ? written : err;
} }
/** /**