lustre: get rid of messing with iovecs
* switch to ->read_iter/->write_iter * keep a pointer to iov_iter instead of iov/nr_segs * do not modify iovecs; use iov_iter_truncate()/iov_iter_advance() and a new primitive - iov_iter_reexpand() (expand previously truncated iterator) istead. * (racy) check for lustre VMAs intersecting with iovecs kept for now as for_each_iov() loop. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
4908b822b3
commit
b42b15fdad
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -721,31 +721,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,
|
||||
|
@ -776,30 +757,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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1105,9 +1105,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)) {
|
||||
|
@ -1171,56 +1169,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;
|
||||
|
||||
count = iov_length(iov, nr_segs);
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -1228,12 +1193,10 @@ 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 = iov_length(iov, nr_segs);
|
||||
ssize_t result;
|
||||
int refcheck;
|
||||
|
||||
|
@ -1242,46 +1205,15 @@ static ssize_t ll_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
|
|||
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
|
||||
*/
|
||||
|
@ -3133,10 +3065,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,
|
||||
|
@ -3148,10 +3080,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,
|
||||
|
@ -3166,10 +3098,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,
|
||||
|
|
|
@ -974,8 +974,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;
|
||||
|
|
|
@ -157,8 +157,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);
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -90,6 +90,15 @@ static inline void iov_iter_truncate(struct iov_iter *i, size_t count)
|
|||
i->count = count;
|
||||
}
|
||||
|
||||
/*
|
||||
* reexpand a previously truncated iterator; count must be no more than how much
|
||||
* we had shrunk it.
|
||||
*/
|
||||
static inline void iov_iter_reexpand(struct iov_iter *i, size_t count)
|
||||
{
|
||||
i->count = count;
|
||||
}
|
||||
|
||||
int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len);
|
||||
int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len);
|
||||
|
||||
|
|
Loading…
Reference in New Issue