]> git.pld-linux.org Git - packages/kernel.git/blame - nwd-2.4.21.patch
- ugh, missing ;
[packages/kernel.git] / nwd-2.4.21.patch
CommitLineData
1046336c
JR
1diff -Nur linux-2.4.20.org/Documentation/Configure.help linux-2.4.20/Documentation/Configure.help
2--- linux-2.4.20.org/Documentation/Configure.help Thu Mar 13 09:16:32 2003
3+++ linux-2.4.20/Documentation/Configure.help Thu Mar 13 09:20:23 2003
4@@ -583,6 +583,35 @@
5 if you want to do performance tuning, by tweaking the elevator, e.g.
6
7 If unsure, say N.
8+
9+Network disk device support
10+CONFIG_BLK_DEV_NWD
11+ If you say Y here, your kernel will be able to act as network disk
12+ client and provide you with network disk block devices. This is
13+ similar to NBD in that the driver forwards block device requests
14+ over network to server, which performs the operations on files on
15+ its local filesystem and returns results back to the client. The
16+ driver will enlarge your kernel by about 8 KiB.
17+
18+ Unlike NBD though, NWD it uses RPC to transfer block device requests
19+ to the server. The network disk devices can be also used for root
20+ filesystems, making it easy to setup diskless environment -- all you
21+ need is kernel image with network drivers. The RPC transport protocol
22+ can be either TCP/IP or UDP/IP, the latter being the default one and
23+ probably the one more suitable for reliable, local area networks. The
24+ driver utilizes built-in kernel SunRPC infrastructure, thus saying Y
25+ here will force SunRPC into your kernel, which will enlarge it by
26+ about 65 KiB.
27+
28+ Consult <file:Documentation/nwd.txt> for more information concerning
29+ the kernel client driver and user space server.
30+
31+ If you want to compile this driver as a module (i.e. code which can be
32+ inserted in and removed from the running kernel whenever you want),
33+ say M here and read <file:Documentation/modules.txt>. The module will be
34+ called nwd.o.
35+
36+ If unsure, say N.
37
38 ATA/IDE/MFM/RLL support
39 CONFIG_IDE
40diff -Nur linux-2.4.20.org/Makefile linux-2.4.20/Makefile
41--- linux-2.4.20.org/Makefile Thu Mar 13 09:16:33 2003
42+++ linux-2.4.20/Makefile Thu Mar 13 09:20:23 2003
43@@ -187,6 +187,7 @@
44 DRIVERS-$(CONFIG_SGI_IP22) += drivers/sgi/sgi.a
45 DRIVERS-$(CONFIG_VT) += drivers/video/video.o
46 DRIVERS-$(CONFIG_PARIDE) += drivers/block/paride/paride.a
47+DRIVERS-$(CONFIG_BLK_DEV_NWD) += drivers/block/nwd/nwd.o
48 DRIVERS-$(CONFIG_HAMRADIO) += drivers/net/hamradio/hamradio.o
49 DRIVERS-$(CONFIG_TC) += drivers/tc/tc.a
50 DRIVERS-$(CONFIG_USB) += drivers/usb/usbdrv.o
51diff -Nur linux-2.4.20.org/drivers/block/Config.in linux-2.4.20/drivers/block/Config.in
52--- linux-2.4.20.org/drivers/block/Config.in Thu Mar 13 09:16:27 2003
53+++ linux-2.4.20/drivers/block/Config.in Thu Mar 13 09:20:23 2003
54@@ -46,6 +46,7 @@
55
56 tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP
57 dep_tristate 'Network block device support' CONFIG_BLK_DEV_NBD $CONFIG_NET
58+dep_tristate 'Network disk device support' CONFIG_BLK_DEV_NWD $CONFIG_NET
59
60 tristate 'RAM disk support' CONFIG_BLK_DEV_RAM
61 if [ "$CONFIG_BLK_DEV_RAM" = "y" -o "$CONFIG_BLK_DEV_RAM" = "m" ]; then
62diff -Nur linux-2.4.20.org/drivers/block/Makefile linux-2.4.20/drivers/block/Makefile
63--- linux-2.4.20.org/drivers/block/Makefile Thu Mar 13 09:16:27 2003
64+++ linux-2.4.20/drivers/block/Makefile Thu Mar 13 09:20:23 2003
65@@ -34,5 +34,6 @@
66 obj-$(CONFIG_CDROM_PKTCDVD) += pktcdvd.o
67
68 subdir-$(CONFIG_PARIDE) += paride
69+subdir-$(CONFIG_BLK_DEV_NWD) += nwd
70
71 include $(TOPDIR)/Rules.make
72diff -Nur linux-2.4.20.org/fs/Config.in linux-2.4.20/fs/Config.in
73--- linux-2.4.20.org/fs/Config.in Thu Mar 13 09:16:25 2003
74+++ linux-2.4.20/fs/Config.in Thu Mar 13 09:20:23 2003
75@@ -150,17 +150,25 @@
76 dep_mbool ' Provide NFS server over TCP support (EXPERIMENTAL)' CONFIG_NFSD_TCP $CONFIG_NFSD $CONFIG_EXPERIMENTAL
77
78 if [ "$CONFIG_NFS_FS" = "y" -o "$CONFIG_NFSD" = "y" ]; then
79- define_tristate CONFIG_SUNRPC y
80 define_tristate CONFIG_LOCKD y
81 else
82 if [ "$CONFIG_NFS_FS" = "m" -o "$CONFIG_NFSD" = "m" ]; then
83- define_tristate CONFIG_SUNRPC m
84 define_tristate CONFIG_LOCKD m
85- else
86- define_tristate CONFIG_SUNRPC n
87- define_tristate CONFIG_LOCKD n
88+ else
89+ define_tristate CONFIG_LOCKD n
90 fi
91 fi
92+
93+ if [ "$CONFIG_NFS_FS" = "y" -o "$CONFIG_NFSD" = "y" -o "$CONFIG_BLK_DEV_NWD" = "y" ]; then
94+ define_tristate CONFIG_SUNRPC y
95+ else
96+ if [ "$CONFIG_NFS_FS" = "m" -o "$CONFIG_NFSD" = "m" -o "$CONFIG_BLK_DEV_NWD" = "m" ]; then
97+ define_tristate CONFIG_SUNRPC m
98+ else
99+ define_tristate CONFIG_SUNRPC n
100+ fi
101+ fi
102+
103 if [ "$CONFIG_NFSD_V3" = "y" -o "$CONFIG_NFS_V3" = "y" ]; then
104 define_bool CONFIG_LOCKD_V4 y
105 fi
106diff -Nur linux-2.4.20.org/include/linux/blk.h linux-2.4.20/include/linux/blk.h
107--- linux-2.4.20.org/include/linux/blk.h Sat Aug 3 02:39:45 2002
108+++ linux-2.4.20/include/linux/blk.h Thu Mar 13 09:20:23 2003
109@@ -295,6 +295,12 @@
110 #define DEVICE_REQUEST do_nbd_request
111 #define DEVICE_NR(device) (MINOR(device))
112
113+#elif (MAJOR_NR == NWD_MAJOR)
114+
115+#define DEVICE_NAME "nwd"
116+#define DEVICE_REQUEST nwd_request
117+#define DEVICE_NR(device) (MINOR(device))
118+
119 #elif (MAJOR_NR == MDISK_MAJOR)
120
121 #define DEVICE_NAME "mdisk"
122diff -Nur linux-2.4.20.org/include/linux/major.h linux-2.4.20/include/linux/major.h
123--- linux-2.4.20.org/include/linux/major.h Thu Mar 13 09:16:27 2003
124+++ linux-2.4.20/include/linux/major.h Thu Mar 13 09:20:23 2003
125@@ -87,6 +87,8 @@
126
127 #define LVM_BLK_MAJOR 58 /* Logical Volume Manager */
128
129+#define NWD_MAJOR 62 /* Network disk driver */
130+
131 #define SCSI_DISK1_MAJOR 65
132 #define SCSI_DISK2_MAJOR 66
133 #define SCSI_DISK3_MAJOR 67
134diff -Nur linux-2.4.20.org/init/do_mounts.c linux-2.4.20/init/do_mounts.c
135--- linux-2.4.20.org/init/do_mounts.c Thu Mar 13 09:16:31 2003
136+++ linux-2.4.20/init/do_mounts.c Thu Mar 13 09:20:23 2003
137@@ -240,6 +240,9 @@
138 { "ftld", 0x2c18 },
139 { "mtdblock", 0x1f00 },
140 { "nb", 0x2b00 },
141+#ifdef CONFIG_BLK_DEV_NWD
142+ { "nwd", 0x3E00 },
143+#endif
144 { NULL, 0 }
145 };
146
147diff -Nur linux-2.4.20.org/init/main.c linux-2.4.20/init/main.c
148--- linux-2.4.20.org/init/main.c Thu Mar 13 09:16:32 2003
149+++ linux-2.4.20/init/main.c Thu Mar 13 09:20:23 2003
150@@ -103,6 +103,7 @@
151 #endif
152
153 extern void ecard_init(void);
154+extern int nwd_boot_init(void);
155
156 #if defined(CONFIG_SYSVIPC)
157 extern void ipc_init(void);
158@@ -536,6 +537,12 @@
159 start_context_thread();
160 do_initcalls();
161
162+#ifdef CONFIG_BLK_DEV_NWD
163+ /* Must be done after NET/RPC initialization */
164+ if (nwd_boot_init())
165+ panic ("Unable to setup network disk root device.");
166+#endif
167+
168 #ifdef CONFIG_IRDA
169 irda_proto_init();
170 irda_device_init(); /* Must be done after protocol initialization */
171diff -Nur linux-2.4.20.org/drivers/block/nwd/Makefile linux-2.4.20/drivers/block/nwd/Makefile
172--- linux-2.4.20.org/drivers/block/nwd/Makefile Thu Jan 1 01:00:00 1970
173+++ linux-2.4.20/drivers/block/nwd/Makefile Mon Sep 3 21:04:07 2001
174@@ -0,0 +1,17 @@
175+#
176+# Makefile for the Network disk client driver (NWD)
177+#
178+# Note 1! Dependencies are done automagically by 'make dep', which also
179+# removes any old dependencies. DON'T put your own dependencies here
180+# unless it's something special (ie not a .c file).
181+#
182+# Note 2! The CFLAGS definitions are now in the main makefile...
183+#
184+#
185+
186+O_TARGET := nwd.o
187+
188+obj-y += nwd_clt.o nwd_xdr.o
189+obj-$(CONFIG_BLK_DEV_NWD) += $(O_TARGET)
190+
191+include $(TOPDIR)/Rules.make
192diff -Nur linux-2.4.20.org/drivers/block/nwd/nwd_clt.c linux-2.4.20/drivers/block/nwd/nwd_clt.c
193--- linux-2.4.20.org/drivers/block/nwd/nwd_clt.c Thu Jan 1 01:00:00 1970
194+++ linux-2.4.20/drivers/block/nwd/nwd_clt.c Fri Sep 14 10:51:32 2001
195@@ -0,0 +1,1034 @@
196+/*
197+ * Network disk client
198+ * Kernel block device driver
199+ *
200+ * Copyright (c) 1996 Petr Salinger
201+ * Copyright (c) 1999 Libor Bus <l.bus@sh.cvut.cz>
202+ * Copyright (c) 2001 Lubomir Bulej <pallas@kadan.cz>
203+ *
204+ *
205+ * This program is free software; you can redistribute it and/or modify
206+ * it under the terms of the GNU General Public License as published by
207+ * the Free Software Foundation; either version 2 of the License, or
208+ * (at your option) any later version.
209+ *
210+ * This program is distributed in the hope that it will be useful,
211+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
212+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
213+ * GNU General Public License for more details.
214+ *
215+ * You should have received a copy of the GNU General Public License
216+ * along with this program; if not, write to the Free Software
217+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
218+ *
219+ */
220+
221+
222+#include <linux/kernel.h>
223+#include <linux/module.h>
224+#include <linux/errno.h>
225+
226+#include <linux/net.h> /* struct net_proto for inet.h */
227+#include <linux/inet.h> /* in_aton, in_ntoa */
228+
229+#include <linux/init.h> /* __init, __exit and stuff */
230+#include <linux/slab.h> /* kmalloc, kfree */
231+#include <linux/reboot.h> /* register_reboot_notifier */
232+#include <linux/devfs_fs_kernel.h> /* devfs_register/unregister */
233+
234+#include <linux/sunrpc/clnt.h> /* rpc_call, xprt stuff, etc. */
235+
236+#include <asm/uaccess.h> /* verify_area, get/put_user */
237+
238+#define MAJOR_NR NWD_MAJOR /* required for blk.h */
239+#include <linux/blk.h> /* block device macros */
240+#include <linux/blkpg.h> /* blk_ioctl */
241+
242+#include <linux/nwd.h>
243+#include "nwd_xdr.h"
244+#include "nwd_dbg.h"
245+
246+
247+/*****************************************************************************\
248+| PRIVATE GLOBALS |
249+\*****************************************************************************/
250+
251+static int * nwd_sizes; /* block device sizes in KiB */
252+static int * nwd_blksizes; /* device block/sector sizes */
253+
254+static int nwd_maxdevs = NWD_MAX_DEVICES; /* max number of devices */
255+static nwd_device_t * nwd_devices; /* device structures */
256+static struct semaphore nwd_mxdev; /* whole device structure mutex */
257+
258+static devfs_handle_t devfs_handle; /* devfs directory handle */
259+
260+
261+/*****************************************************************************\
262+| DEVICE OPERATIONS |
263+\*****************************************************************************/
264+
265+static
266+int nwd_disconnect (nwd_device_t * device)
267+{
268+ if (device->client == NULL)
269+ return 0;
270+ if (rpc_shutdown_client (device->client) != 0)
271+ eprintk ("unable to shutdown RPC client for device %d\n", device->devnum);
272+
273+ /* disconnected device must have device->client == NULL */
274+ nwd_sizes [device->devnum] = 0;
275+ device->client = NULL;
276+ return 0;
277+} /* nwd_disconnect */
278+
279+
280+static
281+int nwd_connect_opt (nwd_device_t * device, int ver, int proto)
282+{
283+ int error;
284+ char * pname;
285+ struct rpc_xprt * p_xprt;
286+ nwd_lookupres lookup_res;
287+
288+ /* refuse to connect on already connected device */
289+ if (device->client != NULL)
290+ return -EISCONN;
291+
292+
293+ /* make string with server name */
294+ memset (device->sname, 0, NWD_MAX_SNLEN);
295+ strncpy (device->sname, in_ntoa (device->server.saddr.sin_addr.s_addr), NWD_MAX_SNLEN);
296+ pname = (proto == IPPROTO_TCP) ? "TCP" : "UDP";
297+
298+
299+ /* create protocol */
300+ p_xprt = xprt_create_proto (proto, & device->server.saddr, NULL);
301+ if (p_xprt == NULL) {
302+ eprintk ("could not create RPC/%s transport\n", pname);
303+ return -EACCES;
304+ }
305+
306+
307+ /* create client & set options */
308+ device->client = rpc_create_client (p_xprt, device->sname, & nwd_program, ver, RPC_AUTH_NULL);
309+ if (device->client == NULL) {
310+ xprt_destroy (p_xprt);
311+ eprintk ("could not create RPC client\n");
312+ return -EACCES;
313+ }
314+
315+ device->client->cl_intr = 1;
316+ device->client->cl_chatty = 0;
317+ device->client->cl_autobind = 1;
318+ device->client->cl_softrtry = 1;
319+
320+
321+ /* lookup file id on server & fill in device size in blocks */
322+ error = rpc_call (device->client, NWDPROC_LOOKUP, & device->server.devid, & lookup_res, 0);
323+ if (error < 0) {
324+ nwd_disconnect (device);
325+ eprintk ("lookup failed on device %d: version %d, proto %s, devid %d, error %d\n",
326+ device->devnum, ver, pname, device->server.devid, abs (error));
327+ return error;
328+ }
329+
330+ nwd_sizes [device->devnum] = lookup_res.size >> BLOCK_SIZE_BITS;
331+ device->remid = lookup_res.file;
332+
333+ iprintk ("lookup successful on device %d: version %d, proto %s, remid %d, blocks %d\n",
334+ device->devnum, ver, pname, device->remid, nwd_sizes [device->devnum]);
335+ return 0;
336+} /* nwd_connect_opt */
337+
338+
339+static
340+int nwd_connect (nwd_device_t * device)
341+{
342+ int error;
343+ int proto = IPPROTO_UDP;
344+
345+ /*
346+ * Try to connect using NWD protocol version 2 first.
347+ * If that fails, fall back to version 1.
348+ */
349+ proto = (device->options & NWD_OPT_PROTO_TCP) ? IPPROTO_TCP : IPPROTO_UDP;
350+ error = nwd_connect_opt (device, NWD_VERSION_2, proto);
351+ if (error == 0)
352+ return 0;
353+
354+ return nwd_connect_opt (device, NWD_VERSION_1, proto);
355+} /* nwd_connect */
356+
357+
358+static
359+int nwd_dispose (nwd_device_t * device)
360+{
361+ nwd_res result;
362+ if (device->client == NULL)
363+ return -ENOTCONN;
364+
365+ return rpc_call (device->client, NWDPROC_DISPOSE, & device->remid, & result, 0);
366+} /* nwd_dispose */
367+
368+
369+static
370+int nwd_sync (nwd_device_t * device)
371+{
372+ nwd_res result;
373+ if (device->client == NULL)
374+ return -ENOTCONN;
375+ if (device->client->cl_vers < 2)
376+ return 0;
377+
378+ return rpc_call (device->client, NWDPROC_SYNC, & device->remid, & result, 0);
379+} /* nwd_sync */
380+
381+
382+/*****************************************************************************\
383+| REQUEST PROCESSING |
384+\*****************************************************************************/
385+
386+static inline
387+int nwd_devnum (kdev_t kdev)
388+{
389+ int devnum = DEVICE_NR (kdev);
390+ if (devnum >= nwd_maxdevs) {
391+ static int limit = 0;
392+ if (limit++ < 5)
393+ wprintk ("invalid device number (%d)", devnum);
394+
395+ return -1;
396+ }
397+
398+ return devnum;
399+} /* nwd_devnum */
400+
401+
402+static
403+request_queue_t * nwd_find_queue (kdev_t kdev)
404+{
405+ int devnum = nwd_devnum (kdev);
406+ if (devnum == -1)
407+ return NULL;
408+
409+ return & nwd_devices [devnum].queue;
410+} /* nwd_find_queue */
411+
412+
413+static inline
414+nwd_device_t * nwd_find_device (kdev_t kdev)
415+{
416+ int devnum = nwd_devnum (kdev);
417+ if (devnum == -1)
418+ return NULL;
419+
420+ return nwd_devices + devnum;
421+} /* nwd_find_device */
422+
423+
424+static inline
425+int nwd_transfer (nwd_device_t * device, const struct request * req)
426+{
427+ u32 dgmlen; /* datagram length in bytes */
428+ u32 reqlen; /* request length in bytes */
429+ u64 offset; /* request offset in bytes */
430+ char * buffer;
431+
432+ /* request attributes */
433+ reqlen = req->current_nr_sectors << NWD_SEC_BITS;
434+ offset = (u64) req->sector << NWD_SEC_BITS;
435+ buffer = req->buffer;
436+
437+
438+ /*
439+ * Split the request into chunks/datagrams handled by individual
440+ * calls. For the request to be successful, all remote calls must
441+ * return without errors.
442+ */
443+ dgmlen = NWD_MAX_DGLEN;
444+ while (reqlen > 0) {
445+ int result; /* remote call result */
446+ int retries; /* call retry counter */
447+ nwd_res res; /* write result */
448+ nwd_rwargs args; /* R/W arguments */
449+ nwd_readres rdres; /* read result */
450+
451+ if (reqlen < dgmlen)
452+ dgmlen = reqlen;
453+
454+ /* remote call arguments */
455+ args.file = device->remid;
456+ args.offset = offset;
457+ args.count = dgmlen;
458+ args.buffer = buffer;
459+
460+ retries = 0;
461+retry_call: switch (req->cmd) {
462+ case READ:
463+ result = rpc_call (device->client, NWDPROC_READ, & args, & rdres, 0);
464+ break;
465+
466+ case WRITE:
467+ result = rpc_call (device->client, NWDPROC_WRITE, & args, & res, 0);
468+ break;
469+
470+ default:
471+ /* should not really happen */
472+ eprintk ("invalid request command: %d\n", req->cmd);
473+ return 0;
474+ } /* command switch */
475+
476+
477+ /*
478+ * Repeat the call in case of timeout. Prolong the timeout
479+ * for initial retries & bail out with error when the number
480+ * of retries reached its limit.
481+ */
482+ if (result == -ETIMEDOUT) {
483+ if (retries == 0)
484+ device->client->cl_timeout.to_initval <<= 1;
485+
486+ if (retries++ < NWD_MAX_RETRIES) {
487+ wprintk ("server not responding, retrying (%d)\n", retries);
488+ goto retry_call;
489+ }
490+ }
491+
492+ /* fail if errors persist (including too many timeouts) */
493+ if (result < 0) {
494+ eprintk ("request for %ld sectors at %ld failed, error %d\n",
495+ req->current_nr_sectors, req->sector, abs (result));
496+ return 0;
497+ }
498+
499+
500+ /* next chunk */
501+ offset += dgmlen;
502+ buffer += dgmlen;
503+ reqlen -= dgmlen;
504+ } /* request loop */
505+
506+ return 1;
507+} /* nwd_transfer */
508+
509+
510+static
511+void nwd_request (request_queue_t * rq)
512+{
513+ /* lookup device, io_request_lock held */
514+ struct request * req = blkdev_entry_next_request (& rq->queue_head);
515+ nwd_device_t * device = nwd_find_device (req->rq_dev);
516+ if (device == NULL)
517+ goto fail_request;
518+ if (device->client == NULL)
519+ goto fail_request;
520+
521+ /*
522+ * Process the request(s). The assumption behind this code is
523+ * that the rpc_call will sleep while waiting for RPC response
524+ * (correct me if I'm wrong, please), therefore we drop the
525+ * io_request_lock to allow processing of other requests and
526+ * also (if rpc_call sleeps) because we must not hold it.
527+ */
528+ while (! list_empty (& rq->queue_head)) {
529+ int status;
530+
531+ /* pull request from queue & release io_request_lock */
532+ req = blkdev_entry_next_request (& rq->queue_head);
533+ blkdev_dequeue_request (req);
534+ spin_unlock_irq (& io_request_lock);
535+
536+ /* process buffers in the request */
537+ do {
538+ status = nwd_transfer (device, req);
539+ } while (end_that_request_first (req, status, DEVICE_NAME));
540+
541+ /* grab io_request_lock & finish the request */
542+ spin_lock_irq (& io_request_lock);
543+ end_that_request_last (req);
544+ } /* request loop */
545+ return;
546+
547+
548+ /*
549+ * Make the request fail if the device was not found
550+ * or the device was not connected.
551+ */
552+fail_request:
553+ while (end_that_request_first (req, 0, DEVICE_NAME));
554+ blkdev_dequeue_request (req);
555+ end_that_request_last (req);
556+} /* nwd_request */
557+
558+
559+/*****************************************************************************\
560+| BLOCK DEVICE OPERATIONS |
561+\*****************************************************************************/
562+
563+static
564+int nwd_open (struct inode * inode, struct file * filp)
565+{
566+ int error;
567+ nwd_device_t * device = nwd_find_device (inode->i_rdev);
568+ if (device == NULL)
569+ return -ENODEV;
570+
571+ MOD_INC_USE_COUNT;
572+
573+
574+ /*
575+ * The code for several ioctls requires that the ioctl issuer be the
576+ * only one having the device opened. The code checks device->users
577+ * so we must not change it behind its back.
578+ */
579+ error = down_interruptible (& device->mxctl);
580+ if (error) {
581+ MOD_DEC_USE_COUNT;
582+ return error;
583+ }
584+
585+ device->users++;
586+ up (& device->mxctl);
587+ return 0;
588+} /* nwd_open */
589+
590+
591+static
592+int nwd_release (struct inode * inode, struct file * filp)
593+{
594+ int error;
595+ nwd_device_t * device;
596+
597+ device = nwd_find_device (inode->i_rdev);
598+ if (device == NULL)
599+ return -ENODEV;
600+
601+
602+ /*
603+ * Process NWD client options when last user releases the device. As
604+ * in the case of nwd_open, we grab the device->mxctl mutex before
605+ * updating device->users because we can sleep while issuing remote
606+ * calls, and don't want anybody opening the device at that time.
607+ *
608+ * We also don't want anyone changing the options under us.
609+ */
610+ error = down_interruptible (& device->mxctl);
611+ if (error)
612+ return error;
613+
614+ device->users--;
615+ if (device->users == 0 && device->client != NULL) {
616+ if (device->options & (NWD_OPT_DISPOSE | NWD_OPT_DISCONNECT))
617+ invalidate_device (inode->i_rdev, 1);
618+
619+ /* get rid of changes made on device */
620+ if (device->options & NWD_OPT_DISPOSE) {
621+ if (nwd_dispose (device))
622+ wprintk ("failed to dispose changes on device %d\n", device->devnum);
623+ }
624+
625+ /* disconnect from server */
626+ if (device->options & NWD_OPT_DISCONNECT)
627+ nwd_disconnect (device);
628+ } /* release actions */
629+
630+ up (& device->mxctl);
631+ MOD_DEC_USE_COUNT;
632+ return 0;
633+} /* nwd_release */
634+
635+
636+static
637+int nwd_check_server (nwd_peer_t * server, nwd_device_t * device)
638+{
639+ int devnum;
640+
641+ /* skip INADDR_ANY servers telling us to disconnect only*/
642+ if (server->saddr.sin_addr.s_addr == INADDR_ANY)
643+ return 0;
644+
645+ /* check other devices except the one we are setting peer on */
646+ for (devnum = 0; devnum < nwd_maxdevs; devnum++) {
647+ if (devnum == device->devnum)
648+ continue;
649+ if (memcmp (server, & nwd_devices [devnum].server, sizeof (nwd_peer_t)) == 0)
650+ return -EADDRINUSE;
651+ }
652+
653+ return 0;
654+} /* nwd_check_server */
655+
656+
657+static
658+int nwd_ioctl (struct inode * inode, struct file * filp,
659+ unsigned int cmd, unsigned long arg)
660+{
661+ int error;
662+ long longv;
663+ long * longp;
664+ nwd_peer_t server;
665+ nwd_device_t * device;
666+
667+ device = nwd_find_device (inode->i_rdev);
668+ if (device == NULL)
669+ return -ENODEV;
670+
671+
672+ longp = (long *) arg;
673+ switch (cmd) {
674+ case NWD_CTL_SETPEER:
675+ case NWD_CTL_DISPOSE:
676+ /*
677+ * First, the user must have sufficient privileges to
678+ * set/change peer or dispose changes on the device.
679+ */
680+ if (! capable (CAP_SYS_ADMIN))
681+ return -EPERM;
682+
683+ error = verify_area (VERIFY_READ, longp, sizeof (nwd_peer_t));
684+ if (error)
685+ return error;
686+
687+ /*
688+ * Second, make sure nobody is going to open the device
689+ * while we are doing this. We also make sure to be the
690+ * only ones having the device opened -- we don't want
691+ * to do this under active users.
692+ */
693+ error = down_interruptible (& device->mxctl);
694+ if (error)
695+ return error;
696+
697+ error = -EBUSY;
698+ if (device->users > 1)
699+ goto setpeer_exit_mxctl;
700+
701+
702+ /*
703+ * Third, make sure we are the only ones doing this
704+ * kind of ioctl, because we want to check that we are
705+ * not setting server:devid pair used on other devices.
706+ */
707+ if (cmd == NWD_CTL_SETPEER) {
708+ __copy_from_user (& server, longp, sizeof (nwd_peer_t));
709+
710+ error = down_interruptible (& nwd_mxdev);
711+ if (error)
712+ goto setpeer_exit_mxctl;
713+
714+ error = nwd_check_server (& server, device);
715+ if (error)
716+ goto setpeer_exit_mxdev;
717+ }
718+
719+
720+ /*
721+ * Fourth, invalidate the device. After that, no new
722+ * requests should arrive because it's only us having
723+ * the device opened. Then we can safely disconnect
724+ * from server and connect to new one or dispose of
725+ * changes made on the device.
726+ */
727+ invalidate_device (inode->i_rdev, 1);
728+
729+ if (cmd == NWD_CTL_SETPEER) {
730+ error = nwd_disconnect (device);
731+ if (server.saddr.sin_addr.s_addr != INADDR_ANY) {
732+ device->server = server;
733+ error = nwd_connect (device);
734+ }
735+ } else
736+ error = nwd_dispose (device);
737+
738+
739+ setpeer_exit_mxdev:
740+ if (cmd == NWD_CTL_SETPEER)
741+ up (& nwd_mxdev);
742+ setpeer_exit_mxctl:
743+ up (& device->mxctl);
744+ return error;
745+
746+
747+ case NWD_CTL_GETPEER:
748+ error = verify_area (VERIFY_WRITE, longp, sizeof (nwd_peer_t));
749+ if (error)
750+ return error;
751+
752+ /*
753+ * Make sure the peer is not being changed.
754+ */
755+ error = down_interruptible (& device->mxctl);
756+ if (error)
757+ return error;
758+
759+ /* report disconnected device to have peer 0.0.0.0 */
760+ server = device->server;
761+ if (device->client == NULL)
762+ server.saddr.sin_addr.s_addr = INADDR_ANY;
763+
764+ /* store peer structure to user space */
765+ __copy_to_user (longp, & server, sizeof (nwd_peer_t));
766+ up (& device->mxctl);
767+ return 0;
768+
769+
770+ case NWD_CTL_SETOPTS:
771+ /* must have sufficient privileges first */
772+ if (! capable (CAP_SYS_ADMIN))
773+ return -EPERM;
774+
775+ /*
776+ * Make sure we are not changing the options
777+ * under anybody reading them.
778+ */
779+ error = down_interruptible (& device->mxctl);
780+ if (error)
781+ return error;
782+
783+ device->options = arg;
784+ up (& device->mxctl);
785+ return error;
786+
787+
788+ case NWD_CTL_GETOPTS:
789+ /*
790+ * Make sure the options are not being changed.
791+ */
792+ error = down_interruptible (& device->mxctl);
793+ if (error)
794+ return error;
795+
796+ error = put_user (device->options, longp);
797+ up (& device->mxctl);
798+ return error;
799+
800+
801+ case BLKGETSIZE:
802+ /*
803+ * Make sure the size is not being changed.
804+ */
805+ error = down_interruptible (& device->mxctl);
806+ if (error)
807+ return error;
808+
809+ /* return device size in sectors */
810+ longv = nwd_sizes [device->devnum] << abs (NWD_B2S_SHIFT);
811+ if (NWD_B2S_SHIFT < 0)
812+ longv = nwd_sizes [device->devnum] >> abs (NWD_B2S_SHIFT);
813+
814+ error = put_user (longv, longp);
815+ up (& device->mxctl);
816+ return error;
817+
818+
819+ case BLKRRPART:
820+ /* partition re-reading is not supported */
821+ return -ENOTTY;
822+
823+
824+ case BLKFLSBUF:
825+ /* flush device locally */
826+ error = blk_ioctl (inode->i_rdev, cmd, arg);
827+ if (error)
828+ return error;
829+
830+ /* fsync remote file */
831+ return nwd_sync (device);
832+
833+
834+ default:
835+ /* let block layer handle other ioctls */
836+ return blk_ioctl (inode->i_rdev, cmd, arg);
837+ } /* command switch */
838+
839+ return -ENOTTY;
840+} /* nwd_ioctl */
841+
842+
843+static struct block_device_operations nwd_bdops = {
844+ open: nwd_open,
845+ release: nwd_release,
846+ ioctl: nwd_ioctl,
847+}; /* nwd_bdops */
848+
849+
850+/*****************************************************************************\
851+| INITIALIZATION & FINALIZATION |
852+\*****************************************************************************/
853+
854+void nwd_cleanup (void)
855+{
856+ /* devfs cleanup */
857+ if (devfs_handle != NULL)
858+ devfs_unregister (devfs_handle);
859+
860+ /* memory cleanup */
861+ if (nwd_blksizes != NULL)
862+ kfree (nwd_blksizes);
863+ if (nwd_sizes != NULL)
864+ kfree (nwd_sizes);
865+ if (nwd_devices != NULL)
866+ kfree (nwd_devices);
867+
868+ /* stop RPC I/O daemon */
869+ rpciod_down ();
870+} /* nwd_cleanup */
871+
872+
873+int __init nwd_init (void)
874+{
875+ int error;
876+ int devnum;
877+
878+ /* start RPC I/O daemon */
879+ error = rpciod_up ();
880+ if (error) {
881+ eprintk ("failed to start RPC I/O daemon\n");
882+ return error;
883+ }
884+
885+
886+ /* register block device and create devfs entries */
887+ error = devfs_register_blkdev (MAJOR_NR, DEVICE_NAME, & nwd_bdops);
888+ if (error) {
889+ eprintk ("unable to register as major %d block device\n", MAJOR_NR);
890+ nwd_cleanup ();
891+ return error;
892+ }
893+
894+ devfs_handle = devfs_mk_dir (NULL, "nwd", NULL);
895+ devfs_register_series (devfs_handle, "%u", nwd_maxdevs, DEVFS_FL_DEFAULT,
896+ MAJOR_NR, 0, S_IFBLK | S_IRUSR | S_IWUSR, & nwd_bdops, NULL);
897+
898+
899+ /* alloc memory for device structures */
900+ if (nwd_maxdevs < 1 || nwd_maxdevs > 255) {
901+ wprintk ("invalid nwd_maxdevs (%d), using default (%d)\n", nwd_maxdevs, NWD_MAX_DEVICES);
902+ nwd_maxdevs = NWD_MAX_DEVICES;
903+ }
904+
905+ nwd_devices = kmalloc (nwd_maxdevs * sizeof (nwd_device_t), GFP_KERNEL);
906+ nwd_sizes = kmalloc (nwd_maxdevs * sizeof (int), GFP_KERNEL);
907+ nwd_blksizes = kmalloc (nwd_maxdevs * sizeof (int), GFP_KERNEL);
908+ if (!nwd_devices || !nwd_sizes || !nwd_blksizes) {
909+ /* unregister device */
910+ if (devfs_unregister_blkdev (MAJOR_NR, DEVICE_NAME) != 0)
911+ wprintk ("failed to unregister block device\n");
912+
913+ eprintk ("unable to allocate memory for device structures\n");
914+ nwd_cleanup ();
915+ return -ENOMEM;
916+ }
917+
918+
919+ /*
920+ * Initialize device structures & queues. The assumption behind
921+ * multiple queues is that rpc_call sleeps while waiting for the
922+ * remote call to return (correct me if I'm wrong). Therefore with
923+ * per-device queues we can process requests to different devices
924+ * (which might possibly send remote calls through different network
925+ * interfaces) independently.
926+ */
927+ init_MUTEX (& nwd_mxdev);
928+ memset (nwd_sizes, 0, nwd_maxdevs * sizeof (nwd_sizes));
929+ memset (nwd_devices, 0, nwd_maxdevs * sizeof (nwd_device_t));
930+ for (devnum = 0; devnum < nwd_maxdevs; devnum++) {
931+ nwd_devices [devnum].devnum = devnum;
932+ nwd_devices [devnum].options = NWD_DFL_OPTIONS;
933+
934+ nwd_blksizes [devnum] = NWD_SEC_SIZE;
935+
936+ init_MUTEX (& nwd_devices [devnum].mxctl);
937+
938+ blk_init_queue (& nwd_devices [devnum].queue, DEVICE_REQUEST);
939+ blk_queue_headactive (& nwd_devices [devnum].queue, 0);
940+ }
941+
942+ blk_dev [MAJOR_NR].queue = & nwd_find_queue;
943+ blksize_size [MAJOR_NR] = nwd_blksizes;
944+ blk_size [MAJOR_NR] = nwd_sizes;
945+
946+
947+ /* register disks */
948+ for (devnum = 0; devnum < nwd_maxdevs; devnum++)
949+ register_disk (NULL, MKDEV (MAJOR_NR, devnum), 1, & nwd_bdops, 0);
950+
951+ iprintk ("version 1.4, block major %d, devices %d\n", MAJOR_NR, nwd_maxdevs);
952+ return 0;
953+} /* nwd_init */
954+
955+
956+void __exit nwd_exit (void)
957+{
958+ int devnum;
959+
960+ /* must-have-been-initialized stuff */
961+ for (devnum = 0; devnum < nwd_maxdevs; devnum++)
962+ invalidate_device (MKDEV (MAJOR_NR, devnum), 1);
963+
964+ if (devfs_unregister_blkdev (MAJOR_NR, DEVICE_NAME) != 0)
965+ wprintk ("failed to unregister block device\n");
966+
967+ for (devnum = 0; devnum < nwd_maxdevs; devnum++)
968+ blk_cleanup_queue (& nwd_devices [devnum].queue);
969+
970+ blk_dev [MAJOR_NR].queue = NULL;
971+ blksize_size [MAJOR_NR] = NULL;
972+ blk_size [MAJOR_NR] = NULL;
973+
974+ /* might-have-been-initialized stuff */
975+ nwd_cleanup ();
976+ iprintk ("driver module removed\n");
977+} /* nwd_exit */
978+
979+
980+
981+#ifdef MODULE
982+
983+/*****************************************************************************\
984+| BUILT-AS-MODULE INTERFACE |
985+\*****************************************************************************/
986+
987+MODULE_AUTHOR ("Petr Salinger, Libor Bus, Lubomir Bulej");
988+MODULE_DESCRIPTION ("Network Disk driver v1.4");
989+MODULE_SUPPORTED_DEVICE ("nwd");
990+
991+MODULE_PARM (nwd_maxdevs, "i");
992+MODULE_PARM_DESC (nwd_maxdevs, "Maximum number of NWD devices (1-255).");
993+
994+module_init (nwd_init);
995+module_exit (nwd_exit);
996+
997+#else /* not a module */
998+
999+/*****************************************************************************\
1000+| BUILT-IN-KERNEL INTERFACE |
1001+\*****************************************************************************/
1002+
1003+static int nwd_ini_port __initdata = 0;
1004+static int nwd_ini_dispose __initdata = NWD_DFL_INIDISPOSE;
1005+static int nwd_ini_devid __initdata = NWD_DFL_DEVID;
1006+static int nwd_ini_options __initdata = NWD_DFL_OPTIONS;
1007+static struct in_addr nwd_ini_server __initdata = { INADDR_ANY };
1008+static struct notifier_block nwd_notifier;
1009+
1010+
1011+static
1012+int nwd_reboot (struct notifier_block * nb, unsigned long event, void * buf)
1013+{
1014+ struct inode inode;
1015+ nwd_device_t * device;
1016+
1017+ /* ignore other devices & uninteresting events */
1018+ if (MAJOR (ROOT_DEV) != NWD_MAJOR)
1019+ return NOTIFY_DONE;
1020+
1021+ if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF)
1022+ return NOTIFY_DONE;
1023+
1024+ device = nwd_find_device (ROOT_DEV);
1025+ if (device == NULL)
1026+ return NOTIFY_BAD;
1027+
1028+
1029+ /* release the device before reboot */
1030+ iprintk ("releasing root filesystem at %s (devid=%d)\n",
1031+ in_ntoa (device->server.saddr.sin_addr.s_addr),
1032+ device->server.devid);
1033+
1034+ inode.i_rdev = ROOT_DEV;
1035+ nwd_release (& inode, NULL);
1036+
1037+
1038+ /* unlink from notifier chain */
1039+ unregister_reboot_notifier (& nwd_notifier);
1040+ return NOTIFY_OK;
1041+} /* nwd_reboot */
1042+
1043+
1044+static struct notifier_block nwd_notifier = {
1045+ notifier_call: nwd_reboot,
1046+ next: NULL,
1047+ priority: 0,
1048+}; /* nwd_notifier */
1049+
1050+
1051+int __init nwd_boot_init (void)
1052+{
1053+ int error;
1054+ nwd_res result;
1055+ nwd_device_t * device;
1056+
1057+ error = nwd_init ();
1058+ if (error)
1059+ return error;
1060+
1061+ /* ignore other devices */
1062+ if (MAJOR (ROOT_DEV) != NWD_MAJOR)
1063+ return 0;
1064+
1065+ device = nwd_find_device (ROOT_DEV);
1066+ if (device == NULL)
1067+ return -ENODEV;
1068+
1069+
1070+ /* fill the device structure with init info */
1071+ device->options = nwd_ini_options;
1072+ device->server.devid = nwd_ini_devid;
1073+ device->server.saddr.sin_family = AF_INET;
1074+ device->server.saddr.sin_addr = nwd_ini_server;
1075+ device->server.saddr.sin_port = htons (nwd_ini_port);
1076+
1077+ if (nwd_ini_server.s_addr == INADDR_ANY) {
1078+ wprintk ("server address not specified, cannot connect\n");
1079+ return -EDESTADDRREQ;
1080+ }
1081+
1082+
1083+ /* connect to the server */
1084+ iprintk ("connecting to server at %s:%d (devid=%d)\n",
1085+ in_ntoa (nwd_ini_server.s_addr), nwd_ini_port, nwd_ini_devid);
1086+
1087+ error = nwd_connect (device);
1088+ if (error)
1089+ return error;
1090+
1091+
1092+ /* initial dispose requested? */
1093+ if (nwd_ini_dispose)
1094+ nwd_dispose (device);
1095+
1096+ register_reboot_notifier (& nwd_notifier);
1097+ return error;
1098+} /* nwd_boot_init */
1099+
1100+
1101+/*****************************************************************************\
1102+| KERNEL BOOT COMMAND-LINE |
1103+\*****************************************************************************/
1104+
1105+static
1106+void __init nwd_adjust_bit (int mask, char * str, int * where)
1107+{
1108+ if ((*str == 'Y') || (*str == 'y') || (*str == '1'))
1109+ * where |= mask;
1110+ if ((*str == 'N') || (*str == 'n') || (*str == '0'))
1111+ * where &= ~mask;
1112+} /* nwd_adjust_bit */
1113+
1114+
1115+static
1116+int __init nwd_devid_setup (char * str)
1117+{
1118+ nwd_ini_devid = simple_strtol (str, NULL, 0);
1119+ return 1;
1120+} /* nwd_devid_setup */
1121+
1122+
1123+static
1124+int __init nwd_server_setup (char * str)
1125+{
1126+ char * pstr;
1127+ nwd_ini_server.s_addr = in_aton (str);
1128+ if ((pstr = strchr (str, ':')))
1129+ nwd_ini_port = simple_strtol (pstr + 1, NULL, 0);
1130+
1131+ return 1;
1132+} /* nwd_server_setup */
1133+
1134+
1135+static
1136+int __init nwd_maxdevs_setup (char * str)
1137+{
1138+ nwd_maxdevs = simple_strtol (str, NULL, 0);
1139+ return 1;
1140+} /* nwd_maxdevs_setup */
1141+
1142+
1143+static
1144+int __init nwd_ini_dispose_setup (char * str)
1145+{
1146+ nwd_adjust_bit (1, str, & nwd_ini_dispose);
1147+ return 1;
1148+} /* nwd_ini_dispose_setup */
1149+
1150+
1151+static
1152+int __init nwd_opt_dispose_setup (char * str)
1153+{
1154+ nwd_adjust_bit (NWD_OPT_DISPOSE, str, & nwd_ini_options);
1155+ return 1;
1156+} /* nwd_opt_dispose_setup */
1157+
1158+
1159+static
1160+int __init nwd_opt_disconnect_setup (char * str)
1161+{
1162+ nwd_adjust_bit (NWD_OPT_DISCONNECT, str, & nwd_ini_options);
1163+ return 1;
1164+} /* nwd_opt_disconnect_setup */
1165+
1166+
1167+static
1168+int __init nwd_opt_proto_tcp_setup (char * str)
1169+{
1170+ nwd_adjust_bit (NWD_OPT_PROTO_TCP, str, & nwd_ini_options);
1171+ return 1;
1172+} /* nwd_opt_proto_tcp_setup */
1173+
1174+
1175+static struct nwd_option {
1176+ char * str;
1177+ int (* parse) (char *);
1178+} nwd_options [] __initdata = {
1179+ { "disconnect=", nwd_opt_disconnect_setup },
1180+ { "inidispose=", nwd_ini_dispose_setup },
1181+ { "dispose=", nwd_opt_dispose_setup },
1182+ { "maxdevs=", nwd_maxdevs_setup },
1183+ { "server=", nwd_server_setup },
1184+ { "devid=", nwd_devid_setup },
1185+ { "tcp=", nwd_opt_proto_tcp_setup },
1186+}; /* nwd_options */
1187+
1188+
1189+static
1190+int __init nwd_parse_options (char * options)
1191+{
1192+ char * optstr;
1193+
1194+ optstr = strsep (& options, ",");
1195+ while (optstr != NULL) {
1196+ int num;
1197+ int len;
1198+ struct nwd_option * opt;
1199+
1200+ for (num = 0; num < ARRAY_SIZE (nwd_options); num++) {
1201+ opt = nwd_options + num;
1202+ len = strlen (opt->str);
1203+ if (strncmp (optstr, opt->str, len) == 0)
1204+ break;
1205+ }
1206+
1207+ if (num < ARRAY_SIZE (nwd_options))
1208+ opt->parse (optstr + len);
1209+
1210+ optstr = strsep (& options, ",");
1211+ }
1212+
1213+ return 1;
1214+} /* nwd_parse_options */
1215+
1216+
1217+/*****************************************************************************\
1218+| COMMAND-LINE PARAMETER HOOKS |
1219+\*****************************************************************************/
1220+
1221+/* new style options */
1222+__setup ("nwd:", nwd_parse_options);
1223+
1224+/* backward compatible options */
1225+__setup ("nwddispose=", nwd_ini_dispose_setup);
1226+__setup ("nwdserver=", nwd_server_setup);
1227+__setup ("nwddevid=", nwd_devid_setup);
1228+
1229+#endif /* not a module */
1230diff -Nur linux-2.4.20.org/drivers/block/nwd/nwd_dbg.h linux-2.4.20/drivers/block/nwd/nwd_dbg.h
1231--- linux-2.4.20.org/drivers/block/nwd/nwd_dbg.h Thu Jan 1 01:00:00 1970
1232+++ linux-2.4.20/drivers/block/nwd/nwd_dbg.h Fri Sep 14 11:01:53 2001
1233@@ -0,0 +1,45 @@
1234+/*
1235+ * Network disk client
1236+ * Debugging support
1237+ *
1238+ * Copyright (c) 1996 Petr Salinger
1239+ * Copyright (c) 1999 Libor Bus <l.bus@sh.cvut.cz>
1240+ * Copyright (c) 2001 Lubomir Bulej <pallas@kadan.cz>
1241+ *
1242+ *
1243+ * This program is free software; you can redistribute it and/or modify
1244+ * it under the terms of the GNU General Public License as published by
1245+ * the Free Software Foundation; either version 2 of the License, or
1246+ * (at your option) any later version.
1247+ *
1248+ * This program is distributed in the hope that it will be useful,
1249+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1250+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1251+ * GNU General Public License for more details.
1252+ *
1253+ * You should have received a copy of the GNU General Public License
1254+ * along with this program; if not, write to the Free Software
1255+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1256+ *
1257+ */
1258+
1259+#ifndef _NWD_DEBUG_H
1260+#define _NWD_DEBUG_H
1261+
1262+#include <linux/kernel.h>
1263+
1264+#if 0
1265+#define dprintk(args...) printk (KERN_DEBUG "nwd: " args)
1266+#define denterfn(args...) printk (KERN_DEBUG "nwd: enter " __FUNCTION__ args)
1267+#define dleavefn(args...) printk (KERN_DEBUG "nwd: leave " __FUNCTION__ args)
1268+#else
1269+#define dprintk(args...)
1270+#define denterfn(args...)
1271+#define dleavefn(args...)
1272+#endif
1273+
1274+#define iprintk(args...) printk (KERN_INFO "nwd: " args)
1275+#define eprintk(args...) printk (KERN_ERR "nwd: error: " args)
1276+#define wprintk(args...) printk (KERN_WARNING "nwd: warning: " args)
1277+
1278+#endif /* _NWD_DEBUG_H */
1279diff -Nur linux-2.4.20.org/drivers/block/nwd/nwd_xdr.c linux-2.4.20/drivers/block/nwd/nwd_xdr.c
1280--- linux-2.4.20.org/drivers/block/nwd/nwd_xdr.c Thu Jan 1 01:00:00 1970
1281+++ linux-2.4.20/drivers/block/nwd/nwd_xdr.c Thu Mar 13 09:46:35 2003
1282@@ -0,0 +1,370 @@
1283+/*
1284+ * Network disk client
1285+ * Server RPC info, XDR routines
1286+ *
1287+ * Copyright (c) 1996 Petr Salinger
1288+ * Copyright (c) 2001 Lubomir Bulej <pallas@kadan.cz>
1289+ *
1290+ *
1291+ * This program is free software; you can redistribute it and/or modify
1292+ * it under the terms of the GNU General Public License as published by
1293+ * the Free Software Foundation; either version 2 of the License, or
1294+ * (at your option) any later version.
1295+ *
1296+ * This program is distributed in the hope that it will be useful,
1297+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1298+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1299+ * GNU General Public License for more details.
1300+ *
1301+ * You should have received a copy of the GNU General Public License
1302+ * along with this program; if not, write to the Free Software
1303+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1304+ *
1305+ */
1306+
1307+#include <linux/kernel.h>
1308+#include <linux/sunrpc/clnt.h>
1309+
1310+#include "nwd_xdr.h"
1311+#include "nwd_dbg.h"
1312+
1313+
1314+/*
1315+ * Space requirements for procedure arguments and
1316+ * return types, all sizes are in 32-bit words
1317+ */
1318+
1319+#define NWD_null_sz 0
1320+#define NWD_res_sz 1
1321+#define NWD_handle_sz 1
1322+#define NWD_readargs1_sz 3
1323+#define NWD_readargs2_sz 4
1324+#define NWD_readres_sz 2
1325+#define NWD_writeargs1_sz 3
1326+#define NWD_writeargs2_sz 4
1327+#define NWD_lookupres1_sz 3
1328+#define NWD_lookupres2_sz 4
1329+
1330+
1331+/*****************************************************************************\
1332+| XDR HELPER FUNCTIONS |
1333+\*****************************************************************************/
1334+
1335+static inline
1336+u32 * xdr_encode_int (u32 * p, __u32 val)
1337+{
1338+ * p++ = htonl (val);
1339+ return p;
1340+} /* xdr_encode_int */
1341+
1342+
1343+static inline
1344+u32 * xdr_decode_int (u32 * p, __u32 * val)
1345+{
1346+ * val = ntohl (* p++);
1347+ return p;
1348+} /* xdr_decode_int */
1349+
1350+
1351+static inline
1352+u32 * xdr_encode_h2int (u32 * p, __u64 val)
1353+{
1354+ * p++ = htonl (val & 0xFFFFFFFF);
1355+ return p;
1356+} /* xdr_encode_h2int */
1357+
1358+
1359+static inline
1360+u32 * xdr_decode_int2h (u32 * p, __u64 * val)
1361+{
1362+ * val = (__u64) ntohl (* p++);
1363+ return p;
1364+} /* xdr_decode_int2h */
1365+
1366+
1367+/*****************************************************************************\
1368+| NWD XDR FUNCTIONS |
1369+\*****************************************************************************/
1370+
1371+static
1372+int nwd_xdr_null (struct rpc_rqst * req, u32 * p, void * dummy)
1373+{
1374+ return -EIO;
1375+} /* nwd_xdr_null */
1376+
1377+
1378+/*
1379+ * Decode result status
1380+ */
1381+
1382+static
1383+int nwd_xdr_res (struct rpc_rqst * req, u32 * p, nwd_res * res)
1384+{
1385+ p = xdr_decode_int (p, res);
1386+ if (* res != NWD_OK)
1387+ return -(* res);
1388+ return 0;
1389+} /* nwd_xdr_res */
1390+
1391+
1392+/*
1393+ * Encode remote file handle
1394+ */
1395+
1396+static
1397+int nwd_xdr_handle (struct rpc_rqst * req, u32 * p, nwd_handle * hnd)
1398+{
1399+ p = xdr_encode_int (p, * hnd);
1400+ req->rq_slen = xdr_adjust_iovec (req->rq_svec, p);
1401+ return 0;
1402+} /* nwd_xdr_handle */
1403+
1404+
1405+/*
1406+ * Encode READ arguments
1407+ *
1408+ * We read data directly into request buffer so we setup the
1409+ * recv iovec [1] buffer base to point at the request buffer.
1410+ *
1411+ * Note: auth->au_rslack contains estimate of the size of verf part of RPC
1412+ * reply. Together with RPC reply header size and the size of (non file-data)
1413+ * fields of procedure result it determines the "offset" of file data in the
1414+ * reply. Knowing that we can align the receive iovecs so that the file-data
1415+ * part of the reply ends up in the request buffer.
1416+ */
1417+
1418+static inline
1419+int nwd_xdr_readargs (struct rpc_rqst * req, u32 * p, nwd_rwargs * args, const int ver)
1420+{
1421+ struct rpc_auth * auth = req->rq_task->tk_auth;
1422+ int replen = (RPC_REPHDRSIZE + auth->au_rslack + NWD_readres_sz) << 2;
1423+
1424+ p = xdr_encode_int (p, args->file);
1425+ if (ver == NWD_VERSION_1)
1426+ p = xdr_encode_h2int (p, args->offset);
1427+ else if (ver == NWD_VERSION_2)
1428+ p = xdr_encode_hyper (p, args->offset);
1429+ else {
1430+ eprintk ("cannot encode readargs for version %d\n", ver);
1431+ return -EINVAL;
1432+ }
1433+
1434+ p = xdr_encode_int (p, args->count);
1435+ req->rq_slen = xdr_adjust_iovec (req->rq_svec, p);
1436+
1437+
1438+ /* set up reply iovec */
1439+ req->rq_rvec [0].iov_len = replen;
1440+ req->rq_rvec [1].iov_len = args->count;
1441+ req->rq_rvec [1].iov_base = args->buffer;
1442+ req->rq_rlen = replen + args->count;
1443+// req->rq_rnr = 2;
1444+ return 0;
1445+} /* nwd_xdr_readargs */
1446+
1447+
1448+static
1449+int nwd_xdr_readargs1 (struct rpc_rqst * req, u32 * p, nwd_rwargs * args)
1450+{
1451+ return nwd_xdr_readargs (req, p, args, NWD_VERSION_1);
1452+} /* nwd_xdr_readargs1 */
1453+
1454+
1455+static
1456+int nwd_xdr_readargs2 (struct rpc_rqst * req, u32 * p, nwd_rwargs * args)
1457+{
1458+ return nwd_xdr_readargs (req, p, args, NWD_VERSION_2);
1459+} /* nwd_xdr_readargs2 */
1460+
1461+
1462+/*
1463+ * Decode READ result
1464+ *
1465+ * Note: The file data are optional and valid only if the operation
1466+ * result status was NWD_OK. In that case, the file data were written
1467+ * directly into request buffer, for which recv iovec [1] was configured.
1468+ */
1469+
1470+static
1471+int nwd_xdr_readres (struct rpc_rqst * req, u32 * p, nwd_readres * res)
1472+{
1473+ int hdlen, recvd;
1474+
1475+ p = xdr_decode_int (p, & res->status);
1476+ if (res->status != NWD_OK)
1477+ return -res->status;
1478+
1479+ p = xdr_decode_int (p, & res->count);
1480+
1481+ /* check length of returned data */
1482+ hdlen = (u8 *) p - (u8 *) req->rq_rvec [0].iov_base;
1483+ recvd = req->rq_rlen - hdlen;
1484+ if (res->count > recvd) {
1485+ wprintk ("server cheating in read reply: count (%d) > recvd (%d)\n", res->count, recvd);
1486+ res->count = recvd;
1487+ }
1488+
1489+ return res->count;
1490+} /* nwd_xdr_readres */
1491+
1492+
1493+/*
1494+ * Encode WRITE arguments
1495+ *
1496+ * We send the data directly from request buffer, so we setup the
1497+ * send iovec [1] buffer base to point at the request buffer.
1498+ */
1499+
1500+static inline
1501+int nwd_xdr_writeargs (struct rpc_rqst * req, u32 * p, nwd_rwargs * args, const int ver)
1502+{
1503+ p = xdr_encode_int (p, args->file);
1504+ if (ver == NWD_VERSION_1)
1505+ p = xdr_encode_h2int (p, args->offset);
1506+ else if (ver == NWD_VERSION_2)
1507+ p = xdr_encode_hyper (p, args->offset);
1508+ else {
1509+ eprintk ("cannot encode writeargs for version %d\n", ver);
1510+ return -EINVAL;
1511+ }
1512+
1513+ p = xdr_encode_int (p, args->count);
1514+ req->rq_slen = xdr_adjust_iovec (req->rq_svec, p);
1515+
1516+ req->rq_svec [1].iov_base = args->buffer;
1517+ req->rq_svec [1].iov_len = args->count;
1518+ req->rq_slen += args->count;
1519+// req->rq_snr = 2;
1520+ return 0;
1521+} /* nwd_xdr_writeargs */
1522+
1523+
1524+static
1525+int nwd_xdr_writeargs1 (struct rpc_rqst * req, u32 * p, nwd_rwargs * args)
1526+{
1527+ return nwd_xdr_writeargs (req, p, args, NWD_VERSION_1);
1528+} /* nwd_xdr_writeargs1 */
1529+
1530+
1531+static
1532+int nwd_xdr_writeargs2 (struct rpc_rqst * req, u32 * p, nwd_rwargs * args)
1533+{
1534+ return nwd_xdr_writeargs (req, p, args, NWD_VERSION_2);
1535+} /* nwd_xdr_writeargs2 */
1536+
1537+
1538+/*
1539+ * Decode LOOKUP result
1540+ *
1541+ * Note: The file lookup info is optional and valid only if the
1542+ * operation result status was NWD_OK.
1543+ */
1544+
1545+static inline
1546+int nwd_xdr_lookupres (struct rpc_rqst * req, u32 * p, nwd_lookupres * res, const int ver)
1547+{
1548+ p = xdr_decode_int (p, & res->status);
1549+ if (res->status != NWD_OK)
1550+ return -res->status;
1551+
1552+ p = xdr_decode_int (p, & res->file);
1553+ if (ver == NWD_VERSION_1)
1554+ p = xdr_decode_int2h (p, & res->size);
1555+ else if (ver == NWD_VERSION_2)
1556+ p = xdr_decode_hyper (p, & res->size);
1557+ else {
1558+ eprintk ("cannot decode lookupres for version %d\n", ver);
1559+ return -EINVAL;
1560+ }
1561+
1562+ return 0;
1563+} /* nwd_xdr_lookupres */
1564+
1565+
1566+static
1567+int nwd_xdr_lookupres1 (struct rpc_rqst * req, u32 * p, nwd_lookupres * res)
1568+{
1569+ return nwd_xdr_lookupres (req, p, res, NWD_VERSION_1);
1570+} /* nwd_xdr_lookupres1 */
1571+
1572+
1573+static
1574+int nwd_xdr_lookupres2 (struct rpc_rqst * req, u32 * p, nwd_lookupres * res)
1575+{
1576+ return nwd_xdr_lookupres (req, p, res, NWD_VERSION_2);
1577+} /* nwd_xdr_lookupres2 */
1578+
1579+
1580+/*****************************************************************************\
1581+| XDR ENCODE/DECODE STRUCTURES |
1582+\*****************************************************************************/
1583+
1584+#ifndef MAX
1585+# define MAX(a, b) (((a) > (b)) ? (a) : (b))
1586+#endif
1587+
1588+/*
1589+ * Template for RPC procinfo structure
1590+ */
1591+
1592+#define PROC(proc, atype, rtype) \
1593+{ \
1594+ p_procname: "nwdproc_" #proc, \
1595+ p_encode: (kxdrproc_t) nwd_xdr_##atype, \
1596+ p_decode: (kxdrproc_t) nwd_xdr_##rtype, \
1597+ p_bufsiz: MAX (NWD_##atype##_sz, NWD_##rtype##_sz) << 2, \
1598+ p_count: 0 \
1599+}
1600+
1601+
1602+static struct rpc_procinfo nwd_procedures_1 [] = {
1603+ PROC (null, null, null),
1604+ PROC (dispose, handle, res),
1605+ PROC (read, readargs1, readres),
1606+ PROC (write, writeargs1, res),
1607+ PROC (lookup, handle, lookupres1)
1608+}; /* nwd_procedures_1 */
1609+
1610+
1611+static struct rpc_procinfo nwd_procedures_2 [] = {
1612+ PROC (null, null, null),
1613+ PROC (dispose, handle, res),
1614+ PROC (read, readargs2, readres),
1615+ PROC (write, writeargs2, res),
1616+ PROC (lookup, handle, lookupres2),
1617+ PROC (sync, handle, res)
1618+}; /* nwd_procedures_2 */
1619+
1620+
1621+static struct rpc_version nwd_version_1 = {
1622+ number: NWD_VERSION_1,
1623+ nrprocs: ARRAY_SIZE (nwd_procedures_1),
1624+ procs: nwd_procedures_1
1625+}; /* nwd_version_1 */
1626+
1627+
1628+static struct rpc_version nwd_version_2 = {
1629+ number: NWD_VERSION_2,
1630+ nrprocs: ARRAY_SIZE (nwd_procedures_2),
1631+ procs: nwd_procedures_2
1632+}; /* nwd_version_2 */
1633+
1634+
1635+
1636+static struct rpc_version * nwd_versions [] = {
1637+ NULL,
1638+ & nwd_version_1,
1639+ & nwd_version_2
1640+}; /* nwd_versions */
1641+
1642+
1643+static struct rpc_stat nwd_rpcstat;
1644+
1645+
1646+struct rpc_program nwd_program = {
1647+ name: "nwd",
1648+ number: NWD_PROGRAM,
1649+ nrvers: ARRAY_SIZE (nwd_versions),
1650+ version: nwd_versions,
1651+ stats: & nwd_rpcstat
1652+}; /* nwd_program */
1653diff -Nur linux-2.4.20.org/drivers/block/nwd/nwd_xdr.h linux-2.4.20/drivers/block/nwd/nwd_xdr.h
1654--- linux-2.4.20.org/drivers/block/nwd/nwd_xdr.h Thu Jan 1 01:00:00 1970
1655+++ linux-2.4.20/drivers/block/nwd/nwd_xdr.h Sun Sep 9 23:22:15 2001
1656@@ -0,0 +1,78 @@
1657+/*
1658+ * Network disk client
1659+ * Server RPC info, XDR routines
1660+ *
1661+ * Copyright (c) 1996 Petr Salinger
1662+ * Copyright (c) 1999 Libor Bus <l.bus@sh.cvut.cz>
1663+ * Copyright (c) 2001 Lubomir Bulej <pallas@kadan.cz>
1664+ *
1665+ *
1666+ * This program is free software; you can redistribute it and/or modify
1667+ * it under the terms of the GNU General Public License as published by
1668+ * the Free Software Foundation; either version 2 of the License, or
1669+ * (at your option) any later version.
1670+ *
1671+ * This program is distributed in the hope that it will be useful,
1672+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1673+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1674+ * GNU General Public License for more details.
1675+ *
1676+ * You should have received a copy of the GNU General Public License
1677+ * along with this program; if not, write to the Free Software
1678+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1679+ */
1680+
1681+#ifndef _NWD_XDR_H
1682+#define _NWD_XDR_H
1683+
1684+#include <linux/errno.h>
1685+#include <linux/types.h>
1686+
1687+
1688+#define NWD_PROGRAM 0x21050003
1689+#define NWD_VERSION_1 1
1690+#define NWD_VERSION_2 2
1691+
1692+#define NWD_OK 0
1693+#define NWD_ENOENT ENOENT
1694+#define NWD_EIO EIO
1695+#define NWD_EINVAL EINVAL
1696+#define NWD_ENOSPC ENOSPC
1697+
1698+#define NWDPROC_NULL 0
1699+#define NWDPROC_DISPOSE 1
1700+#define NWDPROC_READ 2
1701+#define NWDPROC_WRITE 3
1702+#define NWDPROC_LOOKUP 4
1703+#define NWDPROC_SYNC 5
1704+
1705+
1706+typedef __s32 nwd_res;
1707+typedef __s32 nwd_handle;
1708+
1709+
1710+typedef struct nwd_rwargs {
1711+ nwd_handle file;
1712+ __u64 offset;
1713+ __u32 count;
1714+ void * buffer;
1715+} nwd_rwargs;
1716+
1717+
1718+typedef struct nwd_readres {
1719+ nwd_res status;
1720+ __u32 count;
1721+} nwd_readres;
1722+
1723+
1724+typedef struct nwd_lookupres {
1725+ nwd_res status;
1726+ nwd_handle file;
1727+ __u64 size;
1728+} nwd_lookupres;
1729+
1730+
1731+extern struct rpc_stat nwd_rpcstat;
1732+extern struct rpc_program nwd_program;
1733+
1734+#endif /* _NWD_XDR_H */
1735diff -Nur linux-2.4.20.org/include/linux/nwd.h linux-2.4.20/include/linux/nwd.h
1736--- linux-2.4.20.org/include/linux/nwd.h Thu Jan 1 01:00:00 1970
1737+++ linux-2.4.20/include/linux/nwd.h Fri Sep 14 01:26:34 2001
1738@@ -0,0 +1,102 @@
1739+/*
1740+ * Network disk client
1741+ * Kernel block device driver
1742+ *
1743+ * Copyright (c) 1996 Petr Salinger
1744+ * Copyright (c) 1999 Libor Bus <l.bus@sh.cvut.cz>
1745+ * Copyright (c) 2001 Lubomir Bulej <pallas@kadan.cz>
1746+ *
1747+ *
1748+ * This program is free software; you can redistribute it and/or modify
1749+ * it under the terms of the GNU General Public License as published by
1750+ * the Free Software Foundation; either version 2 of the License, or
1751+ * (at your option) any later version.
1752+ *
1753+ * This program is distributed in the hope that it will be useful,
1754+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1755+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1756+ * GNU General Public License for more details.
1757+ *
1758+ * You should have received a copy of the GNU General Public License
1759+ * along with this program; if not, write to the Free Software
1760+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1761+ *
1762+ */
1763+
1764+#ifndef _LINUX_NWD_H
1765+#define _LINUX_NWD_H
1766+
1767+#include <linux/ioctl.h>
1768+
1769+
1770+/*****************************************************************************\
1771+| KERNEL & USER SPACE |
1772+\*****************************************************************************/
1773+
1774+#define NWD_IOCTL_CHAR 'N'
1775+#define NWD_CTL_SETPEER _IOW (NWD_IOCTL_CHAR, 0, nwd_peer_t)
1776+#define NWD_CTL_GETPEER _IOR (NWD_IOCTL_CHAR, 1, nwd_peer_t)
1777+#define NWD_CTL_SETOPTS _IO (NWD_IOCTL_CHAR, 3)
1778+#define NWD_CTL_GETOPTS _IO (NWD_IOCTL_CHAR, 4)
1779+#define NWD_CTL_DISPOSE _IO (NWD_IOCTL_CHAR, 5)
1780+
1781+#define NWD_OPT_DISPOSE 0x1 /* dispose changes on release */
1782+#define NWD_OPT_DISCONNECT 0x2 /* disconnect from server on release */
1783+#define NWD_OPT_PROTO_TCP 0x4 /* use TCP for RPC transport */
1784+
1785+typedef struct nwd_peer {
1786+ struct sockaddr_in saddr; /* socket address of the server */
1787+ int devid; /* requested identification for lookup */
1788+} nwd_peer_t;
1789+
1790+
1791+/*****************************************************************************\
1792+| KERNEL ONLY |
1793+\*****************************************************************************/
1794+
1795+#ifdef __KERNEL__
1796+
1797+#include <linux/fs.h>
1798+#include <asm/semaphore.h>
1799+#include <linux/sunrpc/clnt.h>
1800+
1801+#define NWD_MAJOR 62
1802+
1803+#define NWD_DFL_DEVID 1
1804+#define NWD_DFL_OPTIONS (NWD_OPT_DISPOSE)
1805+#define NWD_DFL_INIDISPOSE 1
1806+
1807+#define NWD_SEC_BITS 9 /* device sector size in bits */
1808+#define NWD_SEC_SIZE (1U << NWD_SEC_BITS) /* sector size (must be power of 2) */
1809+#define NWD_B2S_SHIFT (BLOCK_SIZE_BITS-NWD_SEC_BITS) /* shift to convert blocks to sectors */
1810+
1811+
1812+/*
1813+ * NWD_MAX_DGLEN determines the number of fragments per datagram
1814+ * 1024 - one fragment is enough; this is usually used for ext2
1815+ * 4096 - more fragments; useful for paging
1816+ */
1817+
1818+#define NWD_MAX_DGLEN (4 * NWD_SEC_SIZE) /* must be multiple of NWD_SEC_SIZE */
1819+#define NWD_MAX_SNLEN 20 /* max. length of server name */
1820+#define NWD_MAX_DEVICES 8 /* default number of nwd devices */
1821+#define NWD_MAX_RETRIES 10 /* how many times we retry the request */
1822+
1823+
1824+typedef struct nwd_device {
1825+ int remid; /* id of remote file disk operations */
1826+ int devnum; /* NWD device number */
1827+ int options; /* NWD device options */
1828+ nwd_peer_t server; /* server address & lookup id */
1829+ struct rpc_clnt * client; /* RPC client */
1830+ char sname [NWD_MAX_SNLEN]; /* server name for debug messages */
1831+
1832+ int users; /* reference counter */
1833+ struct semaphore mxctl; /* device control mutex */
1834+
1835+ request_queue_t queue; /* device request queue */
1836+} nwd_device_t;
1837+
1838+#endif /* __KERNEL__ */
1839+
1840+#endif /* _LINUX_NWD_H */
1841--- linux-2.4.20/include/linux/inet.h.org Sat Aug 3 02:39:45 2002
1842+++ linux-2.4.20/include/linux/inet.h Fri Mar 21 13:34:17 2003
1843@@ -46,6 +46,7 @@
1844
1845 extern void inet_proto_init(struct net_proto *pro);
1846 extern __u32 in_aton(const char *str);
1847+extern char *in_ntoa(__u32 in);
1848
1849 #endif
1850 #endif /* _LINUX_INET_H */
1851--- linux-2.4.20/net/netsyms.c.org Fri Mar 21 10:07:21 2003
1852+++ linux-2.4.20/net/netsyms.c Fri Mar 21 13:34:52 2003
1853@@ -262,6 +262,7 @@
1854 EXPORT_SYMBOL(ip_fragment);
1855 EXPORT_SYMBOL(inet_family_ops);
1856 EXPORT_SYMBOL(in_aton);
1857+EXPORT_SYMBOL(in_ntoa);
1858 EXPORT_SYMBOL(ip_mc_inc_group);
1859 EXPORT_SYMBOL(ip_mc_dec_group);
1860 EXPORT_SYMBOL(ip_mc_join_group);
1861--- linux-2.4.20/net/ipv4/utils.c.org Sat Aug 3 02:39:46 2002
1862+++ linux-2.4.20/net/ipv4/utils.c Fri Mar 21 14:35:14 2003
1863@@ -43,6 +43,22 @@
1864
1865
1866 /*
1867+ * Display an IP address in readable format.
1868+ */
1869+
1870+char *in_ntoa(__u32 in)
1871+{
1872+ static char buff[18];
1873+ char *p;
1874+
1875+ p = (char *) &in;
1876+ sprintf(buff, "%d.%d.%d.%d",
1877+ (p[0] & 255), (p[1] & 255), (p[2] & 255), (p[3] & 255));
1878+ return(buff);
1879+}
1880+
1881+
1882+/*
1883 * Convert an ASCII string to binary IP.
1884 */
1885
This page took 0.533708 seconds and 4 git commands to generate.