/* inode size will be in ll_setattr_ost, can't do it now since dirty
* cache is not cleared yet. */
op_data->op_attr.ia_valid &= ~(TIMES_SET_FLAGS | ATTR_SIZE);
+ if (S_ISREG(inode->i_mode))
+ mutex_lock(&inode->i_mutex);
rc = simple_setattr(dentry, &op_data->op_attr);
+ if (S_ISREG(inode->i_mode))
+ mutex_unlock(&inode->i_mutex);
op_data->op_attr.ia_valid = ia_valid;
rc = ll_update_inode(inode, &md);
struct inode *inode = dentry->d_inode;
struct ll_inode_info *lli = ll_i2info(inode);
struct md_op_data *op_data = NULL;
- bool file_is_released = false;
int rc = 0;
ENTRY;
LTIME_S(attr->ia_mtime), LTIME_S(attr->ia_ctime),
cfs_time_current_sec());
- /* We always do an MDS RPC, even if we're only changing the size;
- * only the MDS knows whether truncate() should fail with -ETXTBUSY */
-
- OBD_ALLOC_PTR(op_data);
- if (op_data == NULL)
- RETURN(-ENOMEM);
-
- if (!S_ISDIR(inode->i_mode)) {
+ if (S_ISREG(inode->i_mode)) {
if (attr->ia_valid & ATTR_SIZE)
inode_dio_write_done(inode);
mutex_unlock(&inode->i_mutex);
}
- /* truncate on a released file must failed with -ENODATA,
- * so size must not be set on MDS for released file
- * but other attributes must be set
- */
- if (S_ISREG(inode->i_mode)) {
- struct cl_layout cl = {
- .cl_is_released = false,
- };
- struct lu_env *env;
- int refcheck;
- __u32 gen;
+ /* We always do an MDS RPC, even if we're only changing the size;
+ * only the MDS knows whether truncate() should fail with -ETXTBUSY */
- rc = ll_layout_refresh(inode, &gen);
- if (rc < 0)
- GOTO(out, rc);
-
- /* XXX: the only place we need to know the layout type,
- * this will be removed by a later patch. -Jinshan */
- env = cl_env_get(&refcheck);
- if (IS_ERR(env))
- GOTO(out, rc = PTR_ERR(env));
-
- rc = cl_object_layout_get(env, lli->lli_clob, &cl);
- cl_env_put(env, &refcheck);
- if (rc < 0)
- GOTO(out, rc);
-
- file_is_released = cl.cl_is_released;
+ OBD_ALLOC_PTR(op_data);
+ if (op_data == NULL)
+ GOTO(out, rc = -ENOMEM);
- if (!hsm_import && attr->ia_valid & ATTR_SIZE) {
- if (file_is_released) {
- rc = ll_layout_restore(inode, 0, attr->ia_size);
- if (rc < 0)
- GOTO(out, rc);
+ op_data->op_attr = *attr;
- file_is_released = false;
- ll_layout_refresh(inode, &gen);
- }
-
- /* If we are changing file size, file content is
- * modified, flag it. */
- attr->ia_valid |= MDS_OPEN_OWNEROVERRIDE;
- op_data->op_bias |= MDS_DATA_MODIFIED;
- }
+ if (!hsm_import && attr->ia_valid & ATTR_SIZE) {
+ /* If we are changing file size, file content is
+ * modified, flag it. */
+ attr->ia_valid |= MDS_OPEN_OWNEROVERRIDE;
+ op_data->op_bias |= MDS_DATA_MODIFIED;
}
- memcpy(&op_data->op_attr, attr, sizeof(*attr));
-
rc = ll_md_setattr(dentry, op_data);
if (rc)
GOTO(out, rc);
- if (!S_ISREG(inode->i_mode) || file_is_released)
+ if (!S_ISREG(inode->i_mode) || hsm_import)
GOTO(out, rc = 0);
if (attr->ia_valid & (ATTR_SIZE |
* time de-synchronization between MDT inode and OST objects */
rc = cl_setattr_ost(lli->lli_clob, attr, 0);
}
+
+ /* If the file was restored, it needs to set dirty flag.
+ *
+ * We've already sent MDS_DATA_MODIFIED flag in
+ * ll_md_setattr() for truncate. However, the MDT refuses to
+ * set the HS_DIRTY flag on released files, so we have to set
+ * it again if the file has been restored. Please check how
+ * LLIF_DATA_MODIFIED is set in vvp_io_setattr_fini().
+ *
+ * Please notice that if the file is not released, the previous
+ * MDS_DATA_MODIFIED has taken effect and usually
+ * LLIF_DATA_MODIFIED is not set(see vvp_io_setattr_fini()).
+ * This way we can save an RPC for common open + trunc
+ * operation. */
+ if (ll_file_test_and_clear_flag(lli, LLIF_DATA_MODIFIED)) {
+ struct hsm_state_set hss = {
+ .hss_valid = HSS_SETMASK,
+ .hss_setmask = HS_DIRTY,
+ };
+ int rc2;
+
+ rc2 = ll_hsm_state_set(inode, &hss);
+ if (rc2 < 0)
+ CERROR(DFID "HSM set dirty failed: rc2 = %d\n",
+ PFID(ll_inode2fid(inode)), rc2);
+ }
+
EXIT;
out:
if (op_data != NULL)
ll_finish_md_op_data(op_data);
- if (!S_ISDIR(inode->i_mode)) {
+ if (S_ISREG(inode->i_mode)) {
mutex_lock(&inode->i_mutex);
if ((attr->ia_valid & ATTR_SIZE) && !hsm_import)
inode_dio_wait(inode);