Example #1
0
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;
}
Example #2
0
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;
}
Example #3
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;
}
Example #4
0
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;
}
Example #5
0
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;
}
Example #6
0
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;
}
Example #7
0
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;
}
Example #8
0
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;
}
Example #9
0
/*
 * 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;
}
Example #10
0
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;
}
Example #11
0
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);
}
Example #12
0
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;
}
Example #13
0
// 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;
}
Example #14
0
__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);
}
Example #15
0
static void init_subsystems()
{
	shared_init();
	heap_init();
	signal_init();
	process_init();
	tls_init();
	vfs_init();
	dbt_init();
}
Example #16
0
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;
}
Example #17
0
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;
}
Example #18
0
/*
 * 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);
}
Example #19
0
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);
}
Example #20
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;
}
Example #21
0
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;
}