mirror of
https://github.com/lkl/linux.git
synced 2025-12-19 16:13:19 +09:00
Merge tag 'pull-work.iov_iter-base' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs iov_iter updates from Al Viro:
"Part 1 - isolated cleanups and optimizations.
One of the goals is to reduce the overhead of using ->read_iter() and
->write_iter() instead of ->read()/->write().
new_sync_{read,write}() has a surprising amount of overhead, in
particular inside iocb_flags(). That's the explanation for the
beginning of the series is in this pile; it's not directly
iov_iter-related, but it's a part of the same work..."
* tag 'pull-work.iov_iter-base' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
first_iovec_segment(): just return address
iov_iter: massage calling conventions for first_{iovec,bvec}_segment()
iov_iter: first_{iovec,bvec}_segment() - simplify a bit
iov_iter: lift dealing with maxpages out of first_{iovec,bvec}_segment()
iov_iter_get_pages{,_alloc}(): cap the maxsize with MAX_RW_COUNT
iov_iter_bvec_advance(): don't bother with bvec_iter
copy_page_{to,from}_iter(): switch iovec variants to generic
keep iocb_flags() result cached in struct file
iocb: delay evaluation of IS_SYNC(...) until we want to check IOCB_DSYNC
struct file: use anonymous union member for rcuhead and llist
btrfs: use IOMAP_DIO_NOSYNC
teach iomap_dio_rw() to suppress dsync
No need of likely/unlikely on calls of check_copy_size()
This commit is contained in:
@@ -943,9 +943,10 @@ static inline int ra_has_index(struct file_ra_state *ra, pgoff_t index)
|
||||
|
||||
struct file {
|
||||
union {
|
||||
struct llist_node fu_llist;
|
||||
struct rcu_head fu_rcuhead;
|
||||
} f_u;
|
||||
struct llist_node f_llist;
|
||||
struct rcu_head f_rcuhead;
|
||||
unsigned int f_iocb_flags;
|
||||
};
|
||||
struct path f_path;
|
||||
struct inode *f_inode; /* cached value */
|
||||
const struct file_operations *f_op;
|
||||
@@ -2328,13 +2329,11 @@ static inline bool HAS_UNMAPPED_ID(struct user_namespace *mnt_userns,
|
||||
!vfsgid_valid(i_gid_into_vfsgid(mnt_userns, inode));
|
||||
}
|
||||
|
||||
static inline int iocb_flags(struct file *file);
|
||||
|
||||
static inline void init_sync_kiocb(struct kiocb *kiocb, struct file *filp)
|
||||
{
|
||||
*kiocb = (struct kiocb) {
|
||||
.ki_filp = filp,
|
||||
.ki_flags = iocb_flags(filp),
|
||||
.ki_flags = filp->f_iocb_flags,
|
||||
.ki_ioprio = get_current_ioprio(),
|
||||
};
|
||||
}
|
||||
@@ -2850,6 +2849,12 @@ extern int vfs_fsync(struct file *file, int datasync);
|
||||
extern int sync_file_range(struct file *file, loff_t offset, loff_t nbytes,
|
||||
unsigned int flags);
|
||||
|
||||
static inline bool iocb_is_dsync(const struct kiocb *iocb)
|
||||
{
|
||||
return (iocb->ki_flags & IOCB_DSYNC) ||
|
||||
IS_SYNC(iocb->ki_filp->f_mapping->host);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sync the bytes written if this was a synchronous write. Expect ki_pos
|
||||
* to already be updated for the write, and will return either the amount
|
||||
@@ -2857,7 +2862,7 @@ extern int sync_file_range(struct file *file, loff_t offset, loff_t nbytes,
|
||||
*/
|
||||
static inline ssize_t generic_write_sync(struct kiocb *iocb, ssize_t count)
|
||||
{
|
||||
if (iocb->ki_flags & IOCB_DSYNC) {
|
||||
if (iocb_is_dsync(iocb)) {
|
||||
int ret = vfs_fsync_range(iocb->ki_filp,
|
||||
iocb->ki_pos - count, iocb->ki_pos - 1,
|
||||
(iocb->ki_flags & IOCB_SYNC) ? 0 : 1);
|
||||
@@ -3380,7 +3385,7 @@ static inline int iocb_flags(struct file *file)
|
||||
res |= IOCB_APPEND;
|
||||
if (file->f_flags & O_DIRECT)
|
||||
res |= IOCB_DIRECT;
|
||||
if ((file->f_flags & O_DSYNC) || IS_SYNC(file->f_mapping->host))
|
||||
if (file->f_flags & O_DSYNC)
|
||||
res |= IOCB_DSYNC;
|
||||
if (file->f_flags & __O_SYNC)
|
||||
res |= IOCB_SYNC;
|
||||
|
||||
Reference in New Issue
Block a user