Exemple #1
0
/* 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;
}
Exemple #2
0
/* Returns new tail after append */
int pmfs_append_link_change_entry(struct super_block *sb,
	struct pmfs_inode *pi, struct inode *inode, u64 tail, u64 *new_tail)
{
	struct pmfs_inode_info *si = PMFS_I(inode);
	struct pmfs_inode_info_header *sih = si->header;
	struct pmfs_link_change_entry *entry;
	u64 curr_p;
	size_t size = sizeof(struct pmfs_link_change_entry);
	timing_t append_time;

	PMFS_START_TIMING(append_entry_t, append_time);
	pmfs_dbg_verbose("%s: inode %lu attr change\n",
				__func__, inode->i_ino);

	curr_p = pmfs_get_append_head(sb, pi, sih, tail, size, 0, 1);
	if (curr_p == 0)
		return -ENOMEM;

	entry = (struct pmfs_link_change_entry *)pmfs_get_block(sb, curr_p);
	entry->entry_type = LINK_CHANGE;
	entry->links = cpu_to_le16(inode->i_nlink);
	entry->ctime = cpu_to_le32(inode->i_ctime.tv_sec);
	entry->flags = cpu_to_le32(inode->i_flags);
	entry->generation = cpu_to_le32(inode->i_generation);
	pmfs_flush_buffer(entry, size, 0);
	*new_tail = curr_p + size;

	PMFS_END_TIMING(append_entry_t, append_time);
	return 0;
}
Exemple #3
0
	/* Now save all the memory ranges allocated in the PMFS. These ranges
	 * are specified by the block_low and block_high fields of every
	 * struct pmfs_blocknode_lowhigh */
	list_for_each_entry(i, head, link) {
		if (i->block_low == 0)
			ptr = (char *)pmfs_get_super(sb);
		else
			ptr = pmfs_get_block(sb, i->block_low << PAGE_SHIFT);
		size = (i->block_high - i->block_low + 1) << PAGE_SHIFT;
		if (pmfs_write_backing_store(flp, ptr, size, &woff) != size)
			goto out;
	}
Exemple #4
0
static int pmfs_recover_lite_journal(struct super_block *sb,
	struct pmfs_inode *pi, int recover)
{
	struct pmfs_lite_journal_entry *entry;
	u64 temp;

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

	if (recover == 2) {
		temp = next_lite_journal(pi->log_head);
		entry = (struct pmfs_lite_journal_entry *)pmfs_get_block(sb,
							temp);
		pmfs_undo_lite_journal_entry(sb, entry);
	}

	pmfs_update_tail(pi, pi->log_head);
	return 0;
}
Exemple #5
0
static void pmfs_recover_lite_journal_entry(struct super_block *sb,
	u64 addr, u64 value, u8 type)
{
	switch (type) {
		case 1:
			*(u8 *)pmfs_get_block(sb, addr) = (u8)value;
			break;
		case 2:
			*(u16 *)pmfs_get_block(sb, addr) = (u16)value;
			break;
		case 4:
			*(u32 *)pmfs_get_block(sb, addr) = (u32)value;
			break;
		case 8:
			*(u64 *)pmfs_get_block(sb, addr) = (u64)value;
			break;
		default:
			pmfs_dbg("%s: unknown data type %u\n",
					__func__, type);
			break;
	}

	pmfs_flush_buffer((void *)pmfs_get_block(sb, addr), CACHELINE_SIZE, 0);
}
Exemple #6
0
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;
}
Exemple #7
0
int pmfs_new_block(struct super_block *sb, unsigned long *blocknr,
	unsigned short btype, int zero)
{
	struct pmfs_sb_info *sbi = PMFS_SB(sb);
	struct list_head *head = &(sbi->block_inuse_head);
	struct pmfs_blocknode *i, *next_i;
	struct pmfs_blocknode *free_blocknode= NULL;
	void *bp;
	unsigned long num_blocks = 0;
	struct pmfs_blocknode *curr_node;
	int errval = 0;
	bool found = 0;
	unsigned long next_block_low;
	unsigned long new_block_low;
	unsigned long new_block_high;

	num_blocks = pmfs_get_numblocks(btype);

	lock_super(sb);

	/* Traverese each blocknode entry */
	list_for_each_entry(i, head, link) {
		if (i->link.next == head) {
			next_i = NULL;
			next_block_low = sbi->block_end;
		} else {
			next_i = list_entry(i->link.next, typeof(*i), link);
			next_block_low = next_i->block_low;
		}

		new_block_low = (i->block_high + num_blocks) & ~(num_blocks - 1);
		new_block_high = new_block_low + num_blocks - 1;

		if (new_block_high >= next_block_low) {
			/* Does not fit - skip to next blocknode */
			continue;
		}

		if ((new_block_low == (i->block_high + 1)) &&
			(new_block_high == (next_block_low - 1)))
		{
			/* Fill the gap completly */
			if (next_i) {
				i->block_high = next_i->block_high;
				list_del(&next_i->link);
				free_blocknode = next_i;
				sbi->num_blocknode_allocated--;
			} else {
				i->block_high = new_block_high;
			}
			found = 1;
			break;
		}

		if ((new_block_low == (i->block_high + 1)) &&
			(new_block_high < (next_block_low - 1))) {
			/* Aligns to left */
			i->block_high = new_block_high;
			found = 1;
			break;
		}

		if ((new_block_low > (i->block_high + 1)) &&
			(new_block_high == (next_block_low - 1))) {
			/* Aligns to right */
			if (next_i) {
				/* right node exist */
				next_i->block_low = new_block_low;
			} else {
				/* right node does NOT exist */
				curr_node = pmfs_alloc_blocknode(sb);
				PMFS_ASSERT(curr_node);
				if (curr_node == NULL) {
					errval = -ENOSPC;
					break;
				}
				curr_node->block_low = new_block_low;
				curr_node->block_high = new_block_high;
				list_add(&curr_node->link, &i->link);
			}
			found = 1;
			break;
		}

		if ((new_block_low > (i->block_high + 1)) &&
			(new_block_high < (next_block_low - 1))) {
			/* Aligns somewhere in the middle */
			curr_node = pmfs_alloc_blocknode(sb);
			PMFS_ASSERT(curr_node);
			if (curr_node == NULL) {
				errval = -ENOSPC;
				break;
			}
			curr_node->block_low = new_block_low;
			curr_node->block_high = new_block_high;
			list_add(&curr_node->link, &i->link);
			found = 1;
			break;
		}
	}
	
	if (found == 1) {
		sbi->num_free_blocks -= num_blocks;
	}	

	unlock_super(sb);

	if (free_blocknode)
		__pmfs_free_blocknode(free_blocknode);

	if (found == 0) {
		return -ENOSPC;
	}

	if (zero) {
		size_t size;
		bp = pmfs_get_block(sb, pmfs_get_block_off(sb, new_block_low, btype));
		pmfs_memunlock_block(sb, bp); //TBDTBD: Need to fix this
		if (btype == PMFS_BLOCK_TYPE_4K)
			size = 0x1 << 12;
		else if (btype == PMFS_BLOCK_TYPE_2M)
			size = 0x1 << 21;
		else
			size = 0x1 << 30;
		memset_nt(bp, 0, size);
		pmfs_memlock_block(sb, bp);
	}
	*blocknr = new_block_low;

	return errval;
}