1 diff -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
5 if you want to do performance tuning, by tweaking the elevator, e.g.
9 +Network disk device support
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.
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
28 + Consult <file:Documentation/nwd.txt> for more information concerning
29 + the kernel client driver and user space server.
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
38 ATA/IDE/MFM/RLL support
40 diff -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
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
51 diff -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
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
60 tristate 'RAM disk support' CONFIG_BLK_DEV_RAM
61 if [ "$CONFIG_BLK_DEV_RAM" = "y" -o "$CONFIG_BLK_DEV_RAM" = "m" ]; then
62 diff -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
66 obj-$(CONFIG_CDROM_PKTCDVD) += pktcdvd.o
68 subdir-$(CONFIG_PARIDE) += paride
69 +subdir-$(CONFIG_BLK_DEV_NWD) += nwd
71 include $(TOPDIR)/Rules.make
72 diff -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
76 dep_mbool ' Provide NFS server over TCP support (EXPERIMENTAL)' CONFIG_NFSD_TCP $CONFIG_NFSD $CONFIG_EXPERIMENTAL
78 if [ "$CONFIG_NFS_FS" = "y" -o "$CONFIG_NFSD" = "y" ]; then
79 - define_tristate CONFIG_SUNRPC y
80 define_tristate CONFIG_LOCKD y
82 if [ "$CONFIG_NFS_FS" = "m" -o "$CONFIG_NFSD" = "m" ]; then
83 - define_tristate CONFIG_SUNRPC m
84 define_tristate CONFIG_LOCKD m
86 - define_tristate CONFIG_SUNRPC n
87 - define_tristate CONFIG_LOCKD n
89 + define_tristate CONFIG_LOCKD n
93 + if [ "$CONFIG_NFS_FS" = "y" -o "$CONFIG_NFSD" = "y" -o "$CONFIG_BLK_DEV_NWD" = "y" ]; then
94 + define_tristate CONFIG_SUNRPC y
96 + if [ "$CONFIG_NFS_FS" = "m" -o "$CONFIG_NFSD" = "m" -o "$CONFIG_BLK_DEV_NWD" = "m" ]; then
97 + define_tristate CONFIG_SUNRPC m
99 + define_tristate CONFIG_SUNRPC n
103 if [ "$CONFIG_NFSD_V3" = "y" -o "$CONFIG_NFS_V3" = "y" ]; then
104 define_bool CONFIG_LOCKD_V4 y
106 diff -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
110 #define DEVICE_REQUEST do_nbd_request
111 #define DEVICE_NR(device) (MINOR(device))
113 +#elif (MAJOR_NR == NWD_MAJOR)
115 +#define DEVICE_NAME "nwd"
116 +#define DEVICE_REQUEST nwd_request
117 +#define DEVICE_NR(device) (MINOR(device))
119 #elif (MAJOR_NR == MDISK_MAJOR)
121 #define DEVICE_NAME "mdisk"
122 diff -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
127 #define LVM_BLK_MAJOR 58 /* Logical Volume Manager */
129 +#define NWD_MAJOR 62 /* Network disk driver */
131 #define SCSI_DISK1_MAJOR 65
132 #define SCSI_DISK2_MAJOR 66
133 #define SCSI_DISK3_MAJOR 67
134 diff -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
139 { "mtdblock", 0x1f00 },
141 +#ifdef CONFIG_BLK_DEV_NWD
147 diff -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
153 extern void ecard_init(void);
154 +extern int nwd_boot_init(void);
156 #if defined(CONFIG_SYSVIPC)
157 extern void ipc_init(void);
159 start_context_thread();
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.");
170 irda_device_init(); /* Must be done after protocol initialization */
171 diff -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
176 +# Makefile for the Network disk client driver (NWD)
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).
182 +# Note 2! The CFLAGS definitions are now in the main makefile...
188 +obj-y += nwd_clt.o nwd_xdr.o
189 +obj-$(CONFIG_BLK_DEV_NWD) += $(O_TARGET)
191 +include $(TOPDIR)/Rules.make
192 diff -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
197 + * Network disk client
198 + * Kernel block device driver
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>
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.
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.
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
222 +#include <linux/kernel.h>
223 +#include <linux/module.h>
224 +#include <linux/errno.h>
226 +#include <linux/net.h> /* struct net_proto for inet.h */
227 +#include <linux/inet.h> /* in_aton, in_ntoa */
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 */
234 +#include <linux/sunrpc/clnt.h> /* rpc_call, xprt stuff, etc. */
236 +#include <asm/uaccess.h> /* verify_area, get/put_user */
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 */
242 +#include <linux/nwd.h>
243 +#include "nwd_xdr.h"
244 +#include "nwd_dbg.h"
247 +/*****************************************************************************\
249 +\*****************************************************************************/
251 +static int * nwd_sizes; /* block device sizes in KiB */
252 +static int * nwd_blksizes; /* device block/sector sizes */
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 */
258 +static devfs_handle_t devfs_handle; /* devfs directory handle */
261 +/*****************************************************************************\
262 +| DEVICE OPERATIONS |
263 +\*****************************************************************************/
266 +int nwd_disconnect (nwd_device_t * device)
268 + if (device->client == NULL)
270 + if (rpc_shutdown_client (device->client) != 0)
271 + eprintk ("unable to shutdown RPC client for device %d\n", device->devnum);
273 + /* disconnected device must have device->client == NULL */
274 + nwd_sizes [device->devnum] = 0;
275 + device->client = NULL;
277 +} /* nwd_disconnect */
281 +int nwd_connect_opt (nwd_device_t * device, int ver, int proto)
285 + struct rpc_xprt * p_xprt;
286 + nwd_lookupres lookup_res;
288 + /* refuse to connect on already connected device */
289 + if (device->client != NULL)
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";
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);
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");
315 + device->client->cl_intr = 1;
316 + device->client->cl_chatty = 0;
317 + device->client->cl_autobind = 1;
318 + device->client->cl_softrtry = 1;
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);
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));
330 + nwd_sizes [device->devnum] = lookup_res.size >> BLOCK_SIZE_BITS;
331 + device->remid = lookup_res.file;
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]);
336 +} /* nwd_connect_opt */
340 +int nwd_connect (nwd_device_t * device)
343 + int proto = IPPROTO_UDP;
346 + * Try to connect using NWD protocol version 2 first.
347 + * If that fails, fall back to version 1.
349 + proto = (device->options & NWD_OPT_PROTO_TCP) ? IPPROTO_TCP : IPPROTO_UDP;
350 + error = nwd_connect_opt (device, NWD_VERSION_2, proto);
354 + return nwd_connect_opt (device, NWD_VERSION_1, proto);
359 +int nwd_dispose (nwd_device_t * device)
362 + if (device->client == NULL)
365 + return rpc_call (device->client, NWDPROC_DISPOSE, & device->remid, & result, 0);
370 +int nwd_sync (nwd_device_t * device)
373 + if (device->client == NULL)
375 + if (device->client->cl_vers < 2)
378 + return rpc_call (device->client, NWDPROC_SYNC, & device->remid, & result, 0);
382 +/*****************************************************************************\
383 +| REQUEST PROCESSING |
384 +\*****************************************************************************/
387 +int nwd_devnum (kdev_t kdev)
389 + int devnum = DEVICE_NR (kdev);
390 + if (devnum >= nwd_maxdevs) {
391 + static int limit = 0;
393 + wprintk ("invalid device number (%d)", devnum);
403 +request_queue_t * nwd_find_queue (kdev_t kdev)
405 + int devnum = nwd_devnum (kdev);
409 + return & nwd_devices [devnum].queue;
410 +} /* nwd_find_queue */
414 +nwd_device_t * nwd_find_device (kdev_t kdev)
416 + int devnum = nwd_devnum (kdev);
420 + return nwd_devices + devnum;
421 +} /* nwd_find_device */
425 +int nwd_transfer (nwd_device_t * device, const struct request * req)
427 + u32 dgmlen; /* datagram length in bytes */
428 + u32 reqlen; /* request length in bytes */
429 + u64 offset; /* request offset in bytes */
432 + /* request attributes */
433 + reqlen = req->current_nr_sectors << NWD_SEC_BITS;
434 + offset = (u64) req->sector << NWD_SEC_BITS;
435 + buffer = req->buffer;
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.
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 */
451 + if (reqlen < dgmlen)
454 + /* remote call arguments */
455 + args.file = device->remid;
456 + args.offset = offset;
457 + args.count = dgmlen;
458 + args.buffer = buffer;
461 +retry_call: switch (req->cmd) {
463 + result = rpc_call (device->client, NWDPROC_READ, & args, & rdres, 0);
467 + result = rpc_call (device->client, NWDPROC_WRITE, & args, & res, 0);
471 + /* should not really happen */
472 + eprintk ("invalid request command: %d\n", req->cmd);
474 + } /* command switch */
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.
482 + if (result == -ETIMEDOUT) {
484 + device->client->cl_timeout.to_initval <<= 1;
486 + if (retries++ < NWD_MAX_RETRIES) {
487 + wprintk ("server not responding, retrying (%d)\n", retries);
492 + /* fail if errors persist (including too many timeouts) */
494 + eprintk ("request for %ld sectors at %ld failed, error %d\n",
495 + req->current_nr_sectors, req->sector, abs (result));
504 + } /* request loop */
507 +} /* nwd_transfer */
511 +void nwd_request (request_queue_t * rq)
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)
518 + if (device->client == NULL)
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.
528 + while (! list_empty (& rq->queue_head)) {
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);
536 + /* process buffers in the request */
538 + status = nwd_transfer (device, req);
539 + } while (end_that_request_first (req, status, DEVICE_NAME));
541 + /* grab io_request_lock & finish the request */
542 + spin_lock_irq (& io_request_lock);
543 + end_that_request_last (req);
544 + } /* request loop */
549 + * Make the request fail if the device was not found
550 + * or the device was not connected.
553 + while (end_that_request_first (req, 0, DEVICE_NAME));
554 + blkdev_dequeue_request (req);
555 + end_that_request_last (req);
559 +/*****************************************************************************\
560 +| BLOCK DEVICE OPERATIONS |
561 +\*****************************************************************************/
564 +int nwd_open (struct inode * inode, struct file * filp)
567 + nwd_device_t * device = nwd_find_device (inode->i_rdev);
568 + if (device == NULL)
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.
579 + error = down_interruptible (& device->mxctl);
586 + up (& device->mxctl);
592 +int nwd_release (struct inode * inode, struct file * filp)
595 + nwd_device_t * device;
597 + device = nwd_find_device (inode->i_rdev);
598 + if (device == NULL)
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.
608 + * We also don't want anyone changing the options under us.
610 + error = down_interruptible (& device->mxctl);
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);
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);
625 + /* disconnect from server */
626 + if (device->options & NWD_OPT_DISCONNECT)
627 + nwd_disconnect (device);
628 + } /* release actions */
630 + up (& device->mxctl);
637 +int nwd_check_server (nwd_peer_t * server, nwd_device_t * device)
641 + /* skip INADDR_ANY servers telling us to disconnect only*/
642 + if (server->saddr.sin_addr.s_addr == INADDR_ANY)
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)
649 + if (memcmp (server, & nwd_devices [devnum].server, sizeof (nwd_peer_t)) == 0)
650 + return -EADDRINUSE;
654 +} /* nwd_check_server */
658 +int nwd_ioctl (struct inode * inode, struct file * filp,
659 + unsigned int cmd, unsigned long arg)
665 + nwd_device_t * device;
667 + device = nwd_find_device (inode->i_rdev);
668 + if (device == NULL)
672 + longp = (long *) arg;
674 + case NWD_CTL_SETPEER:
675 + case NWD_CTL_DISPOSE:
677 + * First, the user must have sufficient privileges to
678 + * set/change peer or dispose changes on the device.
680 + if (! capable (CAP_SYS_ADMIN))
683 + error = verify_area (VERIFY_READ, longp, sizeof (nwd_peer_t));
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.
693 + error = down_interruptible (& device->mxctl);
698 + if (device->users > 1)
699 + goto setpeer_exit_mxctl;
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.
707 + if (cmd == NWD_CTL_SETPEER) {
708 + __copy_from_user (& server, longp, sizeof (nwd_peer_t));
710 + error = down_interruptible (& nwd_mxdev);
712 + goto setpeer_exit_mxctl;
714 + error = nwd_check_server (& server, device);
716 + goto setpeer_exit_mxdev;
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.
727 + invalidate_device (inode->i_rdev, 1);
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);
736 + error = nwd_dispose (device);
739 + setpeer_exit_mxdev:
740 + if (cmd == NWD_CTL_SETPEER)
742 + setpeer_exit_mxctl:
743 + up (& device->mxctl);
747 + case NWD_CTL_GETPEER:
748 + error = verify_area (VERIFY_WRITE, longp, sizeof (nwd_peer_t));
753 + * Make sure the peer is not being changed.
755 + error = down_interruptible (& device->mxctl);
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;
764 + /* store peer structure to user space */
765 + __copy_to_user (longp, & server, sizeof (nwd_peer_t));
766 + up (& device->mxctl);
770 + case NWD_CTL_SETOPTS:
771 + /* must have sufficient privileges first */
772 + if (! capable (CAP_SYS_ADMIN))
776 + * Make sure we are not changing the options
777 + * under anybody reading them.
779 + error = down_interruptible (& device->mxctl);
783 + device->options = arg;
784 + up (& device->mxctl);
788 + case NWD_CTL_GETOPTS:
790 + * Make sure the options are not being changed.
792 + error = down_interruptible (& device->mxctl);
796 + error = put_user (device->options, longp);
797 + up (& device->mxctl);
803 + * Make sure the size is not being changed.
805 + error = down_interruptible (& device->mxctl);
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);
814 + error = put_user (longv, longp);
815 + up (& device->mxctl);
820 + /* partition re-reading is not supported */
825 + /* flush device locally */
826 + error = blk_ioctl (inode->i_rdev, cmd, arg);
830 + /* fsync remote file */
831 + return nwd_sync (device);
835 + /* let block layer handle other ioctls */
836 + return blk_ioctl (inode->i_rdev, cmd, arg);
837 + } /* command switch */
843 +static struct block_device_operations nwd_bdops = {
845 + release: nwd_release,
850 +/*****************************************************************************\
851 +| INITIALIZATION & FINALIZATION |
852 +\*****************************************************************************/
854 +void nwd_cleanup (void)
856 + /* devfs cleanup */
857 + if (devfs_handle != NULL)
858 + devfs_unregister (devfs_handle);
860 + /* memory cleanup */
861 + if (nwd_blksizes != NULL)
862 + kfree (nwd_blksizes);
863 + if (nwd_sizes != NULL)
865 + if (nwd_devices != NULL)
866 + kfree (nwd_devices);
868 + /* stop RPC I/O daemon */
873 +int __init nwd_init (void)
878 + /* start RPC I/O daemon */
879 + error = rpciod_up ();
881 + eprintk ("failed to start RPC I/O daemon\n");
886 + /* register block device and create devfs entries */
887 + error = devfs_register_blkdev (MAJOR_NR, DEVICE_NAME, & nwd_bdops);
889 + eprintk ("unable to register as major %d block device\n", MAJOR_NR);
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);
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;
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");
913 + eprintk ("unable to allocate memory for device structures\n");
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.
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;
934 + nwd_blksizes [devnum] = NWD_SEC_SIZE;
936 + init_MUTEX (& nwd_devices [devnum].mxctl);
938 + blk_init_queue (& nwd_devices [devnum].queue, DEVICE_REQUEST);
939 + blk_queue_headactive (& nwd_devices [devnum].queue, 0);
942 + blk_dev [MAJOR_NR].queue = & nwd_find_queue;
943 + blksize_size [MAJOR_NR] = nwd_blksizes;
944 + blk_size [MAJOR_NR] = nwd_sizes;
947 + /* register disks */
948 + for (devnum = 0; devnum < nwd_maxdevs; devnum++)
949 + register_disk (NULL, MKDEV (MAJOR_NR, devnum), 1, & nwd_bdops, 0);
951 + iprintk ("version 1.4, block major %d, devices %d\n", MAJOR_NR, nwd_maxdevs);
956 +void __exit nwd_exit (void)
960 + /* must-have-been-initialized stuff */
961 + for (devnum = 0; devnum < nwd_maxdevs; devnum++)
962 + invalidate_device (MKDEV (MAJOR_NR, devnum), 1);
964 + if (devfs_unregister_blkdev (MAJOR_NR, DEVICE_NAME) != 0)
965 + wprintk ("failed to unregister block device\n");
967 + for (devnum = 0; devnum < nwd_maxdevs; devnum++)
968 + blk_cleanup_queue (& nwd_devices [devnum].queue);
970 + blk_dev [MAJOR_NR].queue = NULL;
971 + blksize_size [MAJOR_NR] = NULL;
972 + blk_size [MAJOR_NR] = NULL;
974 + /* might-have-been-initialized stuff */
976 + iprintk ("driver module removed\n");
983 +/*****************************************************************************\
984 +| BUILT-AS-MODULE INTERFACE |
985 +\*****************************************************************************/
987 +MODULE_AUTHOR ("Petr Salinger, Libor Bus, Lubomir Bulej");
988 +MODULE_DESCRIPTION ("Network Disk driver v1.4");
989 +MODULE_SUPPORTED_DEVICE ("nwd");
991 +MODULE_PARM (nwd_maxdevs, "i");
992 +MODULE_PARM_DESC (nwd_maxdevs, "Maximum number of NWD devices (1-255).");
994 +module_init (nwd_init);
995 +module_exit (nwd_exit);
997 +#else /* not a module */
999 +/*****************************************************************************\
1000 +| BUILT-IN-KERNEL INTERFACE |
1001 +\*****************************************************************************/
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;
1012 +int nwd_reboot (struct notifier_block * nb, unsigned long event, void * buf)
1014 + struct inode inode;
1015 + nwd_device_t * device;
1017 + /* ignore other devices & uninteresting events */
1018 + if (MAJOR (ROOT_DEV) != NWD_MAJOR)
1019 + return NOTIFY_DONE;
1021 + if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF)
1022 + return NOTIFY_DONE;
1024 + device = nwd_find_device (ROOT_DEV);
1025 + if (device == NULL)
1026 + return NOTIFY_BAD;
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);
1034 + inode.i_rdev = ROOT_DEV;
1035 + nwd_release (& inode, NULL);
1038 + /* unlink from notifier chain */
1039 + unregister_reboot_notifier (& nwd_notifier);
1044 +static struct notifier_block nwd_notifier = {
1045 + notifier_call: nwd_reboot,
1048 +}; /* nwd_notifier */
1051 +int __init nwd_boot_init (void)
1055 + nwd_device_t * device;
1057 + error = nwd_init ();
1061 + /* ignore other devices */
1062 + if (MAJOR (ROOT_DEV) != NWD_MAJOR)
1065 + device = nwd_find_device (ROOT_DEV);
1066 + if (device == NULL)
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);
1077 + if (nwd_ini_server.s_addr == INADDR_ANY) {
1078 + wprintk ("server address not specified, cannot connect\n");
1079 + return -EDESTADDRREQ;
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);
1087 + error = nwd_connect (device);
1092 + /* initial dispose requested? */
1093 + if (nwd_ini_dispose)
1094 + nwd_dispose (device);
1096 + register_reboot_notifier (& nwd_notifier);
1098 +} /* nwd_boot_init */
1101 +/*****************************************************************************\
1102 +| KERNEL BOOT COMMAND-LINE |
1103 +\*****************************************************************************/
1106 +void __init nwd_adjust_bit (int mask, char * str, int * where)
1108 + if ((*str == 'Y') || (*str == 'y') || (*str == '1'))
1110 + if ((*str == 'N') || (*str == 'n') || (*str == '0'))
1112 +} /* nwd_adjust_bit */
1116 +int __init nwd_devid_setup (char * str)
1118 + nwd_ini_devid = simple_strtol (str, NULL, 0);
1120 +} /* nwd_devid_setup */
1124 +int __init nwd_server_setup (char * str)
1127 + nwd_ini_server.s_addr = in_aton (str);
1128 + if ((pstr = strchr (str, ':')))
1129 + nwd_ini_port = simple_strtol (pstr + 1, NULL, 0);
1132 +} /* nwd_server_setup */
1136 +int __init nwd_maxdevs_setup (char * str)
1138 + nwd_maxdevs = simple_strtol (str, NULL, 0);
1140 +} /* nwd_maxdevs_setup */
1144 +int __init nwd_ini_dispose_setup (char * str)
1146 + nwd_adjust_bit (1, str, & nwd_ini_dispose);
1148 +} /* nwd_ini_dispose_setup */
1152 +int __init nwd_opt_dispose_setup (char * str)
1154 + nwd_adjust_bit (NWD_OPT_DISPOSE, str, & nwd_ini_options);
1156 +} /* nwd_opt_dispose_setup */
1160 +int __init nwd_opt_disconnect_setup (char * str)
1162 + nwd_adjust_bit (NWD_OPT_DISCONNECT, str, & nwd_ini_options);
1164 +} /* nwd_opt_disconnect_setup */
1168 +int __init nwd_opt_proto_tcp_setup (char * str)
1170 + nwd_adjust_bit (NWD_OPT_PROTO_TCP, str, & nwd_ini_options);
1172 +} /* nwd_opt_proto_tcp_setup */
1175 +static struct nwd_option {
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 */
1190 +int __init nwd_parse_options (char * options)
1194 + optstr = strsep (& options, ",");
1195 + while (optstr != NULL) {
1198 + struct nwd_option * opt;
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)
1207 + if (num < ARRAY_SIZE (nwd_options))
1208 + opt->parse (optstr + len);
1210 + optstr = strsep (& options, ",");
1214 +} /* nwd_parse_options */
1217 +/*****************************************************************************\
1218 +| COMMAND-LINE PARAMETER HOOKS |
1219 +\*****************************************************************************/
1221 +/* new style options */
1222 +__setup ("nwd:", nwd_parse_options);
1224 +/* backward compatible options */
1225 +__setup ("nwddispose=", nwd_ini_dispose_setup);
1226 +__setup ("nwdserver=", nwd_server_setup);
1227 +__setup ("nwddevid=", nwd_devid_setup);
1229 +#endif /* not a module */
1230 diff -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
1235 + * Network disk client
1236 + * Debugging support
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>
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.
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.
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
1259 +#ifndef _NWD_DEBUG_H
1260 +#define _NWD_DEBUG_H
1262 +#include <linux/kernel.h>
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)
1269 +#define dprintk(args...)
1270 +#define denterfn(args...)
1271 +#define dleavefn(args...)
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)
1278 +#endif /* _NWD_DEBUG_H */
1279 diff -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
1284 + * Network disk client
1285 + * Server RPC info, XDR routines
1287 + * Copyright (c) 1996 Petr Salinger
1288 + * Copyright (c) 2001 Lubomir Bulej <pallas@kadan.cz>
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.
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.
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
1307 +#include <linux/kernel.h>
1308 +#include <linux/sunrpc/clnt.h>
1310 +#include "nwd_xdr.h"
1311 +#include "nwd_dbg.h"
1315 + * Space requirements for procedure arguments and
1316 + * return types, all sizes are in 32-bit words
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
1331 +/*****************************************************************************\
1332 +| XDR HELPER FUNCTIONS |
1333 +\*****************************************************************************/
1336 +u32 * xdr_encode_int (u32 * p, __u32 val)
1338 + * p++ = htonl (val);
1340 +} /* xdr_encode_int */
1344 +u32 * xdr_decode_int (u32 * p, __u32 * val)
1346 + * val = ntohl (* p++);
1348 +} /* xdr_decode_int */
1352 +u32 * xdr_encode_h2int (u32 * p, __u64 val)
1354 + * p++ = htonl (val & 0xFFFFFFFF);
1356 +} /* xdr_encode_h2int */
1360 +u32 * xdr_decode_int2h (u32 * p, __u64 * val)
1362 + * val = (__u64) ntohl (* p++);
1364 +} /* xdr_decode_int2h */
1367 +/*****************************************************************************\
1368 +| NWD XDR FUNCTIONS |
1369 +\*****************************************************************************/
1372 +int nwd_xdr_null (struct rpc_rqst * req, u32 * p, void * dummy)
1375 +} /* nwd_xdr_null */
1379 + * Decode result status
1383 +int nwd_xdr_res (struct rpc_rqst * req, u32 * p, nwd_res * res)
1385 + p = xdr_decode_int (p, res);
1386 + if (* res != NWD_OK)
1389 +} /* nwd_xdr_res */
1393 + * Encode remote file handle
1397 +int nwd_xdr_handle (struct rpc_rqst * req, u32 * p, nwd_handle * hnd)
1399 + p = xdr_encode_int (p, * hnd);
1400 + req->rq_slen = xdr_adjust_iovec (req->rq_svec, p);
1402 +} /* nwd_xdr_handle */
1406 + * Encode READ arguments
1408 + * We read data directly into request buffer so we setup the
1409 + * recv iovec [1] buffer base to point at the request buffer.
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.
1419 +int nwd_xdr_readargs (struct rpc_rqst * req, u32 * p, nwd_rwargs * args, const int ver)
1421 + struct rpc_auth * auth = req->rq_task->tk_auth;
1422 + int replen = (RPC_REPHDRSIZE + auth->au_rslack + NWD_readres_sz) << 2;
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);
1430 + eprintk ("cannot encode readargs for version %d\n", ver);
1434 + p = xdr_encode_int (p, args->count);
1435 + req->rq_slen = xdr_adjust_iovec (req->rq_svec, p);
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;
1445 +} /* nwd_xdr_readargs */
1449 +int nwd_xdr_readargs1 (struct rpc_rqst * req, u32 * p, nwd_rwargs * args)
1451 + return nwd_xdr_readargs (req, p, args, NWD_VERSION_1);
1452 +} /* nwd_xdr_readargs1 */
1456 +int nwd_xdr_readargs2 (struct rpc_rqst * req, u32 * p, nwd_rwargs * args)
1458 + return nwd_xdr_readargs (req, p, args, NWD_VERSION_2);
1459 +} /* nwd_xdr_readargs2 */
1463 + * Decode READ result
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.
1471 +int nwd_xdr_readres (struct rpc_rqst * req, u32 * p, nwd_readres * res)
1475 + p = xdr_decode_int (p, & res->status);
1476 + if (res->status != NWD_OK)
1477 + return -res->status;
1479 + p = xdr_decode_int (p, & res->count);
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;
1489 + return res->count;
1490 +} /* nwd_xdr_readres */
1494 + * Encode WRITE arguments
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.
1501 +int nwd_xdr_writeargs (struct rpc_rqst * req, u32 * p, nwd_rwargs * args, const int ver)
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);
1509 + eprintk ("cannot encode writeargs for version %d\n", ver);
1513 + p = xdr_encode_int (p, args->count);
1514 + req->rq_slen = xdr_adjust_iovec (req->rq_svec, p);
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;
1521 +} /* nwd_xdr_writeargs */
1525 +int nwd_xdr_writeargs1 (struct rpc_rqst * req, u32 * p, nwd_rwargs * args)
1527 + return nwd_xdr_writeargs (req, p, args, NWD_VERSION_1);
1528 +} /* nwd_xdr_writeargs1 */
1532 +int nwd_xdr_writeargs2 (struct rpc_rqst * req, u32 * p, nwd_rwargs * args)
1534 + return nwd_xdr_writeargs (req, p, args, NWD_VERSION_2);
1535 +} /* nwd_xdr_writeargs2 */
1539 + * Decode LOOKUP result
1541 + * Note: The file lookup info is optional and valid only if the
1542 + * operation result status was NWD_OK.
1546 +int nwd_xdr_lookupres (struct rpc_rqst * req, u32 * p, nwd_lookupres * res, const int ver)
1548 + p = xdr_decode_int (p, & res->status);
1549 + if (res->status != NWD_OK)
1550 + return -res->status;
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);
1558 + eprintk ("cannot decode lookupres for version %d\n", ver);
1563 +} /* nwd_xdr_lookupres */
1567 +int nwd_xdr_lookupres1 (struct rpc_rqst * req, u32 * p, nwd_lookupres * res)
1569 + return nwd_xdr_lookupres (req, p, res, NWD_VERSION_1);
1570 +} /* nwd_xdr_lookupres1 */
1574 +int nwd_xdr_lookupres2 (struct rpc_rqst * req, u32 * p, nwd_lookupres * res)
1576 + return nwd_xdr_lookupres (req, p, res, NWD_VERSION_2);
1577 +} /* nwd_xdr_lookupres2 */
1580 +/*****************************************************************************\
1581 +| XDR ENCODE/DECODE STRUCTURES |
1582 +\*****************************************************************************/
1585 +# define MAX(a, b) (((a) > (b)) ? (a) : (b))
1589 + * Template for RPC procinfo structure
1592 +#define PROC(proc, atype, rtype) \
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, \
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 */
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 */
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 */
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 */
1636 +static struct rpc_version * nwd_versions [] = {
1640 +}; /* nwd_versions */
1643 +static struct rpc_stat nwd_rpcstat;
1646 +struct rpc_program nwd_program = {
1648 + number: NWD_PROGRAM,
1649 + nrvers: ARRAY_SIZE (nwd_versions),
1650 + version: nwd_versions,
1651 + stats: & nwd_rpcstat
1652 +}; /* nwd_program */
1653 diff -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
1658 + * Network disk client
1659 + * Server RPC info, XDR routines
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>
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.
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.
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
1684 +#include <linux/errno.h>
1685 +#include <linux/types.h>
1688 +#define NWD_PROGRAM 0x21050003
1689 +#define NWD_VERSION_1 1
1690 +#define NWD_VERSION_2 2
1693 +#define NWD_ENOENT ENOENT
1694 +#define NWD_EIO EIO
1695 +#define NWD_EINVAL EINVAL
1696 +#define NWD_ENOSPC ENOSPC
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
1706 +typedef __s32 nwd_res;
1707 +typedef __s32 nwd_handle;
1710 +typedef struct nwd_rwargs {
1718 +typedef struct nwd_readres {
1724 +typedef struct nwd_lookupres {
1731 +extern struct rpc_stat nwd_rpcstat;
1732 +extern struct rpc_program nwd_program;
1734 +#endif /* _NWD_XDR_H */
1735 diff -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
1740 + * Network disk client
1741 + * Kernel block device driver
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>
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.
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.
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
1764 +#ifndef _LINUX_NWD_H
1765 +#define _LINUX_NWD_H
1767 +#include <linux/ioctl.h>
1770 +/*****************************************************************************\
1771 +| KERNEL & USER SPACE |
1772 +\*****************************************************************************/
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)
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 */
1785 +typedef struct nwd_peer {
1786 + struct sockaddr_in saddr; /* socket address of the server */
1787 + int devid; /* requested identification for lookup */
1791 +/*****************************************************************************\
1793 +\*****************************************************************************/
1797 +#include <linux/fs.h>
1798 +#include <asm/semaphore.h>
1799 +#include <linux/sunrpc/clnt.h>
1801 +#define NWD_MAJOR 62
1803 +#define NWD_DFL_DEVID 1
1804 +#define NWD_DFL_OPTIONS (NWD_OPT_DISPOSE)
1805 +#define NWD_DFL_INIDISPOSE 1
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 */
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
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 */
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 */
1832 + int users; /* reference counter */
1833 + struct semaphore mxctl; /* device control mutex */
1835 + request_queue_t queue; /* device request queue */
1838 +#endif /* __KERNEL__ */
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
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);
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
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
1867 + * Display an IP address in readable format.
1870 +char *in_ntoa(__u32 in)
1872 + static char buff[18];
1876 + sprintf(buff, "%d.%d.%d.%d",
1877 + (p[0] & 255), (p[1] & 255), (p[2] & 255), (p[3] & 255));
1883 * Convert an ASCII string to binary IP.