Whamcloud - gitweb
For iam lib.
authorfanyong <fanyong>
Thu, 10 Aug 2006 03:09:10 +0000 (03:09 +0000)
committerfanyong <fanyong>
Thu, 10 Aug 2006 03:09:10 +0000 (03:09 +0000)
lustre/include/lustre/Makefile.am
lustre/include/lustre/libiam.h [new file with mode: 0644]
lustre/utils/Makefile.am
lustre/utils/libiam.c [new file with mode: 0644]

index 0acd90f..09b9290 100644 (file)
@@ -4,7 +4,7 @@
 # See the file COPYING in this distribution
 
 if UTILS
-pkginclude_HEADERS = lustre_idl.h lustre_user.h liblustreapi.h types.h
+pkginclude_HEADERS = lustre_idl.h lustre_user.h liblustreapi.h libiam.h types.h
 endif
 
-EXTRA_DIST = lustre_idl.h lustre_user.h liblustreapi.h types.h
+EXTRA_DIST = lustre_idl.h lustre_user.h liblustreapi.h libiam.h types.h
diff --git a/lustre/include/lustre/libiam.h b/lustre/include/lustre/libiam.h
new file mode 100644 (file)
index 0000000..06c82b8
--- /dev/null
@@ -0,0 +1,128 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ *  libiam.h
+ *  iam user level library
+ *
+ *   Copyright (c) 2006 Cluster File Systems, Inc.
+ *   Author: Wang Di <wangdi@clusterfs.com>
+ *   Author: Nikita Danilov <nikita@clusterfs.com>
+ *   Author: Fan Yong <fanyong@clusterfs.com>
+ *
+ *   This file is part of the Lustre file system, http://www.lustre.org
+ *   Lustre is a trademark of Cluster File Systems, Inc.
+ *
+ *   You may have signed or agreed to another license before downloading
+ *   this software.  If so, you are bound by the terms and conditions
+ *   of that agreement, and the following does not apply to you.  See the
+ *   LICENSE file included with this distribution for more information.
+ *
+ *   If you did not agree to a different license, then this copy of Lustre
+ *   is open source software; you can redistribute it and/or modify it
+ *   under the terms of version 2 of the GNU General Public License as
+ *   published by the Free Software Foundation.
+ *
+ *   In either case, Lustre is distributed in the hope that it will be
+ *   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ *   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   license text for more details.
+ */
+
+/*
+ *  lustre/libiam.h
+ */
+
+#ifndef __IAM_ULIB_H__
+#define __IAM_ULIB_H__
+
+
+#define SET_DEFAULT     -1
+#define DX_FMT_NAME_LEN 16
+
+enum iam_fmt_t {
+        FMT_LFIX,
+        FMT_LVAR
+};
+
+struct iam_uapi_info {
+        __u16 iui_keysize;
+        __u16 iui_recsize;
+        __u16 iui_ptrsize;
+        __u16 iui_height;
+        char  iui_fmt_name[DX_FMT_NAME_LEN];
+};
+
+/*
+ * Creat an iam file, but do NOT open it.
+ * Return 0 if success, else -1.
+ */
+int iam_creat(char *filename, enum iam_fmt_t fmt,
+              int blocksize, int keysize, int recsize, int ptrsize);
+
+/*
+ * Open an iam file, but do NOT creat it if the file doesn't exist.
+ * Please use iam_creat for creating the file before use iam_open.
+ * Return file id (fd) if success, else -1.
+ */
+int iam_open(char *filename, struct iam_uapi_info *ua);
+
+/*
+ * Close file opened by iam_open. 
+ */
+int iam_close(int fd);
+
+/*
+ * Please use iam_open before use this function.
+ */
+int iam_insert(int fd, struct iam_uapi_info *ua,
+               int key_need_convert, char *keybuf,
+               int rec_need_convert, char *recbuf);
+
+/*
+ * Please use iam_open before use this function.
+ */
+int iam_lookup(int fd, struct iam_uapi_info *ua,
+               int key_need_convert, char *key_buf,
+               int *keysize, char *save_key,
+               int rec_need_convert, char *rec_buf,
+               int *recsize, char *save_rec);
+
+/*
+ * Please use iam_open before use this function.
+ */
+int iam_delete(int fd, struct iam_uapi_info *ua,
+               int key_need_convert, char *keybuf,
+               int rec_need_convert, char *recbuf);
+
+/*
+ * Please use iam_open before use this function.
+ */
+int iam_it_start(int fd, struct iam_uapi_info *ua,
+                 int key_need_convert, char *key_buf,
+                 int *keysize, char *save_key,
+                 int rec_need_convert, char *rec_buf,
+                 int *recsize, char *save_rec);
+
+/*
+ * Please use iam_open before use this function.
+ */
+int iam_it_next(int fd, struct iam_uapi_info *ua,
+                int key_need_convert, char *key_buf,
+                int *keysize, char *save_key,
+                int rec_need_convert, char *rec_buf,
+                int *recsize, char *save_rec);
+
+/*
+ * Please use iam_open before use this function.
+ */
+int iam_it_stop(int fd, struct iam_uapi_info *ua,
+                int key_need_convert, char *keybuf,
+                int rec_need_convert, char *recbuf);
+
+/*
+ * Change iam file mode.
+ */
+int iam_polymorph(char *filename, unsigned long mode);
+
+
+#endif
index efd09f3..9d7444c 100644 (file)
@@ -17,8 +17,8 @@ rootsbin_PROGRAMS = mount.lustre
 sbin_PROGRAMS = lctl obdio obdbarrier lload wirecheck wiretest \
        mount_lustre mkfs_lustre mkfs.lustre \
        tunefs_lustre tunefs.lustre l_getgroups
-bin_PROGRAMS = lfs llog_reader create_iam req_layout
-lib_LIBRARIES = liblustreapi.a
+bin_PROGRAMS = lfs llog_reader req_layout
+lib_LIBRARIES = liblustreapi.a libiam.a
 sbin_SCRIPTS = $(sbin_scripts)
 bin_SCRIPTS = $(bin_scripts)
 endif # UTILS
@@ -36,6 +36,7 @@ lload_LDADD := $(LIBREADLINE) $(LIBPTLCTL)
 lload_DEPENDENCIES := $(LIBPTLCTL)
 
 liblustreapi_a_SOURCES = liblustreapi.c
+libiam_a_SOURCES = libiam.c
 
 wirecheck_SOURCES = wirecheck.c
 wirecheck_CPPFLAGS = -DCC="\"$(CC)\""
@@ -44,7 +45,6 @@ wiretest_SOURCES = wiretest.c
 
 obdio_SOURCES = obdio.c obdiolib.c obdiolib.h
 obdbarrier_SOURCES = obdbarrier.c obdiolib.c obdiolib.h
-create_iam_SOURCES = create_iam.c
 req_layout_SOURCES = req-layout.c
 
 llog_reader_SOURCES = llog_reader.c
@@ -57,8 +57,8 @@ mount_lustre_DEPENDENCIES := $(LIBPTLCTL)
 
 mkfs_lustre_SOURCES = mkfs_lustre.c
 mkfs_lustre_CPPFLAGS = -UTUNEFS $(AM_CPPFLAGS)
-mkfs_lustre_LDADD := $(LIBPTLCTL)
-mkfs_lustre_DEPENDENCIES := $(LIBPTLCTL)
+mkfs_lustre_LDADD := libiam.a $(LIBPTLCTL)
+mkfs_lustre_DEPENDENCIES := $(LIBPTLCTL) libiam.a
 
 tunefs_lustre_SOURCES = $(mkfs_lustre_SOURCES)
 tunefs_lustre_CPPFLAGS = -DTUNEFS $(AM_CPPFLAGS)
diff --git a/lustre/utils/libiam.c b/lustre/utils/libiam.c
new file mode 100644 (file)
index 0000000..7202187
--- /dev/null
@@ -0,0 +1,589 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ *  libiam.c
+ *  iam user level library
+ *
+ *   Copyright (c) 2006 Cluster File Systems, Inc.
+ *   Author: Wang Di <wangdi@clusterfs.com>
+ *   Author: Nikita Danilov <nikita@clusterfs.com>
+ *   Author: Fan Yong <fanyong@clusterfs.com>
+ *
+ *   This file is part of the Lustre file system, http://www.lustre.org
+ *   Lustre is a trademark of Cluster File Systems, Inc.
+ *
+ *   You may have signed or agreed to another license before downloading
+ *   this software.  If so, you are bound by the terms and conditions
+ *   of that agreement, and the following does not apply to you.  See the
+ *   LICENSE file included with this distribution for more information.
+ *
+ *   If you did not agree to a different license, then this copy of Lustre
+ *   is open source software; you can redistribute it and/or modify it
+ *   under the terms of version 2 of the GNU General Public License as
+ *   published by the Free Software Foundation.
+ *
+ *   In either case, Lustre is distributed in the hope that it will be
+ *   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ *   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   license text for more details.
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+
+#include <sys/types.h>
+
+#ifdef HAVE_ENDIAN_H
+#include <endian.h>
+#endif
+
+#include <libcfs/libcfs.h>
+
+#include <lustre/libiam.h>
+
+typedef __u32 lvar_hash_t;
+
+enum {
+        IAM_LFIX_ROOT_MAGIC = 0xbedabb1edULL,
+        IAM_LVAR_ROOT_MAGIC = 0xb01dface
+};
+
+struct iam_lfix_root {
+        u_int64_t  ilr_magic;
+        u_int16_t  ilr_keysize;
+        u_int16_t  ilr_recsize;
+        u_int16_t  ilr_ptrsize;
+        u_int16_t  ilr_indirect_levels;
+};
+
+enum {
+        IAM_LEAF_HEADER_MAGIC = 0x1976,
+        IAM_LVAR_LEAF_MAGIC   = 0x1973
+};
+
+struct iam_leaf_head {
+        u_int16_t ill_magic;
+        u_int16_t ill_count;
+};
+
+struct dx_countlimit {
+        u_int16_t limit;
+        u_int16_t count;
+};
+
+struct lvar_leaf_header {
+        u_int16_t vlh_magic; /* magic number IAM_LVAR_LEAF_MAGIC */
+        u_int16_t vlh_used;  /* used bytes, including header */
+};
+
+struct lvar_root {
+        u_int32_t vr_magic;
+        u_int16_t vr_recsize;
+        u_int16_t vr_ptrsize;
+        u_int8_t  vr_indirect_levels;
+        u_int8_t  vr_padding0;
+        u_int16_t vr_padding1;
+};
+
+struct lvar_leaf_entry {
+        u_int32_t vle_hash;
+        u_int16_t vle_keysize;
+        u_int8_t  vle_key[0];
+};
+
+enum {
+        LVAR_PAD   = 4,
+        LVAR_ROUND = LVAR_PAD - 1
+};
+
+static void lfix_root(void *buf,
+                      int blocksize, int keysize, int ptrsize, int recsize)
+{
+        struct iam_lfix_root *root;
+        struct dx_countlimit *limit;
+        void                 *entry;
+
+        root = buf;
+        *root = (typeof(*root)) {
+                .ilr_magic           = cpu_to_le64(IAM_LFIX_ROOT_MAGIC),
+                .ilr_keysize         = cpu_to_le16(keysize),
+                .ilr_recsize         = cpu_to_le16(recsize),
+                .ilr_ptrsize         = cpu_to_le16(ptrsize),
+                .ilr_indirect_levels = 0
+        };
+
+        limit = (void *)(root + 1);
+        *limit = (typeof(*limit)){
+                /*
+                 * limit itself + one pointer to the leaf.
+                 */
+                .count = cpu_to_le16(2),
+                .limit = (blocksize - sizeof *root) / (keysize + ptrsize)
+        };
+
+        entry = root + 1;
+        /*
+         * Skip over @limit.
+         */
+        entry += keysize + ptrsize;
+
+        /*
+         * Entry format is <key> followed by <ptr>. In the minimal tree
+         * consisting of a root and single node, <key> is a minimal possible
+         * key.
+         *
+         * XXX: this key is hard-coded to be a sequence of 0's.
+         */
+        entry += keysize;
+        /* now @entry points to <ptr> */
+        if (ptrsize == 4)
+                *(u_int32_t *)entry = cpu_to_le32(1);
+        else
+                *(u_int64_t *)entry = cpu_to_le64(1);
+}
+
+static void lfix_leaf(void *buf,
+                      int blocksize, int keysize, int ptrsize, int recsize)
+{
+        struct iam_leaf_head *head;
+
+        /* form leaf */
+        head = buf;
+        *head = (struct iam_leaf_head) {
+                .ill_magic = cpu_to_le16(IAM_LEAF_HEADER_MAGIC),
+                /*
+                 * Leaf contains an entry with the smallest possible key
+                 * (created by zeroing).
+                 */
+                .ill_count = cpu_to_le16(1),
+        };
+}
+
+static void lvar_root(void *buf,
+                      int blocksize, int keysize, int ptrsize, int recsize)
+{
+        struct lvar_root *root;
+        struct dx_countlimit *limit;
+        void                 *entry;
+        int isize;
+
+        isize = sizeof(lvar_hash_t) + ptrsize;
+        root = buf;
+        *root = (typeof(*root)) {
+                .vr_magic            = cpu_to_le32(IAM_LVAR_ROOT_MAGIC),
+                .vr_recsize          = cpu_to_le16(recsize),
+                .vr_ptrsize          = cpu_to_le16(ptrsize),
+                .vr_indirect_levels  = 0
+        };
+
+        limit = (void *)(root + 1);
+        *limit = (typeof(*limit)){
+                /*
+                 * limit itself + one pointer to the leaf.
+                 */
+                .count = cpu_to_le16(2),
+                .limit = (blocksize - sizeof *root) / isize
+        };
+
+        entry = root + 1;
+        /*
+         * Skip over @limit.
+         */
+        entry += isize;
+
+        /*
+         * Entry format is <key> followed by <ptr>. In the minimal tree
+         * consisting of a root and single node, <key> is a minimal possible
+         * key.
+         *
+         * XXX: this key is hard-coded to be a sequence of 0's.
+         */
+        entry += sizeof(lvar_hash_t);
+        /* now @entry points to <ptr> */
+        if (ptrsize == 4)
+                *(u_int32_t *)entry = cpu_to_le32(1);
+        else
+                *(u_int64_t *)entry = cpu_to_le64(1);
+}
+
+static int lvar_esize(int namelen, int recsize)
+{
+        return (offsetof(struct lvar_leaf_entry, vle_key) +
+                namelen + recsize + LVAR_ROUND) & ~LVAR_ROUND;
+}
+
+static void lvar_leaf(void *buf,
+                      int blocksize, int keysize, int ptrsize, int recsize)
+{
+        struct lvar_leaf_header *head;
+
+        /* form leaf */
+        head = buf;
+        *head = (typeof(*head)) {
+                .vlh_magic = cpu_to_le16(IAM_LVAR_LEAF_MAGIC),
+                .vlh_used  = cpu_to_le16(sizeof *head + lvar_esize(0, recsize))
+        };
+}
+
+
+struct iam_uapi_op {
+        void *iul_key;
+        void *iul_rec;
+};
+
+struct iam_uapi_it {
+        struct iam_uapi_op iui_op;
+        __u16              iui_state;
+};
+
+enum iam_ioctl_cmd {
+        IAM_IOC_INIT      = _IOW('i', 1, struct iam_uapi_info),
+        IAM_IOC_GETINFO   = _IOR('i', 2, struct iam_uapi_info),
+        IAM_IOC_INSERT    = _IOR('i', 3, struct iam_uapi_op),
+        IAM_IOC_LOOKUP    = _IOWR('i', 4, struct iam_uapi_op),
+        IAM_IOC_DELETE    = _IOR('i', 5, struct iam_uapi_op),
+        IAM_IOC_IT_START  = _IOR('i', 6, struct iam_uapi_it),
+        IAM_IOC_IT_NEXT   = _IOW('i', 7, struct iam_uapi_it),
+        IAM_IOC_IT_STOP   = _IOR('i', 8, struct iam_uapi_it),
+        IAM_IOC_POLYMORPH = _IOR('i', 9, unsigned long)
+};
+
+static unsigned char hex2dec(unsigned char hex)
+{
+        if (('0' <= hex) && (hex <= '9'))
+                return hex - '0';
+        else if (('a' <= hex) && (hex <= 'f'))
+                return hex - 'a' + 10;
+        else if (('A' <= hex) && (hex <= 'F'))
+                return hex - 'A' + 10;
+        else
+                exit(1);
+}
+
+static unsigned char *packdigit(unsigned char *number)
+{
+        unsigned char *area;
+        unsigned char *scan;
+
+        area = calloc(strlen(number) / 2 + 2, sizeof(char));
+        if (area != NULL) {
+                for (scan = area; *number; number += 2, scan++)
+                        *scan = (hex2dec(number[0]) << 4) | hex2dec(number[1]);
+        }
+        return area;
+}
+
+
+static char *iam_convert(int size, int need_convert, char *source)
+{
+        char *ptr;
+        char *opt;
+
+        if (source == NULL)
+                return NULL;
+
+        ptr = calloc(size + 1, sizeof(char));
+        if (ptr == NULL)
+                return NULL;
+
+        if (need_convert) {
+                opt = packdigit(source);
+                if (opt == NULL) {
+                        free(ptr);
+                        return NULL;
+                } else {
+                        memcpy(ptr, opt, size + 1);
+                        free(opt);
+                }
+        } else {
+                strncpy(ptr, source, size + 1);
+        }
+
+        return ptr;
+}
+
+static int iam_doop(int fd, struct iam_uapi_info *ua, int cmd,
+                    int key_need_convert, char *key_buf,
+                    int *keysize, char *save_key,
+                    int rec_need_convert, char *rec_buf,
+                    int *recsize, char *save_rec)
+{
+        int ret;
+        char *key;
+        char *rec;
+        struct iam_uapi_op op;
+
+        key = iam_convert(ua->iui_keysize, key_need_convert, key_buf);
+        if (key == NULL)
+                return -1;
+
+        rec = iam_convert(ua->iui_recsize, rec_need_convert, rec_buf);
+        if (rec == NULL) {
+                free(key);
+                return -1;
+        }
+
+        op.iul_key = key;
+        op.iul_rec = rec;
+        ret = ioctl(fd, cmd, &op);
+        if (ret == 0) {
+                if ((keysize != NULL) && (*keysize > 0) && (save_key != NULL)) {
+                        if (*keysize > ua->iui_keysize)
+                                *keysize = ua->iui_keysize;
+                        memcpy(save_key, key, *keysize);
+                }
+                if ((recsize != NULL) && (*recsize > 0) && (save_rec != NULL)) {
+                        if (*recsize > ua->iui_recsize)
+                                *recsize = ua->iui_recsize;
+                        memcpy(save_rec, rec, *recsize);
+                }
+        }
+        free(key);
+        free(rec);
+        return ret;
+}
+
+
+/*
+ * Creat an iam file, but do NOT open it.
+ * Return 0 if success, else -1.
+ */
+int iam_creat(char *filename, enum iam_fmt_t fmt,
+              int blocksize, int keysize, int recsize, int ptrsize)
+{
+        int fd;
+        char *buf;
+
+        if (filename == NULL) {
+                errno = EINVAL;
+                return -1;
+        }
+
+        if ((fmt != FMT_LFIX) && (fmt != FMT_LVAR)) {
+                errno = EOPNOTSUPP;
+                return -1;
+        }
+
+        if (blocksize == SET_DEFAULT) {
+                blocksize = 4096;
+        } else if (blocksize <= 100) {
+                errno = EINVAL;
+                return -1;
+        }
+
+        if (keysize == SET_DEFAULT) {
+                keysize = 8;
+        } else if (keysize < 1) {
+                errno = EINVAL;
+                return -1;
+        }
+
+        if (recsize == SET_DEFAULT) {
+                recsize = 8;
+        } else if (recsize < 0) {
+                errno = EINVAL;
+                return -1;
+        }
+
+        if (ptrsize == SET_DEFAULT) {
+                ptrsize = 4;
+        } else if ((ptrsize != 4) && (ptrsize != 8)) {
+                errno = EINVAL;
+                return -1;
+        }
+
+        if ((keysize + recsize + sizeof(struct iam_leaf_head)) > (blocksize / 3)) {
+                errno = EINVAL;
+                return -1;
+        }
+
+        fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0600);
+        if (fd < 0) {
+                return -1;
+        }
+
+        buf = malloc(blocksize);
+        if (buf == NULL) {
+                close(fd);
+                return -1;
+        }
+
+        memset(buf, 0, blocksize);
+        if (fmt == FMT_LFIX)
+                lfix_root(buf, blocksize, keysize, ptrsize, recsize);
+        else
+                lvar_root(buf, blocksize, keysize, ptrsize, recsize);
+
+        if (write(fd, buf, blocksize) != blocksize) {
+                close(fd);
+                free(buf);
+                return -1;
+        }
+
+        memset(buf, 0, blocksize);
+        if (fmt == FMT_LFIX)
+                lfix_leaf(buf, blocksize, keysize, ptrsize, recsize);
+        else
+                lvar_leaf(buf, blocksize, keysize, ptrsize, recsize);
+
+        if (write(fd, buf, blocksize) != blocksize) {
+                close(fd);
+                free(buf);
+                return -1;
+        }
+
+        close(fd);
+        free(buf);
+        return 0;
+}
+
+/*
+ * Open an iam file, but do NOT creat it if the file doesn't exist.
+ * Please use iam_creat for creating the file before use iam_open.
+ * Return file id (fd) if success, else -1.
+ */
+int iam_open(char *filename, struct iam_uapi_info *ua)
+{
+        int fd;
+
+        if (filename == NULL) {
+                errno = EINVAL;
+                return -1;
+        }
+
+        if (ua == NULL) {
+                errno = EINVAL;
+                return -1;
+        }
+
+        fd = open(filename, O_RDONLY);
+        if (fd < 0) {
+                return -1;
+        }
+
+        if (ioctl(fd, IAM_IOC_INIT, ua) != 0) {
+                close(fd);
+                return -1;
+        }
+
+        if (ioctl(fd, IAM_IOC_GETINFO, ua) != 0) {
+                close(fd);
+                return -1;
+        }
+
+        return fd;
+}
+
+/*
+ * Close file opened by iam_open. 
+ */
+int iam_close(int fd)
+{
+        return close(fd);
+}
+
+/*
+ * Please use iam_open before use this function.
+ */
+int iam_insert(int fd, struct iam_uapi_info *ua,
+               int key_need_convert, char *key_buf,
+               int rec_need_convert, char *rec_buf)
+{
+        return iam_doop(fd, ua, IAM_IOC_INSERT,
+                        key_need_convert, key_buf, NULL, NULL,
+                        rec_need_convert, rec_buf, NULL, NULL);
+}
+
+/*
+ * Please use iam_open before use this function.
+ */
+int iam_lookup(int fd, struct iam_uapi_info *ua,
+               int key_need_convert, char *key_buf,
+               int *keysize, char *save_key,
+               int rec_need_convert, char *rec_buf,
+               int *recsize, char *save_rec)
+{
+        return iam_doop(fd, ua, IAM_IOC_LOOKUP,
+                       key_need_convert, key_buf, keysize, save_key,
+                       rec_need_convert, rec_buf, recsize, save_rec);
+}
+
+/*
+ * Please use iam_open before use this function.
+ */
+int iam_delete(int fd, struct iam_uapi_info *ua,
+               int key_need_convert, char *key_buf,
+               int rec_need_convert, char *rec_buf)
+{
+        return iam_doop(fd, ua, IAM_IOC_DELETE,
+                        key_need_convert, key_buf, NULL, NULL,
+                        rec_need_convert, rec_buf, NULL, NULL);
+}
+
+/*
+ * Please use iam_open before use this function.
+ */
+int iam_it_start(int fd, struct iam_uapi_info *ua,
+                 int key_need_convert, char *key_buf,
+                 int *keysize, char *save_key,
+                 int rec_need_convert, char *rec_buf,
+                 int *recsize, char *save_rec)
+{
+        return iam_doop(fd, ua, IAM_IOC_IT_START,
+                       key_need_convert, key_buf, keysize, save_key,
+                       rec_need_convert, rec_buf, recsize, save_rec);
+}
+
+/*
+ * Please use iam_open before use this function.
+ */
+int iam_it_next(int fd, struct iam_uapi_info *ua,
+                int key_need_convert, char *key_buf,
+                int *keysize, char *save_key,
+                int rec_need_convert, char *rec_buf,
+                int *recsize, char *save_rec)
+{
+        return iam_doop(fd, ua, IAM_IOC_IT_NEXT,
+                       key_need_convert, key_buf, keysize, save_key,
+                       rec_need_convert, rec_buf, recsize, save_rec);
+}
+
+/*
+ * Please use iam_open before use this function.
+ */
+int iam_it_stop(int fd, struct iam_uapi_info *ua,
+                int key_need_convert, char *key_buf,
+                int rec_need_convert, char *rec_buf)
+{
+        return iam_doop(fd, ua, IAM_IOC_IT_STOP,
+                        key_need_convert, key_buf, NULL, NULL,
+                        rec_need_convert, rec_buf, NULL, NULL);
+}
+
+/*
+ * Change iam file mode.
+ */
+int iam_polymorph(char *filename, unsigned long mode)
+{
+        int fd;
+        int ret;
+
+        if (filename == NULL) {
+                errno = EINVAL;
+                return -1;
+        }
+
+        fd = open(filename, O_RDONLY);
+        if (fd < 0) {
+                return -1;
+        }
+
+        ret = ioctl(fd, IAM_IOC_POLYMORPH, mode);
+        close(fd);
+        return ret;
+}