Whamcloud - gitweb
LU-6214 llite: tar restore fails for HSM released files.
[fs/lustre-release.git] / lustre / llite / xattr.c
index 8a365b4..89bda2a 100644 (file)
@@ -144,9 +144,12 @@ int ll_setxattr_common(struct inode *inode, const char *name,
                return -EPERM;
 
         /* b10667: ignore lustre special xattr for now */
-        if ((xattr_type == XATTR_TRUSTED_T && strcmp(name, "trusted.lov") == 0) ||
-            (xattr_type == XATTR_LUSTRE_T && strcmp(name, "lustre.lov") == 0))
-                RETURN(0);
+       if (strcmp(name, XATTR_NAME_HSM) == 0 ||
+               (xattr_type == XATTR_TRUSTED_T &&
+               strcmp(name, XATTR_NAME_LOV) == 0) ||
+               (xattr_type == XATTR_LUSTRE_T &&
+                strcmp(name, "lustre.lov") == 0))
+               RETURN(0);
 
         /* b15587: ignore security.capability xattr for now */
         if ((xattr_type == XATTR_SECURITY_T &&
@@ -225,6 +228,37 @@ int ll_setxattr_common(struct inode *inode, const char *name,
         RETURN(0);
 }
 
+static int get_hsm_state(struct inode *inode, __u32 *hus_states)
+{
+       struct md_op_data *op_data;
+       struct hsm_user_state *hus;
+       int rc;
+
+       OBD_ALLOC_PTR(hus);
+       if (hus == NULL)
+               return -ENOMEM;
+
+       op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0,
+                                    LUSTRE_OPC_ANY, hus);
+       if (!IS_ERR(op_data)) {
+               rc = obd_iocontrol(LL_IOC_HSM_STATE_GET, ll_i2mdexp(inode),
+                                  sizeof(*op_data), op_data, NULL);
+               if (rc == 0)
+                       *hus_states = hus->hus_states;
+               else
+                       CDEBUG(D_VFSTRACE, "obd_iocontrol failed. rc = %d\n",
+                              rc);
+
+               ll_finish_md_op_data(op_data);
+       } else {
+               rc = PTR_ERR(op_data);
+               CDEBUG(D_VFSTRACE, "Could not prepare the opdata. rc = %d\n",
+                      rc);
+       }
+       OBD_FREE_PTR(hus);
+       return rc;
+}
+
 int ll_setxattr(struct dentry *dentry, const char *name,
                 const void *value, size_t size, int flags)
 {
@@ -238,20 +272,40 @@ int ll_setxattr(struct dentry *dentry, const char *name,
 
         ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_SETXATTR, 1);
 
-        if ((strncmp(name, XATTR_TRUSTED_PREFIX,
-                     sizeof(XATTR_TRUSTED_PREFIX) - 1) == 0 &&
-             strcmp(name + sizeof(XATTR_TRUSTED_PREFIX) - 1, "lov") == 0) ||
-            (strncmp(name, XATTR_LUSTRE_PREFIX,
-                     sizeof(XATTR_LUSTRE_PREFIX) - 1) == 0 &&
-             strcmp(name + sizeof(XATTR_LUSTRE_PREFIX) - 1, "lov") == 0)) {
+       if ((strncmp(name, XATTR_TRUSTED_PREFIX,
+                    sizeof(XATTR_TRUSTED_PREFIX) - 1) == 0 &&
+            strcmp(name + sizeof(XATTR_TRUSTED_PREFIX) - 1, "lov") == 0) ||
+           (strncmp(name, XATTR_LUSTRE_PREFIX,
+                    sizeof(XATTR_LUSTRE_PREFIX) - 1) == 0 &&
+            strcmp(name + sizeof(XATTR_LUSTRE_PREFIX) - 1, "lov") == 0)) {
                struct lov_user_md *lump = (struct lov_user_md *)value;
-               int                 rc = 0;
-
-                /* Attributes that are saved via getxattr will always have
-                 * the stripe_offset as 0.  Instead, the MDS should be
-                 * allowed to pick the starting OST index.   b=17846 */
-                if (lump != NULL && lump->lmm_stripe_offset == 0)
-                        lump->lmm_stripe_offset = -1;
+               int rc = 0;
+
+               /* Attributes that are saved via getxattr will always have
+                * the stripe_offset as 0.  Instead, the MDS should be
+                * allowed to pick the starting OST index.   b=17846 */
+               if (lump != NULL && lump->lmm_stripe_offset == 0)
+                       lump->lmm_stripe_offset = -1;
+               /* Avoid anyone directly setting the RELEASED flag. */
+               if (lump != NULL &&
+                       (lump->lmm_pattern & LOV_PATTERN_F_RELEASED)) {
+                       /* Only if we have a released flag check if the file
+                       * was indeed archived. */
+                       __u32 state = HS_NONE;
+                       rc = get_hsm_state(inode, &state);
+                       if (rc != 0)
+                               RETURN(rc);
+                       if (!(state & HS_ARCHIVED)) {
+                               CDEBUG(D_VFSTRACE,
+                                       "hus_states state = %x, pattern = %x\n",
+                                       state, lump->lmm_pattern);
+                               /* Here the state is: real file is not
+                                * archived but user is requesting to set
+                                * the RELEASED flag so we mask off the
+                                * released flag from the request */
+                               lump->lmm_pattern ^= LOV_PATTERN_F_RELEASED;
+                       }
+               }
 
                if (lump != NULL && S_ISREG(inode->i_mode)) {
                        struct file     f;