From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Aneesh Kumar K.V" Subject: [PATCH] vfs: Don't rehash the dentry on successfull deletion Date: Wed, 16 Feb 2011 16:44:46 +0530 Message-ID: <1297854886-2672-1-git-send-email-aneesh.kumar@linux.vnet.ibm.com> Cc: linux-fsdevel@vger.kernel.org, "Aneesh Kumar K.V" , Sage Weil , Miklos Szeredi To: hch@infradead.org, viro@zeniv.linux.org.uk Return-path: Received: from e28smtp05.in.ibm.com ([122.248.162.5]:44524 "EHLO e28smtp05.in.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755856Ab1BPLPV (ORCPT ); Wed, 16 Feb 2011 06:15:21 -0500 Received: from d28relay01.in.ibm.com (d28relay01.in.ibm.com [9.184.220.58]) by e28smtp05.in.ibm.com (8.14.4/8.13.1) with ESMTP id p1GBFJ3Y009643 for ; Wed, 16 Feb 2011 16:45:19 +0530 Received: from d28av02.in.ibm.com (d28av02.in.ibm.com [9.184.220.64]) by d28relay01.in.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id p1GBFJG84333746 for ; Wed, 16 Feb 2011 16:45:19 +0530 Received: from d28av02.in.ibm.com (loopback [127.0.0.1]) by d28av02.in.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id p1GBFIlL025541 for ; Wed, 16 Feb 2011 22:15:19 +1100 Sender: linux-fsdevel-owner@vger.kernel.org List-ID: vfs_rename_dir() doesn't properly account for filesystems with FS_RENAME_DOES_D_MOVE. If new_dentry has a target inode attached, it unhashes the new_dentry prior to the rename() iop and rehashes it after, but doesn't account for the possibility that rename() may have swapped {old,new}_dentry. For FS_RENAME_DOES_D_MOVE filesystems, it rehashes new_dentry (now the old renamed-from name, which d_move() expected to go away), such that a subsequent lookup will find it... and the overwritte target inode. To correct this call d_rehash only in case of error or in if the file systems doesn't do d_move itself. Based on the original patch by Sage Weil http://kerneltrap.org/mailarchive/linux-fsdevel/2008/4/18/1498534 Cc: Zach Brown Cc: Miklos Szeredi Signed-off-by: Aneesh Kumar K.V --- fs/namei.c | 11 +++++++++-- 1 files changed, 9 insertions(+), 2 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index 7d77f24..5631ccf 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -3259,8 +3259,15 @@ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, dont_mount(new_dentry); } mutex_unlock(&target->i_mutex); - if (d_unhashed(new_dentry)) - d_rehash(new_dentry); + /* + * if rename callback returned success and we have + * FS_RENAME_DOES_D_MOVE set, then don't do the + * rehash. + */ + if (error || + !(old_dir->i_sb->s_type->fs_flags & FS_RENAME_DOES_D_MOVE)) + if (d_unhashed(new_dentry)) + d_rehash(new_dentry); dput(new_dentry); } if (!error) -- 1.7.1