+static bool osd_index_need_recreate(const struct lu_env *env,
+ struct osd_device *dev, struct inode *inode)
+{
+ struct osd_directory *iam = &osd_oti_get(env)->oti_iam;
+ struct iam_container *bag = &iam->od_container;
+ int rc;
+ ENTRY;
+
+ rc = iam_container_init(bag, &iam->od_descr, inode);
+ if (rc)
+ RETURN(true);
+
+ rc = iam_container_setup(bag);
+ iam_container_fini(bag);
+ if (rc)
+ RETURN(true);
+
+ RETURN(false);
+}
+
+static void osd_ios_index_register(const struct lu_env *env,
+ struct osd_device *osd,
+ const struct lu_fid *fid,
+ struct inode *inode)
+{
+ struct osd_directory *iam = &osd_oti_get(env)->oti_iam;
+ struct iam_container *bag = &iam->od_container;
+ struct super_block *sb = osd_sb(osd);
+ struct iam_descr *descr;
+ __u32 keysize = 0;
+ __u32 recsize = 0;
+ int rc;
+ ENTRY;
+
+ /* Index must be a regular file. */
+ if (!S_ISREG(inode->i_mode))
+ RETURN_EXIT;
+
+ /* Index's size must be block aligned. */
+ if (inode->i_size < sb->s_blocksize ||
+ (inode->i_size & (sb->s_blocksize - 1)) != 0)
+ RETURN_EXIT;
+
+ iam_container_init(bag, &iam->od_descr, inode);
+ rc = iam_container_setup(bag);
+ if (rc)
+ GOTO(fini, rc = 1);
+
+ descr = bag->ic_descr;
+ /* May be regular file with IAM_LFIX_ROOT_MAGIC matched
+ * coincidentally, or corrupted index object, skip it. */
+ if (descr->id_ptr_size != 4)
+ GOTO(fini, rc = 1);
+
+ keysize = descr->id_key_size;
+ recsize = descr->id_rec_size;
+ rc = osd_index_register(osd, fid, keysize, recsize);
+
+ GOTO(fini, rc);
+
+fini:
+ iam_container_fini(bag);
+ if (!rc)
+ CDEBUG(D_LFSCK, "%s: index object "DFID" (%u/%u) registered\n",
+ osd_name(osd), PFID(fid), keysize, recsize);
+}
+
+static void osd_index_restore(const struct lu_env *env, struct osd_device *dev,
+ struct lustre_index_restore_unit *liru,
+ void *buf, int bufsize)
+{
+ struct osd_thread_info *info = osd_oti_get(env);
+ struct osd_inode_id *id = &info->oti_id;
+ struct lu_fid *tgt_fid = &liru->liru_cfid;
+ struct inode *bak_inode = NULL;
+ struct ldiskfs_dir_entry_2 *de = NULL;
+ struct buffer_head *bh = NULL;
+ struct dentry *dentry;
+ char *name = buf;
+ struct lu_fid bak_fid;
+ int rc;
+ ENTRY;
+
+ lustre_fid2lbx(name, tgt_fid, bufsize);
+ dentry = osd_child_dentry_by_inode(env, dev->od_index_backup_inode,
+ name, strlen(name));
+ bh = osd_ldiskfs_find_entry(dev->od_index_backup_inode,
+ &dentry->d_name, &de, NULL, NULL);
+ if (IS_ERR(bh))
+ GOTO(log, rc = PTR_ERR(bh));
+
+ osd_id_gen(id, le32_to_cpu(de->inode), OSD_OII_NOGEN);
+ brelse(bh);
+ bak_inode = osd_iget_fid(info, dev, id, &bak_fid);
+ if (IS_ERR(bak_inode))
+ GOTO(log, rc = PTR_ERR(bak_inode));
+
+ iput(bak_inode);
+ /* The OI mapping for index may be invalid, since it will be
+ * re-created, not update the OI mapping, just cache it in RAM. */
+ osd_id_gen(id, liru->liru_clid, OSD_OII_NOGEN);
+ osd_add_oi_cache(info, dev, id, tgt_fid);
+ rc = lustre_index_restore(env, &dev->od_dt_dev, &liru->liru_pfid,
+ tgt_fid, &bak_fid, liru->liru_name,
+ &dev->od_index_backup_list, &dev->od_lock,
+ buf, bufsize);
+ GOTO(log, rc);
+
+log:
+ CDEBUG(D_WARNING, "%s: restore index '%s' with "DFID": rc = %d\n",
+ osd_name(dev), liru->liru_name, PFID(tgt_fid), rc);
+}
+