コード例 #1
0
ファイル: journal.c プロジェクト: arakashic/coolfs
/* Do not fail, do not sleep. Make it fast! */
u64 pmfs_create_lite_transaction(struct super_block *sb,
	struct pmfs_lite_journal_entry *dram_entry1,
	struct pmfs_lite_journal_entry *dram_entry2,
	int entries)
{
	struct pmfs_inode *pi;
	struct pmfs_lite_journal_entry *entry;
	size_t size = sizeof(struct pmfs_lite_journal_entry);
	u64 new_tail, temp;;

	pi = pmfs_get_inode_by_ino(sb, PMFS_LITEJOURNAL_INO);
	if (pi->log_head == 0 || pi->log_head != pi->log_tail)
		BUG();

	temp = pi->log_head;
	entry = (struct pmfs_lite_journal_entry *)pmfs_get_block(sb,
							temp);

	pmfs_print_lite_transaction(dram_entry1);
	memcpy_to_pmem_nocache(entry, dram_entry1, size);

	if (entries == 2) {
		temp = next_lite_journal(temp);
		entry = (struct pmfs_lite_journal_entry *)pmfs_get_block(sb,
							temp);
		pmfs_print_lite_transaction(dram_entry2);
		memcpy_to_pmem_nocache(entry, dram_entry2, size);
	}

	new_tail = next_lite_journal(temp);
	pmfs_update_tail(pi, new_tail);
	return new_tail;
}
コード例 #2
0
ファイル: dir.c プロジェクト: NVSL/NOVA
/*
 * Append a nova_dentry to the current nova_inode_log_page.
 * Note unlike append_file_write_entry(), this method returns the tail pointer
 * after append.
 */
static u64 nova_append_dir_inode_entry(struct super_block *sb,
	struct nova_inode *pidir, struct inode *dir,
	u64 ino, struct dentry *dentry, unsigned short de_len, u64 tail,
	int link_change, u64 *curr_tail)
{
	struct nova_inode_info *si = NOVA_I(dir);
	struct nova_inode_info_header *sih = &si->header;
	struct nova_dentry *entry;
	u64 curr_p;
	size_t size = de_len;
	int extended = 0;
	unsigned short links_count;
	timing_t append_time;

	NOVA_START_TIMING(append_dir_entry_t, append_time);

	curr_p = nova_get_append_head(sb, pidir, sih, tail, size, &extended);
	if (curr_p == 0)
		BUG();

	entry = (struct nova_dentry *)nova_get_block(sb, curr_p);
	entry->entry_type = DIR_LOG;
	entry->ino = cpu_to_le64(ino);
	entry->name_len = dentry->d_name.len;
	memcpy_to_pmem_nocache(entry->name, dentry->d_name.name,
				dentry->d_name.len);
	entry->name[dentry->d_name.len] = '\0';
	entry->file_type = 0;
	entry->invalid = 0;
	entry->mtime = cpu_to_le32(dir->i_mtime.tv_sec);
	entry->size = cpu_to_le64(dir->i_size);

	links_count = cpu_to_le16(dir->i_nlink);
	if (links_count == 0 && link_change == -1)
		links_count = 0;
	else
		links_count += link_change;
	entry->links_count = cpu_to_le16(links_count);

	/* Update actual de_len */
	entry->de_len = cpu_to_le16(de_len);
	nova_dbg_verbose("dir entry @ 0x%llx: ino %llu, entry len %u, "
			"name len %u, file type %u\n",
			curr_p, entry->ino, entry->de_len,
			entry->name_len, entry->file_type);

	nova_flush_buffer(entry, de_len, 0);

	*curr_tail = curr_p + de_len;

	dir->i_blocks = pidir->i_blocks;
	NOVA_END_TIMING(append_dir_entry_t, append_time);
	return curr_p;
}
コード例 #3
0
ファイル: namei.c プロジェクト: arakashic/coolfs
static int pmfs_rename(struct inode *old_dir,
			struct dentry *old_dentry,
			struct inode *new_dir, struct dentry *new_dentry)
{
	struct inode *old_inode = old_dentry->d_inode;
	struct inode *new_inode = new_dentry->d_inode;
	struct super_block *sb = old_inode->i_sb;
	struct pmfs_sb_info *sbi = PMFS_SB(sb);
	struct pmfs_inode *old_pi = NULL, *new_pi = NULL;
	struct pmfs_inode *new_old_pi = NULL;
	struct pmfs_inode *new_pidir = NULL, *old_pidir = NULL;
	struct pmfs_lite_journal_entry entry, entry1;
	struct pmfs_inode_info *si = PMFS_I(old_inode);
	struct pmfs_inode_info_header *sih = si->header;
	u64 old_tail = 0, new_tail = 0, tail, new_pi_tail = 0, old_pi_tail = 0;
	u64 pi_newaddr = 0;
	int need_new_pi = 0;
	int err = -ENOENT;
	int inc_link = 0, dec_link = 0;
	int entries = 0;
	u64 journal_tail;
	timing_t rename_time;

	pmfs_dbgv("%s: rename %s to %s, old dir %lu, new dir %lu\n", __func__,
			old_dentry->d_name.name, new_dentry->d_name.name,
			old_dir->i_ino, new_dir->i_ino);
	PMFS_START_TIMING(rename_t, rename_time);

	if (new_inode) {
		err = -ENOTEMPTY;
		if (S_ISDIR(old_inode->i_mode) && !pmfs_empty_dir(new_inode))
			goto out;
	} else {
		if (S_ISDIR(old_inode->i_mode)) {
			err = -EMLINK;
			if (new_dir->i_nlink >= PMFS_LINK_MAX)
				goto out;
		}
		if (S_ISDIR(old_inode->i_mode)) {
			inc_link = 1;
			dec_link = -1;
		}
	}

	new_pidir = pmfs_get_inode(sb, new_dir);
	old_pidir = pmfs_get_inode(sb, old_dir);

	old_pi = pmfs_get_inode(sb, old_inode);
	old_inode->i_ctime = CURRENT_TIME;
	err = pmfs_append_link_change_entry(sb, old_pi,
						old_inode, 0, &old_pi_tail);
	if (err)
		goto out;

	if (new_inode) {
		/* First remove the old entry in the new directory */
		err = pmfs_remove_entry(new_dentry, 0,  0, &new_tail);
		if (err)
			goto out;
	}

	/* If old dir is different from new dir, copy the inode to new dir */
	if (new_pidir != old_pidir)
		need_new_pi = 1;

	/* link into the new directory. */
	err = pmfs_add_entry(new_dentry, &pi_newaddr, old_inode->i_ino,
				inc_link, need_new_pi, new_tail, &new_tail);
	if (err)
		goto out;

	/* and unlink the inode from the old directory ... */
	if (need_new_pi) {
		tail = 0;
		new_old_pi = (struct pmfs_inode *)pmfs_get_block(sb,
						pi_newaddr);
		memcpy_to_pmem_nocache(new_old_pi, old_pi, PMFS_INODE_SIZE);
		/* new_old_pi is part of the log so in-place update is fine */
		pmfs_update_tail(new_old_pi, old_pi_tail);
	} else {
		tail = new_tail;
	}

	err = pmfs_remove_entry(old_dentry, dec_link, tail, &old_tail);
	if (err)
		goto out;

	if (new_inode) {
		new_pi = pmfs_get_inode(sb, new_inode);
		new_inode->i_ctime = CURRENT_TIME;

		if (S_ISDIR(old_inode->i_mode)) {
			if (new_inode->i_nlink)
				drop_nlink(new_inode);
		}
		if (new_inode->i_nlink)
			drop_nlink(new_inode);

		err = pmfs_append_link_change_entry(sb, new_pi,
						new_inode, 0, &new_pi_tail);
		if (err)
			goto out;
	}

	if (inc_link)
		inc_nlink(new_dir);
	if (dec_link < 0)
		drop_nlink(old_dir);

	entries = 1;
	memset(&entry, 0, sizeof(struct pmfs_lite_journal_entry));

	entry.addrs[0] = (u64)pmfs_get_addr_off(sbi, &old_pi->log_tail);
	entry.addrs[0] |= (u64)8 << 56;
	entry.values[0] = old_pi->log_tail;

	entry.addrs[1] = (u64)pmfs_get_addr_off(sbi, &old_pidir->log_tail);
	entry.addrs[1] |= (u64)8 << 56;
	entry.values[1] = old_pidir->log_tail;

	if (old_pidir != new_pidir) {
		entry.addrs[2] = (u64)pmfs_get_addr_off(sbi,
						&old_pi->valid);
		entry.addrs[2] |= (u64)1 << 56;
		entry.values[2] = old_pi->valid;

		entry.addrs[3] = (u64)pmfs_get_addr_off(sbi,
						&new_pidir->log_tail);
		entry.addrs[3] |= (u64)8 << 56;
		entry.values[3] = new_pidir->log_tail;
	}

	if (new_inode) {
		entries++;
		memset(&entry1, 0, sizeof(struct pmfs_lite_journal_entry));

		entry1.addrs[0] = (u64)pmfs_get_addr_off(sbi,
						&new_pi->log_tail);
		entry1.addrs[0] |= (u64)8 << 56;
		entry1.values[0] = new_pi->log_tail;

		if (!new_inode->i_nlink) {
			entry1.addrs[1] = (u64)pmfs_get_addr_off(sbi,
							&new_pi->valid);
			entry1.addrs[1] |= (u64)1 << 56;
			entry1.values[1] = new_pi->valid;
		}
	}

	mutex_lock(&sbi->lite_journal_mutex);
	journal_tail = pmfs_create_lite_transaction(sb, &entry,
							&entry1, entries);

	pmfs_update_tail(old_pi, old_pi_tail);
	pmfs_update_tail(old_pidir, old_tail);
	if (old_pidir != new_pidir) {
		pmfs_update_tail(new_pidir, new_tail);
		old_pi->valid = 0;
	}
	if (new_inode) {
		pmfs_update_tail(new_pi, new_pi_tail);
		if (!new_inode->i_nlink)
			new_pi->valid = 0;
	}

	pmfs_commit_lite_transaction(sb, journal_tail);
	mutex_unlock(&sbi->lite_journal_mutex);

	if (need_new_pi && pi_newaddr)
		sih->pi_addr = pi_newaddr;

	PMFS_END_TIMING(rename_t, rename_time);
	return 0;
out:
	pmfs_err(sb, "%s return %d\n", __func__, err);
	PMFS_END_TIMING(rename_t, rename_time);
	return err;
}