Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1759897AbYBQDBq (ORCPT ); Sat, 16 Feb 2008 22:01:46 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1757725AbYBQC6b (ORCPT ); Sat, 16 Feb 2008 21:58:31 -0500 Received: from filer.fsl.cs.sunysb.edu ([130.245.126.2]:36356 "EHLO filer.fsl.cs.sunysb.edu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757617AbYBQC60 (ORCPT ); Sat, 16 Feb 2008 21:58:26 -0500 From: Erez Zadok To: akpm@linux-foundation.org Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, viro@ftp.linux.org.uk, hch@infradead.org, Erez Zadok Subject: [PATCH 10/17] Unionfs: factor out revalidation routine Date: Sat, 16 Feb 2008 21:57:19 -0500 Message-Id: <1203217051613-git-send-email-ezk@cs.sunysb.edu> X-Mailer: git-send-email 1.5.2.2 X-MailKey: Erez_Zadok In-Reply-To: <12032170461107-git-send-email-ezk@cs.sunysb.edu> References: <12032170461107-git-send-email-ezk@cs.sunysb.edu> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 4902 Lines: 139 To be used by rest of revalidation code, as well a callers who already locked the child and parent dentry branch-configurations. Signed-off-by: Erez Zadok --- fs/unionfs/dentry.c | 87 +++++++++++++++++++++++++++++++------------------- fs/unionfs/union.h | 3 ++ 2 files changed, 57 insertions(+), 33 deletions(-) diff --git a/fs/unionfs/dentry.c b/fs/unionfs/dentry.c index afa2120..3bd2dfb 100644 --- a/fs/unionfs/dentry.c +++ b/fs/unionfs/dentry.c @@ -285,6 +285,59 @@ void purge_sb_data(struct super_block *sb) } /* + * Revalidate a single file/symlink/special dentry. Assume that info nodes + * of the dentry and its parent are locked. Assume that parent(s) are all + * valid already, but the child may not yet be valid. Returns true if + * valid, false otherwise. + */ +bool __unionfs_d_revalidate_one_locked(struct dentry *dentry, + struct nameidata *nd, + bool willwrite) +{ + bool valid = false; /* default is invalid */ + int sbgen, dgen, bindex; + + verify_locked(dentry); + verify_locked(dentry->d_parent); + + sbgen = atomic_read(&UNIONFS_SB(dentry->d_sb)->generation); + dgen = atomic_read(&UNIONFS_D(dentry)->generation); + + if (unlikely(is_newer_lower(dentry))) { + /* root dentry special case as aforementioned */ + if (IS_ROOT(dentry)) { + unionfs_copy_attr_times(dentry->d_inode); + } else { + /* + * reset generation number to zero, guaranteed to be + * "old" + */ + dgen = 0; + atomic_set(&UNIONFS_D(dentry)->generation, dgen); + } + if (!willwrite) + purge_inode_data(dentry->d_inode); + } + valid = __unionfs_d_revalidate_one(dentry, nd); + + /* + * If __unionfs_d_revalidate_one() succeeded above, then it will + * have incremented the refcnt of the mnt's, but also the branch + * indices of the dentry will have been updated (to take into + * account any branch insertions/deletion. So the current + * dbstart/dbend match the current, and new, indices of the mnts + * which __unionfs_d_revalidate_one has incremented. Note: the "if" + * test below does not depend on whether chain_len was 0 or greater. + */ + if (!valid || sbgen == dgen) + goto out; + for (bindex = dbstart(dentry); bindex <= dbend(dentry); bindex++) + unionfs_mntput(dentry, bindex); +out: + return valid; +} + +/* * Revalidate a parent chain of dentries, then the actual node. * Assumes that dentry is locked, but will lock all parents if/when needed. * @@ -404,42 +457,10 @@ out_this: if (dentry != dentry->d_parent) unionfs_lock_dentry(dentry->d_parent, UNIONFS_DMUTEX_REVAL_PARENT); - dgen = atomic_read(&UNIONFS_D(dentry)->generation); - - if (unlikely(is_newer_lower(dentry))) { - /* root dentry special case as aforementioned */ - if (IS_ROOT(dentry)) { - unionfs_copy_attr_times(dentry->d_inode); - } else { - /* - * reset generation number to zero, guaranteed to be - * "old" - */ - dgen = 0; - atomic_set(&UNIONFS_D(dentry)->generation, dgen); - } - if (!willwrite) - purge_inode_data(dentry->d_inode); - } - valid = __unionfs_d_revalidate_one(dentry, nd); + valid = __unionfs_d_revalidate_one_locked(dentry, nd, willwrite); if (dentry != dentry->d_parent) unionfs_unlock_dentry(dentry->d_parent); - /* - * If __unionfs_d_revalidate_one() succeeded above, then it will - * have incremented the refcnt of the mnt's, but also the branch - * indices of the dentry will have been updated (to take into - * account any branch insertions/deletion. So the current - * dbstart/dbend match the current, and new, indices of the mnts - * which __unionfs_d_revalidate_one has incremented. Note: the "if" - * test below does not depend on whether chain_len was 0 or greater. - */ - if (valid && sbgen != dgen) - for (bindex = dbstart(dentry); - bindex <= dbend(dentry); - bindex++) - unionfs_mntput(dentry, bindex); - out_free: /* unlock/dput all dentries in chain and return status */ if (chain_len > 0) { diff --git a/fs/unionfs/union.h b/fs/unionfs/union.h index 0e0ccde..5001b07 100644 --- a/fs/unionfs/union.h +++ b/fs/unionfs/union.h @@ -368,6 +368,9 @@ extern int unionfs_rename(struct inode *old_dir, struct dentry *old_dentry, extern int unionfs_unlink(struct inode *dir, struct dentry *dentry); extern int unionfs_rmdir(struct inode *dir, struct dentry *dentry); +extern bool __unionfs_d_revalidate_one_locked(struct dentry *dentry, + struct nameidata *nd, + bool willwrite); extern bool __unionfs_d_revalidate_chain(struct dentry *dentry, struct nameidata *nd, bool willwrite); extern bool is_newer_lower(const struct dentry *dentry); -- 1.5.2.2 -- 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/