+static void osd_oi_table_put(struct osd_thread_info *info,
+ struct osd_oi **oi_table, unsigned oi_count)
+{
+ struct iam_container *bag;
+ int i;
+
+ for (i = 0; i < oi_count; i++) {
+ LASSERT(oi_table[i] != NULL);
+ LASSERT(oi_table[i]->oi_inode != NULL);
+
+ bag = &(oi_table[i]->oi_dir.od_container);
+ if (bag->ic_object == oi_table[i]->oi_inode)
+ iam_container_fini(bag);
+ iput(oi_table[i]->oi_inode);
+ oi_table[i]->oi_inode = NULL;
+ OBD_FREE_PTR(oi_table[i]);
+ }
+}
+
+static int osd_oi_index_create_one(struct osd_thread_info *info,
+ struct osd_device *osd, const char *name,
+ struct dt_index_features *feat)
+{
+ const struct lu_env *env = info->oti_env;
+ struct osd_inode_id *id = &info->oti_id;
+ struct buffer_head *bh;
+ struct inode *inode;
+ struct ldiskfs_dir_entry_2 *de;
+ struct dentry *dentry;
+ struct inode *dir;
+ handle_t *jh;
+ int rc;
+
+ dentry = osd_child_dentry_by_inode(env, osd_sb(osd)->s_root->d_inode,
+ name, strlen(name));
+ dir = osd_sb(osd)->s_root->d_inode;
+ bh = osd_ldiskfs_find_entry(dir, dentry, &de, NULL);
+ if (bh) {
+ brelse(bh);
+
+ id->oii_ino = le32_to_cpu(de->inode);
+ id->oii_gen = OSD_OII_NOGEN;
+
+ inode = osd_iget(info, osd, id);
+ if (!IS_ERR(inode)) {
+ iput(inode);
+ RETURN(-EEXIST);
+ }
+ RETURN(PTR_ERR(inode));
+ }
+
+ jh = ldiskfs_journal_start_sb(osd_sb(osd), 100);
+ LASSERT(!IS_ERR(jh));
+
+ inode = ldiskfs_create_inode(jh, osd_sb(osd)->s_root->d_inode,
+ (S_IFREG | S_IRUGO | S_IWUSR));
+ LASSERT(!IS_ERR(inode));
+
+ if (feat->dif_flags & DT_IND_VARKEY)
+ rc = iam_lvar_create(inode, feat->dif_keysize_max,
+ feat->dif_ptrsize, feat->dif_recsize_max,
+ jh);
+ else
+ rc = iam_lfix_create(inode, feat->dif_keysize_max,
+ feat->dif_ptrsize, feat->dif_recsize_max,
+ jh);
+
+ dentry = osd_child_dentry_by_inode(env, osd_sb(osd)->s_root->d_inode,
+ name, strlen(name));
+ rc = osd_ldiskfs_add_entry(jh, dentry, inode, NULL);
+ LASSERT(rc == 0);
+
+ ldiskfs_journal_stop(jh);
+ iput(inode);
+
+ return rc;
+}
+
+static struct inode *osd_oi_index_open(struct osd_thread_info *info,
+ struct osd_device *osd,
+ const char *name,
+ struct dt_index_features *f,
+ bool create)
+{
+ struct dentry *dentry;
+ struct inode *inode;
+ int rc;
+
+ dentry = ll_lookup_one_len(name, osd_sb(osd)->s_root, strlen(name));
+ if (IS_ERR(dentry))
+ return (void *) dentry;
+
+ if (dentry->d_inode) {
+ LASSERT(!is_bad_inode(dentry->d_inode));
+ inode = dentry->d_inode;
+ atomic_inc(&inode->i_count);
+ dput(dentry);
+ return inode;
+ }
+
+ /* create */
+ dput(dentry);
+ shrink_dcache_parent(osd_sb(osd)->s_root);
+ if (!create)
+ return ERR_PTR(-ENOENT);
+
+ rc = osd_oi_index_create_one(info, osd, name, f);
+ if (rc)
+ RETURN(ERR_PTR(rc));
+
+ dentry = ll_lookup_one_len(name, osd_sb(osd)->s_root, strlen(name));
+ if (IS_ERR(dentry))
+ return (void *) dentry;
+
+ if (dentry->d_inode) {
+ LASSERT(!is_bad_inode(dentry->d_inode));
+ inode = dentry->d_inode;
+ atomic_inc(&inode->i_count);
+ dput(dentry);
+ return inode;
+ }
+
+ return ERR_PTR(-ENOENT);
+}
+