Skip to content

Commit

Permalink
lustre: get rid of messing with iovecs
Browse files Browse the repository at this point in the history
* 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>
  • Loading branch information
Al Viro committed May 6, 2014
1 parent 4908b82 commit b42b15f
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 163 deletions.
11 changes: 1 addition & 10 deletions drivers/staging/lustre/lustre/include/lclient.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down
48 changes: 3 additions & 45 deletions drivers/staging/lustre/lustre/lclient/lcommon_cl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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);
}

/**
Expand Down
106 changes: 19 additions & 87 deletions drivers/staging/lustre/lustre/llite/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -1105,9 +1105,7 @@ ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args,

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)) {
Expand Down Expand Up @@ -1171,69 +1169,34 @@ ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args,
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;
}

/*
* 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;

Expand All @@ -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
*/
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand Down
3 changes: 1 addition & 2 deletions drivers/staging/lustre/lustre/llite/llite_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 1 addition & 2 deletions drivers/staging/lustre/lustre/llite/rw.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
29 changes: 12 additions & 17 deletions drivers/staging/lustre/lustre/llite/vvp_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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.
*
Expand Down
9 changes: 9 additions & 0 deletions include/linux/uio.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down

0 comments on commit b42b15f

Please sign in to comment.