Whamcloud - gitweb
LU-1069 mdc: Avoid doing permission check again.
[fs/lustre-release.git] / lustre / llite / llite_lib.c
index 4e49985..815cf6c 100644 (file)
@@ -1200,7 +1200,7 @@ int ll_md_setattr(struct dentry *dentry, struct md_op_data *op_data,
         struct inode *inode = dentry->d_inode;
         struct ll_sb_info *sbi = ll_i2sbi(inode);
         struct ptlrpc_request *request = NULL;
         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,
         ENTRY;
 
         op_data = ll_prep_md_op_data(op_data, inode, NULL, NULL, 0, 0,
@@ -1217,8 +1217,12 @@ int ll_md_setattr(struct dentry *dentry, struct md_op_data *op_data,
                         /* Unlinked special device node? Or just a race?
                          * Pretend we done everything. */
                         if (!S_ISREG(inode->i_mode) &&
                         /* 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);
                                 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);
                 }
                 } else if (rc != -EPERM && rc != -EACCES && rc != -ETXTBSY) {
                         CERROR("md_setattr fails: rc = %d\n", rc);
                 }
@@ -1232,12 +1236,16 @@ int ll_md_setattr(struct dentry *dentry, struct md_op_data *op_data,
                 RETURN(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
          * 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) */
          * (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);
         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;
 
         /* Extract epoch data if obtained. */
         op_data->op_handle = md.body->handle;
@@ -1340,7 +1348,7 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr)
         }
 
         /* POSIX: check before ATTR_*TIME_SET set (from inode_change_ok) */
         }
 
         /* 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 (cfs_curproc_fsuid() != inode->i_uid &&
                     !cfs_capable(CFS_CAP_FOWNER))
                         RETURN(-EPERM);
@@ -1377,14 +1385,15 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr)
         if (op_data == NULL)
                 RETURN(-ENOMEM);
 
         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);
                 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));
 
 
         memcpy(&op_data->op_attr, attr, sizeof(*attr));