int ftfs_bstore_update_ino(struct ftfs_sb_info *sbi, ino_t ino) { DB_TXN *txn; int ret; ino_t curr_ino; DBT next_ino_key_dbt, next_ino_value_dbt; dbt_init(&next_ino_key_dbt, &next_ino_meta_key, SIZEOF_KEY(next_ino_meta_key)); dbt_init(&next_ino_value_dbt, &curr_ino, sizeof(curr_ino)); TXN_GOTO_LABEL(retry); { ftfs_bstore_txn_begin(sbi->db_env, NULL, &txn, TXN_MAY_WRITE); ret = sbi->meta_db->get(sbi->meta_db, txn, &next_ino_key_dbt, &next_ino_value_dbt, DB_GET_FLAGS); if (!ret && ino > curr_ino) { curr_ino = ino; ret = sbi->meta_db->put(sbi->meta_db, txn, &next_ino_key_dbt, &next_ino_value_dbt, DB_PUT_FLAGS); } } if (ret) { DBOP_JUMP_ON_CONFLICT(ret, retry); } ret = ftfs_bstore_txn_commit(txn, DB_TXN_NOSYNC); COMMIT_JUMP_ON_CONFLICT(ret, retry); return ret; }
int main(void) { int one = 1; if (*(unsigned char *) &one == 1) { printf("little endian\n"); } else { printf("big endian\n"); } const int len = 25; unsigned char a[len], b[len]; DBT ax, bx; dbt_init(&ax, a, sizeof(a)); dbt_init(&bx, b, sizeof(b)); srand(time(NULL)); for (int i = 0; i < len; i++) { a[i] = rand() & 0xFF; for (int j = 0; j < len; j++) { b[i] = rand() & 0xFF; int tokucmp = toku_keycompare(a, len, b, len); int mycmp = keycmp(NULL, &ax, &bx); if ((tokucmp < 0) != (mycmp < 0)) { doerror(tokucmp, mycmp, a, len, b, len); } if ((tokucmp == 0) != (mycmp == 0)) { doerror(tokucmp, mycmp, a, len, b, len); } if ((tokucmp > 0) != (mycmp > 0)) { doerror(tokucmp, mycmp, a, len, b, len); } } } return 0; }
int ftfs_bstore_data_hot_flush(DB *data_db, struct ftfs_meta_key *meta_key, uint64_t start, uint64_t end) { int ret; DBT start_key, end_key; uint64_t loops; struct ftfs_data_key *start_data_key, *end_data_key; start_data_key = alloc_data_key_from_meta_key(meta_key, start); if (start_data_key == NULL) return -ENOMEM; end_data_key = alloc_data_key_from_meta_key(meta_key, end); if (end_data_key == NULL) { ret = -ENOMEM; goto out; } dbt_init(&start_key, start_data_key, SIZEOF_KEY(*start_data_key)); dbt_init(&end_key, end_data_key, SIZEOF_KEY(*end_data_key)); ret = data_db->hot_optimize(data_db, &start_key, &end_key, NULL, NULL, &loops); ftfs_log(__func__, "hot optimized(%llu, %s, %llu, %llu): %d\n", meta_key_get_circle_id(meta_key), meta_key_get_path(meta_key), start, end, ret); data_key_free(end_data_key); out: data_key_free(start_data_key); return ret; }
int ftfs_bstore_truncate(DB *data_db, struct ftfs_meta_key *meta_key, DB_TXN *txn, uint64_t min_num, uint64_t max_num) { int ret; struct ftfs_data_key *min_data_key, *max_data_key; DBT min_data_key_dbt, max_data_key_dbt; min_data_key = alloc_data_key_from_meta_key(meta_key, min_num); if (!min_data_key) return -ENOMEM; max_data_key = alloc_data_key_from_meta_key(meta_key, max_num); if (!max_data_key) { ret = -ENOMEM; goto out; } dbt_init(&min_data_key_dbt, min_data_key, SIZEOF_KEY(*min_data_key)); dbt_init(&max_data_key_dbt, max_data_key, SIZEOF_KEY(*max_data_key)); ret = data_db->del_multi(data_db, txn, &min_data_key_dbt, &max_data_key_dbt, 0, 0); data_key_free(max_data_key); out: data_key_free(min_data_key); return ret; }
int ftfs_bstore_scan_one_page(DB *data_db, struct ftfs_meta_key *meta_key, DB_TXN *txn, struct page *page) { int ret; uint64_t block_num; size_t block_offset; loff_t offset; size_t len; struct ftfs_data_key *data_key; void *buf, *value_buf; DBT key_dbt, value_dbt; DBC *cursor; offset = page_offset(page); block_num = block_get_num_by_position(offset); data_key = kmalloc(DATA_KEY_MAX_LEN, GFP_KERNEL); if (!data_key) return -ENOMEM; value_buf = kmalloc(FTFS_BSTORE_BLOCKSIZE, GFP_KERNEL); if (!value_buf) { ret = -ENOMEM; goto out1; } copy_data_key_from_meta_key(data_key, meta_key, block_num); dbt_init(&key_dbt, data_key, DATA_KEY_MAX_LEN); dbt_init(&value_dbt, value_buf, FTFS_BSTORE_BLOCKSIZE); len = PAGE_CACHE_SIZE; buf = kmap(page); ret = data_db->cursor(data_db, txn, &cursor, DB_CURSOR_FLAGS); if (ret) goto out2; ret = cursor->c_get(cursor, &key_dbt, &value_dbt, DB_SET_RANGE); while (len > 0 && ret) { ssize_t read_size; block_num = block_get_num_by_position(offset); block_offset = block_get_offset_by_position(offset); read_size = min(len, (FTFS_BSTORE_BLOCKSIZE - block_offset)); if (data_key->circle_id == meta_key->circle_id && !strcmp(data_key->path, meta_key->path) && data_key->block_num == block_num) { memcpy(buf, value_buf, read_size); ret = cursor->c_get(cursor, &key_dbt, &value_dbt, DB_NEXT); } else memset(buf, 0, read_size); buf += read_size; offset += read_size; len -= read_size; } cursor->c_close(cursor); out2: kunmap(page); out1: kfree(value_buf); data_key_free(data_key); return ret; }
int ftfs_bstore_scan_pages(DB *data_db, struct ftfs_meta_key *meta_key, DB_TXN *txn, struct ftio *ftio) { int ret, r; uint64_t block_num; struct ftfs_scan_pages_cb_info info; struct ftfs_data_key *data_key, *prefetch_data_key; DBT key_dbt, prefetch_key_dbt; DBC *cursor; if (ftio_job_done(ftio)) return 0; block_num = ftio_current_page(ftio)->index; data_key = alloc_data_key_from_meta_key(meta_key, block_num); if (!data_key) return -ENOMEM; block_num = ftio_last_page(ftio)->index; prefetch_data_key = alloc_data_key_from_meta_key(meta_key, block_num); if (!prefetch_data_key) { ret = -ENOMEM; goto out; } dbt_init(&key_dbt, data_key, SIZEOF_KEY(*data_key)); dbt_init(&prefetch_key_dbt, prefetch_data_key, SIZEOF_KEY(*prefetch_data_key)); ret = data_db->cursor(data_db, txn, &cursor, DB_CURSOR_FLAGS); if (ret) goto free_out; ret = cursor->c_set_bounds(cursor, &key_dbt, &prefetch_key_dbt, true, 0); if (ret) goto close_cursor; info.meta_key = meta_key; info.ftio = ftio; r = cursor->c_getf_set_range(cursor, 0, &key_dbt, ftfs_scan_pages_cb, &info); while (info.do_continue && !r) r = cursor->c_getf_next(cursor, 0, ftfs_scan_pages_cb, &info); if (r && r != DB_NOTFOUND) ret = r; if (!ret) ftfs_bstore_fill_rest_page(ftio); close_cursor: r = cursor->c_close(cursor); BUG_ON(r); free_out: data_key_free(prefetch_data_key); out: data_key_free(data_key); return ret; }
int ftfs_bstore_meta_put(DB *meta_db, struct ftfs_meta_key *meta_key, DB_TXN *txn, struct ftfs_metadata *metadata) { int ret; DBT key, value; dbt_init(&key, meta_key, SIZEOF_KEY(*meta_key)); dbt_init(&value, metadata, sizeof(struct ftfs_metadata)); ret = meta_db->put(meta_db, txn, &key, &value, DB_PUT_FLAGS); return ret; }
int ftfs_bstore_meta_get(DB *meta_db, struct ftfs_meta_key *meta_key, DB_TXN *txn, struct ftfs_metadata *metadata) { int ret; DBT key, value; dbt_init(&key, meta_key, SIZEOF_KEY(*meta_key)); dbt_init(&value, metadata, sizeof(struct ftfs_metadata)); ret = meta_db->get(meta_db, txn, &key, &value, DB_GET_FLAGS); if (ret == DB_NOTFOUND) ret = -ENOENT; return ret; }
/* * Update callback function * db: the database * key: key dbt of the kv pair * old_val: old_val of the key dbt, if its null, we must create val * extra: the struct we pass to db->update function * set_val: set value function, should be provided by tokudb * set_extra: argument for set_val callback */ static int env_update_cb(DB *db, const DBT *key, const DBT *old_val, const DBT *extra, void (*set_val)(const DBT *newval, void *set_extra), void *set_extra) { int ret; DBT val; size_t newval_size; void *newval; BUG_ON(db == NULL || key == NULL || extra == NULL || extra->data == NULL); // there is no meta update currently BUG_ON(IS_META_KEY_DBT(key)); ret = block_update_cb(&newval, &newval_size, old_val, extra->data); if (!ret) { dbt_init(&val, newval, newval_size); set_val(&val, set_extra); kfree(newval); } return ret; }
int ftfs_directory_is_empty(DB *meta_db, struct ftfs_meta_key *meta_key, DB_TXN *txn, int *is_empty) { int ret, r; struct ftfs_meta_key *start_meta_key; struct ftfs_die_cb_info info; DBT key; DBC *cursor; start_meta_key = alloc_child_meta_key_from_meta_key(meta_key, ""); if (!start_meta_key) return -ENOMEM; dbt_init(&key, start_meta_key, SIZEOF_KEY(*start_meta_key)); ret = meta_db->cursor(meta_db, txn, &cursor, DB_CURSOR_FLAGS); if (ret) goto out; info.meta_key = meta_key; info.is_empty = is_empty; ret = cursor->c_getf_set_range(cursor, 0, &key, ftfs_die_cb, &info); if (ret == DB_NOTFOUND) { ret = 0; *is_empty = 1; } r = cursor->c_close(cursor); BUG_ON(r); out: meta_key_free(start_meta_key); return ret; }
int ftfs_bstore_meta_del(DB *meta_db, struct ftfs_meta_key *meta_key, DB_TXN *txn) { DBT key; dbt_init(&key, meta_key, SIZEOF_KEY(*meta_key)); return meta_db->del(meta_db, txn, &key, DB_DEL_FLAGS); }
int ftfs_bstore_get(DB *data_db, struct ftfs_data_key *data_key, DB_TXN *txn, void *buf) { int ret; DBT key, value; dbt_init(&key, data_key, SIZEOF_KEY(*data_key)); dbt_init(&value, buf, FTFS_BSTORE_BLOCKSIZE); ret = data_db->get(data_db, txn, &key, &value, DB_GET_FLAGS); if (!ret && value.size < FTFS_BSTORE_BLOCKSIZE) memset(buf + value.size, 0, FTFS_BSTORE_BLOCKSIZE - value.size); if (ret == DB_NOTFOUND) ret = -ENOENT; return ret; }
// size of buf must be FTFS_BLOCK_SIZE int ftfs_bstore_put(DB *data_db, struct ftfs_data_key *data_key, DB_TXN *txn, const void *buf, size_t len, int is_seq) { int ret; DBT key, value; dbt_init(&key, data_key, SIZEOF_KEY(*data_key)); dbt_init(&value, buf, len); #if FTFS_USE_SEQ_PUT ret = is_seq ? data_db->seq_put(data_db, txn, &key, &value, DB_PUT_FLAGS) : data_db->put(data_db, txn, &key, &value, DB_PUT_FLAGS); #else ret = data_db->put(data_db, txn, &key, &value, DB_PUT_FLAGS); #endif return ret; }
__declspec(noreturn) static void fork_child() { install_syscall_handler(); tls_afterfork(); process_init(fork->stack_base); dbt_init(); if (fork->ctid) *(pid_t *)fork->ctid = GetCurrentProcessId(); restore_fork_context(&fork->context); }
static void init_subsystems() { shared_init(); heap_init(); signal_init(); process_init(); tls_init(); vfs_init(); dbt_init(); }
int ftfs_bstore_get_ino(DB *meta_db, DB_TXN *txn, ino_t *ino) { int ret; ino_t curr_ino; DBT next_ino_key_dbt, next_ino_value_dbt; dbt_init(&next_ino_key_dbt, &next_ino_meta_key, SIZEOF_KEY(next_ino_meta_key)); dbt_init(&next_ino_value_dbt, &curr_ino, sizeof(curr_ino)); ret = meta_db->get(meta_db, txn, &next_ino_key_dbt, &next_ino_value_dbt, DB_GET_FLAGS); if (ret == DB_NOTFOUND) { *ino = curr_ino = FTFS_ROOT_INO + 1; ret = meta_db->put(meta_db, txn, &next_ino_key_dbt, &next_ino_value_dbt, DB_PUT_FLAGS); } else if (!ret) *ino = curr_ino; return ret; }
int ftfs_bstore_update(DB *data_db, struct ftfs_data_key *data_key, DB_TXN *txn, const void *buf, size_t size, loff_t offset) { int ret; DBT key, extra_dbt; struct block_update_cb_info *info; size_t info_size = sizeof(struct block_update_cb_info) + size; info = kmalloc(info_size, GFP_KERNEL); if (!info) return -ENOMEM; info->offset = offset; info->size = size; memcpy(info->buf, buf, size); dbt_init(&key, data_key, SIZEOF_KEY(*data_key)); dbt_init(&extra_dbt, info, info_size); ret = data_db->update(data_db, txn, &key, &extra_dbt, DB_UPDATE_FLAGS); kfree(info); return ret; }
/* * Call out to per-macro handlers after clearing the persistent database * key. If the macro sets the database key, flush it to the database. */ static void pmdoc_node(MDOC_ARGS) { if (NULL == n) return; switch (n->type) { case (MDOC_HEAD): /* FALLTHROUGH */ case (MDOC_BODY): /* FALLTHROUGH */ case (MDOC_TAIL): /* FALLTHROUGH */ case (MDOC_BLOCK): /* FALLTHROUGH */ case (MDOC_ELEM): if (NULL == mdocs[n->tok]) break; dbt_init(key, ksz); (*mdocs[n->tok])(db, dbn, key, ksz, val, n); if (0 == key->size) break; if (0 == (*db->put)(db, key, val, 0)) break; perror(dbn); exit((int)MANDOCLEVEL_SYSERR); /* NOTREACHED */ default: break; } pmdoc_node(db, dbn, key, ksz, val, n->child); pmdoc_node(db, dbn, key, ksz, val, n->next); }
void main() { log_init(); fork_init(); /* fork_init() will directly jump to restored thread context if we are a fork child */ mm_init(); install_syscall_handler(); heap_init(); signal_init(); process_init(); tls_init(); vfs_init(); dbt_init(); /* Parse command line */ const char *cmdline = GetCommandLineA(); int len = strlen(cmdline); if (len > BLOCK_SIZE) /* TODO: Test if there is sufficient space for argv[] array */ { kprintf("Command line too long.\n"); process_exit(1, 0); } startup = mm_mmap(NULL, BLOCK_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS, INTERNAL_MAP_TOPDOWN | INTERNAL_MAP_NORESET, NULL, 0); *(uintptr_t*) startup = 1; char *current_startup_base = startup + sizeof(uintptr_t); memcpy(current_startup_base, cmdline, len + 1); char *envbuf = (char *)ALIGN_TO(current_startup_base + len + 1, sizeof(void*)); char *env0 = envbuf; ENV("TERM=xterm"); char *env1 = envbuf; ENV("HOME=/root"); char *env2 = envbuf; ENV("DISPLAY=127.0.0.1:0"); char *env3 = envbuf; ENV("PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/bin:/sbin"); int argc = 0; char **argv = (char **)ALIGN_TO(envbuf, sizeof(void*)); /* Parse command line */ int in_quote = 0; char *j = current_startup_base; for (char *i = current_startup_base; i <= current_startup_base + len; i++) if (!in_quote && (*i == ' ' || *i == '\t' || *i == '\r' || *i == '\n' || *i == 0)) { *i = 0; if (i > j) argv[argc++] = j; j = i + 1; } else if (*i == '"') { *i = 0; if (in_quote) argv[argc++] = j; in_quote = !in_quote; j = i + 1; } argv[argc] = NULL; char **envp = argv + argc + 1; int env_size = 4; envp[0] = env0; envp[1] = env1; envp[2] = env2; envp[3] = env3; envp[4] = NULL; char *buffer_base = (char*)(envp + env_size + 1); const char *filename = NULL; for (int i = 1; i < argc; i++) { if (argv[i][0] == '-') { } else if (!filename) filename = argv[i]; } if (filename) do_execve(filename, argc - 1, argv + 1, env_size, envp, buffer_base, NULL); kprintf("Usage: flinux <executable> [arguments]\n"); process_exit(1, 0); }
int ftfs_bstore_move(DB *meta_db, DB *data_db, struct ftfs_meta_key *old_meta_key, struct ftfs_meta_key *new_meta_key, DB_TXN *txn, int flag, struct ftfs_metadata *old_meta) { int ret, r, rot, is_dir; size_t key_buf_len; void *key_buf[2], *new_key_buf, *block_buf; struct ftfs_metadata meta; DBT old_meta_key_dbt, new_meta_key_dbt; DBT key_dbt[2], new_key_dbt, value_dbt; DBC *cursor = NULL; key_buf[0] = key_buf[1] = new_key_buf = block_buf = NULL; dbt_init(&old_meta_key_dbt, old_meta_key, SIZEOF_KEY(*old_meta_key)); dbt_init(&new_meta_key_dbt, new_meta_key, SIZEOF_KEY(*new_meta_key)); dbt_init(&value_dbt, old_meta, sizeof(struct ftfs_metadata)); if ((ret = meta_db->put(meta_db, txn, &new_meta_key_dbt, &value_dbt, DB_PUT_FLAGS)) || (ret = meta_db->del(meta_db, txn, &old_meta_key_dbt, DB_DEL_FLAGS))) { ret = -EINVAL; goto out; } if ((flag & FTFS_BSTORE_MOVE_NO_DATA)) goto out; ret = -ENOMEM; key_buf_len = KEY_MAX_LEN; key_buf[0] = kmalloc(key_buf_len, GFP_KERNEL); if (!key_buf[0]) goto out; key_buf[1] = kmalloc(key_buf_len, GFP_KERNEL); if (!key_buf[1]) goto out; new_key_buf = kmalloc(key_buf_len, GFP_KERNEL); if (!new_key_buf) goto out; block_buf = kmalloc(FTFS_BSTORE_BLOCKSIZE, GFP_KERNEL); if (!block_buf) goto out; is_dir = S_ISDIR(old_meta->u.st.st_mode); if (is_dir) { struct ftfs_meta_key *it_meta_key[2]; struct ftfs_meta_key *new_it_meta_key = new_key_buf; it_meta_key[0] = key_buf[0]; it_meta_key[1] = key_buf[1]; rot = 0; copy_child_meta_key_from_meta_key(it_meta_key[rot], old_meta_key, ""); dbt_init_extra_size(&key_dbt[rot], it_meta_key[rot], SIZEOF_KEY(*it_meta_key[rot]), key_buf_len); dbt_init(&key_dbt[1 - rot], it_meta_key[1 - rot], key_buf_len); dbt_init(&value_dbt, &meta, sizeof(struct ftfs_metadata)); ret = meta_db->cursor(meta_db, txn, &cursor, DB_CURSOR_FLAGS); if (ret) goto out; r = cursor->c_get(cursor, &key_dbt[rot], &value_dbt, DB_SET_RANGE); while (!r) { if (!meta_key_is_descendant_of_meta_key(it_meta_key[rot], old_meta_key)) break; copy_meta_key_move_to_directory(new_it_meta_key, old_meta_key, new_meta_key, it_meta_key[rot]); dbt_init(&new_key_dbt, new_it_meta_key, SIZEOF_KEY(*new_it_meta_key)); ret = meta_db->put(meta_db, txn, &new_key_dbt, &value_dbt, DB_PUT_FLAGS); if (ret) goto out; rot = 1 - rot; r = cursor->c_get(cursor, &key_dbt[rot], &value_dbt, DB_NEXT); ret = meta_db->del(meta_db, txn, &key_dbt[1 - rot], DB_DEL_FLAGS); if (ret) goto out; } if (r && r != DB_NOTFOUND) { ret = r; goto out; } cursor->c_close(cursor); cursor = NULL; } { struct ftfs_data_key *it_data_key[2]; struct ftfs_data_key *new_it_data_key = new_key_buf; it_data_key[0] = key_buf[0]; it_data_key[1] = key_buf[1]; rot = 0; if (is_dir) copy_child_data_key_from_meta_key(it_data_key[rot], old_meta_key, "", 0); else copy_data_key_from_meta_key(it_data_key[rot], old_meta_key, 0); dbt_init_extra_size(&key_dbt[rot], it_data_key[rot], SIZEOF_KEY(*it_data_key[rot]), key_buf_len); dbt_init(&key_dbt[1 - rot], it_data_key[1 - rot], key_buf_len); dbt_init(&value_dbt, block_buf, FTFS_BSTORE_BLOCKSIZE); ret = data_db->cursor(data_db, txn, &cursor, DB_CURSOR_FLAGS); if (ret) goto out; r = cursor->c_get(cursor, &key_dbt[rot], &value_dbt, DB_SET_RANGE); while (!r) { if (!data_key_is_descendant_of_meta_key(it_data_key[rot], old_meta_key)) break; copy_data_key_move_to_directory(new_it_data_key, old_meta_key, new_meta_key, it_data_key[rot]); dbt_init(&new_key_dbt, new_it_data_key, SIZEOF_KEY(*new_it_data_key)); ret = data_db->put(data_db, txn, &new_key_dbt, &value_dbt, DB_PUT_FLAGS); if (ret) goto out; rot = 1 - rot; r = cursor->c_get(cursor, &key_dbt[rot], &value_dbt, DB_NEXT); ret = data_db->del(data_db, txn, &key_dbt[1 - rot], DB_DEL_FLAGS); if (ret) goto out; } if (r && r != DB_NOTFOUND) { ret = r; goto out; } cursor->c_close(cursor); cursor = NULL; } out: if (cursor) cursor->c_close(cursor); if (key_buf[0]) kfree(key_buf[0]); if (key_buf[1]) kfree(key_buf[1]); if (new_key_buf) kfree(new_key_buf); if (block_buf) kfree(block_buf); return ret; }
int ftfs_bstore_meta_readdir(DB *meta_db, struct ftfs_meta_key *meta_key, DB_TXN *txn, struct dir_context *ctx) { int ret, r; struct ftfs_meta_key *child_meta_key; struct ftfs_metadata meta; DBT child_meta_key_dbt, meta_dbt; DBC *cursor; if (ctx->pos == 1) return 0; child_meta_key = kmalloc(META_KEY_MAX_LEN, GFP_KERNEL); if (!child_meta_key) return -ENOMEM; if (ctx->pos == 0) { ctx->pos = (loff_t)kmalloc(NAME_MAX, GFP_KERNEL); BUG_ON(ctx->pos == (loff_t)NULL); copy_child_meta_key_from_meta_key(child_meta_key, meta_key, ""); } else { copy_child_meta_key_from_meta_key(child_meta_key, meta_key, (char *)ctx->pos); } dbt_init_extra_size(&child_meta_key_dbt, child_meta_key, SIZEOF_KEY(*child_meta_key), META_KEY_MAX_LEN); dbt_init(&meta_dbt, &meta, sizeof(struct ftfs_metadata)); ret = meta_db->cursor(meta_db, txn, &cursor, DB_CURSOR_FLAGS); if (ret) goto out; r = cursor->c_get(cursor, &child_meta_key_dbt, &meta_dbt, DB_SET_RANGE); while (!r) { char *name; u64 ino; unsigned type; if (!meta_key_is_child_of_meta_key(child_meta_key, meta_key)) { kfree((char *)ctx->pos); ctx->pos = 1; break; } if (meta.type == FTFS_METADATA_TYPE_REDIRECT) { struct ftfs_meta_key *readdir_circle_meta_key = alloc_meta_key_from_circle_id(meta.u.circle_id); if (!readdir_circle_meta_key) { r = -ENOMEM; break; } r = ftfs_bstore_meta_get(meta_db, readdir_circle_meta_key, txn, &meta); meta_key_free(readdir_circle_meta_key); if (r) break; } ino = meta.u.st.st_ino; type = ftfs_get_type(meta.u.st.st_mode); name = strrchr(child_meta_key->path, '/') + 1; if (!dir_emit(ctx, name, strlen(name), ino, type)) { strcpy((char *)ctx->pos, name); break; } r = cursor->c_get(cursor, &child_meta_key_dbt, &meta_dbt, DB_NEXT); } if (r == DB_NOTFOUND) { kfree((char *)ctx->pos); ctx->pos = 1; } cursor->c_close(cursor); if (r && r != DB_NOTFOUND) ret = r; out: kfree(child_meta_key); return ret; }