From patchwork Mon Jun 28 11:10:13 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Layton X-Patchwork-Id: 108336 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.4/8.14.3) with ESMTP id o5SBAGJC000947 for ; Mon, 28 Jun 2010 11:10:20 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751504Ab0F1LKR (ORCPT ); Mon, 28 Jun 2010 07:10:17 -0400 Received: from cdptpa-omtalb.mail.rr.com ([75.180.132.121]:55867 "EHLO cdptpa-omtalb.mail.rr.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751263Ab0F1LKO (ORCPT ); Mon, 28 Jun 2010 07:10:14 -0400 X-Authority-Analysis: v=1.1 cv=7qLQTOyu9xTBqhpUHgmrs7bafsFFGlkSRBtYgNIkZcY= c=1 sm=0 a=zfZbGrQD9eAA:10 a=ygRHs6EKU7oA:10 a=ld/erqUjW76FpBUqCqkKeA==:17 a=20KFwNOVAAAA:8 a=_-ooyrUg1VAsmJShslMA:9 a=oIXNXUG8VPBShWM1yy0A:7 a=3MXRQvDpWMsl5MKiAU17TVjTgTsA:4 a=jEp0ucaQiEUA:10 a=ld/erqUjW76FpBUqCqkKeA==:117 X-Cloudmark-Score: 0 X-Originating-IP: 71.70.153.3 Received: from [71.70.153.3] ([71.70.153.3:50343] helo=mail.poochiereds.net) by cdptpa-oedge02.mail.rr.com (envelope-from ) (ecelerity 2.2.2.39 r()) with ESMTP id 49/BB-12872-513882C4; Mon, 28 Jun 2010 11:10:13 +0000 Received: by mail.poochiereds.net (Postfix, from userid 4447) id 359C758105; Mon, 28 Jun 2010 07:10:13 -0400 (EDT) From: Jeff Layton To: linux-cifs@vger.kernel.org Cc: linux-fsdevel@vger.kernel.org Subject: [PATCH 3/3] cifs: reduce false positives with inode aliasing serverino autodisable Date: Mon, 28 Jun 2010 07:10:13 -0400 Message-Id: <1277723413-23769-4-git-send-email-jlayton@redhat.com> X-Mailer: git-send-email 1.6.6.1 In-Reply-To: <1277723413-23769-1-git-send-email-jlayton@redhat.com> References: <1277723413-23769-1-git-send-email-jlayton@redhat.com> Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Mon, 28 Jun 2010 11:10:20 +0000 (UTC) diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 35e2466..1bfb8ec 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -736,15 +736,9 @@ cifs_find_inode(struct inode *inode, void *opaque) if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT)) return 0; - /* - * uh oh -- it's a directory. We can't use it since hardlinked dirs are - * verboten. Disable serverino and return it as if it were found, the - * caller can discard it, generate a uniqueid and retry the find - */ - if (S_ISDIR(inode->i_mode) && !list_empty(&inode->i_dentry)) { + /* if it's not a directory or has no dentries, then flag it */ + if (S_ISDIR(inode->i_mode) && !list_empty(&inode->i_dentry)) fattr->cf_flags |= CIFS_FATTR_INO_COLLISION; - cifs_autodisable_serverino(CIFS_SB(inode->i_sb)); - } return 1; } @@ -759,6 +753,27 @@ cifs_init_inode(struct inode *inode, void *opaque) return 0; } +/* + * walk dentry list for an inode and report whether it has aliases that + * are hashed. We use this to determine if a directory inode can actually + * be used. + */ +static bool +inode_has_hashed_dentries(struct inode *inode) +{ + struct dentry *dentry; + + spin_lock(&dcache_lock); + list_for_each_entry(dentry, &inode->i_dentry, d_alias) { + if (!d_unhashed(dentry) || IS_ROOT(dentry)) { + spin_unlock(&dcache_lock); + return true; + } + } + spin_unlock(&dcache_lock); + return false; +} + /* Given fattrs, get a corresponding inode */ struct inode * cifs_iget(struct super_block *sb, struct cifs_fattr *fattr) @@ -774,12 +789,16 @@ retry_iget5_locked: inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr); if (inode) { - /* was there a problematic inode number collision? */ + /* was there a potentially problematic inode collision? */ if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) { - iput(inode); - fattr->cf_uniqueid = iunique(sb, ROOT_I); fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION; - goto retry_iget5_locked; + + if (inode_has_hashed_dentries(inode)) { + cifs_autodisable_serverino(CIFS_SB(sb)); + iput(inode); + fattr->cf_uniqueid = iunique(sb, ROOT_I); + goto retry_iget5_locked; + } } cifs_fattr_to_inode(inode, fattr);