From: fanyong Date: Thu, 10 Aug 2006 03:09:10 +0000 (+0000) Subject: For iam lib. X-Git-Tag: v1_8_0_110~486^2~1224 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=7bf8bf89f90471e070879e353da6bba4c704615f;p=fs%2Flustre-release.git For iam lib. --- diff --git a/lustre/include/lustre/Makefile.am b/lustre/include/lustre/Makefile.am index 0acd90f..09b9290 100644 --- a/lustre/include/lustre/Makefile.am +++ b/lustre/include/lustre/Makefile.am @@ -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 index 0000000..06c82b8 --- /dev/null +++ b/lustre/include/lustre/libiam.h @@ -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 + * Author: Nikita Danilov + * Author: Fan Yong + * + * 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 diff --git a/lustre/utils/Makefile.am b/lustre/utils/Makefile.am index efd09f3..9d7444c 100644 --- a/lustre/utils/Makefile.am +++ b/lustre/utils/Makefile.am @@ -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 index 0000000..7202187 --- /dev/null +++ b/lustre/utils/libiam.c @@ -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 + * Author: Nikita Danilov + * Author: Fan Yong + * + * 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 +#include +#include +#include +#include +#include +#include + +#include + +#ifdef HAVE_ENDIAN_H +#include +#endif + +#include + +#include + +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 followed by . In the minimal tree + * consisting of a root and single node, is a minimal possible + * key. + * + * XXX: this key is hard-coded to be a sequence of 0's. + */ + entry += keysize; + /* now @entry points to */ + 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 followed by . In the minimal tree + * consisting of a root and single node, 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 */ + 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; +}