Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754089AbYJOWvn (ORCPT ); Wed, 15 Oct 2008 18:51:43 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1754168AbYJOWuf (ORCPT ); Wed, 15 Oct 2008 18:50:35 -0400 Received: from mail.parknet.ad.jp ([210.171.162.6]:54097 "EHLO mail.officemail.jp" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753992AbYJOWud (ORCPT ); Wed, 15 Oct 2008 18:50:33 -0400 Subject: [PATCH vfs-2.6 2/6] vfs: add d_ancestor() To: viro@zeniv.linux.org.uk Cc: akpm@linux-foundation.org, linux-kernel@vger.kernel.org, hirofumi@mail.parknet.co.jp From: OGAWA Hirofumi Date: Thu, 16 Oct 2008 07:50:28 +0900 Message-ID: References: In-Reply-To: X-Anti-Virus: Kaspersky Anti-Virus for MailServers 5.5.10/RELEASE, bases: 24052007 #308098, status: clean Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 4749 Lines: 152 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 --- fs/dcache.c | 45 +++++++++++++++++++++++---------------------- fs/namei.c | 22 ++++++++++------------ include/linux/dcache.h | 1 + 3 files changed, 34 insertions(+), 34 deletions(-) diff -puN fs/dcache.c~dcache-cleanup-2 fs/dcache.c --- vfs-2.6/fs/dcache.c~dcache-cleanup-2 2008-10-16 06:57:29.000000000 +0900 +++ vfs-2.6-hirofumi/fs/dcache.c 2008-10-16 06:57:29.000000000 +0900 @@ -1718,18 +1718,23 @@ void d_move(struct dentry * dentry, stru 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; } /* @@ -1753,7 +1758,7 @@ static struct dentry *__d_unalias(struct /* Check for loops */ ret = ERR_PTR(-ELOOP); - if (d_isparent(alias, dentry)) + if (d_ancestor(alias, dentry)) goto out_err; /* See lock_rename() */ @@ -2153,31 +2158,27 @@ out: * Caller must ensure that "new_dentry" is pinned before calling is_subdir() */ -int is_subdir(struct dentry * new_dentry, struct dentry * old_dentry) +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 { + 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(); diff -puN include/linux/dcache.h~dcache-cleanup-2 include/linux/dcache.h --- vfs-2.6/include/linux/dcache.h~dcache-cleanup-2 2008-10-16 06:57:29.000000000 +0900 +++ vfs-2.6-hirofumi/include/linux/dcache.h 2008-10-16 06:57:29.000000000 +0900 @@ -287,6 +287,7 @@ static inline struct dentry *d_add_uniqu /* 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 *); diff -puN fs/namei.c~dcache-cleanup-2 fs/namei.c --- vfs-2.6/fs/namei.c~dcache-cleanup-2 2008-10-16 06:57:29.000000000 +0900 +++ vfs-2.6-hirofumi/fs/namei.c 2008-10-16 06:57:29.000000000 +0900 @@ -1454,20 +1454,18 @@ struct dentry *lock_rename(struct dentry 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) { - mutex_lock_nested(&p2->d_inode->i_mutex, I_MUTEX_PARENT); - mutex_lock_nested(&p1->d_inode->i_mutex, I_MUTEX_CHILD); - return p; - } + 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) { - mutex_lock_nested(&p1->d_inode->i_mutex, I_MUTEX_PARENT); - mutex_lock_nested(&p2->d_inode->i_mutex, I_MUTEX_CHILD); - return p; - } + 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); _ -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/