From: fanyong Date: Mon, 7 Aug 2006 03:08:57 +0000 (+0000) Subject: mkfs_lustre.c X-Git-Tag: v1_8_0_110~486^2~1254 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=738ee72e31244a8e433510b30ffa9704cb398a40;p=fs%2Flustre-release.git mkfs_lustre.c --- diff --git a/lustre/utils/mkfs_lustre.c b/lustre/utils/mkfs_lustre.c index 114fd04..6d28548 100644 --- a/lustre/utils/mkfs_lustre.c +++ b/lustre/utils/mkfs_lustre.c @@ -853,6 +853,10 @@ static char *convert_hostnames(char *s1) lnet_nid_t nid; converted = malloc(left); + if (converted == NULL) { + return NULL; + } + c = converted; while ((left > 0) && ((s2 = strsep(&s1, ",: \0")))) { nid = libcfs_str2nid(s2); @@ -1060,6 +1064,644 @@ int parse_opts(int argc, char *const argv[], struct mkfs_opts *mop, return 0; } + +#include +#include + +#ifdef HAVE_ENDIAN_H +#include +#endif + +#include + +/* Move from create_iam.c */ +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; +}; + +typedef __u32 lvar_hash_t; + +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)) + }; +} + +enum iam_fmt_t { + FMT_LFIX, + FMT_LVAR +}; + +static int create_iam(enum iam_fmt_t fmt, int keysize, int recsize, + char *target) +{ + int rc; + int blocksize = 4096; + int ptrsize = 4; + int fd = -1; + void *buf = NULL; + + if ((fmt != FMT_LFIX) && (fmt != FMT_LVAR)) { + fprintf(stderr, "Wrong format %i\n", (int)fmt); + return 1; + } + + if (keysize <= 0) { + keysize = 8; + } + + if (recsize <= 0) { + recsize = 8; + } + + if (target == NULL) { + fprintf(stderr, "Target must not be NULL\n"); + return 1; + } + + if (keysize + recsize + sizeof(struct iam_leaf_head) > blocksize / 3) { + fprintf(stderr, "Too large (record, key) or too small block\n"); + return 1; + } + + vprint("fmt: %i, key: %i, rec: %i, ptr: %i, block: %i\n", + (int)fmt, keysize, recsize, ptrsize, blocksize); + + fd = open(target, O_WRONLY | O_TRUNC | O_CREAT, 0600); + if (fd < 0) { + fprintf(stderr, "%s: failed to open %s, errno = %d\n", + __FUNCTION__, target, errno); + return 1; + } + + buf = malloc(blocksize); + if (buf == NULL) { + fprintf(stderr, "Unable to allocate %i bytes\n", blocksize); + 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); + } + + rc = write(fd, buf, blocksize); + if (rc != blocksize) { + fprintf(stderr, "Unable to write root node: %m (%i)\n", rc); + rc = 1; + goto out; + } + + /* form leaf */ + memset(buf, 0, blocksize); + if (fmt == FMT_LFIX) { + lfix_leaf(buf, blocksize, keysize, ptrsize, recsize); + } else { + lvar_leaf(buf, blocksize, keysize, ptrsize, recsize); + } + + rc = write(fd, buf, blocksize); + if (rc != blocksize) { + fprintf(stderr, "Unable to write leaf node: %m (%i)\n", rc); + rc = 1; + goto out; + } + + rc = 0; + +out: + close(fd); + free(buf); + return rc; +} +/* End of create_iam.c */ + +/* Copy from iam_ut.c */ +enum { + /* + * Maximal format name length. + */ + DX_FMT_NAME_LEN = 16 +}; + +struct iam_uapi_info { + __u16 iui_keysize; + __u16 iui_recsize; + __u16 iui_ptrsize; + __u16 iui_height; + char iui_fmt_name[DX_FMT_NAME_LEN]; +}; + +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_POLYMORPH = _IOR('i', 9, unsigned long) +}; + +static int doop(int fd, const void *key, const void *rec, + int cmd, const char *name) +{ + int result; + + struct iam_uapi_op op = { + .iul_key = key, + .iul_rec = rec + }; + result = ioctl(fd, cmd, &op); + if (result != 0) + fprintf(stderr, "ioctl(%s): %i/%i (%m)\n", name, result, errno); + return result; +} + +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 { + fprintf(stderr, "Wrong hex digit '%c'\n", hex); + exit(1); + } +} + +static unsigned char *packdigit(unsigned char *number) +{ + unsigned char *area; + unsigned char *scan; + + area = calloc(strlen(number) / 2 + 2, sizeof area[0]); + if (area != NULL) { + for (scan = area; *number; number += 2, scan++) + *scan = (hex2dec(number[0]) << 4) | hex2dec(number[1]); + } + return area; +} + +static int iam_insert(int key_need_convert, char *keybuf, + int rec_need_convert, char *recbuf, char *source) +{ + int rc; + int keysize; + int recsize; + int fd = -1; + char *key_opt; + char *rec_opt; + char *key = NULL; + char *rec = NULL; + void *(*copier)(void *, void *, size_t); + struct iam_uapi_info ua; + + if (key_need_convert) { + key_opt = packdigit(keybuf); + } else { + key_opt = keybuf; + } + + if (rec_need_convert) { + rec_opt = packdigit(recbuf); + } else { + rec_opt = recbuf; + } + + if (source == NULL) { + fprintf(stderr, "source must not be NULL\n"); + return 1; + } + + fd = open(source, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "%s: failed to open %s, errno = %d\n", + __FUNCTION__, source, errno); + rc = 1; + goto out; + } + + rc = ioctl(fd, IAM_IOC_INIT, &ua); + if (rc != 0) { + fprintf(stderr, "ioctl(IAM_IOC_INIT): %i (%m)\n", rc); + rc = 1; + goto out; + } + + rc = ioctl(fd, IAM_IOC_GETINFO, &ua); + if (rc != 0) { + fprintf(stderr, "ioctl(IAM_IOC_GETATTR): %i (%m)\n", rc); + rc = 1; + goto out; + } + + keysize = ua.iui_keysize; + recsize = ua.iui_recsize; + vprint("keysize: %i, recsize: %i, ptrsize: %i, " + "height: %i, name: %s\n", + keysize, recsize, ua.iui_ptrsize, + ua.iui_height, ua.iui_fmt_name); + + key = calloc(keysize + 1, sizeof key[0]); + rec = calloc(recsize + 1, sizeof rec[0]); + if ((key == NULL) || (rec == NULL)) { + fprintf(stderr, "cannot allocate memory\n"); + rc = 1; + goto out; + } + + copier = (key_need_convert == 0) ? &strncpy : &memcpy; + copier(key, key_opt ? : "RIVERRUN", keysize + 1); + if (key_need_convert) { + free(key_opt); + key_opt = NULL; + } + + copier = (rec_need_convert == 0) ? &strncpy : &memcpy; + copier(rec, rec_opt ? : "PALEFIRE", recsize + 1); + if (rec_need_convert) { + free(rec_opt); + rec_opt = NULL; + } + + rc = doop(fd, key, rec, IAM_IOC_INSERT, "IAM_IOC_INSERT"); + +out: + if (fd >= 0) { + close(fd); + } + if (key != NULL) { + free(key); + } + if (rec != NULL) { + free(rec); + } + return rc; +} +/* End of iam_ut.c */ + +#define LDISKFS_IOC_GETVERSION _IOR('f', 3, long) + +static int touch_file(char *filename) +{ + int fd; + + if (filename == NULL) { + return 1; + } + + fd = open(filename, O_CREAT | O_TRUNC, 0600); + if (fd < 0) { + return 1; + } else { + close(fd); + return 0; + } +} + +static int get_generation(char *filename, unsigned long *result) +{ + int fd; + int ret; + + if (filename == NULL) { + return 1; + } + + fd = open(filename, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "%s: failed to open %s\n", + __FUNCTION__, filename); + return 1; + } + + ret = ioctl(fd, LDISKFS_IOC_GETVERSION, result); + close(fd); + + return ((ret < 0) ? ret : 0); +} + +static int mkfs_mdt(struct mkfs_opts *mop) +{ + char mntpt[] = "/tmp/mntXXXXXX"; + char fstype[] = "ldiskfs"; + char filepnm[128]; + char recbuf[64]; + char *source; + int ret; + int fd; + unsigned long generation; + struct stat st; + + source = mop->mo_device; + if (mop->mo_flags & MO_IS_LOOP) { + source = mop->mo_loopdev; + } + + if ((source == NULL) || (*source == 0)) { + return 1; + } + + if (!mkdtemp(mntpt)) { + fprintf(stderr, "%s: failed to mkdtemp %s\n", + __FUNCTION__, mntpt); + return errno; + } + + ret = mount(source, mntpt, fstype, 0, NULL); + if (ret) { + goto out_rmdir; + } + + snprintf(filepnm, sizeof(filepnm) - 1, "%s/%s", mntpt, "seq"); + ret = touch_file(filepnm); + if (ret) { + goto out_umount; + } + + snprintf(filepnm, sizeof(filepnm) - 1, "%s/%s", mntpt, "last_rcvd"); + ret = touch_file(filepnm); + if (ret) { + goto out_umount; + } + + snprintf(filepnm, sizeof(filepnm) - 1, "%s/%s", mntpt, "lov_objid"); + ret = touch_file(filepnm); + if (ret) { + goto out_umount; + } + + snprintf(filepnm, sizeof(filepnm) - 1, "%s/%s", mntpt, "root"); + ret = create_iam(FMT_LVAR, 0, 16, filepnm); + if (ret) { + goto out_umount; + } + + snprintf(filepnm, sizeof(filepnm) - 1, "%s/%s", mntpt, "fld"); + ret = create_iam(FMT_LFIX, 8, 8, filepnm); + if (ret) { + goto out_umount; + } + + snprintf(filepnm, sizeof(filepnm) - 1, "%s/%s", mntpt, "oi"); + ret = create_iam(FMT_LFIX, 16, 16, filepnm); + if (ret) { + goto out_umount; + } + + umount(mntpt); + ret = mount(source, mntpt, fstype, 0, NULL); + if (ret) { + goto out_rmdir; + } + + snprintf(filepnm, sizeof(filepnm) - 1, "%s/%s", mntpt, "root"); + fd = open(filepnm, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "%s: failed to open %s, errno = %d\n", + __FUNCTION__, filepnm, errno); + ret = 1; + goto out_umount; + } + + ret = ioctl(fd, IAM_IOC_POLYMORPH, 040700); + close(fd); + if (ret) { + perror("IAM_IOC_POLYMORPH"); + goto out_umount; + } + + umount(mntpt); + ret = mount(source, mntpt, fstype, 0, NULL); + if (ret) { + goto out_rmdir; + } + + snprintf(filepnm, sizeof(filepnm) - 1, "%s/%s", mntpt, "fld"); + ret = iam_insert(1, "0000000000000002", 1, "0000000000000000", filepnm); + if (ret) { + goto out_umount; + } + + ret = iam_insert(1, "0000000000000001", 1, "0000000000000000", filepnm); + if (ret) { + goto out_umount; + } + + snprintf(filepnm, sizeof(filepnm) - 1, "%s/%s", mntpt, "root"); + ret = stat(filepnm, &st); + if (ret) { + goto out_umount; + } + + ret = get_generation(filepnm, &generation); + if (ret) { + goto out_umount; + } + + snprintf(recbuf, sizeof(recbuf) - 1, "0000000000000001%8.8x%8.8x", + (unsigned int)generation, (unsigned int)st.st_ino); + ret = iam_insert(0, ".", 1, recbuf, filepnm); + if (ret) { + goto out_umount; + } + + ret = iam_insert(0, "..", 1, recbuf, filepnm); + if (ret) { + goto out_umount; + } + +out_umount: + umount(mntpt); +out_rmdir: + rmdir(mntpt); + return ret; +} + int main(int argc, char *const argv[]) { struct mkfs_opts mop; @@ -1275,6 +1917,14 @@ int main(int argc, char *const argv[]) goto out; } + if (IS_MDT(ldd)) { + ret = mkfs_mdt(&mop); + if (ret != 0) { + fprintf(stderr, "failed to mkfs_mdt\n"); + goto out; + } + } + out: loop_cleanup(&mop); return ret;