Esempio n. 1
0
void tux3_iattrdirty(struct inode *inode)
{
	struct tux3_inode *tuxnode = tux_inode(inode);
	unsigned delta = tux3_inode_delta(inode);
	unsigned flags = tuxnode->flags;

	/* If dirtied on this delta, nothing to do */
	if (tux3_iattrsta_has_delta(flags) &&
	    tux3_iattrsta_get_delta(flags) == tux3_delta(delta))
		return;

	trace("inum %Lu, delta %u", tuxnode->inum, delta);

	spin_lock(&tuxnode->lock);
	flags = tuxnode->flags;
	if (S_ISREG(inode->i_mode) || tux3_iattrsta_has_delta(flags)) {
		unsigned old_delta;

		/*
		 * For a regular file, and even if iattrs are clean,
		 * we have to provide stable idata for backend.
		 *
		 * Because backend may be committing data pages. If
		 * so, backend have to check idata->i_size, and may
		 * save dtree root. But previous delta doesn't have
		 * stable iattrs.
		 *
		 * So, this provides stable iattrs for regular file,
		 * even if previous delta is clean.
		 *
		 * Other types don't have this problem, because:
		 * - Never dirty iattr (e.g. volmap). IOW, iattrs are
		 *   always stable.
		 * - Or dirty iattr with data, e.g. directory updates
		 *   timestamp too with data blocks.
		 */
		if (S_ISREG(inode->i_mode) && !tux3_iattrsta_has_delta(flags))
			old_delta = tux3_delta(delta - 1);
		else
			old_delta = tux3_iattrsta_get_delta(flags);

		/* If delta is difference, iattrs was stabilized. Copy. */
		if (old_delta != tux3_delta(delta)) {
			struct tux3_iattr_data *idata =
				&tux3_inode_ddc(inode, old_delta)->idata;
			idata_copy(inode, idata);
		}
	}
	/* Update iattr state to current delta */
	tuxnode->flags = tux3_iattrsta_update(flags, delta);
	spin_unlock(&tuxnode->lock);
}
Esempio n. 2
0
/*
 * Read iattrs, then clear iattr dirty to tell no need to iattrfork
 * anymore if needed.
 *
 * Caller must hold tuxnode->lock.
 */
static void tux3_iattr_read_and_clear(struct inode *inode,
				      struct tux3_iattr_data *result,
				      unsigned delta)
{
	struct tux3_inode *tuxnode = tux_inode(inode);
	unsigned long flags;

	trace("inum %Lu, delta %u", tuxnode->inum, delta);

	/*
	 * If delta is same, iattrs are available in inode. If not,
	 * iattrs were forked.
	 */
	flags = tuxnode->flags;
	if (!tux3_iattrsta_has_delta(flags) ||
	    tux3_iattrsta_get_delta(flags) == tux3_delta(delta)) {
		/*
		 * If btree is only dirtied, or if dirty and no fork,
		 * use inode.
		 */
		idata_copy(inode, result);
		tuxnode->flags = tux3_iattrsta_clear(flags);
	} else {
		/* If dirty and forked, use copy */
		struct tux3_iattr_data *idata =
			&tux3_inode_ddc(inode, delta)->idata;
		assert(idata->present != TUX3_INVALID_PRESENT);
		*result = *idata;
	}

	/* For debugging, set invalid value to ->present after read */
	tux3_inode_ddc(inode, delta)->idata.present = TUX3_INVALID_PRESENT;
}
Esempio n. 3
0
/* Check whether we can modify buffer atomically for delta */
int buffer_can_modify(struct buffer_head *buffer, unsigned delta)
{
	unsigned long state = buffer->b_state;
	/* If buffer is clean or dirtied for same delta, we can modify */
	return !tux3_bufsta_has_delta(state) ||
		tux3_bufsta_get_delta(state) == tux3_delta(delta);
}
Esempio n. 4
0
/*
 * FIXME: this is hack to save delta to linux buffer_head.
 * Inefficient, and this is not atomic with dirty bit change. And this
 * may not work on all arch (If set_bit() and cmpxchg() is not
 * exclusive, this has race).
 */
static void tux3_set_bufdelta(struct buffer_head *buffer, int delta)
{
	unsigned long state, old_state;

	delta = tux3_delta(delta);

	state = buffer->b_state;
	for (;;) {
		old_state = state;
		state = tux3_bufsta_update(old_state, delta);
		state = cmpxchg(&buffer->b_state, old_state, state);
		if (state == old_state)
			break;
	}
}
Esempio n. 5
0
/*
 * Check whether inode was dead. Then clear iattr dirty to tell no
 * need to iattrfork anymore if needed.
 */
static void tux3_dead_read_and_clear(struct inode *inode,
				     unsigned *deleted,
				     unsigned delta)
{
	struct tux3_inode *tuxnode = tux_inode(inode);
	unsigned flags = tuxnode->flags;

	*deleted = 0;

	if (tux3_deadsta_has_delta(flags) &&
	    tux3_deadsta_get_delta(flags) == tux3_delta(delta)) {
		*deleted = 1;
		flags |= TUX3_INODE_DEAD;
		tuxnode->flags = tux3_deadsta_clear(flags);
	}
}
Esempio n. 6
0
/* Check whether buffer was already dirtied atomically for delta */
int buffer_already_dirty(struct buffer_head *buffer, unsigned delta)
{
	unsigned long state = buffer->b_state;
	/* If buffer had same delta, buffer was already dirtied for delta */
	return buffer_check_dirty_delta(state) == tux3_delta(delta);
}