From mboxrd@z Thu Jan 1 00:00:00 1970 From: Sage Weil Subject: [PATCH 2/3] ceph: take a reference to the dentry in d_find_any_alias() Date: Thu, 22 Dec 2011 12:13:10 -0800 Message-ID: <1324584791-31933-2-git-send-email-sage@newdream.net> References: <1324584791-31933-1-git-send-email-sage@newdream.net> Return-path: Received: from cobra.newdream.net ([66.33.216.30]:45296 "EHLO cobra.newdream.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753896Ab1LVURM (ORCPT ); Thu, 22 Dec 2011 15:17:12 -0500 In-Reply-To: <1324584791-31933-1-git-send-email-sage@newdream.net> Sender: ceph-devel-owner@vger.kernel.org List-ID: To: ceph-devel@vger.kernel.org Cc: Alex Elder From: Alex Elder The ceph code duplicates __d_find_any_alias(), but it currently does not take a reference to the returned dentry as it should. Replace the ceph implementation with an exact copy of what's found in "fs/dcache.c", and update the callers so they drop their reference when they're done with it. Unfortunately this requires the wholesale copy of the functions that implement __dget(). It would be much nicer to just export d_find_any_alias() from "fs/dcache.c" instead. Signed-off-by: Alex Elder --- fs/ceph/dir.c | 31 +++++++++++++++++++++++++------ 1 files changed, 25 insertions(+), 6 deletions(-) diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index e58b0d1..caddb7d 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -1091,9 +1091,20 @@ static int ceph_snapdir_d_revalidate(struct dentry *dentry, return 1; } -/* - * Set/clear/test dir complete flag on the dir's dentry. - */ +/* The following code copied from "fs/dcache.c" */ +/* This must be called with d_lock held */ +static inline void __dget_dlock(struct dentry *dentry) +{ + dentry->d_count++; +} + +static inline void __dget(struct dentry *dentry) +{ + spin_lock(&dentry->d_lock); + __dget_dlock(dentry); + spin_unlock(&dentry->d_lock); +} + static struct dentry * __d_find_any_alias(struct inode *inode) { struct dentry *alias; @@ -1101,10 +1112,10 @@ static struct dentry * __d_find_any_alias(struct inode *inode) if (list_empty(&inode->i_dentry)) return NULL; alias = list_first_entry(&inode->i_dentry, struct dentry, d_alias); + __dget(alias); return alias; } -/* The following code copied from "fs/dcache.c" */ static struct dentry * d_find_any_alias(struct inode *inode) { struct dentry *de; @@ -1116,6 +1127,9 @@ static struct dentry * d_find_any_alias(struct inode *inode) } /* End of code copied from "fs/dcache.c" */ +/* + * Set/clear/test dir complete flag on the dir's dentry. + */ void ceph_dir_set_complete(struct inode *inode) { struct dentry *dentry = d_find_any_alias(inode); @@ -1124,6 +1138,7 @@ void ceph_dir_set_complete(struct inode *inode) dout(" marking %p (%p) complete\n", inode, dentry); set_bit(CEPH_D_COMPLETE, &ceph_dentry(dentry)->flags); } + dput(dentry); } void ceph_dir_clear_complete(struct inode *inode) @@ -1134,15 +1149,19 @@ void ceph_dir_clear_complete(struct inode *inode) dout(" marking %p (%p) NOT complete\n", inode, dentry); clear_bit(CEPH_D_COMPLETE, &ceph_dentry(dentry)->flags); } + dput(dentry); } bool ceph_dir_test_complete(struct inode *inode) { struct dentry *dentry = d_find_any_alias(inode); + bool ret = false; if (dentry && ceph_dentry(dentry)) - return test_bit(CEPH_D_COMPLETE, &ceph_dentry(dentry)->flags); - return false; + ret = test_bit(CEPH_D_COMPLETE, &ceph_dentry(dentry)->flags); + dput(dentry); + + return ret; } /* -- 1.7.5.4