Sophie

Sophie

distrib > Mandriva > 10.0-com > i586 > by-pkgid > 276c4c69ed5efcebe43ee6121194cf59 > files > 47

kernel22-2.2.20-9mdk.src.rpm

diff -urN 2.2.19pre3/fs/nfsd/nfsfh.c nfsd/fs/nfsd/nfsfh.c
--- 2.2.19pre3/fs/nfsd/nfsfh.c	Mon Dec 11 16:58:01 2000
+++ nfsd/fs/nfsd/nfsfh.c	Sun Dec 24 17:01:28 2000
@@ -114,6 +114,38 @@
 	return error;
 }
 
+/* Arrange a dentry for the given inode:
+ *  1. Prefer an existing connected dentry.
+ *  2. Settle for an existing disconnected dentry.
+ *  3. If necessary, create a (disconnected) dentry.
+ */
+static struct dentry *nfsd_arrange_dentry(struct inode *inode)
+{
+	struct list_head *lp;
+	struct dentry *result;
+
+	result = NULL;
+	for (lp = inode->i_dentry.next; lp != &inode->i_dentry ; lp=lp->next) {
+		result = list_entry(lp,struct dentry, d_alias);
+		if (! (result->d_flags & DCACHE_NFSD_DISCONNECTED))
+			break;
+	}
+	if (result) {
+		dget(result);
+		iput(inode);
+	} else {
+		result = d_alloc_root(inode, NULL);
+		if (!result) {
+			iput(inode);
+			return ERR_PTR(-ENOMEM);
+		}
+		result->d_flags |= DCACHE_NFSD_DISCONNECTED;
+		d_rehash(result); /* so a dput won't loose it */
+	}
+	return result;
+}
+
+
 /* this should be provided by each filesystem in an nfsd_operations interface as
  * iget isn't really the right interface
  */
@@ -128,8 +160,6 @@
 	 * so a generation of 0 means "accept any"
 	 */
 	struct inode *inode;
-	struct list_head *lp;
-	struct dentry *result;
 	inode = iget_in_use(sb, ino);
 	if (!inode) {
 		dprintk("nfsd_iget: failed to find ino: %lu on %s\n",
@@ -149,25 +179,8 @@
 		iput(inode);
 		return ERR_PTR(-ESTALE);
 	}
-	/* now to find a dentry.
-	 * If possible, get a well-connected one
-	 */
-	for (lp = inode->i_dentry.next; lp != &inode->i_dentry ; lp=lp->next) {
-		result = list_entry(lp,struct dentry, d_alias);
-		if (! (result->d_flags & DCACHE_NFSD_DISCONNECTED)) {
-			dget(result);
-			iput(inode);
-			return result;
-		}
-	}
-	result = d_alloc_root(inode, NULL);
-	if (result == NULL) {
-		iput(inode);
-		return ERR_PTR(-ENOMEM);
-	}
-	result->d_flags |= DCACHE_NFSD_DISCONNECTED;
-	d_rehash(result); /* so a dput won't loose it */
-	return result;
+
+	return nfsd_arrange_dentry(inode);
 }
 
 /* this routine links an IS_ROOT dentry into the dcache tree.  It gains "parent"
@@ -228,45 +241,27 @@
  */
 struct dentry *nfsd_findparent(struct dentry *child)
 {
-	struct dentry *tdentry, *pdentry;
-	tdentry = d_alloc(child, &(const struct qstr) {"..", 2, 0});
-	if (!tdentry)
+	struct dentry *dotdot, *parent;
+
+	dotdot = d_alloc(child, &(const struct qstr) {"..", 2, 0});
+	if (!dotdot)
 		return ERR_PTR(-ENOMEM);
 
 	/* I'm going to assume that if the returned dentry is different, then
 	 * it is well connected.  But nobody returns different dentrys do they?
 	 */
-	pdentry = child->d_inode->i_op->lookup(child->d_inode, tdentry);
-	d_drop(tdentry); /* we never want ".." hashed */
-	if (!pdentry) {
-		/* I don't want to return a ".." dentry.
-		 * I would prefer to return an unconnected "IS_ROOT" dentry,
-		 * though a properly connected dentry is even better
-		 */
-		/* if first or last of alias list is not tdentry, use that
-		 * else make a root dentry
-		 */
-		struct list_head *aliases = &tdentry->d_inode->i_dentry;
-		if (aliases->next != aliases) {
-			pdentry = list_entry(aliases->next, struct dentry, d_alias);
-			if (pdentry == tdentry)
-				pdentry = list_entry(aliases->prev, struct dentry, d_alias);
-			if (pdentry == tdentry)
-				pdentry = NULL;
-			if (pdentry) dget(pdentry);
-		}
-		if (pdentry == NULL) {
-			pdentry = d_alloc_root(igrab(tdentry->d_inode), NULL);
-			if (pdentry) {
-				pdentry->d_flags |= DCACHE_NFSD_DISCONNECTED;
-				d_rehash(pdentry);
-			}
-		}
-		if (pdentry == NULL)
-			pdentry = ERR_PTR(-ENOMEM);
+	parent = child->d_inode->i_op->lookup(child->d_inode, dotdot);
+	d_drop(dotdot); /* we never want ".." hashed */
+
+	if (parent)
+		dput(dotdot); /* not hashed, thus discarded */
+	else {
+		/* Discard the ".." dentry, then arrange for a better one */
+		struct inode *inode = igrab(dotdot->d_inode);
+		dput(dotdot); /* not hashed, thus discarded */
+		parent = nfsd_arrange_dentry(inode);
 	}
-	dput(tdentry); /* it is not hashed, it will be discarded */
-	return pdentry;
+	return parent;
 }
 
 static struct dentry *splice(struct dentry *child, struct dentry *parent)