Ejemplo n.º 1
0
int pmfs_lite_journal_soft_init(struct super_block *sb)
{
	struct pmfs_sb_info *sbi = PMFS_SB(sb);
	struct pmfs_inode *pi;
	u64 temp;

	mutex_init(&sbi->lite_journal_mutex);
	pi = pmfs_get_inode_by_ino(sb, PMFS_LITEJOURNAL_INO);

	if (pi->log_head == pi->log_tail)
		return 0;

	/* We only allow up to two uncommited entries */
	temp = next_lite_journal(pi->log_head);
	if (pi->log_tail == temp) {
		pmfs_recover_lite_journal(sb, pi, 1);
		return 0;
	}

	temp = next_lite_journal(temp);
	if (pi->log_tail == temp) {
		pmfs_recover_lite_journal(sb, pi, 2);
		return 0;
	}

	/* We are in trouble */
	pmfs_dbg("%s: lite journal head 0x%llx, tail 0x%llx\n",
			__func__, pi->log_head, pi->log_tail);
	return -EINVAL;
}
Ejemplo n.º 2
0
static void pmfs_lite_transaction_for_time_and_link(struct super_block *sb,
	struct pmfs_inode *pi, struct pmfs_inode *pidir, u64 pi_tail,
	u64 pidir_tail, int invalidate)
{
	struct pmfs_sb_info *sbi = PMFS_SB(sb);
	struct pmfs_lite_journal_entry entry;
	u64 journal_tail;

	/* Commit a lite transaction */
	memset(&entry, 0, sizeof(struct pmfs_lite_journal_entry));
	entry.addrs[0] = (u64)pmfs_get_addr_off(sbi, &pi->log_tail);
	entry.addrs[0] |= (u64)8 << 56;
	entry.values[0] = pi->log_tail;

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

	if (invalidate) {
		entry.addrs[2] = (u64)pmfs_get_addr_off(sbi, &pi->valid);
		entry.addrs[2] |= (u64)1 << 56;
		entry.values[2] = pi->valid;
	}

	mutex_lock(&sbi->lite_journal_mutex);
	journal_tail = pmfs_create_lite_transaction(sb, &entry, NULL, 1);

	pmfs_update_tail(pi, pi_tail);
	pmfs_update_tail(pidir, pidir_tail);
	if (invalidate)
		pi->valid = 0;

	pmfs_commit_lite_transaction(sb, journal_tail);
	mutex_unlock(&sbi->lite_journal_mutex);
}
Ejemplo n.º 3
0
void pmfs_init_blockmap(struct super_block *sb, unsigned long init_used_size)
{
	struct pmfs_sb_info *sbi = PMFS_SB(sb);
	unsigned long num_used_block;
	struct pmfs_blocknode *blknode;

	num_used_block = (init_used_size + sb->s_blocksize - 1) >>
		sb->s_blocksize_bits;

	blknode = pmfs_alloc_blocknode(sb);
	if (blknode == NULL)
		PMFS_ASSERT(0);
	blknode->block_low = sbi->block_start;
	blknode->block_high = sbi->block_start + num_used_block - 1;
	sbi->num_free_blocks -= num_used_block;
	list_add(&blknode->link, &sbi->block_inuse_head);
}
Ejemplo n.º 4
0
/* Stores PMFS memory image into a storage file. Uses the allocation blocknode
 * linked list to determine which memory ranges to save */
static int pmfs_storefs(struct file *flp, struct super_block *sb)
{
	loff_t woff = 0;
	struct pmfs_sb_info *sbi = PMFS_SB(sb);
	u64 num_blocknodes = sbi->num_blocknode_allocated, size;
	struct list_head *head = &(sbi->block_inuse_head);
	struct pmfs_blocknode *i;
	struct pmfs_blocknode_lowhigh p;
	char *ptr;

	pmfs_info("storing pmfs to %s with 0x%llx blknodes\n",
			   sbi->pmfs_backing_file, num_blocknodes);
	/* first save the number of blocknodes */
	if (pmfs_write_backing_store(flp, (char *)&num_blocknodes, sizeof(u64),
		    &woff) != sizeof(u64))
		goto out;
	/* Then save the blocks containing blocknodes. */
	list_for_each_entry(i, head, link) {
		p.block_low = cpu_to_le64(i->block_low);
		p.block_high = cpu_to_le64(i->block_high);
		if (pmfs_write_backing_store(flp, (char *)&p, sizeof(p), &woff)
				!= sizeof(p))
			goto out;
	}
Ejemplo n.º 5
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;
}
Ejemplo n.º 6
0
void pmfs_free_block(struct super_block *sb, unsigned long blocknr,
		      unsigned short btype)
{
	struct pmfs_sb_info *sbi = PMFS_SB(sb);
	struct list_head *head = &(sbi->block_inuse_head);
	unsigned long new_block_low;
	unsigned long new_block_high;
	unsigned long num_blocks = 0;
	struct pmfs_blocknode *i;
	struct pmfs_blocknode *free_blocknode= NULL;
	struct pmfs_blocknode *curr_node;

	num_blocks = pmfs_get_numblocks(btype);
	new_block_low = blocknr;
	new_block_high = blocknr + num_blocks - 1;

	lock_super(sb);

	/* Traverese each blocknode entry */
	list_for_each_entry(i, head, link) {

		if (new_block_low > i->block_high) {
			/* skip to next blocknode */
			continue;
		}

		if ((new_block_low == i->block_low) &&
			(new_block_high == i->block_high)) {
			/* fits entire datablock */
			list_del(&i->link);
			free_blocknode = i;
			sbi->num_blocknode_allocated--;
			sbi->num_free_blocks += num_blocks;
			break;
		}
		if ((new_block_low == i->block_low) &&
			(new_block_high < i->block_high)) {
			/* Aligns left */
			i->block_low = new_block_high + 1;
			sbi->num_free_blocks += num_blocks;
			break;
		}
		if ((new_block_low > i->block_low) && 
			(new_block_high == i->block_high)) {
			/* Aligns right */
			i->block_high = new_block_low - 1;
			sbi->num_free_blocks += num_blocks;
			break;
		}
		if ((new_block_low > i->block_low) &&
			(new_block_high < i->block_high)) {
			/* Aligns somewhere in the middle */
			curr_node = pmfs_alloc_blocknode(sb);
			PMFS_ASSERT(curr_node);
			if (curr_node == NULL) {
				/* returning without freeing the block*/
				break;
			}
			curr_node->block_low = new_block_high + 1;
			curr_node->block_high = i->block_high;
			i->block_high = new_block_low - 1;
			list_add(&curr_node->link, &i->link);
			sbi->num_free_blocks += num_blocks;
			break;
		}
	}

	unlock_super(sb);

	if (free_blocknode)
		__pmfs_free_blocknode(free_blocknode);
		
	return;
}
Ejemplo n.º 7
0
unsigned long pmfs_count_free_blocks(struct super_block *sb)
{
	struct pmfs_sb_info *sbi = PMFS_SB(sb);
	return sbi->num_free_blocks; 
}
Ejemplo n.º 8
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;
}