NFS utils for 2.1.32

Olaf Kirch (okir@monad.swb.de)
Tue, 08 Apr 1997 03:16:39 +0200


Sorry for the confusion, I should really have included some documentation
along with the new NFS code, but I was away at the Linux Expo...

Anyway, here's the story in brief:

* Get linux-nfs-0.4.21.tar.gz from
ftp.mathematik.th-darmstadt.de/pub/linux/okir or
linux.nrao.edu/pub/people/okir
It contains all the utilities you need. It also contains a
copy of the code that's now in the kernel; just remove the
kernel target from Makefile.

* To use the NFS client fully, you need at least the patched mount
program. If you don't want to use file locking, mount all your
NFS volumes using -o no_lock.

* If you do want to test the file locking code, you must create
/var/lib/nfs/sm and install and run rpc.statd.

* To run nfsd, include nfsd in your kernel and run
the and rpc.mountd and rpc.nfsd included in the package.
rpc.kmountd
rpc.knfsd 4
kexports -va
will start four server threads. (By default, these will will
be installed with a leading `k' in order not to overwrite existing
programs--yet :).

* If something does not work, please send me bug reports. The utils
package contains a tool called rpcdebug, by which you can enable
and disable various logging features. Use
rpcdebug -m <module> <flags>
where module can be one of rpc, nfs, nfsd, and nlm (for lockd).
Each module supports a different set of flags; the easiest way
is to use `all'.
If you provide me with debug logs of how things go wrong, this
will help me a lot.

* Also, volunteers are welcome to participate in maintaining the
user utilities, write manpages etc. Of course, kernel patches
are also welcome.

Below I'm appending a kernel patch that lets you compile NFS as a module,
and enables the /proc files for NFS statistics (can be printed out using
knfsstat). Depending on your setup, you may also have to add one of the
ksyms patches posted to the list by other people.

Cheers
Olaf

-- 
Olaf Kirch        | Why don't you try assert(__TUBORG__); ?
okir@monad.swb.de | 			--Olaf Titz (no relation)
------------------------------------------------------------------
diff -ur v2.1.32/fs/Config.in linux/fs/Config.in
--- v2.1.32/fs/Config.in	Mon Apr  7 23:58:09 1997
+++ linux/fs/Config.in	Mon Apr  7 20:56:51 1997
@@ -18,12 +18,23 @@
 if [ "$CONFIG_INET" = "y" ]; then
   tristate 'NFS filesystem support' CONFIG_NFS_FS
   if [ "$CONFIG_NFS_FS" = "y" ]; then
-    define_bool CONFIG_SUNRPC y
-    define_bool CONFIG_LOCKD y
     bool '   Root file system on NFS' CONFIG_ROOT_NFS
     if [ "$CONFIG_ROOT_NFS" = "y" ]; then
       bool '      BOOTP support' CONFIG_RNFS_BOOTP
       bool '      RARP support' CONFIG_RNFS_RARP
+    fi
+  fi
+  tristate 'NFS server support' CONFIG_NFSD
+  if [ "$CONFIG_NFS_FS" = "y" -o "$CONFIG_NFSD" = "y" ]; then
+    define_bool CONFIG_SUNRPC y
+    define_bool CONFIG_LOCKD y
+  else
+    if [ "$CONFIG_NFS_FS" = "m" -o "$CONFIG_NFSD" = "m" ]; then
+      define_bool CONFIG_SUNRPC m
+      define_bool CONFIG_LOCKD m
+    else
+      define_bool CONFIG_SUNRPC n
+      define_bool CONFIG_LOCKD n
     fi
   fi
   tristate 'SMB filesystem support (to mount WfW shares etc..)' CONFIG_SMB_FS
diff -ur v2.1.32/fs/lockd/clntproc.c linux/fs/lockd/clntproc.c
--- v2.1.32/fs/lockd/clntproc.c	Mon Apr  7 23:58:11 1997
+++ linux/fs/lockd/clntproc.c	Tue Apr  8 02:25:40 1997
@@ -322,7 +322,8 @@
 	int		status;
 
 	if (!host->h_monitored && nsm_monitor(host) < 0) {
-		printk(KERN_NOTICE "lockd: failed to monitor %s", host->h_name);
+		printk(KERN_NOTICE "lockd: failed to monitor %s\n",
+					host->h_name);
 		return -ENOLCK;
 	}
 
@@ -496,10 +497,10 @@
 		/* Everything's good */
 		break;
 	case NLM_LCK_DENIED_NOLOCKS:
-		dprintk("lockd: CANCEL failed (server has no locks)");
+		dprintk("lockd: CANCEL failed (server has no locks)\n");
 		goto retry_cancel;
 	default:
-		printk(KERN_NOTICE "lockd: weird return %d for CANCEL call",
+		printk(KERN_NOTICE "lockd: weird return %d for CANCEL call\n",
 			req->a_res.status);
 	}
 
diff -ur v2.1.32/fs/nfs/inode.c linux/fs/nfs/inode.c
--- v2.1.32/fs/nfs/inode.c	Mon Apr  7 23:58:12 1997
+++ linux/fs/nfs/inode.c	Mon Apr  7 18:35:48 1997
@@ -25,11 +25,12 @@
 #include <linux/locks.h>
 #include <linux/unistd.h>
 #include <linux/sunrpc/clnt.h>
+#include <linux/sunrpc/stats.h>
 #include <linux/nfs_fs.h>
 #include <linux/lockd/bind.h>
 
 #include <asm/system.h>
-# include <asm/uaccess.h>
+#include <asm/uaccess.h>
 
 #define NFSDBG_FACILITY		NFSDBG_VFS
 
@@ -50,6 +51,7 @@
 	NULL
 };
 
+struct rpc_stat			nfs_rpcstat = { &nfs_program };
 
 /*
  * The "read_inode" function doesn't actually do anything:
@@ -438,7 +440,7 @@
 init_nfs_fs(void)
 {
 #ifdef CONFIG_PROC_FS
-	rpcstat_register(&nfs_rpcstat);
+	rpc_proc_register(&nfs_rpcstat);
 #endif
         return register_filesystem(&nfs_fs_type);
 }
@@ -462,7 +464,7 @@
 cleanup_module(void)
 {
 #ifdef CONFIG_PROC_FS
-	rpcstat_unregister(&nfs_rpcstat);
+	rpc_proc_unregister("nfs");
 #endif
 	unregister_filesystem(&nfs_fs_type);
 	nfs_free_dircache();
diff -ur v2.1.32/fs/nfs/nfs2xdr.c linux/fs/nfs/nfs2xdr.c
--- v2.1.32/fs/nfs/nfs2xdr.c	Mon Apr  7 23:58:12 1997
+++ linux/fs/nfs/nfs2xdr.c	Mon Apr  7 15:58:24 1997
@@ -625,25 +625,3 @@
 	nfs_version,
 	&nfs_rpcstat,
 };
-
-/*
- * RPC stats support
- */
-static int
-nfs_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
-{
-	return rpcstat_get_info(&nfs_rpcstat, buffer, start, offset, length);
-}
-
-static struct proc_dir_entry	proc_nfsclnt = {
-	0, 3, "nfs",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	6, &proc_net_inode_operations,
-	nfs_get_info
-};
-
-struct rpc_stat			nfs_rpcstat = {
-	NULL,			/* next */
-	&proc_nfsclnt,		/* /proc/net directory entry */
-	&nfs_program,		/* RPC program */
-};
diff -ur v2.1.32/fs/nfsd/stats.c linux/fs/nfsd/stats.c
--- v2.1.32/fs/nfsd/stats.c	Mon Apr  7 23:58:13 1997
+++ linux/fs/nfsd/stats.c	Mon Apr  7 15:49:57 1997
@@ -1,18 +1,16 @@
 /*
- * nfsstat.c	procfs-based user access to knfsd statistics
+ * linux/fs/nfsd/stats.c
  *
- * /proc/net/nfssrv
+ * procfs-based user access to knfsd statistics
+ *
+ * /proc/net/rpc/nfsd
+ *
  * Format:
- *	net <packets> <udp> <tcp> <tcpconn>
- *	rpc <packets> <badfmt> <badclnt>
- *	auth <flavor> <creds> <upcalls> <badauth> <badverf> <authrej>
- *	fh  <hits> <misses> <avg_util> <stale> <cksum> <badcksum>
  *	rc <hits> <misses> <nocache>
- *	proto <version> <nrprocs>
- *	<calls> <time_msec>
- *	... (for each procedure and protocol version)
+ *			Statistsics for the reply cache
+ *	plus generic RPC stats (see net/sunrpc/stats.c)
  *
- * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
  */
 
 #include <linux/kernel.h>
@@ -26,28 +24,13 @@
 #include <linux/nfsd/stats.h>
 
 struct nfsd_stats	nfsdstats;
-
-static int		nfsd_get_info(char *, char **, off_t, int, int);
+struct svc_stat		nfsd_svcstats = { &nfsd_program, };
 
-#ifndef PROC_NET_NFSSRV
-# define PROC_NET_NFSSRV	0
-#endif
-
-static struct proc_dir_entry proc_nfssrv = {
-	PROC_NET_NFSSRV, 4, "nfsd",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	6, &proc_net_inode_operations,
-	nfsd_get_info
-};
-
-struct svc_stat		nfsd_svcstats = {
-	NULL, &proc_nfssrv, &nfsd_program,
-};
-
 static int
-nfsd_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
+nfsd_proc_read(char *buffer, char **start, off_t offset, int count,
+				int *eof, void *data)
 {
-	int			len;
+	int	len;
 
 	len = sprintf(buffer,
 		"rc %d %d %d\n",
@@ -55,38 +38,45 @@
 			nfsdstats.rcmisses,
 			nfsdstats.rcnocache);
 
+	/* Assume we haven't hit EOF yet. Will be set by svc_proc_read. */
+	*eof = 0;
+
 	/*
-	 * Append generic nfsd RPC statistics
+	 * Append generic nfsd RPC statistics if there's room for it.
 	 */
-	if (offset >= len) {
-		offset -= len;
-		len = svcstat_get_info(&nfsd_svcstats, buffer, start,
-					offset, length);
-#if 0
-	} else if (len < length) {
-		len = svcstat_get_info(&nfsd_svcstats, buffer + len, start,
-					offset - len, length - len);
-#endif
+	if (len <= offset) {
+		len = svc_proc_read(buffer, start, offset - len, count,
+				eof, data);
+		return len;
+	}
+
+	if (len < count) {
+		len += svc_proc_read(buffer + len, start, 0, count - len,
+				eof, data);
 	}
 
 	if (offset >= len) {
 		*start = buffer;
 		return 0;
 	}
+
 	*start = buffer + offset;
-	if ((len -= offset) > length)
-		len = length;
+	if ((len -= offset) > count)
+		return count;
 	return len;
 }
 
 void
 nfsd_stat_init(void)
 {
-	svcstat_register(&nfsd_svcstats);
+	struct proc_dir_entry	*ent;
+
+	if ((ent = svc_proc_register(&nfsd_svcstats)) != 0)
+		ent->read_proc = nfsd_proc_read;
 }
 
 void
 nfsd_stat_shutdown(void)
 {
-	svcstat_unregister(&nfsd_svcstats);
+	svc_proc_unregister("nfsd");
 }
diff -ur v2.1.32/fs/proc/procfs_syms.c linux/fs/proc/procfs_syms.c
--- v2.1.32/fs/proc/procfs_syms.c	Mon Apr  7 23:56:37 1997
+++ linux/fs/proc/procfs_syms.c	Mon Apr  7 23:50:17 1997
@@ -14,6 +14,8 @@
 
 EXPORT_SYMBOL(proc_register);
 EXPORT_SYMBOL(proc_unregister);
+EXPORT_SYMBOL(create_proc_entry);
+EXPORT_SYMBOL(remove_proc_entry);
 EXPORT_SYMBOL(proc_root);
 EXPORT_SYMBOL(proc_get_inode);
 EXPORT_SYMBOL(in_group_p);
diff -ur v2.1.32/include/linux/sunrpc/stats.h linux/include/linux/sunrpc/stats.h
--- v2.1.32/include/linux/sunrpc/stats.h	Mon Apr  7 23:58:15 1997
+++ linux/include/linux/sunrpc/stats.h	Mon Apr  7 21:01:57 1997
@@ -12,8 +12,6 @@
 #include <linux/proc_fs.h>
 
 struct rpc_stat {
-	struct rpc_stat *	next;
-	struct proc_dir_entry *	entry;
 	struct rpc_program *	program;
 
 	unsigned int		netcnt,
@@ -28,8 +26,6 @@
 };
 
 struct svc_stat {
-	struct svc_stat *	next;
-	struct proc_dir_entry *	entry;
 	struct svc_program *	program;
 
 	unsigned int		netcnt,
@@ -42,18 +38,18 @@
 				rpcbadclnt;
 };
 
-void		rpcstat_init(void);
-void		rpcstat_exit(void);
+void			rpc_proc_init(void);
+void			rpc_proc_exit(void);
 
-void		rpcstat_register(struct rpc_stat *);
-void		rpcstat_unregister(struct rpc_stat *);
-int		rpcstat_get_info(struct rpc_stat *, char *, char **,
-					off_t, int);
-void		rpcstat_zero_info(struct rpc_program *);
-void		svcstat_register(struct svc_stat *);
-void		svcstat_unregister(struct svc_stat *);
-int		svcstat_get_info(struct svc_stat *, char *, char **,
-					off_t, int);
-void		svcstat_zero_info(struct svc_program *);
+struct proc_dir_entry *	rpc_proc_register(struct rpc_stat *);
+void			rpc_proc_unregister(const char *);
+int			rpc_proc_read(char *, char **, off_t, int,
+					int *, void *);
+void			rpc_proc_zero(struct rpc_program *);
+struct proc_dir_entry *	svc_proc_register(struct svc_stat *);
+void			svc_proc_unregister(const char *);
+int			svc_proc_read(char *, char **, off_t, int,
+					int *, void *);
+void			svc_proc_zero(struct svc_program *);
 
 #endif /* _LINUX_SUNRPC_STATS_H */
diff -ur v2.1.32/kernel/printk.c linux/kernel/printk.c
--- v2.1.32/kernel/printk.c	Mon Apr  7 23:58:17 1997
+++ linux/kernel/printk.c	Mon Apr  7 20:06:19 1997
@@ -218,7 +218,7 @@
 			struct console *c = console_drivers;
 			while(c) {
 				if (c->write)
-					c->write(msg, p - msg + 1);
+					c->write(msg, p - msg + (*p == '\n'));
 				c = c->next;
 			}
 		}
diff -ur v2.1.32/net/sunrpc/clnt.c linux/net/sunrpc/clnt.c
--- v2.1.32/net/sunrpc/clnt.c	Mon Apr  7 23:58:18 1997
+++ linux/net/sunrpc/clnt.c	Mon Apr  7 16:38:20 1997
@@ -746,7 +746,7 @@
 #ifdef RPC_DEBUG
 	rpc_register_sysctl();
 #endif
-	rpcstat_init();
+	rpc_proc_init();
 	return 0;
 }
 
@@ -756,6 +756,6 @@
 #ifdef RPC_DEBUG
 	rpc_unregister_sysctl();
 #endif
-	rpcstat_exit();
+	rpc_proc_exit();
 }
 #endif
diff -ur v2.1.32/net/sunrpc/stats.c linux/net/sunrpc/stats.c
--- v2.1.32/net/sunrpc/stats.c	Mon Apr  7 23:58:18 1997
+++ linux/net/sunrpc/stats.c	Mon Apr  7 23:48:30 1997
@@ -1,14 +1,15 @@
 /*
  * linux/net/sunrpc/stats.c
  *
- * procfs-based user access to RPC statistics
+ * procfs-based user access to generic RPC statistics. The stats files
+ * reside in /proc/net/rpc.
  *
- * Everything is complicated by the fact that procfs doesn't pass the
- * proc_dir_info struct in the call to get_info. We need our own 
- * inode_ops for /proc/net/rpc (we want to have a write op for zeroing
- * the current stats, anyway).
+ * The read routines assume that the buffer passed in is just big enough.
+ * If you implement an RPC service that has its own stats routine which
+ * appends the generic RPC stats, make sure you don't exceed the PAGE_SIZE
+ * limit.
  *
- * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
  */
 
 #include <linux/kernel.h>
@@ -19,83 +20,16 @@
 
 #define RPCDBG_FACILITY	RPCDBG_MISC
 
-/*
- * Generic stats object (same for clnt and svc stats).
- * Must agree with first two fields of either.
- */
-struct stats {
-	struct stats *		next;
-	struct proc_dir_entry *	entry;
-};
-
-/* Code disabled until updated to new dynamic /proc code */
-#if 0
-
-static struct stats *		rpc_stats = NULL;
-static struct stats *		svc_stats = NULL;
-
-static struct proc_dir_entry	proc_rpc = {
-	0, 3, "rpc",
-	S_IFDIR | S_IRUGO | S_IXUGO, 1, 0, 0,
-	0, NULL,
-	NULL, NULL,
-	NULL,
-	NULL, NULL,
-};
-
-/*
- * Register/unregister a stats file
- */
-static void
-stats_register(struct stats **q, struct stats *p)
-{
-	dprintk("RPC: registering /proc/net/rpc/%s\n",
-				p->entry->name);
-	/* return; */
-	if (p->entry->low_ino)
-		return;
-	p->next = *q;
-	*q = p;
-	proc_register_dynamic(&proc_rpc, p->entry);
-}
+static struct proc_dir_entry	*proc_net_rpc = 0;
 
-static void
-stats_unregister(struct stats **q, struct stats *p)
-{
-	dprintk("RPC: unregistering /proc/net/rpc/%s\n",
-				p->entry->name);
-	/* return; */
-	if (!p->entry->low_ino)
-		return;
-	while (*q) {
-		if (*q == p) {
-			*q = p->next;
-			proc_unregister(&proc_rpc, p->entry->low_ino);
-			return;
-		}
-		q = &((*q)->next);
-	}
-}
-
 /*
- * Client stats handling
+ * Get RPC client stats
  */
-void
-rpcstat_register(struct rpc_stat *statp)
-{
-	stats_register(&rpc_stats, (struct stats *) statp);
-}
-
-void
-rpcstat_unregister(struct rpc_stat *statp)
-{
-	stats_unregister(&rpc_stats, (struct stats *) statp);
-}
-
 int
-rpcstat_get_info(struct rpc_stat *statp, char *buffer,
-			char **start, off_t offset, int length)
+rpc_proc_read(char *buffer, char **start, off_t offset, int count,
+				int *eof, void *data)
 {
+	struct rpc_stat	*statp = (struct rpc_stat *) data;
 	struct rpc_program *prog = statp->program;
 	struct rpc_version *vers;
 	int		len, i, j;
@@ -125,34 +59,24 @@
 
 	if (offset >= len) {
 		*start = buffer;
+		*eof = 1;
 		return 0;
 	}
 	*start = buffer + offset;
-	len -= offset;
-	if (len > length)
-		len = length;
+	if ((len -= offset) > count)
+		return count;
+	*eof = 1;
 	return len;
 }
 
 /*
- * Server stats handling
+ * Get RPC server stats
  */
-void
-svcstat_register(struct svc_stat *statp)
-{
-	stats_register(&svc_stats, (struct stats *) statp);
-}
-
-void
-svcstat_unregister(struct svc_stat *statp)
-{
-	stats_unregister(&svc_stats, (struct stats *) statp);
-}
-
 int
-svcstat_get_info(struct svc_stat *statp, char *buffer,
-			char **start, off_t offset, int length)
+svc_proc_read(char *buffer, char **start, off_t offset, int count,
+				int *eof, void *data)
 {
+	struct svc_stat *statp	= (struct svc_stat *) data;
 	struct svc_program *prog = statp->program;
 	struct svc_procedure *proc;
 	struct svc_version *vers;
@@ -183,85 +107,69 @@
 
 	if (offset >= len) {
 		*start = buffer;
+		*eof = 1;
 		return 0;
 	}
 	*start = buffer + offset;
-	if ((len -= offset) > length)
-		len = length;
+	if ((len -= offset) > count)
+		return count;
+	*eof = 1;
 	return len;
 }
 
 /*
- * Register /proc/net/rpc
- */
-void
-rpcstat_init(void)
-{
-	dprintk("RPC: registering /proc/net/rpc\n");
-	proc_rpc.ops = proc_net.ops;	/* cheat */
-	proc_register_dynamic(&proc_net, &proc_rpc);
-}
-
-/*
- * Unregister /proc/net/rpc
+ * Register/unregister RPC proc files
  */
-void
-rpcstat_exit(void)
+static inline struct proc_dir_entry *
+do_register(const char *name, void *data, int issvc)
 {
-	while (rpc_stats)
-		stats_unregister(&rpc_stats, rpc_stats);
-	while (svc_stats)
-		stats_unregister(&svc_stats, svc_stats);
-	dprintk("RPC: unregistering /proc/net/rpc\n");
-	proc_unregister(&proc_net, proc_rpc.low_ino);
-}
+	struct proc_dir_entry	*ent;
 
-#else
+	dprintk("RPC: registering /proc/net/rpc/%s\n", name);
+	ent = create_proc_entry(name, 0, proc_net_rpc);
+	ent->read_proc = issvc? svc_proc_read : rpc_proc_read;
+	ent->data = data;
 
-/* Various dummy functions */
-
-int
-rpcstat_get_info(struct rpc_stat *statp, char *buffer,
-			char **start, off_t offset, int length)
-{
-	return 0;
-}
-
-int
-svcstat_get_info(struct svc_stat *statp, char *buffer,
-			char **start, off_t offset, int length)
-{
-	return 0;
+	return ent;
 }
 
-void
-rpcstat_register(struct rpc_stat *statp)
+struct proc_dir_entry *
+rpc_proc_register(struct rpc_stat *statp)
 {
+	return do_register(statp->program->name, statp, 0);
 }
 
 void
-rpcstat_unregister(struct rpc_stat *statp)
+rpc_proc_unregister(const char *name)
 {
+	remove_proc_entry(name, proc_net_rpc);
 }
 
-void
-svcstat_register(struct svc_stat *statp)
+struct proc_dir_entry *
+svc_proc_register(struct svc_stat *statp)
 {
+	return do_register(statp->program->pg_name, statp, 1);
 }
 
 void
-svcstat_unregister(struct svc_stat *statp)
+svc_proc_unregister(const char *name)
 {
+	remove_proc_entry(name, proc_net_rpc);
 }
 
 void
-rpcstat_init(void)
+rpc_proc_init(void)
 {
+	dprintk("RPC: registering /proc/net/rpc\n");
+	if (!proc_net_rpc)
+		proc_net_rpc = create_proc_entry("net/rpc", S_IFDIR, 0);
 }
 
 void
-rpcstat_exit(void)
+rpc_proc_exit(void)
 {
+	dprintk("RPC: unregistering /proc/net/rpc\n");
+	if (proc_net_rpc)
+		remove_proc_entry("net/rpc", 0);
+	proc_net_rpc = 0;
 }
-
-#endif
diff -ur v2.1.32/net/sunrpc/sunrpc_syms.c linux/net/sunrpc/sunrpc_syms.c
--- v2.1.32/net/sunrpc/sunrpc_syms.c	Mon Apr  7 23:58:18 1997
+++ linux/net/sunrpc/sunrpc_syms.c	Mon Apr  7 16:39:36 1997
@@ -10,8 +10,6 @@
 #include <linux/config.h>
 #include <linux/module.h>
 
-#ifdef CONFIG_MODULES
-
 #include <linux/types.h>
 #include <linux/socket.h>
 #include <linux/sched.h>
@@ -75,12 +73,12 @@
 
 /* RPC statistics */
 #ifdef CONFIG_PROC_FS
-EXPORT_SYMBOL(rpcstat_register);
-EXPORT_SYMBOL(rpcstat_unregister);
-EXPORT_SYMBOL(rpcstat_get_info);
-EXPORT_SYMBOL(svcstat_register);
-EXPORT_SYMBOL(svcstat_unregister);
-EXPORT_SYMBOL(svcstat_get_info);
+EXPORT_SYMBOL(rpc_proc_register);
+EXPORT_SYMBOL(rpc_proc_unregister);
+EXPORT_SYMBOL(rpc_proc_read);
+EXPORT_SYMBOL(svc_proc_register);
+EXPORT_SYMBOL(svc_proc_unregister);
+EXPORT_SYMBOL(svc_proc_read);
 #endif
 
 /* Generic XDR */
@@ -101,5 +99,3 @@
 EXPORT_SYMBOL(nfs_debug);
 EXPORT_SYMBOL(nfsd_debug);
 EXPORT_SYMBOL(nlm_debug);
-
-#endif /* CONFIG_MODULES */
----------------------- END OF PATCH ------------------------