Exemple #1
0
/* This function is called by both msync() and fsync().
 * TODO: Check if we can avoid calling pmfs_flush_buffer() for fsync. We use
 * movnti to write data to files, so we may want to avoid doing unnecessary
 * pmfs_flush_buffer() on fsync() */
int pmfs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
{
	/* Sync from start to end[inclusive] */
	struct address_space *mapping = file->f_mapping;
	struct inode *inode = mapping->host;
	loff_t isize;
	int error;

	/* if the file is not mmap'ed, there is no need to do clflushes */
	if (mapping_mapped(mapping) == 0)
		goto persist;

	end += 1; /* end is inclusive. We like our indices normal please ! */

	isize = i_size_read(inode);

	if ((unsigned long)end > (unsigned long)isize)
		end = isize;
	if (!isize || (start >= end))
	{
		pmfs_dbg_verbose("[%s:%d] : (ERR) isize(%llx), start(%llx),"
			" end(%llx)\n", __func__, __LINE__, isize, start, end);
		return -ENODATA;
	}

	/* Align start and end to cacheline boundaries */
	start = start & CACHELINE_MASK;
	end = CACHELINE_ALIGN(end);
	do {
		void *xip_mem;
		pgoff_t pgoff;
		loff_t offset;
		unsigned long xip_pfn, nr_flush_bytes;

		pgoff = start >> PAGE_CACHE_SHIFT;
		offset = start & ~PAGE_CACHE_MASK;

		nr_flush_bytes = PAGE_CACHE_SIZE - offset;
		if (nr_flush_bytes > (end - start))
			nr_flush_bytes = end - start;

		error = mapping->a_ops->get_xip_mem(mapping, pgoff, 0,
		&xip_mem, &xip_pfn);

		if (unlikely(error)) {
			/* sparse files could have such holes */
			pmfs_dbg_verbose("[%s:%d] : start(%llx), end(%llx),"
			" pgoff(%lx)\n", __func__, __LINE__, start, end, pgoff);
		} else {
			/* flush the range */
			pmfs_flush_buffer(xip_mem+offset, nr_flush_bytes, 0);
		}

		start += nr_flush_bytes;
	} while (start < end);
persist:
	PERSISTENT_MARK();
	PERSISTENT_BARRIER();
	return 0;
}
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
/* Caller needs to hold lite_journal_mutex until this returns. */
void pmfs_commit_lite_transaction(struct super_block *sb, u64 tail)
{
	struct pmfs_inode *pi;

	pi = pmfs_get_inode_by_ino(sb, PMFS_LITEJOURNAL_INO);
	if (pi->log_tail != tail)
		BUG();

	pi->log_head = tail;
	pmfs_flush_buffer(&pi->log_head, CACHELINE_SIZE, 1);
}
Exemple #4
0
int pmfs_lite_journal_hard_init(struct super_block *sb)
{
	struct pmfs_inode *pi;
	unsigned long blocknr = 0;
	unsigned long pmfs_ino;
	int allocated;
	u64 block;

	pi = pmfs_get_inode_by_ino(sb, PMFS_LITEJOURNAL_INO);
	pmfs_ino = PMFS_LITEJOURNAL_INO;
	allocated = pmfs_new_log_blocks(sb, pmfs_ino, &blocknr, 1,
						PMFS_BLOCK_TYPE_4K, 1);
	pmfs_dbg_verbose("%s: allocate log @ 0x%lx\n", __func__, blocknr);
	if (allocated != 1 || blocknr == 0)
		return -ENOSPC;

	pi->i_blocks = 1;
	block = pmfs_get_block_off(sb, blocknr,	PMFS_BLOCK_TYPE_4K);
	pi->log_head = pi->log_tail = block;
	pmfs_flush_buffer(&pi->log_head, CACHELINE_SIZE, 1);

	return pmfs_lite_journal_soft_init(sb);
}
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);
}