Whamcloud - gitweb
LU-10193 osd-ldiskfs: backup index object with plain format 11/30911/11
authorFan Yong <fan.yong@intel.com>
Thu, 25 Jan 2018 08:48:00 +0000 (16:48 +0800)
committerOleg Drokin <oleg.drokin@intel.com>
Tue, 6 Feb 2018 04:27:36 +0000 (04:27 +0000)
This patch is mainly for migrating filesyste between ZFS
backend and ldiskfs backend via server file level backup
and restore. It will dumps the ldiskfs special formatted
index object to the local '/index_backup' directory with
the name of source index's FID string and ".lbx" postfix
when umount device.

The format of the backup is as following (same ZFS case):
1) header: 512 bytes, including:
   magic:       4 bytes
   count:       4 bytes
   keysize:     4 bytes
   recsize:     4 bytes
   owner_fid:   16 bytes
   padding:     480 bytes

2) body: after the header, <key, rec> pairs one by one.

The backup will be done when server umount. The backup behavior
is controlled via new OSD lproc interface "index_backup". It is
off by default. You can turn it on to enable backup when server
umount via writing non-zero value to such lproc interface.

Signed-off-by: Fan Yong <fan.yong@intel.com>
Change-Id: I5ac81dd470f3cb29eb3c9ec0e01935c9b1a0fda9
Reviewed-on: https://review.whamcloud.com/30911
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Reviewed-by: Alex Zhuravlev <alexey.zhuravlev@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/include/lustre_scrub.h
lustre/osd-ldiskfs/osd_compat.c
lustre/osd-ldiskfs/osd_handler.c
lustre/osd-ldiskfs/osd_internal.h
lustre/osd-ldiskfs/osd_lproc.c
lustre/osd-ldiskfs/osd_scrub.c
lustre/tests/sanity-scrub.sh

index 055b248..4002ba6 100644 (file)
@@ -257,7 +257,6 @@ struct scrub_file {
 };
 
 struct lustre_scrub {
 };
 
 struct lustre_scrub {
-       struct lu_object_header os_obj_header;
        /* Object for the scrub file. */
        struct dt_object       *os_obj;
 
        /* Object for the scrub file. */
        struct dt_object       *os_obj;
 
index 53a7420..9bb215b 100644 (file)
@@ -67,9 +67,14 @@ static void osd_push_ctxt(const struct osd_device *dev,
 }
 
 /* utility to make a directory */
 }
 
 /* utility to make a directory */
-static struct dentry *simple_mkdir(struct dentry *dir, struct vfsmount *mnt,
-                                  const char *name, int mode, int fix)
+static struct dentry *
+simple_mkdir(const struct lu_env *env, struct osd_device *osd,
+            struct dentry *dir, const struct lu_fid *fid,
+            const char *name, __u32 compat, int mode, bool *created)
 {
 {
+       struct osd_thread_info *info = osd_oti_get(env);
+       struct lu_fid *tfid = &info->oti_fid3;
+       struct inode *inode;
        struct dentry *dchild;
        int err = 0;
        ENTRY;
        struct dentry *dchild;
        int err = 0;
        ENTRY;
@@ -78,40 +83,72 @@ static struct dentry *simple_mkdir(struct dentry *dir, struct vfsmount *mnt,
        CDEBUG(D_INODE, "creating directory %.*s\n", (int)strlen(name), name);
        dchild = ll_lookup_one_len(name, dir, strlen(name));
        if (IS_ERR(dchild))
        CDEBUG(D_INODE, "creating directory %.*s\n", (int)strlen(name), name);
        dchild = ll_lookup_one_len(name, dir, strlen(name));
        if (IS_ERR(dchild))
-               GOTO(out_up, dchild);
+               RETURN(dchild);
+
+       inode = dchild->d_inode;
+       if (inode) {
+               struct lustre_mdt_attrs *lma = &info->oti_ost_attrs.loa_lma;
+               int old_mode = inode->i_mode;
+
+               if (created)
+                       *created = false;
 
 
-       if (dchild->d_inode) {
-               int old_mode = dchild->d_inode->i_mode;
                if (!S_ISDIR(old_mode)) {
                        CERROR("found %s (%lu/%u) is mode %o\n", name,
                if (!S_ISDIR(old_mode)) {
                        CERROR("found %s (%lu/%u) is mode %o\n", name,
-                              dchild->d_inode->i_ino,
-                              dchild->d_inode->i_generation, old_mode);
+                              inode->i_ino, inode->i_generation, old_mode);
                        GOTO(out_err, err = -ENOTDIR);
                }
 
                        GOTO(out_err, err = -ENOTDIR);
                }
 
+               if (unlikely(osd->od_dt_dev.dd_rdonly))
+                       RETURN(dchild);
+
                /* Fixup directory permissions if necessary */
                /* Fixup directory permissions if necessary */
-               if (fix && (old_mode & S_IALLUGO) != (mode & S_IALLUGO)) {
+               if ((old_mode & S_IALLUGO) != (mode & S_IALLUGO)) {
                        CDEBUG(D_CONFIG,
                               "fixing permissions on %s from %o to %o\n",
                               name, old_mode, mode);
                        CDEBUG(D_CONFIG,
                               "fixing permissions on %s from %o to %o\n",
                               name, old_mode, mode);
-                       dchild->d_inode->i_mode = (mode & S_IALLUGO) |
-                                                 (old_mode & ~S_IALLUGO);
-                       mark_inode_dirty(dchild->d_inode);
+                       inode->i_mode = (mode & S_IALLUGO) |
+                                       (old_mode & ~S_IALLUGO);
+                       mark_inode_dirty(inode);
                }
                }
-               GOTO(out_up, dchild);
+
+               err = osd_get_lma(info, inode, &info->oti_obj_dentry,
+                                 &info->oti_ost_attrs);
+               if (err == -ENODATA)
+                       goto set_fid;
+
+               if (err)
+                       GOTO(out_err, err);
+
+               if ((fid && !lu_fid_eq(fid, &lma->lma_self_fid)) ||
+                   lma->lma_compat != compat)
+                       goto set_fid;
+
+               RETURN(dchild);
        }
 
        err = vfs_mkdir(dir->d_inode, dchild, mode);
        if (err)
                GOTO(out_err, err);
 
        }
 
        err = vfs_mkdir(dir->d_inode, dchild, mode);
        if (err)
                GOTO(out_err, err);
 
+       inode = dchild->d_inode;
+       if (created)
+               *created = true;
+
+set_fid:
+       if (fid)
+               *tfid = *fid;
+       else
+               lu_igif_build(tfid, inode->i_ino, inode->i_generation);
+       err = osd_ea_fid_set(info, inode, tfid, compat, 0);
+       if (err)
+               GOTO(out_err, err);
+
        RETURN(dchild);
 
 out_err:
        dput(dchild);
        RETURN(dchild);
 
 out_err:
        dput(dchild);
-       dchild = ERR_PTR(err);
-out_up:
-       return dchild;
+       return ERR_PTR(err);
 }
 
 static int osd_last_rcvd_subdir_count(struct osd_device *osd)
 }
 
 static int osd_last_rcvd_subdir_count(struct osd_device *osd)
@@ -173,18 +210,15 @@ static int osd_mdt_init(const struct lu_env *env, struct osd_device *dev)
        parent = osd_sb(dev)->s_root;
        osd_push_ctxt(dev, &new, &save);
 
        parent = osd_sb(dev)->s_root;
        osd_push_ctxt(dev, &new, &save);
 
-       d = simple_mkdir(parent, dev->od_mnt, REMOTE_PARENT_DIR,
-                        0755, 1);
+       lu_local_obj_fid(fid, REMOTE_PARENT_DIR_OID);
+       d = simple_mkdir(env, dev, parent, fid, REMOTE_PARENT_DIR,
+                        LMAC_NOT_IN_OI, 0755, NULL);
        if (IS_ERR(d))
                GOTO(cleanup, rc = PTR_ERR(d));
 
        omm->omm_remote_parent = d;
 
        if (IS_ERR(d))
                GOTO(cleanup, rc = PTR_ERR(d));
 
        omm->omm_remote_parent = d;
 
-       /* Set LMA for remote parent inode */
-       lu_local_obj_fid(fid, REMOTE_PARENT_DIR_OID);
-       rc = osd_ea_fid_set(info, d->d_inode, fid, LMAC_NOT_IN_OI, 0);
-
-       GOTO(cleanup, rc);
+       GOTO(cleanup, rc = 0);
 
 cleanup:
        pop_ctxt(&save, &new);
 
 cleanup:
        pop_ctxt(&save, &new);
@@ -377,14 +411,11 @@ int osd_lookup_in_remote_parent(struct osd_thread_info *oti,
  */
 static int osd_ost_init(const struct lu_env *env, struct osd_device *dev)
 {
  */
 static int osd_ost_init(const struct lu_env *env, struct osd_device *dev)
 {
-       struct lvfs_run_ctxt     new;
-       struct lvfs_run_ctxt     save;
-       struct dentry           *rootd = osd_sb(dev)->s_root;
-       struct dentry           *d;
-       struct osd_thread_info  *info = osd_oti_get(env);
-       struct inode            *inode;
-       struct lu_fid           *fid = &info->oti_fid3;
-       int                      rc;
+       struct lvfs_run_ctxt new;
+       struct lvfs_run_ctxt save;
+       struct dentry *d;
+       int rc;
+       bool created = false;
        ENTRY;
 
        OBD_ALLOC_PTR(dev->od_ost_map);
        ENTRY;
 
        OBD_ALLOC_PTR(dev->od_ost_map);
@@ -397,46 +428,25 @@ static int osd_ost_init(const struct lu_env *env, struct osd_device *dev)
                GOTO(cleanup_alloc, rc);
 
        dev->od_ost_map->om_subdir_count = rc;
                GOTO(cleanup_alloc, rc);
 
        dev->od_ost_map->om_subdir_count = rc;
-        rc = 0;
-
        INIT_LIST_HEAD(&dev->od_ost_map->om_seq_list);
        rwlock_init(&dev->od_ost_map->om_seq_list_lock);
        mutex_init(&dev->od_ost_map->om_dir_init_mutex);
 
        INIT_LIST_HEAD(&dev->od_ost_map->om_seq_list);
        rwlock_init(&dev->od_ost_map->om_seq_list_lock);
        mutex_init(&dev->od_ost_map->om_dir_init_mutex);
 
-        osd_push_ctxt(dev, &new, &save);
-
-       d = ll_lookup_one_len("O", rootd, strlen("O"));
+       osd_push_ctxt(dev, &new, &save);
+       d = simple_mkdir(env, dev, osd_sb(dev)->s_root, NULL, "O",
+                        LMAC_NOT_IN_OI | LMAC_FID_ON_OST, 0755, &created);
        if (IS_ERR(d))
                GOTO(cleanup_ctxt, rc = PTR_ERR(d));
        if (IS_ERR(d))
                GOTO(cleanup_ctxt, rc = PTR_ERR(d));
-       if (d->d_inode == NULL) {
-               dput(d);
-               /* The lookup() may be called again inside simple_mkdir().
-                * Since the repeated lookup() only be called for "/O" at
-                * mount time, it will not affect the whole performance. */
-               d = simple_mkdir(rootd, dev->od_mnt, "O", 0755, 1);
-               if (IS_ERR(d))
-                       GOTO(cleanup_ctxt, rc = PTR_ERR(d));
 
 
+       if (created)
                /* It is quite probably that the device is new formatted. */
                dev->od_maybe_new = 1;
                /* It is quite probably that the device is new formatted. */
                dev->od_maybe_new = 1;
-       }
 
 
-       inode = d->d_inode;
        dev->od_ost_map->om_root = d;
 
        dev->od_ost_map->om_root = d;
 
-       /* '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);
-       rc = osd_ea_fid_set(info, inode, fid,
-                   LMAC_NOT_IN_OI | LMAC_FID_ON_OST, 0);
-       if (rc)
-               GOTO(cleanup_dentry, rc);
-
        pop_ctxt(&save, &new);
        RETURN(0);
 
        pop_ctxt(&save, &new);
        RETURN(0);
 
-cleanup_dentry:
-       dput(d);
 cleanup_ctxt:
        pop_ctxt(&save, &new);
 cleanup_alloc:
 cleanup_ctxt:
        pop_ctxt(&save, &new);
 cleanup_alloc:
@@ -489,22 +499,65 @@ static void osd_ost_fini(struct osd_device *osd)
        EXIT;
 }
 
        EXIT;
 }
 
+static int osd_index_backup_dir_init(const struct lu_env *env,
+                                    struct osd_device *dev)
+{
+       struct lu_fid *fid = &osd_oti_get(env)->oti_fid;
+       struct lvfs_run_ctxt new;
+       struct lvfs_run_ctxt save;
+       struct dentry *dentry;
+       int rc = 0;
+       ENTRY;
+
+       lu_local_obj_fid(fid, INDEX_BACKUP_OID);
+       osd_push_ctxt(dev, &new, &save);
+       dentry = simple_mkdir(env, dev, osd_sb(dev)->s_root, fid,
+                             INDEX_BACKUP_DIR, LMAC_NOT_IN_OI, 0755, NULL);
+       if (IS_ERR(dentry)) {
+               rc = PTR_ERR(dentry);
+       } else {
+               dev->od_index_backup_inode = igrab(dentry->d_inode);
+               dput(dentry);
+       }
+       pop_ctxt(&save, &new);
+
+       RETURN(rc);
+}
+
+static void osd_index_backup_dir_fini(struct osd_device *dev)
+{
+       if (dev->od_index_backup_inode) {
+               iput(dev->od_index_backup_inode);
+               dev->od_index_backup_inode = NULL;
+       }
+}
+
 int osd_obj_map_init(const struct lu_env *env, struct osd_device *dev)
 {
        int rc;
 int osd_obj_map_init(const struct lu_env *env, struct osd_device *dev)
 {
        int rc;
+       bool ost_init = false;
+       bool mdt_init = false;
        ENTRY;
 
        ENTRY;
 
-       /* prepare structures for OST */
        rc = osd_ost_init(env, dev);
        if (rc)
                RETURN(rc);
 
        rc = osd_ost_init(env, dev);
        if (rc)
                RETURN(rc);
 
-       /* prepare structures for MDS */
+       ost_init = true;
        rc = osd_mdt_init(env, dev);
        rc = osd_mdt_init(env, dev);
-       if (rc)
-               osd_ost_fini(dev);
+       if (!rc) {
+               mdt_init = true;
+               rc = osd_index_backup_dir_init(env, dev);
+       }
 
 
-        RETURN(rc);
+       if (rc) {
+               if (ost_init)
+                       osd_ost_fini(dev);
+               if (mdt_init)
+                       osd_mdt_fini(dev);
+       }
+
+       RETURN(rc);
 }
 
 static struct osd_obj_seq *osd_seq_find_locked(struct osd_obj_map *map, u64 seq)
 }
 
 static struct osd_obj_seq *osd_seq_find_locked(struct osd_obj_map *map, u64 seq)
@@ -530,6 +583,7 @@ static struct osd_obj_seq *osd_seq_find(struct osd_obj_map *map, u64 seq)
 
 void osd_obj_map_fini(struct osd_device *dev)
 {
 
 void osd_obj_map_fini(struct osd_device *dev)
 {
+       osd_index_backup_dir_fini(dev);
        osd_ost_fini(dev);
        osd_mdt_fini(dev);
 }
        osd_ost_fini(dev);
        osd_mdt_fini(dev);
 }
@@ -798,8 +852,6 @@ static int osd_seq_load_locked(struct osd_thread_info *info,
 {
        struct osd_obj_map  *map = osd->od_ost_map;
        struct dentry       *seq_dir;
 {
        struct osd_obj_map  *map = osd->od_ost_map;
        struct dentry       *seq_dir;
-       struct inode        *inode;
-       struct lu_fid       *fid = &info->oti_fid3;
        int                 rc = 0;
        int                 i;
        char                dir_name[32];
        int                 rc = 0;
        int                 i;
        char                dir_name[32];
@@ -813,23 +865,15 @@ static int osd_seq_load_locked(struct osd_thread_info *info,
 
        osd_seq_name(dir_name, sizeof(dir_name), osd_seq->oos_seq);
 
 
        osd_seq_name(dir_name, sizeof(dir_name), osd_seq->oos_seq);
 
-       seq_dir = simple_mkdir(map->om_root, osd->od_mnt, dir_name, 0755, 1);
+       seq_dir = simple_mkdir(info->oti_env, osd, map->om_root, NULL, dir_name,
+                              LMAC_NOT_IN_OI | LMAC_FID_ON_OST, 0755, NULL);
        if (IS_ERR(seq_dir))
                GOTO(out_err, rc = PTR_ERR(seq_dir));
        else if (seq_dir->d_inode == NULL)
                GOTO(out_put, rc = -EFAULT);
 
        if (IS_ERR(seq_dir))
                GOTO(out_err, rc = PTR_ERR(seq_dir));
        else if (seq_dir->d_inode == NULL)
                GOTO(out_put, rc = -EFAULT);
 
-       inode = seq_dir->d_inode;
        osd_seq->oos_root = seq_dir;
 
        osd_seq->oos_root = seq_dir;
 
-       /* '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);
-       rc = osd_ea_fid_set(info, inode, fid,
-                           LMAC_NOT_IN_OI | LMAC_FID_ON_OST, 0);
-       if (rc != 0)
-               GOTO(out_put, rc);
-
        LASSERT(osd_seq->oos_dirs == NULL);
        OBD_ALLOC(osd_seq->oos_dirs,
                  sizeof(seq_dir) * osd_seq->oos_subdir_count);
        LASSERT(osd_seq->oos_dirs == NULL);
        OBD_ALLOC(osd_seq->oos_dirs,
                  sizeof(seq_dir) * osd_seq->oos_subdir_count);
@@ -840,8 +884,9 @@ static int osd_seq_load_locked(struct osd_thread_info *info,
                struct dentry   *dir;
 
                snprintf(dir_name, sizeof(dir_name), "d%u", i);
                struct dentry   *dir;
 
                snprintf(dir_name, sizeof(dir_name), "d%u", i);
-               dir = simple_mkdir(osd_seq->oos_root, osd->od_mnt, dir_name,
-                                  0700, 1);
+               dir = simple_mkdir(info->oti_env, osd, osd_seq->oos_root, NULL,
+                                  dir_name, LMAC_NOT_IN_OI | LMAC_FID_ON_OST,
+                                  0700, NULL);
                if (IS_ERR(dir)) {
                        GOTO(out_free, rc = PTR_ERR(dir));
                } else if (dir->d_inode == NULL) {
                if (IS_ERR(dir)) {
                        GOTO(out_free, rc = PTR_ERR(dir));
                } else if (dir->d_inode == NULL) {
@@ -849,16 +894,7 @@ static int osd_seq_load_locked(struct osd_thread_info *info,
                        GOTO(out_free, rc = -EFAULT);
                }
 
                        GOTO(out_free, rc = -EFAULT);
                }
 
-               inode = dir->d_inode;
                osd_seq->oos_dirs[i] = dir;
                osd_seq->oos_dirs[i] = dir;
-
-               /* '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);
-               rc = osd_ea_fid_set(info, inode, fid,
-                                   LMAC_NOT_IN_OI | LMAC_FID_ON_OST, 0);
-               if (rc != 0)
-                       GOTO(out_free, rc);
        }
 
        if (rc != 0) {
        }
 
        if (rc != 0) {
index 501e1fd..118bec0 100644 (file)
@@ -329,17 +329,25 @@ static struct lu_object *osd_object_alloc(const struct lu_env *env,
         if (mo != NULL) {
                 struct lu_object *l;
                struct lu_object_header *h;
         if (mo != NULL) {
                 struct lu_object *l;
                struct lu_object_header *h;
+               struct osd_device *o = osd_dev(d);
 
                l = &mo->oo_dt.do_lu;
 
                l = &mo->oo_dt.do_lu;
-               h = &osd_dev(d)->od_scrub.os_scrub.os_obj_header;
-               if (unlikely(fid_is_zero(&h->loh_fid))) {
-                       /* For the OI_scrub object during OSD device init. */
+               if (unlikely(o->od_in_init)) {
+                       OBD_ALLOC_PTR(h);
+                       if (!h) {
+                               OBD_FREE_PTR(mo);
+                               return NULL;
+                       }
+
                        lu_object_header_init(h);
                        lu_object_init(l, h, d);
                        lu_object_add_top(h, l);
                        lu_object_header_init(h);
                        lu_object_init(l, h, d);
                        lu_object_add_top(h, l);
+                       mo->oo_header = h;
                } else {
                        dt_object_init(&mo->oo_dt, NULL, d);
                } else {
                        dt_object_init(&mo->oo_dt, NULL, d);
+                       mo->oo_header = NULL;
                }
                }
+
                mo->oo_dt.do_ops = &osd_obj_ops;
                l->lo_ops = &osd_lu_obj_ops;
                init_rwsem(&mo->oo_sem);
                mo->oo_dt.do_ops = &osd_obj_ops;
                l->lo_ops = &osd_lu_obj_ops;
                init_rwsem(&mo->oo_sem);
@@ -484,7 +492,7 @@ int osd_ldiskfs_add_entry(struct osd_thread_info *info, struct osd_device *osd,
 }
 
 
 }
 
 
-static struct inode *
+struct inode *
 osd_iget_fid(struct osd_thread_info *info, struct osd_device *dev,
             struct osd_inode_id *id, struct lu_fid *fid)
 {
 osd_iget_fid(struct osd_thread_info *info, struct osd_device *dev,
             struct osd_inode_id *id, struct lu_fid *fid)
 {
@@ -1164,8 +1172,11 @@ join:
        goto found;
 
 check_lma:
        goto found;
 
 check_lma:
-       result = osd_check_lma(env, obj);
        checked = true;
        checked = true;
+       if (unlikely(obj->oo_header))
+               goto found;
+
+       result = osd_check_lma(env, obj);
        if (!result)
                goto found;
 
        if (!result)
                goto found;
 
@@ -1321,19 +1332,15 @@ static int osd_object_init(const struct lu_env *env, struct lu_object *l,
        }
 
        result = osd_fid_lookup(env, obj, lu_object_fid(l), conf);
        }
 
        result = osd_fid_lookup(env, obj, lu_object_fid(l), conf);
-       if (unlikely(l->lo_header ==
-                    &osd_obj2dev(obj)->od_scrub.os_scrub.os_obj_header)) {
-               /* For the OI_scrub object during OSD device init. */
-               l->lo_header->loh_attr |= LOHA_EXISTS;
-               obj->oo_dt.do_body_ops = &osd_body_ops;
-       } else {
-               obj->oo_dt.do_body_ops = &osd_body_ops_new;
-       }
+       obj->oo_dt.do_body_ops = &osd_body_ops_new;
        if (result == 0 && obj->oo_inode != NULL) {
                struct osd_thread_info *oti = osd_oti_get(env);
                struct lustre_ost_attrs *loa = &oti->oti_ost_attrs;
 
                osd_object_init0(obj);
        if (result == 0 && obj->oo_inode != NULL) {
                struct osd_thread_info *oti = osd_oti_get(env);
                struct lustre_ost_attrs *loa = &oti->oti_ost_attrs;
 
                osd_object_init0(obj);
+               if (unlikely(obj->oo_header))
+                       return 0;
+
                result = osd_get_lma(oti, obj->oo_inode,
                                     &oti->oti_obj_dentry, loa);
                if (!result) {
                result = osd_get_lma(oti, obj->oo_inode,
                                     &oti->oti_obj_dentry, loa);
                if (!result) {
@@ -1488,21 +1495,19 @@ static void osd_oxc_fini(struct osd_object *obj)
 static void osd_object_free(const struct lu_env *env, struct lu_object *l)
 {
        struct osd_object *obj = osd_obj(l);
 static void osd_object_free(const struct lu_env *env, struct lu_object *l)
 {
        struct osd_object *obj = osd_obj(l);
-       struct lu_object_header *h = NULL;
+       struct lu_object_header *h = obj->oo_header;
 
        LINVRNT(osd_invariant(obj));
 
 
        LINVRNT(osd_invariant(obj));
 
-       if (unlikely(l->lo_header ==
-                    &osd_obj2dev(obj)->od_scrub.os_scrub.os_obj_header))
-               h = l->lo_header;
-
        osd_oxc_fini(obj);
        dt_object_fini(&obj->oo_dt);
        if (obj->oo_hl_head != NULL)
                ldiskfs_htree_lock_head_free(obj->oo_hl_head);
        OBD_FREE_PTR(obj);
        osd_oxc_fini(obj);
        dt_object_fini(&obj->oo_dt);
        if (obj->oo_hl_head != NULL)
                ldiskfs_htree_lock_head_free(obj->oo_hl_head);
        OBD_FREE_PTR(obj);
-       if (unlikely(h))
+       if (unlikely(h)) {
                lu_object_header_fini(h);
                lu_object_header_fini(h);
+               OBD_FREE_PTR(h);
+       }
 }
 
 /*
 }
 
 /*
@@ -1993,10 +1998,9 @@ static void osd_object_delete(const struct lu_env *env, struct lu_object *l)
                qid_t                    uid = i_uid_read(inode);
                qid_t                    gid = i_gid_read(inode);
 
                qid_t                    uid = i_uid_read(inode);
                qid_t                    gid = i_gid_read(inode);
 
-                iput(inode);
-                obj->oo_inode = NULL;
-
-               if (qsd != NULL) {
+               obj->oo_inode = NULL;
+               iput(inode);
+               if (!obj->oo_header && qsd) {
                        struct osd_thread_info  *info = osd_oti_get(env);
                        struct lquota_id_info   *qi = &info->oti_qi;
 
                        struct osd_thread_info  *info = osd_oti_get(env);
                        struct lquota_id_info   *qi = &info->oti_qi;
 
@@ -4498,11 +4502,13 @@ static int osd_index_try(const struct lu_env *env, struct dt_object *dt,
                dt->do_index_ops = &osd_acct_index_ops;
                result = 0;
                skip_iam = 1;
                dt->do_index_ops = &osd_acct_index_ops;
                result = 0;
                skip_iam = 1;
-        } else if (!osd_has_index(obj)) {
-                struct osd_directory *dir;
+       } else if (!osd_has_index(obj)) {
+               struct osd_directory *dir;
+               struct osd_device *osd = osd_obj2dev(obj);
+               const struct lu_fid *fid = lu_object_fid(&dt->do_lu);
 
 
-                OBD_ALLOC_PTR(dir);
-                if (dir != NULL) {
+               OBD_ALLOC_PTR(dir);
+               if (dir) {
 
                        spin_lock(&obj->oo_guard);
                        if (obj->oo_dir == NULL)
 
                        spin_lock(&obj->oo_guard);
                        if (obj->oo_dir == NULL)
@@ -4521,11 +4527,35 @@ static int osd_index_try(const struct lu_env *env, struct dt_object *dt,
                        /*
                         * recheck under lock.
                         */
                        /*
                         * recheck under lock.
                         */
-                       if (!osd_has_index(obj))
-                               result = osd_iam_container_init(env, obj,
-                                                               obj->oo_dir);
-                       else
+
+                       if (osd_has_index(obj)) {
                                result = 0;
                                result = 0;
+                               goto unlock;
+                       }
+
+                       result = osd_iam_container_init(env, obj, obj->oo_dir);
+                       if (result || feat == &dt_lfsck_namespace_features ||
+                           feat == &dt_lfsck_layout_orphan_features ||
+                           feat == &dt_lfsck_layout_dangling_features)
+                               goto unlock;
+
+                       result = osd_index_register(osd, fid,
+                                                   feat->dif_keysize_max,
+                                                   feat->dif_recsize_max);
+                       if (result < 0)
+                               CWARN("%s: failed to register index "
+                                     DFID": rc = %d\n",
+                                     osd_name(osd), PFID(fid), result);
+                       else if (result > 0)
+                               result = 0;
+                       else
+                               CDEBUG(D_LFSCK, "%s: index object "DFID
+                                      " (%d/%d) registered\n",
+                                      osd_name(osd), PFID(fid),
+                                      (int)feat->dif_keysize_max,
+                                      (int)feat->dif_recsize_max);
+
+unlock:
                        up_write(&obj->oo_ext_idx_sem);
                 } else {
                         result = -ENOMEM;
                        up_write(&obj->oo_ext_idx_sem);
                 } else {
                         result = -ENOMEM;
@@ -7023,8 +7053,10 @@ static int osd_shutdown(const struct lu_env *env, struct osd_device *o)
 
        /* shutdown quota slave instance associated with the device */
        if (o->od_quota_slave != NULL) {
 
        /* shutdown quota slave instance associated with the device */
        if (o->od_quota_slave != NULL) {
-               qsd_fini(env, o->od_quota_slave);
+               struct qsd_instance *qsd = o->od_quota_slave;
+
                o->od_quota_slave = NULL;
                o->od_quota_slave = NULL;
+               qsd_fini(env, qsd);
        }
 
        osd_fid_fini(env, o);
        }
 
        osd_fid_fini(env, o);
@@ -7277,6 +7309,10 @@ static int osd_device_init0(const struct lu_env *env,
        spin_lock_init(&o->od_osfs_lock);
        mutex_init(&o->od_otable_mutex);
        INIT_LIST_HEAD(&o->od_orphan_list);
        spin_lock_init(&o->od_osfs_lock);
        mutex_init(&o->od_otable_mutex);
        INIT_LIST_HEAD(&o->od_orphan_list);
+       INIT_LIST_HEAD(&o->od_index_backup_list);
+       INIT_LIST_HEAD(&o->od_index_restore_list);
+       spin_lock_init(&o->od_lock);
+       o->od_index_backup_policy = LIBP_NONE;
 
        o->od_read_cache = 1;
        o->od_writethrough_cache = 1;
 
        o->od_read_cache = 1;
        o->od_writethrough_cache = 1;
@@ -7290,6 +7326,7 @@ static int osd_device_init0(const struct lu_env *env,
                GOTO(out, rc);
        }
 
                GOTO(out, rc);
        }
 
+       o->od_index_backup_stop = 0;
        o->od_index = -1; /* -1 means index is invalid */
        rc = server_name2index(o->od_svname, &o->od_index, NULL);
        if (rc == LDD_F_SV_TYPE_OST)
        o->od_index = -1; /* -1 means index is invalid */
        rc = server_name2index(o->od_svname, &o->od_index, NULL);
        if (rc == LDD_F_SV_TYPE_OST)
@@ -7316,7 +7353,9 @@ static int osd_device_init0(const struct lu_env *env,
 
        INIT_LIST_HEAD(&o->od_ios_list);
        /* setup scrub, including OI files initialization */
 
        INIT_LIST_HEAD(&o->od_ios_list);
        /* setup scrub, including OI files initialization */
+       o->od_in_init = 1;
        rc = osd_scrub_setup(env, o);
        rc = osd_scrub_setup(env, o);
+       o->od_in_init = 0;
        if (rc < 0)
                GOTO(out_site, rc);
 
        if (rc < 0)
                GOTO(out_site, rc);
 
@@ -7413,6 +7452,9 @@ static int osd_process_config(const struct lu_env *env,
                rc = osd_mount(env, o, cfg);
                break;
        case LCFG_CLEANUP:
                rc = osd_mount(env, o, cfg);
                break;
        case LCFG_CLEANUP:
+               /* For the case LCFG_PRE_CLEANUP is not called in advance,
+                * that may happend if hit failure during mount process. */
+               osd_index_backup(env, o, false);
                lu_dev_del_linkage(d->ld_site, d);
                rc = osd_shutdown(env, o);
                break;
                lu_dev_del_linkage(d->ld_site, d);
                rc = osd_shutdown(env, o);
                break;
@@ -7428,6 +7470,11 @@ static int osd_process_config(const struct lu_env *env,
                                rc = 0;
                }
                break;
                                rc = 0;
                }
                break;
+       case LCFG_PRE_CLEANUP:
+               osd_index_backup(env, o,
+                                o->od_index_backup_policy != LIBP_NONE);
+               rc = 0;
+               break;
        default:
                rc = -ENOSYS;
        }
        default:
                rc = -ENOSYS;
        }
index 08b1a09..5d4c6f3 100644 (file)
@@ -154,6 +154,7 @@ struct osd_object {
 #endif
 
        struct list_head        oo_xattr_list;
 #endif
 
        struct list_head        oo_xattr_list;
+       struct lu_object_header *oo_header;
 };
 
 struct osd_obj_seq {
 };
 
 struct osd_obj_seq {
@@ -259,6 +260,7 @@ struct osd_device {
                                  od_igif_inoi:1,
                                  od_check_ff:1,
                                  od_is_ost:1,
                                  od_igif_inoi:1,
                                  od_check_ff:1,
                                  od_is_ost:1,
+                                 od_in_init:1,
                                  od_index_in_idif:1;
 
        __s64                     od_auto_scrub_interval;
                                  od_index_in_idif:1;
 
        __s64                     od_auto_scrub_interval;
@@ -309,6 +311,12 @@ struct osd_device {
 
        /* a list of orphaned agent inodes, protected with od_osfs_lock */
        struct list_head         od_orphan_list;
 
        /* a list of orphaned agent inodes, protected with od_osfs_lock */
        struct list_head         od_orphan_list;
+       struct list_head         od_index_backup_list;
+       struct list_head         od_index_restore_list;
+       spinlock_t               od_lock;
+       struct inode            *od_index_backup_inode;
+       enum lustre_index_backup_policy od_index_backup_policy;
+       int                      od_index_backup_stop;
 };
 
 enum osd_full_scrub_ratio {
 };
 
 enum osd_full_scrub_ratio {
@@ -627,6 +635,7 @@ struct osd_thread_info {
        unsigned int            oti_declare_ops[OSD_OT_MAX];
        unsigned int            oti_declare_ops_cred[OSD_OT_MAX];
        unsigned int            oti_declare_ops_used[OSD_OT_MAX];
        unsigned int            oti_declare_ops[OSD_OT_MAX];
        unsigned int            oti_declare_ops_cred[OSD_OT_MAX];
        unsigned int            oti_declare_ops_used[OSD_OT_MAX];
+       struct osd_directory    oti_iam;
 };
 
 extern int ldiskfs_pdo;
 };
 
 extern int ldiskfs_pdo;
@@ -670,6 +679,9 @@ int osd_statfs(const struct lu_env *env, struct dt_device *dev,
                struct obd_statfs *sfs);
 struct inode *osd_iget(struct osd_thread_info *info, struct osd_device *dev,
                       struct osd_inode_id *id);
                struct obd_statfs *sfs);
 struct inode *osd_iget(struct osd_thread_info *info, struct osd_device *dev,
                       struct osd_inode_id *id);
+struct inode *
+osd_iget_fid(struct osd_thread_info *info, struct osd_device *dev,
+            struct osd_inode_id *id, struct lu_fid *fid);
 int osd_ea_fid_set(struct osd_thread_info *info, struct inode *inode,
                   const struct lu_fid *fid, __u32 compat, __u32 incompat);
 int osd_get_lma(struct osd_thread_info *info, struct inode *inode,
 int osd_ea_fid_set(struct osd_thread_info *info, struct inode *inode,
                   const struct lu_fid *fid, __u32 compat, __u32 incompat);
 int osd_get_lma(struct osd_thread_info *info, struct inode *inode,
@@ -1300,5 +1312,31 @@ void ldiskfs_dec_count(handle_t *handle, struct inode *inode);
 
 void osd_fini_iobuf(struct osd_device *d, struct osd_iobuf *iobuf);
 
 
 void osd_fini_iobuf(struct osd_device *d, struct osd_iobuf *iobuf);
 
+static inline int
+osd_index_register(struct osd_device *osd, const struct lu_fid *fid,
+                  __u32 keysize, __u32 recsize)
+{
+       return lustre_index_register(&osd->od_dt_dev, osd_name(osd),
+                                    &osd->od_index_backup_list, &osd->od_lock,
+                                    &osd->od_index_backup_stop,
+                                    fid, keysize, recsize);
+}
+
+static inline void
+osd_index_backup(const struct lu_env *env, struct osd_device *osd, bool backup)
+{
+       struct osd_thread_info *info = osd_oti_get(env);
+       struct lu_fid *fid = &info->oti_fid3;
+       struct osd_inode_id *id = &info->oti_id3;
+
+       lu_local_obj_fid(fid, INDEX_BACKUP_OID);
+       osd_id_gen(id, osd->od_index_backup_inode->i_ino,
+                  osd->od_index_backup_inode->i_generation);
+       osd_add_oi_cache(info, osd, id, fid);
+
+       lustre_index_backup(env, &osd->od_dt_dev, osd_name(osd),
+                           &osd->od_index_backup_list, &osd->od_lock,
+                           &osd->od_index_backup_stop, backup);
+}
 
 #endif /* _OSD_INTERNAL_H */
 
 #endif /* _OSD_INTERNAL_H */
index 6d905fe..0c93d27 100644 (file)
@@ -645,6 +645,41 @@ int osd_register_proc_index_in_idif(struct osd_device *osd)
 }
 #endif
 
 }
 #endif
 
+static int ldiskfs_osd_index_backup_seq_show(struct seq_file *m, void *data)
+{
+       struct osd_device *dev = osd_dt_dev((struct dt_device *)m->private);
+
+       LASSERT(dev != NULL);
+       if (unlikely(dev->od_mnt == NULL))
+               return -EINPROGRESS;
+
+       seq_printf(m, "%d\n", dev->od_index_backup_policy);
+       return 0;
+}
+
+static ssize_t ldiskfs_osd_index_backup_seq_write(struct file *file,
+                                                 const char __user *buffer,
+                                                 size_t count, loff_t *off)
+{
+       struct seq_file *m = file->private_data;
+       struct dt_device *dt = m->private;
+       struct osd_device *dev = osd_dt_dev(dt);
+       __s64 val;
+       int rc;
+
+       LASSERT(dev != NULL);
+       if (unlikely(dev->od_mnt == NULL))
+               return -EINPROGRESS;
+
+       rc = lprocfs_str_to_s64(buffer, count, &val);
+       if (rc)
+               return rc;
+
+       dev->od_index_backup_policy = val;
+       return count;
+}
+LPROC_SEQ_FOPS(ldiskfs_osd_index_backup);
+
 LPROC_SEQ_FOPS_RO_TYPE(ldiskfs, dt_blksize);
 LPROC_SEQ_FOPS_RO_TYPE(ldiskfs, dt_kbytestotal);
 LPROC_SEQ_FOPS_RO_TYPE(ldiskfs, dt_kbytesfree);
 LPROC_SEQ_FOPS_RO_TYPE(ldiskfs, dt_blksize);
 LPROC_SEQ_FOPS_RO_TYPE(ldiskfs, dt_kbytestotal);
 LPROC_SEQ_FOPS_RO_TYPE(ldiskfs, dt_kbytesfree);
@@ -687,6 +722,8 @@ struct lprocfs_vars lprocfs_osd_obd_vars[] = {
          .fops =       &ldiskfs_osd_wcache_fops        },
        { .name =       "readcache_max_filesize",
          .fops =       &ldiskfs_osd_readcache_fops     },
          .fops =       &ldiskfs_osd_wcache_fops        },
        { .name =       "readcache_max_filesize",
          .fops =       &ldiskfs_osd_readcache_fops     },
+       { .name =       "index_backup",
+         .fops =       &ldiskfs_osd_index_backup_fops  },
        { NULL }
 };
 
        { NULL }
 };
 
index 0a94e88..2ede42c 100644 (file)
@@ -1671,6 +1671,19 @@ static const struct osd_lf_map osd_lf_maps[] = {
                .olm_name       = LUSTRE_NODEMAP_NAME,
        },
 
                .olm_name       = LUSTRE_NODEMAP_NAME,
        },
 
+       /* index_backup */
+       {
+               .olm_name       = INDEX_BACKUP_DIR,
+               .olm_fid        = {
+                       .f_seq  = FID_SEQ_LOCAL_FILE,
+                       .f_oid  = INDEX_BACKUP_OID,
+               },
+               .olm_flags      = OLF_SCAN_SUBITEMS | OLF_NOT_BACKUP,
+               .olm_namelen    = sizeof(INDEX_BACKUP_DIR) - 1,
+               .olm_scandir    = osd_ios_general_scan,
+               .olm_filldir    = osd_ios_varfid_fill,
+       },
+
        {
                .olm_name       = NULL
        }
        {
                .olm_name       = NULL
        }
@@ -1767,6 +1780,119 @@ osd_ios_new_item(struct osd_device *dev, struct dentry *dentry,
        RETURN(0);
 }
 
        RETURN(0);
 }
 
+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);
+}
+
 /**
  * osd_ios_scan_one() - check/fix LMA FID and OI entry for one inode
  *
 /**
  * osd_ios_scan_one() - check/fix LMA FID and OI entry for one inode
  *
@@ -1776,7 +1902,9 @@ osd_ios_new_item(struct osd_device *dev, struct dentry *dentry,
  */
 static int
 osd_ios_scan_one(struct osd_thread_info *info, struct osd_device *dev,
  */
 static int
 osd_ios_scan_one(struct osd_thread_info *info, struct osd_device *dev,
-                struct inode *inode, const struct lu_fid *fid, int flags)
+                struct inode *parent, struct inode *inode,
+                const struct lu_fid *fid, const char *name,
+                int namelen, int flags)
 {
        struct lustre_mdt_attrs *lma    = &info->oti_ost_attrs.loa_lma;
        struct osd_inode_id     *id     = &info->oti_id;
 {
        struct lustre_mdt_attrs *lma    = &info->oti_ost_attrs.loa_lma;
        struct osd_inode_id     *id     = &info->oti_id;
@@ -1820,6 +1948,28 @@ osd_ios_scan_one(struct osd_thread_info *info, struct osd_device *dev,
                        RETURN(0);
 
                tfid = lma->lma_self_fid;
                        RETURN(0);
 
                tfid = lma->lma_self_fid;
+               if (lma->lma_compat & LMAC_IDX_BACKUP &&
+                   osd_index_need_recreate(info->oti_env, dev, inode)) {
+                       struct lu_fid *pfid = &info->oti_fid3;
+
+                       if (parent == osd_sb(dev)->s_root->d_inode) {
+                               lu_local_obj_fid(pfid, OSD_FS_ROOT_OID);
+                       } else {
+                               rc = osd_scrub_get_fid(info, dev, parent, pfid,
+                                                      false);
+                               if (rc)
+                                       RETURN(rc);
+                       }
+
+                       rc = lustre_liru_new(&dev->od_index_restore_list, pfid,
+                                       &tfid, inode->i_ino, name, namelen);
+
+                       RETURN(rc);
+               }
+
+               if (!(flags & OLF_NOT_BACKUP))
+                       osd_ios_index_register(info->oti_env, dev, &tfid,
+                                              inode);
        }
 
        rc = osd_oi_lookup(info, dev, &tfid, id2, 0);
        }
 
        rc = osd_oi_lookup(info, dev, &tfid, id2, 0);
@@ -1959,8 +2109,9 @@ static int osd_ios_varfid_fill(void *buf,
        if (IS_ERR(child))
                RETURN(PTR_ERR(child));
 
        if (IS_ERR(child))
                RETURN(PTR_ERR(child));
 
-       rc = osd_ios_scan_one(fill_buf->oifb_info, dev, child->d_inode,
-                             NULL, 0);
+       rc = osd_ios_scan_one(fill_buf->oifb_info, dev,
+                             fill_buf->oifb_dentry->d_inode, child->d_inode,
+                             NULL, name, namelen, 0);
        if (rc == 0 && S_ISDIR(child->d_inode->i_mode))
                rc = osd_ios_new_item(dev, child, osd_ios_general_scan,
                                      osd_ios_varfid_fill);
        if (rc == 0 && S_ISDIR(child->d_inode->i_mode))
                rc = osd_ios_new_item(dev, child, osd_ios_general_scan,
                                      osd_ios_varfid_fill);
@@ -2006,8 +2157,9 @@ static int osd_ios_dl_fill(void *buf,
        if (IS_ERR(child))
                RETURN(PTR_ERR(child));
 
        if (IS_ERR(child))
                RETURN(PTR_ERR(child));
 
-       rc = osd_ios_scan_one(fill_buf->oifb_info, dev, child->d_inode,
-                             &map->olm_fid, map->olm_flags);
+       rc = osd_ios_scan_one(fill_buf->oifb_info, dev,
+                             fill_buf->oifb_dentry->d_inode, child->d_inode,
+                             &map->olm_fid, name, namelen, map->olm_flags);
        dput(child);
 
        RETURN(rc);
        dput(child);
 
        RETURN(rc);
@@ -2042,7 +2194,8 @@ static int osd_ios_uld_fill(void *buf,
        sscanf(&name[1], SFID, RFID(&tfid));
        if (fid_is_sane(&tfid))
                rc = osd_ios_scan_one(fill_buf->oifb_info, fill_buf->oifb_dev,
        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);
+                                     fill_buf->oifb_dentry->d_inode,
+                                     child->d_inode, &tfid, name, namelen, 0);
        else
                rc = -EIO;
        dput(child);
        else
                rc = -EIO;
        dput(child);
@@ -2088,8 +2241,9 @@ static int osd_ios_root_fill(void *buf,
                RETURN(PTR_ERR(child));
 
        if (!(map->olm_flags & OLF_NO_OI))
                RETURN(PTR_ERR(child));
 
        if (!(map->olm_flags & OLF_NO_OI))
-               rc = osd_ios_scan_one(fill_buf->oifb_info, dev, child->d_inode,
-                                     &map->olm_fid, map->olm_flags);
+               rc = osd_ios_scan_one(fill_buf->oifb_info, dev,
+                               fill_buf->oifb_dentry->d_inode, child->d_inode,
+                               &map->olm_fid, name, namelen, map->olm_flags);
        if (rc == 0 && map->olm_flags & OLF_SCAN_SUBITEMS)
                rc = osd_ios_new_item(dev, child, map->olm_scandir,
                                      map->olm_filldir);
        if (rc == 0 && map->olm_flags & OLF_SCAN_SUBITEMS)
                rc = osd_ios_new_item(dev, child, map->olm_scandir,
                                      map->olm_filldir);
@@ -2205,8 +2359,10 @@ osd_ios_ROOT_scan(struct osd_thread_info *info, struct osd_device *dev,
                 * Usually, it is rare case for the old connected clients
                 * to access the ".lustre" with cached IGIF. So we prefer
                 * to the solution 2). */
                 * Usually, it is rare case for the old connected clients
                 * to access the ".lustre" with cached IGIF. So we prefer
                 * to the solution 2). */
-               rc = osd_ios_scan_one(info, dev, child->d_inode,
-                                     &LU_DOT_LUSTRE_FID, 0);
+               rc = osd_ios_scan_one(info, dev, dentry->d_inode,
+                                     child->d_inode, &LU_DOT_LUSTRE_FID,
+                                     dot_lustre_name,
+                                     strlen(dot_lustre_name), 0);
                if (rc == 0)
                        rc = osd_ios_new_item(dev, child, osd_ios_general_scan,
                                              osd_ios_dl_fill);
                if (rc == 0)
                        rc = osd_ios_new_item(dev, child, osd_ios_general_scan,
                                              osd_ios_dl_fill);
@@ -2235,7 +2391,9 @@ osd_ios_OBJECTS_scan(struct osd_thread_info *info, struct osd_device *dev,
 
        child = osd_ios_lookup_one_len(ADMIN_USR, dentry, strlen(ADMIN_USR));
        if (!IS_ERR(child)) {
 
        child = osd_ios_lookup_one_len(ADMIN_USR, dentry, strlen(ADMIN_USR));
        if (!IS_ERR(child)) {
-               rc = osd_ios_scan_one(info, dev, child->d_inode, NULL, 0);
+               rc = osd_ios_scan_one(info, dev, dentry->d_inode,
+                                     child->d_inode, NULL, ADMIN_USR,
+                                     strlen(ADMIN_USR), 0);
                dput(child);
        } else {
                rc = PTR_ERR(child);
                dput(child);
        } else {
                rc = PTR_ERR(child);
@@ -2246,7 +2404,9 @@ osd_ios_OBJECTS_scan(struct osd_thread_info *info, struct osd_device *dev,
 
        child = osd_ios_lookup_one_len(ADMIN_GRP, dentry, strlen(ADMIN_GRP));
        if (!IS_ERR(child)) {
 
        child = osd_ios_lookup_one_len(ADMIN_GRP, dentry, strlen(ADMIN_GRP));
        if (!IS_ERR(child)) {
-               rc = osd_ios_scan_one(info, dev, child->d_inode, NULL, 0);
+               rc = osd_ios_scan_one(info, dev, dentry->d_inode,
+                                     child->d_inode, NULL, ADMIN_GRP,
+                                     strlen(ADMIN_GRP), 0);
                dput(child);
        } else {
                rc = PTR_ERR(child);
                dput(child);
        } else {
                rc = PTR_ERR(child);
@@ -2258,30 +2418,26 @@ osd_ios_OBJECTS_scan(struct osd_thread_info *info, struct osd_device *dev,
        RETURN(rc);
 }
 
        RETURN(rc);
 }
 
-static int osd_initial_OI_scrub(struct osd_thread_info *info,
-                               struct osd_device *dev)
+static void osd_initial_OI_scrub(struct osd_thread_info *info,
+                                struct osd_device *dev)
 {
        struct osd_ios_item     *item    = NULL;
        scandir_t                scandir = osd_ios_general_scan;
        filldir_t                filldir = osd_ios_root_fill;
        struct dentry           *dentry  = osd_sb(dev)->s_root;
        const struct osd_lf_map *map     = osd_lf_maps;
 {
        struct osd_ios_item     *item    = NULL;
        scandir_t                scandir = osd_ios_general_scan;
        filldir_t                filldir = osd_ios_root_fill;
        struct dentry           *dentry  = osd_sb(dev)->s_root;
        const struct osd_lf_map *map     = osd_lf_maps;
-       int                      rc;
        ENTRY;
 
        /* Lookup IGIF in OI by force for initial OI scrub. */
        dev->od_igif_inoi = 1;
 
        while (1) {
        ENTRY;
 
        /* Lookup IGIF in OI by force for initial OI scrub. */
        dev->od_igif_inoi = 1;
 
        while (1) {
-               rc = scandir(info, dev, dentry, filldir);
+               scandir(info, dev, dentry, filldir);
                if (item != NULL) {
                        dput(item->oii_dentry);
                        OBD_FREE_PTR(item);
                }
 
                if (item != NULL) {
                        dput(item->oii_dentry);
                        OBD_FREE_PTR(item);
                }
 
-               if (rc != 0)
-                       break;
-
                if (list_empty(&dev->od_ios_list))
                        break;
 
                if (list_empty(&dev->od_ios_list))
                        break;
 
@@ -2295,17 +2451,6 @@ static int osd_initial_OI_scrub(struct osd_thread_info *info,
                dentry = item->oii_dentry;
        }
 
                dentry = item->oii_dentry;
        }
 
-       while (!list_empty(&dev->od_ios_list)) {
-               item = list_entry(dev->od_ios_list.next,
-                                 struct osd_ios_item, oii_list);
-               list_del_init(&item->oii_list);
-               dput(item->oii_dentry);
-               OBD_FREE_PTR(item);
-       }
-
-       if (rc != 0)
-               RETURN(rc);
-
        /* There maybe the case that the object has been removed, but its OI
         * mapping is still in the OI file, such as the "CATALOGS" after MDT
         * file-level backup/restore. So here cleanup the stale OI mappings. */
        /* There maybe the case that the object has been removed, but its OI
         * mapping is still in the OI file, such as the "CATALOGS" after MDT
         * file-level backup/restore. So here cleanup the stale OI mappings. */
@@ -2329,7 +2474,32 @@ static int osd_initial_OI_scrub(struct osd_thread_info *info,
                map++;
        }
 
                map++;
        }
 
-       RETURN(0);
+       if (!list_empty(&dev->od_index_restore_list)) {
+               char *buf;
+
+               OBD_ALLOC_LARGE(buf, INDEX_BACKUP_BUFSIZE);
+               if (!buf)
+                       CERROR("%s: not enough RAM for rebuild index\n",
+                              osd_name(dev));
+
+               while (!list_empty(&dev->od_index_restore_list)) {
+                       struct lustre_index_restore_unit *liru;
+
+                       liru = list_entry(dev->od_index_restore_list.next,
+                                         struct lustre_index_restore_unit,
+                                         liru_link);
+                       list_del(&liru->liru_link);
+                       if (buf)
+                               osd_index_restore(info->oti_env, dev, liru,
+                                                 buf, INDEX_BACKUP_BUFSIZE);
+                       OBD_FREE(liru, liru->liru_len);
+               }
+
+               if (buf)
+                       OBD_FREE_LARGE(buf, INDEX_BACKUP_BUFSIZE);
+       }
+
+       EXIT;
 }
 
 char *osd_lf_fid2name(const struct lu_fid *fid)
 }
 
 char *osd_lf_fid2name(const struct lu_fid *fid)
@@ -2405,7 +2575,7 @@ int osd_scrub_setup(const struct lu_env *env, struct osd_device *dev)
        struct file *filp;
        struct inode *inode;
        struct lu_fid *fid = &info->oti_fid;
        struct file *filp;
        struct inode *inode;
        struct lu_fid *fid = &info->oti_fid;
-       struct lu_object_conf conf;
+       struct osd_inode_id *id = &info->oti_id;
        struct dt_object *obj;
        bool dirty = false;
        bool restored = false;
        struct dt_object *obj;
        bool dirty = false;
        bool restored = false;
@@ -2445,18 +2615,15 @@ int osd_scrub_setup(const struct lu_env *env, struct osd_device *dev)
                }
        }
 
                }
        }
 
-       igrab(inode);
+       osd_id_gen(id, inode->i_ino, inode->i_generation);
+       osd_add_oi_cache(info, dev, id, fid);
        filp_close(filp, NULL);
        pop_ctxt(&saved, ctxt);
 
        filp_close(filp, NULL);
        pop_ctxt(&saved, ctxt);
 
-       conf.loc_flags = LOC_F_NEW;
-       obj = lu2dt(lu_object_find_slice(env, osd2lu_dev(dev), fid, &conf));
-       if (IS_ERR_OR_NULL(obj)) {
-               iput(inode);
-               RETURN(obj == NULL ? -ENOENT : PTR_ERR(obj));
-       }
+       obj = lu2dt(lu_object_find_slice(env, osd2lu_dev(dev), fid, NULL));
+       if (IS_ERR_OR_NULL(obj))
+               RETURN(obj ? PTR_ERR(obj) : -ENOENT);
 
 
-       osd_dt_obj(obj)->oo_inode = inode;
        scrub->os_obj = obj;
        rc = scrub_file_load(env, scrub);
        if (rc == -ENOENT || rc == -EFAULT) {
        scrub->os_obj = obj;
        rc = scrub_file_load(env, scrub);
        if (rc == -ENOENT || rc == -EFAULT) {
@@ -2533,11 +2700,8 @@ int osd_scrub_setup(const struct lu_env *env, struct osd_device *dev)
        if (rc < 0)
                GOTO(cleanup_obj, rc);
 
        if (rc < 0)
                GOTO(cleanup_obj, rc);
 
-       if (!dev->od_dt_dev.dd_rdonly) {
-               rc = osd_initial_OI_scrub(info, dev);
-               if (rc)
-                       GOTO(cleanup_oi, rc);
-       }
+       if (!dev->od_dt_dev.dd_rdonly)
+               osd_initial_OI_scrub(info, dev);
 
        if (sf->sf_flags & SF_UPGRADE ||
            !(sf->sf_internal_flags & SIF_NO_HANDLE_OLD_FID ||
 
        if (sf->sf_flags & SF_UPGRADE ||
            !(sf->sf_internal_flags & SIF_NO_HANDLE_OLD_FID ||
index 6a14220..24c81a9 100644 (file)
@@ -1227,9 +1227,6 @@ test_15() {
 run_test 15 "Dryrun mode OI scrub"
 
 test_16() {
 run_test 15 "Dryrun mode OI scrub"
 
 test_16() {
-       [ $(facet_fstype $SINGLEMDS) != "zfs" ] &&
-               skip "only support zfs temporarily" && return
-
        check_mount_and_prep
        scrub_enable_index_backup
 
        check_mount_and_prep
        scrub_enable_index_backup