You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs updates from Al Viro:
"This the bunch that sat in -next + lock_parent() fix. This is the
minimal set; there's more pending stuff.
In particular, I really hope to get acct.c fixes merged this cycle -
we need that to deal sanely with delayed-mntput stuff. In the next
pile, hopefully - that series is fairly short and localized
(kernel/acct.c, fs/super.c and fs/namespace.c). In this pile: more
iov_iter work. Most of prereqs for ->splice_write with sane locking
order are there and Kent's dio rewrite would also fit nicely on top of
this pile"
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (70 commits)
lock_parent: don't step on stale ->d_parent of all-but-freed one
kill generic_file_splice_write()
ceph: switch to iter_file_splice_write()
shmem: switch to iter_file_splice_write()
nfs: switch to iter_splice_write_file()
fs/splice.c: remove unneeded exports
ocfs2: switch to iter_file_splice_write()
->splice_write() via ->write_iter()
bio_vec-backed iov_iter
optimize copy_page_{to,from}_iter()
bury generic_file_aio_{read,write}
lustre: get rid of messing with iovecs
ceph: switch to ->write_iter()
ceph_sync_direct_write: stop poking into iov_iter guts
ceph_sync_read: stop poking into iov_iter guts
new helper: copy_page_from_iter()
fuse: switch to ->write_iter()
btrfs: switch to ->write_iter()
ocfs2: switch to ->write_iter()
xfs: switch to ->write_iter()
...
This commit is contained in:
@@ -196,8 +196,7 @@ prototypes:
|
||||
void (*invalidatepage) (struct page *, unsigned int, unsigned int);
|
||||
int (*releasepage) (struct page *, int);
|
||||
void (*freepage)(struct page *);
|
||||
int (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
|
||||
loff_t offset, unsigned long nr_segs);
|
||||
int (*direct_IO)(int, struct kiocb *, struct iov_iter *iter, loff_t offset);
|
||||
int (*get_xip_mem)(struct address_space *, pgoff_t, int, void **,
|
||||
unsigned long *);
|
||||
int (*migratepage)(struct address_space *, struct page *, struct page *);
|
||||
@@ -431,6 +430,8 @@ prototypes:
|
||||
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
|
||||
ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
|
||||
ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
|
||||
ssize_t (*read_iter) (struct kiocb *, struct iov_iter *);
|
||||
ssize_t (*write_iter) (struct kiocb *, struct iov_iter *);
|
||||
int (*iterate) (struct file *, struct dir_context *);
|
||||
unsigned int (*poll) (struct file *, struct poll_table_struct *);
|
||||
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
|
||||
|
||||
@@ -589,8 +589,7 @@ struct address_space_operations {
|
||||
void (*invalidatepage) (struct page *, unsigned int, unsigned int);
|
||||
int (*releasepage) (struct page *, int);
|
||||
void (*freepage)(struct page *);
|
||||
ssize_t (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
|
||||
loff_t offset, unsigned long nr_segs);
|
||||
ssize_t (*direct_IO)(int, struct kiocb *, struct iov_iter *iter, loff_t offset);
|
||||
struct page* (*get_xip_page)(struct address_space *, sector_t,
|
||||
int);
|
||||
/* migrate the contents of a page to the specified target */
|
||||
@@ -807,6 +806,8 @@ struct file_operations {
|
||||
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
|
||||
ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
|
||||
ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
|
||||
ssize_t (*read_iter) (struct kiocb *, struct iov_iter *);
|
||||
ssize_t (*write_iter) (struct kiocb *, struct iov_iter *);
|
||||
int (*iterate) (struct file *, struct dir_context *);
|
||||
unsigned int (*poll) (struct file *, struct poll_table_struct *);
|
||||
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
|
||||
@@ -837,11 +838,15 @@ otherwise noted.
|
||||
|
||||
read: called by read(2) and related system calls
|
||||
|
||||
aio_read: called by io_submit(2) and other asynchronous I/O operations
|
||||
aio_read: vectored, possibly asynchronous read
|
||||
|
||||
read_iter: possibly asynchronous read with iov_iter as destination
|
||||
|
||||
write: called by write(2) and related system calls
|
||||
|
||||
aio_write: called by io_submit(2) and other asynchronous I/O operations
|
||||
aio_write: vectored, possibly asynchronous write
|
||||
|
||||
write_iter: possibly asynchronous write with iov_iter as source
|
||||
|
||||
iterate: called when the VFS needs to read the directory contents
|
||||
|
||||
|
||||
+4
-4
@@ -284,10 +284,10 @@ static long raw_ctl_compat_ioctl(struct file *file, unsigned int cmd,
|
||||
#endif
|
||||
|
||||
static const struct file_operations raw_fops = {
|
||||
.read = do_sync_read,
|
||||
.aio_read = generic_file_aio_read,
|
||||
.write = do_sync_write,
|
||||
.aio_write = blkdev_aio_write,
|
||||
.read = new_sync_read,
|
||||
.read_iter = generic_file_read_iter,
|
||||
.write = new_sync_write,
|
||||
.write_iter = blkdev_write_iter,
|
||||
.fsync = blkdev_fsync,
|
||||
.open = raw_open,
|
||||
.release = raw_release,
|
||||
|
||||
@@ -575,12 +575,12 @@ static int alloc_device(struct nandsim *ns)
|
||||
cfile = filp_open(cache_file, O_CREAT | O_RDWR | O_LARGEFILE, 0600);
|
||||
if (IS_ERR(cfile))
|
||||
return PTR_ERR(cfile);
|
||||
if (!cfile->f_op->read && !cfile->f_op->aio_read) {
|
||||
if (!(cfile->f_mode & FMODE_CAN_READ)) {
|
||||
NS_ERR("alloc_device: cache file not readable\n");
|
||||
err = -EINVAL;
|
||||
goto err_close;
|
||||
}
|
||||
if (!cfile->f_op->write && !cfile->f_op->aio_write) {
|
||||
if (!(cfile->f_mode & FMODE_CAN_WRITE)) {
|
||||
NS_ERR("alloc_device: cache file not writeable\n");
|
||||
err = -EINVAL;
|
||||
goto err_close;
|
||||
|
||||
@@ -82,16 +82,7 @@ struct ccc_io {
|
||||
/**
|
||||
* I/O vector information to or from which read/write is going.
|
||||
*/
|
||||
struct iovec *cui_iov;
|
||||
unsigned long cui_nrsegs;
|
||||
/**
|
||||
* Total iov count for left IO.
|
||||
*/
|
||||
unsigned long cui_tot_nrsegs;
|
||||
/**
|
||||
* Old length for iov that was truncated partially.
|
||||
*/
|
||||
size_t cui_iov_olen;
|
||||
struct iov_iter *cui_iter;
|
||||
/**
|
||||
* Total size for the left IO.
|
||||
*/
|
||||
|
||||
@@ -720,31 +720,12 @@ int ccc_io_one_lock_index(const struct lu_env *env, struct cl_io *io,
|
||||
void ccc_io_update_iov(const struct lu_env *env,
|
||||
struct ccc_io *cio, struct cl_io *io)
|
||||
{
|
||||
int i;
|
||||
size_t size = io->u.ci_rw.crw_count;
|
||||
|
||||
cio->cui_iov_olen = 0;
|
||||
if (!cl_is_normalio(env, io) || cio->cui_tot_nrsegs == 0)
|
||||
if (!cl_is_normalio(env, io) || cio->cui_iter == NULL)
|
||||
return;
|
||||
|
||||
for (i = 0; i < cio->cui_tot_nrsegs; i++) {
|
||||
struct iovec *iv = &cio->cui_iov[i];
|
||||
|
||||
if (iv->iov_len < size)
|
||||
size -= iv->iov_len;
|
||||
else {
|
||||
if (iv->iov_len > size) {
|
||||
cio->cui_iov_olen = iv->iov_len;
|
||||
iv->iov_len = size;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cio->cui_nrsegs = i + 1;
|
||||
LASSERTF(cio->cui_tot_nrsegs >= cio->cui_nrsegs,
|
||||
"tot_nrsegs: %lu, nrsegs: %lu\n",
|
||||
cio->cui_tot_nrsegs, cio->cui_nrsegs);
|
||||
iov_iter_truncate(cio->cui_iter, size);
|
||||
}
|
||||
|
||||
int ccc_io_one_lock(const struct lu_env *env, struct cl_io *io,
|
||||
@@ -775,30 +756,7 @@ void ccc_io_advance(const struct lu_env *env,
|
||||
if (!cl_is_normalio(env, io))
|
||||
return;
|
||||
|
||||
LASSERT(cio->cui_tot_nrsegs >= cio->cui_nrsegs);
|
||||
LASSERT(cio->cui_tot_count >= nob);
|
||||
|
||||
cio->cui_iov += cio->cui_nrsegs;
|
||||
cio->cui_tot_nrsegs -= cio->cui_nrsegs;
|
||||
cio->cui_tot_count -= nob;
|
||||
|
||||
/* update the iov */
|
||||
if (cio->cui_iov_olen > 0) {
|
||||
struct iovec *iv;
|
||||
|
||||
cio->cui_iov--;
|
||||
cio->cui_tot_nrsegs++;
|
||||
iv = &cio->cui_iov[0];
|
||||
if (io->ci_continue) {
|
||||
iv->iov_base += iv->iov_len;
|
||||
LASSERT(cio->cui_iov_olen > iv->iov_len);
|
||||
iv->iov_len = cio->cui_iov_olen - iv->iov_len;
|
||||
} else {
|
||||
/* restore the iov_len, in case of restart io. */
|
||||
iv->iov_len = cio->cui_iov_olen;
|
||||
}
|
||||
cio->cui_iov_olen = 0;
|
||||
}
|
||||
iov_iter_reexpand(cio->cui_iter, cio->cui_tot_count -= nob);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1114,9 +1114,7 @@ restart:
|
||||
|
||||
switch (vio->cui_io_subtype) {
|
||||
case IO_NORMAL:
|
||||
cio->cui_iov = args->u.normal.via_iov;
|
||||
cio->cui_nrsegs = args->u.normal.via_nrsegs;
|
||||
cio->cui_tot_nrsegs = cio->cui_nrsegs;
|
||||
cio->cui_iter = args->u.normal.via_iter;
|
||||
cio->cui_iocb = args->u.normal.via_iocb;
|
||||
if ((iot == CIT_WRITE) &&
|
||||
!(cio->cui_fd->fd_flags & LL_FILE_GROUP_LOCKED)) {
|
||||
@@ -1180,58 +1178,23 @@ out:
|
||||
return result;
|
||||
}
|
||||
|
||||
static ssize_t ll_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
|
||||
unsigned long nr_segs, loff_t pos)
|
||||
static ssize_t ll_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
|
||||
{
|
||||
struct lu_env *env;
|
||||
struct vvp_io_args *args;
|
||||
size_t count = 0;
|
||||
ssize_t result;
|
||||
int refcheck;
|
||||
|
||||
result = generic_segment_checks(iov, &nr_segs, &count, VERIFY_WRITE);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
env = cl_env_get(&refcheck);
|
||||
if (IS_ERR(env))
|
||||
return PTR_ERR(env);
|
||||
|
||||
args = vvp_env_args(env, IO_NORMAL);
|
||||
args->u.normal.via_iov = (struct iovec *)iov;
|
||||
args->u.normal.via_nrsegs = nr_segs;
|
||||
args->u.normal.via_iter = to;
|
||||
args->u.normal.via_iocb = iocb;
|
||||
|
||||
result = ll_file_io_generic(env, args, iocb->ki_filp, CIT_READ,
|
||||
&iocb->ki_pos, count);
|
||||
cl_env_put(env, &refcheck);
|
||||
return result;
|
||||
}
|
||||
|
||||
static ssize_t ll_file_read(struct file *file, char *buf, size_t count,
|
||||
loff_t *ppos)
|
||||
{
|
||||
struct lu_env *env;
|
||||
struct iovec *local_iov;
|
||||
struct kiocb *kiocb;
|
||||
ssize_t result;
|
||||
int refcheck;
|
||||
|
||||
env = cl_env_get(&refcheck);
|
||||
if (IS_ERR(env))
|
||||
return PTR_ERR(env);
|
||||
|
||||
local_iov = &vvp_env_info(env)->vti_local_iov;
|
||||
kiocb = &vvp_env_info(env)->vti_kiocb;
|
||||
local_iov->iov_base = (void __user *)buf;
|
||||
local_iov->iov_len = count;
|
||||
init_sync_kiocb(kiocb, file);
|
||||
kiocb->ki_pos = *ppos;
|
||||
kiocb->ki_nbytes = count;
|
||||
|
||||
result = ll_file_aio_read(kiocb, local_iov, 1, kiocb->ki_pos);
|
||||
*ppos = kiocb->ki_pos;
|
||||
|
||||
&iocb->ki_pos, iov_iter_count(to));
|
||||
cl_env_put(env, &refcheck);
|
||||
return result;
|
||||
}
|
||||
@@ -1239,64 +1202,27 @@ static ssize_t ll_file_read(struct file *file, char *buf, size_t count,
|
||||
/*
|
||||
* Write to a file (through the page cache).
|
||||
*/
|
||||
static ssize_t ll_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
|
||||
unsigned long nr_segs, loff_t pos)
|
||||
static ssize_t ll_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
|
||||
{
|
||||
struct lu_env *env;
|
||||
struct vvp_io_args *args;
|
||||
size_t count = 0;
|
||||
ssize_t result;
|
||||
int refcheck;
|
||||
|
||||
result = generic_segment_checks(iov, &nr_segs, &count, VERIFY_READ);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
env = cl_env_get(&refcheck);
|
||||
if (IS_ERR(env))
|
||||
return PTR_ERR(env);
|
||||
|
||||
args = vvp_env_args(env, IO_NORMAL);
|
||||
args->u.normal.via_iov = (struct iovec *)iov;
|
||||
args->u.normal.via_nrsegs = nr_segs;
|
||||
args->u.normal.via_iter = from;
|
||||
args->u.normal.via_iocb = iocb;
|
||||
|
||||
result = ll_file_io_generic(env, args, iocb->ki_filp, CIT_WRITE,
|
||||
&iocb->ki_pos, count);
|
||||
&iocb->ki_pos, iov_iter_count(from));
|
||||
cl_env_put(env, &refcheck);
|
||||
return result;
|
||||
}
|
||||
|
||||
static ssize_t ll_file_write(struct file *file, const char *buf, size_t count,
|
||||
loff_t *ppos)
|
||||
{
|
||||
struct lu_env *env;
|
||||
struct iovec *local_iov;
|
||||
struct kiocb *kiocb;
|
||||
ssize_t result;
|
||||
int refcheck;
|
||||
|
||||
env = cl_env_get(&refcheck);
|
||||
if (IS_ERR(env))
|
||||
return PTR_ERR(env);
|
||||
|
||||
local_iov = &vvp_env_info(env)->vti_local_iov;
|
||||
kiocb = &vvp_env_info(env)->vti_kiocb;
|
||||
local_iov->iov_base = (void __user *)buf;
|
||||
local_iov->iov_len = count;
|
||||
init_sync_kiocb(kiocb, file);
|
||||
kiocb->ki_pos = *ppos;
|
||||
kiocb->ki_nbytes = count;
|
||||
|
||||
result = ll_file_aio_write(kiocb, local_iov, 1, kiocb->ki_pos);
|
||||
*ppos = kiocb->ki_pos;
|
||||
|
||||
cl_env_put(env, &refcheck);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Send file content (through pagecache) somewhere with helper
|
||||
*/
|
||||
@@ -3143,10 +3069,10 @@ int ll_inode_permission(struct inode *inode, int mask)
|
||||
|
||||
/* -o localflock - only provides locally consistent flock locks */
|
||||
struct file_operations ll_file_operations = {
|
||||
.read = ll_file_read,
|
||||
.aio_read = ll_file_aio_read,
|
||||
.write = ll_file_write,
|
||||
.aio_write = ll_file_aio_write,
|
||||
.read = new_sync_read,
|
||||
.read_iter = ll_file_read_iter,
|
||||
.write = new_sync_write,
|
||||
.write_iter = ll_file_write_iter,
|
||||
.unlocked_ioctl = ll_file_ioctl,
|
||||
.open = ll_file_open,
|
||||
.release = ll_file_release,
|
||||
@@ -3158,10 +3084,10 @@ struct file_operations ll_file_operations = {
|
||||
};
|
||||
|
||||
struct file_operations ll_file_operations_flock = {
|
||||
.read = ll_file_read,
|
||||
.aio_read = ll_file_aio_read,
|
||||
.write = ll_file_write,
|
||||
.aio_write = ll_file_aio_write,
|
||||
.read = new_sync_read,
|
||||
.read_iter = ll_file_read_iter,
|
||||
.write = new_sync_write,
|
||||
.write_iter = ll_file_write_iter,
|
||||
.unlocked_ioctl = ll_file_ioctl,
|
||||
.open = ll_file_open,
|
||||
.release = ll_file_release,
|
||||
@@ -3176,10 +3102,10 @@ struct file_operations ll_file_operations_flock = {
|
||||
|
||||
/* These are for -o noflock - to return ENOSYS on flock calls */
|
||||
struct file_operations ll_file_operations_noflock = {
|
||||
.read = ll_file_read,
|
||||
.aio_read = ll_file_aio_read,
|
||||
.write = ll_file_write,
|
||||
.aio_write = ll_file_aio_write,
|
||||
.read = new_sync_read,
|
||||
.read_iter = ll_file_read_iter,
|
||||
.write = new_sync_write,
|
||||
.write_iter = ll_file_write_iter,
|
||||
.unlocked_ioctl = ll_file_ioctl,
|
||||
.open = ll_file_open,
|
||||
.release = ll_file_release,
|
||||
|
||||
@@ -917,8 +917,7 @@ struct vvp_io_args {
|
||||
union {
|
||||
struct {
|
||||
struct kiocb *via_iocb;
|
||||
struct iovec *via_iov;
|
||||
unsigned long via_nrsegs;
|
||||
struct iov_iter *via_iter;
|
||||
} normal;
|
||||
struct {
|
||||
struct pipe_inode_info *via_pipe;
|
||||
|
||||
@@ -151,8 +151,7 @@ static struct ll_cl_context *ll_cl_init(struct file *file,
|
||||
result = cl_io_rw_init(env, io, CIT_WRITE, pos, PAGE_CACHE_SIZE);
|
||||
if (result == 0) {
|
||||
cio->cui_fd = LUSTRE_FPRIVATE(file);
|
||||
cio->cui_iov = NULL;
|
||||
cio->cui_nrsegs = 0;
|
||||
cio->cui_iter = NULL;
|
||||
result = cl_io_iter_init(env, io);
|
||||
if (result == 0) {
|
||||
result = cl_io_lock(env, io);
|
||||
|
||||
@@ -218,14 +218,11 @@ static void ll_free_user_pages(struct page **pages, int npages, int do_dirty)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < npages; i++) {
|
||||
if (pages[i] == NULL)
|
||||
break;
|
||||
if (do_dirty)
|
||||
set_page_dirty_lock(pages[i]);
|
||||
page_cache_release(pages[i]);
|
||||
}
|
||||
|
||||
OBD_FREE_LARGE(pages, npages * sizeof(*pages));
|
||||
kvfree(pages);
|
||||
}
|
||||
|
||||
ssize_t ll_direct_rw_pages(const struct lu_env *env, struct cl_io *io,
|
||||
@@ -363,18 +360,16 @@ static ssize_t ll_direct_IO_26_seg(const struct lu_env *env, struct cl_io *io,
|
||||
#define MAX_DIO_SIZE ((MAX_MALLOC / sizeof(struct brw_page) * PAGE_CACHE_SIZE) & \
|
||||
~(DT_MAX_BRW_SIZE - 1))
|
||||
static ssize_t ll_direct_IO_26(int rw, struct kiocb *iocb,
|
||||
const struct iovec *iov, loff_t file_offset,
|
||||
unsigned long nr_segs)
|
||||
struct iov_iter *iter, loff_t file_offset)
|
||||
{
|
||||
struct lu_env *env;
|
||||
struct cl_io *io;
|
||||
struct file *file = iocb->ki_filp;
|
||||
struct inode *inode = file->f_mapping->host;
|
||||
struct ccc_object *obj = cl_inode2ccc(inode);
|
||||
long count = iov_length(iov, nr_segs);
|
||||
long tot_bytes = 0, result = 0;
|
||||
ssize_t count = iov_iter_count(iter);
|
||||
ssize_t tot_bytes = 0, result = 0;
|
||||
struct ll_inode_info *lli = ll_i2info(inode);
|
||||
unsigned long seg = 0;
|
||||
long size = MAX_DIO_SIZE;
|
||||
int refcheck;
|
||||
|
||||
@@ -392,11 +387,8 @@ static ssize_t ll_direct_IO_26(int rw, struct kiocb *iocb,
|
||||
MAX_DIO_SIZE >> PAGE_CACHE_SHIFT);
|
||||
|
||||
/* Check that all user buffers are aligned as well */
|
||||
for (seg = 0; seg < nr_segs; seg++) {
|
||||
if (((unsigned long)iov[seg].iov_base & ~CFS_PAGE_MASK) ||
|
||||
(iov[seg].iov_len & ~CFS_PAGE_MASK))
|
||||
if (iov_iter_alignment(iter) & ~CFS_PAGE_MASK)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
env = cl_env_get(&refcheck);
|
||||
LASSERT(!IS_ERR(env));
|
||||
@@ -411,37 +403,26 @@ static ssize_t ll_direct_IO_26(int rw, struct kiocb *iocb,
|
||||
mutex_lock(&inode->i_mutex);
|
||||
|
||||
LASSERT(obj->cob_transient_pages == 0);
|
||||
for (seg = 0; seg < nr_segs; seg++) {
|
||||
long iov_left = iov[seg].iov_len;
|
||||
unsigned long user_addr = (unsigned long)iov[seg].iov_base;
|
||||
while (iov_iter_count(iter)) {
|
||||
struct page **pages;
|
||||
size_t offs;
|
||||
|
||||
count = min_t(size_t, iov_iter_count(iter), size);
|
||||
if (rw == READ) {
|
||||
if (file_offset >= i_size_read(inode))
|
||||
break;
|
||||
if (file_offset + iov_left > i_size_read(inode))
|
||||
iov_left = i_size_read(inode) - file_offset;
|
||||
if (file_offset + count > i_size_read(inode))
|
||||
count = i_size_read(inode) - file_offset;
|
||||
}
|
||||
|
||||
while (iov_left > 0) {
|
||||
struct page **pages;
|
||||
int page_count, max_pages = 0;
|
||||
long bytes;
|
||||
|
||||
bytes = min(size, iov_left);
|
||||
page_count = ll_get_user_pages(rw, user_addr, bytes,
|
||||
&pages, &max_pages);
|
||||
if (likely(page_count > 0)) {
|
||||
if (unlikely(page_count < max_pages))
|
||||
bytes = page_count << PAGE_CACHE_SHIFT;
|
||||
result = iov_iter_get_pages_alloc(iter, &pages, count, &offs);
|
||||
if (likely(result > 0)) {
|
||||
int n = (result + offs + PAGE_SIZE - 1) / PAGE_SIZE;
|
||||
result = ll_direct_IO_26_seg(env, io, rw, inode,
|
||||
file->f_mapping,
|
||||
bytes, file_offset,
|
||||
pages, page_count);
|
||||
ll_free_user_pages(pages, max_pages, rw==READ);
|
||||
} else if (page_count == 0) {
|
||||
GOTO(out, result = -EFAULT);
|
||||
} else {
|
||||
result = page_count;
|
||||
result, file_offset,
|
||||
pages, n);
|
||||
ll_free_user_pages(pages, n, rw==READ);
|
||||
}
|
||||
if (unlikely(result <= 0)) {
|
||||
/* If we can't allocate a large enough buffer
|
||||
@@ -462,12 +443,9 @@ static ssize_t ll_direct_IO_26(int rw, struct kiocb *iocb,
|
||||
|
||||
GOTO(out, result);
|
||||
}
|
||||
|
||||
iov_iter_advance(iter, result);
|
||||
tot_bytes += result;
|
||||
file_offset += result;
|
||||
iov_left -= result;
|
||||
user_addr += result;
|
||||
}
|
||||
}
|
||||
out:
|
||||
LASSERT(obj->cob_transient_pages == 0);
|
||||
|
||||
@@ -211,27 +211,26 @@ static int vvp_mmap_locks(const struct lu_env *env,
|
||||
struct cl_lock_descr *descr = &cti->cti_descr;
|
||||
ldlm_policy_data_t policy;
|
||||
unsigned long addr;
|
||||
unsigned long seg;
|
||||
ssize_t count;
|
||||
int result;
|
||||
struct iov_iter i;
|
||||
struct iovec iov;
|
||||
|
||||
LASSERT(io->ci_type == CIT_READ || io->ci_type == CIT_WRITE);
|
||||
|
||||
if (!cl_is_normalio(env, io))
|
||||
return 0;
|
||||
|
||||
if (vio->cui_iov == NULL) /* nfs or loop back device write */
|
||||
if (vio->cui_iter == NULL) /* nfs or loop back device write */
|
||||
return 0;
|
||||
|
||||
/* No MM (e.g. NFS)? No vmas too. */
|
||||
if (mm == NULL)
|
||||
return 0;
|
||||
|
||||
for (seg = 0; seg < vio->cui_nrsegs; seg++) {
|
||||
const struct iovec *iv = &vio->cui_iov[seg];
|
||||
|
||||
addr = (unsigned long)iv->iov_base;
|
||||
count = iv->iov_len;
|
||||
iov_for_each(iov, i, *(vio->cui_iter)) {
|
||||
addr = (unsigned long)iov.iov_base;
|
||||
count = iov.iov_len;
|
||||
if (count == 0)
|
||||
continue;
|
||||
|
||||
@@ -527,9 +526,7 @@ static int vvp_io_read_start(const struct lu_env *env,
|
||||
switch (vio->cui_io_subtype) {
|
||||
case IO_NORMAL:
|
||||
LASSERT(cio->cui_iocb->ki_pos == pos);
|
||||
result = generic_file_aio_read(cio->cui_iocb,
|
||||
cio->cui_iov, cio->cui_nrsegs,
|
||||
cio->cui_iocb->ki_pos);
|
||||
result = generic_file_read_iter(cio->cui_iocb, cio->cui_iter);
|
||||
break;
|
||||
case IO_SPLICE:
|
||||
result = generic_file_splice_read(file, &pos,
|
||||
@@ -595,12 +592,11 @@ static int vvp_io_write_start(const struct lu_env *env,
|
||||
|
||||
CDEBUG(D_VFSTRACE, "write: [%lli, %lli)\n", pos, pos + (long long)cnt);
|
||||
|
||||
if (cio->cui_iov == NULL) /* from a temp io in ll_cl_init(). */
|
||||
if (cio->cui_iter == NULL) /* from a temp io in ll_cl_init(). */
|
||||
result = 0;
|
||||
else
|
||||
result = generic_file_aio_write(cio->cui_iocb,
|
||||
cio->cui_iov, cio->cui_nrsegs,
|
||||
cio->cui_iocb->ki_pos);
|
||||
result = generic_file_write_iter(cio->cui_iocb, cio->cui_iter);
|
||||
|
||||
if (result > 0) {
|
||||
if (result < cnt)
|
||||
io->ci_continue = 0;
|
||||
@@ -1162,10 +1158,9 @@ int vvp_io_init(const struct lu_env *env, struct cl_object *obj,
|
||||
* results." -- Single Unix Spec */
|
||||
if (count == 0)
|
||||
result = 1;
|
||||
else {
|
||||
else
|
||||
cio->cui_tot_count = count;
|
||||
cio->cui_tot_nrsegs = 0;
|
||||
}
|
||||
|
||||
/* for read/write, we store the jobid in the inode, and
|
||||
* it'll be fetched by osc when building RPC.
|
||||
*
|
||||
|
||||
@@ -220,11 +220,11 @@ int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
|
||||
* If we can't read the file, it's no good.
|
||||
* If we can't write the file, use it read-only.
|
||||
*/
|
||||
if (!(filp->f_op->read || filp->f_op->aio_read)) {
|
||||
if (!(filp->f_mode & FMODE_CAN_READ)) {
|
||||
LINFO(curlun, "file not readable: %s\n", filename);
|
||||
goto out;
|
||||
}
|
||||
if (!(filp->f_op->write || filp->f_op->aio_write))
|
||||
if (!(filp->f_mode & FMODE_CAN_WRITE))
|
||||
ro = 1;
|
||||
|
||||
size = i_size_read(inode->i_mapping->host);
|
||||
|
||||
+2
-3
@@ -259,8 +259,7 @@ static int v9fs_launder_page(struct page *page)
|
||||
*
|
||||
*/
|
||||
static ssize_t
|
||||
v9fs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
|
||||
loff_t pos, unsigned long nr_segs)
|
||||
v9fs_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, loff_t pos)
|
||||
{
|
||||
/*
|
||||
* FIXME
|
||||
@@ -269,7 +268,7 @@ v9fs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
|
||||
*/
|
||||
p9_debug(P9_DEBUG_VFS, "v9fs_direct_IO: v9fs_direct_IO (%s) off/no(%lld/%lu) EINVAL\n",
|
||||
iocb->ki_filp->f_path.dentry->d_name.name,
|
||||
(long long)pos, nr_segs);
|
||||
(long long)pos, iter->nr_segs);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
+7
-7
@@ -692,7 +692,7 @@ v9fs_cached_file_read(struct file *filp, char __user *data, size_t count,
|
||||
{
|
||||
if (filp->f_flags & O_DIRECT)
|
||||
return v9fs_direct_read(filp, data, count, offset);
|
||||
return do_sync_read(filp, data, count, offset);
|
||||
return new_sync_read(filp, data, count, offset);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -760,7 +760,7 @@ err_out:
|
||||
|
||||
buff_write:
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
return do_sync_write(filp, data, count, offsetp);
|
||||
return new_sync_write(filp, data, count, offsetp);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -778,7 +778,7 @@ v9fs_cached_file_write(struct file *filp, const char __user * data,
|
||||
|
||||
if (filp->f_flags & O_DIRECT)
|
||||
return v9fs_direct_write(filp, data, count, offset);
|
||||
return do_sync_write(filp, data, count, offset);
|
||||
return new_sync_write(filp, data, count, offset);
|
||||
}
|
||||
|
||||
|
||||
@@ -847,8 +847,8 @@ const struct file_operations v9fs_cached_file_operations = {
|
||||
.llseek = generic_file_llseek,
|
||||
.read = v9fs_cached_file_read,
|
||||
.write = v9fs_cached_file_write,
|
||||
.aio_read = generic_file_aio_read,
|
||||
.aio_write = generic_file_aio_write,
|
||||
.read_iter = generic_file_read_iter,
|
||||
.write_iter = generic_file_write_iter,
|
||||
.open = v9fs_file_open,
|
||||
.release = v9fs_dir_release,
|
||||
.lock = v9fs_file_lock,
|
||||
@@ -860,8 +860,8 @@ const struct file_operations v9fs_cached_file_operations_dotl = {
|
||||
.llseek = generic_file_llseek,
|
||||
.read = v9fs_cached_file_read,
|
||||
.write = v9fs_cached_file_write,
|
||||
.aio_read = generic_file_aio_read,
|
||||
.aio_write = generic_file_aio_write,
|
||||
.read_iter = generic_file_read_iter,
|
||||
.write_iter = generic_file_write_iter,
|
||||
.open = v9fs_file_open,
|
||||
.release = v9fs_dir_release,
|
||||
.lock = v9fs_file_lock_dotl,
|
||||
|
||||
+4
-4
@@ -23,12 +23,12 @@
|
||||
|
||||
const struct file_operations adfs_file_operations = {
|
||||
.llseek = generic_file_llseek,
|
||||
.read = do_sync_read,
|
||||
.aio_read = generic_file_aio_read,
|
||||
.read = new_sync_read,
|
||||
.read_iter = generic_file_read_iter,
|
||||
.mmap = generic_file_mmap,
|
||||
.fsync = generic_file_fsync,
|
||||
.write = do_sync_write,
|
||||
.aio_write = generic_file_aio_write,
|
||||
.write = new_sync_write,
|
||||
.write_iter = generic_file_write_iter,
|
||||
.splice_read = generic_file_splice_read,
|
||||
};
|
||||
|
||||
|
||||
+4
-4
@@ -27,10 +27,10 @@ static int affs_file_release(struct inode *inode, struct file *filp);
|
||||
|
||||
const struct file_operations affs_file_operations = {
|
||||
.llseek = generic_file_llseek,
|
||||
.read = do_sync_read,
|
||||
.aio_read = generic_file_aio_read,
|
||||
.write = do_sync_write,
|
||||
.aio_write = generic_file_aio_write,
|
||||
.read = new_sync_read,
|
||||
.read_iter = generic_file_read_iter,
|
||||
.write = new_sync_write,
|
||||
.write_iter = generic_file_write_iter,
|
||||
.mmap = generic_file_mmap,
|
||||
.open = affs_file_open,
|
||||
.release = affs_file_release,
|
||||
|
||||
+4
-4
@@ -31,10 +31,10 @@ const struct file_operations afs_file_operations = {
|
||||
.open = afs_open,
|
||||
.release = afs_release,
|
||||
.llseek = generic_file_llseek,
|
||||
.read = do_sync_read,
|
||||
.write = do_sync_write,
|
||||
.aio_read = generic_file_aio_read,
|
||||
.aio_write = afs_file_write,
|
||||
.read = new_sync_read,
|
||||
.write = new_sync_write,
|
||||
.read_iter = generic_file_read_iter,
|
||||
.write_iter = afs_file_write,
|
||||
.mmap = generic_file_readonly_mmap,
|
||||
.splice_read = generic_file_splice_read,
|
||||
.fsync = afs_fsync,
|
||||
|
||||
+1
-2
@@ -747,8 +747,7 @@ extern int afs_write_end(struct file *file, struct address_space *mapping,
|
||||
extern int afs_writepage(struct page *, struct writeback_control *);
|
||||
extern int afs_writepages(struct address_space *, struct writeback_control *);
|
||||
extern void afs_pages_written_back(struct afs_vnode *, struct afs_call *);
|
||||
extern ssize_t afs_file_write(struct kiocb *, const struct iovec *,
|
||||
unsigned long, loff_t);
|
||||
extern ssize_t afs_file_write(struct kiocb *, struct iov_iter *);
|
||||
extern int afs_writeback_all(struct afs_vnode *);
|
||||
extern int afs_fsync(struct file *, loff_t, loff_t, int);
|
||||
|
||||
|
||||
+5
-6
@@ -625,15 +625,14 @@ void afs_pages_written_back(struct afs_vnode *vnode, struct afs_call *call)
|
||||
/*
|
||||
* write to an AFS file
|
||||
*/
|
||||
ssize_t afs_file_write(struct kiocb *iocb, const struct iovec *iov,
|
||||
unsigned long nr_segs, loff_t pos)
|
||||
ssize_t afs_file_write(struct kiocb *iocb, struct iov_iter *from)
|
||||
{
|
||||
struct afs_vnode *vnode = AFS_FS_I(file_inode(iocb->ki_filp));
|
||||
ssize_t result;
|
||||
size_t count = iov_length(iov, nr_segs);
|
||||
size_t count = iov_iter_count(from);
|
||||
|
||||
_enter("{%x.%u},{%zu},%lu,",
|
||||
vnode->fid.vid, vnode->fid.vnode, count, nr_segs);
|
||||
_enter("{%x.%u},{%zu},",
|
||||
vnode->fid.vid, vnode->fid.vnode, count);
|
||||
|
||||
if (IS_SWAPFILE(&vnode->vfs_inode)) {
|
||||
printk(KERN_INFO
|
||||
@@ -644,7 +643,7 @@ ssize_t afs_file_write(struct kiocb *iocb, const struct iovec *iov,
|
||||
if (!count)
|
||||
return 0;
|
||||
|
||||
result = generic_file_aio_write(iocb, iov, nr_segs, pos);
|
||||
result = generic_file_write_iter(iocb, from);
|
||||
if (IS_ERR_VALUE(result)) {
|
||||
_leave(" = %zd", result);
|
||||
return result;
|
||||
|
||||
@@ -1241,6 +1241,7 @@ SYSCALL_DEFINE1(io_destroy, aio_context_t, ctx)
|
||||
|
||||
typedef ssize_t (aio_rw_op)(struct kiocb *, const struct iovec *,
|
||||
unsigned long, loff_t);
|
||||
typedef ssize_t (rw_iter_op)(struct kiocb *, struct iov_iter *);
|
||||
|
||||
static ssize_t aio_setup_vectored_rw(struct kiocb *kiocb,
|
||||
int rw, char __user *buf,
|
||||
@@ -1298,7 +1299,9 @@ static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode,
|
||||
int rw;
|
||||
fmode_t mode;
|
||||
aio_rw_op *rw_op;
|
||||
rw_iter_op *iter_op;
|
||||
struct iovec inline_vec, *iovec = &inline_vec;
|
||||
struct iov_iter iter;
|
||||
|
||||
switch (opcode) {
|
||||
case IOCB_CMD_PREAD:
|
||||
@@ -1306,6 +1309,7 @@ static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode,
|
||||
mode = FMODE_READ;
|
||||
rw = READ;
|
||||
rw_op = file->f_op->aio_read;
|
||||
iter_op = file->f_op->read_iter;
|
||||
goto rw_common;
|
||||
|
||||
case IOCB_CMD_PWRITE:
|
||||
@@ -1313,12 +1317,13 @@ static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode,
|
||||
mode = FMODE_WRITE;
|
||||
rw = WRITE;
|
||||
rw_op = file->f_op->aio_write;
|
||||
iter_op = file->f_op->write_iter;
|
||||
goto rw_common;
|
||||
rw_common:
|
||||
if (unlikely(!(file->f_mode & mode)))
|
||||
return -EBADF;
|
||||
|
||||
if (!rw_op)
|
||||
if (!rw_op && !iter_op)
|
||||
return -EINVAL;
|
||||
|
||||
ret = (opcode == IOCB_CMD_PREADV ||
|
||||
@@ -1347,7 +1352,12 @@ rw_common:
|
||||
if (rw == WRITE)
|
||||
file_start_write(file);
|
||||
|
||||
if (iter_op) {
|
||||
iov_iter_init(&iter, rw, iovec, nr_segs, req->ki_nbytes);
|
||||
ret = iter_op(req, &iter);
|
||||
} else {
|
||||
ret = rw_op(req, iovec, nr_segs, req->ki_pos);
|
||||
}
|
||||
|
||||
if (rw == WRITE)
|
||||
file_end_write(file);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user