lockd-2.2.2-1.patch

This patch addresses two problems in the lockd code.

1) the entire NFS file handle was being used to locate items
   in the lock hash.  This causes a new entry for each file-
   name, instead of one per file.  This is would be weirder
   with the new style nfs filehandles becuase there would
   be a hash entry per parent directory.

2) lockd should be independent of nfsd.  That is it should
   should not know anything about nfsd that is not described 
   in lock/bind.h.  But knfs_fh was in the code.  I added
   a new function to bind structure that return ino and
   dev from the nfs filehandle.

BUGS: lockd and nfsd must be updated together or bad things
      will happen. (Oops?)

TODO: The bind_hash structure does not need to be
      ino and dev.  It could be made more opaque.

TESTING: patch; complile; cthon/locks/tlock

   gam3@acm.org Fri Feb 26 00:24:08 PST 1999

---------------------------------------------------------
diff -u -X exclude linux-2.2.1/include/linux/lockd/bind.h linux/include/linux/lockd/bind.h
--- linux-2.2.1/include/linux/lockd/bind.h	Mon Apr  7 11:35:31 1997
+++ linux/include/linux/lockd/bind.h	Thu Feb 25 22:53:23 1999
@@ -3,7 +3,7 @@
  *
  * This is the part of lockd visible to nfsd and the nfs client.
  *
- * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
+ * Copyright (C) 1996,1999 Olaf Kirch <okir@monad.swb.de>
  */
 
 #ifndef LINUX_LOCKD_BIND_H
@@ -13,8 +13,12 @@
 
 /* Dummy declarations */
 struct svc_rqst;
-struct knfs_fh;
+struct nfs_fh;			/* opaque type */
 struct svc_client;		/* opaque type */
+struct bind_hash {
+	dev_t b_dev;
+	ino_t b_ino;
+};
 
 /*
  * This is the set of functions for lockd->nfsd communication
@@ -24,10 +28,13 @@
 	void			(*exp_unlock)(void);
 	struct svc_client *	(*exp_getclient)(struct sockaddr_in *);
 	u32			(*fopen)(struct svc_rqst *,
-						struct knfs_fh *,
+						struct nfs_fh *,
 						struct file *);
 	void			(*fclose)(struct file *);
 	void			(*detach)(void);
+	u32			(*gethash)(struct svc_rqst *,
+					  	  struct nfs_fh *,
+						  struct bind_hash *);
 };
 
 extern struct nlmsvc_binding *	nlmsvc_ops;
diff -u -X exclude linux-2.2.1/include/linux/lockd/lockd.h linux/include/linux/lockd/lockd.h
--- linux-2.2.1/include/linux/lockd/lockd.h	Mon Feb 22 19:36:44 1999
+++ linux/include/linux/lockd/lockd.h	Thu Feb 25 22:59:07 1999
@@ -71,7 +71,7 @@
  */
 struct nlm_file {
 	struct nlm_file *	f_next;		/* linked list */
-	struct knfs_fh		f_handle;	/* NFS file handle */
+	struct bind_hash	f_hash;		/* NFS file hash */
 	struct file		f_file;		/* VFS file pointer */
 	struct nlm_share *	f_shares;	/* DOS shares */
 	struct nlm_block *	f_blocks;	/* blocked locks */
diff -u -X exclude linux-2.2.1/fs/nfsd/lockd.c linux/fs/nfsd/lockd.c
--- linux-2.2.1/fs/nfsd/lockd.c	Mon Aug 31 11:03:38 1998
+++ linux/fs/nfsd/lockd.c	Fri Feb 26 00:00:55 1999
@@ -20,14 +20,14 @@
  * Note: we hold the dentry use count while the file is open.
  */
 static u32
-nlm_fopen(struct svc_rqst *rqstp, struct knfs_fh *f, struct file *filp)
+nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file *filp)
 {
 	u32		nfserr;
 	struct svc_fh	fh;
 
 	/* must initialize before using! */
 	fh_init(&fh);
-	fh.fh_handle = *f;
+	fh.fh_handle = *(struct knfs_fh *)f;
 	fh.fh_export = NULL;
 
 	nfserr = nfsd_open(rqstp, &fh, S_IFREG, 0, filp);
@@ -44,6 +44,20 @@
 	dput(filp->f_dentry);
 }
 
+/*
+ * FIXME: it may be that this should do some sort of security check
+ */
+
+static u32
+nlm_gethash(struct svc_rqst *rqstp, struct nfs_fh *f,
+            struct bind_hash *bhash)
+{
+	struct knfs_fh *fh = (struct nfs_fh *)f;
+	bhash->b_dev = u32_to_kdev_t(fh->fh_dev);
+	bhash->b_ino = u32_to_ino_t(fh->fh_ino);
+	return 0;
+}
+
 struct nlmsvc_binding		nfsd_nlm_ops = {
 	exp_readlock,		/* lock export table for reading */
 	exp_unlock,		/* unlock export table */
@@ -51,6 +65,7 @@
 	nlm_fopen,		/* open file for locking */
 	nlm_fclose,		/* close file */
 	exp_nlmdetach,		/* lockd shutdown notification */
+	nlm_gethash,		/* get data for lockd */
 };
 
 /*
diff -u -X exclude linux-2.2.1/fs/lockd/svcsubs.c linux/fs/lockd/svcsubs.c
--- linux-2.2.1/fs/lockd/svcsubs.c	Fri Jan  1 23:03:08 1999
+++ linux/fs/lockd/svcsubs.c	Fri Feb 26 00:11:46 1999
@@ -46,39 +46,44 @@
  */
 u32
 nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result,
-					struct nfs_fh *f)
+					struct nfs_fh *fh)
 {
-	struct knfs_fh	*fh = (struct knfs_fh *) f;
-	struct nlm_file	*file;
-	unsigned int	hash;
-	u32		nfserr;
-	uid_t		saved_cr_uid;
-	struct svc_cred	*cred;
-
-	dprintk("lockd: nlm_file_lookup(%s/%u)\n",
-		kdevname(u32_to_kdev_t(fh->fh_dev)), fh->fh_ino);
+	struct nlm_file	 *file;
+	unsigned int	 hash;
+	u32		 nfserr;
+	uid_t		 saved_cr_uid;
+	struct bind_hash bhash;
+	struct svc_cred	 *cred;
+
+	if ((nfserr = nlmsvc_ops->gethash(rqstp, fh, &bhash)) != 0) {
+		dprintk("lockd: gethash failed (nfserr %ld)\n", ntohl(nfserr));
+		goto out;
+	}
+	dprintk("lockd: nlm_file_lookup(%s/%ld)\n",
+	        kdevname(bhash.b_dev), bhash.b_ino);
 
-	hash = file_hash(u32_to_kdev_t(fh->fh_dev), u32_to_ino_t(fh->fh_ino));
+	hash = file_hash(bhash.b_dev, bhash.b_ino);
 
 	/* Lock file table */
 	down(&nlm_file_sema);
 
 	for (file = nlm_files[hash]; file; file = file->f_next) {
-		if (file->f_handle.fh_dcookie == fh->fh_dcookie &&
-		    !memcmp(&file->f_handle, fh, sizeof(*fh)))
+		if ((bhash.b_ino = file->f_file.f_dentry->d_inode->i_ino) &&
+		    (bhash.b_dev = file->f_file.f_dentry->d_inode->i_dev)) {
 			goto found;
+		}
 	}
 
-	dprintk("lockd: creating file for %s/%u\n",
-		kdevname(u32_to_kdev_t(fh->fh_dev)), fh->fh_ino);
+	dprintk("lockd: creating file for %s/%ld\n",
+	        kdevname(bhash.b_dev), bhash.b_ino);
 	nfserr = nlm_lck_denied_nolocks;
 	file = (struct nlm_file *) kmalloc(sizeof(*file), GFP_KERNEL);
 	if (!file)
 		goto out_unlock;
 
 	memset(file, 0, sizeof(*file));
-	file->f_handle = *fh;
-	file->f_sema   = MUTEX;
+	file->f_hash = bhash;
+	file->f_sema = MUTEX;
 
 	/* Open the file. Note that this must not sleep for too long, else
 	 * we would lock up lockd:-) So no NFS re-exports, folks.
@@ -107,6 +112,7 @@
 
 out_unlock:
 	up(&nlm_file_sema);
+out:
 	return nfserr;
 
 out_free:

