Skip to contentSkip to conversation

Fix d_find_alias brokenness

PATCH In review NeilBrown 1 participant 2 messages Nov 11, 2004 – Nov 12, 2004 2 messages not in the archive

Subsystems (3)
lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): 20041112105449.24459.patches@notabene

NeilBrown

author
#1 lore raw

PATCH 1/1 Fix d_find_alias brokenness

Hi Andrew,
it wold be great if this could get into 2.6.10 as it fixed a very noticable
problem with knfsd.

Thanks,
NeilBrown

### Comments for Changeset
A recent change to d_alloc_anon was a little broken, and needs a small change to d_find_alias to fix it.

Without this, a dcache flush on the server can cause stale file handles on the client.

### Diffstat output

 ./fs/dcache.c |   16 ++++++++++------
 1 files changed, 10 insertions(+), 6 deletions(-)
fs/dcache.c renamed from fs/dcache.c~current~ +10 -6
diff ./fs/dcache.c~current~ ./fs/dcache.c
@@ -279,14 +279,18 @@ struct dentry * dget_locked(struct dentr
 /**
  * d_find_alias - grab a hashed alias of inode
  * @inode: inode in question
+ * @want_discon:  flag, used by d_splice_alias, to request 
+ *          that only a DISCONNECTED alias be returned.
  *
- * If inode has a hashed alias - acquire the reference to alias and
- * return it. Otherwise return NULL. Notice that if inode is a directory
- * there can be only one alias and it can be unhashed only if it has
- * no children.
+ * If inode has a hashed alias, or is a directory and has any alias,
+ * acquire the reference to alias and return it. Otherwise return NULL.
+ * Notice that if inode is a directory there can be only one alias and
+ * it can be unhashed only if it has no children, or if it is the root 
+ * of a filesystem.
  *
  * If the inode has a DCACHE_DISCONNECTED alias, then prefer
- * any other hashed alias over that one.
+ * any other hashed alias over that one unless @want_discon is set,
+ * in which case only return a DCACHE_DISCONNECTED alias.
  */
 
 static struct dentry * __d_find_alias(struct inode *inode, int want_discon)
@@ -301,7 +305,7 @@ static struct dentry * __d_find_alias(st
 		next = tmp->next;
 		prefetch(next);
 		alias = list_entry(tmp, struct dentry, d_alias);
- 		if (!d_unhashed(alias)) {
+ 		if (S_ISDIR(inode->i_mode) || !d_unhashed(alias)) {
 			if (alias->d_flags & DCACHE_DISCONNECTED)
 				discon_alias = alias;
 			else if (!want_discon) {

-------------------------------------------------------
This SF.Net email is sponsored by:
Sybase ASE Linux Express Edition - download now for FREE LinuxWorld Reader's Choice Award Winner for best database on Linux.
http://ads.osdn.com/?ad_id=5588&alloc_id=12065&op=click
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

A message that is not in the archive (sent off-list or not yet received): [email protected]

author
#3 lore raw
Quoted 3 lines · On Thursday November 11, [email protected] wrote:

Could I trouble you for a more complete description? Which was the offending change, and in what way was it broken?

10 weeks ago,
http://linux.bkbits.com:8080/linux-2.5/cset@415b3380pxf4sB97gM8ujLqDxi6GfQ

The patch was mostly right, and fixed a real problem, but missed a bit.
It passed the job of checking if an inode had a current alias off to d_find_alias instead of open-coding it in d_alloc_anon. However there is one case where d_alloc_anon would not return the right dentry. That case being when the inode was for the root of the filesystem.
The root is a special case because it is not hashed. All other dentries that are not hashed are quite un-interesting: There are "unlinked" but not yet closed. The root of a filesystem is unhashed, but is interesting.

Allowing d_find_alias to return an unhashed alias for a directory solves this problem. It is safe because callers of d_find_alias on a directory inode either have a name for the inode already (so finding an unlinked directory by mistake is impossible) or will soon be looking for a name and will drop the dentry if a name is not found.

NeilBrown

-------------------------------------------------------
This SF.Net email is sponsored by:
Sybase ASE Linux Express Edition - download now for FREE LinuxWorld Reader's Choice Award Winner for best database on Linux.
http://ads.osdn.com/?ad_id=5588&alloc_id=12065&op=click
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs