inode_dio_write_done(inode);
mutex_unlock(&inode->i_mutex);
down_write(&lli->lli_trunc_sem);
- mutex_lock(&inode->i_mutex);
- if (ia_valid & ATTR_SIZE)
- inode_dio_wait(inode);
}
/* We need a steady stripe configuration for setattr to avoid
}
ll_finish_md_op_data(op_data);
}
- if (!S_ISDIR(inode->i_mode))
+ if (!S_ISDIR(inode->i_mode)) {
up_write(&lli->lli_trunc_sem);
+ mutex_lock(&inode->i_mutex);
+ if (ia_valid & ATTR_SIZE)
+ inode_dio_wait(inode);
+ }
- ll_stats_ops_tally(ll_i2sbi(inode), (ia_valid & ATTR_SIZE) ?
- LPROC_LL_TRUNC : LPROC_LL_SETATTR, 1);
+ ll_stats_ops_tally(ll_i2sbi(inode), (ia_valid & ATTR_SIZE) ?
+ LPROC_LL_TRUNC : LPROC_LL_SETATTR, 1);
- return rc;
+ return rc;
}
int ll_setattr(struct dentry *de, struct iattr *attr)
static int vvp_io_setattr_iter_init(const struct lu_env *env,
const struct cl_io_slice *ios)
{
- struct ccc_io *cio = ccc_env_io(env);
- struct inode *inode = ccc_object_inode(ios->cis_obj);
-
- /*
- * We really need to get our PW lock before we change inode->i_size.
- * If we don't we can race with other i_size updaters on our node,
- * like ll_file_read. We can also race with i_size propogation to
- * other nodes through dirtying and writeback of final cached pages.
- * This last one is especially bad for racing o_append users on other
- * nodes.
- */
- if (cl_io_is_trunc(ios->cis_io))
- inode_dio_write_done(inode);
- mutex_unlock(&inode->i_mutex);
- cio->u.setattr.cui_locks_released = 1;
return 0;
}
static int vvp_io_setattr_start(const struct lu_env *env,
const struct cl_io_slice *ios)
{
- struct ccc_io *cio = cl2ccc_io(env, ios);
struct cl_io *io = ios->cis_io;
struct inode *inode = ccc_object_inode(io->ci_obj);
- LASSERT(cio->u.setattr.cui_locks_released);
-
mutex_lock(&inode->i_mutex);
- cio->u.setattr.cui_locks_released = 0;
-
if (cl_io_is_trunc(io))
return vvp_io_setattr_trunc(env, ios, inode,
io->u.ci_setattr.sa_attr.lvb_size);
static void vvp_io_setattr_end(const struct lu_env *env,
const struct cl_io_slice *ios)
{
- struct cl_io *io = ios->cis_io;
- struct inode *inode = ccc_object_inode(io->ci_obj);
-
- if (!cl_io_is_trunc(io))
- return;
+ struct cl_io *io = ios->cis_io;
+ struct inode *inode = ccc_object_inode(io->ci_obj);
- /* Truncate in memory pages - they must be clean pages because osc
- * has already notified to destroy osc_extents. */
- vvp_do_vmtruncate(inode, io->u.ci_setattr.sa_attr.lvb_size);
+ if (cl_io_is_trunc(io)) {
+ /* Truncate in memory pages - they must be clean pages
+ * because osc has already notified to destroy osc_extents. */
+ vvp_do_vmtruncate(inode, io->u.ci_setattr.sa_attr.lvb_size);
+ inode_dio_write_done(inode);
+ }
+ mutex_unlock(&inode->i_mutex);
}
static void vvp_io_setattr_fini(const struct lu_env *env,
const struct cl_io_slice *ios)
{
- struct ccc_io *cio = ccc_env_io(env);
- struct cl_io *io = ios->cis_io;
- struct inode *inode = ccc_object_inode(ios->cis_io->ci_obj);
-
- if (cio->u.setattr.cui_locks_released) {
- mutex_lock(&inode->i_mutex);
- if (cl_io_is_trunc(io))
- inode_dio_wait(inode);
- cio->u.setattr.cui_locks_released = 0;
- }
vvp_io_fini(env, ios);
}