Exemple #1
0
int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
	   unsigned int d_type, ino_t *ino)
{
	int err;
	struct mutex *mtx;
	const int isdir = (d_type == DT_DIR);

	/* prevent hardlinks from race condition */
	mtx = NULL;
	if (!isdir) {
		mtx = &au_sbr(sb, bindex)->br_xino.xi_nondir_mtx;
		mutex_lock(mtx);
	}
	err = au_xino_read(sb, bindex, h_ino, ino);
	if (unlikely(err))
		goto out;

	if (!*ino) {
		err = -EIO;
		*ino = au_xino_new_ino(sb);
		if (unlikely(!*ino))
			goto out;
		err = au_xino_write(sb, bindex, h_ino, *ino);
		if (unlikely(err))
			goto out;
	}

 out:
	if (!isdir)
		mutex_unlock(mtx);
	return err;
}
Exemple #2
0
/* todo: return with unlocked? */
struct inode *au_new_inode(struct dentry *dentry, int must_new)
{
	struct inode *inode;
	struct dentry *h_dentry;
	struct super_block *sb;
	ino_t h_ino, ino;
	int err, match;
	aufs_bindex_t bstart;

	sb = dentry->d_sb;
	bstart = au_dbstart(dentry);
	h_dentry = au_h_dptr(dentry, bstart);
	h_ino = h_dentry->d_inode->i_ino;
	err = au_xino_read(sb, bstart, h_ino, &ino);
	inode = ERR_PTR(err);
	if (unlikely(err))
		goto out;
 new_ino:
	if (!ino) {
		ino = au_xino_new_ino(sb);
		if (unlikely(!ino)) {
			inode = ERR_PTR(-EIO);
			goto out;
		}
	}

	AuDbg("i%lu\n", (unsigned long)ino);
	inode = au_iget_locked(sb, ino);
	err = PTR_ERR(inode);
	if (IS_ERR(inode))
		goto out;

	AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW));
	if (inode->i_state & I_NEW) {
		ii_write_lock_new_child(inode);
		err = set_inode(inode, dentry);
		if (!err) {
			unlock_new_inode(inode);
			goto out; /* success */
		}

		ii_write_unlock(inode);
		iget_failed(inode);
		goto out_err;
	} else if (!must_new) {
		err = reval_inode(inode, dentry, &match);
		if (!err)
			goto out; /* success */
		else if (match)
			goto out_iput;
	}

	if (unlikely(au_test_fs_unique_ino(h_dentry->d_inode)))
		AuWarn1("Warning: Un-notified UDBA or repeatedly renamed dir,"
			" b%d, %s, %.*s, hi%lu, i%lu.\n",
			bstart, au_sbtype(h_dentry->d_sb), AuDLNPair(dentry),
			(unsigned long)h_ino, (unsigned long)ino);
	ino = 0;
	err = au_xino_write(sb, bstart, h_ino, /*ino*/0);
	if (!err) {
		iput(inode);
		goto new_ino;
	}

 out_iput:
	iput(inode);
 out_err:
	inode = ERR_PTR(err);
 out:
	return inode;
}
Exemple #3
0
/* todo: return with unlocked? */
struct inode *au_new_inode(struct dentry *dentry, int must_new)
{
	struct inode *inode, *h_inode;
	struct dentry *h_dentry;
	struct super_block *sb;
	struct mutex *mtx;
	ino_t h_ino, ino;
	int err;
	aufs_bindex_t bstart;

	sb = dentry->d_sb;
	bstart = au_dbstart(dentry);
	h_dentry = au_h_dptr(dentry, bstart);
	h_inode = h_dentry->d_inode;
	h_ino = h_inode->i_ino;

	/*
	 * stop 'race'-ing between hardlinks under different
	 * parents.
	 */
	mtx = NULL;
	if (!S_ISDIR(h_inode->i_mode))
		mtx = &au_sbr(sb, bstart)->br_xino.xi_nondir_mtx;

new_ino:
	if (mtx)
		mutex_lock(mtx);
	err = au_xino_read(sb, bstart, h_ino, &ino);
	inode = ERR_PTR(err);
	if (unlikely(err))
		goto out;

	if (!ino) {
		ino = au_xino_new_ino(sb);
		if (unlikely(!ino)) {
			inode = ERR_PTR(-EIO);
			goto out;
		}
	}

	AuDbg("i%lu\n", (unsigned long)ino);
	inode = au_iget_locked(sb, ino);
	err = PTR_ERR(inode);
	if (IS_ERR(inode))
		goto out;

	AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW));
	if (inode->i_state & I_NEW) {
		/* verbose coding for lock class name */
		if (unlikely(S_ISLNK(h_inode->i_mode)))
			au_rw_class(&au_ii(inode)->ii_rwsem,
				    au_lc_key + AuLcSymlink_IIINFO);
		else if (unlikely(S_ISDIR(h_inode->i_mode)))
			au_rw_class(&au_ii(inode)->ii_rwsem,
				    au_lc_key + AuLcDir_IIINFO);
		else /* likely */
			au_rw_class(&au_ii(inode)->ii_rwsem,
				    au_lc_key + AuLcNonDir_IIINFO);

		ii_write_lock_new_child(inode);
		err = set_inode(inode, dentry);
		if (!err) {
			unlock_new_inode(inode);
			goto out; /* success */
		}

		/*
		 * iget_failed() calls iput(), but we need to call
		 * ii_write_unlock() after iget_failed(). so dirty hack for
		 * i_count.
		 */
		atomic_inc(&inode->i_count);
		iget_failed(inode);
		ii_write_unlock(inode);
		au_xino_write(sb, bstart, h_ino, /*ino*/0);
		/* ignore this error */
		goto out_iput;
	} else if (!must_new && !IS_DEADDIR(inode) && inode->i_nlink) {
		/*
		 * horrible race condition between lookup, readdir and copyup
		 * (or something).
		 */
		if (mtx)
			mutex_unlock(mtx);
		err = reval_inode(inode, dentry);
		if (unlikely(err < 0)) {
			mtx = NULL;
			goto out_iput;
		}

		if (!err) {
			mtx = NULL;
			goto out; /* success */
		} else if (mtx)
			mutex_lock(mtx);
	}

	if (unlikely(au_test_fs_unique_ino(h_dentry->d_inode)))
		AuWarn1("Warning: Un-notified UDBA or repeatedly renamed dir,"
			" b%d, %s, %pd, hi%lu, i%lu.\n",
			bstart, au_sbtype(h_dentry->d_sb), dentry,
			(unsigned long)h_ino, (unsigned long)ino);
	ino = 0;
	err = au_xino_write(sb, bstart, h_ino, /*ino*/0);
	if (!err) {
		iput(inode);
		if (mtx)
			mutex_unlock(mtx);
		goto new_ino;
	}

out_iput:
	iput(inode);
	inode = ERR_PTR(err);
out:
	if (mtx)
		mutex_unlock(mtx);
	return inode;
}
Exemple #4
0
/* todo: return with unlocked? */
struct inode *au_new_inode(struct dentry *dentry, int must_new)
{
	struct inode *inode, *h_inode;
	struct dentry *h_dentry;
	struct super_block *sb;
	struct mutex *mtx;
	ino_t h_ino, ino;
	int err, match;
	aufs_bindex_t bstart;

	sb = dentry->d_sb;
	bstart = au_dbstart(dentry);
	h_dentry = au_h_dptr(dentry, bstart);
	h_inode = h_dentry->d_inode;
	h_ino = h_inode->i_ino;

	/*
	 * stop 'race'-ing between hardlinks under different
	 * parents.
	 */
	mtx = NULL;
	if (!S_ISDIR(h_inode->i_mode))
		mtx = &au_sbr(sb, bstart)->br_xino.xi_nondir_mtx;

new_ino:
	if (mtx)
		mutex_lock(mtx);
	err = au_xino_read(sb, bstart, h_ino, &ino);
	inode = ERR_PTR(err);
	if (unlikely(err))
		goto out;

	if (!ino) {
		ino = au_xino_new_ino(sb);
		if (unlikely(!ino)) {
			inode = ERR_PTR(-EIO);
			goto out;
		}
	}

	AuDbg("i%lu\n", (unsigned long)ino);
	inode = au_iget_locked(sb, ino);
	err = PTR_ERR(inode);
	if (IS_ERR(inode))
		goto out;

	AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW));
	if (inode->i_state & I_NEW) {
		ii_write_lock_new_child(inode);
		err = set_inode(inode, dentry);
		if (!err) {
			unlock_new_inode(inode);
			goto out; /* success */
		}

		ii_write_unlock(inode);
		iget_failed(inode);
		goto out_err;
	} else if (!must_new) {
		/*
		 * horrible race condition between lookup, readdir and copyup
		 * (or something).
		 */
		if (mtx)
			mutex_unlock(mtx);
		err = reval_inode(inode, dentry, &match);
		if (!err) {
			mtx = NULL;
			goto out; /* success */
		} else if (match) {
			mtx = NULL;
			goto out_iput;
		} else if (mtx)
			mutex_lock(mtx);
	}

	if (unlikely(au_test_fs_unique_ino(h_dentry->d_inode)))
		AuWarn1("Warning: Un-notified UDBA or repeatedly renamed dir,"
			" b%d, %s, %.*s, hi%lu, i%lu.\n",
			bstart, au_sbtype(h_dentry->d_sb), AuDLNPair(dentry),
			(unsigned long)h_ino, (unsigned long)ino);
	ino = 0;
	err = au_xino_write(sb, bstart, h_ino, /*ino*/0);
	if (!err) {
		iput(inode);
		if (mtx)
			mutex_unlock(mtx);
		goto new_ino;
	}

out_iput:
	iput(inode);
out_err:
	inode = ERR_PTR(err);
out:
	if (mtx)
		mutex_unlock(mtx);
	return inode;
}