aboutsummaryrefslogtreecommitdiffstats
path: root/fs/dcache.c
diff options
context:
space:
mode:
authorOGAWA Hirofumi <hirofumi@mail.parknet.co.jp>2008-10-15 18:50:28 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2008-10-23 05:13:16 -0400
commite2761a1167633ed943fea29002f990194923d060 (patch)
treee91816e85c7721fcff72e5f84336b1dde9d1ac17 /fs/dcache.c
parent871c0067d53ba2dc35897c7da1da675bf4c70511 (diff)
[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: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Diffstat (limited to 'fs/dcache.c')
-rw-r--r--fs/dcache.c45
1 files changed, 23 insertions, 22 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index c6fd1f27da57..64024005da43 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1720,18 +1720,23 @@ void d_move(struct dentry * dentry, struct dentry * target)
1720 spin_unlock(&dcache_lock); 1720 spin_unlock(&dcache_lock);
1721} 1721}
1722 1722
1723/* 1723/**
1724 * Helper that returns 1 if p1 is a parent of p2, else 0 1724 * d_ancestor - search for an ancestor
1725 * @p1: ancestor dentry
1726 * @p2: child dentry
1727 *
1728 * Returns the ancestor dentry of p2 which is a child of p1, if p1 is
1729 * an ancestor of p2, else NULL.
1725 */ 1730 */
1726static int d_isparent(struct dentry *p1, struct dentry *p2) 1731struct dentry *d_ancestor(struct dentry *p1, struct dentry *p2)
1727{ 1732{
1728 struct dentry *p; 1733 struct dentry *p;
1729 1734
1730 for (p = p2; !IS_ROOT(p); p = p->d_parent) { 1735 for (p = p2; !IS_ROOT(p); p = p->d_parent) {
1731 if (p->d_parent == p1) 1736 if (p->d_parent == p1)
1732 return 1; 1737 return p;
1733 } 1738 }
1734 return 0; 1739 return NULL;
1735} 1740}
1736 1741
1737/* 1742/*
@@ -1755,7 +1760,7 @@ static struct dentry *__d_unalias(struct dentry *dentry, struct dentry *alias)
1755 1760
1756 /* Check for loops */ 1761 /* Check for loops */
1757 ret = ERR_PTR(-ELOOP); 1762 ret = ERR_PTR(-ELOOP);
1758 if (d_isparent(alias, dentry)) 1763 if (d_ancestor(alias, dentry))
1759 goto out_err; 1764 goto out_err;
1760 1765
1761 /* See lock_rename() */ 1766 /* See lock_rename() */
@@ -2155,31 +2160,27 @@ out:
2155 * Caller must ensure that "new_dentry" is pinned before calling is_subdir() 2160 * Caller must ensure that "new_dentry" is pinned before calling is_subdir()
2156 */ 2161 */
2157 2162
2158int is_subdir(struct dentry * new_dentry, struct dentry * old_dentry) 2163int is_subdir(struct dentry *new_dentry, struct dentry *old_dentry)
2159{ 2164{
2160 int result; 2165 int result;
2161 struct dentry * saved = new_dentry;
2162 unsigned long seq; 2166 unsigned long seq;
2163 2167
2164 /* need rcu_readlock to protect against the d_parent trashing due to 2168 /* FIXME: This is old behavior, needed? Please check callers. */
2165 * d_move 2169 if (new_dentry == old_dentry)
2170 return 1;
2171
2172 /*
2173 * Need rcu_readlock to protect against the d_parent trashing
2174 * due to d_move
2166 */ 2175 */
2167 rcu_read_lock(); 2176 rcu_read_lock();
2168 do { 2177 do {
2169 /* for restarting inner loop in case of seq retry */ 2178 /* for restarting inner loop in case of seq retry */
2170 new_dentry = saved;
2171 result = 0;
2172 seq = read_seqbegin(&rename_lock); 2179 seq = read_seqbegin(&rename_lock);
2173 for (;;) { 2180 if (d_ancestor(old_dentry, new_dentry))
2174 if (new_dentry != old_dentry) {
2175 if (IS_ROOT(new_dentry))
2176 break;
2177 new_dentry = new_dentry->d_parent;
2178 continue;
2179 }
2180 result = 1; 2181 result = 1;
2181 break; 2182 else
2182 } 2183 result = 0;
2183 } while (read_seqretry(&rename_lock, seq)); 2184 } while (read_seqretry(&rename_lock, seq));
2184 rcu_read_unlock(); 2185 rcu_read_unlock();
2185 2186