Whamcloud - gitweb
LU-7268 scrub: NOT assign LMA for EA inode
[fs/lustre-release.git] / lustre / osd-ldiskfs / osd_scrub.c
index 435c0fc..ff639e2 100644 (file)
@@ -20,7 +20,7 @@
  * GPL HEADER END
  */
 /*
- * Copyright (c) 2012, 2014, Intel Corporation.
+ * Copyright (c) 2012, 2015, Intel Corporation.
  */
 /*
  * lustre/osd-ldiskfs/osd_scrub.c
@@ -37,6 +37,7 @@
 
 #define DEBUG_SUBSYSTEM S_LFSCK
 
+#include <linux/kthread.h>
 #include <lustre/lustre_idl.h>
 #include <lustre_disk.h>
 #include <dt_object.h>
@@ -180,7 +181,8 @@ static int osd_scrub_refresh_mapping(struct osd_thread_info *info,
        if (rc < 0)
                CDEBUG(D_LFSCK, "%s: fail to refresh OI map for scrub op %d "
                       DFID" => %u/%u: rc = %d\n", osd_name(dev), ops,
-                      PFID(fid), id->oii_ino, id->oii_gen, rc);
+                      PFID(fid), id ? id->oii_ino : -1, id ? id->oii_gen : -1,
+                      rc);
 
        RETURN(rc);
 }
@@ -495,6 +497,10 @@ osd_scrub_check_update(struct osd_thread_info *info, struct osd_device *dev,
                        GOTO(out, rc);
                }
 
+               /* The inode has been reused as EA inode, ignore it. */
+               if (unlikely(osd_is_ea_inode(inode)))
+                       GOTO(out, rc = 0);
+
                sf->sf_flags |= SF_UPGRADE;
                sf->sf_internal_flags &= ~SIF_NO_HANDLE_OLD_FID;
                dev->od_check_ff = 1;
@@ -534,6 +540,10 @@ iget:
                                        rc = 0;
                                GOTO(out, rc);
                        }
+
+                       /* The inode has been reused as EA inode, ignore it. */
+                       if (unlikely(osd_is_ea_inode(inode)))
+                               GOTO(out, rc = 0);
                }
 
                if (!scrub->os_partial_scan)
@@ -613,7 +623,8 @@ out:
        /* There may be conflict unlink during the OI scrub,
         * if happend, then remove the new added OI mapping. */
        if (ops == DTO_INDEX_INSERT && inode != NULL && !IS_ERR(inode) &&
-           unlikely(inode->i_nlink == 0))
+           unlikely(ldiskfs_test_inode_state(inode,
+                                             LDISKFS_STATE_LUSTRE_DESTROY)))
                osd_scrub_refresh_mapping(info, dev, fid, lid,
                                DTO_INDEX_DELETE, false,
                                (val == SCRUB_NEXT_OSTOBJ ||
@@ -625,13 +636,11 @@ out:
                iput(inode);
 
        if (oii != NULL) {
-               LASSERT(!list_empty(&oii->oii_list));
+               LASSERT(list_empty(&oii->oii_list));
 
-               spin_lock(&scrub->os_lock);
-               list_del_init(&oii->oii_list);
-               spin_unlock(&scrub->os_lock);
                OBD_FREE_PTR(oii);
        }
+
        RETURN(sf->sf_param & SP_FAILOUT ? rc : 0);
 }
 
@@ -739,9 +748,10 @@ static int osd_scrub_checkpoint(struct osd_scrub *scrub)
        return rc;
 }
 
-static void osd_scrub_post(struct osd_scrub *scrub, int result)
+static int osd_scrub_post(struct osd_scrub *scrub, int result)
 {
        struct scrub_file *sf = &scrub->os_file;
+       int rc;
        ENTRY;
 
        CDEBUG(D_LFSCK, "%.16s: OI scrub post, result = %d\n",
@@ -781,10 +791,10 @@ static void osd_scrub_post(struct osd_scrub *scrub, int result)
        }
        sf->sf_run_time += cfs_duration_sec(cfs_time_current() + HALF_SEC -
                                            scrub->os_time_last_checkpoint);
-       result = osd_scrub_file_store(scrub);
+       rc = osd_scrub_file_store(scrub);
        up_write(&scrub->os_rwsem);
 
-       EXIT;
+       RETURN(rc < 0 ? rc : result);
 }
 
 /* iteration engine */
@@ -956,6 +966,10 @@ static int osd_iit_iget(struct osd_thread_info *info, struct osd_device *dev,
                RETURN(rc);
        }
 
+       /* It is an EA inode, no OI mapping for it, skip it. */
+       if (osd_is_ea_inode(inode))
+               GOTO(put, rc = SCRUB_NEXT_CONTINUE);
+
        if (scrub &&
            ldiskfs_test_inode_state(inode, LDISKFS_STATE_LUSTRE_NOSCRUB)) {
                /* Only skip it for the first OI scrub accessing. */
@@ -1007,13 +1021,21 @@ static int osd_scrub_next(struct osd_thread_info *info, struct osd_device *dev,
                return SCRUB_NEXT_EXIT;
 
        if (!list_empty(&scrub->os_inconsistent_items)) {
-               struct osd_inconsistent_item *oii;
+               spin_lock(&scrub->os_lock);
+               if (likely(!list_empty(&scrub->os_inconsistent_items))) {
+                       struct osd_inconsistent_item *oii;
 
-               oii = list_entry(scrub->os_inconsistent_items.next,
-                                struct osd_inconsistent_item, oii_list);
-               *oic = &oii->oii_cache;
-               scrub->os_in_prior = 1;
-               return 0;
+                       oii = list_entry(scrub->os_inconsistent_items.next,
+                               struct osd_inconsistent_item, oii_list);
+                       list_del_init(&oii->oii_list);
+                       spin_unlock(&scrub->os_lock);
+
+                       *oic = &oii->oii_cache;
+                       scrub->os_in_prior = 1;
+
+                       return 0;
+               }
+               spin_unlock(&scrub->os_lock);
        }
 
        if (noslot)
@@ -1100,8 +1122,10 @@ static int osd_scrub_exec(struct osd_thread_info *info, struct osd_device *dev,
        }
 
        rc = osd_scrub_check_update(info, dev, oic, rc);
-       if (rc != 0)
+       if (rc != 0) {
+               scrub->os_in_prior = 0;
                return rc;
+       }
 
        rc = osd_scrub_checkpoint(scrub);
        if (rc != 0) {
@@ -1491,7 +1515,7 @@ static int osd_scrub_main(void *args)
        GOTO(post, rc);
 
 post:
-       osd_scrub_post(scrub, rc);
+       rc = osd_scrub_post(scrub, rc);
        CDEBUG(D_LFSCK, "%.16s: OI scrub: stop, pos = %u: rc = %d\n",
               osd_scrub2name(scrub), scrub->os_pos_current, rc);
 
@@ -1525,6 +1549,8 @@ static int osd_ios_lf_fill(void *buf, const char *name, int namelen,
                           loff_t offset, __u64 ino, unsigned d_type);
 static int osd_ios_dl_fill(void *buf, const char *name, int namelen,
                           loff_t offset, __u64 ino, unsigned d_type);
+static int osd_ios_uld_fill(void *buf, const char *name, int namelen,
+                           loff_t offset, __u64 ino, unsigned d_type);
 
 static int
 osd_ios_general_scan(struct osd_thread_info *info, struct osd_device *dev,
@@ -1542,6 +1568,7 @@ enum osd_lf_flags {
        OLF_HIDE_FID            = 0x0002,
        OLF_SHOW_NAME           = 0x0004,
        OLF_NO_OI               = 0x0008,
+       OLF_IDX_IN_FID          = 0x0010,
 };
 
 struct osd_lf_map {
@@ -1593,6 +1620,10 @@ static const struct osd_lf_map osd_lf_maps[] = {
        { LAST_RCVD, { FID_SEQ_LOCAL_FILE, LAST_RECV_OID, 0 }, OLF_SHOW_NAME,
                sizeof(LAST_RCVD) - 1, NULL, NULL },
 
+       /* reply_data */
+       { REPLY_DATA, { FID_SEQ_LOCAL_FILE, REPLY_DATA_OID, 0 }, OLF_SHOW_NAME,
+               sizeof(REPLY_DATA) - 1, NULL, NULL },
+
        /* lov_objid */
        { LOV_OBJID, { FID_SEQ_LOCAL_FILE, MDD_LOV_OBJ_OID, 0 }, OLF_SHOW_NAME,
                sizeof(LOV_OBJID) - 1, NULL, NULL },
@@ -1653,9 +1684,24 @@ static const struct osd_lf_map osd_lf_maps[] = {
        { "LAST_GROUP", { FID_SEQ_LOCAL_FILE, OFD_LAST_GROUP_OID, 0 },
                OLF_SHOW_NAME, sizeof("LAST_GROUP") - 1, NULL, NULL },
 
-       /* SLAVE_LOG, llog for destroy slave stripes of striped dir */
-       { "SLAVE_LOG", { FID_SEQ_LOCAL_FILE, SLAVE_LLOG_CATALOGS_OID, 0 },
-              OLF_SHOW_NAME, sizeof("SLAVE_LOG") - 1, NULL, NULL },
+       /* committed batchid for cross-MDT operation */
+       { "BATCHID", { FID_SEQ_LOCAL_FILE, BATCHID_COMMITTED_OID, 0 },
+               OLF_SHOW_NAME, sizeof("BATCHID") - 1, NULL, NULL },
+
+       /* OSP update logs update_log{_dir} use f_seq = FID_SEQ_UPDATE_LOG{_DIR}
+        * and f_oid = index for their log files.  See lu_update_log{_dir}_fid()
+        * for more details. */
+
+       /* update_log */
+       { "update_log", { FID_SEQ_UPDATE_LOG, 0, 0 },
+               OLF_SHOW_NAME | OLF_IDX_IN_FID, sizeof("update_log") - 1,
+               NULL, NULL },
+
+       /* update_log_dir */
+       { "update_log_dir", { FID_SEQ_UPDATE_LOG_DIR, 0, 0 },
+               OLF_SHOW_NAME | OLF_SCAN_SUBITEMS | OLF_IDX_IN_FID,
+               sizeof("update_log_dir") - 1,
+               osd_ios_general_scan, osd_ios_uld_fill },
 
        /* lost+found */
        { "lost+found", { FID_SEQ_LOCAL_FILE, OSD_LPF_OID, 0 },
@@ -1701,7 +1747,19 @@ osd_ios_lookup_one_len(const char *name, struct dentry *parent, int namelen)
        struct dentry *dentry;
 
        dentry = ll_lookup_one_len(name, parent, namelen);
-       if (!IS_ERR(dentry) && dentry->d_inode == NULL) {
+       if (IS_ERR(dentry)) {
+               int rc = PTR_ERR(dentry);
+
+               if (rc != -ENOENT)
+                       CERROR("Fail to find %.*s in %.*s (%lu/%u): rc = %d\n",
+                              namelen, name, parent->d_name.len,
+                              parent->d_name.name, parent->d_inode->i_ino,
+                              parent->d_inode->i_generation, rc);
+
+               return dentry;
+       }
+
+       if (dentry->d_inode == NULL) {
                dput(dentry);
                return ERR_PTR(-ENOENT);
        }
@@ -1759,10 +1817,16 @@ osd_ios_scan_one(struct osd_thread_info *info, struct osd_device *dev,
 
        osd_id_gen(id, inode->i_ino, inode->i_generation);
        if (rc == -ENODATA) {
-               if (fid == NULL || fid_is_zero(fid) || flags & OLF_HIDE_FID)
+               if (fid == NULL || fid_is_zero(fid) || flags & OLF_HIDE_FID) {
                        lu_igif_build(&tfid, inode->i_ino, inode->i_generation);
-               else
+               } else {
                        tfid = *fid;
+                       if (flags & OLF_IDX_IN_FID) {
+                               LASSERT(dev->od_index >= 0);
+
+                               tfid.f_oid = dev->od_index;
+                       }
+               }
                rc = osd_ea_fid_set(info, inode, &tfid, 0, 0);
                if (rc != 0) {
                        CDEBUG(D_LFSCK, "%s: fail to set LMA for init OI "
@@ -1945,6 +2009,35 @@ static int osd_ios_dl_fill(void *buf, const char *name, int namelen,
        RETURN(rc);
 }
 
+static int osd_ios_uld_fill(void *buf, const char *name, int namelen,
+                           loff_t offset, __u64 ino, unsigned d_type)
+{
+       struct osd_ios_filldir_buf *fill_buf = buf;
+       struct dentry              *child;
+       struct lu_fid               tfid;
+       int                         rc       = 0;
+       ENTRY;
+
+       /* skip any non-DFID format name */
+       if (name[0] != '[')
+               RETURN(0);
+
+       child = osd_ios_lookup_one_len(name, fill_buf->oifb_dentry, namelen);
+       if (IS_ERR(child))
+               RETURN(PTR_ERR(child));
+
+       /* skip the start '[' */
+       sscanf(&name[1], SFID, RFID(&tfid));
+       if (fid_is_sane(&tfid))
+               rc = osd_ios_scan_one(fill_buf->oifb_info, fill_buf->oifb_dev,
+                                     child->d_inode, &tfid, 0);
+       else
+               rc = -EIO;
+       dput(child);
+
+       RETURN(rc);
+}
+
 static int osd_ios_root_fill(void *buf, const char *name, int namelen,
                             loff_t offset, __u64 ino, unsigned d_type)
 {
@@ -2005,7 +2098,7 @@ osd_ios_general_scan(struct osd_thread_info *info, struct osd_device *dev,
        LASSERT(filldir != NULL);
 
        filp->f_pos = 0;
-       filp->f_dentry = dentry;
+       filp->f_path.dentry = dentry;
        filp->f_mode = FMODE_64BITHASH;
        filp->f_mapping = inode->i_mapping;
        filp->f_op = fops;
@@ -2382,7 +2475,7 @@ int osd_scrub_setup(const struct lu_env *env, struct osd_device *dev)
                RETURN(PTR_ERR(filp));
        }
 
-       inode = filp->f_dentry->d_inode;
+       inode = filp->f_path.dentry->d_inode;
        /* 'What the @fid is' is not imporatant, because the object
         * has no OI mapping, and only is visible inside the OSD.*/
        lu_igif_build(fid, inode->i_ino, inode->i_generation);
@@ -2419,8 +2512,29 @@ int osd_scrub_setup(const struct lu_env *env, struct osd_device *dev)
                GOTO(cleanup_inode, rc);
        } else {
                if (memcmp(sf->sf_uuid, es->s_uuid, 16) != 0) {
+                       struct obd_uuid *old_uuid;
+                       struct obd_uuid *new_uuid;
+
+                       OBD_ALLOC_PTR(old_uuid);
+                       OBD_ALLOC_PTR(new_uuid);
+                       if (old_uuid == NULL || new_uuid == NULL) {
+                               CERROR("%.16s: UUID has been changed, but"
+                                      "failed to allocate RAM for report\n",
+                                      LDISKFS_SB(sb)->s_es->s_volume_name);
+                       } else {
+                               class_uuid_unparse(sf->sf_uuid, old_uuid);
+                               class_uuid_unparse(es->s_uuid, new_uuid);
+                               CERROR("%.16s: UUID has been changed from "
+                                      "%s to %s\n",
+                                      LDISKFS_SB(sb)->s_es->s_volume_name,
+                                      old_uuid->uuid, new_uuid->uuid);
+                       }
                        osd_scrub_file_reset(scrub, es->s_uuid,SF_INCONSISTENT);
                        dirty = 1;
+                       if (old_uuid != NULL)
+                               OBD_FREE_PTR(old_uuid);
+                       if (new_uuid != NULL)
+                               OBD_FREE_PTR(new_uuid);
                } else if (sf->sf_status == SS_SCANNING) {
                        sf->sf_status = SS_CRASHED;
                        dirty = 1;
@@ -3009,7 +3123,7 @@ int osd_scrub_dump(struct seq_file *m, struct osd_device *dev)
                              "real-time_speed: "LPU64" objects/sec\n"
                              "current_position: %u\n"
                              "lf_scanned: "LPU64"\n"
-                             "lf_reparied: "LPU64"\n"
+                             "lf_repaired: "LPU64"\n"
                              "lf_failed: "LPU64"\n",
                              rtime, speed, new_checked, scrub->os_pos_current,
                              scrub->os_lf_scanned, scrub->os_lf_repaired,
@@ -3022,7 +3136,7 @@ int osd_scrub_dump(struct seq_file *m, struct osd_device *dev)
                              "real-time_speed: N/A\n"
                              "current_position: N/A\n"
                              "lf_scanned: "LPU64"\n"
-                             "lf_reparied: "LPU64"\n"
+                             "lf_repaired: "LPU64"\n"
                              "lf_failed: "LPU64"\n",
                              sf->sf_run_time, speed, scrub->os_lf_scanned,
                              scrub->os_lf_repaired, scrub->os_lf_failed);