struct inode *inode = dentry->d_inode;
struct ll_sb_info *sbi = ll_i2sbi(inode);
struct ptlrpc_request *request = NULL;
- int rc;
+ int rc, ia_valid;
ENTRY;
op_data = ll_prep_md_op_data(op_data, inode, NULL, NULL, 0, 0,
/* Unlinked special device node? Or just a race?
* Pretend we done everything. */
if (!S_ISREG(inode->i_mode) &&
- !S_ISDIR(inode->i_mode))
+ !S_ISDIR(inode->i_mode)) {
+ ia_valid = op_data->op_attr.ia_valid;
+ op_data->op_attr.ia_valid &= ~TIMES_SET_FLAGS;
rc = simple_setattr(dentry, &op_data->op_attr);
+ op_data->op_attr.ia_valid = ia_valid;
+ }
} else if (rc != -EPERM && rc != -EACCES && rc != -ETXTBSY) {
CERROR("md_setattr fails: rc = %d\n", rc);
}
RETURN(rc);
}
- /* We call inode_setattr to adjust timestamps.
+ /* We want to adjust timestamps.
* If there is at least some data in file, we cleared ATTR_SIZE
- * above to avoid invoking vmtruncate, otherwise it is important
- * to call vmtruncate in inode_setattr to update inode->i_size
+ * to avoid update size, otherwise it is important to do.(SOM case)
* (bug 6196) */
+ ia_valid = op_data->op_attr.ia_valid;
+ /* Since we set ATTR_*_SET flags above, and already done permission
+ * check, So don't let inode_change_ok() check it again. */
+ op_data->op_attr.ia_valid &= ~TIMES_SET_FLAGS;
rc = simple_setattr(dentry, &op_data->op_attr);
+ op_data->op_attr.ia_valid = ia_valid;
/* Extract epoch data if obtained. */
op_data->op_handle = md.body->handle;
}
/* POSIX: check before ATTR_*TIME_SET set (from inode_change_ok) */
- if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET)) {
+ if (ia_valid & TIMES_SET_FLAGS) {
if (cfs_curproc_fsuid() != inode->i_uid &&
!cfs_capable(CFS_CAP_FOWNER))
RETURN(-EPERM);
if (op_data == NULL)
RETURN(-ENOMEM);
- UNLOCK_INODE_MUTEX(inode);
- if (ia_valid & ATTR_SIZE)
- UP_WRITE_I_ALLOC_SEM(inode);
- if (!S_ISDIR(inode->i_mode))
+ if (!S_ISDIR(inode->i_mode)) {
+ if (ia_valid & ATTR_SIZE)
+ UP_WRITE_I_ALLOC_SEM(inode);
+ UNLOCK_INODE_MUTEX(inode);
cfs_down_write(&lli->lli_trunc_sem);
- LOCK_INODE_MUTEX(inode);
- if (ia_valid & ATTR_SIZE)
- DOWN_WRITE_I_ALLOC_SEM(inode);
+ LOCK_INODE_MUTEX(inode);
+ if (ia_valid & ATTR_SIZE)
+ DOWN_WRITE_I_ALLOC_SEM(inode);
+ }
memcpy(&op_data->op_attr, attr, sizeof(*attr));
/* We set these flags on the client, but have already checked perms
* so don't confuse inode_change_ok. */
- iattr->ia_valid &= ~(ATTR_MTIME_SET | ATTR_ATIME_SET);
+ iattr->ia_valid &= ~TIMES_SET_FLAGS;
if (inode->i_op->setattr) {
rc = inode->i_op->setattr(dentry, iattr);
} else {
+#ifndef HAVE_SIMPLE_SETATTR /* simple_setattr() already call it */
rc = inode_change_ok(inode, iattr);
if (!rc)
+#endif
rc = simple_setattr(dentry, iattr);
}