struct cl_lockset ci_lockset;
/** lock requirements, this is just a help info for sublayers. */
enum cl_io_lock_dmd ci_lockreq;
- /**
- * This io has held grouplock, to inform sublayers that
- * don't do lockless i/o.
- */
- int ci_no_srvlock;
union {
struct cl_rd_io {
struct cl_io_rw_common rd;
struct cl_2queue ci_queue;
size_t ci_nob;
int ci_result;
- int ci_continue;
+ unsigned int ci_continue:1,
+ /**
+ * This io has held grouplock, to inform sublayers that
+ * don't do lockless i/o.
+ */
+ ci_no_srvlock:1,
+ /**
+ * The whole IO need to be restarted because layout has been changed
+ */
+ ci_need_restart:1,
+ /**
+ * Ignore layout change.
+ * Most of the CIT_MISC operations can ignore layout change, because
+ * the purpose to create this kind of cl_io is to give an environment
+ * to run clio methods, for example:
+ * 1. request group lock;
+ * 2. flush caching pages by osc;
+ * 3. writepage
+ * 4. echo client
+ * So far, only direct IO and glimpse clio need restart if layout
+ * change during IO time.
+ */
+ ci_ignore_layout:1;
/**
* Number of pages owned by this IO. For invariant checking.
*/
* True iff io is processing glimpse right now.
*/
int cui_glimpse;
+ /**
+ * Layout version when this IO is initialized
+ */
+ __u32 cui_layout_gen;
/**
* File descriptor against which IO is done.
*/
result = cl_io_get(inode, &env, &io, &refcheck);
if (result > 0) {
+ again:
result = cl_io_init(env, io, CIT_MISC, io->ci_obj);
if (result > 0)
/*
result = cl_glimpse_lock(env, io, inode, io->ci_obj,
agl);
cl_io_fini(env, io);
- cl_env_put(env, &refcheck);
- }
- RETURN(result);
+ if (unlikely(io->ci_need_restart))
+ goto again;
+ cl_env_put(env, &refcheck);
+ }
+ RETURN(result);
}
int cl_local_size(struct inode *inode)
io->u.ci_setattr.sa_valid = attr->ia_valid;
io->u.ci_setattr.sa_capa = capa;
+again:
if (cl_io_init(env, io, CIT_SETATTR, io->ci_obj) == 0) {
struct ccc_io *cio = ccc_env_io(env);
result = io->ci_result;
}
cl_io_fini(env, io);
- cl_env_put(env, &refcheck);
- RETURN(result);
+ if (unlikely(io->ci_need_restart))
+ goto again;
+ cl_env_put(env, &refcheck);
+ RETURN(result);
}
/*****************************************************************************
io = ccc_env_thread_io(env);
io->ci_obj = obj;
+ io->ci_ignore_layout = 1;
rc = cl_io_init(env, io, CIT_MISC, io->ci_obj);
if (rc) {
io = ccc_env_thread_io(env);
io->ci_obj = cl_i2info(inode)->lli_clob;
+ io->ci_ignore_layout = 1;
/* initialize parameters for sync */
fio = &io->u.ci_fsync;
io = ccc_env_thread_io(env);
io->ci_obj = clob;
+ io->ci_ignore_layout = 1;
result = cl_io_init(env, io, CIT_MISC, clob);
if (result == 0) {
page = cl_page_find(env, clob, vmpage->index,
static void vvp_io_fini(const struct lu_env *env, const struct cl_io_slice *ios)
{
- struct cl_io *io = ios->cis_io;
- struct cl_object *obj = io->ci_obj;
+ struct cl_io *io = ios->cis_io;
+ struct cl_object *obj = io->ci_obj;
+ struct ccc_io *cio = cl2ccc_io(env, ios);
+ __u32 gen;
+ int result;
CLOBINVRNT(env, obj, ccc_object_invariant(obj));
- if (io->ci_type == CIT_READ) {
- struct vvp_io *vio = cl2vvp_io(env, ios);
- struct ccc_io *cio = cl2ccc_io(env, ios);
-
- if (vio->cui_ra_window_set)
- ll_ra_read_ex(cio->cui_fd->fd_file, &vio->cui_bead);
- }
+ /* check layout version */
+ result = ll_layout_refresh(ccc_object_inode(obj), &gen);
+ if (cio->cui_layout_gen > 0)
+ io->ci_need_restart = cio->cui_layout_gen == gen;
}
static void vvp_io_fault_fini(const struct lu_env *env,
return result;
}
+static void vvp_io_read_fini(const struct lu_env *env, const struct cl_io_slice *ios)
+{
+ struct vvp_io *vio = cl2vvp_io(env, ios);
+ struct ccc_io *cio = cl2ccc_io(env, ios);
+
+ if (vio->cui_ra_window_set)
+ ll_ra_read_ex(cio->cui_fd->fd_file, &vio->cui_bead);
+
+ vvp_io_fini(env, ios);
+}
+
static int vvp_io_write_start(const struct lu_env *env,
const struct cl_io_slice *ios)
{
static const struct cl_io_operations vvp_io_ops = {
.op = {
[CIT_READ] = {
- .cio_fini = vvp_io_fini,
+ .cio_fini = vvp_io_read_fini,
.cio_lock = vvp_io_read_lock,
.cio_start = vvp_io_read_start,
.cio_advance = ccc_io_advance
int vvp_io_init(const struct lu_env *env, struct cl_object *obj,
struct cl_io *io)
{
- struct vvp_io *vio = vvp_env_io(env);
- struct ccc_io *cio = ccc_env_io(env);
+ struct vvp_io *vio = vvp_env_io(env);
+ struct ccc_io *cio = ccc_env_io(env);
+ struct inode *inode = ccc_object_inode(obj);
int result;
CLOBINVRNT(env, obj, ccc_object_invariant(obj));
CL_IO_SLICE_CLEAN(cio, cui_cl);
cl_io_slice_add(io, &cio->cui_cl, obj, &vvp_io_ops);
vio->cui_ra_window_set = 0;
- result = 0;
- if (io->ci_type == CIT_READ || io->ci_type == CIT_WRITE) {
- size_t count;
- struct ll_inode_info *lli = ll_i2info(ccc_object_inode(obj));
+ result = 0;
+ if (io->ci_type == CIT_READ || io->ci_type == CIT_WRITE) {
+ size_t count;
+ struct ll_inode_info *lli = ll_i2info(inode);
count = io->u.ci_rw.crw_count;
/* "If nbyte is 0, read() will return 0 and have no other
* jobs.
*/
lustre_get_jobid(lli->lli_jobid);
- } else if (io->ci_type == CIT_SETATTR) {
- if (!cl_io_is_trunc(io))
- io->ci_lockreq = CILR_MANDATORY;
- }
- RETURN(result);
+ } else if (io->ci_type == CIT_SETATTR) {
+ if (!cl_io_is_trunc(io))
+ io->ci_lockreq = CILR_MANDATORY;
+ }
+
+ /* Enqueue layout lock and get layout version. We need to do this
+ * even for operations requiring to open file, such as read and write,
+ * because it might not grant layout lock in IT_OPEN. */
+ if (result == 0 && !io->ci_ignore_layout)
+ result = ll_layout_refresh(inode, &cio->cui_layout_gen);
+
+ RETURN(result);
}
static struct vvp_io *cl2vvp_io(const struct lu_env *env,
*/
void cl_io_fini(const struct lu_env *env, struct cl_io *io)
{
- struct cl_io_slice *slice;
- struct cl_thread_info *info;
+ struct cl_io_slice *slice;
+ struct cl_thread_info *info;
LINVRNT(cl_io_type_is_valid(io->ci_type));
LINVRNT(cl_io_invariant(io));
info = cl_env_info(env);
if (info->clt_current_io == io)
info->clt_current_io = NULL;
- EXIT;
+
+ /* sanity check for layout change */
+ switch(io->ci_type) {
+ case CIT_READ:
+ case CIT_WRITE:
+ case CIT_FAULT:
+ case CIT_FSYNC:
+ LASSERT(!io->ci_need_restart);
+ break;
+ case CIT_MISC:
+ /* Check ignore layout change conf */
+ LASSERT(ergo(io->ci_ignore_layout, !io->ci_need_restart));
+ case CIT_SETATTR:
+ break;
+ default:
+ LBUG();
+ }
+ EXIT;
}
EXPORT_SYMBOL(cl_io_fini);
ENTRY;
io->ci_obj = cl_object_top(descr->cld_obj);
+ io->ci_ignore_layout = 1;
result = cl_io_init(env, io, CIT_MISC, io->ci_obj);
if (result != 0)
GOTO(out, result);
* function, we just make cl_page_list functions happy. -jay
*/
io->ci_obj = obj;
+ io->ci_ignore_layout = 1;
result = cl_io_init(env, io, CIT_MISC, obj);
if (result != 0) {
cl_io_fini(env, io);
info = echo_env_info(env);
io = &info->eti_io;
+ io->ci_ignore_layout = 1;
result = cl_io_init(env, io, CIT_MISC, echo_obj2cl(eco));
if (result < 0)
GOTO(out, result);
queue = &info->eti_queue;
cl_2queue_init(queue);
+
+ io->ci_ignore_layout = 1;
rc = cl_io_init(env, io, CIT_MISC, obj);
if (rc < 0)
GOTO(out, rc);
cfs_mutex_lock(&oob->oo_debug_mutex);
io->ci_obj = cl_object_top(obj);
+ io->ci_ignore_layout = 1;
cl_io_init(env, io, CIT_MISC, io->ci_obj);
do {
result = cl_page_gang_lookup(env, obj, io,