Whamcloud - gitweb
LU-3432 llite: Access to released file trigs a restore
[fs/lustre-release.git] / lustre / llite / llite_lib.c
index ea33cda..c549b78 100644 (file)
@@ -1389,6 +1389,7 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr)
         struct ll_inode_info *lli = ll_i2info(inode);
         struct md_op_data *op_data = NULL;
         struct md_open_data *mod = NULL;
+       bool file_is_released = false;
         int rc = 0, rc1 = 0;
         ENTRY;
 
@@ -1473,10 +1474,40 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr)
             (attr->ia_valid & (ATTR_SIZE | ATTR_MTIME | ATTR_MTIME_SET)))
                 op_data->op_flags = MF_EPOCH_OPEN;
 
+       /* 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 lov_stripe_md *lsm;
+               __u32 gen;
+
+               ll_layout_refresh(inode, &gen);
+               lsm = ccc_inode_lsm_get(inode);
+               if (lsm && lsm->lsm_pattern & LOV_PATTERN_F_RELEASED)
+                       file_is_released = true;
+               ccc_inode_lsm_put(inode, lsm);
+       }
+
+       /* clear size attr for released file
+        * we clear the attribute send to MDT in op_data, not the original
+        * received from caller in attr which is used later to
+        * decide return code */
+       if (file_is_released && (attr->ia_valid & ATTR_SIZE))
+               op_data->op_attr.ia_valid &= ~ATTR_SIZE;
+
         rc = ll_md_setattr(dentry, op_data, &mod);
         if (rc)
                 GOTO(out, rc);
 
+       /* truncate failed, others succeed */
+       if (file_is_released) {
+               if (attr->ia_valid & ATTR_SIZE)
+                       GOTO(out, rc = -ENODATA);
+               else
+                       GOTO(out, rc = 0);
+       }
+
        /* RPC to MDT is sent, cancel data modification flag */
        if (rc == 0 && (op_data->op_bias & MDS_DATA_MODIFIED)) {
                spin_lock(&lli->lli_lock);
@@ -1490,7 +1521,7 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr)
 
        if (attr->ia_valid & (ATTR_SIZE |
                              ATTR_ATIME | ATTR_ATIME_SET |
-                             ATTR_MTIME | ATTR_MTIME_SET))
+                             ATTR_MTIME | ATTR_MTIME_SET)) {
                 /* For truncate and utimes sending attributes to OSTs, setting
                  * mtime/atime to the past will be performed under PW [0:EOF]
                  * extent lock (new_size:EOF for truncate).  It may seem
@@ -1498,6 +1529,7 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr)
                  * setting times to past, but it is necessary due to possible
                  * time de-synchronization between MDT inode and OST objects */
                 rc = ll_setattr_ost(inode, attr);
+       }
         EXIT;
 out:
         if (op_data) {
@@ -1800,6 +1832,11 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md)
                 LASSERT(md->oss_capa);
                 ll_add_capa(inode, md->oss_capa);
         }
+
+       if (body->valid & OBD_MD_TSTATE) {
+               if (body->t_state & MS_RESTORE)
+                       lli->lli_flags |= LLIF_FILE_RESTORING;
+       }
 }
 
 void ll_read_inode2(struct inode *inode, void *opaque)