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
6 +# Makefile for the Network disk client driver (NWD)
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).
12 +# Note 2! The CFLAGS definitions are now in the main makefile...
18 +obj-y += nwd_clt.o nwd_xdr.o
19 +obj-$(CONFIG_BLK_DEV_NWD) += $(O_TARGET)
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
27 + * Network disk client
28 + * Kernel block device driver
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>
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.
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.
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
52 +#include <linux/kernel.h>
53 +#include <linux/module.h>
54 +#include <linux/errno.h>
56 +#include <linux/net.h> /* struct net_proto for inet.h */
57 +#include <linux/inet.h> /* in_aton, in_ntoa */
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 */
64 +#include <linux/sunrpc/clnt.h> /* rpc_call, xprt stuff, etc. */
66 +#include <asm/uaccess.h> /* verify_area, get/put_user */
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 */
72 +#include <linux/nwd.h>
77 +/*****************************************************************************\
79 +\*****************************************************************************/
81 +static int * nwd_sizes; /* block device sizes in KiB */
82 +static int * nwd_blksizes; /* device block/sector sizes */
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 */
88 +static devfs_handle_t devfs_handle; /* devfs directory handle */
91 +/*****************************************************************************\
92 +| DEVICE OPERATIONS |
93 +\*****************************************************************************/
96 +int nwd_disconnect (nwd_device_t * device)
98 + if (device->client == NULL)
100 + if (rpc_shutdown_client (device->client) != 0)
101 + eprintk ("unable to shutdown RPC client for device %d\n", device->devnum);
103 + /* disconnected device must have device->client == NULL */
104 + nwd_sizes [device->devnum] = 0;
105 + device->client = NULL;
107 +} /* nwd_disconnect */
111 +int nwd_connect_opt (nwd_device_t * device, int ver, int proto)
115 + struct rpc_xprt * p_xprt;
116 + nwd_lookupres lookup_res;
118 + /* refuse to connect on already connected device */
119 + if (device->client != NULL)
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";
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);
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");
145 + device->client->cl_intr = 1;
146 + device->client->cl_chatty = 0;
147 + device->client->cl_autobind = 1;
148 + device->client->cl_softrtry = 1;
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);
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));
160 + nwd_sizes [device->devnum] = lookup_res.size >> BLOCK_SIZE_BITS;
161 + device->remid = lookup_res.file;
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]);
166 +} /* nwd_connect_opt */
170 +int nwd_connect (nwd_device_t * device)
173 + int proto = IPPROTO_UDP;
176 + * Try to connect using NWD protocol version 2 first.
177 + * If that fails, fall back to version 1.
179 + proto = (device->options & NWD_OPT_PROTO_TCP) ? IPPROTO_TCP : IPPROTO_UDP;
180 + error = nwd_connect_opt (device, NWD_VERSION_2, proto);
184 + return nwd_connect_opt (device, NWD_VERSION_1, proto);
189 +int nwd_dispose (nwd_device_t * device)
192 + if (device->client == NULL)
195 + return rpc_call (device->client, NWDPROC_DISPOSE, & device->remid, & result, 0);
200 +int nwd_sync (nwd_device_t * device)
203 + if (device->client == NULL)
205 + if (device->client->cl_vers < 2)
208 + return rpc_call (device->client, NWDPROC_SYNC, & device->remid, & result, 0);
212 +/*****************************************************************************\
213 +| REQUEST PROCESSING |
214 +\*****************************************************************************/
217 +int nwd_devnum (kdev_t kdev)
219 + int devnum = DEVICE_NR (kdev);
220 + if (devnum >= nwd_maxdevs) {
221 + static int limit = 0;
223 + wprintk ("invalid device number (%d)", devnum);
233 +request_queue_t * nwd_find_queue (kdev_t kdev)
235 + int devnum = nwd_devnum (kdev);
239 + return & nwd_devices [devnum].queue;
240 +} /* nwd_find_queue */
244 +nwd_device_t * nwd_find_device (kdev_t kdev)
246 + int devnum = nwd_devnum (kdev);
250 + return nwd_devices + devnum;
251 +} /* nwd_find_device */
255 +int nwd_transfer (nwd_device_t * device, const struct request * req)
257 + u32 dgmlen; /* datagram length in bytes */
258 + u32 reqlen; /* request length in bytes */
259 + u64 offset; /* request offset in bytes */
262 + /* request attributes */
263 + reqlen = req->current_nr_sectors << NWD_SEC_BITS;
264 + offset = (u64) req->sector << NWD_SEC_BITS;
265 + buffer = req->buffer;
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.
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 */
281 + if (reqlen < dgmlen)
284 + /* remote call arguments */
285 + args.file = device->remid;
286 + args.offset = offset;
287 + args.count = dgmlen;
288 + args.buffer = buffer;
291 +retry_call: switch (req->cmd) {
293 + result = rpc_call (device->client, NWDPROC_READ, & args, & rdres, 0);
297 + result = rpc_call (device->client, NWDPROC_WRITE, & args, & res, 0);
301 + /* should not really happen */
302 + eprintk ("invalid request command: %d\n", req->cmd);
304 + } /* command switch */
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.
312 + if (result == -ETIMEDOUT) {
314 + device->client->cl_timeout.to_initval <<= 1;
316 + if (retries++ < NWD_MAX_RETRIES) {
317 + wprintk ("server not responding, retrying (%d)\n", retries);
322 + /* fail if errors persist (including too many timeouts) */
324 + eprintk ("request for %ld sectors at %ld failed, error %d\n",
325 + req->current_nr_sectors, req->sector, abs (result));
334 + } /* request loop */
337 +} /* nwd_transfer */
341 +void nwd_request (request_queue_t * rq)
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)
348 + if (device->client == NULL)
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.
358 + while (! list_empty (& rq->queue_head)) {
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);
366 + /* process buffers in the request */
368 + status = nwd_transfer (device, req);
369 + } while (end_that_request_first (req, status, DEVICE_NAME));
371 + /* grab io_request_lock & finish the request */
372 + spin_lock_irq (& io_request_lock);
373 + end_that_request_last (req);
374 + } /* request loop */
379 + * Make the request fail if the device was not found
380 + * or the device was not connected.
383 + while (end_that_request_first (req, 0, DEVICE_NAME));
384 + blkdev_dequeue_request (req);
385 + end_that_request_last (req);
389 +/*****************************************************************************\
390 +| BLOCK DEVICE OPERATIONS |
391 +\*****************************************************************************/
394 +int nwd_open (struct inode * inode, struct file * filp)
397 + nwd_device_t * device = nwd_find_device (inode->i_rdev);
398 + if (device == NULL)
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.
409 + error = down_interruptible (& device->mxctl);
416 + up (& device->mxctl);
422 +int nwd_release (struct inode * inode, struct file * filp)
425 + nwd_device_t * device;
427 + device = nwd_find_device (inode->i_rdev);
428 + if (device == NULL)
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.
438 + * We also don't want anyone changing the options under us.
440 + error = down_interruptible (& device->mxctl);
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);
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);
455 + /* disconnect from server */
456 + if (device->options & NWD_OPT_DISCONNECT)
457 + nwd_disconnect (device);
458 + } /* release actions */
460 + up (& device->mxctl);
467 +int nwd_check_server (nwd_peer_t * server, nwd_device_t * device)
471 + /* skip INADDR_ANY servers telling us to disconnect only*/
472 + if (server->saddr.sin_addr.s_addr == INADDR_ANY)
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)
479 + if (memcmp (server, & nwd_devices [devnum].server, sizeof (nwd_peer_t)) == 0)
480 + return -EADDRINUSE;
484 +} /* nwd_check_server */
488 +int nwd_ioctl (struct inode * inode, struct file * filp,
489 + unsigned int cmd, unsigned long arg)
495 + nwd_device_t * device;
497 + device = nwd_find_device (inode->i_rdev);
498 + if (device == NULL)
502 + longp = (long *) arg;
504 + case NWD_CTL_SETPEER:
505 + case NWD_CTL_DISPOSE:
507 + * First, the user must have sufficient privileges to
508 + * set/change peer or dispose changes on the device.
510 + if (! capable (CAP_SYS_ADMIN))
513 + error = verify_area (VERIFY_READ, longp, sizeof (nwd_peer_t));
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.
523 + error = down_interruptible (& device->mxctl);
528 + if (device->users > 1)
529 + goto setpeer_exit_mxctl;
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.
537 + if (cmd == NWD_CTL_SETPEER) {
538 + __copy_from_user (& server, longp, sizeof (nwd_peer_t));
540 + error = down_interruptible (& nwd_mxdev);
542 + goto setpeer_exit_mxctl;
544 + error = nwd_check_server (& server, device);
546 + goto setpeer_exit_mxdev;
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.
557 + invalidate_device (inode->i_rdev, 1);
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);
566 + error = nwd_dispose (device);
569 + setpeer_exit_mxdev:
570 + if (cmd == NWD_CTL_SETPEER)
572 + setpeer_exit_mxctl:
573 + up (& device->mxctl);
577 + case NWD_CTL_GETPEER:
578 + error = verify_area (VERIFY_WRITE, longp, sizeof (nwd_peer_t));
583 + * Make sure the peer is not being changed.
585 + error = down_interruptible (& device->mxctl);
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;
594 + /* store peer structure to user space */
595 + __copy_to_user (longp, & server, sizeof (nwd_peer_t));
596 + up (& device->mxctl);
600 + case NWD_CTL_SETOPTS:
601 + /* must have sufficient privileges first */
602 + if (! capable (CAP_SYS_ADMIN))
606 + * Make sure we are not changing the options
607 + * under anybody reading them.
609 + error = down_interruptible (& device->mxctl);
613 + device->options = arg;
614 + up (& device->mxctl);
618 + case NWD_CTL_GETOPTS:
620 + * Make sure the options are not being changed.
622 + error = down_interruptible (& device->mxctl);
626 + error = put_user (device->options, longp);
627 + up (& device->mxctl);
633 + * Make sure the size is not being changed.
635 + error = down_interruptible (& device->mxctl);
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);
644 + error = put_user (longv, longp);
645 + up (& device->mxctl);
650 + /* partition re-reading is not supported */
655 + /* flush device locally */
656 + error = blk_ioctl (inode->i_rdev, cmd, arg);
660 + /* fsync remote file */
661 + return nwd_sync (device);
665 + /* let block layer handle other ioctls */
666 + return blk_ioctl (inode->i_rdev, cmd, arg);
667 + } /* command switch */
673 +static struct block_device_operations nwd_bdops = {
675 + release: nwd_release,
680 +/*****************************************************************************\
681 +| INITIALIZATION & FINALIZATION |
682 +\*****************************************************************************/
684 +void nwd_cleanup (void)
686 + /* devfs cleanup */
687 + if (devfs_handle != NULL)
688 + devfs_unregister (devfs_handle);
690 + /* memory cleanup */
691 + if (nwd_blksizes != NULL)
692 + kfree (nwd_blksizes);
693 + if (nwd_sizes != NULL)
695 + if (nwd_devices != NULL)
696 + kfree (nwd_devices);
698 + /* stop RPC I/O daemon */
703 +int __init nwd_init (void)
708 + /* start RPC I/O daemon */
709 + error = rpciod_up ();
711 + eprintk ("failed to start RPC I/O daemon\n");
716 + /* register block device and create devfs entries */
717 + error = devfs_register_blkdev (MAJOR_NR, DEVICE_NAME, & nwd_bdops);
719 + eprintk ("unable to register as major %d block device\n", MAJOR_NR);
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);
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;
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");
743 + eprintk ("unable to allocate memory for device structures\n");
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.
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;
764 + nwd_blksizes [devnum] = NWD_SEC_SIZE;
766 + init_MUTEX (& nwd_devices [devnum].mxctl);
768 + blk_init_queue (& nwd_devices [devnum].queue, DEVICE_REQUEST);
769 + blk_queue_headactive (& nwd_devices [devnum].queue, 0);
772 + blk_dev [MAJOR_NR].queue = & nwd_find_queue;
773 + blksize_size [MAJOR_NR] = nwd_blksizes;
774 + blk_size [MAJOR_NR] = nwd_sizes;
777 + /* register disks */
778 + for (devnum = 0; devnum < nwd_maxdevs; devnum++)
779 + register_disk (NULL, MKDEV (MAJOR_NR, devnum), 1, & nwd_bdops, 0);
781 + iprintk ("version 1.4, block major %d, devices %d\n", MAJOR_NR, nwd_maxdevs);
786 +void __exit nwd_exit (void)
790 + /* must-have-been-initialized stuff */
791 + for (devnum = 0; devnum < nwd_maxdevs; devnum++)
792 + invalidate_device (MKDEV (MAJOR_NR, devnum), 1);
794 + if (devfs_unregister_blkdev (MAJOR_NR, DEVICE_NAME) != 0)
795 + wprintk ("failed to unregister block device\n");
797 + for (devnum = 0; devnum < nwd_maxdevs; devnum++)
798 + blk_cleanup_queue (& nwd_devices [devnum].queue);
800 + blk_dev [MAJOR_NR].queue = NULL;
801 + blksize_size [MAJOR_NR] = NULL;
802 + blk_size [MAJOR_NR] = NULL;
804 + /* might-have-been-initialized stuff */
806 + iprintk ("driver module removed\n");
813 +/*****************************************************************************\
814 +| BUILT-AS-MODULE INTERFACE |
815 +\*****************************************************************************/
817 +MODULE_AUTHOR ("Petr Salinger, Libor Bus, Lubomir Bulej");
818 +MODULE_DESCRIPTION ("Network Disk driver v1.4");
819 +MODULE_SUPPORTED_DEVICE ("nwd");
821 +MODULE_PARM (nwd_maxdevs, "i");
822 +MODULE_PARM_DESC (nwd_maxdevs, "Maximum number of NWD devices (1-255).");
824 +module_init (nwd_init);
825 +module_exit (nwd_exit);
827 +#else /* not a module */
829 +/*****************************************************************************\
830 +| BUILT-IN-KERNEL INTERFACE |
831 +\*****************************************************************************/
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;
842 +int nwd_reboot (struct notifier_block * nb, unsigned long event, void * buf)
844 + struct inode inode;
845 + nwd_device_t * device;
847 + /* ignore other devices & uninteresting events */
848 + if (MAJOR (ROOT_DEV) != NWD_MAJOR)
849 + return NOTIFY_DONE;
851 + if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF)
852 + return NOTIFY_DONE;
854 + device = nwd_find_device (ROOT_DEV);
855 + if (device == NULL)
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);
864 + inode.i_rdev = ROOT_DEV;
865 + nwd_release (& inode, NULL);
868 + /* unlink from notifier chain */
869 + unregister_reboot_notifier (& nwd_notifier);
874 +static struct notifier_block nwd_notifier = {
875 + notifier_call: nwd_reboot,
878 +}; /* nwd_notifier */
881 +int __init nwd_boot_init (void)
885 + nwd_device_t * device;
887 + error = nwd_init ();
891 + /* ignore other devices */
892 + if (MAJOR (ROOT_DEV) != NWD_MAJOR)
895 + device = nwd_find_device (ROOT_DEV);
896 + if (device == NULL)
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);
907 + if (nwd_ini_server.s_addr == INADDR_ANY) {
908 + wprintk ("server address not specified, cannot connect\n");
909 + return -EDESTADDRREQ;
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);
917 + error = nwd_connect (device);
922 + /* initial dispose requested? */
923 + if (nwd_ini_dispose)
924 + nwd_dispose (device);
926 + register_reboot_notifier (& nwd_notifier);
928 +} /* nwd_boot_init */
931 +/*****************************************************************************\
932 +| KERNEL BOOT COMMAND-LINE |
933 +\*****************************************************************************/
936 +void __init nwd_adjust_bit (int mask, char * str, int * where)
938 + if ((*str == 'Y') || (*str == 'y') || (*str == '1'))
940 + if ((*str == 'N') || (*str == 'n') || (*str == '0'))
942 +} /* nwd_adjust_bit */
946 +int __init nwd_devid_setup (char * str)
948 + nwd_ini_devid = simple_strtol (str, NULL, 0);
950 +} /* nwd_devid_setup */
954 +int __init nwd_server_setup (char * str)
957 + nwd_ini_server.s_addr = in_aton (str);
958 + if ((pstr = strchr (str, ':')))
959 + nwd_ini_port = simple_strtol (pstr + 1, NULL, 0);
962 +} /* nwd_server_setup */
966 +int __init nwd_maxdevs_setup (char * str)
968 + nwd_maxdevs = simple_strtol (str, NULL, 0);
970 +} /* nwd_maxdevs_setup */
974 +int __init nwd_ini_dispose_setup (char * str)
976 + nwd_adjust_bit (1, str, & nwd_ini_dispose);
978 +} /* nwd_ini_dispose_setup */
982 +int __init nwd_opt_dispose_setup (char * str)
984 + nwd_adjust_bit (NWD_OPT_DISPOSE, str, & nwd_ini_options);
986 +} /* nwd_opt_dispose_setup */
990 +int __init nwd_opt_disconnect_setup (char * str)
992 + nwd_adjust_bit (NWD_OPT_DISCONNECT, str, & nwd_ini_options);
994 +} /* nwd_opt_disconnect_setup */
998 +int __init nwd_opt_proto_tcp_setup (char * str)
1000 + nwd_adjust_bit (NWD_OPT_PROTO_TCP, str, & nwd_ini_options);
1002 +} /* nwd_opt_proto_tcp_setup */
1005 +static struct nwd_option {
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 */
1020 +int __init nwd_parse_options (char * options)
1024 + optstr = strsep (& options, ",");
1025 + while (optstr != NULL) {
1028 + struct nwd_option * opt;
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)
1037 + if (num < ARRAY_SIZE (nwd_options))
1038 + opt->parse (optstr + len);
1040 + optstr = strsep (& options, ",");
1044 +} /* nwd_parse_options */
1047 +/*****************************************************************************\
1048 +| COMMAND-LINE PARAMETER HOOKS |
1049 +\*****************************************************************************/
1051 +/* new style options */
1052 +__setup ("nwd:", nwd_parse_options);
1054 +/* backward compatible options */
1055 +__setup ("nwddispose=", nwd_ini_dispose_setup);
1056 +__setup ("nwdserver=", nwd_server_setup);
1057 +__setup ("nwddevid=", nwd_devid_setup);
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
1065 + * Network disk client
1066 + * Debugging support
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>
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.
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.
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
1089 +#ifndef _NWD_DEBUG_H
1090 +#define _NWD_DEBUG_H
1092 +#include <linux/kernel.h>
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)
1099 +#define dprintk(args...)
1100 +#define denterfn(args...)
1101 +#define dleavefn(args...)
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)
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
1114 + * Network disk client
1115 + * Server RPC info, XDR routines
1117 + * Copyright (c) 1996 Petr Salinger
1118 + * Copyright (c) 2001 Lubomir Bulej <pallas@kadan.cz>
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.
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.
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
1137 +#include <linux/kernel.h>
1138 +#include <linux/sunrpc/clnt.h>
1140 +#include "nwd_xdr.h"
1141 +#include "nwd_dbg.h"
1145 + * Space requirements for procedure arguments and
1146 + * return types, all sizes are in 32-bit words
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
1161 +/*****************************************************************************\
1162 +| XDR HELPER FUNCTIONS |
1163 +\*****************************************************************************/
1166 +u32 * xdr_encode_int (u32 * p, __u32 val)
1168 + * p++ = htonl (val);
1170 +} /* xdr_encode_int */
1174 +u32 * xdr_decode_int (u32 * p, __u32 * val)
1176 + * val = ntohl (* p++);
1178 +} /* xdr_decode_int */
1182 +u32 * xdr_encode_h2int (u32 * p, __u64 val)
1184 + * p++ = htonl (val & 0xFFFFFFFF);
1186 +} /* xdr_encode_h2int */
1190 +u32 * xdr_decode_int2h (u32 * p, __u64 * val)
1192 + * val = (__u64) ntohl (* p++);
1194 +} /* xdr_decode_int2h */
1197 +/*****************************************************************************\
1198 +| NWD XDR FUNCTIONS |
1199 +\*****************************************************************************/
1202 +int nwd_xdr_null (struct rpc_rqst * req, u32 * p, void * dummy)
1205 +} /* nwd_xdr_null */
1209 + * Decode result status
1213 +int nwd_xdr_res (struct rpc_rqst * req, u32 * p, nwd_res * res)
1215 + p = xdr_decode_int (p, res);
1216 + if (* res != NWD_OK)
1219 +} /* nwd_xdr_res */
1223 + * Encode remote file handle
1227 +int nwd_xdr_handle (struct rpc_rqst * req, u32 * p, nwd_handle * hnd)
1229 + p = xdr_encode_int (p, * hnd);
1230 + req->rq_slen = xdr_adjust_iovec (req->rq_svec, p);
1232 +} /* nwd_xdr_handle */
1236 + * Encode READ arguments
1238 + * We read data directly into request buffer so we setup the
1239 + * recv iovec [1] buffer base to point at the request buffer.
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.
1249 +int nwd_xdr_readargs (struct rpc_rqst * req, u32 * p, nwd_rwargs * args, const int ver)
1251 + struct rpc_auth * auth = req->rq_task->tk_auth;
1252 + int replen = (RPC_REPHDRSIZE + auth->au_rslack + NWD_readres_sz) << 2;
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);
1260 + eprintk ("cannot encode readargs for version %d\n", ver);
1264 + p = xdr_encode_int (p, args->count);
1265 + req->rq_slen = xdr_adjust_iovec (req->rq_svec, p);
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;
1275 +} /* nwd_xdr_readargs */
1279 +int nwd_xdr_readargs1 (struct rpc_rqst * req, u32 * p, nwd_rwargs * args)
1281 + return nwd_xdr_readargs (req, p, args, NWD_VERSION_1);
1282 +} /* nwd_xdr_readargs1 */
1286 +int nwd_xdr_readargs2 (struct rpc_rqst * req, u32 * p, nwd_rwargs * args)
1288 + return nwd_xdr_readargs (req, p, args, NWD_VERSION_2);
1289 +} /* nwd_xdr_readargs2 */
1293 + * Decode READ result
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.
1301 +int nwd_xdr_readres (struct rpc_rqst * req, u32 * p, nwd_readres * res)
1305 + p = xdr_decode_int (p, & res->status);
1306 + if (res->status != NWD_OK)
1307 + return -res->status;
1309 + p = xdr_decode_int (p, & res->count);
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;
1319 + return res->count;
1320 +} /* nwd_xdr_readres */
1324 + * Encode WRITE arguments
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.
1331 +int nwd_xdr_writeargs (struct rpc_rqst * req, u32 * p, nwd_rwargs * args, const int ver)
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);
1339 + eprintk ("cannot encode writeargs for version %d\n", ver);
1343 + p = xdr_encode_int (p, args->count);
1344 + req->rq_slen = xdr_adjust_iovec (req->rq_svec, p);
1346 + req->rq_svec [1].iov_base = args->buffer;
1347 + req->rq_svec [1].iov_len = args->count;
1348 + req->rq_slen += args->count;
1351 +} /* nwd_xdr_writeargs */
1355 +int nwd_xdr_writeargs1 (struct rpc_rqst * req, u32 * p, nwd_rwargs * args)
1357 + return nwd_xdr_writeargs (req, p, args, NWD_VERSION_1);
1358 +} /* nwd_xdr_writeargs1 */
1362 +int nwd_xdr_writeargs2 (struct rpc_rqst * req, u32 * p, nwd_rwargs * args)
1364 + return nwd_xdr_writeargs (req, p, args, NWD_VERSION_2);
1365 +} /* nwd_xdr_writeargs2 */
1369 + * Decode LOOKUP result
1371 + * Note: The file lookup info is optional and valid only if the
1372 + * operation result status was NWD_OK.
1376 +int nwd_xdr_lookupres (struct rpc_rqst * req, u32 * p, nwd_lookupres * res, const int ver)
1378 + p = xdr_decode_int (p, & res->status);
1379 + if (res->status != NWD_OK)
1380 + return -res->status;
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);
1388 + eprintk ("cannot decode lookupres for version %d\n", ver);
1393 +} /* nwd_xdr_lookupres */
1397 +int nwd_xdr_lookupres1 (struct rpc_rqst * req, u32 * p, nwd_lookupres * res)
1399 + return nwd_xdr_lookupres (req, p, res, NWD_VERSION_1);
1400 +} /* nwd_xdr_lookupres1 */
1404 +int nwd_xdr_lookupres2 (struct rpc_rqst * req, u32 * p, nwd_lookupres * res)
1406 + return nwd_xdr_lookupres (req, p, res, NWD_VERSION_2);
1407 +} /* nwd_xdr_lookupres2 */
1410 +/*****************************************************************************\
1411 +| XDR ENCODE/DECODE STRUCTURES |
1412 +\*****************************************************************************/
1415 +# define MAX(a, b) (((a) > (b)) ? (a) : (b))
1419 + * Template for RPC procinfo structure
1422 +#define PROC(proc, atype, rtype) \
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, \
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 */
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 */
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 */
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 */
1466 +static struct rpc_version * nwd_versions [] = {
1470 +}; /* nwd_versions */
1473 +static struct rpc_stat nwd_rpcstat;
1476 +struct rpc_program nwd_program = {
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
1488 + * Network disk client
1489 + * Server RPC info, XDR routines
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>
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.
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.
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
1514 +#include <linux/errno.h>
1515 +#include <linux/types.h>
1518 +#define NWD_PROGRAM 0x21050003
1519 +#define NWD_VERSION_1 1
1520 +#define NWD_VERSION_2 2
1523 +#define NWD_ENOENT ENOENT
1524 +#define NWD_EIO EIO
1525 +#define NWD_EINVAL EINVAL
1526 +#define NWD_ENOSPC ENOSPC
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
1536 +typedef __s32 nwd_res;
1537 +typedef __s32 nwd_handle;
1540 +typedef struct nwd_rwargs {
1548 +typedef struct nwd_readres {
1554 +typedef struct nwd_lookupres {
1561 +extern struct rpc_stat nwd_rpcstat;
1562 +extern struct rpc_program nwd_program;
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
1571 if [ "$CONFIG_NFS_FS" = "y" -o "$CONFIG_NFSD" = "y" ]; then
1572 - define_tristate CONFIG_SUNRPC y
1573 define_tristate CONFIG_LOCKD y
1575 if [ "$CONFIG_NFS_FS" = "m" -o "$CONFIG_NFSD" = "m" ]; then
1576 - define_tristate CONFIG_SUNRPC m
1577 define_tristate CONFIG_LOCKD m
1579 - define_tristate CONFIG_SUNRPC n
1580 - define_tristate CONFIG_LOCKD n
1582 + define_tristate CONFIG_LOCKD n
1586 + if [ "$CONFIG_NFS_FS" = "y" -o "$CONFIG_NFSD" = "y" -o "$CONFIG_BLK_DEV_NWD" = "y" ]; then
1587 + define_tristate CONFIG_SUNRPC y
1589 + if [ "$CONFIG_NFS_FS" = "m" -o "$CONFIG_NFSD" = "m" -o "$CONFIG_BLK_DEV_NWD" = "m" ]; then
1590 + define_tristate CONFIG_SUNRPC m
1592 + define_tristate CONFIG_SUNRPC n
1596 if [ "$CONFIG_NFSD_V3" = "y" -o "$CONFIG_NFS_V3" = "y" ]; then
1597 define_bool CONFIG_LOCKD_V4 y
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
1604 + * Network disk client
1605 + * Kernel block device driver
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>
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.
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.
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
1628 +#ifndef _LINUX_NWD_H
1629 +#define _LINUX_NWD_H
1631 +#include <linux/ioctl.h>
1634 +/*****************************************************************************\
1635 +| KERNEL & USER SPACE |
1636 +\*****************************************************************************/
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)
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 */
1649 +typedef struct nwd_peer {
1650 + struct sockaddr_in saddr; /* socket address of the server */
1651 + int devid; /* requested identification for lookup */
1655 +/*****************************************************************************\
1657 +\*****************************************************************************/
1661 +#include <linux/fs.h>
1662 +#include <asm/semaphore.h>
1663 +#include <linux/sunrpc/clnt.h>
1665 +#define NWD_MAJOR 62
1667 +#define NWD_DFL_DEVID 1
1668 +#define NWD_DFL_OPTIONS (NWD_OPT_DISPOSE)
1669 +#define NWD_DFL_INIDISPOSE 1
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 */
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
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 */
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 */
1696 + int users; /* reference counter */
1697 + struct semaphore mxctl; /* device control mutex */
1699 + request_queue_t queue; /* device request queue */
1702 +#endif /* __KERNEL__ */
1704 +#endif /* _LINUX_NWD_H */