]> git.pld-linux.org Git - packages/kernel.git/blob - nwd-2.4.21.patch
- Release 4. One more bcm43xx fix.
[packages/kernel.git] / nwd-2.4.21.patch
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
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
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
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
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
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
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
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
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
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
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
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"
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
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
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
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  
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
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 */
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
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
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
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 */
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
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 */
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
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 */
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
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 */
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
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.157611 seconds and 3 git commands to generate.