static void do_ii_write_lock(struct inode *inode, unsigned int lsc)
{
	switch (lsc) {
	case AuLsc_DI_CHILD:
		ii_write_lock_child(inode);
		break;
	case AuLsc_DI_CHILD2:
		ii_write_lock_child2(inode);
		break;
	case AuLsc_DI_CHILD3:
		ii_write_lock_child3(inode);
		break;
	case AuLsc_DI_PARENT:
		ii_write_lock_parent(inode);
		break;
	case AuLsc_DI_PARENT2:
		ii_write_lock_parent2(inode);
		break;
	case AuLsc_DI_PARENT3:
		ii_write_lock_parent3(inode);
		break;
	default:
		BUG();
	}
}
Beispiel #2
0
static int aufs_commit_metadata(struct inode *inode)
{
	int err;
	aufs_bindex_t bindex;
	struct super_block *sb;
	struct inode *h_inode;
	int (*f)(struct inode *inode);

	sb = inode->i_sb;
	si_read_lock(sb, AuLock_FLUSH);
	ii_write_lock_child(inode);
	bindex = au_ibstart(inode);
	AuDebugOn(bindex < 0);
	h_inode = au_h_iptr(inode, bindex);

	f = h_inode->i_sb->s_export_op->commit_metadata;
	if (f)
		err = f(h_inode);
	else {
		struct writeback_control wbc = {
			.sync_mode	= WB_SYNC_ALL,
			.nr_to_write	= 0 /* metadata only */
		};

		err = sync_inode(h_inode, &wbc);
	}

	au_cpup_attr_timesizes(inode);
	ii_write_unlock(inode);
	si_read_unlock(sb);
	return err;
}

/* ---------------------------------------------------------------------- */

static struct export_operations aufs_export_op = {
	.fh_to_dentry		= aufs_fh_to_dentry,
	/* .fh_to_parent	= aufs_fh_to_parent, */
	.encode_fh		= aufs_encode_fh,
	.commit_metadata	= aufs_commit_metadata
};

void au_export_init(struct super_block *sb)
{
	struct au_sbinfo *sbinfo;
	__u32 u;

	sb->s_export_op = &aufs_export_op;
	sbinfo = au_sbi(sb);
	sbinfo->si_xigen = NULL;
	get_random_bytes(&u, sizeof(u));
	BUILD_BUG_ON(sizeof(u) != sizeof(int));
	atomic_set(&sbinfo->si_xigen_next, u);
}
static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex,
			   unsigned int sigen, const unsigned int verbose)
{
	int err;
	unsigned long long max, ull;
	struct inode *i, **array;
	aufs_bindex_t bstart, bend;

	array = au_iarray_alloc(sb, &max);
	err = PTR_ERR(array);
	if (IS_ERR(array))
		goto out;

	err = 0;
	AuDbg("b%d\n", bindex);
	for (ull = 0; !err && ull < max; ull++) {
		i = array[ull];
		if (i->i_ino == AUFS_ROOT_INO)
			continue;

		/* AuDbgInode(i); */
		if (au_iigen(i) == sigen)
			ii_read_lock_child(i);
		else {
			ii_write_lock_child(i);
			err = au_refresh_hinode_self(i);
			au_iigen_dec(i);
			if (!err)
				ii_downgrade_lock(i);
			else {
				ii_write_unlock(i);
				break;
			}
		}

		bstart = au_ibstart(i);
		bend = au_ibend(i);
		if (bstart <= bindex
		    && bindex <= bend
		    && au_h_iptr(i, bindex)
		    && au_test_ibusy(i, bstart, bend)) {
			err = -EBUSY;
			AuVerbose(verbose, "busy i%lu\n", i->i_ino);
			AuDbgInode(i);
		}
		ii_read_unlock(i);
	}
	au_iarray_free(array, max);

out:
	return err;
}