Whamcloud - gitweb
LU-6109 lfsck: check FID validity before locating object
[fs/lustre-release.git] / lustre / osd-ldiskfs / osd_handler.c
index dddbba3..58a1e1a 100644 (file)
@@ -495,15 +495,14 @@ static int osd_check_lma(const struct lu_env *env, struct osd_object *obj)
        if (rc == -ENODATA && !fid_is_igif(rfid) && osd->od_check_ff) {
                fid = &lma->lma_self_fid;
                rc = osd_get_idif(info, inode, dentry, fid);
-               if ((rc > 0) || (rc == -ENODATA && osd->od_lma_self_repair)) {
+               if ((rc > 0) || (rc == -ENODATA && osd->od_index_in_idif)) {
                        /* For the given OST-object, if it has neither LMA nor
                         * FID in XATTR_NAME_FID, then the given FID (which is
                         * contained in the @obj, from client RPC for locating
                         * the OST-object) is trusted. We use it to generate
                         * the LMA. */
                        osd_lma_self_repair(info, osd, inode, rfid,
-                               fid_is_on_ost(info, osd, fid, OI_CHECK_FLD) ?
-                               LMAC_FID_ON_OST : 0);
+                                           LMAC_FID_ON_OST);
                        RETURN(0);
                }
        }
@@ -546,7 +545,7 @@ static int osd_check_lma(const struct lu_env *env, struct osd_object *obj)
                                fid_to_ostid(fid, oi);
                                ostid_to_fid(fid1, oi, idx);
                                if (lu_fid_eq(fid1, rfid)) {
-                                       if (osd->od_lma_self_repair)
+                                       if (osd->od_index_in_idif)
                                                osd_lma_self_repair(info, osd,
                                                        inode, rfid,
                                                        LMAC_FID_ON_OST);
@@ -2093,14 +2092,13 @@ static int osd_mkfile(struct osd_thread_info *info, struct osd_object *obj,
                                               osd_sb(osd)->s_root->d_inode,
                                      mode);
         if (!IS_ERR(inode)) {
-                /* Do not update file c/mtime in ldiskfs.
-                 * NB: don't need any lock because no contention at this
-                 * early stage */
-                inode->i_flags |= S_NOCMTIME;
+               /* Do not update file c/mtime in ldiskfs. */
+               inode->i_flags |= S_NOCMTIME;
 
                /* For new created object, it must be consistent,
                 * and it is unnecessary to scrub against it. */
                ldiskfs_set_inode_state(inode, LDISKFS_STATE_LUSTRE_NOSCRUB);
+
                 obj->oo_inode = inode;
                 result = 0;
         } else {
@@ -2327,13 +2325,16 @@ static int __osd_object_create(struct osd_thread_info *info,
 
        result = osd_create_type_f(dof->dof_type)(info, obj, attr, hint, dof,
                                                  th);
-        if (result == 0) {
+       if (result == 0) {
                osd_attr_init(info, obj, attr, dof);
                osd_object_init0(obj);
-               /* bz 24037 */
-               if (obj->oo_inode && (obj->oo_inode->i_state & I_NEW))
-                       unlock_new_inode(obj->oo_inode);
-        }
+       }
+
+       if (obj->oo_inode != NULL) {
+               LASSERT(obj->oo_inode->i_state & I_NEW);
+
+               unlock_new_inode(obj->oo_inode);
+       }
 
        /* restore previous umask value */
        current->fs->umask = umask;
@@ -2705,6 +2706,9 @@ static struct inode *osd_create_local_agent_inode(const struct lu_env *env,
                RETURN(local);
        }
 
+       ldiskfs_set_inode_state(local, LDISKFS_STATE_LUSTRE_NOSCRUB);
+       unlock_new_inode(local);
+
        /* Set special LMA flag for local agent inode */
        rc = osd_ea_fid_set(info, local, fid, 0, LMAI_AGENT);
        if (rc != 0) {
@@ -2796,11 +2800,23 @@ static int osd_object_ea_create(const struct lu_env *env, struct dt_object *dt,
        osd_trans_declare_rb(env, th, OSD_OT_REF_ADD);
 
        result = __osd_object_create(info, obj, attr, hint, dof, th);
-       if (result == 0)
-               result = osd_ea_fid_set(info, obj->oo_inode, fid,
+       if (result == 0) {
+               if (fid_is_idif(fid) &&
+                   !osd_dev(dt->do_lu.lo_dev)->od_index_in_idif) {
+                       struct lu_fid *tfid = &info->oti_fid;
+                       struct ost_id *oi   = &info->oti_ostid;
+
+                       fid_to_ostid(fid, oi);
+                       ostid_to_fid(tfid, oi, 0);
+                       result = osd_ea_fid_set(info, obj->oo_inode, tfid,
+                                               LMAC_FID_ON_OST, 0);
+               } else {
+                       result = osd_ea_fid_set(info, obj->oo_inode, fid,
                                fid_is_on_ost(info, osd_obj2dev(obj),
                                              fid, OI_CHECK_FLD) ?
                                LMAC_FID_ON_OST : 0, 0);
+               }
+       }
 
        if (result == 0)
                result = __osd_oi_insert(env, obj, fid, th);
@@ -4390,13 +4406,19 @@ static int osd_ea_lookup_rec(const struct lu_env *env, struct osd_object *obj,
                /* done with de, release bh */
                brelse(bh);
                if (rc != 0) {
-                       if (unlikely(ino == osd_remote_parent_ino(dev)))
+                       if (unlikely(ino == osd_remote_parent_ino(dev))) {
+                               const char *name = (const char *)key;
+
                                /* If the parent is on remote MDT, and there
                                 * is no FID-in-dirent, then we have to get
                                 * the parent FID from the linkEA.  */
-                               rc = osd_get_pfid_from_linkea(env, obj, fid);
-                       else
+                               if (likely(strlen(name) == 2 &&
+                                          name[0] == '.' && name[1] == '.'))
+                                       rc = osd_get_pfid_from_linkea(env, obj,
+                                                                     fid);
+                       } else {
                                rc = osd_ea_fid_get(env, obj, ino, fid, id);
+                       }
                } else {
                        osd_id_gen(id, ino, OSD_OII_NOGEN);
                }
@@ -5640,7 +5662,11 @@ static inline int osd_it_ea_rec(const struct lu_env *env,
                        /* If the parent is on remote MDT, and there
                         * is no FID-in-dirent, then we have to get
                         * the parent FID from the linkEA.  */
-                       osd_get_pfid_from_linkea(env, obj, fid);
+                       if (!fid_is_sane(fid) &&
+                           it->oie_dirent->oied_namelen == 2 &&
+                           it->oie_dirent->oied_name[0] == '.' &&
+                           it->oie_dirent->oied_name[1] == '.')
+                               osd_get_pfid_from_linkea(env, obj, fid);
                } else {
                        rc = osd_dirent_check_repair(env, obj, it, fid, id,
                                                     &attr);
@@ -5648,19 +5674,21 @@ static inline int osd_it_ea_rec(const struct lu_env *env,
        } else {
                attr &= ~LU_DIRENT_ATTRS_MASK;
                if (!fid_is_sane(fid)) {
-                       if (OBD_FAIL_CHECK(OBD_FAIL_FID_LOOKUP) &&
-                           likely(it->oie_dirent->oied_namelen != 2 ||
-                                  it->oie_dirent->oied_name[0] != '.' ||
-                                  it->oie_dirent->oied_name[1] != '.'))
-                               RETURN(-ENOENT);
-
-                       if (unlikely(ino == osd_remote_parent_ino(dev)))
+                       if (it->oie_dirent->oied_namelen == 2 &&
+                           it->oie_dirent->oied_name[0] == '.' &&
+                           it->oie_dirent->oied_name[1] == '.') {
                                /* If the parent is on remote MDT, and there
                                 * is no FID-in-dirent, then we have to get
                                 * the parent FID from the linkEA.  */
-                               rc = osd_get_pfid_from_linkea(env, obj, fid);
-                       else
+                               if (ino == osd_remote_parent_ino(dev))
+                                       rc = osd_get_pfid_from_linkea(env, obj,
+                                                                     fid);
+                       } else {
+                               if (OBD_FAIL_CHECK(OBD_FAIL_FID_LOOKUP))
+                                       RETURN(-ENOENT);
+
                                rc = osd_ea_fid_get(env, obj, ino, fid, id);
+                       }
                } else {
                        osd_id_gen(id, ino, OSD_OII_NOGEN);
                }
@@ -6129,9 +6157,6 @@ static int osd_device_init0(const struct lu_env *env,
        if (rc != 0)
                GOTO(out_site, rc);
 
-       /* self-repair LMA by default */
-       o->od_lma_self_repair = 1;
-
        INIT_LIST_HEAD(&o->od_ios_list);
        /* setup scrub, including OI files initialization */
        rc = osd_scrub_setup(env, o);
@@ -6322,10 +6347,12 @@ static int osd_obd_disconnect(struct obd_export *exp)
 }
 
 static int osd_prepare(const struct lu_env *env, struct lu_device *pdev,
-                       struct lu_device *dev)
+                      struct lu_device *dev)
 {
-       struct osd_device *osd = osd_dev(dev);
-       int                result = 0;
+       struct osd_device       *osd    = osd_dev(dev);
+       struct lr_server_data   *lsd    =
+                       &osd->od_dt_dev.dd_lu_dev.ld_site->ls_tgt->lut_lsd;
+       int                      result = 0;
        ENTRY;
 
        if (osd->od_quota_slave != NULL) {
@@ -6335,6 +6362,21 @@ static int osd_prepare(const struct lu_env *env, struct lu_device *pdev,
                        RETURN(result);
        }
 
+       if (lsd->lsd_feature_incompat & OBD_COMPAT_OST) {
+#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 0, 52, 0)
+               if (lsd->lsd_feature_rocompat & OBD_ROCOMPAT_IDX_IN_IDIF) {
+                       osd->od_index_in_idif = 1;
+               } else {
+                       osd->od_index_in_idif = 0;
+                       result = osd_register_proc_index_in_idif(osd);
+                       if (result != 0)
+                               RETURN(result);
+               }
+#else
+               osd->od_index_in_idif = 1;
+#endif
+       }
+
        result = osd_fid_init(env, osd);
 
        RETURN(result);
@@ -6385,6 +6427,14 @@ static struct lu_device_type osd_device_type = {
         .ldt_ctx_tags = LCT_LOCAL,
 };
 
+static int osd_health_check(const struct lu_env *env, struct obd_device *obd)
+{
+       struct osd_device *osd = osd_dev(obd->obd_lu_dev);
+       struct super_block *sb = osd_sb(osd);
+
+       return (osd->od_mnt == NULL || sb->s_flags & MS_RDONLY);
+}
+
 /*
  * lprocfs legacy support.
  */
@@ -6393,6 +6443,7 @@ static struct obd_ops osd_obd_device_ops = {
        .o_connect      = osd_obd_connect,
        .o_disconnect   = osd_obd_disconnect,
        .o_fid_alloc    = osd_fid_alloc,
+       .o_health_check = osd_health_check,
 };
 
 static int __init osd_mod_init(void)