Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull third hunk of vfs changes from Al Viro:
 "This contains the ->direct_IO() changes from Omar + saner
  generic_write_checks() + dealing with fcntl()/{read,write}() races
  (mirroring O_APPEND/O_DIRECT into iocb->ki_flags and instead of
  repeatedly looking at ->f_flags, which can be changed by fcntl(2),
  check ->ki_flags - which cannot) + infrastructure bits for dhowells'
  d_inode annotations + Christophs switch of /dev/loop to
  vfs_iter_write()"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (30 commits)
  block: loop: switch to VFS ITER_BVEC
  configfs: Fix inconsistent use of file_inode() vs file->f_path.dentry->d_inode
  VFS: Make pathwalk use d_is_reg() rather than S_ISREG()
  VFS: Fix up debugfs to use d_is_dir() in place of S_ISDIR()
  VFS: Combine inode checks with d_is_negative() and d_is_positive() in pathwalk
  NFS: Don't use d_inode as a variable name
  VFS: Impose ordering on accesses of d_inode and d_flags
  VFS: Add owner-filesystem positive/negative dentry checks
  nfs: generic_write_checks() shouldn't be done on swapout...
  ocfs2: use __generic_file_write_iter()
  mirror O_APPEND and O_DIRECT into iocb->ki_flags
  switch generic_write_checks() to iocb and iter
  ocfs2: move generic_write_checks() before the alignment checks
  ocfs2_file_write_iter: stop messing with ppos
  udf_file_write_iter: reorder and simplify
  fuse: ->direct_IO() doesn't need generic_write_checks()
  ext4_file_write_iter: move generic_write_checks() up
  xfs_file_aio_write_checks: switch to iocb/iov_iter
  generic_write_checks(): drop isblk argument
  blkdev_write_iter: expand generic_file_checks() call in there
  ...
This commit is contained in:
Linus Torvalds 2015-04-16 23:27:56 -04:00
commit 4fc8adcfec
55 changed files with 700 additions and 870 deletions

View File

@ -196,7 +196,7 @@ prototypes:
void (*invalidatepage) (struct page *, unsigned int, unsigned int); void (*invalidatepage) (struct page *, unsigned int, unsigned int);
int (*releasepage) (struct page *, int); int (*releasepage) (struct page *, int);
void (*freepage)(struct page *); void (*freepage)(struct page *);
int (*direct_IO)(int, struct kiocb *, struct iov_iter *iter, loff_t offset); int (*direct_IO)(struct kiocb *, struct iov_iter *iter, loff_t offset);
int (*migratepage)(struct address_space *, struct page *, struct page *); int (*migratepage)(struct address_space *, struct page *, struct page *);
int (*launder_page)(struct page *); int (*launder_page)(struct page *);
int (*is_partially_uptodate)(struct page *, unsigned long, unsigned long); int (*is_partially_uptodate)(struct page *, unsigned long, unsigned long);

View File

@ -590,7 +590,7 @@ struct address_space_operations {
void (*invalidatepage) (struct page *, unsigned int, unsigned int); void (*invalidatepage) (struct page *, unsigned int, unsigned int);
int (*releasepage) (struct page *, int); int (*releasepage) (struct page *, int);
void (*freepage)(struct page *); void (*freepage)(struct page *);
ssize_t (*direct_IO)(int, struct kiocb *, struct iov_iter *iter, loff_t offset); ssize_t (*direct_IO)(struct kiocb *, struct iov_iter *iter, loff_t offset);
/* migrate the contents of a page to the specified target */ /* migrate the contents of a page to the specified target */
int (*migratepage) (struct page *, struct page *); int (*migratepage) (struct page *, struct page *);
int (*launder_page) (struct page *); int (*launder_page) (struct page *);

View File

@ -88,28 +88,6 @@ static int part_shift;
static struct workqueue_struct *loop_wq; static struct workqueue_struct *loop_wq;
/*
* Transfer functions
*/
static int transfer_none(struct loop_device *lo, int cmd,
struct page *raw_page, unsigned raw_off,
struct page *loop_page, unsigned loop_off,
int size, sector_t real_block)
{
char *raw_buf = kmap_atomic(raw_page) + raw_off;
char *loop_buf = kmap_atomic(loop_page) + loop_off;
if (cmd == READ)
memcpy(loop_buf, raw_buf, size);
else
memcpy(raw_buf, loop_buf, size);
kunmap_atomic(loop_buf);
kunmap_atomic(raw_buf);
cond_resched();
return 0;
}
static int transfer_xor(struct loop_device *lo, int cmd, static int transfer_xor(struct loop_device *lo, int cmd,
struct page *raw_page, unsigned raw_off, struct page *raw_page, unsigned raw_off,
struct page *loop_page, unsigned loop_off, struct page *loop_page, unsigned loop_off,
@ -148,14 +126,13 @@ static int xor_init(struct loop_device *lo, const struct loop_info64 *info)
static struct loop_func_table none_funcs = { static struct loop_func_table none_funcs = {
.number = LO_CRYPT_NONE, .number = LO_CRYPT_NONE,
.transfer = transfer_none, };
};
static struct loop_func_table xor_funcs = { static struct loop_func_table xor_funcs = {
.number = LO_CRYPT_XOR, .number = LO_CRYPT_XOR,
.transfer = transfer_xor, .transfer = transfer_xor,
.init = xor_init .init = xor_init
}; };
/* xfer_funcs[0] is special - its release function is never called */ /* xfer_funcs[0] is special - its release function is never called */
static struct loop_func_table *xfer_funcs[MAX_LO_CRYPT] = { static struct loop_func_table *xfer_funcs[MAX_LO_CRYPT] = {
@ -215,209 +192,171 @@ lo_do_transfer(struct loop_device *lo, int cmd,
struct page *lpage, unsigned loffs, struct page *lpage, unsigned loffs,
int size, sector_t rblock) int size, sector_t rblock)
{ {
if (unlikely(!lo->transfer)) int ret;
ret = lo->transfer(lo, cmd, rpage, roffs, lpage, loffs, size, rblock);
if (likely(!ret))
return 0; return 0;
return lo->transfer(lo, cmd, rpage, roffs, lpage, loffs, size, rblock); printk_ratelimited(KERN_ERR
"loop: Transfer error at byte offset %llu, length %i.\n",
(unsigned long long)rblock << 9, size);
return ret;
} }
/** static int lo_write_bvec(struct file *file, struct bio_vec *bvec, loff_t *ppos)
* __do_lo_send_write - helper for writing data to a loop device
*
* This helper just factors out common code between do_lo_send_direct_write()
* and do_lo_send_write().
*/
static int __do_lo_send_write(struct file *file,
u8 *buf, const int len, loff_t pos)
{ {
struct kvec kvec = {.iov_base = buf, .iov_len = len}; struct iov_iter i;
struct iov_iter from;
ssize_t bw; ssize_t bw;
iov_iter_kvec(&from, ITER_KVEC | WRITE, &kvec, 1, len); iov_iter_bvec(&i, ITER_BVEC, bvec, 1, bvec->bv_len);
file_start_write(file); file_start_write(file);
bw = vfs_iter_write(file, &from, &pos); bw = vfs_iter_write(file, &i, ppos);
file_end_write(file); file_end_write(file);
if (likely(bw == len))
if (likely(bw == bvec->bv_len))
return 0; return 0;
printk_ratelimited(KERN_ERR "loop: Write error at byte offset %llu, length %i.\n",
(unsigned long long)pos, len); printk_ratelimited(KERN_ERR
"loop: Write error at byte offset %llu, length %i.\n",
(unsigned long long)*ppos, bvec->bv_len);
if (bw >= 0) if (bw >= 0)
bw = -EIO; bw = -EIO;
return bw; return bw;
} }
/** static int lo_write_simple(struct loop_device *lo, struct request *rq,
* do_lo_send_direct_write - helper for writing data to a loop device loff_t pos)
*
* This is the fast, non-transforming version that does not need double
* buffering.
*/
static int do_lo_send_direct_write(struct loop_device *lo,
struct bio_vec *bvec, loff_t pos, struct page *page)
{ {
ssize_t bw = __do_lo_send_write(lo->lo_backing_file, struct bio_vec bvec;
kmap(bvec->bv_page) + bvec->bv_offset, struct req_iterator iter;
bvec->bv_len, pos); int ret = 0;
kunmap(bvec->bv_page);
cond_resched(); rq_for_each_segment(bvec, rq, iter) {
return bw; ret = lo_write_bvec(lo->lo_backing_file, &bvec, &pos);
if (ret < 0)
break;
cond_resched();
}
return ret;
} }
/** /*
* do_lo_send_write - helper for writing data to a loop device
*
* This is the slow, transforming version that needs to double buffer the * This is the slow, transforming version that needs to double buffer the
* data as it cannot do the transformations in place without having direct * data as it cannot do the transformations in place without having direct
* access to the destination pages of the backing file. * access to the destination pages of the backing file.
*/ */
static int do_lo_send_write(struct loop_device *lo, struct bio_vec *bvec, static int lo_write_transfer(struct loop_device *lo, struct request *rq,
loff_t pos, struct page *page) loff_t pos)
{ {
int ret = lo_do_transfer(lo, WRITE, page, 0, bvec->bv_page, struct bio_vec bvec, b;
bvec->bv_offset, bvec->bv_len, pos >> 9);
if (likely(!ret))
return __do_lo_send_write(lo->lo_backing_file,
page_address(page), bvec->bv_len,
pos);
printk_ratelimited(KERN_ERR "loop: Transfer error at byte offset %llu, "
"length %i.\n", (unsigned long long)pos, bvec->bv_len);
if (ret > 0)
ret = -EIO;
return ret;
}
static int lo_send(struct loop_device *lo, struct request *rq, loff_t pos)
{
int (*do_lo_send)(struct loop_device *, struct bio_vec *, loff_t,
struct page *page);
struct bio_vec bvec;
struct req_iterator iter; struct req_iterator iter;
struct page *page = NULL; struct page *page;
int ret = 0; int ret = 0;
if (lo->transfer != transfer_none) { page = alloc_page(GFP_NOIO);
page = alloc_page(GFP_NOIO | __GFP_HIGHMEM); if (unlikely(!page))
if (unlikely(!page)) return -ENOMEM;
goto fail;
kmap(page);
do_lo_send = do_lo_send_write;
} else {
do_lo_send = do_lo_send_direct_write;
}
rq_for_each_segment(bvec, rq, iter) { rq_for_each_segment(bvec, rq, iter) {
ret = do_lo_send(lo, &bvec, pos, page); ret = lo_do_transfer(lo, WRITE, page, 0, bvec.bv_page,
bvec.bv_offset, bvec.bv_len, pos >> 9);
if (unlikely(ret))
break;
b.bv_page = page;
b.bv_offset = 0;
b.bv_len = bvec.bv_len;
ret = lo_write_bvec(lo->lo_backing_file, &b, &pos);
if (ret < 0) if (ret < 0)
break; break;
pos += bvec.bv_len;
} }
if (page) {
kunmap(page); __free_page(page);
__free_page(page);
}
out:
return ret; return ret;
fail:
printk_ratelimited(KERN_ERR "loop: Failed to allocate temporary page for write.\n");
ret = -ENOMEM;
goto out;
} }
struct lo_read_data { static int lo_read_simple(struct loop_device *lo, struct request *rq,
struct loop_device *lo; loff_t pos)
struct page *page;
unsigned offset;
int bsize;
};
static int
lo_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
struct splice_desc *sd)
{
struct lo_read_data *p = sd->u.data;
struct loop_device *lo = p->lo;
struct page *page = buf->page;
sector_t IV;
int size;
IV = ((sector_t) page->index << (PAGE_CACHE_SHIFT - 9)) +
(buf->offset >> 9);
size = sd->len;
if (size > p->bsize)
size = p->bsize;
if (lo_do_transfer(lo, READ, page, buf->offset, p->page, p->offset, size, IV)) {
printk_ratelimited(KERN_ERR "loop: transfer error block %ld\n",
page->index);
size = -EINVAL;
}
flush_dcache_page(p->page);
if (size > 0)
p->offset += size;
return size;
}
static int
lo_direct_splice_actor(struct pipe_inode_info *pipe, struct splice_desc *sd)
{
return __splice_from_pipe(pipe, sd, lo_splice_actor);
}
static ssize_t
do_lo_receive(struct loop_device *lo,
struct bio_vec *bvec, int bsize, loff_t pos)
{
struct lo_read_data cookie;
struct splice_desc sd;
struct file *file;
ssize_t retval;
cookie.lo = lo;
cookie.page = bvec->bv_page;
cookie.offset = bvec->bv_offset;
cookie.bsize = bsize;
sd.len = 0;
sd.total_len = bvec->bv_len;
sd.flags = 0;
sd.pos = pos;
sd.u.data = &cookie;
file = lo->lo_backing_file;
retval = splice_direct_to_actor(file, &sd, lo_direct_splice_actor);
return retval;
}
static int
lo_receive(struct loop_device *lo, struct request *rq, int bsize, loff_t pos)
{ {
struct bio_vec bvec; struct bio_vec bvec;
struct req_iterator iter; struct req_iterator iter;
ssize_t s; struct iov_iter i;
ssize_t len;
rq_for_each_segment(bvec, rq, iter) { rq_for_each_segment(bvec, rq, iter) {
s = do_lo_receive(lo, &bvec, bsize, pos); iov_iter_bvec(&i, ITER_BVEC, &bvec, 1, bvec.bv_len);
if (s < 0) len = vfs_iter_read(lo->lo_backing_file, &i, &pos);
return s; if (len < 0)
return len;
if (s != bvec.bv_len) { flush_dcache_page(bvec.bv_page);
if (len != bvec.bv_len) {
struct bio *bio; struct bio *bio;
__rq_for_each_bio(bio, rq) __rq_for_each_bio(bio, rq)
zero_fill_bio(bio); zero_fill_bio(bio);
break; break;
} }
pos += bvec.bv_len; cond_resched();
} }
return 0; return 0;
} }
static int lo_read_transfer(struct loop_device *lo, struct request *rq,
loff_t pos)
{
struct bio_vec bvec, b;
struct req_iterator iter;
struct iov_iter i;
struct page *page;
ssize_t len;
int ret = 0;
page = alloc_page(GFP_NOIO);
if (unlikely(!page))
return -ENOMEM;
rq_for_each_segment(bvec, rq, iter) {
loff_t offset = pos;
b.bv_page = page;
b.bv_offset = 0;
b.bv_len = bvec.bv_len;
iov_iter_bvec(&i, ITER_BVEC, &b, 1, b.bv_len);
len = vfs_iter_read(lo->lo_backing_file, &i, &pos);
if (len < 0) {
ret = len;
goto out_free_page;
}
ret = lo_do_transfer(lo, READ, page, 0, bvec.bv_page,
bvec.bv_offset, len, offset >> 9);
if (ret)
goto out_free_page;
flush_dcache_page(bvec.bv_page);
if (len != bvec.bv_len) {
struct bio *bio;
__rq_for_each_bio(bio, rq)
zero_fill_bio(bio);
break;
}
}
ret = 0;
out_free_page:
__free_page(page);
return ret;
}
static int lo_discard(struct loop_device *lo, struct request *rq, loff_t pos) static int lo_discard(struct loop_device *lo, struct request *rq, loff_t pos)
{ {
/* /*
@ -464,10 +403,17 @@ static int do_req_filebacked(struct loop_device *lo, struct request *rq)
ret = lo_req_flush(lo, rq); ret = lo_req_flush(lo, rq);
else if (rq->cmd_flags & REQ_DISCARD) else if (rq->cmd_flags & REQ_DISCARD)
ret = lo_discard(lo, rq, pos); ret = lo_discard(lo, rq, pos);
else if (lo->transfer)
ret = lo_write_transfer(lo, rq, pos);
else else
ret = lo_send(lo, rq, pos); ret = lo_write_simple(lo, rq, pos);
} else
ret = lo_receive(lo, rq, lo->lo_blocksize, pos); } else {
if (lo->transfer)
ret = lo_read_transfer(lo, rq, pos);
else
ret = lo_read_simple(lo, rq, pos);
}
return ret; return ret;
} }
@ -788,7 +734,7 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
lo->lo_device = bdev; lo->lo_device = bdev;
lo->lo_flags = lo_flags; lo->lo_flags = lo_flags;
lo->lo_backing_file = file; lo->lo_backing_file = file;
lo->transfer = transfer_none; lo->transfer = NULL;
lo->ioctl = NULL; lo->ioctl = NULL;
lo->lo_sizelimit = 0; lo->lo_sizelimit = 0;
lo->old_gfp_mask = mapping_gfp_mask(mapping); lo->old_gfp_mask = mapping_gfp_mask(mapping);
@ -1007,7 +953,7 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
memcpy(lo->lo_encrypt_key, info->lo_encrypt_key, memcpy(lo->lo_encrypt_key, info->lo_encrypt_key,
info->lo_encrypt_key_size); info->lo_encrypt_key_size);
lo->lo_key_owner = uid; lo->lo_key_owner = uid;
} }
return 0; return 0;
} }

View File

@ -359,8 +359,8 @@ static ssize_t ll_direct_IO_26_seg(const struct lu_env *env, struct cl_io *io,
* up to 22MB for 128kB kmalloc and up to 682MB for 4MB kmalloc. */ * up to 22MB for 128kB kmalloc and up to 682MB for 4MB kmalloc. */
#define MAX_DIO_SIZE ((MAX_MALLOC / sizeof(struct brw_page) * PAGE_CACHE_SIZE) & \ #define MAX_DIO_SIZE ((MAX_MALLOC / sizeof(struct brw_page) * PAGE_CACHE_SIZE) & \
~(DT_MAX_BRW_SIZE - 1)) ~(DT_MAX_BRW_SIZE - 1))
static ssize_t ll_direct_IO_26(int rw, struct kiocb *iocb, static ssize_t ll_direct_IO_26(struct kiocb *iocb, struct iov_iter *iter,
struct iov_iter *iter, loff_t file_offset) loff_t file_offset)
{ {
struct lu_env *env; struct lu_env *env;
struct cl_io *io; struct cl_io *io;
@ -399,7 +399,7 @@ static ssize_t ll_direct_IO_26(int rw, struct kiocb *iocb,
* size changing by concurrent truncates and writes. * size changing by concurrent truncates and writes.
* 1. Need inode mutex to operate transient pages. * 1. Need inode mutex to operate transient pages.
*/ */
if (rw == READ) if (iov_iter_rw(iter) == READ)
mutex_lock(&inode->i_mutex); mutex_lock(&inode->i_mutex);
LASSERT(obj->cob_transient_pages == 0); LASSERT(obj->cob_transient_pages == 0);
@ -408,7 +408,7 @@ static ssize_t ll_direct_IO_26(int rw, struct kiocb *iocb,
size_t offs; size_t offs;
count = min_t(size_t, iov_iter_count(iter), size); count = min_t(size_t, iov_iter_count(iter), size);
if (rw == READ) { if (iov_iter_rw(iter) == READ) {
if (file_offset >= i_size_read(inode)) if (file_offset >= i_size_read(inode))
break; break;
if (file_offset + count > i_size_read(inode)) if (file_offset + count > i_size_read(inode))
@ -418,11 +418,11 @@ static ssize_t ll_direct_IO_26(int rw, struct kiocb *iocb,
result = iov_iter_get_pages_alloc(iter, &pages, count, &offs); result = iov_iter_get_pages_alloc(iter, &pages, count, &offs);
if (likely(result > 0)) { if (likely(result > 0)) {
int n = DIV_ROUND_UP(result + offs, PAGE_SIZE); int n = DIV_ROUND_UP(result + offs, PAGE_SIZE);
result = ll_direct_IO_26_seg(env, io, rw, inode, result = ll_direct_IO_26_seg(env, io, iov_iter_rw(iter),
file->f_mapping, inode, file->f_mapping,
result, file_offset, result, file_offset, pages,
pages, n); n);
ll_free_user_pages(pages, n, rw==READ); ll_free_user_pages(pages, n, iov_iter_rw(iter) == READ);
} }
if (unlikely(result <= 0)) { if (unlikely(result <= 0)) {
/* If we can't allocate a large enough buffer /* If we can't allocate a large enough buffer
@ -449,11 +449,11 @@ static ssize_t ll_direct_IO_26(int rw, struct kiocb *iocb,
} }
out: out:
LASSERT(obj->cob_transient_pages == 0); LASSERT(obj->cob_transient_pages == 0);
if (rw == READ) if (iov_iter_rw(iter) == READ)
mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex);
if (tot_bytes > 0) { if (tot_bytes > 0) {
if (rw == WRITE) { if (iov_iter_rw(iter) == WRITE) {
struct lov_stripe_md *lsm; struct lov_stripe_md *lsm;
lsm = ccc_inode_lsm_get(inode); lsm = ccc_inode_lsm_get(inode);

View File

@ -230,7 +230,6 @@ static int v9fs_launder_page(struct page *page)
/** /**
* v9fs_direct_IO - 9P address space operation for direct I/O * v9fs_direct_IO - 9P address space operation for direct I/O
* @rw: direction (read or write)
* @iocb: target I/O control block * @iocb: target I/O control block
* @iov: array of vectors that define I/O buffer * @iov: array of vectors that define I/O buffer
* @pos: offset in file to begin the operation * @pos: offset in file to begin the operation
@ -248,12 +247,12 @@ static int v9fs_launder_page(struct page *page)
* *
*/ */
static ssize_t static ssize_t
v9fs_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, loff_t pos) v9fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter, loff_t pos)
{ {
struct file *file = iocb->ki_filp; struct file *file = iocb->ki_filp;
ssize_t n; ssize_t n;
int err = 0; int err = 0;
if (rw & WRITE) { if (iov_iter_rw(iter) == WRITE) {
n = p9_client_write(file->private_data, pos, iter, &err); n = p9_client_write(file->private_data, pos, iter, &err);
if (n) { if (n) {
struct inode *inode = file_inode(file); struct inode *inode = file_inode(file);

View File

@ -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, 0); 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)
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;
} }

View File

@ -389,8 +389,7 @@ static void affs_write_failed(struct address_space *mapping, loff_t to)
} }
static ssize_t static ssize_t
affs_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, affs_direct_IO(struct kiocb *iocb, struct iov_iter *iter, loff_t offset)
loff_t offset)
{ {
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;
@ -398,15 +397,15 @@ affs_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter,
size_t count = iov_iter_count(iter); size_t count = iov_iter_count(iter);
ssize_t ret; ssize_t ret;
if (rw == WRITE) { if (iov_iter_rw(iter) == WRITE) {
loff_t size = offset + count; loff_t size = offset + count;
if (AFFS_I(inode)->mmu_private < size) if (AFFS_I(inode)->mmu_private < size)
return 0; return 0;
} }
ret = blockdev_direct_IO(rw, iocb, inode, iter, offset, affs_get_block); ret = blockdev_direct_IO(iocb, inode, iter, offset, affs_get_block);
if (ret < 0 && (rw & WRITE)) if (ret < 0 && iov_iter_rw(iter) == WRITE)
affs_write_failed(mapping, offset + count); affs_write_failed(mapping, offset + count);
return ret; return ret;
} }

View File

@ -1517,7 +1517,7 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
} }
req->common.ki_pos = iocb->aio_offset; req->common.ki_pos = iocb->aio_offset;
req->common.ki_complete = aio_complete; req->common.ki_complete = aio_complete;
req->common.ki_flags = 0; req->common.ki_flags = iocb_flags(req->common.ki_filp);
if (iocb->aio_flags & IOCB_FLAG_RESFD) { if (iocb->aio_flags & IOCB_FLAG_RESFD) {
/* /*

View File

@ -146,15 +146,13 @@ blkdev_get_block(struct inode *inode, sector_t iblock,
} }
static ssize_t static ssize_t
blkdev_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, loff_t offset)
loff_t offset)
{ {
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;
return __blockdev_direct_IO(rw, iocb, inode, I_BDEV(inode), iter, return __blockdev_direct_IO(iocb, inode, I_BDEV(inode), iter, offset,
offset, blkdev_get_block, blkdev_get_block, NULL, NULL, 0);
NULL, NULL, 0);
} }
int __sync_blockdev(struct block_device *bdev, int wait) int __sync_blockdev(struct block_device *bdev, int wait)
@ -1597,9 +1595,22 @@ static long block_ioctl(struct file *file, unsigned cmd, unsigned long arg)
ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from) ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from)
{ {
struct file *file = iocb->ki_filp; struct file *file = iocb->ki_filp;
struct inode *bd_inode = file->f_mapping->host;
loff_t size = i_size_read(bd_inode);
struct blk_plug plug; struct blk_plug plug;
ssize_t ret; ssize_t ret;
if (bdev_read_only(I_BDEV(bd_inode)))
return -EPERM;
if (!iov_iter_count(from))
return 0;
if (iocb->ki_pos >= size)
return -ENOSPC;
iov_iter_truncate(from, size - iocb->ki_pos);
blk_start_plug(&plug); blk_start_plug(&plug);
ret = __generic_file_write_iter(iocb, from); ret = __generic_file_write_iter(iocb, from);
if (ret > 0) { if (ret > 0) {

View File

@ -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);
if (err <= 0) {
mutex_unlock(&inode->i_mutex);
return err;
}
current->backing_dev_info = inode_to_bdi(inode); current->backing_dev_info = inode_to_bdi(inode);
err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode));
if (err) {
mutex_unlock(&inode->i_mutex);
goto out;
}
if (count == 0) {
mutex_unlock(&inode->i_mutex);
goto out;
}
iov_iter_truncate(from, count);
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,
*/ */
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 */
@ -1800,7 +1794,7 @@ static ssize_t btrfs_file_write_iter(struct kiocb *iocb,
if (sync) if (sync)
atomic_inc(&BTRFS_I(inode)->sync_writers); atomic_inc(&BTRFS_I(inode)->sync_writers);
if (file->f_flags & O_DIRECT) { if (iocb->ki_flags & IOCB_DIRECT) {
num_written = __btrfs_direct_write(iocb, from, pos); num_written = __btrfs_direct_write(iocb, from, pos);
} else { } else {
num_written = __btrfs_buffered_write(file, from, pos); num_written = __btrfs_buffered_write(file, from, pos);

View File

@ -8081,7 +8081,7 @@ free_ordered:
bio_endio(dio_bio, ret); bio_endio(dio_bio, ret);
} }
static ssize_t check_direct_IO(struct btrfs_root *root, int rw, struct kiocb *iocb, static ssize_t check_direct_IO(struct btrfs_root *root, struct kiocb *iocb,
const struct iov_iter *iter, loff_t offset) const struct iov_iter *iter, loff_t offset)
{ {
int seg; int seg;
@ -8096,7 +8096,7 @@ static ssize_t check_direct_IO(struct btrfs_root *root, int rw, struct kiocb *io
goto out; goto out;
/* If this is a write we don't need to check anymore */ /* If this is a write we don't need to check anymore */
if (rw & WRITE) if (iov_iter_rw(iter) == WRITE)
return 0; return 0;
/* /*
* Check to make sure we don't have duplicate iov_base's in this * Check to make sure we don't have duplicate iov_base's in this
@ -8114,8 +8114,8 @@ out:
return retval; return retval;
} }
static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb, static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
struct iov_iter *iter, loff_t offset) loff_t offset)
{ {
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;
@ -8126,7 +8126,7 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb,
bool relock = false; bool relock = false;
ssize_t ret; ssize_t ret;
if (check_direct_IO(BTRFS_I(inode)->root, rw, iocb, iter, offset)) if (check_direct_IO(BTRFS_I(inode)->root, iocb, iter, offset))
return 0; return 0;
atomic_inc(&inode->i_dio_count); atomic_inc(&inode->i_dio_count);
@ -8144,7 +8144,7 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb,
filemap_fdatawrite_range(inode->i_mapping, offset, filemap_fdatawrite_range(inode->i_mapping, offset,
offset + count - 1); offset + count - 1);
if (rw & WRITE) { if (iov_iter_rw(iter) == WRITE) {
/* /*
* If the write DIO is beyond the EOF, we need update * If the write DIO is beyond the EOF, we need update
* the isize, but it is protected by i_mutex. So we can * the isize, but it is protected by i_mutex. So we can
@ -8174,11 +8174,11 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb,
wakeup = false; wakeup = false;
} }
ret = __blockdev_direct_IO(rw, iocb, inode, ret = __blockdev_direct_IO(iocb, inode,
BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev, BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev,
iter, offset, btrfs_get_blocks_direct, NULL, iter, offset, btrfs_get_blocks_direct, NULL,
btrfs_submit_direct, flags); btrfs_submit_direct, flags);
if (rw & WRITE) { if (iov_iter_rw(iter) == WRITE) {
current->journal_info = NULL; current->journal_info = NULL;
if (ret < 0 && ret != -EIOCBQUEUED) if (ret < 0 && ret != -EIOCBQUEUED)
btrfs_delalloc_release_space(inode, count); btrfs_delalloc_release_space(inode, count);

View File

@ -1198,8 +1198,7 @@ static int ceph_write_end(struct file *file, struct address_space *mapping,
* intercept O_DIRECT reads and writes early, this function should * intercept O_DIRECT reads and writes early, this function should
* never get called. * never get called.
*/ */
static ssize_t ceph_direct_io(int rw, struct kiocb *iocb, static ssize_t ceph_direct_io(struct kiocb *iocb, struct iov_iter *iter,
struct iov_iter *iter,
loff_t pos) loff_t pos)
{ {
WARN_ON(1); WARN_ON(1);

View File

@ -457,7 +457,7 @@ static ssize_t ceph_sync_read(struct kiocb *iocb, struct iov_iter *i,
if (ret < 0) if (ret < 0)
return ret; return ret;
if (file->f_flags & O_DIRECT) { if (iocb->ki_flags & IOCB_DIRECT) {
while (iov_iter_count(i)) { while (iov_iter_count(i)) {
size_t start; size_t start;
ssize_t n; ssize_t n;
@ -828,7 +828,7 @@ again:
return ret; return ret;
if ((got & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)) == 0 || if ((got & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)) == 0 ||
(iocb->ki_filp->f_flags & O_DIRECT) || (iocb->ki_flags & IOCB_DIRECT) ||
(fi->flags & CEPH_F_SYNC)) { (fi->flags & CEPH_F_SYNC)) {
dout("aio_sync_read %p %llx.%llx %llu~%u got cap refs on %s\n", dout("aio_sync_read %p %llx.%llx %llu~%u got cap refs on %s\n",
@ -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)
/* 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, S_ISBLK(inode->i_mode)); err = generic_write_checks(iocb, from);
if (err) if (err <= 0)
goto out; goto out;
if (count == 0) pos = iocb->ki_pos;
goto out; count = iov_iter_count(from);
iov_iter_truncate(from, count);
err = file_remove_suid(file); err = file_remove_suid(file);
if (err) if (err)
goto out; goto out;
@ -997,12 +995,12 @@ retry_snap:
inode, ceph_vinop(inode), pos, count, ceph_cap_string(got)); inode, ceph_vinop(inode), pos, count, ceph_cap_string(got));
if ((got & (CEPH_CAP_FILE_BUFFER|CEPH_CAP_FILE_LAZYIO)) == 0 || if ((got & (CEPH_CAP_FILE_BUFFER|CEPH_CAP_FILE_LAZYIO)) == 0 ||
(file->f_flags & O_DIRECT) || (fi->flags & CEPH_F_SYNC)) { (iocb->ki_flags & IOCB_DIRECT) || (fi->flags & CEPH_F_SYNC)) {
struct iov_iter data; struct iov_iter data;
mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex);
/* we might need to revert back to that point */ /* we might need to revert back to that point */
data = *from; data = *from;
if (file->f_flags & O_DIRECT) if (iocb->ki_flags & IOCB_DIRECT)
written = ceph_sync_direct_write(iocb, &data, pos); written = ceph_sync_direct_write(iocb, &data, pos);
else else
written = ceph_sync_write(iocb, &data, pos); written = ceph_sync_write(iocb, &data, pos);

View File

@ -2560,10 +2560,9 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from,
return rc; return rc;
} }
static ssize_t ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from)
cifs_iovec_write(struct file *file, struct iov_iter *from, loff_t *poffset)
{ {
size_t len; struct file *file = iocb->ki_filp;
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;
@ -2573,16 +2572,16 @@ cifs_iovec_write(struct file *file, struct iov_iter *from, loff_t *poffset)
struct iov_iter saved_from; struct iov_iter saved_from;
int rc; int rc;
len = iov_iter_count(from); /*
rc = generic_write_checks(file, poffset, &len, 0); * BB - optimize the way when signing is disabled. We can drop this
if (rc) * extra memory-to-memory copying and use iovec buffers for constructing
* write request.
*/
rc = generic_write_checks(iocb, from);
if (rc <= 0)
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;
@ -2593,8 +2592,8 @@ cifs_iovec_write(struct file *file, struct iov_iter *from, loff_t *poffset)
memcpy(&saved_from, from, sizeof(struct iov_iter)); memcpy(&saved_from, from, sizeof(struct iov_iter));
rc = cifs_write_from_iter(*poffset, 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
@ -2633,7 +2632,7 @@ restart_loop:
memcpy(&tmp_from, &saved_from, memcpy(&tmp_from, &saved_from,
sizeof(struct iov_iter)); sizeof(struct iov_iter));
iov_iter_advance(&tmp_from, iov_iter_advance(&tmp_from,
wdata->offset - *poffset); wdata->offset - iocb->ki_pos);
rc = cifs_write_from_iter(wdata->offset, rc = cifs_write_from_iter(wdata->offset,
wdata->bytes, &tmp_from, wdata->bytes, &tmp_from,
@ -2650,34 +2649,13 @@ restart_loop:
kref_put(&wdata->refcount, cifs_uncached_writedata_release); kref_put(&wdata->refcount, cifs_uncached_writedata_release);
} }
if (total_written > 0) if (unlikely(!total_written))
*poffset += total_written; return rc;
iocb->ki_pos += total_written;
set_bit(CIFS_INO_INVALID_MAPPING, &CIFS_I(file_inode(file))->flags);
cifs_stats_bytes_written(tcon, total_written); cifs_stats_bytes_written(tcon, total_written);
return total_written ? total_written : (ssize_t)rc; return total_written;
}
ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from)
{
ssize_t written;
struct inode *inode;
loff_t pos = iocb->ki_pos;
inode = file_inode(iocb->ki_filp);
/*
* BB - optimize the way when signing is disabled. We can drop this
* extra memory-to-memory copying and use iovec buffers for constructing
* write request.
*/
written = cifs_iovec_write(iocb->ki_filp, from, &pos);
if (written > 0) {
set_bit(CIFS_INO_INVALID_MAPPING, &CIFS_I(inode)->flags);
iocb->ki_pos = pos;
}
return written;
} }
static ssize_t static ssize_t
@ -2688,8 +2666,7 @@ cifs_writev(struct kiocb *iocb, struct iov_iter *from)
struct inode *inode = file->f_mapping->host; struct inode *inode = file->f_mapping->host;
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 = -EACCES; ssize_t rc;
loff_t lock_pos = iocb->ki_pos;
/* /*
* 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
@ -2697,23 +2674,24 @@ 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);
if (file->f_flags & O_APPEND)
lock_pos = i_size_read(inode); rc = generic_write_checks(iocb, from);
if (!cifs_find_lock_conflict(cfile, lock_pos, iov_iter_count(from), if (rc <= 0)
goto out;
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))
rc = __generic_file_write_iter(iocb, from); rc = __generic_file_write_iter(iocb, from);
mutex_unlock(&inode->i_mutex); else
rc = -EACCES;
out:
mutex_unlock(&inode->i_mutex);
if (rc > 0) { if (rc > 0) {
ssize_t err; ssize_t err = generic_write_sync(file, iocb->ki_pos - rc, rc);
if (err < 0)
err = generic_write_sync(file, iocb->ki_pos - rc, rc); rc = err;
if (err < 0)
rc = err;
}
} else {
mutex_unlock(&inode->i_mutex);
} }
up_read(&cinode->lock_sem); up_read(&cinode->lock_sem);
return rc; return rc;
@ -3877,8 +3855,7 @@ void cifs_oplock_break(struct work_struct *work)
* Direct IO is not yet supported in the cached mode. * Direct IO is not yet supported in the cached mode.
*/ */
static ssize_t static ssize_t
cifs_direct_io(int rw, struct kiocb *iocb, struct iov_iter *iter, cifs_direct_io(struct kiocb *iocb, struct iov_iter *iter, loff_t pos)
loff_t pos)
{ {
/* /*
* FIXME * FIXME

View File

@ -1598,7 +1598,7 @@ static loff_t configfs_dir_lseek(struct file *file, loff_t offset, int whence)
if (offset >= 0) if (offset >= 0)
break; break;
default: default:
mutex_unlock(&file_inode(file)->i_mutex); mutex_unlock(&dentry->d_inode->i_mutex);
return -EINVAL; return -EINVAL;
} }
if (offset != file->f_pos) { if (offset != file->f_pos) {

View File

@ -98,9 +98,9 @@ static bool buffer_size_valid(struct buffer_head *bh)
return bh->b_state != 0; return bh->b_state != 0;
} }
static ssize_t dax_io(int rw, struct inode *inode, struct iov_iter *iter, static ssize_t dax_io(struct inode *inode, struct iov_iter *iter,
loff_t start, loff_t end, get_block_t get_block, loff_t start, loff_t end, get_block_t get_block,
struct buffer_head *bh) struct buffer_head *bh)
{ {
ssize_t retval = 0; ssize_t retval = 0;
loff_t pos = start; loff_t pos = start;
@ -109,7 +109,7 @@ static ssize_t dax_io(int rw, struct inode *inode, struct iov_iter *iter,
void *addr; void *addr;
bool hole = false; bool hole = false;
if (rw != WRITE) if (iov_iter_rw(iter) != WRITE)
end = min(end, i_size_read(inode)); end = min(end, i_size_read(inode));
while (pos < end) { while (pos < end) {
@ -124,7 +124,7 @@ static ssize_t dax_io(int rw, struct inode *inode, struct iov_iter *iter,
bh->b_size = PAGE_ALIGN(end - pos); bh->b_size = PAGE_ALIGN(end - pos);
bh->b_state = 0; bh->b_state = 0;
retval = get_block(inode, block, bh, retval = get_block(inode, block, bh,
rw == WRITE); iov_iter_rw(iter) == WRITE);
if (retval) if (retval)
break; break;
if (!buffer_size_valid(bh)) if (!buffer_size_valid(bh))
@ -137,7 +137,7 @@ static ssize_t dax_io(int rw, struct inode *inode, struct iov_iter *iter,
bh->b_size -= done; bh->b_size -= done;
} }
hole = (rw != WRITE) && !buffer_written(bh); hole = iov_iter_rw(iter) != WRITE && !buffer_written(bh);
if (hole) { if (hole) {
addr = NULL; addr = NULL;
size = bh->b_size - first; size = bh->b_size - first;
@ -154,7 +154,7 @@ static ssize_t dax_io(int rw, struct inode *inode, struct iov_iter *iter,
max = min(pos + size, end); max = min(pos + size, end);
} }
if (rw == WRITE) if (iov_iter_rw(iter) == WRITE)
len = copy_from_iter(addr, max - pos, iter); len = copy_from_iter(addr, max - pos, iter);
else if (!hole) else if (!hole)
len = copy_to_iter(addr, max - pos, iter); len = copy_to_iter(addr, max - pos, iter);
@ -173,7 +173,6 @@ static ssize_t dax_io(int rw, struct inode *inode, struct iov_iter *iter,
/** /**
* dax_do_io - Perform I/O to a DAX file * dax_do_io - Perform I/O to a DAX file
* @rw: READ to read or WRITE to write
* @iocb: The control block for this I/O * @iocb: The control block for this I/O
* @inode: The file which the I/O is directed at * @inode: The file which the I/O is directed at
* @iter: The addresses to do I/O from or to * @iter: The addresses to do I/O from or to
@ -189,9 +188,9 @@ static ssize_t dax_io(int rw, struct inode *inode, struct iov_iter *iter,
* As with do_blockdev_direct_IO(), we increment i_dio_count while the I/O * As with do_blockdev_direct_IO(), we increment i_dio_count while the I/O
* is in progress. * is in progress.
*/ */
ssize_t dax_do_io(int rw, struct kiocb *iocb, struct inode *inode, ssize_t dax_do_io(struct kiocb *iocb, struct inode *inode,
struct iov_iter *iter, loff_t pos, struct iov_iter *iter, loff_t pos, get_block_t get_block,
get_block_t get_block, dio_iodone_t end_io, int flags) dio_iodone_t end_io, int flags)
{ {
struct buffer_head bh; struct buffer_head bh;
ssize_t retval = -EINVAL; ssize_t retval = -EINVAL;
@ -199,7 +198,7 @@ ssize_t dax_do_io(int rw, struct kiocb *iocb, struct inode *inode,
memset(&bh, 0, sizeof(bh)); memset(&bh, 0, sizeof(bh));
if ((flags & DIO_LOCKING) && (rw == READ)) { if ((flags & DIO_LOCKING) && iov_iter_rw(iter) == READ) {
struct address_space *mapping = inode->i_mapping; struct address_space *mapping = inode->i_mapping;
mutex_lock(&inode->i_mutex); mutex_lock(&inode->i_mutex);
retval = filemap_write_and_wait_range(mapping, pos, end - 1); retval = filemap_write_and_wait_range(mapping, pos, end - 1);
@ -212,9 +211,9 @@ ssize_t dax_do_io(int rw, struct kiocb *iocb, struct inode *inode,
/* Protects against truncate */ /* Protects against truncate */
atomic_inc(&inode->i_dio_count); atomic_inc(&inode->i_dio_count);
retval = dax_io(rw, inode, iter, pos, end, get_block, &bh); retval = dax_io(inode, iter, pos, end, get_block, &bh);
if ((flags & DIO_LOCKING) && (rw == READ)) if ((flags & DIO_LOCKING) && iov_iter_rw(iter) == READ)
mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex);
if ((retval > 0) && end_io) if ((retval > 0) && end_io)

View File

@ -269,6 +269,41 @@ static inline int dname_external(const struct dentry *dentry)
return dentry->d_name.name != dentry->d_iname; return dentry->d_name.name != dentry->d_iname;
} }
/*
* Make sure other CPUs see the inode attached before the type is set.
*/
static inline void __d_set_inode_and_type(struct dentry *dentry,
struct inode *inode,
unsigned type_flags)
{
unsigned flags;
dentry->d_inode = inode;
smp_wmb();
flags = READ_ONCE(dentry->d_flags);
flags &= ~(DCACHE_ENTRY_TYPE | DCACHE_FALLTHRU);
flags |= type_flags;
WRITE_ONCE(dentry->d_flags, flags);
}
/*
* Ideally, we want to make sure that other CPUs see the flags cleared before
* the inode is detached, but this is really a violation of RCU principles
* since the ordering suggests we should always set inode before flags.
*
* We should instead replace or discard the entire dentry - but that sucks
* performancewise on mass deletion/rename.
*/
static inline void __d_clear_type_and_inode(struct dentry *dentry)
{
unsigned flags = READ_ONCE(dentry->d_flags);
flags &= ~(DCACHE_ENTRY_TYPE | DCACHE_FALLTHRU);
WRITE_ONCE(dentry->d_flags, flags);
smp_wmb();
dentry->d_inode = NULL;
}
static void dentry_free(struct dentry *dentry) static void dentry_free(struct dentry *dentry)
{ {
WARN_ON(!hlist_unhashed(&dentry->d_u.d_alias)); WARN_ON(!hlist_unhashed(&dentry->d_u.d_alias));
@ -311,7 +346,7 @@ static void dentry_iput(struct dentry * dentry)
{ {
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
if (inode) { if (inode) {
dentry->d_inode = NULL; __d_clear_type_and_inode(dentry);
hlist_del_init(&dentry->d_u.d_alias); hlist_del_init(&dentry->d_u.d_alias);
spin_unlock(&dentry->d_lock); spin_unlock(&dentry->d_lock);
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
@ -335,8 +370,7 @@ static void dentry_unlink_inode(struct dentry * dentry)
__releases(dentry->d_inode->i_lock) __releases(dentry->d_inode->i_lock)
{ {
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
__d_clear_type(dentry); __d_clear_type_and_inode(dentry);
dentry->d_inode = NULL;
hlist_del_init(&dentry->d_u.d_alias); hlist_del_init(&dentry->d_u.d_alias);
dentry_rcuwalk_barrier(dentry); dentry_rcuwalk_barrier(dentry);
spin_unlock(&dentry->d_lock); spin_unlock(&dentry->d_lock);
@ -1715,11 +1749,9 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode)
unsigned add_flags = d_flags_for_inode(inode); unsigned add_flags = d_flags_for_inode(inode);
spin_lock(&dentry->d_lock); spin_lock(&dentry->d_lock);
dentry->d_flags &= ~(DCACHE_ENTRY_TYPE | DCACHE_FALLTHRU);
dentry->d_flags |= add_flags;
if (inode) if (inode)
hlist_add_head(&dentry->d_u.d_alias, &inode->i_dentry); hlist_add_head(&dentry->d_u.d_alias, &inode->i_dentry);
dentry->d_inode = inode; __d_set_inode_and_type(dentry, inode, add_flags);
dentry_rcuwalk_barrier(dentry); dentry_rcuwalk_barrier(dentry);
spin_unlock(&dentry->d_lock); spin_unlock(&dentry->d_lock);
fsnotify_d_instantiate(dentry, inode); fsnotify_d_instantiate(dentry, inode);
@ -1937,8 +1969,7 @@ static struct dentry *__d_obtain_alias(struct inode *inode, int disconnected)
add_flags |= DCACHE_DISCONNECTED; add_flags |= DCACHE_DISCONNECTED;
spin_lock(&tmp->d_lock); spin_lock(&tmp->d_lock);
tmp->d_inode = inode; __d_set_inode_and_type(tmp, inode, add_flags);
tmp->d_flags |= add_flags;
hlist_add_head(&tmp->d_u.d_alias, &inode->i_dentry); hlist_add_head(&tmp->d_u.d_alias, &inode->i_dentry);
hlist_bl_lock(&tmp->d_sb->s_anon); hlist_bl_lock(&tmp->d_sb->s_anon);
hlist_bl_add_head(&tmp->d_hash, &tmp->d_sb->s_anon); hlist_bl_add_head(&tmp->d_hash, &tmp->d_sb->s_anon);

View File

@ -524,7 +524,7 @@ static int __debugfs_remove(struct dentry *dentry, struct dentry *parent)
if (debugfs_positive(dentry)) { if (debugfs_positive(dentry)) {
dget(dentry); dget(dentry);
if (S_ISDIR(dentry->d_inode->i_mode)) if (d_is_dir(dentry))
ret = simple_rmdir(parent->d_inode, dentry); ret = simple_rmdir(parent->d_inode, dentry);
else else
simple_unlink(parent->d_inode, dentry); simple_unlink(parent->d_inode, dentry);

View File

@ -1093,10 +1093,10 @@ static inline int drop_refcount(struct dio *dio)
* for the whole file. * for the whole file.
*/ */
static inline ssize_t static inline ssize_t
do_blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, do_blockdev_direct_IO(struct kiocb *iocb, struct inode *inode,
struct block_device *bdev, struct iov_iter *iter, loff_t offset, struct block_device *bdev, struct iov_iter *iter,
get_block_t get_block, dio_iodone_t end_io, loff_t offset, get_block_t get_block, dio_iodone_t end_io,
dio_submit_t submit_io, int flags) dio_submit_t submit_io, int flags)
{ {
unsigned i_blkbits = ACCESS_ONCE(inode->i_blkbits); unsigned i_blkbits = ACCESS_ONCE(inode->i_blkbits);
unsigned blkbits = i_blkbits; unsigned blkbits = i_blkbits;
@ -1110,9 +1110,6 @@ do_blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
struct blk_plug plug; struct blk_plug plug;
unsigned long align = offset | iov_iter_alignment(iter); unsigned long align = offset | iov_iter_alignment(iter);
if (rw & WRITE)
rw = WRITE_ODIRECT;
/* /*
* Avoid references to bdev if not absolutely needed to give * Avoid references to bdev if not absolutely needed to give
* the early prefetch in the caller enough time. * the early prefetch in the caller enough time.
@ -1127,7 +1124,7 @@ do_blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
} }
/* watch out for a 0 len io from a tricksy fs */ /* watch out for a 0 len io from a tricksy fs */
if (rw == READ && !iov_iter_count(iter)) if (iov_iter_rw(iter) == READ && !iov_iter_count(iter))
return 0; return 0;
dio = kmem_cache_alloc(dio_cache, GFP_KERNEL); dio = kmem_cache_alloc(dio_cache, GFP_KERNEL);
@ -1143,7 +1140,7 @@ do_blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
dio->flags = flags; dio->flags = flags;
if (dio->flags & DIO_LOCKING) { if (dio->flags & DIO_LOCKING) {
if (rw == READ) { if (iov_iter_rw(iter) == READ) {
struct address_space *mapping = struct address_space *mapping =
iocb->ki_filp->f_mapping; iocb->ki_filp->f_mapping;
@ -1169,19 +1166,19 @@ do_blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
if (is_sync_kiocb(iocb)) if (is_sync_kiocb(iocb))
dio->is_async = false; dio->is_async = false;
else if (!(dio->flags & DIO_ASYNC_EXTEND) && else if (!(dio->flags & DIO_ASYNC_EXTEND) &&
(rw & WRITE) && end > i_size_read(inode)) iov_iter_rw(iter) == WRITE && end > i_size_read(inode))
dio->is_async = false; dio->is_async = false;
else else
dio->is_async = true; dio->is_async = true;
dio->inode = inode; dio->inode = inode;
dio->rw = rw; dio->rw = iov_iter_rw(iter) == WRITE ? WRITE_ODIRECT : READ;
/* /*
* For AIO O_(D)SYNC writes we need to defer completions to a workqueue * For AIO O_(D)SYNC writes we need to defer completions to a workqueue
* so that we can call ->fsync. * so that we can call ->fsync.
*/ */
if (dio->is_async && (rw & WRITE) && if (dio->is_async && iov_iter_rw(iter) == WRITE &&
((iocb->ki_filp->f_flags & O_DSYNC) || ((iocb->ki_filp->f_flags & O_DSYNC) ||
IS_SYNC(iocb->ki_filp->f_mapping->host))) { IS_SYNC(iocb->ki_filp->f_mapping->host))) {
retval = dio_set_defer_completion(dio); retval = dio_set_defer_completion(dio);
@ -1274,7 +1271,7 @@ do_blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
* we can let i_mutex go now that its achieved its purpose * we can let i_mutex go now that its achieved its purpose
* of protecting us from looking up uninitialized blocks. * of protecting us from looking up uninitialized blocks.
*/ */
if (rw == READ && (dio->flags & DIO_LOCKING)) if (iov_iter_rw(iter) == READ && (dio->flags & DIO_LOCKING))
mutex_unlock(&dio->inode->i_mutex); mutex_unlock(&dio->inode->i_mutex);
/* /*
@ -1286,7 +1283,7 @@ do_blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
*/ */
BUG_ON(retval == -EIOCBQUEUED); BUG_ON(retval == -EIOCBQUEUED);
if (dio->is_async && retval == 0 && dio->result && if (dio->is_async && retval == 0 && dio->result &&
(rw == READ || dio->result == count)) (iov_iter_rw(iter) == READ || dio->result == count))
retval = -EIOCBQUEUED; retval = -EIOCBQUEUED;
else else
dio_await_completion(dio); dio_await_completion(dio);
@ -1300,11 +1297,11 @@ out:
return retval; return retval;
} }
ssize_t ssize_t __blockdev_direct_IO(struct kiocb *iocb, struct inode *inode,
__blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, struct block_device *bdev, struct iov_iter *iter,
struct block_device *bdev, struct iov_iter *iter, loff_t offset, loff_t offset, get_block_t get_block,
get_block_t get_block, dio_iodone_t end_io, dio_iodone_t end_io, dio_submit_t submit_io,
dio_submit_t submit_io, int flags) int flags)
{ {
/* /*
* The block device state is needed in the end to finally * The block device state is needed in the end to finally
@ -1318,8 +1315,8 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
prefetch(bdev->bd_queue); prefetch(bdev->bd_queue);
prefetch((char *)bdev->bd_queue + SMP_CACHE_BYTES); prefetch((char *)bdev->bd_queue + SMP_CACHE_BYTES);
return do_blockdev_direct_IO(rw, iocb, inode, bdev, iter, offset, return do_blockdev_direct_IO(iocb, inode, bdev, iter, offset, get_block,
get_block, end_io, submit_io, flags); end_io, submit_io, flags);
} }
EXPORT_SYMBOL(__blockdev_direct_IO); EXPORT_SYMBOL(__blockdev_direct_IO);

View File

@ -963,8 +963,8 @@ static void exofs_invalidatepage(struct page *page, unsigned int offset,
/* TODO: Should be easy enough to do proprly */ /* TODO: Should be easy enough to do proprly */
static ssize_t exofs_direct_IO(int rw, struct kiocb *iocb, static ssize_t exofs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
struct iov_iter *iter, loff_t offset) loff_t offset)
{ {
return 0; return 0;
} }

View File

@ -851,8 +851,7 @@ static sector_t ext2_bmap(struct address_space *mapping, sector_t block)
} }
static ssize_t static ssize_t
ext2_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, ext2_direct_IO(struct kiocb *iocb, struct iov_iter *iter, loff_t offset)
loff_t offset)
{ {
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;
@ -861,12 +860,12 @@ ext2_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter,
ssize_t ret; ssize_t ret;
if (IS_DAX(inode)) if (IS_DAX(inode))
ret = dax_do_io(rw, iocb, inode, iter, offset, ext2_get_block, ret = dax_do_io(iocb, inode, iter, offset, ext2_get_block, NULL,
NULL, DIO_LOCKING); DIO_LOCKING);
else else
ret = blockdev_direct_IO(rw, iocb, inode, iter, offset, ret = blockdev_direct_IO(iocb, inode, iter, offset,
ext2_get_block); ext2_get_block);
if (ret < 0 && (rw & WRITE)) if (ret < 0 && iov_iter_rw(iter) == WRITE)
ext2_write_failed(mapping, offset + count); ext2_write_failed(mapping, offset + count);
return ret; return ret;
} }

View File

@ -1820,8 +1820,8 @@ static int ext3_releasepage(struct page *page, gfp_t wait)
* crashes then stale disk data _may_ be exposed inside the file. But current * crashes then stale disk data _may_ be exposed inside the file. But current
* VFS code falls back into buffered path in that case so we are safe. * VFS code falls back into buffered path in that case so we are safe.
*/ */
static ssize_t ext3_direct_IO(int rw, struct kiocb *iocb, static ssize_t ext3_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
struct iov_iter *iter, loff_t offset) loff_t offset)
{ {
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;
@ -1832,9 +1832,9 @@ static ssize_t ext3_direct_IO(int rw, struct kiocb *iocb,
size_t count = iov_iter_count(iter); size_t count = iov_iter_count(iter);
int retries = 0; int retries = 0;
trace_ext3_direct_IO_enter(inode, offset, count, rw); trace_ext3_direct_IO_enter(inode, offset, count, iov_iter_rw(iter));
if (rw == WRITE) { if (iov_iter_rw(iter) == WRITE) {
loff_t final_size = offset + count; loff_t final_size = offset + count;
if (final_size > inode->i_size) { if (final_size > inode->i_size) {
@ -1856,12 +1856,12 @@ static ssize_t ext3_direct_IO(int rw, struct kiocb *iocb,
} }
retry: retry:
ret = blockdev_direct_IO(rw, iocb, inode, iter, offset, ext3_get_block); ret = blockdev_direct_IO(iocb, inode, iter, offset, ext3_get_block);
/* /*
* In case of error extending write may have instantiated a few * In case of error extending write may have instantiated a few
* blocks outside i_size. Trim these off again. * blocks outside i_size. Trim these off again.
*/ */
if (unlikely((rw & WRITE) && ret < 0)) { if (unlikely(iov_iter_rw(iter) == WRITE && ret < 0)) {
loff_t isize = i_size_read(inode); loff_t isize = i_size_read(inode);
loff_t end = offset + count; loff_t end = offset + count;
@ -1908,7 +1908,7 @@ retry:
ret = err; ret = err;
} }
out: out:
trace_ext3_direct_IO_exit(inode, offset, count, rw, ret); trace_ext3_direct_IO_exit(inode, offset, count, iov_iter_rw(iter), ret);
return ret; return ret;
} }

View File

@ -2152,8 +2152,8 @@ extern void ext4_da_update_reserve_space(struct inode *inode,
/* indirect.c */ /* indirect.c */
extern int ext4_ind_map_blocks(handle_t *handle, struct inode *inode, extern int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
struct ext4_map_blocks *map, int flags); struct ext4_map_blocks *map, int flags);
extern ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb, extern ssize_t ext4_ind_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
struct iov_iter *iter, loff_t offset); loff_t offset);
extern int ext4_ind_calc_metadata_amount(struct inode *inode, sector_t lblock); extern int ext4_ind_calc_metadata_amount(struct inode *inode, sector_t lblock);
extern int ext4_ind_trans_blocks(struct inode *inode, int nrblocks); extern int ext4_ind_trans_blocks(struct inode *inode, int nrblocks);
extern void ext4_ind_truncate(handle_t *, struct inode *inode); extern void ext4_ind_truncate(handle_t *, struct inode *inode);

View File

@ -95,11 +95,9 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
struct inode *inode = file_inode(iocb->ki_filp); struct inode *inode = file_inode(iocb->ki_filp);
struct mutex *aio_mutex = NULL; struct mutex *aio_mutex = NULL;
struct blk_plug plug; struct blk_plug plug;
int o_direct = io_is_direct(file); int o_direct = iocb->ki_flags & IOCB_DIRECT;
int overwrite = 0; int overwrite = 0;
size_t length = iov_iter_count(from);
ssize_t ret; ssize_t ret;
loff_t pos = iocb->ki_pos;
/* /*
* Unaligned direct AIO must be serialized; see comment above * Unaligned direct AIO must be serialized; see comment above
@ -108,16 +106,17 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
if (o_direct && if (o_direct &&
ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS) && ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS) &&
!is_sync_kiocb(iocb) && !is_sync_kiocb(iocb) &&
(file->f_flags & O_APPEND || (iocb->ki_flags & IOCB_APPEND ||
ext4_unaligned_aio(inode, from, pos))) { ext4_unaligned_aio(inode, from, iocb->ki_pos))) {
aio_mutex = ext4_aio_mutex(inode); aio_mutex = ext4_aio_mutex(inode);
mutex_lock(aio_mutex); mutex_lock(aio_mutex);
ext4_unwritten_wait(inode); ext4_unwritten_wait(inode);
} }
mutex_lock(&inode->i_mutex); mutex_lock(&inode->i_mutex);
if (file->f_flags & O_APPEND) ret = generic_write_checks(iocb, from);
iocb->ki_pos = pos = i_size_read(inode); if (ret <= 0)
goto out;
/* /*
* If we have encountered a bitmap-format file, the size limit * If we have encountered a bitmap-format file, the size limit
@ -126,22 +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) {
(pos == sbi->s_bitmap_maxbytes && length > 0)) {
mutex_unlock(&inode->i_mutex);
ret = -EFBIG; ret = -EFBIG;
goto errout; goto out;
} }
iov_iter_truncate(from, sbi->s_bitmap_maxbytes - iocb->ki_pos);
if (pos + length > sbi->s_bitmap_maxbytes)
iov_iter_truncate(from, sbi->s_bitmap_maxbytes - pos);
} }
iocb->private = &overwrite; iocb->private = &overwrite;
if (o_direct) { if (o_direct) {
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)) {
@ -185,7 +181,12 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
if (o_direct) if (o_direct)
blk_finish_plug(&plug); blk_finish_plug(&plug);
errout: if (aio_mutex)
mutex_unlock(aio_mutex);
return ret;
out:
mutex_unlock(&inode->i_mutex);
if (aio_mutex) if (aio_mutex)
mutex_unlock(aio_mutex); mutex_unlock(aio_mutex);
return ret; return ret;

View File

@ -642,8 +642,8 @@ out:
* crashes then stale disk data _may_ be exposed inside the file. But current * crashes then stale disk data _may_ be exposed inside the file. But current
* VFS code falls back into buffered path in that case so we are safe. * VFS code falls back into buffered path in that case so we are safe.
*/ */
ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb, ssize_t ext4_ind_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
struct iov_iter *iter, loff_t offset) loff_t offset)
{ {
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;
@ -654,7 +654,7 @@ ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb,
size_t count = iov_iter_count(iter); size_t count = iov_iter_count(iter);
int retries = 0; int retries = 0;
if (rw == WRITE) { if (iov_iter_rw(iter) == WRITE) {
loff_t final_size = offset + count; loff_t final_size = offset + count;
if (final_size > inode->i_size) { if (final_size > inode->i_size) {
@ -676,7 +676,7 @@ ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb,
} }
retry: retry:
if (rw == READ && ext4_should_dioread_nolock(inode)) { if (iov_iter_rw(iter) == READ && ext4_should_dioread_nolock(inode)) {
/* /*
* Nolock dioread optimization may be dynamically disabled * Nolock dioread optimization may be dynamically disabled
* via ext4_inode_block_unlocked_dio(). Check inode's state * via ext4_inode_block_unlocked_dio(). Check inode's state
@ -690,23 +690,24 @@ retry:
goto locked; goto locked;
} }
if (IS_DAX(inode)) if (IS_DAX(inode))
ret = dax_do_io(rw, iocb, inode, iter, offset, ret = dax_do_io(iocb, inode, iter, offset,
ext4_get_block, NULL, 0); ext4_get_block, NULL, 0);
else else
ret = __blockdev_direct_IO(rw, iocb, inode, ret = __blockdev_direct_IO(iocb, inode,
inode->i_sb->s_bdev, iter, offset, inode->i_sb->s_bdev, iter,
ext4_get_block, NULL, NULL, 0); offset, ext4_get_block, NULL,
NULL, 0);
inode_dio_done(inode); inode_dio_done(inode);
} else { } else {
locked: locked:
if (IS_DAX(inode)) if (IS_DAX(inode))
ret = dax_do_io(rw, iocb, inode, iter, offset, ret = dax_do_io(iocb, inode, iter, offset,
ext4_get_block, NULL, DIO_LOCKING); ext4_get_block, NULL, DIO_LOCKING);
else else
ret = blockdev_direct_IO(rw, iocb, inode, iter, ret = blockdev_direct_IO(iocb, inode, iter, offset,
offset, ext4_get_block); ext4_get_block);
if (unlikely((rw & WRITE) && ret < 0)) { if (unlikely(iov_iter_rw(iter) == WRITE && ret < 0)) {
loff_t isize = i_size_read(inode); loff_t isize = i_size_read(inode);
loff_t end = offset + count; loff_t end = offset + count;

View File

@ -2952,8 +2952,8 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset,
* if the machine crashes during the write. * if the machine crashes during the write.
* *
*/ */
static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, static ssize_t ext4_ext_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
struct iov_iter *iter, loff_t offset) loff_t offset)
{ {
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;
@ -2966,8 +2966,8 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb,
ext4_io_end_t *io_end = NULL; ext4_io_end_t *io_end = NULL;
/* Use the old path for reads and writes beyond i_size. */ /* Use the old path for reads and writes beyond i_size. */
if (rw != WRITE || final_size > inode->i_size) if (iov_iter_rw(iter) != WRITE || final_size > inode->i_size)
return ext4_ind_direct_IO(rw, iocb, iter, offset); return ext4_ind_direct_IO(iocb, iter, offset);
BUG_ON(iocb->private == NULL); BUG_ON(iocb->private == NULL);
@ -2976,7 +2976,7 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb,
* conversion. This also disallows race between truncate() and * conversion. This also disallows race between truncate() and
* overwrite DIO as i_dio_count needs to be incremented under i_mutex. * overwrite DIO as i_dio_count needs to be incremented under i_mutex.
*/ */
if (rw == WRITE) if (iov_iter_rw(iter) == WRITE)
atomic_inc(&inode->i_dio_count); atomic_inc(&inode->i_dio_count);
/* If we do a overwrite dio, i_mutex locking can be released */ /* If we do a overwrite dio, i_mutex locking can be released */
@ -3034,10 +3034,10 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb,
dio_flags = DIO_LOCKING; dio_flags = DIO_LOCKING;
} }
if (IS_DAX(inode)) if (IS_DAX(inode))
ret = dax_do_io(rw, iocb, inode, iter, offset, get_block_func, ret = dax_do_io(iocb, inode, iter, offset, get_block_func,
ext4_end_io_dio, dio_flags); ext4_end_io_dio, dio_flags);
else else
ret = __blockdev_direct_IO(rw, iocb, inode, ret = __blockdev_direct_IO(iocb, inode,
inode->i_sb->s_bdev, iter, offset, inode->i_sb->s_bdev, iter, offset,
get_block_func, get_block_func,
ext4_end_io_dio, NULL, dio_flags); ext4_end_io_dio, NULL, dio_flags);
@ -3078,7 +3078,7 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb,
} }
retake_lock: retake_lock:
if (rw == WRITE) if (iov_iter_rw(iter) == WRITE)
inode_dio_done(inode); inode_dio_done(inode);
/* take i_mutex locking again if we do a ovewrite dio */ /* take i_mutex locking again if we do a ovewrite dio */
if (overwrite) { if (overwrite) {
@ -3089,8 +3089,8 @@ retake_lock:
return ret; return ret;
} }
static ssize_t ext4_direct_IO(int rw, struct kiocb *iocb, static ssize_t ext4_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
struct iov_iter *iter, loff_t offset) loff_t offset)
{ {
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;
@ -3107,12 +3107,12 @@ static ssize_t ext4_direct_IO(int rw, struct kiocb *iocb,
if (ext4_has_inline_data(inode)) if (ext4_has_inline_data(inode))
return 0; return 0;
trace_ext4_direct_IO_enter(inode, offset, count, rw); trace_ext4_direct_IO_enter(inode, offset, count, iov_iter_rw(iter));
if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
ret = ext4_ext_direct_IO(rw, iocb, iter, offset); ret = ext4_ext_direct_IO(iocb, iter, offset);
else else
ret = ext4_ind_direct_IO(rw, iocb, iter, offset); ret = ext4_ind_direct_IO(iocb, iter, offset);
trace_ext4_direct_IO_exit(inode, offset, count, rw, ret); trace_ext4_direct_IO_exit(inode, offset, count, iov_iter_rw(iter), ret);
return ret; return ret;
} }

View File

@ -1118,12 +1118,12 @@ static int f2fs_write_end(struct file *file,
return copied; return copied;
} }
static int check_direct_IO(struct inode *inode, int rw, static int check_direct_IO(struct inode *inode, struct iov_iter *iter,
struct iov_iter *iter, loff_t offset) loff_t offset)
{ {
unsigned blocksize_mask = inode->i_sb->s_blocksize - 1; unsigned blocksize_mask = inode->i_sb->s_blocksize - 1;
if (rw == READ) if (iov_iter_rw(iter) == READ)
return 0; return 0;
if (offset & blocksize_mask) if (offset & blocksize_mask)
@ -1135,8 +1135,8 @@ static int check_direct_IO(struct inode *inode, int rw,
return 0; return 0;
} }
static ssize_t f2fs_direct_IO(int rw, struct kiocb *iocb, static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
struct iov_iter *iter, loff_t offset) loff_t offset)
{ {
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;
@ -1151,19 +1151,19 @@ static ssize_t f2fs_direct_IO(int rw, struct kiocb *iocb,
return err; return err;
} }
if (check_direct_IO(inode, rw, iter, offset)) if (check_direct_IO(inode, iter, offset))
return 0; return 0;
trace_f2fs_direct_IO_enter(inode, offset, count, rw); trace_f2fs_direct_IO_enter(inode, offset, count, iov_iter_rw(iter));
if (rw & WRITE) if (iov_iter_rw(iter) == WRITE)
__allocate_data_blocks(inode, offset, count); __allocate_data_blocks(inode, offset, count);
err = blockdev_direct_IO(rw, iocb, inode, iter, offset, get_data_block); err = blockdev_direct_IO(iocb, inode, iter, offset, get_data_block);
if (err < 0 && (rw & WRITE)) if (err < 0 && iov_iter_rw(iter) == WRITE)
f2fs_write_failed(mapping, offset + count); f2fs_write_failed(mapping, offset + count);
trace_f2fs_direct_IO_exit(inode, offset, count, rw, err); trace_f2fs_direct_IO_exit(inode, offset, count, iov_iter_rw(iter), err);
return err; return err;
} }

View File

@ -245,8 +245,7 @@ static int fat_write_end(struct file *file, struct address_space *mapping,
return err; return err;
} }
static ssize_t fat_direct_IO(int rw, struct kiocb *iocb, static ssize_t fat_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
struct iov_iter *iter,
loff_t offset) loff_t offset)
{ {
struct file *file = iocb->ki_filp; struct file *file = iocb->ki_filp;
@ -255,7 +254,7 @@ static ssize_t fat_direct_IO(int rw, struct kiocb *iocb,
size_t count = iov_iter_count(iter); size_t count = iov_iter_count(iter);
ssize_t ret; ssize_t ret;
if (rw == WRITE) { if (iov_iter_rw(iter) == WRITE) {
/* /*
* FIXME: blockdev_direct_IO() doesn't use ->write_begin(), * FIXME: blockdev_direct_IO() doesn't use ->write_begin(),
* so we need to update the ->mmu_private to block boundary. * so we need to update the ->mmu_private to block boundary.
@ -274,8 +273,8 @@ static ssize_t fat_direct_IO(int rw, struct kiocb *iocb,
* FAT need to use the DIO_LOCKING for avoiding the race * FAT need to use the DIO_LOCKING for avoiding the race
* condition of fat_get_block() and ->truncate(). * condition of fat_get_block() and ->truncate().
*/ */
ret = blockdev_direct_IO(rw, iocb, inode, iter, offset, fat_get_block); ret = blockdev_direct_IO(iocb, inode, iter, offset, fat_get_block);
if (ret < 0 && (rw & WRITE)) if (ret < 0 && iov_iter_rw(iter) == WRITE)
fat_write_failed(mapping, offset + count); fat_write_failed(mapping, offset + count);
return ret; return ret;

View File

@ -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)
/* 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, S_ISBLK(inode->i_mode)); err = generic_write_checks(iocb, from);
if (err) if (err <= 0)
goto out; goto out;
if (count == 0)
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;
@ -1183,7 +1177,8 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
if (err) if (err)
goto out; goto out;
if (file->f_flags & O_DIRECT) { if (iocb->ki_flags & IOCB_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)
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)
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)
/* 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, 0); 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);
@ -2782,8 +2774,7 @@ static inline loff_t fuse_round_up(loff_t off)
} }
static ssize_t static ssize_t
fuse_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter, loff_t offset)
loff_t offset)
{ {
DECLARE_COMPLETION_ONSTACK(wait); DECLARE_COMPLETION_ONSTACK(wait);
ssize_t ret = 0; ssize_t ret = 0;
@ -2800,15 +2791,15 @@ fuse_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter,
inode = file->f_mapping->host; inode = file->f_mapping->host;
i_size = i_size_read(inode); i_size = i_size_read(inode);
if ((rw == READ) && (offset > i_size)) if ((iov_iter_rw(iter) == READ) && (offset > i_size))
return 0; return 0;
/* optimization for short read */ /* optimization for short read */
if (async_dio && rw != WRITE && offset + count > i_size) { if (async_dio && iov_iter_rw(iter) != WRITE && offset + count > i_size) {
if (offset >= i_size) if (offset >= i_size)
return 0; return 0;
count = min_t(loff_t, count, fuse_round_up(i_size - offset)); iov_iter_truncate(iter, fuse_round_up(i_size - offset));
iov_iter_truncate(iter, count); count = iov_iter_count(iter);
} }
io = kmalloc(sizeof(struct fuse_io_priv), GFP_KERNEL); io = kmalloc(sizeof(struct fuse_io_priv), GFP_KERNEL);
@ -2819,7 +2810,7 @@ fuse_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter,
io->bytes = -1; io->bytes = -1;
io->size = 0; io->size = 0;
io->offset = offset; io->offset = offset;
io->write = (rw == WRITE); io->write = (iov_iter_rw(iter) == WRITE);
io->err = 0; io->err = 0;
io->file = file; io->file = file;
/* /*
@ -2834,19 +2825,15 @@ fuse_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter,
* to wait on real async I/O requests, so we must submit this request * to wait on real async I/O requests, so we must submit this request
* synchronously. * synchronously.
*/ */
if (!is_sync_kiocb(iocb) && (offset + count > i_size) && rw == WRITE) if (!is_sync_kiocb(iocb) && (offset + count > i_size) &&
iov_iter_rw(iter) == WRITE)
io->async = false; io->async = false;
if (io->async && is_sync_kiocb(iocb)) if (io->async && is_sync_kiocb(iocb))
io->done = &wait; io->done = &wait;
if (rw == WRITE) { if (iov_iter_rw(iter) == WRITE) {
ret = generic_write_checks(file, &pos, &count, 0); ret = fuse_direct_io(io, iter, &pos, FUSE_DIO_WRITE);
if (!ret) {
iov_iter_truncate(iter, count);
ret = fuse_direct_io(io, iter, &pos, FUSE_DIO_WRITE);
}
fuse_invalidate_attr(inode); fuse_invalidate_attr(inode);
} else { } else {
ret = __fuse_direct_read(io, iter, &pos); ret = __fuse_direct_read(io, iter, &pos);
@ -2865,7 +2852,7 @@ fuse_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter,
kfree(io); kfree(io);
if (rw == WRITE) { if (iov_iter_rw(iter) == WRITE) {
if (ret > 0) if (ret > 0)
fuse_write_update_size(inode, pos); fuse_write_update_size(inode, pos);
else if (ret < 0 && offset + count > i_size) else if (ret < 0 && offset + count > i_size)

View File

@ -1016,13 +1016,12 @@ out:
/** /**
* gfs2_ok_for_dio - check that dio is valid on this file * gfs2_ok_for_dio - check that dio is valid on this file
* @ip: The inode * @ip: The inode
* @rw: READ or WRITE
* @offset: The offset at which we are reading or writing * @offset: The offset at which we are reading or writing
* *
* Returns: 0 (to ignore the i/o request and thus fall back to buffered i/o) * Returns: 0 (to ignore the i/o request and thus fall back to buffered i/o)
* 1 (to accept the i/o request) * 1 (to accept the i/o request)
*/ */
static int gfs2_ok_for_dio(struct gfs2_inode *ip, int rw, loff_t offset) static int gfs2_ok_for_dio(struct gfs2_inode *ip, loff_t offset)
{ {
/* /*
* Should we return an error here? I can't see that O_DIRECT for * Should we return an error here? I can't see that O_DIRECT for
@ -1039,8 +1038,8 @@ static int gfs2_ok_for_dio(struct gfs2_inode *ip, int rw, loff_t offset)
static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb, static ssize_t gfs2_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
struct iov_iter *iter, loff_t offset) loff_t offset)
{ {
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;
@ -1061,7 +1060,7 @@ static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb,
rv = gfs2_glock_nq(&gh); rv = gfs2_glock_nq(&gh);
if (rv) if (rv)
return rv; return rv;
rv = gfs2_ok_for_dio(ip, rw, offset); rv = gfs2_ok_for_dio(ip, offset);
if (rv != 1) if (rv != 1)
goto out; /* dio not valid, fall back to buffered i/o */ goto out; /* dio not valid, fall back to buffered i/o */
@ -1091,13 +1090,12 @@ static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb,
rv = filemap_write_and_wait_range(mapping, lstart, end); rv = filemap_write_and_wait_range(mapping, lstart, end);
if (rv) if (rv)
goto out; goto out;
if (rw == WRITE) if (iov_iter_rw(iter) == WRITE)
truncate_inode_pages_range(mapping, lstart, end); truncate_inode_pages_range(mapping, lstart, end);
} }
rv = __blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, rv = __blockdev_direct_IO(iocb, inode, inode->i_sb->s_bdev, iter,
iter, offset, offset, gfs2_get_block_direct, NULL, NULL, 0);
gfs2_get_block_direct, NULL, NULL, 0);
out: out:
gfs2_glock_dq(&gh); gfs2_glock_dq(&gh);
gfs2_holder_uninit(&gh); gfs2_holder_uninit(&gh);

View File

@ -709,7 +709,7 @@ static ssize_t gfs2_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
gfs2_size_hint(file, iocb->ki_pos, iov_iter_count(from)); gfs2_size_hint(file, iocb->ki_pos, iov_iter_count(from));
if (file->f_flags & O_APPEND) { if (iocb->ki_flags & IOCB_APPEND) {
struct gfs2_holder gh; struct gfs2_holder gh;
ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &gh); ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &gh);

View File

@ -124,8 +124,8 @@ static int hfs_releasepage(struct page *page, gfp_t mask)
return res ? try_to_free_buffers(page) : 0; return res ? try_to_free_buffers(page) : 0;
} }
static ssize_t hfs_direct_IO(int rw, struct kiocb *iocb, static ssize_t hfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
struct iov_iter *iter, loff_t offset) loff_t offset)
{ {
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;
@ -133,13 +133,13 @@ static ssize_t hfs_direct_IO(int rw, struct kiocb *iocb,
size_t count = iov_iter_count(iter); size_t count = iov_iter_count(iter);
ssize_t ret; ssize_t ret;
ret = blockdev_direct_IO(rw, iocb, inode, iter, offset, hfs_get_block); ret = blockdev_direct_IO(iocb, inode, iter, offset, hfs_get_block);
/* /*
* In case of error extending write may have instantiated a few * In case of error extending write may have instantiated a few
* blocks outside i_size. Trim these off again. * blocks outside i_size. Trim these off again.
*/ */
if (unlikely((rw & WRITE) && ret < 0)) { if (unlikely(iov_iter_rw(iter) == WRITE && ret < 0)) {
loff_t isize = i_size_read(inode); loff_t isize = i_size_read(inode);
loff_t end = offset + count; loff_t end = offset + count;

View File

@ -122,8 +122,8 @@ static int hfsplus_releasepage(struct page *page, gfp_t mask)
return res ? try_to_free_buffers(page) : 0; return res ? try_to_free_buffers(page) : 0;
} }
static ssize_t hfsplus_direct_IO(int rw, struct kiocb *iocb, static ssize_t hfsplus_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
struct iov_iter *iter, loff_t offset) loff_t offset)
{ {
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;
@ -131,14 +131,13 @@ static ssize_t hfsplus_direct_IO(int rw, struct kiocb *iocb,
size_t count = iov_iter_count(iter); size_t count = iov_iter_count(iter);
ssize_t ret; ssize_t ret;
ret = blockdev_direct_IO(rw, iocb, inode, iter, offset, ret = blockdev_direct_IO(iocb, inode, iter, offset, hfsplus_get_block);
hfsplus_get_block);
/* /*
* In case of error extending write may have instantiated a few * In case of error extending write may have instantiated a few
* blocks outside i_size. Trim these off again. * blocks outside i_size. Trim these off again.
*/ */
if (unlikely((rw & WRITE) && ret < 0)) { if (unlikely(iov_iter_rw(iter) == WRITE && ret < 0)) {
loff_t isize = i_size_read(inode); loff_t isize = i_size_read(inode);
loff_t end = offset + count; loff_t end = offset + count;

View File

@ -330,8 +330,8 @@ static sector_t jfs_bmap(struct address_space *mapping, sector_t block)
return generic_block_bmap(mapping, block, jfs_get_block); return generic_block_bmap(mapping, block, jfs_get_block);
} }
static ssize_t jfs_direct_IO(int rw, struct kiocb *iocb, static ssize_t jfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
struct iov_iter *iter, loff_t offset) loff_t offset)
{ {
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;
@ -339,13 +339,13 @@ static ssize_t jfs_direct_IO(int rw, struct kiocb *iocb,
size_t count = iov_iter_count(iter); size_t count = iov_iter_count(iter);
ssize_t ret; ssize_t ret;
ret = blockdev_direct_IO(rw, iocb, inode, iter, offset, jfs_get_block); ret = blockdev_direct_IO(iocb, inode, iter, offset, jfs_get_block);
/* /*
* In case of error extending write may have instantiated a few * In case of error extending write may have instantiated a few
* blocks outside i_size. Trim these off again. * blocks outside i_size. Trim these off again.
*/ */
if (unlikely((rw & WRITE) && ret < 0)) { if (unlikely(iov_iter_rw(iter) == WRITE && ret < 0)) {
loff_t isize = i_size_read(inode); loff_t isize = i_size_read(inode);
loff_t end = offset + count; loff_t end = offset + count;

View File

@ -1585,7 +1585,7 @@ static inline int walk_component(struct nameidata *nd, struct path *path,
inode = path->dentry->d_inode; inode = path->dentry->d_inode;
} }
err = -ENOENT; err = -ENOENT;
if (!inode || d_is_negative(path->dentry)) if (d_is_negative(path->dentry))
goto out_path_put; goto out_path_put;
if (should_follow_link(path->dentry, follow)) { if (should_follow_link(path->dentry, follow)) {
@ -2310,7 +2310,7 @@ mountpoint_last(struct nameidata *nd, struct path *path)
mutex_unlock(&dir->d_inode->i_mutex); mutex_unlock(&dir->d_inode->i_mutex);
done: done:
if (!dentry->d_inode || d_is_negative(dentry)) { if (d_is_negative(dentry)) {
error = -ENOENT; error = -ENOENT;
dput(dentry); dput(dentry);
goto out; goto out;
@ -3038,7 +3038,7 @@ retry_lookup:
finish_lookup: finish_lookup:
/* we _can_ be in RCU mode here */ /* we _can_ be in RCU mode here */
error = -ENOENT; error = -ENOENT;
if (!inode || d_is_negative(path->dentry)) { if (d_is_negative(path->dentry)) {
path_to_nameidata(path, nd); path_to_nameidata(path, nd);
goto out; goto out;
} }
@ -3077,7 +3077,7 @@ finish_open:
error = -ENOTDIR; error = -ENOTDIR;
if ((nd->flags & LOOKUP_DIRECTORY) && !d_can_lookup(nd->path.dentry)) if ((nd->flags & LOOKUP_DIRECTORY) && !d_can_lookup(nd->path.dentry))
goto out; goto out;
if (!S_ISREG(nd->inode->i_mode)) if (!d_is_reg(nd->path.dentry))
will_truncate = false; will_truncate = false;
if (will_truncate) { if (will_truncate) {

View File

@ -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, 0); 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)
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) {

View File

@ -240,7 +240,6 @@ static int nfs_direct_cmp_commit_data_verf(struct nfs_direct_req *dreq,
/** /**
* nfs_direct_IO - NFS address space operation for direct I/O * nfs_direct_IO - NFS address space operation for direct I/O
* @rw: direction (read or write)
* @iocb: target I/O control block * @iocb: target I/O control block
* @iov: array of vectors that define I/O buffer * @iov: array of vectors that define I/O buffer
* @pos: offset in file to begin the operation * @pos: offset in file to begin the operation
@ -251,7 +250,7 @@ static int nfs_direct_cmp_commit_data_verf(struct nfs_direct_req *dreq,
* shunt off direct read and write requests before the VFS gets them, * shunt off direct read and write requests before the VFS gets them,
* so this method is only ever called for swap. * so this method is only ever called for swap.
*/ */
ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, loff_t pos) ssize_t nfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter, loff_t pos)
{ {
struct inode *inode = iocb->ki_filp->f_mapping->host; struct inode *inode = iocb->ki_filp->f_mapping->host;
@ -267,9 +266,9 @@ ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, loff_t
#else #else
VM_BUG_ON(iov_iter_count(iter) != PAGE_SIZE); VM_BUG_ON(iov_iter_count(iter) != PAGE_SIZE);
if (rw == READ) if (iov_iter_rw(iter) == READ)
return nfs_file_direct_read(iocb, iter, pos); return nfs_file_direct_read(iocb, iter, pos);
return nfs_file_direct_write(iocb, iter, pos); return nfs_file_direct_write(iocb, iter);
#endif /* CONFIG_NFS_SWAP */ #endif /* CONFIG_NFS_SWAP */
} }
@ -960,8 +959,7 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq,
* Note that O_APPEND is not supported for NFS direct writes, as there * Note that O_APPEND is not supported for NFS direct writes, as there
* is no atomic O_APPEND write facility in the NFS protocol. * is no atomic O_APPEND write facility in the NFS protocol.
*/ */
ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter, ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter)
loff_t pos)
{ {
ssize_t result = -EINVAL; ssize_t result = -EINVAL;
struct file *file = iocb->ki_filp; struct file *file = iocb->ki_filp;
@ -969,25 +967,16 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter,
struct inode *inode = mapping->host; struct inode *inode = mapping->host;
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 pos, 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, 0); nfs_add_stats(mapping->host, NFSIOS_DIRECTWRITTENBYTES,
if (result) iov_iter_count(iter));
goto out;
result = -EINVAL; pos = iocb->ki_pos;
if ((ssize_t) count < 0) end = (pos + iov_iter_count(iter) - 1) >> PAGE_CACHE_SHIFT;
goto out;
result = 0;
if (!count)
goto out;
mutex_lock(&inode->i_mutex); mutex_lock(&inode->i_mutex);
@ -1002,7 +991,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();
@ -1010,7 +999,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);
@ -1050,7 +1039,6 @@ out_release:
nfs_direct_req_release(dreq); nfs_direct_req_release(dreq);
out_unlock: out_unlock:
mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex);
out:
return result; return result;
} }

View File

@ -170,7 +170,7 @@ nfs_file_read(struct kiocb *iocb, struct iov_iter *to)
struct inode *inode = file_inode(iocb->ki_filp); struct inode *inode = file_inode(iocb->ki_filp);
ssize_t result; ssize_t result;
if (iocb->ki_filp->f_flags & O_DIRECT) if (iocb->ki_flags & IOCB_DIRECT)
return nfs_file_direct_read(iocb, to, iocb->ki_pos); return nfs_file_direct_read(iocb, to, iocb->ki_pos);
dprintk("NFS: read(%pD2, %zu@%lu)\n", dprintk("NFS: read(%pD2, %zu@%lu)\n",
@ -674,17 +674,20 @@ ssize_t nfs_file_write(struct kiocb *iocb, struct iov_iter *from)
unsigned long written = 0; unsigned long written = 0;
ssize_t result; ssize_t result;
size_t count = iov_iter_count(from); size_t count = iov_iter_count(from);
loff_t pos = iocb->ki_pos;
result = nfs_key_timeout_notify(file, inode); result = nfs_key_timeout_notify(file, inode);
if (result) if (result)
return result; return result;
if (file->f_flags & O_DIRECT) if (iocb->ki_flags & IOCB_DIRECT) {
return nfs_file_direct_write(iocb, from, pos); result = generic_write_checks(iocb, from);
if (result <= 0)
return result;
return nfs_file_direct_write(iocb, from);
}
dprintk("NFS: write(%pD2, %zu@%Ld)\n", dprintk("NFS: write(%pD2, %zu@%Ld)\n",
file, count, (long long) pos); file, count, (long long) iocb->ki_pos);
result = -EBUSY; result = -EBUSY;
if (IS_SWAPFILE(inode)) if (IS_SWAPFILE(inode))
@ -692,7 +695,7 @@ ssize_t nfs_file_write(struct kiocb *iocb, struct iov_iter *from)
/* /*
* O_APPEND implies that we must revalidate the file length. * O_APPEND implies that we must revalidate the file length.
*/ */
if (file->f_flags & O_APPEND) { if (iocb->ki_flags & IOCB_APPEND) {
result = nfs_revalidate_file_size(inode, file); result = nfs_revalidate_file_size(inode, file);
if (result) if (result)
goto out; goto out;

View File

@ -117,15 +117,15 @@ int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
static void nfs_readpage_release(struct nfs_page *req) static void nfs_readpage_release(struct nfs_page *req)
{ {
struct inode *d_inode = req->wb_context->dentry->d_inode; struct inode *inode = req->wb_context->dentry->d_inode;
dprintk("NFS: read done (%s/%llu %d@%lld)\n", d_inode->i_sb->s_id, dprintk("NFS: read done (%s/%llu %d@%lld)\n", inode->i_sb->s_id,
(unsigned long long)NFS_FILEID(d_inode), req->wb_bytes, (unsigned long long)NFS_FILEID(inode), req->wb_bytes,
(long long)req_offset(req)); (long long)req_offset(req));
if (nfs_page_group_sync_on_bit(req, PG_UNLOCKPAGE)) { if (nfs_page_group_sync_on_bit(req, PG_UNLOCKPAGE)) {
if (PageUptodate(req->wb_page)) if (PageUptodate(req->wb_page))
nfs_readpage_to_fscache(d_inode, req->wb_page, 0); nfs_readpage_to_fscache(inode, req->wb_page, 0);
unlock_page(req->wb_page); unlock_page(req->wb_page);
} }

View File

@ -305,8 +305,7 @@ static int nilfs_write_end(struct file *file, struct address_space *mapping,
} }
static ssize_t static ssize_t
nilfs_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, nilfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter, loff_t offset)
loff_t offset)
{ {
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;
@ -314,18 +313,17 @@ nilfs_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter,
size_t count = iov_iter_count(iter); size_t count = iov_iter_count(iter);
ssize_t size; ssize_t size;
if (rw == WRITE) if (iov_iter_rw(iter) == WRITE)
return 0; return 0;
/* Needs synchronization with the cleaner */ /* Needs synchronization with the cleaner */
size = blockdev_direct_IO(rw, iocb, inode, iter, offset, size = blockdev_direct_IO(iocb, inode, iter, offset, nilfs_get_block);
nilfs_get_block);
/* /*
* In case of error extending write may have instantiated a few * In case of error extending write may have instantiated a few
* blocks outside i_size. Trim these off again. * blocks outside i_size. Trim these off again.
*/ */
if (unlikely((rw & WRITE) && size < 0)) { if (unlikely(iov_iter_rw(iter) == WRITE && size < 0)) {
loff_t isize = i_size_read(inode); loff_t isize = i_size_read(inode);
loff_t end = offset + count; loff_t end = offset + count;

View File

@ -328,25 +328,25 @@ 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;
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,
/* We can write back this queue in page reclaim. */ iov_iter_count(from));
current->backing_dev_info = inode_to_bdi(vi); err = generic_write_checks(iocb, from);
err = generic_write_checks(file, ppos, count, S_ISBLK(vi->i_mode)); if (unlikely(err <= 0))
if (unlikely(err))
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
@ -379,8 +379,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 +390,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 +420,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 +436,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 +1927,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;
ssize_t err;
mutex_lock(&vi->i_mutex); mutex_lock(&vi->i_mutex);
ret = ntfs_file_write_iter_nolock(iocb, from); /* 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); mutex_unlock(&vi->i_mutex);
if (ret > 0) { if (likely(written > 0)) {
ssize_t err; err = generic_write_sync(file, iocb->ki_pos, written);
err = generic_write_sync(file, iocb->ki_pos - ret, ret);
if (err < 0) if (err < 0)
ret = err; written = 0;
} }
return ret; iocb->ki_pos += written;
return written ? written : err;
} }
/** /**

View File

@ -855,10 +855,9 @@ static ssize_t ocfs2_direct_IO_write(struct kiocb *iocb,
ocfs2_inode_unlock(inode, 1); ocfs2_inode_unlock(inode, 1);
} }
written = __blockdev_direct_IO(WRITE, iocb, inode, inode->i_sb->s_bdev, written = __blockdev_direct_IO(iocb, inode, inode->i_sb->s_bdev, iter,
iter, offset, offset, ocfs2_direct_IO_get_blocks,
ocfs2_direct_IO_get_blocks, ocfs2_dio_end_io, NULL, 0);
ocfs2_dio_end_io, NULL, 0);
if (unlikely(written < 0)) { if (unlikely(written < 0)) {
loff_t i_size = i_size_read(inode); loff_t i_size = i_size_read(inode);
@ -946,9 +945,7 @@ out:
return ret; return ret;
} }
static ssize_t ocfs2_direct_IO(int rw, static ssize_t ocfs2_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
struct kiocb *iocb,
struct iov_iter *iter,
loff_t offset) loff_t offset)
{ {
struct file *file = iocb->ki_filp; struct file *file = iocb->ki_filp;
@ -970,12 +967,11 @@ static ssize_t ocfs2_direct_IO(int rw,
if (i_size_read(inode) <= offset && !full_coherency) if (i_size_read(inode) <= offset && !full_coherency)
return 0; return 0;
if (rw == READ) if (iov_iter_rw(iter) == READ)
return __blockdev_direct_IO(rw, iocb, inode, return __blockdev_direct_IO(iocb, inode, inode->i_sb->s_bdev,
inode->i_sb->s_bdev, iter, offset,
iter, offset, ocfs2_direct_IO_get_blocks,
ocfs2_direct_IO_get_blocks, ocfs2_dio_end_io, NULL, 0);
ocfs2_dio_end_io, NULL, 0);
else else
return ocfs2_direct_IO_write(iocb, iter, offset); return ocfs2_direct_IO_write(iocb, iter, offset);
} }

View File

@ -2106,7 +2106,7 @@ out:
} }
static int ocfs2_prepare_inode_for_write(struct file *file, static int ocfs2_prepare_inode_for_write(struct file *file,
loff_t *ppos, loff_t pos,
size_t count, size_t count,
int appending, int appending,
int *direct_io, int *direct_io,
@ -2115,7 +2115,7 @@ static int ocfs2_prepare_inode_for_write(struct file *file,
int ret = 0, meta_level = 0; int ret = 0, meta_level = 0;
struct dentry *dentry = file->f_path.dentry; struct dentry *dentry = file->f_path.dentry;
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
loff_t saved_pos = 0, end; loff_t end;
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
int full_coherency = !(osb->s_mount_opt & int full_coherency = !(osb->s_mount_opt &
OCFS2_MOUNT_COHERENCY_BUFFERED); OCFS2_MOUNT_COHERENCY_BUFFERED);
@ -2155,23 +2155,16 @@ static int ocfs2_prepare_inode_for_write(struct file *file,
} }
} }
/* work on a copy of ppos until we're sure that we won't have end = pos + count;
* to recalculate it due to relocking. */
if (appending)
saved_pos = i_size_read(inode);
else
saved_pos = *ppos;
end = saved_pos + count; ret = ocfs2_check_range_for_refcount(inode, pos, count);
ret = ocfs2_check_range_for_refcount(inode, saved_pos, count);
if (ret == 1) { if (ret == 1) {
ocfs2_inode_unlock(inode, meta_level); ocfs2_inode_unlock(inode, meta_level);
meta_level = -1; meta_level = -1;
ret = ocfs2_prepare_inode_for_refcount(inode, ret = ocfs2_prepare_inode_for_refcount(inode,
file, file,
saved_pos, pos,
count, count,
&meta_level); &meta_level);
if (has_refcount) if (has_refcount)
@ -2227,7 +2220,7 @@ static int ocfs2_prepare_inode_for_write(struct file *file,
* caller will have to retake some cluster * caller will have to retake some cluster
* locks and initiate the io as buffered. * locks and initiate the io as buffered.
*/ */
ret = ocfs2_check_range_for_holes(inode, saved_pos, count); ret = ocfs2_check_range_for_holes(inode, pos, count);
if (ret == 1) { if (ret == 1) {
/* /*
* Fallback to old way if the feature bit is not set. * Fallback to old way if the feature bit is not set.
@ -2242,12 +2235,9 @@ static int ocfs2_prepare_inode_for_write(struct file *file,
break; break;
} }
if (appending)
*ppos = saved_pos;
out_unlock: out_unlock:
trace_ocfs2_prepare_inode_for_write(OCFS2_I(inode)->ip_blkno, trace_ocfs2_prepare_inode_for_write(OCFS2_I(inode)->ip_blkno,
saved_pos, appending, count, pos, appending, count,
direct_io, has_refcount); direct_io, has_refcount);
if (meta_level >= 0) if (meta_level >= 0)
@ -2260,19 +2250,20 @@ out:
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;
size_t count = iov_iter_count(from); ssize_t ret;
loff_t old_size, *ppos = &iocb->ki_pos; size_t count = iov_iter_count(from), orig_count;
loff_t old_size;
u32 old_clusters; u32 old_clusters;
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 address_space *mapping = file->f_mapping;
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
int full_coherency = !(osb->s_mount_opt & int full_coherency = !(osb->s_mount_opt &
OCFS2_MOUNT_COHERENCY_BUFFERED); OCFS2_MOUNT_COHERENCY_BUFFERED);
int unaligned_dio = 0; int unaligned_dio = 0;
int dropped_dio = 0;
trace_ocfs2_file_aio_write(inode, file, file->f_path.dentry, trace_ocfs2_file_aio_write(inode, file, file->f_path.dentry,
(unsigned long long)OCFS2_I(inode)->ip_blkno, (unsigned long long)OCFS2_I(inode)->ip_blkno,
@ -2283,8 +2274,8 @@ static ssize_t ocfs2_file_write_iter(struct kiocb *iocb,
if (count == 0) if (count == 0)
return 0; return 0;
appending = file->f_flags & O_APPEND ? 1 : 0; appending = iocb->ki_flags & IOCB_APPEND ? 1 : 0;
direct_io = file->f_flags & O_DIRECT ? 1 : 0; direct_io = iocb->ki_flags & IOCB_DIRECT ? 1 : 0;
mutex_lock(&inode->i_mutex); mutex_lock(&inode->i_mutex);
@ -2329,8 +2320,17 @@ relock:
ocfs2_inode_unlock(inode, 1); ocfs2_inode_unlock(inode, 1);
} }
orig_count = iov_iter_count(from);
ret = generic_write_checks(iocb, from);
if (ret <= 0) {
if (ret)
mlog_errno(ret);
goto out;
}
count = ret;
can_do_direct = direct_io; can_do_direct = direct_io;
ret = ocfs2_prepare_inode_for_write(file, ppos, count, appending, ret = ocfs2_prepare_inode_for_write(file, iocb->ki_pos, count, appending,
&can_do_direct, &has_refcount); &can_do_direct, &has_refcount);
if (ret < 0) { if (ret < 0) {
mlog_errno(ret); mlog_errno(ret);
@ -2338,7 +2338,7 @@ relock:
} }
if (direct_io && !is_sync_kiocb(iocb)) if (direct_io && !is_sync_kiocb(iocb))
unaligned_dio = ocfs2_is_io_unaligned(inode, count, *ppos); unaligned_dio = ocfs2_is_io_unaligned(inode, count, iocb->ki_pos);
/* /*
* We can't complete the direct I/O as requested, fall back to * We can't complete the direct I/O as requested, fall back to
@ -2351,6 +2351,9 @@ relock:
rw_level = -1; rw_level = -1;
direct_io = 0; direct_io = 0;
iocb->ki_flags &= ~IOCB_DIRECT;
iov_iter_reexpand(from, orig_count);
dropped_dio = 1;
goto relock; goto relock;
} }
@ -2374,74 +2377,15 @@ relock:
/* communicate with ocfs2_dio_end_io */ /* communicate with ocfs2_dio_end_io */
ocfs2_iocb_set_rw_locked(iocb, rw_level); ocfs2_iocb_set_rw_locked(iocb, rw_level);
ret = generic_write_checks(file, ppos, &count, written = __generic_file_write_iter(iocb, from);
S_ISBLK(inode->i_mode));
if (ret)
goto out_dio;
iov_iter_truncate(from, count);
if (direct_io) {
loff_t endbyte;
ssize_t written_buffered;
written = generic_file_direct_write(iocb, from, *ppos);
if (written < 0 || written == count) {
ret = written;
goto out_dio;
}
/*
* for completing the rest of the request.
*/
count -= written;
written_buffered = generic_perform_write(file, from, *ppos);
/*
* If generic_file_buffered_write() returned a synchronous error
* then we want to return the number of bytes which were
* direct-written, or the error code if that was zero. Note
* that this differs from normal direct-io semantics, which
* will return -EFOO even if some bytes were written.
*/
if (written_buffered < 0) {
ret = written_buffered;
goto out_dio;
}
/* We need to ensure that the page cache pages are written to
* disk and invalidated to preserve the expected O_DIRECT
* semantics.
*/
endbyte = *ppos + written_buffered - 1;
ret = filemap_write_and_wait_range(file->f_mapping, *ppos,
endbyte);
if (ret == 0) {
iocb->ki_pos = *ppos + written_buffered;
written += written_buffered;
invalidate_mapping_pages(mapping,
*ppos >> PAGE_CACHE_SHIFT,
endbyte >> PAGE_CACHE_SHIFT);
} else {
/*
* We don't know how much we wrote, so just return
* the number of bytes which were direct-written
*/
}
} else {
current->backing_dev_info = inode_to_bdi(inode);
written = generic_perform_write(file, from, *ppos);
if (likely(written >= 0))
iocb->ki_pos = *ppos + written;
current->backing_dev_info = NULL;
}
out_dio:
/* buffered aio wouldn't have proper lock coverage today */ /* buffered aio wouldn't have proper lock coverage today */
BUG_ON(ret == -EIOCBQUEUED && !(file->f_flags & O_DIRECT)); BUG_ON(written == -EIOCBQUEUED && !(iocb->ki_flags & IOCB_DIRECT));
if (unlikely(written <= 0)) if (unlikely(written <= 0))
goto no_sync; goto no_sync;
if (((file->f_flags & O_DSYNC) && !direct_io) || IS_SYNC(inode) || if (((file->f_flags & O_DSYNC) && !direct_io) ||
((file->f_flags & O_DIRECT) && !direct_io)) { IS_SYNC(inode) || dropped_dio) {
ret = filemap_fdatawrite_range(file->f_mapping, ret = filemap_fdatawrite_range(file->f_mapping,
iocb->ki_pos - written, iocb->ki_pos - written,
iocb->ki_pos - 1); iocb->ki_pos - 1);
@ -2552,7 +2496,7 @@ static ssize_t ocfs2_file_read_iter(struct kiocb *iocb,
* buffered reads protect themselves in ->readpage(). O_DIRECT reads * buffered reads protect themselves in ->readpage(). O_DIRECT reads
* need locks to protect pending reads from racing with truncate. * need locks to protect pending reads from racing with truncate.
*/ */
if (filp->f_flags & O_DIRECT) { if (iocb->ki_flags & IOCB_DIRECT) {
have_alloc_sem = 1; have_alloc_sem = 1;
ocfs2_iocb_set_sem_locked(iocb); ocfs2_iocb_set_sem_locked(iocb);
@ -2586,7 +2530,7 @@ static ssize_t ocfs2_file_read_iter(struct kiocb *iocb,
trace_generic_file_aio_read_ret(ret); trace_generic_file_aio_read_ret(ret);
/* buffered aio wouldn't have proper lock coverage today */ /* buffered aio wouldn't have proper lock coverage today */
BUG_ON(ret == -EIOCBQUEUED && !(filp->f_flags & O_DIRECT)); BUG_ON(ret == -EIOCBQUEUED && !(iocb->ki_flags & IOCB_DIRECT));
/* see ocfs2_file_write_iter */ /* see ocfs2_file_write_iter */
if (ret == -EIOCBQUEUED || !ocfs2_iocb_is_rw_locked(iocb)) { if (ret == -EIOCBQUEUED || !ocfs2_iocb_is_rw_locked(iocb)) {

View File

@ -477,7 +477,8 @@ static ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t
ret = filp->f_op->write_iter(&kiocb, &iter); ret = filp->f_op->write_iter(&kiocb, &iter);
BUG_ON(ret == -EIOCBQUEUED); BUG_ON(ret == -EIOCBQUEUED);
*ppos = kiocb.ki_pos; if (ret > 0)
*ppos = kiocb.ki_pos;
return ret; return ret;
} }

View File

@ -3278,22 +3278,22 @@ static int reiserfs_releasepage(struct page *page, gfp_t unused_gfp_flags)
* We thank Mingming Cao for helping us understand in great detail what * We thank Mingming Cao for helping us understand in great detail what
* to do in this section of the code. * to do in this section of the code.
*/ */
static ssize_t reiserfs_direct_IO(int rw, struct kiocb *iocb, static ssize_t reiserfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
struct iov_iter *iter, loff_t offset) loff_t offset)
{ {
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;
size_t count = iov_iter_count(iter); size_t count = iov_iter_count(iter);
ssize_t ret; ssize_t ret;
ret = blockdev_direct_IO(rw, iocb, inode, iter, offset, ret = blockdev_direct_IO(iocb, inode, iter, offset,
reiserfs_get_blocks_direct_io); reiserfs_get_blocks_direct_io);
/* /*
* In case of error extending write may have instantiated a few * In case of error extending write may have instantiated a few
* blocks outside i_size. Trim these off again. * blocks outside i_size. Trim these off again.
*/ */
if (unlikely((rw & WRITE) && ret < 0)) { if (unlikely(iov_iter_rw(iter) == WRITE && ret < 0)) {
loff_t isize = i_size_read(inode); loff_t isize = i_size_read(inode);
loff_t end = offset + count; loff_t end = offset + count;

View File

@ -99,8 +99,7 @@ static int udf_adinicb_write_begin(struct file *file,
return 0; return 0;
} }
static ssize_t udf_adinicb_direct_IO(int rw, struct kiocb *iocb, static ssize_t udf_adinicb_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
struct iov_iter *iter,
loff_t offset) loff_t offset)
{ {
/* Fallback to buffered I/O. */ /* Fallback to buffered I/O. */
@ -120,21 +119,21 @@ 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);
int err, pos;
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;
mutex_lock(&inode->i_mutex); mutex_lock(&inode->i_mutex);
retval = generic_write_checks(iocb, from);
if (retval <= 0)
goto out;
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) {
if (file->f_flags & O_APPEND) loff_t end = iocb->ki_pos + iov_iter_count(from);
pos = inode->i_size;
else
pos = iocb->ki_pos;
if (inode->i_sb->s_blocksize < if (inode->i_sb->s_blocksize <
(udf_file_entry_alloc_offset(inode) + (udf_file_entry_alloc_offset(inode) + end)) {
pos + count)) {
err = udf_expand_file_adinicb(inode); err = udf_expand_file_adinicb(inode);
if (err) { if (err) {
mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex);
@ -142,16 +141,14 @@ static ssize_t udf_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
return err; return err;
} }
} else { } else {
if (pos + count > inode->i_size) iinfo->i_lenAlloc = max(end, inode->i_size);
iinfo->i_lenAlloc = pos + count;
else
iinfo->i_lenAlloc = inode->i_size;
up_write(&iinfo->i_data_sem); up_write(&iinfo->i_data_sem);
} }
} else } else
up_write(&iinfo->i_data_sem); up_write(&iinfo->i_data_sem);
retval = __generic_file_write_iter(iocb, from); retval = __generic_file_write_iter(iocb, from);
out:
mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex);
if (retval > 0) { if (retval > 0) {

View File

@ -214,8 +214,7 @@ static int udf_write_begin(struct file *file, struct address_space *mapping,
return ret; return ret;
} }
static ssize_t udf_direct_IO(int rw, struct kiocb *iocb, static ssize_t udf_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
struct iov_iter *iter,
loff_t offset) loff_t offset)
{ {
struct file *file = iocb->ki_filp; struct file *file = iocb->ki_filp;
@ -224,8 +223,8 @@ static ssize_t udf_direct_IO(int rw, struct kiocb *iocb,
size_t count = iov_iter_count(iter); size_t count = iov_iter_count(iter);
ssize_t ret; ssize_t ret;
ret = blockdev_direct_IO(rw, iocb, inode, iter, offset, udf_get_block); ret = blockdev_direct_IO(iocb, inode, iter, offset, udf_get_block);
if (unlikely(ret < 0 && (rw & WRITE))) if (unlikely(ret < 0 && iov_iter_rw(iter) == WRITE))
udf_write_failed(mapping, offset + count); udf_write_failed(mapping, offset + count);
return ret; return ret;
} }

View File

@ -1495,7 +1495,6 @@ xfs_end_io_direct_write(
STATIC ssize_t STATIC ssize_t
xfs_vm_direct_IO( xfs_vm_direct_IO(
int rw,
struct kiocb *iocb, struct kiocb *iocb,
struct iov_iter *iter, struct iov_iter *iter,
loff_t offset) loff_t offset)
@ -1503,15 +1502,14 @@ xfs_vm_direct_IO(
struct inode *inode = iocb->ki_filp->f_mapping->host; struct inode *inode = iocb->ki_filp->f_mapping->host;
struct block_device *bdev = xfs_find_bdev_for_inode(inode); struct block_device *bdev = xfs_find_bdev_for_inode(inode);
if (rw & WRITE) { if (iov_iter_rw(iter) == WRITE) {
return __blockdev_direct_IO(rw, iocb, inode, bdev, iter, return __blockdev_direct_IO(iocb, inode, bdev, iter, offset,
offset, xfs_get_blocks_direct, xfs_get_blocks_direct,
xfs_end_io_direct_write, NULL, xfs_end_io_direct_write, NULL,
DIO_ASYNC_EXTEND); DIO_ASYNC_EXTEND);
} }
return __blockdev_direct_IO(rw, iocb, inode, bdev, iter, return __blockdev_direct_IO(iocb, inode, bdev, iter, offset,
offset, xfs_get_blocks_direct, xfs_get_blocks_direct, NULL, NULL, 0);
NULL, NULL, 0);
} }
/* /*

View File

@ -279,7 +279,7 @@ xfs_file_read_iter(
XFS_STATS_INC(xs_read_calls); XFS_STATS_INC(xs_read_calls);
if (unlikely(file->f_flags & O_DIRECT)) if (unlikely(iocb->ki_flags & IOCB_DIRECT))
ioflags |= XFS_IO_ISDIRECT; ioflags |= XFS_IO_ISDIRECT;
if (file->f_mode & FMODE_NOCMTIME) if (file->f_mode & FMODE_NOCMTIME)
ioflags |= XFS_IO_INVIS; ioflags |= XFS_IO_INVIS;
@ -544,18 +544,19 @@ xfs_zero_eof(
*/ */
STATIC ssize_t STATIC ssize_t
xfs_file_aio_write_checks( xfs_file_aio_write_checks(
struct file *file, struct kiocb *iocb,
loff_t *pos, struct iov_iter *from,
size_t *count,
int *iolock) int *iolock)
{ {
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);
restart: restart:
error = generic_write_checks(file, pos, count, S_ISBLK(inode->i_mode)); 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);
@ -569,16 +570,17 @@ restart:
* iolock shared, we need to update it to exclusive which implies * iolock shared, we need to update it to exclusive which implies
* having to redo all checks before. * having to redo all checks before.
*/ */
if (*pos > i_size_read(inode)) { if (iocb->ki_pos > i_size_read(inode)) {
bool zero = false; bool zero = false;
if (*iolock == XFS_IOLOCK_SHARED) { if (*iolock == XFS_IOLOCK_SHARED) {
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, *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;
} }
@ -678,10 +680,11 @@ xfs_file_dio_aio_write(
xfs_rw_ilock(ip, iolock); xfs_rw_ilock(ip, iolock);
} }
ret = xfs_file_aio_write_checks(file, &pos, &count, &iolock); ret = xfs_file_aio_write_checks(iocb, from, &iolock);
if (ret) if (ret)
goto out; goto out;
iov_iter_truncate(from, count); count = iov_iter_count(from);
pos = iocb->ki_pos;
if (mapping->nrpages) { if (mapping->nrpages) {
ret = filemap_write_and_wait_range(VFS_I(ip)->i_mapping, ret = filemap_write_and_wait_range(VFS_I(ip)->i_mapping,
@ -734,24 +737,22 @@ xfs_file_buffered_aio_write(
ssize_t ret; ssize_t ret;
int enospc = 0; int enospc = 0;
int iolock = XFS_IOLOCK_EXCL; int iolock = XFS_IOLOCK_EXCL;
loff_t pos = iocb->ki_pos;
size_t count = iov_iter_count(from);
xfs_rw_ilock(ip, iolock); xfs_rw_ilock(ip, iolock);
ret = xfs_file_aio_write_checks(file, &pos, &count, &iolock); ret = xfs_file_aio_write_checks(iocb, from, &iolock);
if (ret) if (ret)
goto out; goto out;
iov_iter_truncate(from, count);
/* 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);
write_retry: write_retry:
trace_xfs_file_buffered_write(ip, count, iocb->ki_pos, 0); trace_xfs_file_buffered_write(ip, iov_iter_count(from),
ret = generic_perform_write(file, from, pos); iocb->ki_pos, 0);
ret = generic_perform_write(file, from, iocb->ki_pos);
if (likely(ret >= 0)) if (likely(ret >= 0))
iocb->ki_pos = pos + ret; iocb->ki_pos += ret;
/* /*
* If we hit a space limit, try to free up some lingering preallocated * If we hit a space limit, try to free up some lingering preallocated
@ -803,7 +804,7 @@ xfs_file_write_iter(
if (XFS_FORCED_SHUTDOWN(ip->i_mount)) if (XFS_FORCED_SHUTDOWN(ip->i_mount))
return -EIO; return -EIO;
if (unlikely(file->f_flags & O_DIRECT)) if (unlikely(iocb->ki_flags & IOCB_DIRECT))
ret = xfs_file_dio_aio_write(iocb, from); ret = xfs_file_dio_aio_write(iocb, from);
else else
ret = xfs_file_buffered_aio_write(iocb, from); ret = xfs_file_buffered_aio_write(iocb, from);

View File

@ -404,26 +404,11 @@ static inline bool d_mountpoint(const struct dentry *dentry)
/* /*
* Directory cache entry type accessor functions. * Directory cache entry type accessor functions.
*/ */
static inline void __d_set_type(struct dentry *dentry, unsigned type)
{
dentry->d_flags = (dentry->d_flags & ~DCACHE_ENTRY_TYPE) | type;
}
static inline void __d_clear_type(struct dentry *dentry)
{
__d_set_type(dentry, DCACHE_MISS_TYPE);
}
static inline void d_set_type(struct dentry *dentry, unsigned type)
{
spin_lock(&dentry->d_lock);
__d_set_type(dentry, type);
spin_unlock(&dentry->d_lock);
}
static inline unsigned __d_entry_type(const struct dentry *dentry) static inline unsigned __d_entry_type(const struct dentry *dentry)
{ {
return dentry->d_flags & DCACHE_ENTRY_TYPE; unsigned type = READ_ONCE(dentry->d_flags);
smp_rmb();
return type & DCACHE_ENTRY_TYPE;
} }
static inline bool d_is_miss(const struct dentry *dentry) static inline bool d_is_miss(const struct dentry *dentry)
@ -482,6 +467,44 @@ static inline bool d_is_positive(const struct dentry *dentry)
return !d_is_negative(dentry); return !d_is_negative(dentry);
} }
/**
* d_really_is_negative - Determine if a dentry is really negative (ignoring fallthroughs)
* @dentry: The dentry in question
*
* Returns true if the dentry represents either an absent name or a name that
* doesn't map to an inode (ie. ->d_inode is NULL). The dentry could represent
* a true miss, a whiteout that isn't represented by a 0,0 chardev or a
* fallthrough marker in an opaque directory.
*
* Note! (1) This should be used *only* by a filesystem to examine its own
* dentries. It should not be used to look at some other filesystem's
* dentries. (2) It should also be used in combination with d_inode() to get
* the inode. (3) The dentry may have something attached to ->d_lower and the
* type field of the flags may be set to something other than miss or whiteout.
*/
static inline bool d_really_is_negative(const struct dentry *dentry)
{
return dentry->d_inode == NULL;
}
/**
* d_really_is_positive - Determine if a dentry is really positive (ignoring fallthroughs)
* @dentry: The dentry in question
*
* Returns true if the dentry represents a name that maps to an inode
* (ie. ->d_inode is not NULL). The dentry might still represent a whiteout if
* that is represented on medium as a 0,0 chardev.
*
* Note! (1) This should be used *only* by a filesystem to examine its own
* dentries. It should not be used to look at some other filesystem's
* dentries. (2) It should also be used in combination with d_inode() to get
* the inode.
*/
static inline bool d_really_is_positive(const struct dentry *dentry)
{
return dentry->d_inode != NULL;
}
extern void d_set_fallthru(struct dentry *dentry); extern void d_set_fallthru(struct dentry *dentry);
static inline bool d_is_fallthru(const struct dentry *dentry) static inline bool d_is_fallthru(const struct dentry *dentry)

View File

@ -315,6 +315,8 @@ struct address_space;
struct writeback_control; struct writeback_control;
#define IOCB_EVENTFD (1 << 0) #define IOCB_EVENTFD (1 << 0)
#define IOCB_APPEND (1 << 1)
#define IOCB_DIRECT (1 << 2)
struct kiocb { struct kiocb {
struct file *ki_filp; struct file *ki_filp;
@ -329,10 +331,13 @@ static inline bool is_sync_kiocb(struct kiocb *kiocb)
return kiocb->ki_complete == NULL; return kiocb->ki_complete == NULL;
} }
static inline int iocb_flags(struct file *file);
static inline void init_sync_kiocb(struct kiocb *kiocb, struct file *filp) static inline void init_sync_kiocb(struct kiocb *kiocb, struct file *filp)
{ {
*kiocb = (struct kiocb) { *kiocb = (struct kiocb) {
.ki_filp = filp, .ki_filp = filp,
.ki_flags = iocb_flags(filp),
}; };
} }
@ -383,7 +388,7 @@ struct address_space_operations {
void (*invalidatepage) (struct page *, unsigned int, unsigned int); void (*invalidatepage) (struct page *, unsigned int, unsigned int);
int (*releasepage) (struct page *, gfp_t); int (*releasepage) (struct page *, gfp_t);
void (*freepage)(struct page *); void (*freepage)(struct page *);
ssize_t (*direct_IO)(int, struct kiocb *, struct iov_iter *iter, loff_t offset); ssize_t (*direct_IO)(struct kiocb *, struct iov_iter *iter, loff_t offset);
/* /*
* migrate the contents of a page to the specified target. If * migrate the contents of a page to the specified target. If
* migrate_mode is MIGRATE_ASYNC, it must not block. * migrate_mode is MIGRATE_ASYNC, it must not block.
@ -2566,7 +2571,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, int isblk); 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 *);
@ -2609,8 +2614,8 @@ extern loff_t fixed_size_llseek(struct file *file, loff_t offset,
extern int generic_file_open(struct inode * inode, struct file * filp); extern int generic_file_open(struct inode * inode, struct file * filp);
extern int nonseekable_open(struct inode * inode, struct file * filp); extern int nonseekable_open(struct inode * inode, struct file * filp);
ssize_t dax_do_io(int rw, struct kiocb *, struct inode *, struct iov_iter *, ssize_t dax_do_io(struct kiocb *, struct inode *, struct iov_iter *, loff_t,
loff_t, get_block_t, dio_iodone_t, int flags); get_block_t, dio_iodone_t, int flags);
int dax_clear_blocks(struct inode *, sector_t block, long size); int dax_clear_blocks(struct inode *, sector_t block, long size);
int dax_zero_page_range(struct inode *, loff_t from, unsigned len, get_block_t); int dax_zero_page_range(struct inode *, loff_t from, unsigned len, get_block_t);
int dax_truncate_page(struct inode *, loff_t from, get_block_t); int dax_truncate_page(struct inode *, loff_t from, get_block_t);
@ -2635,16 +2640,18 @@ enum {
void dio_end_io(struct bio *bio, int error); void dio_end_io(struct bio *bio, int error);
ssize_t __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, ssize_t __blockdev_direct_IO(struct kiocb *iocb, struct inode *inode,
struct block_device *bdev, struct iov_iter *iter, loff_t offset, struct block_device *bdev, struct iov_iter *iter,
get_block_t get_block, dio_iodone_t end_io, loff_t offset, get_block_t get_block,
dio_submit_t submit_io, int flags); dio_iodone_t end_io, dio_submit_t submit_io,
int flags);
static inline ssize_t blockdev_direct_IO(int rw, struct kiocb *iocb, static inline ssize_t blockdev_direct_IO(struct kiocb *iocb,
struct inode *inode, struct iov_iter *iter, loff_t offset, struct inode *inode,
get_block_t get_block) struct iov_iter *iter, loff_t offset,
get_block_t get_block)
{ {
return __blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iter, return __blockdev_direct_IO(iocb, inode, inode->i_sb->s_bdev, iter,
offset, get_block, NULL, NULL, offset, get_block, NULL, NULL,
DIO_LOCKING | DIO_SKIP_HOLES); DIO_LOCKING | DIO_SKIP_HOLES);
} }
@ -2777,6 +2784,16 @@ static inline bool io_is_direct(struct file *filp)
return (filp->f_flags & O_DIRECT) || IS_DAX(file_inode(filp)); return (filp->f_flags & O_DIRECT) || IS_DAX(file_inode(filp));
} }
static inline int iocb_flags(struct file *file)
{
int res = 0;
if (file->f_flags & O_APPEND)
res |= IOCB_APPEND;
if (io_is_direct(file))
res |= IOCB_DIRECT;
return res;
}
static inline ino_t parent_ino(struct dentry *dentry) static inline ino_t parent_ino(struct dentry *dentry)
{ {
ino_t res; ino_t res;

View File

@ -447,13 +447,12 @@ static inline struct rpc_cred *nfs_file_cred(struct file *file)
/* /*
* linux/fs/nfs/direct.c * linux/fs/nfs/direct.c
*/ */
extern ssize_t nfs_direct_IO(int, struct kiocb *, struct iov_iter *, loff_t); extern ssize_t nfs_direct_IO(struct kiocb *, struct iov_iter *, loff_t);
extern ssize_t nfs_file_direct_read(struct kiocb *iocb, extern ssize_t nfs_file_direct_read(struct kiocb *iocb,
struct iov_iter *iter, struct iov_iter *iter,
loff_t pos); loff_t pos);
extern ssize_t nfs_file_direct_write(struct kiocb *iocb, extern ssize_t nfs_file_direct_write(struct kiocb *iocb,
struct iov_iter *iter, struct iov_iter *iter);
loff_t pos);
/* /*
* linux/fs/nfs/dir.c * linux/fs/nfs/dir.c

View File

@ -111,6 +111,14 @@ static inline bool iter_is_iovec(struct iov_iter *i)
return !(i->type & (ITER_BVEC | ITER_KVEC)); return !(i->type & (ITER_BVEC | ITER_KVEC));
} }
/*
* Get one of READ or WRITE out of iter->type without any other flags OR'd in
* with it.
*
* The ?: is just for type safety.
*/
#define iov_iter_rw(i) ((0 ? (struct iov_iter *)0 : (i))->type & RW_MASK)
/* /*
* Cap the iov_iter by given limit; note that the second argument is * Cap the iov_iter by given limit; note that the second argument is
* *not* the new size - it's upper limit for such. Passing it a value * *not* the new size - it's upper limit for such. Passing it a value

View File

@ -1693,7 +1693,7 @@ generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
loff_t *ppos = &iocb->ki_pos; loff_t *ppos = &iocb->ki_pos;
loff_t pos = *ppos; loff_t pos = *ppos;
if (io_is_direct(file)) { if (iocb->ki_flags & IOCB_DIRECT) {
struct address_space *mapping = file->f_mapping; struct address_space *mapping = file->f_mapping;
struct inode *inode = mapping->host; struct inode *inode = mapping->host;
size_t count = iov_iter_count(iter); size_t count = iov_iter_count(iter);
@ -1706,7 +1706,7 @@ generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
pos + count - 1); pos + count - 1);
if (!retval) { if (!retval) {
struct iov_iter data = *iter; struct iov_iter data = *iter;
retval = mapping->a_ops->direct_IO(READ, iocb, &data, pos); retval = mapping->a_ops->direct_IO(iocb, &data, pos);
} }
if (retval > 0) { if (retval > 0) {
@ -2259,41 +2259,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, int isblk) 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;
if (!isblk) { /* FIXME: this is for backwards compatibility with 2.4 */
/* FIXME: this is for backwards compatibility with 2.4 */ if (iocb->ki_flags & IOCB_APPEND)
if (file->f_flags & O_APPEND) iocb->ki_pos = i_size_read(inode);
*pos = i_size_read(inode);
if (limit != RLIM_INFINITY) { pos = iocb->ki_pos;
if (*pos >= limit) {
send_sig(SIGXFSZ, current, 0); if (limit != RLIM_INFINITY) {
return -EFBIG; if (iocb->ki_pos >= limit) {
} send_sig(SIGXFSZ, current, 0);
if (*count > limit - (typeof(limit))*pos) { return -EFBIG;
*count = limit - (typeof(limit))*pos;
}
} }
iov_iter_truncate(from, limit - (unsigned long)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;
} iov_iter_truncate(from, MAX_NON_LFS - (unsigned long)pos);
if (*count > MAX_NON_LFS - (unsigned long)*pos) {
*count = MAX_NON_LFS - (unsigned long)*pos;
}
} }
/* /*
@ -2303,34 +2300,11 @@ inline int generic_write_checks(struct file *file, loff_t *pos, size_t *count, i
* 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 (likely(!isblk)) { if (unlikely(pos >= inode->i_sb->s_maxbytes))
if (unlikely(*pos >= inode->i_sb->s_maxbytes)) { return -EFBIG;
if (*count || *pos > inode->i_sb->s_maxbytes) {
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);
} else {
#ifdef CONFIG_BLOCK
loff_t isize;
if (bdev_read_only(I_BDEV(inode)))
return -EPERM;
isize = i_size_read(inode);
if (*pos >= isize) {
if (*count || *pos > isize)
return -ENOSPC;
}
if (*pos + *count > isize)
*count = isize - *pos;
#else
return -EPERM;
#endif
}
return 0;
} }
EXPORT_SYMBOL(generic_write_checks); EXPORT_SYMBOL(generic_write_checks);
@ -2394,7 +2368,7 @@ generic_file_direct_write(struct kiocb *iocb, struct iov_iter *from, loff_t pos)
} }
data = *from; data = *from;
written = mapping->a_ops->direct_IO(WRITE, iocb, &data, pos); written = mapping->a_ops->direct_IO(iocb, &data, pos);
/* /*
* Finally, try again to invalidate clean pages which might have been * Finally, try again to invalidate clean pages which might have been
@ -2556,23 +2530,12 @@ 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 address_space * mapping = file->f_mapping; struct address_space * mapping = file->f_mapping;
struct inode *inode = mapping->host; struct inode *inode = mapping->host;
loff_t pos = iocb->ki_pos;
ssize_t written = 0; ssize_t written = 0;
ssize_t err; ssize_t err;
ssize_t status; ssize_t status;
size_t count = iov_iter_count(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, S_ISBLK(inode->i_mode));
if (err)
goto out;
if (count == 0)
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;
@ -2581,10 +2544,10 @@ ssize_t __generic_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
if (err) if (err)
goto out; goto out;
if (io_is_direct(file)) { if (iocb->ki_flags & IOCB_DIRECT) {
loff_t endbyte; loff_t pos, endbyte;
written = generic_file_direct_write(iocb, from, pos); written = generic_file_direct_write(iocb, from, iocb->ki_pos);
/* /*
* If the write stopped short of completing, fall back to * If the write stopped short of completing, fall back to
* buffered writes. Some filesystems do this for writes to * buffered writes. Some filesystems do this for writes to
@ -2592,13 +2555,10 @@ ssize_t __generic_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
* not succeed (even if it did, DAX does not handle dirty * not succeed (even if it did, DAX does not handle dirty
* page-cache pages correctly). * page-cache pages correctly).
*/ */
if (written < 0 || written == count || IS_DAX(inode)) if (written < 0 || !iov_iter_count(from) || IS_DAX(inode))
goto out; goto out;
pos += written; status = generic_perform_write(file, from, pos = iocb->ki_pos);
count -= written;
status = generic_perform_write(file, from, pos);
/* /*
* If generic_perform_write() returned a synchronous error * If generic_perform_write() returned a synchronous error
* then we want to return the number of bytes which were * then we want to return the number of bytes which were
@ -2610,15 +2570,15 @@ ssize_t __generic_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
err = status; err = status;
goto out; goto out;
} }
iocb->ki_pos = pos + status;
/* /*
* We need to ensure that the page cache pages are written to * We need to ensure that the page cache pages are written to
* disk and invalidated to preserve the expected O_DIRECT * disk and invalidated to preserve the expected O_DIRECT
* semantics. * semantics.
*/ */
endbyte = pos + status - 1; endbyte = pos + status - 1;
err = filemap_write_and_wait_range(file->f_mapping, pos, endbyte); err = filemap_write_and_wait_range(mapping, pos, endbyte);
if (err == 0) { if (err == 0) {
iocb->ki_pos = endbyte + 1;
written += status; written += status;
invalidate_mapping_pages(mapping, invalidate_mapping_pages(mapping,
pos >> PAGE_CACHE_SHIFT, pos >> PAGE_CACHE_SHIFT,
@ -2630,9 +2590,9 @@ ssize_t __generic_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
*/ */
} }
} else { } else {
written = generic_perform_write(file, from, pos); written = generic_perform_write(file, from, iocb->ki_pos);
if (likely(written >= 0)) if (likely(written > 0))
iocb->ki_pos = pos + written; iocb->ki_pos += written;
} }
out: out:
current->backing_dev_info = NULL; current->backing_dev_info = NULL;
@ -2656,7 +2616,9 @@ ssize_t generic_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
ssize_t ret; ssize_t ret;
mutex_lock(&inode->i_mutex); mutex_lock(&inode->i_mutex);
ret = __generic_file_write_iter(iocb, from); ret = generic_write_checks(iocb, from);
if (ret > 0)
ret = __generic_file_write_iter(iocb, from);
mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex);
if (ret > 0) { if (ret > 0) {

View File

@ -277,9 +277,7 @@ int __swap_writepage(struct page *page, struct writeback_control *wbc,
set_page_writeback(page); set_page_writeback(page);
unlock_page(page); unlock_page(page);
ret = mapping->a_ops->direct_IO(ITER_BVEC | WRITE, ret = mapping->a_ops->direct_IO(&kiocb, &from, kiocb.ki_pos);
&kiocb, &from,
kiocb.ki_pos);
if (ret == PAGE_SIZE) { if (ret == PAGE_SIZE) {
count_vm_event(PSWPOUT); count_vm_event(PSWPOUT);
ret = 0; ret = 0;