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