Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e2761a11 authored by OGAWA Hirofumi's avatar OGAWA Hirofumi Committed by Al Viro
Browse files

[PATCH vfs-2.6 2/6] vfs: add d_ancestor()



This adds d_ancestor() instead of d_isparent(), then use it.

If new_dentry == old_dentry, is_subdir() returns 1, looks strange.
"new_dentry == old_dentry" is not subdir obviously. But I'm not
checking callers for now, so this keeps current behavior.

Signed-off-by: default avatarOGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
parent 871c0067
Loading
Loading
Loading
Loading
+23 −22
Original line number Diff line number Diff line
@@ -1720,18 +1720,23 @@ void d_move(struct dentry * dentry, struct dentry * target)
	spin_unlock(&dcache_lock);
}

/*
 * Helper that returns 1 if p1 is a parent of p2, else 0
/**
 * d_ancestor - search for an ancestor
 * @p1: ancestor dentry
 * @p2: child dentry
 *
 * Returns the ancestor dentry of p2 which is a child of p1, if p1 is
 * an ancestor of p2, else NULL.
 */
static int d_isparent(struct dentry *p1, struct dentry *p2)
struct dentry *d_ancestor(struct dentry *p1, struct dentry *p2)
{
	struct dentry *p;

	for (p = p2; !IS_ROOT(p); p = p->d_parent) {
		if (p->d_parent == p1)
			return 1;
			return p;
	}
	return 0;
	return NULL;
}

/*
@@ -1755,7 +1760,7 @@ static struct dentry *__d_unalias(struct dentry *dentry, struct dentry *alias)

	/* Check for loops */
	ret = ERR_PTR(-ELOOP);
	if (d_isparent(alias, dentry))
	if (d_ancestor(alias, dentry))
		goto out_err;

	/* See lock_rename() */
@@ -2158,28 +2163,24 @@ asmlinkage long sys_getcwd(char __user *buf, unsigned long size)
int is_subdir(struct dentry *new_dentry, struct dentry *old_dentry)
{
	int result;
	struct dentry * saved = new_dentry;
	unsigned long seq;

	/* need rcu_readlock to protect against the d_parent trashing due to
	 * d_move
	/* FIXME: This is old behavior, needed? Please check callers. */
	if (new_dentry == old_dentry)
		return 1;

	/*
	 * Need rcu_readlock to protect against the d_parent trashing
	 * due to d_move
	 */
	rcu_read_lock();
	do {
		/* for restarting inner loop in case of seq retry */
		new_dentry = saved;
		result = 0;
		seq = read_seqbegin(&rename_lock);
		for (;;) {
			if (new_dentry != old_dentry) {
				if (IS_ROOT(new_dentry))
					break;
				new_dentry = new_dentry->d_parent;
				continue;
			}
		if (d_ancestor(old_dentry, new_dentry))
			result = 1;
			break;
		}
		else
			result = 0;
	} while (read_seqretry(&rename_lock, seq));
	rcu_read_unlock();

+10 −12
Original line number Diff line number Diff line
@@ -1454,21 +1454,19 @@ struct dentry *lock_rename(struct dentry *p1, struct dentry *p2)

	mutex_lock(&p1->d_inode->i_sb->s_vfs_rename_mutex);

	for (p = p1; !IS_ROOT(p); p = p->d_parent) {
		if (p->d_parent == p2) {
	p = d_ancestor(p2, p1);
	if (p) {
		mutex_lock_nested(&p2->d_inode->i_mutex, I_MUTEX_PARENT);
		mutex_lock_nested(&p1->d_inode->i_mutex, I_MUTEX_CHILD);
		return p;
	}
	}

	for (p = p2; !IS_ROOT(p); p = p->d_parent) {
		if (p->d_parent == p1) {
	p = d_ancestor(p1, p2);
	if (p) {
		mutex_lock_nested(&p1->d_inode->i_mutex, I_MUTEX_PARENT);
		mutex_lock_nested(&p2->d_inode->i_mutex, I_MUTEX_CHILD);
		return p;
	}
	}

	mutex_lock_nested(&p1->d_inode->i_mutex, I_MUTEX_PARENT);
	mutex_lock_nested(&p2->d_inode->i_mutex, I_MUTEX_CHILD);
+1 −0
Original line number Diff line number Diff line
@@ -287,6 +287,7 @@ static inline struct dentry *d_add_unique(struct dentry *entry, struct inode *in

/* used for rename() and baskets */
extern void d_move(struct dentry *, struct dentry *);
extern struct dentry *d_ancestor(struct dentry *, struct dentry *);

/* appendix may either be NULL or be used for transname suffixes */
extern struct dentry * d_lookup(struct dentry *, struct qstr *);