]> git.pld-linux.org Git - packages/kernel.git/blame - 2.6.0-t5-enbd-2.4.31_20030506.patch
- minor fix. it builds but linking needs fix.
[packages/kernel.git] / 2.6.0-t5-enbd-2.4.31_20030506.patch
CommitLineData
3e18f7ab 1diff -Nur linux-2.6.0-test5.org/drivers/Makefile linux-2.6.0-test5/drivers/Makefile
2--- linux-2.6.0-test5.org/drivers/Makefile Mon Sep 8 19:50:21 2003
3+++ linux-2.6.0-test5/drivers/Makefile Thu Sep 25 10:39:41 2003
4@@ -33,6 +33,7 @@
5 obj-$(CONFIG_SBUS) += sbus/
6 obj-$(CONFIG_ZORRO) += zorro/
7 obj-$(CONFIG_MAC) += macintosh/
8+obj-$(CONFIG_ENBD) += block/enbd/
9 obj-$(CONFIG_PARIDE) += block/paride/
10 obj-$(CONFIG_TC) += tc/
11 obj-$(CONFIG_USB) += usb/
12diff -Nur linux-2.6.0-test5.org/drivers/Makefile.orig linux-2.6.0-test5/drivers/Makefile.orig
13--- linux-2.6.0-test5.org/drivers/Makefile.orig Thu Jan 1 00:00:00 1970
14+++ linux-2.6.0-test5/drivers/Makefile.orig Mon Sep 8 19:50:21 2003
15@@ -0,0 +1,51 @@
16+#
17+# Makefile for the Linux kernel device drivers.
18+#
19+# 15 Sep 2000, Christoph Hellwig <hch@infradead.org>
20+# Rewritten to use lists instead of if-statements.
21+#
22+
23+obj-$(CONFIG_PCI) += pci/
24+obj-$(CONFIG_PARISC) += parisc/
25+obj-$(CONFIG_ACPI_BOOT) += acpi/
26+# PnP must come after ACPI since it will eventually need to check if acpi
27+# was used and do nothing if so
28+obj-$(CONFIG_PNP) += pnp/
29+
30+# char/ comes before serial/ etc so that the VT console is the boot-time
31+# default.
32+obj-y += char/
33+obj-y += serial/
34+obj-$(CONFIG_PARPORT) += parport/
35+obj-y += base/ block/ misc/ net/ media/
36+obj-$(CONFIG_NUBUS) += nubus/
37+obj-$(CONFIG_ATM) += atm/
38+obj-$(CONFIG_PPC_PMAC) += macintosh/
39+obj-$(CONFIG_IDE) += ide/
40+obj-$(CONFIG_FC4) += fc4/
41+obj-$(CONFIG_SCSI) += scsi/
42+obj-$(CONFIG_FUSION) += message/
43+obj-$(CONFIG_IEEE1394) += ieee1394/
44+obj-y += cdrom/ video/
45+obj-$(CONFIG_MTD) += mtd/
46+obj-$(CONFIG_PCMCIA) += pcmcia/
47+obj-$(CONFIG_DIO) += dio/
48+obj-$(CONFIG_SBUS) += sbus/
49+obj-$(CONFIG_ZORRO) += zorro/
50+obj-$(CONFIG_MAC) += macintosh/
51+obj-$(CONFIG_PARIDE) += block/paride/
52+obj-$(CONFIG_TC) += tc/
53+obj-$(CONFIG_USB) += usb/
54+obj-$(CONFIG_USB_GADGET) += usb/gadget/
55+obj-$(CONFIG_INPUT) += input/
56+obj-$(CONFIG_GAMEPORT) += input/gameport/
57+obj-$(CONFIG_SERIO) += input/serio/
58+obj-$(CONFIG_I2O) += message/
59+obj-$(CONFIG_I2C) += i2c/
60+obj-$(CONFIG_PHONE) += telephony/
61+obj-$(CONFIG_MD) += md/
62+obj-$(CONFIG_BT) += bluetooth/
63+obj-$(CONFIG_ISDN_BOOL) += isdn/
64+obj-$(CONFIG_MCA) += mca/
65+obj-$(CONFIG_EISA) += eisa/
66+obj-$(CONFIG_CPU_FREQ) += cpufreq/
67diff -Nur linux-2.6.0-test5.org/drivers/block/Kconfig linux-2.6.0-test5/drivers/block/Kconfig
68--- linux-2.6.0-test5.org/drivers/block/Kconfig Thu Sep 25 10:31:05 2003
69+++ linux-2.6.0-test5/drivers/block/Kconfig Thu Sep 25 10:39:41 2003
70@@ -300,6 +300,15 @@
d912b53b 71
72 If unsure, say N.
73
74+config ENBD
75+ bool 'Enhanced network block device'
76+ depends on NET
77+ ---help---
78+ To use the ENBD support, you must say Y here and select one
79+ of the driver's units (e.g. BLK_DEV_ENBD, BLK_DEV_ENBD_IOCTL).
80+
81+source "drivers/block/enbd/Kconfig"
82+
83 config BLK_DEV_RAM
84 tristate "RAM disk support"
85 ---help---
3e18f7ab 86diff -Nur linux-2.6.0-test5.org/drivers/block/Kconfig.orig linux-2.6.0-test5/drivers/block/Kconfig.orig
87--- linux-2.6.0-test5.org/drivers/block/Kconfig.orig Thu Jan 1 00:00:00 1970
88+++ linux-2.6.0-test5/drivers/block/Kconfig.orig Thu Sep 25 10:38:06 2003
89@@ -0,0 +1,350 @@
90+#
91+# Block device driver configuration
92+#
93+
94+menu "Block devices"
95+
96+config BLK_DEV_FD
97+ tristate "Normal floppy disk support"
98+ depends on !X86_PC9800
99+ ---help---
100+ If you want to use the floppy disk drive(s) of your PC under Linux,
101+ say Y. Information about this driver, especially important for IBM
102+ Thinkpad users, is contained in <file:Documentation/floppy.txt>.
103+ That file also contains the location of the Floppy driver FAQ as
104+ well as location of the fdutils package used to configure additional
105+ parameters of the driver at run time.
106+
107+ This driver is also available as a module ( = code which can be
108+ inserted in and removed from the running kernel whenever you want).
109+ The module will be called floppy. If you want to compile it as a
110+ module, say M here and read <file:Documentation/modules.txt>.
111+
112+config AMIGA_FLOPPY
113+ tristate "Amiga floppy support"
114+ depends on AMIGA
115+
116+config ATARI_FLOPPY
117+ tristate "Atari floppy support"
118+ depends on ATARI
119+
120+config BLK_DEV_FD98
121+ tristate "NEC PC-9800 floppy disk support"
122+ depends on X86_PC9800
123+ ---help---
124+ If you want to use the floppy disk drive(s) of NEC PC-9801/PC-9821,
125+ say Y.
126+
127+config BLK_DEV_SWIM_IOP
128+ bool "Macintosh IIfx/Quadra 900/Quadra 950 floppy support (EXPERIMENTAL)"
129+ depends on MAC && EXPERIMENTAL
130+ help
131+ Say Y here to support the SWIM (Super Woz Integrated Machine) IOP
132+ floppy controller on the Macintosh IIfx and Quadra 900/950.
133+
134+config BLK_DEV_PS2
135+ tristate "PS/2 ESDI hard disk support"
136+ depends on MCA && MCA_LEGACY
137+ help
138+ Say Y here if you have a PS/2 machine with a MCA bus and an ESDI
139+ hard disk.
140+
141+ If you want to compile the driver as a module ( = code which can be
142+ inserted in and removed from the running kernel whenever you want),
143+ say M here and read <file:Documentation/modules.txt>. The module
144+ will be called ps2esdi.
145+
146+config AMIGA_Z2RAM
147+ tristate "Amiga Zorro II ramdisk support"
148+ depends on ZORRO
149+ help
150+ This enables support for using Chip RAM and Zorro II RAM as a
151+ ramdisk or as a swap partition. Say Y if you want to include this
152+ driver in the kernel. This driver is also available as a module
153+ ( = code which can be inserted in and removed from the running
154+ kernel whenever you want). The module is called z2ram. If you want
155+ to compile it as a module, say M here and read
156+ <file:Documentation/modules.txt>.
157+
158+config ATARI_ACSI
159+ tristate "Atari ACSI support"
160+ depends on ATARI
161+ ---help---
162+ This enables support for the Atari ACSI interface. The driver
163+ supports hard disks and CD-ROMs, which have 512-byte sectors, or can
164+ be switched to that mode. Due to the ACSI command format, only disks
165+ up to 1 GB are supported. Special support for certain ACSI to SCSI
166+ adapters, which could relax that, isn't included yet. The ACSI
167+ driver is also the basis for certain other drivers for devices
168+ attached to the ACSI bus: Atari SLM laser printer, BioNet-100
169+ Ethernet, and PAMsNet Ethernet. If you want to use one of these
170+ devices, you need ACSI support, too.
171+
172+ This driver is also available as a module ( = code which can be
173+ inserted in and removed from the running kernel whenever you want).
174+ The module will be called acsi.
175+
176+comment "Some devices (e.g. CD jukebox) support multiple LUNs"
177+ depends on ATARI && ATARI_ACSI
178+
179+config ACSI_MULTI_LUN
180+ bool "Probe all LUNs on each ACSI device"
181+ depends on ATARI_ACSI
182+ help
183+ If you have a ACSI device that supports more than one LUN (Logical
184+ Unit Number), e.g. a CD jukebox, you should say Y here so that all
185+ will be found by the ACSI driver. An ACSI device with multiple LUNs
186+ acts logically like multiple ACSI devices. The vast majority of ACSI
187+ devices have only one LUN, and so most people can say N here and
188+ should in fact do so, because it is safer.
189+
190+config ATARI_SLM
191+ tristate "Atari SLM laser printer support"
192+ depends on ATARI && ATARI_ACSI!=n
193+ help
194+ If you have an Atari SLM laser printer, say Y to include support for
195+ it in the kernel. Otherwise, say N. This driver is also available as
196+ a module ( = code which can be inserted in and removed from the
197+ running kernel whenever you want). The module will be called
198+ acsi_slm. Be warned: the driver needs much ST-RAM and can cause
199+ problems due to that fact!
200+
201+config BLK_DEV_XD
202+ tristate "XT hard disk support"
203+ depends on ISA
204+ help
205+ Very old 8 bit hard disk controllers used in the IBM XT computer
206+ will be supported if you say Y here.
207+
208+ If you want to compile the driver as a module ( = code which can be
209+ inserted in and removed from the running kernel whenever you want),
210+ say M here and read <file:Documentation/modules.txt>. The module
211+ will be called xd.
212+
213+ It's pretty unlikely that you have one of these: say N.
214+
215+config PARIDE
216+ tristate "Parallel port IDE device support"
217+ depends on PARPORT
218+ ---help---
219+ There are many external CD-ROM and disk devices that connect through
220+ your computer's parallel port. Most of them are actually IDE devices
221+ using a parallel port IDE adapter. This option enables the PARIDE
222+ subsystem which contains drivers for many of these external drives.
223+ Read <file:Documentation/paride.txt> for more information.
224+
225+ If you have said Y to the "Parallel-port support" configuration
226+ option, you may share a single port between your printer and other
227+ parallel port devices. Answer Y to build PARIDE support into your
228+ kernel, or M if you would like to build it as a loadable module. If
229+ your parallel port support is in a loadable module, you must build
230+ PARIDE as a module. If you built PARIDE support into your kernel,
231+ you may still build the individual protocol modules and high-level
232+ drivers as loadable modules. If you build this support as a module,
233+ it will be called paride.
234+
235+ To use the PARIDE support, you must say Y or M here and also to at
236+ least one high-level driver (e.g. "Parallel port IDE disks",
237+ "Parallel port ATAPI CD-ROMs", "Parallel port ATAPI disks" etc.) and
238+ to at least one protocol driver (e.g. "ATEN EH-100 protocol",
239+ "MicroSolutions backpack protocol", "DataStor Commuter protocol"
240+ etc.).
241+
242+source "drivers/block/paride/Kconfig"
243+
244+config BLK_CPQ_DA
245+ tristate "Compaq SMART2 support"
246+ depends on PCI
247+ help
248+ This is the driver for Compaq Smart Array controllers. Everyone
249+ using these boards should say Y here. See the file
250+ <file:Documentation/cpqarray.txt> for the current list of boards
251+ supported by this driver, and for further information on the use of
252+ this driver.
253+
254+config BLK_CPQ_CISS_DA
255+ tristate "Compaq Smart Array 5xxx support"
256+ depends on PCI
257+ help
258+ This is the driver for Compaq Smart Array 5xxx controllers.
259+ Everyone using these boards should say Y here.
260+ See <file:Documentation/cciss.txt> for the current list of
261+ boards supported by this driver, and for further information
262+ on the use of this driver.
263+
264+config CISS_SCSI_TAPE
265+ bool "SCSI tape drive support for Smart Array 5xxx"
266+ depends on BLK_CPQ_CISS_DA && SCSI
267+ help
268+ When enabled (Y), this option allows SCSI tape drives and SCSI medium
269+ changers (tape robots) to be accessed via a Compaq 5xxx array
270+ controller. (See Documentation/cciss.txt for more details.)
271+
272+ "SCSI support" and "SCSI tape support" must also be enabled for this
273+ option to work.
274+
275+ When this option is disabled (N), the SCSI portion of the driver
276+ is not compiled.
277+
278+config BLK_DEV_DAC960
279+ tristate "Mylex DAC960/DAC1100 PCI RAID Controller support"
280+ depends on PCI
281+ help
282+ This driver adds support for the Mylex DAC960, AcceleRAID, and
283+ eXtremeRAID PCI RAID controllers. See the file
284+ <file:Documentation/README.DAC960> for further information about
285+ this driver.
286+
287+ If you want to compile the driver as a module ( = code which can be
288+ inserted in and removed from the running kernel whenever you want),
289+ say M here and read <file:Documentation/modules.txt>. The module
290+ will be called DAC960.
291+
292+config BLK_DEV_UMEM
293+ tristate "Micro Memory MM5415 Battery Backed RAM support (EXPERIMENTAL)"
294+ depends on PCI && EXPERIMENTAL
295+ ---help---
296+ Saying Y here will include support for the MM5415 family of
297+ battery backed (Non-volatile) RAM cards.
298+ http://www.umem.com/
299+
300+ The cards appear as block devices that can be partitioned into
301+ as many as 15 partitions.
302+
303+ If you want to compile this driver as a module ( = code which can be
304+ inserted in and removed from the running kernel whenever you want),
305+ say M here and read Documentation/modules.txt. The module will be
306+ called umem.
307+
308+ The umem driver has not yet been allocated a MAJOR number, so
309+ one is chosen dynamically. Use "devfs" or look in /proc/devices
310+ for the device number
311+
312+config BLK_DEV_LOOP
313+ tristate "Loopback device support"
314+ ---help---
315+ Saying Y here will allow you to use a regular file as a block
316+ device; you can then create a file system on that block device and
317+ mount it just as you would mount other block devices such as hard
318+ drive partitions, CD-ROM drives or floppy drives. The loop devices
319+ are block special device files with major number 7 and typically
320+ called /dev/loop0, /dev/loop1 etc.
321+
322+ This is useful if you want to check an ISO 9660 file system before
323+ burning the CD, or if you want to use floppy images without first
324+ writing them to floppy. Furthermore, some Linux distributions avoid
325+ the need for a dedicated Linux partition by keeping their complete
326+ root file system inside a DOS FAT file using this loop device
327+ driver.
328+
329+ To use the loop device, you need the losetup utility, found in the
330+ util-linux package, see
331+ <ftp://ftp.kernel.org/pub/linux/utils/util-linux/>.
332+
333+ The loop device driver can also be used to "hide" a file system in
334+ a disk partition, floppy, or regular file, either using encryption
335+ (scrambling the data) or steganography (hiding the data in the low
336+ bits of, say, a sound file). This is also safe if the file resides
337+ on a remote file server.
338+
339+ There are several ways of doing this. Some of these require kernel
340+ patches. The vanilla kernel offers the cryptoloop option. If you
341+ want to use that, say Y to both LOOP and CRYPTOLOOP, and make sure
342+ you have a recent (version 2.12 or later) version of util-linux.
343+
344+ Note that this loop device has nothing to do with the loopback
345+ device used for network connections from the machine to itself.
346+
347+ If you want to compile this driver as a module ( = code which can be
348+ inserted in and removed from the running kernel whenever you want),
349+ say M here and read <file:Documentation/modules.txt>. The module
350+ will be called loop.
351+
352+ Most users will answer N here.
353+
354+config BLK_DEV_CRYPTOLOOP
355+ tristate "Cryptoloop Support"
356+ select CRYPTO
357+ depends on BLK_DEV_LOOP
358+ ---help---
359+ Say Y here if you want to be able to use the ciphers that are
360+ provided by the CryptoAPI as loop transformation. This might be
361+ used as hard disk encryption.
362+
363+config BLK_DEV_NBD
364+ tristate "Network block device support"
365+ depends on NET
366+ ---help---
367+ Saying Y here will allow your computer to be a client for network
368+ block devices, i.e. it will be able to use block devices exported by
369+ servers (mount file systems on them etc.). Communication between
370+ client and server works over TCP/IP networking, but to the client
371+ program this is hidden: it looks like a regular local file access to
372+ a block device special file such as /dev/nd0.
373+
374+ Network block devices also allows you to run a block-device in
375+ userland (making server and client physically the same computer,
376+ communicating using the loopback network device).
377+
378+ Read <file:Documentation/nbd.txt> for more information, especially
379+ about where to find the server code, which runs in user space and
380+ does not need special kernel support.
381+
382+ Note that this has nothing to do with the network file systems NFS
383+ or Coda; you can say N here even if you intend to use NFS or Coda.
384+
385+ If you want to compile this driver as a module ( = code which can be
386+ inserted in and removed from the running kernel whenever you want),
387+ say M here and read <file:Documentation/modules.txt>. The module
388+ will be called nbd.
389+
390+ If unsure, say N.
391+
392+config BLK_DEV_RAM
393+ tristate "RAM disk support"
394+ ---help---
395+ Saying Y here will allow you to use a portion of your RAM memory as
396+ a block device, so that you can make file systems on it, read and
397+ write to it and do all the other things that you can do with normal
398+ block devices (such as hard drives). It is usually used to load and
399+ store a copy of a minimal root file system off of a floppy into RAM
400+ during the initial install of Linux.
401+
402+ Note that the kernel command line option "ramdisk=XX" is now
403+ obsolete. For details, read <file:Documentation/ramdisk.txt>.
404+
405+ If you want to compile this as a module ( = code which can be
406+ inserted in and removed from the running kernel whenever you want),
407+ say M and read <file:Documentation/modules.txt>. The module will be
408+ called rd.
409+
410+ Most normal users won't need the RAM disk functionality, and can
411+ thus say N here.
412+
413+config BLK_DEV_RAM_SIZE
414+ int "Default RAM disk size"
415+ depends on BLK_DEV_RAM
416+ default "4096"
417+ help
418+ The default value is 4096. Only change this if you know what are
419+ you doing. If you are using IBM S/390, then set this to 8192.
420+
421+config BLK_DEV_INITRD
422+ bool "Initial RAM disk (initrd) support"
423+ help
424+ The initial RAM disk is a RAM disk that is loaded by the boot loader
425+ (loadlin or lilo) and that is mounted as root before the normal boot
426+ procedure. It is typically used to load modules needed to mount the
427+ "real" root file system, etc. See <file:Documentation/initrd.txt>
428+ for details.
429+
430+config LBD
431+ bool "Support for Large Block Devices"
432+ depends on X86 || MIPS32 || PPC32 || ARCH_S390_31 || SUPERH
433+ help
434+ Say Y here if you want to attach large (bigger than 2TB) discs to
435+ your machine, or if you want to have a raid or loopback device
436+ bigger than 2TB. Otherwise say N.
437+
438+endmenu
439+
440diff -Nur linux-2.6.0-test5.org/drivers/block/enbd/Kconfig linux-2.6.0-test5/drivers/block/enbd/Kconfig
441--- linux-2.6.0-test5.org/drivers/block/enbd/Kconfig Thu Jan 1 00:00:00 1970
442+++ linux-2.6.0-test5/drivers/block/enbd/Kconfig Mon Mar 24 17:32:36 2003
443@@ -0,0 +1,47 @@
444+#
445+# ENBD configuration
446+#
447+#comment "Enhanced network block device"
448+
449+config BLK_DEV_ENBD
450+ tristate 'Enhanced network block device driver'
451+ depends on ENBD
452+ ---help---
453+ Saying Y here will build in support for the "enhanced network
454+ block device". Like the plain NBD, this device proxies a remote
455+ hard disk or other block device, such as a cdrom or floppy. The
456+ difference between ENBD and NBD is that ENBD is a much more
457+ heavyweight solution for an industrial setting - it does automatic
458+ reconnects after network brownouts, and uses multiple channels at
459+ once to carry the data. It supports remote ioctls, removable
460+ devices, and uses an MD5 sampling technique to accelerate softRAID
461+ resyncs. It will connect through (secure) SSL channels. It will
462+ hide transient errors from overlying softRAID devices, etc.
463+
464+ You will need the userspace daemons, which packages are mirrored
465+ on several places on the net. The primary source is
466+ ftp://oboe.it.uc3m.es/pub/Programs/nbd/nbd-2.4-current.tgz.
467+
468+ If you want to compile this driver as a module ( = code which can
469+ be inserted in and removed from the running kernel whenever you
470+ want), say M here and read <file:Documentation/modules.txt>. The
471+ module will be called enbd.o.
472+
473+ If unsure, say N.
474+
475+config BLK_DEV_ENBD_IOCTL
476+ tristate 'Enhanced network block device remote ioctl support'
477+ depends on BLK_DEV_ENBD
478+ ---help---
479+ Saying Y here will build in support to ENBD for execution
480+ of remote ioctls on compatible architectures. This means that
481+ you can eject a CD on the other machine.
482+
483+ If you want to compile this driver as a module ( = code which can
484+ be inserted in and removed from the running kernel whenever you
485+ want), say M here and read <file:Documentation/modules.txt>. The
486+ module will be called enbd.o.
487+
488+ If unsure, say N.
489+#endmenu
490+
491diff -Nur linux-2.6.0-test5.org/drivers/block/enbd/Makefile linux-2.6.0-test5/drivers/block/enbd/Makefile
492--- linux-2.6.0-test5.org/drivers/block/enbd/Makefile Thu Jan 1 00:00:00 1970
493+++ linux-2.6.0-test5/drivers/block/enbd/Makefile Mon Mar 24 21:52:59 2003
494@@ -0,0 +1,11 @@
495+#
496+# Makefile for ENBD (Peter T. Breuer ptb@it.uc3m.es)
497+#
498+#
499+
500+obj-$(CONFIG_BLK_DEV_ENBD) += enbd.o
501+obj-$(CONFIG_BLK_DEV_ENBD_IOCTL) += enbd_ioctl.o
502+
503+enbd-objs := enbd_base.o enbd_ioctl_stub.o enbd_seqno.o enbd_md.o enbd_speed.o enbd_proc.o
504+
505+
506diff -Nur linux-2.6.0-test5.org/drivers/block/enbd/ccount.lst linux-2.6.0-test5/drivers/block/enbd/ccount.lst
507--- linux-2.6.0-test5.org/drivers/block/enbd/ccount.lst Thu Jan 1 00:00:00 1970
508+++ linux-2.6.0-test5/drivers/block/enbd/ccount.lst Tue Mar 25 15:00:00 2003
509@@ -0,0 +1,12 @@
510+ ccount 1.0: NCSS Comnts Funcs Blanks Lines
511+ enbd.mod.c: 2 0 0 3 13
512+ enbd_base.c: 1449 739 71 615 4174
513+enbd_base.mod.c: 2 0 0 3 13
514+ enbd_ioctl.c: 70 59 12 42 409
515+enbd_ioctl.mod.c: 2 0 0 3 13
516+enbd_ioctl_stub.c: 10 3 3 3 30
517+ enbd_md.c: 34 7 6 13 99
518+ enbd_proc.c: 452 32 16 133 1060
519+ enbd_seqno.c: 20 13 5 8 75
520+ enbd_speed.c: 18 4 2 14 64
521+ Totals: 2059 857 115 837 5950
522diff -Nur linux-2.6.0-test5.org/drivers/block/enbd/enbd.mod.c linux-2.6.0-test5/drivers/block/enbd/enbd.mod.c
523--- linux-2.6.0-test5.org/drivers/block/enbd/enbd.mod.c Thu Jan 1 00:00:00 1970
524+++ linux-2.6.0-test5/drivers/block/enbd/enbd.mod.c Mon Mar 24 21:51:59 2003
525@@ -0,0 +1,13 @@
526+#include <linux/module.h>
527+#include <linux/vermagic.h>
528+#include <linux/compiler.h>
529+
530+const char vermagic[]
531+__attribute__((section("__vermagic"))) =
532+VERMAGIC_STRING;
533+
534+static const char __module_depends[]
535+__attribute_used__
536+__attribute__((section(".modinfo"))) =
537+"depends=";
538+
539diff -Nur linux-2.6.0-test5.org/drivers/block/enbd/enbd_base.c linux-2.6.0-test5/drivers/block/enbd/enbd_base.c
540--- linux-2.6.0-test5.org/drivers/block/enbd/enbd_base.c Thu Jan 1 00:00:00 1970
541+++ linux-2.6.0-test5/drivers/block/enbd/enbd_base.c Tue Mar 25 22:19:54 2003
542@@ -0,0 +1,4192 @@
d912b53b 543+/*
544+ * (Enhanced) Network block device - make block devices work over TCP
545+ *
546+ * Original NBD Copyright 1997 Pavel Machek <pavel@elf.mj.gts.cz>
547+ * Further ENBD Copyrights 1998, 1999, 2000 Peter Breuer <ptb@it.uc3m.es>
548+ *
549+ *
550+ *
551+ * ATTENTION: You need the userspace daemons available from
552+ * ftp://oboe.it.uc3m.es/pub/Programs/nbd-2.4.*.tgz
553+ * and/or the ENBD project on http://freshmeat.net
554+ *
555+ *
556+ *
557+ * Development of the ENBD software has been supported by grants and
558+ * contributions from Realm Information Technologies, Inc. of 5555
559+ * Oakbrook Parkway, NW Norcross, GA and iNsu Innovations Inc. of
560+ * 3465, Boulevard Thimens, Saint-Laurent, Quebec, Canada.
561+ *
562+ * ------------ Pavel's history notes ----------------------------------
563+ * 97-3-25 compiled 0-th version, not yet tested it
564+ * (it did not work, BTW) (later that day) HEY! it works!
565+ * (bit later) hmm, not that much... 2:00am next day:
566+ * yes, it works, but it gives something like 50kB/sec
567+ * 97-3-28 it's completely strange - when using 1024 byte "packets"
568+ * it gives 50kB/sec and CPU idle; with 2048 bytes it gives
569+ * 500kB/sec (and CPU loaded 100% as it should be) (all done
570+ * against localhost)
571+ * 97-4-1 complete rewrite to make it possible for many requests at
572+ * once to be processed
573+ * 97-4-1 23:57 rewrite once again to make it work :-(
574+ * 97-4-3 00:02 hmm, it does not work.
575+ * 97-4-3 23:06 hmm, it will need one more rewrite :-)
576+ * 97-4-10 It looks like it's working and stable. But I still do not
577+ * have any recovery from lost connection...
578+ * (setq tab-width 4)
579+ * 97-4-11 Making protocol independent of endianity etc.
580+ * 97-4-15 Probably one more rewrite, since it loses requests under
581+ * heavy loads
582+ * 97-9-13 Cosmetic changes
583+ *
584+ * possible FIXME: make set_sock / set_blksize / set_size / do_it one syscall
585+ * why not: would need verify_area and friends, would share yet another
586+ * structure with userland
587+ *
588+ * FIXME: not module-safe
589+ *
590+ * ------------ Peter's history notes ----------------------------------
591+ * 98-12-18 modules now OK ptb@it.uc3m.es (Peter Breuer) ported to
592+ * 2.0.*. + better debugging. Still possible lockup in connection with APM
593+ * and spurious interrupt - only on write. Error treatment should
594+ * be improved. After 100 errors from end_request the kernel can
595+ * do anything. We should catch it ourselves.
596+ * 99-1-sometime fixed lockup by extending semaphore - ptb v1.0.
597+ * 99-3-sometime reconnect protocol (client mod agreed by pavel) - ptb v1.1
598+ * 99-4-25 add /proc/nbdinfo - ptb v1.1.1
599+ * 99-4-sometime add multiplex - ptb v1.2
600+ * 99-4-26 fix multiplex and redundancy - ptb v1.2.1
601+ * 99-4-29 reentrant client threads - ptb v1.2.2
602+ * 99-4-29 socket related stuff placed in user space - amarin v1.3.0
603+ * 99-5-3 fix all, all writes had to be before all reads - ptb v1.2.4
604+ * 99-5-5 fix out-of-order, async - ptb v1.2.5
605+ * 99-5-7 semaphores removed (still works!), fail cases corrected - ptb v1.2.6
606+ * 99-5-12 signals unblocked in xmit, blksize != 1024 fixed, ioctls
607+ * added - ptb v1.2.7
608+ * 99-6-1 interaction with client split into two functions - amarin v1.3.0
609+ * 99-6-3 reintegrated fully, mem manager fixed, accounts fixed - ptb v1.2.8.3
610+ * 99-6-3 extra queue removed, mem manager removed - ptb v1.2.8.4
611+ * 99-7-3 buffer registration introduced - ptb v1.2.8.5
612+ * 99-7-3 some client redundancy reestablished - ptb v2.1.1
613+ * 99-7-10 encapsulated queue calls. One element rollback buffer - ptb v2.1.2
614+ * 99-7-20 timestamp and rollback old abandoned request - ptb v2.1.3
615+ * 99-7-24 64bit file sizes and offsets accepted - ptb v2.1.9
616+ * 99-7-26 experimental request coalesces - ptb v2.1.10
617+ * 99-7-27 partitioning scheme - ptb v2.2.1
618+ * 99-8-3 nbd_clr_sock bug in invalidate_device fixed? - ptb v2.2.4
619+ * 99-8-5 reverse replace of block_fsync, add sig ioctls - ptb v2.2.5
620+ * reverse bug introduced about v2.2.3 for compound reqs - ptb v2.2.5
621+ * fix clear_que bug (didn't rollback first) from 2.1.3 - ptb v2.2.5
622+ * 99-8-22 workaround strange nr_sectors bug - ptb v2.2.6
623+ * 99-8-11 fix MY_NBD_SYNC bug. Never sync'ed all - ptb v2.2.7
624+ * 99-8-12 wakeups all moved to enqueue - ptb v2.2.7
625+ * 99-8-23 remove slot->cli_age - ptb v2.2.7
626+ * 99-8-24 first 8 bytes of signature embedded in packets - ptb v2.2.8
627+ * fix SET_SIG define buglet, remove hardcoded constants - ptb v2.2.8
628+ * fix huge bug. Missing copy_fromfs in my_nbd_ack - ptb v2.2.8
629+ * removed signature embedding and all other decorations - ptb v2.2.8
630+ * 99-8-25 recast fix in my_nbd_ack to avoid align. bug - ptb v2.2.9
631+ * put in MKDEVs and put back some hardcode const fixes - ptb v2.2.10
632+ * 99-9-29 fix BLKGETSIZE bug - ptb v2.2.14
633+ * 99-10-2 run with interrupts on throughout. Think we lose some - ptb v2.2.15
634+ * 99-10-8 trim dead code, kernel 2.2 ifdef's - ptb v2.2.17
635+ * 99-12-18 further o-o - ptb v2.2.19
636+ * 99-12-28 queue account cleanup. endio on queue reqs at reset - ptb v2.2.20
637+ * interruptible semaphores for better client recovery - ptb v2.2.20
638+ * 00-1-2 debugging cleanups. Fix race in end_request - ptb v2.2.21
639+ * 00-1-4 semaphores simplified. - ptb v2.2.22
640+ * 00-6-8 emergency control by write to proc - ptb v2.2.24
641+ * 00-7-20 ported to 2.4.0-test1. Possible minor bugs found/fixed - ptb v2.2.24
642+ * 00-7-27 changed proc i/f to read_proc from get_info in 2.2/2.4 - ptb v2.2.25
643+ * 00-7-30 fixed reads before writes under 2.4 by disabling merge - ptb v2.2.25
644+ * 00-7-30 and fixed merge_reqs for 2.4, now that I understand! - ptb v2.2.25
645+ * 00-7-30 fixed/introduced possible bug in end_io for 2.2/2.4 - ptb v2.2.25
646+ * 00-7-30 added timeval/zone field in requests and replies - ptb v2.4.0
647+ * 00-7-30 fixed hitherto masked bug in read_stat in nbd_client - ptb v2.4.0
648+ * 00-7-30 added timeout to net writes in nbd_client - ptb v2.4.0
649+ * 00-8-20 display fix for devices over 2GB - ptb v2.4.5
650+ * 00-8-23 more 64 bit fixes + error out overrange requests- ptb v2.4.6/2.2.27
651+ * 00-8-31 add NBD_ERR ioctl to error out slot request- ptb v2.4.9
652+ * 00-8-31 soften NBD_SOFT_RESET so doesn't wreck protocol - ptb v2.4.9
653+ * 00-9-1 remove %L's from printfs. Kernel 2.2. doesn't - ptb v2.4.10/2.2.27
654+ * 00-9-6 add various state flags to help init order - ptb v2.4.11
655+ * 00-9-8 add checks for device initialised to set_sock - ptb v2.4.12
656+ * 00-9-17 en/disable device as aslot count goes through 0 - ptb v2.4.13/2.2.28
657+ * 00-9-21 split read/write dev req counts for accounting - ptb v2.4.14
658+ * 00-9-21 renamed sync_intvl to req_timeo - ptb v2.4.14
659+ * 00-9-21 made sync_intvl count write blocks - ptb v2.4.14
660+ * 00-9-22 repair enable after delayed disable when disabled - ptb v2.4.14
661+ * 00-9-22 include sync (nonblocking) after sync_intvl reqs - ptb v2.4.14
662+ * 00-9-25 disable sync (nonblocking) after sync_intvl reqs - ptb v2.4.14
663+ * 00-9-25 bundle invalidate_buffers in clr_sock - ptb v2.4.14
664+ * 00-10-20 implement req_timeo per device + ioctl (Wang Gang) - ptb v2.4.15
665+ * 00-10-20 add raid mode (Wang Gang) - ptb v2.4.15
666+ * 00-10-26 throttle in do_req - ptb v2.4.15
667+ * 00-10-28 do set_sock on first open and clr_sock on last close - ptb v2.4.15
668+ * 00-11-01 make sync_intvl really sync - ptb v2.4.15
669+ * 00-11-14 rename throttle to plug, nbd_sync takes arg - ptb v2.4.17
670+ * 00-11-19 clr_sock errs req not rollback if show_errs & !aslot - ptb v2.4.17
671+ * 00-11-20 removed autodeadlock when disabled in do_req end_req - ptb v2.4.17
672+ * 00-11-21 make MY_NBD_SYNC only sync when sync_intvl > 0 - ptb v2.4.17
673+ * 00-12-24 make MY_NBD_GET_REQ use a timeout arg - ptb v2.4.18
674+ * 01-02-12 ported to 2.4.0 (works). do_nbd_request rewritten - ptb v2.4.20
675+ * 01-02-20 managed to get plugging and clustered read/writes OK - ptb v2.4.21
676+ * 01-02-21 eliminated slot->buflen for the time being - ptb v2.4.21
677+ * 01-02-27 added proper devfs support - ptb v2.4.22
678+ * 01-03-15 allowed more devices/in devfs, cleaned up endio - ptb v2.4.23
679+ * 01-03-15 added device letter (<= 3 chars) to struct- - ptb v2.4.23
680+ * 01-03-15 added request size check to do_nbd_req - ptb v2.4.23
681+ * 01-03-15 increased MAX_SECTORS to 512 by default - ptb v2.4.23
682+ * 01-03-15 made major number a module parameter - ptb v2.4.23
683+ * 01-03-18 added max_sectors array - ptb v2.4.23
684+ * 01-03-23 added devfs links - ptb v2.4.23
685+ * 01-04-17 plugging always enabled for 2.4 kernels - ptb v2.4.24
686+ * 01-04-17 made SET_RO set_device_ro as well as set local flags - ptb v2.4.25
687+ * 01-04-28 impl SET_MD5SUM ioctl and proc support for md5sum - ptb v2.4.25
688+ * 01-04-29 added accounting for md5'd reqs - ptb v2.4.25
689+ * 01-07-29 added atomic protections for accounting - ptb v2.4.25
690+ * 01-08-01 fixed 2.4 smp bugs. Interrupts off in spinlocks - ptb v2.4.25
691+ * 01-08-01 removed all semaphores for spinlocks - ptb v2.4.25
692+ * 01-08-01 invalidate_buffers in clr_sock (req'd Rogier Wolff) - ptb v2.4.25
693+ * 01-08-02 fixed smp deadlock - end_that_request_first slept! ptb v2.4.26
694+ * 01-10-16 provisionally added error in device open when notenabled ptb v2.4.27
695+ * 01-10-18 added DIRTY flag to save on repeated invalidate_buffers ptb v2.4.27
696+ * 01-10-31 increment seqno_out before delivery, so really starts at 1 v2.4.27
697+ * 01-11-01 move zeroing of seqno in cmd field to nbe_end_req* ptb v2.4.27
698+ * 01-11-18 add speed calculation, dev fields, display in proc ptb v2.4.27
699+ * 01-11-20 modifications for compiling into monolithic kernel ptb v2.4.27
700+ * 01-12-06 clr requests before reenabling, not after, in nbd_enable ptb 2.4.27
701+ * 02-02-21 make nbd_rollback modal, absirbing nbd_error ptb 2.4.27
702+ * 02-08-08 added local BLKSSZGET (reject) and related ioctls ptb 2.4.30
703+ * 02-08-12 make nbd_ack not ruin req when its rolled back already ptb 2.4.30
704+ * 02-09-18 fix __FUNCTION__ for new gcc ptb 2.4.30
705+ * 02-09-18 always allow daemon death even with reqs waiting ptb 2.4.30
706+ * 02-09-18 eliminate SYNC_REQD, RLSE_REQD ptb 2.4.30
707+ * 02-09-18 eliminate speed_lim ptb 2.4.30
708+ * 02-09-18 fix countq accounting ptb 2.4.30
709+ * 02-09-18 encapsulate remote ioctl handling ptb 2.4.30
710+ * 02-09-18 remote ioctl uses kernel req, not our fake one ptb 2.4.30
711+ * 02-09-18 eliminated ctldta use (too much tricky logic) ptb 2.4.30
712+ * 02-09-28 handle req specials ptb 2.4.30
713+ * 02-10-10 introduce DIRECT flag ptb 2.4.30
714+ * 02-10-13 rollback pushes reqs to local queue, not queues them! ptb 2.4.30
715+ * 02-10-13 add hooks for separate ioctl module ptb 2.4.30
716+ * 02-10-16 take set_sock out of open. Put pid check in handshake ptb 2.4.30
717+ * 02-10-16 define MY_NBD_GET_NPORT ioctl ptb 2.4.30
718+ * 02-10-18 remove wait from MY_NBD_SYNC ioctl ptb 2.4.30
719+ * 02-10-20 rollback adds requests to queue in seqno order ptb 2.4.30
720+ * 02-10-23 introduce and use pid_sem instead of req_sem ptb 2.4.30
721+ * 02-10-30 support client fallback to ioctls on whole disk ptb 2.4.30
722+ * 02-11-3 moved set INITIALISED up to coincide with setting inode ptb 2.4.30
723+ * 02-11-3 add media check and revalidate routines ptb 2.4.30
724+ * 02-11-4 encapuslate lives++ and ENABLED changes into nbd_enable ptb 2.4.30
725+ * 02-11-4 set_enable from proc only enables, not clears queue ptb 2.4.30
726+ * 11-11-4 take blk_put_request out of end_request (it locks!) ptb 2.4.30
727+ * 11-11-4 replace list_del by list_del_init ptb 2.4.30
728+ * 02-12-7 nbd_release made aware of daemons on whole disk ptb 2.4.30
729+ * 03-01-7 added ioctls for setfaulty etc. ptb 2.4.31
730+ * 03-02-1 used metalock for non-queue changes ptb 2.4.31
731+ * 03-03-12 add md_list notification ioctls ptb 2.4.31
732+ */
733+
734+#include <linux/major.h>
735+#ifndef UNIX98_PTY_MAJOR_COUNT
736+ #define UNIX98_PTY_MAJOR_COUNT 8
737+ #ifndef UNIX98_NR_MAJORS
738+ #define UNIX98_NR_MAJORS=UNIX98_PTY_MAJOR_COUNT
739+ #endif
740+#endif
741+
742+#include <linux/module.h>
743+
744+#if defined(__GNUC__) && __GNUC__ >= 2
745+#define _LOOSE_KERNEL_NAMES
746+#endif
747+
748+#include <linux/version.h>
749+
750+#include <linux/fs.h>
751+#include <linux/stat.h>
752+#include <linux/errno.h>
753+#include <asm/segment.h>
754+
755+#include <asm/uaccess.h> /* PTB - when did this arrive in kernel? */
756+#include <asm/byteorder.h>
757+#include <linux/wrapper.h>
758+
759+#define MAJOR_NR NBD_MAJOR
760+static int major = MAJOR_NR;
761+
762+#include <linux/proc_fs.h>
763+#include <linux/genhd.h>
764+#include <linux/hdreg.h>
765+
766+#include <linux/file.h> /* PTB - when did this arrive in kernel? */
767+
768+#include <linux/smp_lock.h>
769+
770+#include <linux/devfs_fs_kernel.h>
771+
772+#include <linux/sysctl.h>
773+#include <linux/init.h>
774+#include <linux/kdev_t.h>
775+#include <linux/buffer_head.h>
776+#include <linux/completion.h>
777+
778+/* *
779+ * PTB --------------- compatibility ------------------- *
780+ * layer starts here. *
781+ */
782+
783+ /*
784+ * PTB BH_Protected disappeared somewhere around 2.4.10 but this is
785+ * still needed for the very rare write local/read remote mode. DOn't
786+ * worry about it in normal operation!
787+ */
3e18f7ab 788+#ifndef mark_buffer_protected
d912b53b 789+ #define mark_buffer_protected(rbh) \
790+ { \
791+ mark_buffer_dirty (rbh); \
792+ mark_buffer_uptodate (rbh, 1); \
793+ refile_buffer (rbh); \
794+ }
3e18f7ab 795+#endif
d912b53b 796+
797+ /* PTB list interface extensions */
3e18f7ab 798+#ifndef list_head
d912b53b 799+ #define list_head(ptr, type, member) \
800+ (list_empty(ptr)?NULL:list_entry(((struct list_head *)ptr)->next,type,member))
3e18f7ab 801+#endif
802+#ifndef list_tail
d912b53b 803+ #define list_tail(ptr, type, member) \
804+ (list_empty(ptr)?NULL:list_entry(((struct list_head *)ptr)->prev,type,member))
3e18f7ab 805+#endif
d912b53b 806+
807+ /* PTB for arches without the atomic mask ops (and no smp, I think!)
808+ * - feel free to correct with assembler
809+ */
3e18f7ab 810+#ifndef atomic_set_mask
811+ #define atomic_set_mask(mask, x) (x)->counter |= (mask)
812+#endif
813+#ifndef atomic_clear_mask
814+ #define atomic_clear_mask(mask, x) (x)->counter &= ~(mask)
815+#endif
d912b53b 816+
817+/* *
818+ * PTB --------------- compatibility ------------------- *
819+ * layer ENDS here. *
820+ */
821+
822+int linux_version_code = LINUX_VERSION_CODE;
823+
824+#include <linux/bio.h>
825+#include <linux/enbd.h>
826+#include <linux/enbd_ioctl.h>
827+
828+/*
829+ * PTB kernel data - 4KB worth
830+ * We need space for nda, nda1, .. nda15, ndb, ndb1, ..
831+ * The index is exactly the minor number.
832+ */
833+ static int nbd_blksizes[MAX_NBD * NBD_MAXCONN];
834+ static int nbd_sizes[MAX_NBD * NBD_MAXCONN];
835+ static __u64 nbd_bytesizes[MAX_NBD * NBD_MAXCONN];
836+ static int nbd_max_sectors[MAX_NBD * NBD_MAXCONN];
837+
838+/*
839+ * PTB our data - about 3KB
840+ * These are nda, ndb, ndc, ...
841+ * Divide the minor by NBD_MAXCONN to get this index.
842+ */
843+ static struct nbd_device nbd_dev[MAX_NBD];
844+ static spinlock_t nbd_lock = SPIN_LOCK_UNLOCKED;
845+ static struct nbd_md nbd_md;
846+ static struct nbd_ioctl_stub nbd_remote_ioctl;
847+
848+ struct nbd_device * nbd_get(int i) {
849+ return &nbd_dev[i];
850+ }
851+
852+ #define NBD_FAIL( s ) { \
853+ NBD_DEBUG(1, s " (result %d).\n" , result ); \
854+ goto error_out; \
855+ }
856+ #define NBD_HARDFAIL( s ) { \
857+ NBD_ERROR( s " (result %d).\n" , result ); \
858+ lo->harderror = result; \
859+ goto hard_error_out; \
860+ }
861+
862+/*
863+ * PTB device parameters. These are module parameters too.
864+ */
865+
866+ static int rahead = NBD_RAHEAD_DFLT;/* PTB - read ahead blocks */
867+ static int sync_intvl = NBD_SYNC_INTVL; /* PTB - sync every n secs/Kreqs */
868+ static int merge_requests /* PTB - bool, do request coalesce */
869+ = NBD_MERGE_REQ_DFLT;
870+ static int buf_sectors = NBD_MAX_SECTORS;
871+ /* PTB - user bufsize required */
872+ static int show_errs = 1; /* PTB - RAID mode? not usually */
873+ static int direct = 0; /* PTB - all opens are O_DIRECT */
874+ static int plug = NBD_PLUG_DFLT;
875+
876+ static int md5sum = 0; /* PTB - use md5summing write proto */
877+ static int md5_on_threshold = 1000; /* PTB - reqs reqd to turn md5 on */
878+ static int md5_off_threshold = 10; /* PTB - errs reqd to turn md5 off */
879+
880+#ifndef NO_BUFFERED_WRITES
881+ static int buffer_writes = 0; /* PTB - act like ramd on write */
882+#endif /* NO_BUFFERED_WRITES */
883+
884+#if defined(MODULE)
885+ MODULE_PARM (rahead, "i");
886+ MODULE_PARM (sync_intvl, "i");
887+ MODULE_PARM (merge_requests, "i");
888+ MODULE_PARM (buf_sectors, "i");
889+ MODULE_PARM (show_errs, "i");
890+ MODULE_PARM (direct,"i");
891+ #ifndef NO_BUFFERED_WRITES
892+ MODULE_PARM (buffer_writes, "i");
893+ #endif /* NO_BUFFERED_WRITES */
894+ MODULE_PARM (major, "i");
895+ MODULE_PARM (md5sum, "i");
896+ MODULE_PARM (md5_on_threshold, "i");
897+ MODULE_PARM (md5_off_threshold, "i");
898+#endif
899+
900+ // PTB This pointer is initialised in nbd_init.
901+ static struct request_queue * nbd_queue;
902+
903+#define NO_BUFFERED_WRITES 1
904+
905+/* *
906+ * PTB --------------- functions ----------------------- *
907+ */
908+
909+/*
910+ * PTB
911+ * Decode the request type of a request and return it. DOn't we
912+ * have anywhere else to put this? Yes, in private data. But
913+ * that's just a pointer to our device data so we don't use it.
914+ *
915+ * we use the low bit (REQ_RW) of the flags and the first high bit
916+ * (REQ_NBD) to designate the type of request.
917+ *
918+ * @req the request to get the type of.
919+ */
920+
921+static int
922+rq_type (struct request *req)
923+{
924+ if (req->flags & REQ_SPECIAL)
925+ return SPECIAL;
926+
927+ switch ( ((req->flags & REQ_RW) ?1:0)
928+ | ((req->flags & REQ_NBD)?2:0)
929+ ) {
930+ case 0:
931+ return READ;
932+ case 1:
933+ return WRITE;
934+ case 2:
935+ return IOCTL;
936+ case 3:
937+ return MD5SUM;
938+ }
939+ // PTB report what we can of the strangeness if it is strange
940+ return (req->flags < 4) ? -1: req->flags;
941+}
942+
943+/*
944+ * PTB code the request type into a request.
945+ *
946+ * This appears to be only used when making an ioctl request and it
947+ * never really escapes from our private area and it doesn't matter too
948+ * much how efficient it is either.
949+ *
950+ * This function marks a request for conventional viewing as
951+ * being of the designated conceptual type. It correspomds to the old
952+ * "type" field in requests.
953+ *
954+ * @req the request to set the type on
955+ * @type one of READ, WRITE, etc.
956+ */
957+static void
958+set_rq_type (struct request *req, int type)
959+{
960+ switch (type) {
961+ case READ:
962+ req->flags &= ~(REQ_RW | REQ_NBD | REQ_SPECIAL);
963+ return;
964+ case WRITE:
965+ req->flags &= ~(REQ_NBD | REQ_SPECIAL);
966+ req->flags |= REQ_RW;
967+ return;
968+ case IOCTL:
969+ req->flags &= ~(REQ_RW | REQ_SPECIAL);
970+ req->flags |= REQ_NBD;
971+ return;
972+ case MD5SUM:
973+ req->flags &= ~REQ_SPECIAL;
974+ req->flags |= REQ_RW | REQ_NBD;
975+ return;
976+ case SPECIAL:
977+ req->flags |= REQ_RW | REQ_NBD | REQ_SPECIAL;
978+ return;
979+ }
980+}
981+
982+/*
983+ * PTB count number of blocks in a request. This will be an overestimate
984+ * if the number is not an exact multiple. It seems to happen. We
985+ * guarrantee to return -ve only if the request is invalid.
986+ *
987+ * @req - request we want to count
988+ */
989+inline long
990+nr_blks (struct request *req)
991+{
992+ unsigned log_sectors_per_blk;
993+ unsigned sectors_per_blk;
994+ int size;
995+ int sectors;
996+ struct nbd_device *lo;
997+
998+ if (!req)
999+ return -EINVAL;
1000+
1001+ if (rq_type(req) == REQ_SPECIAL) // PTB contains no data
1002+ return 0;
1003+
1004+ lo = req->rq_disk->private_data;
1005+
1006+ log_sectors_per_blk = lo->logblksize - 9;
1007+ sectors_per_blk = 1 << log_sectors_per_blk;
1008+
1009+ sectors = req->nr_sectors;
1010+ size = (sectors + sectors_per_blk - 1) >> log_sectors_per_blk;
1011+
1012+ return size;
1013+}
1014+
1015+/*
1016+ * return a temporary buffer containing the (1 or 2 char) device letter.
1017+ * This works for i up to 26*26. 0 is "a". The buffer is zero
1018+ * terminated.
1019+ *
1020+ * @i number to be translated to x[y] alphabetical form.
1021+ */
1022+static char *
1023+device_letter (int i)
1024+{
1025+
1026+ static char buf[3];
1027+ static int cached_i = -1;
1028+
1029+ if (cached_i == i)
1030+ return buf;
1031+
1032+ cached_i = i;
1033+
1034+ if (i < 26) {
1035+ buf[0] = 'a' + i;
1036+ buf[1] = 0;
1037+ return buf;
1038+ }
1039+
1040+ buf[0] = 'a' + i / 26;
1041+ buf[1] = 'a' + i % 26;
1042+ buf[2] = 0;
1043+ return buf;
1044+}
1045+
1046+/*
1047+ * PTB auxiliary functions for manipulating the sequence number. Isn't
1048+ * there anything private we can use in a request?
1049+ *
1050+ * This function returns the sequno
1051+ *
1052+ * @req the request to get the sequence number of
1053+ */
1054+static int
1055+rq_seqno (struct request *req)
1056+{
1057+ return req->flags >> __REQ_NBDSEQNO;
1058+}
1059+static void
1060+rq_set_seqno (struct request *req, int val)
1061+{
1062+ // PTB preserve first __REQ_NR_BITS bits
1063+ req->flags &= REQ_NBDSEQNO - 1;
1064+ // PTB shift by one more than strictly necessary (see rq_seqno)
1065+ req->flags |= val << __REQ_NBDSEQNO;
1066+}
1067+
1068+/*
1069+ * PTB sync the device. Modes:
1070+ * @arg = 1: Do it sync
1071+ * @arg = 0: Do it async
1072+ *
1073+ * We can't call sync_dev outside a process context. I don't know why.
1074+ * Death results from a scheduled attempt.
1075+ *
1076+ * Call without the semaphore held, as we lock it and call sync_dev.
1077+ */
1078+static void
1079+nbd_sync (struct nbd_device *lo, long arg)
1080+{
1081+ struct inode *inode = lo->inode;
1082+ short minor, nbd, islot;
1083+
1084+ islot = atomic_read (&lo->islot);
1085+
1086+ if (!(atomic_read (&lo->flags) & NBD_INITIALISED) || !inode) {
1087+ goto fail;
1088+ }
1089+
1090+ minor = minor (inode->i_rdev);
1091+ nbd = minor >> NBD_SHIFT;
1092+
1093+ // PTB sync_dev is async. fsync_dev is sync.
1094+ switch (arg) {
1095+ case 0: // async
1096+ // PTB 2.5.7 does not have async sync! FIXME
1097+ break;
1098+ default: // sync
1099+ fsync_bdev (inode->i_bdev);
1100+ invalidate_buffers (mk_kdev (major, nbd << NBD_SHIFT));
1101+ break;
1102+ }
1103+
1104+ return;
1105+
1106+ fail:
1107+}
1108+
1109+static void
1110+nbd_async_sync (struct nbd_device *lo)
1111+{
1112+ nbd_sync (lo, 0);
1113+}
1114+static void
1115+nbd_sync_sync (struct nbd_device *lo)
1116+{
1117+ nbd_sync (lo, 1);
1118+}
1119+
1120+/*
1121+ * Do sync async if we're enabled, sync if we're not.
1122+ *
1123+ * @lo the device to maybe sync (sync or async sync!)
1124+ */
1125+static void
1126+nbd_maybe_sync_sync (struct nbd_device *lo)
1127+{
1128+
1129+ if ((atomic_read (&lo->flags) & NBD_ENABLED)
1130+ && !(atomic_read (&lo->flags) & NBD_REMOTE_INVALID)) {
1131+ nbd_async_sync (lo);
1132+ return;
1133+ }
1134+ nbd_sync_sync (lo);
1135+}
1136+
1137+
1138+
1139+
1140+/*
1141+ * PTB - put a request onto the head of a nbd device's queue
1142+ * - presumably having taken it off the kernel's queue first!
1143+ * - We take the queue spinlock.
1144+ *
1145+ * @lo = the device we are on (could we get it from the req?)
1146+ * @req = the request we shift
1147+ * @irqsave = save and restore irqmask when taking our queue spinlock
1148+ */
1149+static void
1150+nbd_enqueue (struct nbd_device *lo, struct request *req)
1151+{
1152+ unsigned long req_blks = nr_blks (req);
1153+
1154+ if (req_blks < 0) {
1155+ short islot = atomic_read (&lo->islot);
1156+ NBD_ERROR ("(%d): invalid req %p. Not touching!\n", islot, req);
1157+ return;
1158+ }
1159+
1160+ /* PTB accounting and nothing more - first, specials */
1161+ if (! (req->flags & REQ_SPECIAL)) {
1162+ // PTB the special req counting semantics relies on
1163+ // countq not including itself in the count!
1164+ int countq;
1165+ int cmd;
3e18f7ab 1166+ struct nbd_acct *acct = &lo->acct;
1167+
d912b53b 1168+ cmd = rq_data_dir (req);
3e18f7ab 1169+ atomic_add (req_blks, &acct->requests_in[cmd]);
d912b53b 1170+
1171+ // PTB do we need locks here? Apparently not.
3e18f7ab 1172+ atomic_inc (&acct->countq[cmd]);
1173+ countq = atomic_read (&acct->countq[cmd]);
d912b53b 1174+
1175+ // PTB the maxes are just noncritical stats
3e18f7ab 1176+ if (atomic_read (&acct->maxq[cmd]) < countq)
1177+ atomic_set (&acct->maxq[cmd], countq);
1178+ atomic_inc (&acct->req_in[cmd][req_blks]);
d912b53b 1179+ // PTB the maxes are just noncritical stats
3e18f7ab 1180+ if (atomic_read (&acct->maxreqblks) < req_blks)
1181+ atomic_set (&acct->maxreqblks, req_blks);
d912b53b 1182+ }
1183+
1184+ write_lock (&lo->queue_lock);
1185+
1186+ list_add (&req->queuelist, &lo->queue);
1187+
1188+ write_unlock (&lo->queue_lock);
1189+
1190+ wake_up_interruptible (&lo->wq);
1191+
1192+}
1193+
1194+/*
1195+ * PTB - remove a request from anywhere in the nbd device general queue
1196+ * - return 0 for success, -ve for fail
1197+ *
1198+ * We need to hold the queue lock when calling this routine.
1199+ * It walks the queue.
1200+ *
1201+ * @lo the nbd device
1202+ * @req the request to be removed
1203+ */
1204+static int
1205+nbd_remove (struct nbd_device *lo, struct request *req)
1206+{
1207+ int cmd;
3e18f7ab 1208+ struct nbd_acct *acct = &lo->acct;
d912b53b 1209+
1210+ if (!req)
1211+ return -EINVAL;
1212+
1213+ list_del_init (&req->queuelist);
1214+
1215+ /* PTB accounting and nothing more */
1216+ cmd = rq_data_dir (req);
3e18f7ab 1217+ atomic_dec (&acct->countq[cmd]);
d912b53b 1218+ return 0;
1219+}
1220+
1221+/*
1222+ * PTB - Open the device. This is the blkops function.
1223+ */
1224+int
1225+nbd_open (struct inode *inode, struct file *file)
1226+{
1227+ int dev;
1228+ struct nbd_device *lo;
1229+ int nbd;
1230+ int part;
1231+ int islot;
1232+ char *devnam;
1233+
1234+ if (!inode && file) { /* added by ptb for 2.0.35. Necessary? */
1235+ inode = file->f_dentry->d_inode;
1236+ }
1237+ if (!inode) {
1238+ NBD_ERROR ("null inode.\n");
1239+ return -EINVAL;
1240+ }
1241+
1242+ dev = minor (inode->i_rdev);
1243+ nbd = dev >> NBD_SHIFT;
1244+ part = dev - (nbd << NBD_SHIFT);
1245+ islot = part - 1;
1246+
1247+ if (nbd >= MAX_NBD) {
1248+ NBD_ERROR ("too many (%d) whole devices open\n", nbd);
1249+ return -ENODEV;
1250+ }
1251+
1252+ lo = &nbd_dev[nbd];
1253+ devnam = lo->devnam;
1254+
1255+ /* PTB provision for opening for direct i/o - gives mount aid */
1256+ if (file
1257+ && (atomic_read(&lo->flags) & NBD_DIRECT)
1258+ && !(file->f_flags & O_DIRECT)) {
1259+ /* PTB we set NOFOLLOW to show we did it ! */
1260+ file->f_flags |= O_DIRECT | O_NOFOLLOW;
1261+ }
1262+
1263+ if (part == 0) {
1264+ /* PTB we have got the whole dev's file or inode for 1st time */
1265+ if (!lo->file || lo->file != file) {
1266+ lo->file = file;
1267+ atomic_set (&(&lo->wspeed)->frstj, jiffies);
1268+ atomic_set (&(&lo->rspeed)->frstj, jiffies);
1269+ atomic_set (&(&lo->tspeed)->frstj, jiffies);
1270+ }
1271+ if (!lo->inode || lo->inode != inode) {
1272+ lo->inode = inode;
1273+ }
1274+ if (!(atomic_read (&lo->flags) & NBD_INITIALISED)) {
1275+ atomic_set_mask (NBD_INITIALISED, &lo->flags);
1276+ }
1277+ }
1278+
1279+ atomic_inc (&lo->refcnt);
1280+
1281+ if (!(atomic_read (&lo->flags) & NBD_VALIDATED)
1282+ && lo->aslot > 0
1283+ && (atomic_read (&lo->flags) & NBD_ENABLED)) {
1284+ NBD_INFO ("partition check on device nd%s\n", lo->devnam);
1285+ check_disk_change(inode->i_bdev);
1286+
1287+ /*
1288+ * PTB do we set VALIDATED here, or let the kernel call
1289+ * sequence result in it happening via our removable
1290+ * device routines? Let's go for the latter option.
1291+ */
1292+ }
1293+
1294+ return 0;
1295+}
1296+
1297+/*
1298+ * PTB - complete a transaction irrefutably by taking it out of the
1299+ * - slot pending position it is in, and reporting end_request to kernel
1300+ *
1301+ * We are called without locks because our call to end request
1302+ * will take some sort of lock momentarily and we don't need
1303+ * locks because our request should already be off all queues.
1304+ *
1305+ * @slot the nbd_slot on which the req notionally was
1306+ * @req the poor defenceless kernel request about to be acked
1307+ */
1308+void
1309+nbd_commit (struct nbd_slot *slot, struct request *req)
1310+{
1311+
1312+ struct nbd_device *lo = slot->lo;
1313+ unsigned long req_blks = nr_blks (req);
1314+ int cmd;
3e18f7ab 1315+ struct nbd_acct * acct = &lo->acct;
d912b53b 1316+
1317+ if (req_blks < 0) {
1318+ NBD_ERROR ("corrupted req %p. Not touching with bargepole.\n",
1319+ req);
1320+ return;
1321+ }
1322+
1323+ list_del_init (&req->queuelist);
1324+
1325+ nbd_end_request_lock (req);
1326+ blk_put_request (req);
1327+
1328+ slot->req_age = 0;
1329+ slot->req -= req_blks;
1330+
1331+ /* PTB accounting and nothing more */
1332+ cmd = rq_data_dir (req);
1333+
3e18f7ab 1334+ atomic_sub (req_blks, &acct->requests_req[cmd]);
d912b53b 1335+ if (req->errors != 0) {
1336+ /* PTB error exit */
3e18f7ab 1337+ atomic_add (req_blks, &acct->requests_err);
d912b53b 1338+ slot->err += req_blks;
1339+ return;
1340+ }
1341+
3e18f7ab 1342+ atomic_add (req_blks, &acct->requests_out[cmd]);
d912b53b 1343+ slot->out += req_blks;
1344+
1345+ if (cmd != WRITE)
1346+ /* PTB everything but a write was easy */
1347+ return;
1348+
1349+ /*
1350+ * PTB now non error case writes
1351+ *
1352+ * account the 4 cases for a md5sum'd transaction
1353+ */
1354+
1355+ switch (slot->flags & (NBD_SLOT_MD5SUM | NBD_SLOT_MD5_OK)) {
1356+
1357+ case NBD_SLOT_MD5SUM | NBD_SLOT_MD5_OK:
1358+ atomic_add (req_blks, &lo->wrequests_5to); // 11
1359+ atomic_add (req_blks, &lo->wrequests_5so);
1360+ // PTB zero the countdown to turning off md5 as it works
1361+ atomic_set (&lo->wrequests_5co, 0);
1362+ break;
1363+
1364+ case NBD_SLOT_MD5SUM:
1365+ atomic_add (req_blks, &lo->wrequests_5to); // 10
1366+ atomic_add (req_blks, &lo->wrequests_5wo);
1367+ atomic_inc (&lo->wrequests_5co);
1368+ if (atomic_read (&lo->wrequests_5co) > md5_off_threshold) {
1369+ atomic_set (&lo->wrequests_5co, 0);
1370+ // PTB turn off md5summing as it is not successful
1371+ atomic_clear_mask (NBD_MD5SUM, &lo->flags);
1372+ }
1373+ break;
1374+
1375+ case NBD_SLOT_MD5_OK:
1376+ atomic_add (req_blks, &lo->wrequests_5to); // 01
1377+ atomic_add (req_blks, &lo->wrequests_5eo);
1378+ atomic_inc (&lo->wrequests_5co);
1379+ if (atomic_read (&lo->wrequests_5co) > md5_off_threshold) {
1380+ atomic_set (&lo->wrequests_5co, 0);
1381+ // PTB turn off md5summing as it is errored
1382+ atomic_clear_mask (NBD_MD5SUM, &lo->flags);
1383+ }
1384+ break;
1385+
1386+ default:
1387+ case 0:
1388+ // PTB nobody asked for a md5 and nobdy gave one back
1389+ atomic_inc (&lo->wrequests_5no);
1390+ if (atomic_read (&lo->wrequests_5no) > md5_on_threshold) {
1391+ atomic_set (&lo->wrequests_5no, 0);
1392+ // PTB turn on md5summing every so often
1393+ atomic_set_mask (NBD_MD5SUM, &lo->flags);
1394+ }
1395+ break;
1396+ }
1397+
1398+ // PTB clear the md5sum indicators from the slot afterwards!
1399+ slot->flags &= ~(NBD_SLOT_MD5SUM | NBD_SLOT_MD5_OK);
1400+
1401+ // PTB we ran out of difficult cases, so return
1402+}
1403+
1404+/*
1405+ * PTB - error out a transaction irrefutably by taking it out of the
1406+ * - slot pending position it is in, and reporting end_request to kernel
1407+ *
1408+ * We must be called without spinlocks held, as we take it in end req
1409+ *
1410+ * @slot the nbd_slot on which the req notionally was
1411+ * @req the poor defenceless kernel request about to be errored
1412+ */
1413+void
1414+nbd_error (struct nbd_slot *slot, struct request *req)
1415+{
1416+ struct nbd_device *lo = slot->lo;
1417+ unsigned long req_blks = nr_blks (req);
1418+ int cmd;
3e18f7ab 1419+ struct nbd_acct * acct = &lo->acct;
d912b53b 1420+
1421+ if (req_blks < 0) {
1422+ NBD_ERROR ("passed illegal request %p\n", req);
1423+ }
1424+
1425+ req->errors++;
1426+
1427+ /*
1428+ * PTB We don't need the queue spinlock since we don't touch our queue,
1429+ * and we're the only ones working on this slot.
1430+ */
1431+ list_del_init (&req->queuelist);
1432+
1433+ NBD_ALERT ("error out req %p from slot %d!\n", req, slot->i);
1434+
1435+ nbd_end_request_lock (req);
1436+ blk_put_request (req);
1437+
1438+ /* PTB accounting and nothing more */
1439+ cmd = rq_data_dir (req);
3e18f7ab 1440+ atomic_sub (req_blks, &acct->requests_req[cmd]);
d912b53b 1441+
1442+ slot->in -= req_blks;
1443+ slot->req -= req_blks;
1444+
1445+ slot->req_age = 0;
1446+ slot->err += req_blks;
3e18f7ab 1447+ atomic_add (req_blks, &acct->requests_err);
d912b53b 1448+}
1449+
1450+/*
1451+ * Take a request out of a slot. This must not hold the queuelock on
1452+ * entry as we take the queue lock in order to play with the devices
1453+ * queue.
1454+ *
1455+ * @slot the nbd slot on which to work
1456+ * @req the request
1457+ */
1458+static void
1459+nbd_rollback (struct nbd_slot *slot, struct request *req)
1460+{
1461+
1462+ struct nbd_device *lo = slot->lo;
1463+ unsigned long req_blks, flags;
1464+ int seqno;
1465+ struct list_head *pos;
1466+ struct request *xreq;
1467+
1468+ if (atomic_read (&lo->flags) & NBD_SHOW_ERRS) {
1469+ nbd_error (slot, req);
1470+ return;
1471+ }
1472+
1473+ req_blks = nr_blks (req);
1474+
1475+ if (req_blks < 0) {
1476+ NBD_ERROR ("passed illegal request %p\n", req);
1477+ return;
1478+ }
1479+
1480+ list_del_init (&req->queuelist);
1481+
1482+ NBD_ALERT ("rollback req %p from slot %d!\n", req, slot->i);
1483+
1484+ if (! (req->flags & REQ_SPECIAL)) {
1485+ /* PTB accounting */
1486+ slot->in -= req_blks;
1487+ slot->req -= req_blks;
1488+ }
1489+
1490+ seqno = rq_seqno(req);
1491+
1492+ write_lock_irqsave(&lo->queue_lock, flags);
1493+ list_for_each_prev (pos, &lo->queue) {
1494+ xreq = list_entry (pos, struct request, queuelist);
1495+ if (rq_seqno(xreq) > seqno) {
1496+ break;
1497+ }
1498+ }
1499+ list_add_tail (&req->queuelist, pos);
1500+ write_unlock_irqrestore(&lo->queue_lock, flags);
1501+
1502+}
1503+
1504+/*
1505+ * PTB - undo transactions by taking them out of the slot pending
1506+ * - position and replacing them on the generic device queue
1507+ * - NB we do not hold the io request lock or queue sem when
1508+ * - calling this as we take it internall in nbd_rollback
1509+ *
1510+ * @slot the nbd slot to scan
1511+ */
1512+static void
1513+nbd_rollback_all (struct nbd_slot *slot)
1514+{
1515+
1516+ struct request *req;
1517+ short count = 0;
1518+
1519+ while (!list_empty (&slot->queue)) {
1520+
1521+ if (count++ > 1000)
1522+ break;
1523+
1524+ req = list_head (&slot->queue, struct request, queuelist);
1525+
1526+ if (!req)
1527+ break;
1528+
1529+ nbd_rollback (slot, req);
1530+ }
1531+
1532+}
1533+
1534+/*
1535+ * PTB error out all the requests on a slot
1536+ *
1537+ * We must be called without the io spinlock held, as we take it in
1538+ * nbd_error().
1539+ *
1540+ * @slot the nbd slot to scan
1541+ */
1542+static void
1543+nbd_error_all (struct nbd_slot *slot)
1544+{
1545+
1546+ struct request *req;
1547+ short count = 0;
1548+
1549+ while (!list_empty (&slot->queue)) {
1550+ if (count++ > 1000)
1551+ break;
1552+ req = list_head (&slot->queue, struct request, queuelist);
1553+ if (!req)
1554+ break;
1555+ nbd_error (slot, req);
1556+ }
1557+}
1558+
1559+/*
1560+ * PTB - let a request onto the slot pending position
1561+ * - Can be called without the spinlock and doesn't take the
1562+ * spinlock as we only deal with our unique slot. If there
1563+ * were more than one client per slot this woould be a problem
1564+ * but there aren't so it isn't.
1565+ *
1566+ * @slot the nbd slot to let the request onto
1567+ * @req the request to move onto the slot queue
1568+ */
1569+void
1570+nbd_accept (struct nbd_slot *slot, struct request *req)
1571+{
1572+
1573+ struct nbd_device *lo = slot->lo;
1574+ unsigned long req_blks = nr_blks (req);
1575+ int cmd;
3e18f7ab 1576+ struct nbd_acct * acct = &lo->acct;
d912b53b 1577+
1578+ if (req_blks < 0)
1579+ return;
1580+
1581+ /* PTB accounting and nothing more */
1582+ cmd = rq_data_dir (req);
1583+
3e18f7ab 1584+ atomic_add (req_blks, &acct->requests_req[cmd]);
d912b53b 1585+ /* PTB - Note that this really is slot and not lo.
1586+ */
1587+ list_add (&req->queuelist, &slot->queue);
1588+
1589+ slot->req_age = jiffies;
1590+ slot->in += req_blks;
1591+ slot->req += req_blks;
1592+}
1593+
1594+/*
1595+ * PTB - read from userspace to a request buffer. Do it piecewuse
1596+ * - to cope with clustered requests.
1597+ * - return number of bytes read
1598+ *
1599+ * Unfortunately the only way we can return less than the right
1600+ * number of bytes is when the receiving req does not have the
1601+ * right number of buffers, because the copy_from_user itself
1602+ * doesn't tell us.
1603+ */
1604+static int
1605+copy_from_user_to_req (struct request *req, char *user, int len)
1606+{
1607+
1608+ unsigned size = 0;
1609+ struct bio *bio /* = req->bio */;
1610+
1611+ /* PTB assume user verified */
1612+
1613+ rq_for_each_bio(bio, req) {
1614+
1615+ int i;
1616+ struct bio_vec * bvl;
1617+
1618+ bio_for_each_segment(bvl, bio, i) {
1619+
1620+ struct page *page = bvl->bv_page;
1621+ int offset = bvl->bv_offset;
1622+ const unsigned current_size
1623+ = bvl->bv_len;
1624+ char *buffer;
1625+ buffer = page_address(page) + offset;
1626+
1627+ copy_from_user (buffer, user + size, current_size);
1628+
1629+ size += current_size;
1630+ }
1631+ }
1632+ if (size != len) {
1633+ NBD_ALERT ("requested %d and only read %d bytes to req %p\n",
1634+ len, size, req);
1635+ NBD_ALERT ("request %p wanted to read user space buffer %p\n",
1636+ req, user);
1637+ }
1638+ return size;
1639+}
1640+
1641+/*
1642+ * PTB - andres' kernel half of the user-space network handshake, used
1643+ * - to complete a transaction.
1644+ * - return 0 for success and -ve for fail.
1645+ *
1646+ * @slot the nbd slot being acted on
1647+ *
1648+ */
1649+int
1650+nbd_ack (struct nbd_slot *slot)
1651+{
1652+ struct nbd_reply reply;
1653+ struct request *req, *xreq;
1654+ int result = 0;
1655+
1656+ void *user;
1657+ unsigned long req_blks = 1;
1658+ struct nbd_device *lo = slot->lo;
3e18f7ab 1659+ struct nbd_acct * acct = &lo->acct;
d912b53b 1660+ unsigned buflen = 0;
1661+ unsigned reqlen;
1662+ int cmd;
1663+ struct list_head *pos;
1664+ int count = 0;
1665+
1666+ if (!(slot->flags & NBD_SLOT_BUFFERED)) {
1667+ return -EINVAL;
1668+ }
1669+
3e18f7ab 1670+ atomic_inc (&acct->cthreads);
d912b53b 1671+ slot->flags |= NBD_SLOT_RUNNING;
1672+ slot->cli_age = jiffies;
1673+
1674+ user = slot->buffer;
1675+ copy_from_user ((char *) &reply, (char *) user,
1676+ sizeof (struct nbd_reply));
1677+
1678+ // PTB we keep tracking the write position in the input buffer
1679+ buflen += NBD_BUFFER_DATA_OFFSET;
1680+
1681+ // PTB save the reply handle (which is an address) as our req
1682+ memcpy (&req, &reply.handle, sizeof (req));
1683+
1684+ xreq = NULL;
1685+ list_for_each (pos, &slot->queue) {
1686+ xreq = list_entry (pos, struct request, queuelist);
1687+ if (count++ > 1000)
1688+ break;
1689+ if (xreq == req)
1690+ /* PTB found it */
1691+ break;
1692+ }
1693+
1694+ if (xreq != req) {
1695+
1696+ if (slot->nerrs++ < 3)
1697+ NBD_ALERT ("fatal: Bad handle %p != %p!\n",
1698+ req, xreq);
1699+
3e18f7ab 1700+ atomic_dec (&acct->cthreads);
d912b53b 1701+ slot->flags &= ~NBD_SLOT_RUNNING;
1702+
1703+ NBD_ALERT("ignoring ack of req %p which slot does not have\n",
1704+ req);
1705+
1706+ /*
1707+ * PTB we lie and say success because userspace got through to
1708+ * us OK and the req they missed has been rolled back and will
1709+ * be retransmitted by the kernel later and elsewhere
1710+ */
1711+ return 0;
1712+ }
1713+
1714+ if (reply.magic != NBD_REPLY_MAGIC) {
1715+
1716+ if (slot->nerrs++ < 3)
1717+ NBD_ALERT ("Not enough reply magic in %s\n",
1718+ __FUNCTION__ );
1719+ /*
1720+ * PTB returning -EAGAIN causes the client to pause 0.5s
1721+ * and throw its reply away, then return to service. We leave
1722+ * any request we have to age and be rolled back.
1723+ */
1724+ return -EAGAIN;
1725+ }
1726+
1727+ if (reply.error > 0 || req->errors > 0) {
1728+ /* PTB wasn't error++'ed before */
1729+ req->errors++;
1730+ if (slot->nerrs++ < 3)
1731+ NBD_ALERT ("exited with reply error\n");
1732+ /* PTB we handle this - it's a repmote error */
1733+ NBD_FAIL ("remote error on request\n");
1734+ }
1735+
1736+ req_blks = nr_blks (req);
1737+
1738+ reqlen = req->nr_sectors;
1739+ reqlen <<= 9;
1740+
1741+ cmd = rq_type (req);
1742+
1743+ switch (cmd) {
1744+
1745+ unsigned long rcmd;
1746+ char * arg;
1747+ int size;
1748+
1749+ case READ:
1750+
1751+ // PTB We have to copy the buffer bit by bit in
1752+ // case the request is clustered.
1753+
1754+ size =
1755+ copy_from_user_to_req (req, ((char *) user) + buflen, reqlen);
1756+ if (size < reqlen) {
1757+ NBD_ALERT
1758+ ("(%d): copy %dB from user to req %p failed (%d)\n",
1759+ slot->i, reqlen, req, size);
1760+ // PTB we could try again? We should investigate.
1761+ NBD_FAIL
1762+ ("exited because of bad copy from user\n");
1763+ // PTB FIXME - think we want to discard and retry
1764+ }
1765+
1766+ // PTB we keep tracking the write position in the buffer
1767+ buflen += size;
1768+ break;
1769+
1770+ case WRITE:
1771+ /*
1772+ * PTB we want to know if the reply is md5summed, and if it is
1773+ * whether the md5sum is the same as the one on the
1774+ * request. But that's not something we can presently see
1775+ * from here as we don't make an md5sum in the kernel.
1776+ * So we have to rely on the reply flag from userspace.
1777+ * We transmit the information to the slot, as we can't
1778+ * keep it on the request.
1779+ */
1780+
1781+ switch (reply.flags &
1782+ (NBD_REPLY_MD5SUM | NBD_REPLY_MD5_OK)) {
1783+
1784+ case NBD_REPLY_MD5SUM | NBD_REPLY_MD5_OK:
1785+ /*
1786+ * PTB we asked for an md5sum comparison and
1787+ * the two matched, so we skipped writing the request
1788+ */
1789+ slot->flags |= (NBD_SLOT_MD5SUM | NBD_SLOT_MD5_OK); //11
1790+ break;
1791+ case NBD_REPLY_MD5SUM:
1792+ // PTB the two differed, so we wrote the request
1793+ slot->flags |= NBD_SLOT_MD5SUM;
1794+ slot->flags &= ~NBD_SLOT_MD5_OK; // 10
1795+ break;
1796+ case NBD_REPLY_MD5_OK:
1797+ // PTB the server refused the md5 request
1798+ slot->flags &= ~NBD_SLOT_MD5SUM;
1799+ slot->flags |= NBD_SLOT_MD5_OK; // 01
1800+ break;
1801+ default:
1802+ case 0:
1803+ // PTB mobody asked for an md5sum comparison
1804+ slot->flags &= ~(NBD_SLOT_MD5SUM | NBD_SLOT_MD5_OK);//00
1805+ break;
1806+ }
1807+ // PTB now we are all set up to do the accounting in commit etc.
1808+ break;
1809+
1810+ case SPECIAL:
1811+ // PTB FIXME. Just temporary.
1812+ NBD_ALERT ("special req %p on slot %d\n", req, slot->i);
1813+ req->errors = 0;
1814+ goto success;
1815+ break;
1816+
1817+
1818+ case IOCTL:
1819+
1820+ if (!(reply.flags & NBD_REPLY_IOCTL))
1821+ NBD_ALERT ("ioctl reply to req %p has no ioctl flag\n",
1822+ req);
1823+
1824+ // PTB the commit should emit the request notification
1825+
1826+ rcmd = (long) req->special;
1827+ arg = req->buffer;
1828+
1829+ if (cmd == -1l) {
1830+ result = -EINVAL;
1831+ NBD_FAIL ("unauthorized remote ioctl\n");
1832+ }
1833+
1834+ if (!(_IOC_DIR (cmd) & _IOC_READ)) {
1835+ break;
1836+ }
1837+
1838+ /*
1839+ * PTB We saved ioctl size in req .. but only approximately,
1840+ * as nr_sectors.
1841+ */
1842+
1843+ /*
1844+ * PTB if we are reading, it should be to the local
1845+ * buffer arg, which points at lo->ctldata or other buffer
1846+ */
1847+
1848+ // PTB we are treating a saved local address or direct val
1849+ if (req->nr_sectors > 0) {
1850+ /*
1851+ * PTB sectors is an overestimate. Should be
1852+ * OK as we are reading from the client
1853+ * buffer which has plenty of room to spare.
1854+ */
1855+ int size = req->nr_sectors << 9;
1856+ copy_from_user (arg, (char *) user + buflen, size);
1857+ buflen += size;
1858+ break;
1859+ }
1860+
1861+ break;
1862+ } // PTB eswitch
1863+ goto success;
1864+
1865+ success:
1866+ slot->nerrs = 0;
1867+ /*
1868+ * PTB - completion (or erroring) of transaction.
1869+ * note that nbd_commit will take a lock to do end_req
1870+ */
1871+ nbd_commit (slot, req);
3e18f7ab 1872+ atomic_dec (&acct->cthreads);
d912b53b 1873+ slot->flags &= ~NBD_SLOT_RUNNING;
1874+ return 0;
1875+
1876+ error_out:
1877+ /* PTB we will next do a client rollback on the slot from userspace.
1878+ * Right here we just skip the request.
1879+ * But .. don't error the request. We might have rolled it
1880+ * back and be referencing it.
1881+ */
1882+ if (result != -EAGAIN && result != 0) {
1883+ req->errors += req_blks;
1884+ slot->err += req_blks;
1885+ }
1886+ result = result < 0 ? result : -ENODEV;
1887+ // PTB one client thread leaves
3e18f7ab 1888+ atomic_dec (&acct->cthreads);
d912b53b 1889+ slot->flags &= ~NBD_SLOT_RUNNING;
1890+ return result;
1891+}
1892+
1893+/*
1894+ * PTB - write to userspace from a request buffer. Do it piecewuse
1895+ * - to cope with clustered requests.
1896+ * - return number of bytes written
1897+ */
1898+static int
1899+copy_to_user_from_req (struct request *req, char *user, int len)
1900+{
1901+
1902+ unsigned size = 0;
1903+ struct bio *bio /* = req->bio */;
1904+
1905+ /* PTB assume user verified */
1906+
1907+ rq_for_each_bio(bio, req) {
1908+
1909+ int i;
1910+ struct bio_vec * bvl;
1911+
1912+ bio_for_each_segment(bvl, bio, i) {
1913+
1914+ struct page *page = bvl->bv_page;
1915+ int offset = bvl->bv_offset;
1916+ const unsigned current_size
1917+ = bvl->bv_len;
1918+ char *buffer;
1919+ buffer = page_address(page) + offset;
1920+
1921+ copy_to_user (user + size, buffer, current_size);
1922+
1923+ size += current_size;
1924+ }
1925+
1926+ }
1927+ return size;
1928+}
1929+
1930+/*
1931+ * PTB do the devices three speed updates
1932+ *
1933+ * @lo the nbd device to do the update on
1934+ */
1935+static void
1936+nbd_set_speed (struct nbd_device *lo)
1937+{
1938+ int r, w, t;
1939+ struct nbd_speed *wspd = &lo->wspeed;
1940+ struct nbd_speed *rspd = &lo->rspeed;
1941+ struct nbd_speed *tspd = &lo->tspeed;
3e18f7ab 1942+ struct nbd_acct *acct = &lo->acct;
1943+ w = atomic_read (&acct->requests_in[WRITE]);
d912b53b 1944+ wspd->update (wspd, w);
3e18f7ab 1945+ r = atomic_read (&acct->requests_in[READ]);
d912b53b 1946+ rspd->update (rspd, r);
1947+ t = w + r;
1948+ tspd->update (tspd, t);
1949+}
1950+
1951+
1952+
1953+/*
1954+ * PTB - andres' kernel half of the userspace networking. This part
1955+ * - initiates the transaction by taking a request off the generic
1956+ * - device queue and placing it in the slots pending position.
1957+ * - I believe we return 0 for success and -ve for fail.
1958+ * - timeo is the number of jiffies we are prepared to wait
1959+ *
1960+ * @slot the nbd slot to act on.
1961+ */
1962+int
1963+nbd_get_req (struct nbd_slot *slot)
1964+{
1965+ struct nbd_request request;
1966+ struct request *req;
1967+ int result = 0;
1968+ static atomic_t count;
1969+ unsigned start_time = jiffies;
1970+ struct nbd_device *lo = slot->lo;
3e18f7ab 1971+ struct nbd_acct * acct = &lo->acct;
d912b53b 1972+ unsigned timeout = lo->req_timeo * HZ;
1973+ int islot = slot->i;
1974+ // PTB for the new timezone field in requests
1975+ extern struct timezone sys_tz;
1976+ struct timeval time;
1977+ unsigned long flags;
1978+ struct nbd_seqno * seqno_out = &lo->seqno_out;
1979+
3e18f7ab 1980+ atomic_inc (&acct->cthreads); // PTB - client thread enters
d912b53b 1981+ slot->flags |= NBD_SLOT_RUNNING;
1982+ slot->cli_age = jiffies;
1983+
1984+ if (!(slot->flags & NBD_SLOT_BUFFERED)) {
1985+ NBD_FAIL ("Our slot has no buffer");
1986+ }
1987+
1988+ atomic_set (&lo->islot, islot);
1989+
1990+ if (!list_empty (&slot->queue)) {
1991+ NBD_FAIL ("impossible! already treating one request");
1992+ // PTB we do a nontrivial rollback from the user daemon
1993+ }
1994+ if (!slot->file) {
1995+ result = -EBADF;
1996+ NBD_FAIL ("Our slot has been nofiled");
1997+ }
1998+ if (!(atomic_read (&lo->flags) & NBD_ENABLED)) {
1999+ result = -ENODEV;
2000+ NBD_FAIL ("Our slot has been vamooshed");
2001+ }
2002+
3e18f7ab 2003+ atomic_inc (&acct->cwaiters);
d912b53b 2004+ slot->flags |= NBD_SLOT_WAITING;
2005+
2006+ // PTB take spinlock in order to examine queue
2007+ // we need to protect ourselves against the request fn too
2008+ read_lock_irqsave (&lo->queue_lock, flags);
3e18f7ab 2009+ atomic_dec (&acct->cwaiters);
d912b53b 2010+ slot->flags &= ~NBD_SLOT_WAITING;
2011+
2012+ // PTB - now spin until request arrives to treat
2013+ while (slot->file && list_empty (&lo->queue)) {
2014+
2015+ static int nbd_clr_sock (struct nbd_slot *slot); // forward decl
2016+ int siz;
2017+ int time_left = start_time + timeout - jiffies;
2018+
2019+ read_unlock_irqrestore (&lo->queue_lock, flags);
2020+
2021+ // PTB one client thread goes to sleep
3e18f7ab 2022+ atomic_inc (&acct->cwaiters);
d912b53b 2023+ slot->flags |= NBD_SLOT_WAITING;
2024+
2025+ interruptible_sleep_on_timeout (&lo->wq, time_left);
2026+
2027+ slot->flags &= ~NBD_SLOT_WAITING;
2028+ // PTB one client thread reactivates
3e18f7ab 2029+ atomic_dec (&acct->cwaiters);
d912b53b 2030+ atomic_inc (&count);
2031+
2032+ // PTB Have to take the spinlock again to check at the queue
3e18f7ab 2033+ atomic_inc (&acct->cwaiters);
d912b53b 2034+ slot->flags |= NBD_SLOT_WAITING;
2035+ // we need to protect ourselves against the request fn too
2036+ read_lock_irqsave (&lo->queue_lock, flags);
3e18f7ab 2037+ atomic_dec (&acct->cwaiters);
d912b53b 2038+ slot->flags &= ~NBD_SLOT_WAITING;
2039+
2040+ // PTB fail for recheck if we are inactive too long
2041+
2042+ time_left = start_time + timeout - jiffies;
2043+ if (time_left > 0 || !list_empty (&lo->queue))
2044+ continue;
2045+
2046+ // PTB bad. timeout with nothing on queue. Error out.
2047+ result = -ETIME;
2048+
2049+ // PTB we will exit with fail, so up spinlock now
2050+ read_unlock_irqrestore (&lo->queue_lock, flags);
2051+
2052+ siz = lo->blksize + sizeof (struct nbd_request);
2053+ // PTB verify the buffer is still OK - holds one block
2054+ if (access_ok(VERIFY_WRITE,slot->buffer,siz))
2055+ goto error_out;
2056+
2057+ // PTB buffer is invalid
2058+ result = -EINVAL;
2059+
2060+ // PTB clr_sock takes both the io lock and the spinlock
2061+ nbd_clr_sock (slot);
2062+ NBD_FAIL ("Our process has died or lost its buffer");
2063+
2064+ /*
2065+ * PTB we may do a rollback from the user daemon here
2066+ * but it'll be trivial - without effect - as we don't
2067+ * have a request in our slot to treat.
2068+ */
2069+ goto error_out;
2070+
2071+ } // end while loop
2072+
2073+ // PTB we still have the (read) spinlock here
2074+
2075+ if (!(atomic_read (&lo->flags) & NBD_ENABLED)) {
2076+ read_unlock_irqrestore (&lo->queue_lock, flags);
2077+ result = -ENODEV;
2078+ NBD_FAIL ("Our slot vaporized while we slept!");
2079+ }
2080+ if (!slot->file) {
2081+ read_unlock_irqrestore (&lo->queue_lock, flags);
2082+ result = -EBADF;
2083+ NBD_FAIL ("Our slot nofiled itself while we slept!");
2084+ }
2085+ if (!list_empty (&slot->queue)) {
2086+ read_unlock_irqrestore (&lo->queue_lock, flags);
2087+ result = -EINVAL;
2088+ NBD_FAIL ("impossible! already treating one request");
2089+ // PTB we do a nontrivial rollback from the user daemon
2090+ }
2091+
2092+ // PTB now relinquish the read lock and try for the write lock
2093+ read_unlock_irqrestore (&lo->queue_lock, flags);
2094+
2095+ write_lock_irqsave (&lo->queue_lock, flags);
2096+ // PTB got the write lock
2097+
2098+ if (list_empty (&lo->queue)) {
2099+ write_unlock_irqrestore (&lo->queue_lock, flags);
2100+ // PTB - somebody else did it while we waited on spinlock. OK
2101+ result = -EINVAL;
2102+ NBD_FAIL ("ho hum beaten to the punch");
2103+ // PTB we may do a trivial rollback from the user daemon
2104+ }
2105+
2106+ // PTB cli/sti here looks unnec. hardware interrupts return here
2107+ // AMARIN begin uninterruptible code
2108+
2109+ // PTB we have the (write) spinlock
2110+
2111+ // PTB oldest=last element in queue
2112+ req = list_tail (&lo->queue, struct request, queuelist);
2113+
2114+ // PTB this is where we free the req from our queue. We need to be
2115+ // holding our spinlock at this point
2116+
2117+ // PTB - must succeed as have the spinlock
2118+ result = nbd_remove (lo, req);
2119+ // PTB now holding irqs off in nbd_remove
2120+
2121+ // AMARIN end uninterruptable code
2122+ // PTB uh - maybe cli/sti is needed? interrupts can muck the queue?
2123+ // - Nah! I have left them enabled so we can see any errors.
2124+
2125+ write_unlock_irqrestore (&lo->queue_lock, flags);
2126+
2127+ request.magic = NBD_REQUEST_MAGIC;
2128+ request.flags = 0;
2129+
2130+ switch (rq_type (req)) {
2131+
2132+ unsigned long cmd;
2133+ char *arg;
2134+ size_t size;
2135+
2136+ case IOCTL:
2137+
2138+ request.type = IOCTL;
2139+
2140+ // PTB this is our special ioctl kernel request
2141+
2142+ cmd = (unsigned long) req->special;
2143+ arg = req->buffer;
2144+ size = req->nr_sectors << 9;
2145+
2146+ // PTB the arg was a literal
2147+
2148+ request.len = 0;
2149+ // PTB we are in get_req, transferring stored ioctl
2150+ if ((_IOC_DIR (cmd) & _IOC_READ) && size > 0) {
2151+ // PTB if len is +ve we copy to the user buffer later
2152+ request.len = size;
2153+ }
2154+ // PTB we store the weirded ioctl id.
2155+ // PTB Yes, this composition is our private invention.
2156+ request.from = (((__u64) cmd) << 32)
2157+ // PTB really want this to go to a 64 bit request.special
2158+ | ((__u64) (unsigned long) arg);
2159+ break;
2160+
2161+ case READ:
2162+ case WRITE:
2163+
2164+ request.type = rq_data_dir (req);
2165+ request.from = req->sector;
2166+ request.from <<= 9;
2167+ request.len = req->nr_sectors;
2168+ request.len <<= 9;
2169+ if (atomic_read (&lo->flags) & NBD_MD5SUM) {
2170+ // PTB set the please do md5sum flag on the request
2171+ request.flags |= NBD_REQUEST_MD5SUM;
2172+ }
2173+ break;
2174+
2175+ case MD5SUM:
2176+ break;
2177+
2178+ case SPECIAL:
2179+ request.type = SPECIAL;
2180+ request.len = req->nr_sectors;
2181+ request.len <<= 9;
2182+ request.from = req->sector;
2183+ request.from <<= 9;
2184+ if (rq_data_dir (req) == WRITE)
2185+ request.flags |= NBD_REQUEST_SPECIALRW;
2186+ request.special = (typeof(request.special))req->special;
2187+ break;
2188+
2189+ default:
2190+ NBD_ALERT ("received unknown req %p type %#x\n",
2191+ req, rq_type (req));
2192+ break;
2193+ }
2194+
2195+ request.seqno = seqno_out->calc(seqno_out, rq_seqno (req));
2196+
2197+ /*
2198+ * PTB we should here erase the extra seqno info in the request
2199+ * so that on error or on ack the kernel can use the right internal
2200+ * array, but I'll erase it in the ack function instead
2201+ */
2202+
2203+ do_gettimeofday (&time);
2204+ request.time = time.tv_sec;
2205+ request.time *= 1000000;
2206+ request.time += time.tv_usec;
2207+ request.zone = sys_tz.tz_minuteswest;
2208+
2209+ // PTB tz_dsttime = 0 always in linux
2210+
2211+ memcpy (&request.handle, &req, sizeof (request.handle));
2212+
2213+ copy_to_user (slot->buffer, (char *) &request, sizeof (request));
2214+
2215+ switch (request.type) {
2216+
2217+ int err;
2218+ char * arg;
2219+
2220+ case READ:
2221+ break;
2222+
2223+ case IOCTL:
2224+ if (request.len <= 0)
2225+ break; // PTB presumably nothing to do
2226+ arg = (char *) slot->buffer + NBD_BUFFER_DATA_OFFSET;
2227+ copy_to_user (arg, req->buffer, request.len);
2228+ break;
2229+
2230+ case WRITE:
2231+ arg = (char *) slot->buffer + NBD_BUFFER_DATA_OFFSET;
2232+ err = copy_to_user_from_req (req, arg, request.len);
2233+ if (err >= request.len)
2234+ break; // OK
2235+ // PTB buffer had missing BHSs
2236+ NBD_ERROR ("req %p offered %d bytes of %d for copy to user\n",
2237+ req, result, request.len);
2238+ // PTB this request is badly damaged. We had better shoot it.
2239+ if (req && req->errors == 0) {
2240+ req->errors++;
2241+ nbd_end_request_lock (req);
2242+ blk_put_request (req);
2243+ }
2244+ NBD_FAIL ("kernel failed to keep req while we copied from it");
2245+ break;
2246+ case MD5SUM:
2247+ break;
2248+ case SPECIAL:
2249+ // PTB temporary. We do not treat specials at the moment.
2250+ req->errors = 0;
2251+ break;
2252+ default:
2253+ NBD_ERROR ("req %p was type %#x\n", req, rq_type(req));
2254+ NBD_FAIL ("unknown req type");
2255+ break;
2256+ }
2257+
2258+ /*
2259+ * PTB nbd_accept does not take spinlock and does not need to as
2260+ * the req is already free of the shared queue and only needs
2261+ * to be placed on the unique slot queue.
2262+ */
2263+
2264+ nbd_accept (slot, req);
2265+
3e18f7ab 2266+ atomic_dec (&acct->cthreads); // PTB - client thread leaves normally
d912b53b 2267+ slot->flags &= ~NBD_SLOT_RUNNING;
2268+
2269+ return 0;
2270+
2271+ error_out:
2272+ // PTB accounting - a fail to get a request is not an errored request
3e18f7ab 2273+ atomic_dec (&acct->cthreads); // PTB - client thread leaves abnormally
d912b53b 2274+ slot->flags &= ~NBD_SLOT_RUNNING;
2275+ result = result < 0 ? result : -ENODEV;
2276+
2277+ return result;
2278+}
2279+
2280+/*
2281+ * PTB error out the pending requests on the kernel queue
2282+ * We have to be called WITHOUT the io request lock held.
2283+ * We sleep imbetween clearing each request, for "safety".
2284+ *
2285+ * @lo the nbd device to scan
2286+ */
2287+static int
2288+nbd_clr_kernel_queue (struct nbd_device *lo)
2289+{
2290+
2291+ int count = 0;
2292+ unsigned long flags;
2293+ request_queue_t *q = lo->q;
2294+
2295+ spin_lock_irqsave (q->queue_lock, flags);
2296+
2297+ while (! blk_queue_empty(q) && count++ < 1000) {
2298+ struct request *req;
2299+ req = elv_next_request(q);
2300+ if (!req) { // PTB impossible
2301+ spin_unlock_irqrestore (q->queue_lock, flags);
2302+ NBD_ALERT
2303+ ("impossible! kernel queue empty after tested nonemty!\n");
2304+ goto fail;
2305+ }
2306+ blkdev_dequeue_request (req);
2307+ spin_unlock_irqrestore (q->queue_lock, flags);
2308+ if (!req->errors)
2309+ req->errors++;
2310+ schedule ();
2311+ nbd_end_request_lock (req);
2312+ blk_put_request (req);
2313+ spin_lock_irqsave (q->queue_lock, flags);
2314+ }
2315+ spin_unlock_irqrestore (q->queue_lock, flags);
2316+ goto success;
2317+
2318+ fail:
2319+ /* PTB fall thru */
2320+ success:
2321+ NBD_ALERT ("removed %d requests\n", count);
2322+ return count;
2323+
2324+}
2325+
2326+/*
2327+ * PTB error out the pending requests on the nbd queue and kernel queue
2328+ * Note that we take the queue spinlock for this
2329+ *
2330+ * @lo the nbd device to scan
2331+ */
2332+static int
2333+nbd_clr_queue (struct nbd_device *lo)
2334+{
2335+ int count = 0;
3e18f7ab 2336+ struct nbd_acct * acct = &lo->acct;
d912b53b 2337+
2338+ while (count < 1000) {
2339+
2340+ struct request *req;
2341+ unsigned long req_blks = 1;
2342+
2343+ // PTB cannot allow new requests via interrupts
2344+ write_lock (&lo->queue_lock);
2345+ if (list_empty (&lo->queue)) {
2346+ write_unlock(&lo->queue_lock);
2347+ break;
2348+ }
2349+ req = list_head (&lo->queue, struct request, queuelist);
2350+ if (!req) {
2351+ write_unlock(&lo->queue_lock);
2352+ break;
2353+ }
2354+
2355+ req_blks = nr_blks (req);
2356+
2357+ req->errors += req_blks + 1;
3e18f7ab 2358+ atomic_add (req_blks, &acct->requests_err);
d912b53b 2359+
2360+ /* PTB - must succeed as have the spinlock */
2361+ nbd_remove (lo, req);
2362+ /* PTB now hold irqs off in nbd_remove */
2363+ write_unlock(&lo->queue_lock);
2364+ count++;
2365+
2366+ nbd_end_request_lock (req);
2367+ blk_put_request (req);
2368+
2369+ }
2370+ NBD_ALERT ("unqueued %d reqs\n", count);
2371+ return count;
2372+}
2373+
2374+/*
2375+ * PTB do under alt spinlock - we take the lo queue_lock oursekves.
2376+ * We take all requests off the alt queue to which they've been
2377+ * diverted and put them on the devices normal queue, where they will
2378+ * then be treated in the normal course of events. They were diverted
2379+ * to the alt queue after we received a SPECIAL, and they're being
2380+ * released now that we've treated all the extant reqs.
2381+ *
2382+ * @lo the nbd device being treated
2383+ */
2384+static int
2385+nbd_requeue (struct nbd_device *lo)
2386+{
2387+ int count = 0;
2388+
2389+ while (count < 1000) {
2390+
2391+ struct request *req;
2392+
2393+ // PTB cannot allow new requests via interrupts
2394+ if (list_empty (&lo->altqueue)) {
2395+ break;
2396+ }
2397+ req = list_tail (&lo->altqueue, struct request, queuelist);
2398+ if (!req)
2399+ break;
2400+
2401+ // PTB heisenbug? without these list_del oopses on null deref
2402+ if (req->queuelist.prev == NULL) {
2403+ NBD_ALERT ("req %p has 0 prev ptr! Abort\n", req);
2404+ break;
2405+ }
2406+ if (req->queuelist.next == NULL) {
2407+ NBD_ALERT ("req %p has 0 next ptr! Abort\n", req);
2408+ break;
2409+ }
2410+ /* PTB - must succeed as have the spinlock */
2411+ list_del_init (&req->queuelist);
2412+ /* PTB now hold irqs off in nbd_remove */
2413+ count++;
2414+
2415+ nbd_enqueue (lo, req);
2416+
2417+ }
2418+ return count;
2419+}
2420+
2421+
2422+#undef NBD_FAIL
2423+#define NBD_FAIL( s... ) { \
2424+ NBD_ERROR( s); printk("\n"); \
2425+ goto error_out; \
2426+}
2427+
2428+#ifndef NO_BUFFERED_WRITES
2429+ /*
2430+ * Magic function from rd.c that we hope saves a buffer head
2431+ * permanently somewhere in the kernel VM system.
2432+ */
2433+static int
2434+buffered_write_pagecache_IO (struct buffer_head *sbh, int nbd)
2435+{
2436+ struct address_space *mapping;
2437+ unsigned long index;
2438+ int offset, size, err;
2439+ struct nbd_device *lo = &nbd_dev[nbd];
2440+ err = 0;
2441+
2442+ // PTB we need to save the /dev/nda inode
2443+ if (!lo->inode) {
2444+ err = -ENODEV;
2445+ goto out;
2446+ }
2447+ mapping = lo->inode->i_mapping;
2448+
2449+ // PTB index appears to be the page number
2450+ index = sbh->b_rsector >> (PAGE_CACHE_SHIFT - 9);
2451+ // PTB offset is in bytes, and says where in the page the sector starts
2452+ offset = (sbh->b_rsector << 9) & ~PAGE_CACHE_MASK;
2453+ // PTB well, an abbreviation for the buffer size, in bytes
2454+ size = sbh->b_size;
2455+
2456+ do {
2457+ // PTB we mark each page that we should write to Uptodate
2458+
2459+ int count;
2460+ struct page **hash;
2461+ struct page *page;
2462+ char *src, *dst;
2463+
2464+ int unlock = 0;
2465+
2466+ // PTB ummm, how much of the page is left to traverse
2467+ count = PAGE_CACHE_SIZE - offset;
2468+ // PTB reduce it to how much we actually need to traverse
2469+ if (count > size)
2470+ count = size;
2471+ // PTB say NOW? that we have traversed what we want of the page
2472+ size -= count;
2473+
2474+ hash = page_hash (mapping, index);
2475+ page = __find_get_page (mapping, index, hash);
2476+
2477+ if (!page) {
2478+ // PTB we get to make a new page
2479+ page = grab_cache_page (mapping, index);
2480+ if (!page) {
2481+ // PTB failed to get new page
2482+ err = -ENOMEM;
2483+ goto out;
2484+ }
2485+ // PTB magic
2486+ if (!Page_Uptodate (page)) {
2487+ memset (kmap (page), 0, PAGE_CACHE_SIZE);
2488+ kunmap (page);
2489+ SetPageUptodate (page);
2490+ }
2491+ // PTB the new page is locked. We need to unlock it later
2492+ unlock = 1;
2493+ }
2494+
2495+ // PTB prepare already for next page
2496+ index++;
2497+
2498+ // PTB set up for copy
2499+ dst = kmap (page);
2500+ dst += offset;
2501+ src = bh_kmap (sbh);
2502+
2503+ // PTB prepare for next round
2504+ offset = 0;
2505+
2506+ // PTB do a copy
2507+ memcpy (dst, src, count);
2508+
2509+ kunmap (page);
2510+ bh_kunmap (sbh);
2511+
2512+ if (unlock) {
2513+ UnlockPage (page);
2514+ }
2515+ SetPageDirty (page);
2516+ __free_page (page);
2517+
2518+ } while (size > 0);
2519+
2520+ out:
2521+ return err;
2522+
2523+}
2524+static int
2525+buffered_write (struct request *req)
2526+{
2527+
2528+ struct buffer_head *bh;
2529+ int dev = minor (req->rq_dev);
2530+ int nbd = dev >> NBD_SHIFT;
2531+ int err = 0;
2532+
2533+ // PTB go through and copy and protect the written buffers
2534+ for (bh = req->bh; bh; bh = bh->b_reqnext) {
2535+ struct buffer_head *rbh;
2536+ rbh =
2537+ getblk (bh->b_rdev, bh->b_rsector / (bh->b_size >> 9),
2538+ bh->b_size);
2539+ if (bh != rbh) {
2540+ char *bdata = bh_kmap (bh);
2541+ memcpy (rbh->b_data, bdata, rbh->b_size);
2542+ NBD_ALERT ("got new bh sector %lu on write\n",
2543+ bh->b_rsector);
2544+ }
2545+ bh_kunmap (bh);
2546+ mark_buffer_protected (rbh); // PTB equals dirty, uptodate
2547+ err = buffered_write_pagecache_IO (bh, nbd);
2548+ if (err < 0) {
2549+ break;
2550+ }
2551+ brelse (rbh);
2552+ }
2553+ return err;
2554+}
2555+
2556+#endif /* NO_BUFFERED_WRITES */
2557+
2558+/*
2559+ * PTB check if the device is read only according to int flags
2560+ *
2561+ * @lo the nbd device to be checked
2562+ */
2563+static int
2564+nbd_read_only(struct nbd_device *lo) {
2565+ return (atomic_read(&lo->flags) & NBD_READ_ONLY) != 0;
2566+}
2567+/*
2568+ * PTB set the device readonly (or not)
2569+ *
2570+ * @lo the nbd device to be set up
2571+ * @ro 1 for read only, 0 for read write.
2572+ */
2573+static void
2574+nbd_set_read_only(struct nbd_device * lo, int ro) {
2575+
2576+ if (ro != 0) {
2577+ atomic_set_mask (NBD_READ_ONLY, &lo->flags);
2578+ } else {
2579+ atomic_clear_mask (NBD_READ_ONLY, &lo->flags);
2580+ }
2581+
2582+ // PTB which device really does not matter. We do the checking.
2583+ set_disk_ro (lo->disk, ro != 0);
2584+}
2585+
2586+/*
2587+ * PTB - kernel function to take reqs off the kernel queue. Runs with
2588+ * io lock held. This is the "request function".
2589+ */
2590+static void
2591+do_nbd_request (request_queue_t * q)
2592+{
2593+ struct request *req;
2594+ unsigned long flags;
2595+
2596+ while (! blk_queue_empty(q)) {
2597+
2598+ struct nbd_device *lo;
3e18f7ab 2599+ struct nbd_acct * acct;
d912b53b 2600+
2601+ req = elv_next_request(q);
2602+
2603+ lo = req->rq_disk->private_data;
3e18f7ab 2604+ acct = &lo->acct;
d912b53b 2605+
2606+ /* PTB - one kernel thread enters */
3e18f7ab 2607+ atomic_inc (&acct->kthreads);
2608+ if (atomic_read (&acct->kthreads) > atomic_read (&acct->kmax))
2609+ atomic_set (&acct->kmax, atomic_read (&acct->kthreads));
d912b53b 2610+
2611+ if (!lo->inode || !lo->file) {
2612+ NBD_FAIL ("Request when device not ready.");
2613+ }
2614+
2615+ if (rq_data_dir (req) == WRITE && nbd_read_only(lo)) {
2616+ NBD_FAIL ("write on read-only device");
2617+ }
2618+ flags = atomic_read (&lo->flags);
2619+ if (!(flags & NBD_INITIALISED)) {
2620+ NBD_FAIL ("device not initialised.");
2621+ }
2622+ if (!(flags & NBD_ENABLED)) {
2623+ NBD_FAIL ("device not enabled.");
2624+ }
2625+ if (flags & NBD_REMOTE_INVALID) {
2626+ NBD_FAIL ("remote device invalidated.");
2627+ }
2628+ if (req->sector + req->nr_sectors > lo->sectors) {
2629+ NBD_FAIL ("overrange request");
2630+ }
2631+ if (req->sector < 0) {
2632+ NBD_FAIL ("underrange request");
2633+ }
2634+ if (req->rq_disk->major != major) {
2635+ NBD_FAIL ("request for wrong major");
2636+ }
2637+ req->errors = 0;
2638+ blkdev_dequeue_request (req);
2639+
2640+ // PTB in 2.5 we can release the iolock briefly here
2641+ spin_unlock_irq(q->queue_lock);
2642+
2643+ if (req->flags & REQ_SPECIAL) {
2644+ // PTB temporary successful end here for SPECIALS
2645+
2646+ // PTB we want to attach it to the device and ack later
2647+ nbd_enqueue (lo, req);
2648+ // PTB block further reqs until these have drained
2649+ write_lock(&lo->altqueue_lock);
2650+ // PTB do not touch this flag without this lock
3e18f7ab 2651+ if (atomic_read(&acct->countq[READ])
2652+ + atomic_read(&acct->countq[WRITE]) > 0) {
d912b53b 2653+ atomic_set_mask(NBD_QBLOCKED, &lo->flags);
2654+ }
2655+ write_unlock(&lo->altqueue_lock);
2656+ goto accounting;
2657+ }
2658+
2659+ // PTB we are the only reader and writer of lo->seqno
2660+ if (rq_data_dir (req) == WRITE && rq_seqno (req) == 0) {
2661+ // PTB it is a new request never seen before
2662+ struct nbd_seqno * seqno_out = &lo->seqno_out;
2663+ seqno_out->inc(seqno_out);
2664+ /*
2665+ * PTB we have to be careful to change this back before
2666+ * giving it back to the kernel, as the kernel uses it.
2667+ * We patch it back again in nbd_end_request.
2668+ */
2669+ rq_set_seqno (req, seqno_out->get(seqno_out));
2670+ }
2671+
2672+ // if BLOCK is set divert requests to alt queue
2673+ write_lock(&lo->altqueue_lock);
2674+ if (atomic_read(&lo->flags) & NBD_QBLOCKED) {
2675+ list_add (&req->queuelist, &lo->altqueue);
2676+ write_unlock(&lo->altqueue_lock);
2677+ goto accounting;
2678+ }
2679+ write_unlock(&lo->altqueue_lock);
2680+
2681+ // PTB normal sequence is to queue request locally
2682+ nbd_enqueue (lo, req);
2683+ goto accounting;
2684+
2685+ accounting:
3e18f7ab 2686+ atomic_dec (&acct->kthreads);
d912b53b 2687+ // PTB regain the iolock for another turn
2688+ spin_lock_irq(q->queue_lock);
2689+ continue; // PTB next request
2690+
2691+ error_out:
2692+ // PTB can rely on req being nonnull here
2693+ NBD_ALERT ("ending req %p with prejudice\n", req);
2694+ req->errors++;
2695+ blkdev_dequeue_request (req);
2696+ spin_unlock_irq(q->queue_lock);
2697+
2698+ nbd_end_request_lock (req);
2699+ blk_put_request (req);
2700+
2701+ // PTB more accounting
2702+ if (lo) {
2703+ int req_blks = nr_blks (req);
3e18f7ab 2704+ struct nbd_acct * acct = &lo->acct;
2705+ atomic_add (req_blks, &acct->requests_err);
2706+ atomic_dec (&acct->kthreads);
d912b53b 2707+ } else {
2708+ NBD_ALERT("failed to account one orphan errored req\n");
2709+ }
2710+ // PTB regain the queue lock for another turn
2711+ spin_lock_irq(q->queue_lock);
2712+ continue;
2713+ }
2714+ return;
2715+}
2716+
2717+/*
2718+ * PTB pair of helpful additional functions, only good for 1 bit in the
2719+ * mask, however. Modify if you want more.
2720+ *
2721+ * @a the atomic element's address
2722+ * @mask the integer with one bit set in the position that we want to test
2723+ * and set, or clear
2724+ */
2725+static int
2726+atomic_test_and_set_mask (atomic_t * a, unsigned mask)
2727+{
2728+ int i = ffs (mask);
2729+ if (!i)
2730+ return -EINVAL;
2731+ // PTB gahhhh ...
2732+ #ifdef __LITTLE_ENDIAN
2733+ return test_and_set_bit (i - 1, (unsigned long *)&a->counter);
2734+ #else
2735+ #ifndef __BIGENDIAN
2736+ #error help, I only know about bigendian or littlendian machines
2737+ #endif
2738+ return test_and_set_bit
2739+ (i - 1 + (sizeof(long)-sizeof(a->counter))*8,
2740+ (unsigned long *)&a->counter);
2741+ #endif
2742+}
2743+static int
2744+atomic_test_and_clear_mask (atomic_t * a, unsigned mask)
2745+{
2746+ int i = ffs (mask);
2747+ if (!i)
2748+ return 0;
2749+ // PTB gahhhh ...
2750+ #ifdef __LITTLE_ENDIAN
2751+ return test_and_clear_bit (i - 1, (unsigned long *)&a->counter);
2752+ #else
2753+ #ifndef __BIGENDIAN
2754+ #error help, I only know about bigendian or littlendian machines
2755+ #endif
2756+ return test_and_clear_bit
2757+ (i - 1 + (sizeof(long)-sizeof(a->counter))*8,
2758+ (unsigned long *)&a->counter);
2759+ #endif
2760+}
2761+
2762+
2763+/*
2764+ * PTB - set the enabled flag on a device (call without the spinlock held)
2765+ *
2766+ * @lo the nbd device being treated
2767+ */
2768+static void
2769+nbd_enable (struct nbd_device *lo) {
2770+ unsigned long flags;
2771+ int did_enabled = 0;
2772+ struct nbd_md *md = &nbd_md;
2773+
2774+ // PTB reenable part
2775+ write_lock_irqsave (&lo->meta_lock, flags);
2776+ if (!atomic_test_and_set_mask (&lo->flags, NBD_ENABLED)) {
2777+ // PTB was not enabled before
2778+ atomic_clear_mask (NBD_VALIDATED, &lo->flags);
2779+ lo->lives++;
2780+ did_enabled = 1;
2781+ }
2782+ write_unlock_irqrestore (&lo->meta_lock, flags);
2783+
2784+ if (did_enabled)
2785+ md->notify(&nbd_md, mk_kdev (major, lo->nbd << NBD_SHIFT));
2786+}
2787+
2788+
2789+/*
2790+ * PTB rollback all requests on a given slot and then invalidate it
2791+ * (so the requests can't go back until somebody reactivates the slot)
2792+ * At least rollback (which we call takes both the io spinlock and our
2793+ * spinlock, so we can hold neither when we are called. Soft_reset
2794+ * (which we call) also calls rollback, so has the same problem.
2795+ *
2796+ * @slot the nbd slot being treated
2797+ */
2798+static int
2799+nbd_clr_sock (struct nbd_slot *slot)
2800+{
2801+ int i = 0;
2802+ struct nbd_device *lo = slot->lo;
2803+ int islot = slot->i;
2804+ unsigned long flags;
2805+ int do_reset = 0;
2806+ int do_enable = 0;
2807+ static int nbd_soft_reset (struct nbd_device*);
2808+
2809+ nbd_rollback_all (slot);
2810+
2811+ slot->file = NULL;
2812+ slot->bufsiz = 0;
2813+ slot->flags = 0;
2814+ slot->buffer = NULL;
2815+
2816+ write_lock_irqsave (&lo->meta_lock, flags);
2817+
2818+ /* PTB reset lo->aslot */
2819+
2820+ if (lo->aslot > 0) {
2821+
2822+ /* PTB grr .. do this the hard way */
2823+ int aslot = 0;
2824+ for (i = 0; i < lo->nslot; i++) {
2825+ struct nbd_slot *sloti = &lo->slots[i];
2826+ if (sloti->file)
2827+ aslot++;
2828+ }
2829+ lo->aslot = aslot;
2830+
2831+ if (lo->aslot <= 0) {
2832+ // PTB we were the last client alive, diasable device
2833+ if (atomic_read (&lo->flags) & NBD_SHOW_ERRS) {
2834+ // PTB soft_reset will invalidate_buffers
2835+ atomic_clear_mask (NBD_ENABLED, &lo->flags);
2836+ do_reset = 1;
2837+ }
2838+ } else if (!(atomic_read (&lo->flags) & NBD_ENABLED)) {
2839+ // PTB must not call reenable as that clears the queue
2840+ do_enable = 1;
2841+ }
2842+
2843+ }
2844+
2845+ // PTB lift the lock temporarily
2846+ write_unlock_irqrestore(&lo->meta_lock, flags);
2847+ if (do_reset) {
2848+ nbd_soft_reset (lo);
2849+ }
2850+ if (do_enable) {
2851+ nbd_enable (lo);
2852+ NBD_ALERT ("enabled device nd%s\n", lo->devnam);
2853+ }
2854+ write_lock_irqsave(&lo->meta_lock, flags);
2855+
2856+ /* PTB reset lo->islot, for no good reason */
2857+
2858+ if (atomic_read (&lo->islot) == islot) {
2859+ for (i = 0; i++ < lo->nslot;) {
2860+ atomic_inc (&lo->islot);
2861+ if (atomic_read (&lo->islot) >= lo->nslot)
2862+ atomic_set (&lo->islot, 0);
2863+ if (lo->slots[atomic_read (&lo->islot)].file)
2864+ break;
2865+ }
2866+ }
2867+ lo->harderror = 0;
2868+ write_unlock_irqrestore (&lo->meta_lock, flags);
2869+
2870+ /* PTB don't clear whole device queue as we might still be open */
2871+
2872+ return 0;
2873+}
2874+
2875+/*
2876+ * PTB - check all slots for old requests and roll them back.
2877+ * At least rollback (which we call takes both the io spinlock and our
2878+ * spinlock, so we can hold neither when we are called.
2879+ *
2880+ * @lo the nbd device to scan
2881+ */
2882+static void
2883+nbd_rollback_old (struct nbd_device *lo)
2884+{
2885+
2886+ int islot;
2887+
2888+ for (islot = 0; islot < lo->nslot; islot++) {
2889+ struct nbd_slot *slot = &lo->slots[islot];
2890+ if (slot->req_age > 0
2891+ && slot->req_age < jiffies - lo->req_timeo * HZ) {
2892+ nbd_rollback_all (slot);
2893+ }
2894+ }
2895+
2896+}
2897+
2898+/*
2899+ * PTB - register a socket to a slot.
2900+ * - Return 0 for success and -ve for failure.
2901+ * Nowadays this doesn't do very much! Just finalizes things.
2902+ *
2903+ * @slot the nbd slot being registered
2904+ */
2905+static int
2906+nbd_set_sock (struct nbd_slot *slot, int arg)
2907+{
2908+
2909+ struct nbd_device *lo = slot->lo;
2910+ int islot = slot->i;
2911+ unsigned long flags;
2912+ int do_enable = 0;
2913+
2914+ if (!(atomic_read (&lo->flags) & NBD_INITIALISED)) {
2915+ NBD_ALERT ("(%d) device nd%s not initialised yet!\n",
2916+ islot, lo->devnam);
2917+ return -ENODEV;
2918+ }
2919+ if (!(atomic_read (&lo->flags) & NBD_SIZED)) {
2920+ NBD_ALERT ("(%d) device nd%s not sized yet!\n", islot,
2921+ lo->devnam);
2922+ return -EINVAL;
2923+ }
2924+ if (!(atomic_read (&lo->flags) & NBD_BLKSIZED)) {
2925+ NBD_ALERT ("(%d) device nd%s not blksized yet!\n", islot,
2926+ lo->devnam);
2927+ return -EINVAL;
2928+ }
2929+ if (!(atomic_read (&lo->flags) & NBD_SIGNED)) {
2930+ NBD_ALERT ("(%d) setting unsigned device nd%s! But harmless.\n",
2931+ islot, lo->devnam);
2932+ return -EINVAL;
2933+ }
2934+
2935+ down (&lo->pid_sem);
2936+
2937+ if (slot->pid != current->pid) {
2938+ if (jiffies > slot->cli_age + 2 * HZ * lo->req_timeo) {
2939+ NBD_ALERT
2940+ ("(%d) dead client process %d has nd%s%d, erasing pid!\n",
2941+ islot, slot->pid, lo->devnam, islot + 1);
2942+ slot->pid = 0;
2943+ } else {
2944+ NBD_ALERT
2945+ ("(%d) other live client process %d has nd%s%d!\n",
2946+ islot, slot->pid, lo->devnam, islot + 1);
2947+ }
2948+ up (&lo->pid_sem);
2949+ return -EINVAL;
2950+ }
2951+ up (&lo->pid_sem);
2952+
2953+ slot = &lo->slots[islot];
2954+
2955+ // PTB this is a queue critical code region for the flags business
2956+ write_lock_irqsave (&lo->meta_lock, flags);
2957+
2958+ // PTB file has to be nonzero to indicate we are all set up.
2959+ slot->file = (void *) (unsigned long) (arg+1 > 0 ? arg+1 : 1);
2960+
2961+ if (islot >= lo->nslot) {
2962+ lo->nslot = islot + 1;
2963+ NBD_INFO ("increased socket count to %d\n", lo->nslot);
2964+ }
2965+
2966+ lo->harderror = 0;
2967+
2968+ if (lo->disk && !get_capacity(lo->disk)) {
2969+ set_capacity(lo->disk, lo->sectors);
2970+ }
2971+ if (++lo->aslot > 0) {
2972+ do_enable = 1;
2973+ }
2974+ // PTB end of queue critical region
2975+ write_unlock_irqrestore (&lo->meta_lock, flags);
2976+
2977+ /*
2978+ * PTB if this is the first slot, we might call reenable and
2979+ * thus clr queue too, but reenable takes the spinlock
2980+ */
2981+ if (do_enable)
2982+ nbd_enable(lo);
2983+
2984+ return 0;
2985+}
2986+
2987+/*
2988+ * PTB - return the index i of 2^i + j, 0 <= j < 2^i
2989+ */
2990+static inline unsigned
2991+log2 (unsigned arg)
2992+{
2993+ unsigned log = 0;
2994+ while ((arg >>= 1) > 0)
2995+ log++;
2996+ return log;
2997+}
2998+
2999+/*
3000+ * PTB - set the blksize in bytes of the block device. Return 0 for
3001+ * - success and -ve for failure.
3002+ */
3003+static int
3004+nbd_set_blksize (struct nbd_device *lo, unsigned int arg)
3005+{
3006+ int nbd = lo->nbd;
3007+ if (arg > PAGE_SIZE || arg < 512 || (arg & (arg - 1))) {
3008+ NBD_ERROR ("blksize too big (%u)\n", arg);
3009+ return -EINVAL;
3010+ }
3011+ lo->blksize = nbd_blksizes[nbd << NBD_SHIFT] = arg;
3012+ lo->logblksize = log2 (lo->blksize);
3013+ set_blocksize(lo->inode->i_bdev, lo->blksize);
3014+ atomic_set_mask (NBD_BLKSIZED, &lo->flags);
3015+ return 0;
3016+}
3017+
3018+/*
3019+ * PTB - set the size in bytes of the block device. Return 0 for
3020+ * - success and -ve for failure.
3021+ */
3022+static int
3023+nbd_set_size (struct nbd_device *lo, __u64 arg)
3024+{
3025+ int nbd = lo->nbd;
3026+ lo->bytesize = nbd_bytesizes[nbd << NBD_SHIFT] = arg;
3027+ lo->size = nbd_sizes[nbd << NBD_SHIFT] = arg >> 10;
3028+ lo->sectors = lo->size << 1;
3029+ if (lo->inode && lo->inode->i_bdev && lo->inode->i_bdev->bd_inode)
3030+ lo->inode->i_bdev->bd_inode->i_size = arg;
3031+ if (lo->disk)
3032+ set_capacity (lo->disk, arg >> 9);
3033+ atomic_set_mask (NBD_SIZED, &lo->flags);
3034+ return 0;
3035+}
3036+
3037+/* WG */
3038+static int
3039+nbd_set_intvl (struct nbd_device *lo, int arg)
3040+{
3041+ if (arg <= 0) {
3042+ NBD_ERROR ("bad pulse interval/req timeout value (%d)\n", arg);
3043+ return -EINVAL;
3044+ }
3045+ lo->req_timeo = arg;
3046+ return 0;
3047+}
3048+
3049+static int
3050+nbd_set_spid (struct nbd_slot *slot, int arg)
3051+{
3052+ short spid = arg;
3053+ if (arg < 0 || arg >= (1 << (sizeof (short) * 8))) {
3054+ NBD_ERROR ("bad spid value (%d)\n", arg);
3055+ return -EINVAL;
3056+ }
3057+ slot->spid = spid;
3058+ return 0;
3059+}
3060+
3061+static int
3062+nbd_set_bufferwr (struct nbd_device *lo, int arg)
3063+{
3064+ if (arg) {
3065+ atomic_set_mask (NBD_BUFFERWR, &lo->flags);
3066+ } else {
3067+ atomic_clear_mask (NBD_BUFFERWR, &lo->flags);
3068+ }
3069+ return 0;
3070+}
3071+
3072+static int
3073+nbd_set_remote_invalid (struct nbd_device *lo, int arg)
3074+{
3075+ /*
3076+ * PTB we handle the event ourself exactly when it happens
3077+ * instead of letting the kernel have check_media defined
3078+ * and doing it there (and reporting 0 to the kernel)
3079+ */
3080+ unsigned long flags;
3081+ int do_invalidate = 0;
3082+ kdev_t dev = mk_kdev (major, lo->nbd << NBD_SHIFT);
3083+
3084+ if (arg == 0) {
3085+ atomic_clear_mask (NBD_REMOTE_INVALID, &lo->flags);
3086+ return 0;
3087+ }
3088+
3089+ write_lock_irqsave (&lo->meta_lock, flags);
3090+ if (!(atomic_test_and_set_mask (&lo->flags, NBD_REMOTE_INVALID))) {
3091+ /*
3092+ * PTB this tells the kernel that next open
3093+ * should cause recheck .. we'll agree not to
3094+ * say we're happy until VALID is set again
3095+ */
3096+ atomic_clear_mask (NBD_VALIDATED, &lo->flags);
3097+ // PTB test removing partitions
3098+ do_invalidate = 1;
3099+ }
3100+ write_unlock_irqrestore (&lo->meta_lock, flags);
3101+
3102+ if (do_invalidate) {
3103+ // PTB destroy buffers
3104+ __invalidate_buffers (dev, 1);
3105+ NBD_ALERT ("invalidating remote on nd%s\n", lo->devnam);
3106+ // PTB - clear buffers now instead of waiting for kernel
3107+ // PTB that will cause requests to start being errored
3108+ invalidate_device (dev, 0);
3109+ }
3110+
3111+ return 0;
3112+}
3113+/*
3114+ * Return the first slot index free when asking for n new ones.
3115+ * If there s no such gap, then NBD_MAXCONN will be returned.
3116+ * The return is always in the same argument address.
3117+ */
3118+static int
3119+nbd_get_nport (struct nbd_device *lo, int *arg)
3120+{
3121+ int err, nslot, i;
3122+
3123+ if (arg == NULL) {
3124+ return -EINVAL;
3125+ }
3126+
3127+ nslot = *arg;
3128+ err = copy_from_user ((char *) &nslot, arg, sizeof (int));
3129+ if (err < 0) {
3130+ return err;
3131+ }
3132+
3133+ for (i = 0; i < NBD_MAXCONN; i++) {
3134+ struct nbd_slot *sloti = &lo->slots[i];
3135+ int j;
3136+ if (sloti->file) {
3137+ continue;
3138+ }
3139+
3140+ for (j = i; j < NBD_MAXCONN && j < i + nslot; j++) {
3141+ if (sloti->file)
3142+ break;
3143+ }
3144+ if (j == i + nslot) {
3145+
3146+ break;
3147+ }
3148+ }
3149+
3150+ err = copy_to_user (arg, (char *) &i, sizeof (int));
3151+ return err;
3152+}
3153+
3154+
3155+/*
3156+ * PTB - if we're not signed, accept new sig and return success.
3157+ * - if we are signed, compare the offer and return success if equal,
3158+ * - and -ve for failure.
3159+ *
3160+ * @slot the slot we're working on
3161+ * @sig the string of signature chars (accessed as int *)
3162+ */
3163+static int
3164+nbd_set_sig (struct nbd_slot *slot, int *sig)
3165+{
3166+ int err = 0;
3167+ int buf[NBD_SIGLEN / sizeof (int)];
3168+ int islot = slot->i;
3169+ struct nbd_device *lo = slot->lo;
3170+
3171+ if (!access_ok (VERIFY_READ, (char *) sig, NBD_SIGLEN)) {
3172+ NBD_ALERT ("(%d): failed sigcheck with bad user address %p\n",
3173+ islot, sig);
3174+ err = -EINVAL;
3175+ return err;
3176+ }
3177+ down (&lo->pid_sem);
3178+
3179+ if (slot->pid == 0) {
3180+ slot->pid = current->pid;
3181+ slot->cli_age = jiffies;
3182+ }
3183+ if (slot->pid != current->pid) {
3184+ if (jiffies > slot->cli_age + 2 * HZ * lo->req_timeo) {
3185+ NBD_ALERT
3186+ ("(%d): dead process %d was setting sig, erasing pid\n",
3187+ islot, slot->pid);
3188+ slot->pid = 0;
3189+ } else {
3190+ NBD_ALERT
3191+ ("(%d): live process %d is trying to set sig\n",
3192+ islot, slot->pid);
3193+ }
3194+ up (&lo->pid_sem);
3195+ return -EINVAL;
3196+ }
3197+
3198+ if (!(atomic_read (&lo->flags) & NBD_SIGNED)) {
3199+ /* PTB first time grab sig */
3200+ copy_from_user ((char *) lo->signature, (char *) &sig[0],
3201+ NBD_SIGLEN);
3202+ atomic_set_mask (NBD_SIGNED, &lo->flags);
3203+ up (&lo->pid_sem);
3204+ return 0;
3205+ }
3206+ copy_from_user ((char *) buf, (char *) &sig[0], NBD_SIGLEN);
3207+
3208+ /* PTB test for equality */
3209+
3210+ if (memcmp (&buf[0], &lo->signature[0], NBD_SIGLEN / sizeof (int))
3211+ != 0) {
3212+ err = -EINVAL;
3213+ up (&lo->pid_sem);
3214+ NBD_ALERT ("(%d): failed sigcheck wth %d\n", islot, err);
3215+ return err;
3216+ }
3217+ up (&lo->pid_sem);
3218+ err = 0;
3219+ return err;
3220+}
3221+
3222+/*
3223+ * PTB - register a userspace buffer to a slot. Return 0 for success
3224+ * - and -ve for failure. Null arg acts as erase.
3225+ */
3226+static int
3227+nbd_reg_buf (struct nbd_slot *slot, char *buffer)
3228+{
3229+
3230+ int err = 0, siz;
3231+ struct nbd_device *lo = slot->lo;
3232+
3233+ if (!buffer) {
3234+ slot->flags &= ~NBD_SLOT_BUFFERED;
3235+ slot->buffer = NULL;
3236+ slot->bufsiz = 0;
3237+ return 0;
3238+ }
3239+
3240+ siz = lo->max_sectors << 9;
3241+
3242+ /* verify the buffer is in the process space */
3243+ if (!access_ok (VERIFY_WRITE, buffer, siz)) {
3244+ err = -EINVAL;
3245+ return err;
3246+ }
3247+ /* PTB hope the buffer is as big as it should be - FIXME */
3248+ slot->buffer = buffer;
3249+ slot->bufsiz = siz;
3250+
3251+ /* PTB let the device bufsiz be min of registered nonzero bufsizes */
3252+ if (!lo->bufsiz) {
3253+ // PTB first time
3254+ lo->bufsiz = siz;
3255+ } else {
3256+ if (lo->bufsiz > siz)
3257+ lo->bufsiz = siz;
3258+ }
3259+
3260+ // PTB just in case the buffer really is small, we reset all the
3261+ // kernels request maxima if we have to adjust the device max
3262+ if (lo->max_sectors < (lo->bufsiz >> 9)) {
3263+ int j;
3264+ lo->max_sectors = lo->bufsiz >> 9;
3265+ for (j = 0; j < NBD_MAXCONN; j++) {
3266+ nbd_max_sectors[(lo->nbd << NBD_SHIFT) + j] =
3267+ lo->max_sectors;
3268+ }
3269+ }
3270+
3271+ slot->flags |= NBD_SLOT_BUFFERED;
3272+ return 0;
3273+}
3274+
3275+/*
3276+ * PTB - this unsets the enabled flag on the device and then clears the
3277+ * - queue for the device.. Call without spinlock.
3278+ *
3279+ * @lo the nbd device to scan
3280+ */
3281+static int
3282+nbd_disable (struct nbd_device *lo)
3283+{
3284+ struct nbd_md * md = &nbd_md;
3285+
3286+ if (!lo || !(atomic_read (&lo->flags) & NBD_INITIALISED)) {
3287+ NBD_ALERT("nbd_disable called on bad device\n");
3288+ return 0;
3289+ }
3290+
3291+ if (atomic_test_and_clear_mask (&lo->flags, NBD_ENABLED)) {
3292+ NBD_ALERT ("disabled device nd%s\n", lo->devnam);
3293+ }
3294+
3295+ md->unnotify(md, mk_kdev (major, lo->nbd << NBD_SHIFT));
3296+
3297+ // PTB have to recheck partitions on next open
3298+ if (atomic_test_and_clear_mask (&lo->flags, NBD_VALIDATED)) {
3299+ NBD_ALERT ("invalidated device nd%s\n", lo->devnam);
3300+ }
3301+ return 0;
3302+}
3303+
3304+
3305+/*
3306+ * PTB - reset the enabled flag on a device and then clear all queues
3307+ * ( call without the spinlock held ) and then enable again.
3308+ */
3309+static void
3310+nbd_reenable (struct nbd_device *lo)
3311+{
3312+
3313+ int m, n;
3314+
3315+ if (!(atomic_read (&lo->flags) & NBD_INITIALISED))
3316+ return;
3317+ if (lo->aslot <= 0)
3318+ return;
3319+ if ((atomic_read (&lo->flags) & NBD_ENABLED))
3320+ return;
3321+
3322+ m = nbd_clr_queue (lo);
3323+ // PTB - have to call clr_kernel_queue without the io_spinlock held
3324+ n = nbd_clr_kernel_queue (lo);
3325+
3326+ nbd_enable(lo);
3327+}
3328+
3329+/*
3330+ * This function launches a thread which wakes for a signal to reenable
3331+ * the device, and then sets the timer to deleiver the signal.
3332+ */
3333+static int
3334+nbd_reenable_delay (struct nbd_device *lo, int delay)
3335+{
3336+ write_lock (&lo->meta_lock);
3337+ if (lo->reenable_time == 0)
3338+ lo->reenable_time = jiffies + delay * HZ;
3339+ write_unlock (&lo->meta_lock);
3340+ return 0;
3341+}
3342+
3343+
3344+
3345+/*
3346+ * PTB - drains device queue. Disables device.
3347+ * At least rollback (which we call takes both the io spinlock and our
3348+ * spinlock, so we can hold neither when we are called. Also
3349+ * invalidate buffers, on request of Rogier Wolff.
3350+ */
3351+static int
3352+nbd_soft_reset (struct nbd_device *lo)
3353+{
3354+ int j;
3355+ const int max_clrq_retries = 100;
3356+ if (!(atomic_read (&lo->flags) & NBD_INITIALISED) || lo->nslot <= 0) {
3357+ return -EINVAL;
3358+ }
3359+ /*
3360+ * PTB We push back the requests in the slot, in order to be able to
3361+ * vamoosh them in a moment. This is a race, surely? We ought to
3362+ * do this atomically or dsiable the slots first.
3363+ */
3364+ for (j = 0; j < lo->nslot; j++) {
3365+ struct nbd_slot *slot = &lo->slots[j];
3366+ nbd_rollback_all (slot);
3367+ }
3368+ // PTB disable unsets the nabled flag and clears the queue
3369+ nbd_disable (lo);
3370+ for (j = 0; j < max_clrq_retries; j++) {
3371+ int m = nbd_clr_queue (lo);
3372+ if (m <= 0)
3373+ break;
3374+ }
3375+ // PTB this would unsign the device: lo->flags &= ~NBD_SIGNED;
3376+
3377+ /*
3378+ * PTB put back invalidate buffers for use when called from
3379+ * clr_sock from nbd_release on request of Rogier Wolff.
3380+ */
3381+ for (j = 0; j < lo->nslot; j++) {
3382+ invalidate_buffers (mk_kdev(major, (lo->nbd << NBD_SHIFT) + j));
3383+ }
3384+ return 0;
3385+}
3386+
3387+/*
3388+ * PTB - added a device/module reset for tidyness in face of rampant hacking
3389+ * - this does a soft_reset of all devices, followed bu a clr sock
3390+ * - on each, and then clears the kernel queue. It unsets the
3391+ * - enabled flag on each device.
3392+ * We have to be called without either the spinlock or the
3393+ * spinlock held, as we call soft_reset which takes both, as
3394+ * does clr_sock
3395+ */
3396+int
3397+nbd_hard_reset (struct nbd_device *lo)
3398+{
3399+ int i;
3400+ int err = 0;
3401+
3402+ for (i = 0; i < MAX_NBD; i++) {
3403+ struct nbd_device *lo = &nbd_dev[i];
3404+ int j;
3405+ if (!lo->file || !lo->inode)
3406+ continue;
3407+ if (!(atomic_read(&lo->flags)&NBD_INITIALISED))
3408+ continue;
3409+ nbd_soft_reset (lo);
3410+ for (j = 0; j < lo->nslot; j++) {
3411+ struct nbd_slot *slot = &lo->slots[j];
3412+ // PTB this takes the io spinlock and our spinlock.
3413+ nbd_clr_sock (slot);
3414+ }
3415+ // PTB - call clr_kernel_queue without the io_spinlock held
3416+ nbd_clr_kernel_queue (lo);
3417+ }
3418+
3419+ return err;
3420+}
3421+
3422+static int
3423+indirect_ioctl_load (struct request *req, int cmd, char * buf)
3424+{
3425+
3426+ int size;
3427+ int err;
3428+ struct nbd_ioctl *remote_ioctl = nbd_remote_ioctl.remote;
3429+
3430+ if (!remote_ioctl)
3431+ return -EINVAL;
3432+
3433+ size = remote_ioctl->size_user (cmd, buf);
3434+
3435+ if (size < 0) {
3436+ // PTB unauthorized ioctl
3437+ err = -EINVAL;
3438+ goto error_out;
3439+ }
3440+
3441+ if (size == 0) {
3442+ // PTB we never use the nbd devices small buffer now
3443+ req->nr_sectors = 0;
3444+ req->buffer = NULL;
3445+ return size;
3446+ }
3447+
3448+ // PTB we have to use an extra buffer or else block
3449+ // here and rendezvous directly with the get_req call
3450+ req->nr_sectors = (size + 511) >> 9;
3451+ req->buffer = kmalloc(req->nr_sectors << 9, GFP_KERNEL);
3452+
3453+ if (!req->buffer) {
3454+ err = -ENOMEM;
3455+ goto error_out;
3456+ }
3457+
3458+ if (_IOC_DIR (cmd) & _IOC_WRITE) {
3459+ err =
3460+ remote_ioctl->cp_from_user (cmd, req->buffer, buf, size);
3461+ if (err < 0) {
3462+ kfree (req->buffer);
3463+ goto error_out;
3464+ }
3465+ }
3466+ return size;
3467+
3468+error_out:
3469+ req->buffer = NULL;
3470+ req->nr_sectors =0;
3471+ return err;
3472+}
3473+
3474+static int
3475+indirect_ioctl_store (struct request *req, int cmd, char * buf,
3476+ int size)
3477+{
3478+ int err;
3479+ struct nbd_ioctl * remote_ioctl = nbd_remote_ioctl.remote;
3480+
3481+ if (!remote_ioctl)
3482+ return -EINVAL;
3483+
3484+ if (size <= 0)
3485+ return size;
3486+
3487+ // PTB if we are reading, it should be to the local buffer
3488+ // PTB the buffer points at a kmalloced area
3489+
3490+ if (!req->buffer)
3491+ return -ENOMEM;
3492+ err = remote_ioctl->cp_to_user (cmd, buf, req->buffer, size);
3493+ kfree (req->buffer);
3494+ if (err < size)
3495+ return -ENOMEM;
3496+ return size;
3497+}
3498+
3499+static int
3500+do_nbd_remote_ioctl(struct nbd_device *lo, int minor, int cmd, unsigned long arg) {
3501+
3502+ unsigned start_time, timeout;
3503+ size_t size;
3504+ int err;
3505+ struct request * req;
3506+ struct completion x;
3e18f7ab 3507+ struct nbd_acct * acct = &lo->acct;
d912b53b 3508+
3509+ /*
3510+ * PTB here we have to treat remote ioctls. We should probably make
3511+ * a request and put it on the local queue, but where can we get
3512+ * the request from? We might have to keep one in reserve.
3513+ * That's not a bad idea, because
3514+ * we generate it here and we delete it here, and the daemon code
3515+ * is all set up to read that sort of thing. So that's what we do ...
3516+ */
3517+
3518+ timeout = lo->req_timeo * HZ;
3519+ start_time = jiffies;
3520+
3521+ while (!(req = blk_get_request(lo->q,WRITE,0))) {
3522+ if (jiffies >= start_time + timeout) {
3523+ // PTB it takes too long
3524+ NBD_ALERT
3525+ ("took too long to get a spare ioctl req: TIMEOUT\n");
3526+ return -ETIME;
3527+ }
3528+ err = interruptible_sleep_on_timeout (&lo->req_wq,
3529+ start_time +
3530+ timeout - jiffies);
3531+ }
3532+
3533+ set_rq_type(req, IOCTL);
3534+
3535+ req->errors = 0;
3536+
3537+ // PTB this is the fixed-up command
3538+ req->special = (void *) cmd;
3539+
3540+ /*
3541+ * PTB this is (arg if it is direct, else) the address of a local buffer
3542+ * PTB we need to store the arg or its dereference somewhere local
3543+ * for a while until the cnb-client thread can enter and pick it
3544+ * up. The alternative is to block the ioctl here until it is
3545+ * picked up, which IS possible.
3546+ */
3547+
3548+ if (_IOC_DIR (cmd) & _IOC_READ) {
3549+ // PTB indirect
3550+ size = indirect_ioctl_load (req, cmd, (char *)arg);
3551+ if (size < 0) {
3552+ goto end;
3553+ }
3554+ } else {
3555+ // PTB direct - we just need to remember the value
3556+ size = 0;
3557+ req->buffer = (char *) arg;
3558+ }
3559+
3560+ // PTB point the request buffer vaguely in the direction of where
3561+ // the data is, but it does not matter.
3562+ req->rq_disk = lo->disk;
3563+
3564+ // PTB we queue the request for treatment and wait till treated
3565+ init_completion(&x);
3566+ req->waiting = &x;
3567+ nbd_enqueue (lo, req);
3568+
3569+ for (err = 0; err <= 0; err = wait_for_completion_timeout(&x, 1)) {
3570+
3571+ /*
3572+ * PTB on slot or queue? Don't know. Only want
3573+ * to vamoosh it if its on queue, not slot
3574+ */
3575+ struct list_head *pos;
3576+ int time_left = start_time + timeout - jiffies;
3577+ // PTB del_req will be run with queue_lock held
3578+ static void delete_req(void) {
3579+
3580+ // PTB change countq only under this lock
3581+ if (! (req->flags & REQ_SPECIAL)) {
3582+ write_lock(&lo->altqueue_lock);
3583+ // PTB reverse inadvertent accounting in enqueue
3e18f7ab 3584+ atomic_dec (&acct->countq[rq_data_dir(req)]);
d912b53b 3585+ write_unlock(&lo->altqueue_lock);
3586+ }
3587+
3588+ list_del_init (&req->queuelist);
3589+
3590+ req->errors = -ETIME;
3591+ if (req->nr_sectors > 0 && req->buffer) {
3592+ kfree (req->buffer);
3593+ req->buffer = NULL;
3594+ }
3595+ };
3596+
3597+ if (time_left > 0)
3598+ continue;
3599+
3600+ // PTB find req on list and delete it
3601+ write_lock (&lo->queue_lock);
3602+ list_for_each (pos, &lo->queue) {
3603+
3604+ if (req != list_entry (pos, struct request, queuelist))
3605+ continue;
3606+
3607+ delete_req ();
3608+ write_unlock (&lo->queue_lock);
3609+ NBD_ALERT
3610+ ("took too long to treat queued ioctl: TIMEOUT\n");
3611+ err = -ETIME;
3612+ goto end;
3613+ }
3614+ write_unlock (&lo->queue_lock);
3615+
3616+ } // end while loop
3617+
3618+
3619+ if (_IOC_DIR (cmd) & _IOC_READ) {
3620+ err = indirect_ioctl_store(req, cmd, (char *)arg, size);
3621+ if (err < 0) {
3622+ goto end;
3623+ }
3624+ }
3625+
3626+ if (req->errors != 0) {
3627+ err = req->errors;
3628+ err = err < 0 ? err : -EINVAL;
3629+ } else {
3630+ err = 0;
3631+ }
3632+end:
3633+ blk_put_request(req);
3634+ return err;
3635+
3636+}
3637+
3638+static int
3639+find_slot (struct nbd_device *lo, int pid)
3640+{
3641+ int i;
3642+ // go search
3643+ for (i = 0; i < NBD_MAXCONN; i++) {
3644+ struct nbd_slot * slot = &lo->slots[i];
3645+ if (slot->pid == pid)
3646+ break;
3647+ }
3648+ if (i < NBD_MAXCONN)
3649+ return i; // found it
3650+ // not found
3651+ return -1;
3652+}
3653+
3654+static int
3655+fixup_slot (struct nbd_device *lo, int islot, unsigned int cmd, unsigned long *arg)
3656+{
3657+ int intval;
3658+
3659+ switch (cmd) {
3660+
3661+ // PTB get slot info from parameter if not given
3662+ case NBD_CLEAR_SOCK:
3663+ case MY_NBD_CLR_REQ:
3664+ case MY_NBD_ERR_REQ:
3665+ // see if we match a known slot pid
3666+ if (arg && *arg == 0) {
3667+ islot = find_slot (lo, current->pid);
3668+ if (islot >= 0)
3669+ return islot;
3670+ }
3671+ NBD_ALERT
3672+ ("failed to find slot for pid %d for ioctl %x arg %lx\n",
3673+ current->pid, cmd, *arg);
3674+ return islot = -1;
3675+ break;
3676+
3677+ // PTB get the slot from the 16 high bits
3678+ case NBD_SET_SOCK:
3679+ case MY_NBD_SET_SPID:
3680+ intval = *arg >> ((sizeof (int) - sizeof (short)) * 8);
3681+ intval &= (1 << (sizeof (short) * 8)) - 1;
3682+ if (intval == 0) {
3683+ // no clue in the pid high bits. Search
3684+ islot = find_slot (lo, current->pid);
3685+ if (islot >= 0) {
3686+ // PTB change arg !!
3687+ *arg &= (1 << (sizeof (short) * 8)) - 1;
3688+ return islot; // found it
3689+ }
3690+ // not found
3691+ }
3692+ NBD_ALERT
3693+ ("failed to find slot for pid %d for ioctl %x arg %lx\n",
3694+ current->pid, cmd, *arg);
3695+ return islot = -1;
3696+ break;
3697+
3698+ case MY_NBD_GET_REQ:
3699+ case MY_NBD_ACK:
3700+ islot = find_slot (lo, current->pid);
3701+ if (islot >= 0)
3702+ return islot;
3703+ NBD_ALERT
3704+ ("failed to find slot for pid %d for ioctl %x arg %lx\n",
3705+ current->pid, cmd, *arg);
3706+ return islot;
3707+ break;
3708+
3709+ case MY_NBD_REG_BUF:
3710+ case MY_NBD_SET_SIG:
3711+ islot = find_slot (lo, current->pid);
3712+ if (islot >= 0)
3713+ return islot;
3714+ /*
3715+ * PTB Otherwise they passed a buffer
3716+ * and the slot number is in the first 4B
3717+ * We need some magic here for safety!
3718+ * set sig is the only call that really needs
3719+ * to send its pid!
3720+ */
3721+
3722+ intval = -1;
3723+ if (!arg || !*arg || get_user (intval, (int *) *arg)
3724+ || intval <= 0
3725+ || intval > NBD_MAXCONN) {
3726+ NBD_ALERT
3727+ ("failed to find slot for pid %d ioctl %x arg %lx\n",
3728+ current->pid, cmd, *arg);
3729+ return islot = -1;
3730+ }
3731+ islot = intval - 1;
3732+
3733+ // PTB CHANGE ARG !!!!
3734+ *arg += sizeof (int);
3735+ return islot;
3736+ break;
3737+ }
3738+
3739+ return islot = -1;
3740+}
3741+
3742+/*
3743+ * PTB - generic ioctl handling
3744+ */
3745+static int
3746+nbd_ioctl (struct inode *inode, struct file *file,
3747+ unsigned int cmd, unsigned long arg)
3748+{
3749+ struct nbd_device *lo
3750+ = NULL; // PTB device pointer
3751+ int minor = -1; // PTB minor on which we got the ioctl
3752+ int islot = -1; // PTB slot number 0, 1, ...
3753+ int nbd = -1; // PTB the count for the device group
3754+ struct nbd_slot *slot
3755+ = NULL; // PTB slot pointer
3756+ int err;
3e18f7ab 3757+ struct nbd_acct *acct = &lo->acct;
d912b53b 3758+
3759+ if (!capable(CAP_SYS_ADMIN)) {
3760+ NBD_ERROR ("caller must be root.\n");
3761+ return -EPERM;
3762+ }
3763+ if (!inode) {
3764+ NBD_ERROR ("given bad inode.\n");
3765+ return -EINVAL;
3766+ }
3767+ if (major (inode->i_rdev) != major) {
3768+ NBD_ERROR ("pseudo-major %d != %d\n",
3769+ major (inode->i_rdev), major);
3770+ return -ENODEV;
3771+ }
3772+ minor = minor (inode->i_rdev);
3773+ nbd = minor >> NBD_SHIFT;
3774+ if (nbd >= MAX_NBD) {
3775+ NBD_ERROR ("tried to open too many devices, %d\n", minor);
3776+ return -ENODEV;
3777+ }
3778+ lo = &nbd_dev[nbd];
3779+ lo->harderror = 0;
3780+ islot = minor % NBD_MAXCONN - 1;
3781+
3782+ /*
3783+ * PTB fixup breakage >= 2.5.44 caused by not being allowed to talk to
3784+ * minors. We deduce the slot number from hints in the call.
3785+ * Or we match against the known pids.
3786+ */
3787+ if (islot < 0) {
3788+ islot = fixup_slot(lo, islot, cmd, &arg);
3789+ }
3790+ if (islot >= 0)
3791+ slot = & lo->slots[islot];
3792+
3793+
3794+ // PTB these are all always local ioctls
3795+ switch (cmd) {
3796+ int err;
3797+ int intval;
3798+ int do_reenable;
3799+
3800+ case NBD_CLEAR_SOCK:
3801+ if (islot < 0) {
3802+ NBD_ALERT ("CLEAR_SOCK called on full device nd%s arg %lx\n",
3803+ lo->devnam, arg);
3804+ return -EINVAL;
3805+ }
3806+ err = nbd_clr_sock (slot);
3807+ return err;
3808+
3809+ case NBD_SET_SOCK:
3810+ if (islot < 0) {
3811+ NBD_ALERT ("SET_SOCK called on full device nd%s arg %lx\n",
3812+ lo->devnam, arg);
3813+ return -EINVAL;
3814+ }
3815+ err = nbd_set_sock (slot, arg);
3816+ return err;
3817+
3818+ case BLKBSZGET:
3819+ // PTB The kernel should intercept this
3820+ NBD_ALERT ("attempted get_blksize with BLKBSZGET\n");
3821+ return -EINVAL;
3822+
3823+ case NBD_GET_BLKSIZE:
3824+ if (!(atomic_read (&lo->flags) & NBD_BLKSIZED)) {
3825+ return -EINVAL;
3826+ }
3827+ err = put_user (lo->blksize, (long *) arg);
3828+ return err;
3829+
3830+ case BLKBSZSET:
3831+ // PTB The kernel should have intercepted this
3832+ NBD_ALERT ("attempted set_blksize with BLKBSZSET\n");
3833+ return -EINVAL;
3834+
3835+ case NBD_SET_BLKSIZE:
3836+ if (!arg)
3837+ return -EINVAL;
3838+ intval = -1;
3839+ if (get_user (intval, (int *)arg))
3840+ return -EFAULT;
3841+ if (intval == -1) {
3842+ NBD_ALERT ("BLKBSZSET got %d from user\n", intval);
3843+ }
3844+ err = nbd_set_blksize (lo, intval);
3845+ return err;
3846+
3847+ case NBD_SET_SIZE:
3848+ err = nbd_set_size (lo, (__u64) arg);
3849+ return err;
3850+
3851+ case NBD_SET_SECTORS:
3852+ err = nbd_set_size (lo, ((__u64) arg) << 9);
3853+ return err;
3854+
3855+ case MY_NBD_SET_INTVL: /* WG */
3856+ err = nbd_set_intvl (lo, arg);
3857+ return err;
3858+
3859+ case MY_NBD_SET_SPID:
3860+ if (islot < 0) {
3861+ NBD_ALERT ("SET_SPID called on full device nd%s\n",
3862+ lo->devnam);
3863+ return -EINVAL;
3864+ }
3865+ err = nbd_set_spid (slot, arg);
3866+ return err;
3867+
3868+ case MY_NBD_SET_BUFFERWR:
3869+ err = nbd_set_bufferwr (lo, arg);
3870+ return err;
3871+
3872+ case MY_NBD_REG_BUF: /* PTB register your buffer per socket here */
3873+ if (!arg) {
3874+ /* PTB serves as existence check for this ioctl */
3875+ return 0;
3876+ }
3877+ if (islot < 0) {
3878+ NBD_ALERT ("REG_BUF called on full device nd%s\n",
3879+ lo->devnam);
3880+ return -EINVAL;
3881+ }
3882+ err = nbd_reg_buf (slot, (char *) arg);
3883+ return err;
3884+
3885+ case MY_NBD_SET_SIG:
3886+ if (islot < 0) {
3887+ NBD_ALERT ("SET_SIG called on full device nd%s\n",
3888+ lo->devnam);
3889+ return -EINVAL;
3890+ }
3891+ err = nbd_set_sig (slot, (int *) arg);
3892+ return err;
3893+
3894+ case MY_NBD_GET_REQ:
3895+ if (islot < 0) {
3896+ NBD_ALERT ("GET_REQ called on full device nd%s\n",
3897+ lo->devnam);
3898+ return -EINVAL;
3899+ }
3900+ if (arg < 4096) {
3901+ arg = (unsigned)slot->buffer;
3902+ if (!arg)
3903+ return -EINVAL;
3904+ }
3905+ err = nbd_get_req (slot);
3906+ return err;
3907+
3908+ case MY_NBD_GET_NPORT:
3909+ err = nbd_get_nport (lo, (int *) arg);
3910+ return err;
3911+
3912+ case MY_NBD_CLR_REQ:
3913+ if (islot < 0) {
3914+ NBD_ALERT ("CLR_REQ called on full device nd%s\n",
3915+ lo->devnam);
3916+ return -EINVAL;
3917+ }
3918+ nbd_rollback_all (slot);
3919+ return 0;
3920+
3921+ case MY_NBD_ERR_REQ:
3922+ if (islot < 0) {
3923+ NBD_ALERT ("ERR_REQ called on full device nd%s\n",
3924+ lo->devnam);
3925+ return -EINVAL;
3926+ }
3927+ nbd_error_all (slot);
3928+ return 0;
3929+
3930+ case MY_NBD_SYNC:
3931+
3932+ // PTB maybe run the reenable function
3933+ do_reenable = 0;
3934+ write_lock(&lo->meta_lock);
3935+ if (lo->reenable_time != 0
3936+ && time_before(lo->reenable_time,jiffies)) {
3937+ lo->reenable_time = 0;
3938+ do_reenable = 1;
3939+ }
3940+ write_unlock(&lo->meta_lock);
3941+ if (do_reenable)
3942+ nbd_reenable(lo);
3943+
3944+ // PTB error too old reqs if show_errs set, else roll them back
3945+ nbd_rollback_old (lo);
3946+
3947+ // PTB opportunity to calculate speed
3948+ nbd_set_speed (lo);
3949+
3950+ return 0;
3951+
3952+ case MY_NBD_ACK:
3953+ if (islot < 0) {
3954+ NBD_ALERT ("NBD_ACK called on full device nd%s\n",
3955+ lo->devnam);
3956+ return -EINVAL;
3957+ }
3958+ err = nbd_ack (slot);
3959+ return err;
3960+
3961+ /* let this be compiled in always - it's useful. PTB */
3962+ case NBD_PRINT_DEBUG:
3963+ NBD_INFO("device %d: hd = %p, tl = %p, in = %d, out = %d\n",
3964+ minor,
3965+ list_head (&lo->queue, struct request, queuelist),
3966+ list_tail (&lo->queue, struct request, queuelist),
3e18f7ab 3967+ atomic_read (&acct->requests_in[READ]) +
3968+ atomic_read (&acct->requests_in[WRITE]),
3969+ atomic_read (&acct->requests_out[READ]) +
3970+ atomic_read (&acct->requests_out[WRITE])
d912b53b 3971+ );
3972+ err = 0;
3973+ return err;
3974+ case NBD_HARD_RESET: /* PTB - debugging */
3975+ err = nbd_hard_reset (lo);
3976+ return err;
3977+
3978+ case NBD_RESET: /* PTB - debugging */
3979+ err = nbd_soft_reset (lo);
3980+ // PTB we reenable in 5s
3981+ nbd_reenable_delay(lo, 5);
3982+ return err;
3983+
3984+ case NBD_SET_MD5SUM: /* PTB - change to do/plead md5summing */
3985+ if (arg) {
3986+ atomic_set_mask (NBD_MD5SUM, &lo->flags);
3987+ } else {
3988+ atomic_clear_mask (NBD_MD5SUM, &lo->flags);
3989+ }
3990+ err = 0;
3991+ return err;
3992+
3993+ case MY_NBD_SET_SHOW_ERRS: /* PTB/WG - change show error status */
3994+ if (arg) {
3995+ atomic_set_mask (NBD_SHOW_ERRS, &lo->flags);
3996+ } else {
3997+ atomic_clear_mask (NBD_SHOW_ERRS, &lo->flags);
3998+ }
3999+ return 0;
4000+
4001+ case MY_NBD_SET_DIRECT: /* PTB - change o_direct status */
4002+ if (arg) {
4003+ atomic_set_mask (NBD_DIRECT, &lo->flags);
4004+ } else {
4005+ atomic_clear_mask (NBD_DIRECT, &lo->flags);
4006+ }
4007+ return 0;
4008+
4009+ case MY_NBD_INVALIDATE:
4010+ err = nbd_set_remote_invalid (lo, (int) arg);
4011+ return err;
4012+
4013+ case NBD_SET_PF_MEMALLOC:
4014+ if (arg) {
4015+ current->flags |= PF_MEMALLOC;
4016+ } else {
4017+ current->flags &= ~PF_MEMALLOC;
4018+ }
4019+ return 0;
4020+ } // PTB endsw
4021+
4022+ // PTB these are the standard ioctls, and we might get them from
4023+ // the other side
4024+
4025+ switch (cmd) {
4026+ int err;
4027+ int intval;
4028+
4029+ case BLKROSET: /* PTB - change ro status */
4030+ if (get_user(intval, (int*)arg))
4031+ return -EFAULT;
4032+ // PTB local flags
4033+ nbd_set_read_only(lo, intval);
4034+ return 0;
4035+
4036+ case BLKROGET:
4037+ intval = nbd_read_only(lo);
4038+ return put_user(intval, (int*)arg);
4039+
4040+ case BLKFLSBUF:
4041+ nbd_maybe_sync_sync (lo); // PTB normally fsync_dev
4042+ // PTB device likely has buffers or caches in kernel
4043+ invalidate_buffers (inode->i_rdev);
4044+#ifndef NO_BUFFERED_WRITES
4045+ if (atomic_read (&lo->flags) & NBD_BUFFERWR) {
4046+ // PTB got this from rd.c
4047+ // PTB destroy buffers
4048+ __invalidate_buffers (inode->i_rdev, 1);
4049+ }
4050+#endif /* NO_BUFFERED_WRITES */
4051+ return 0;
4052+
4053+ case HDIO_GETGEO:
4054+ if (!arg) {
4055+ return -EINVAL;
4056+ } else {
4057+ struct hd_geometry *geo =
4058+ (struct hd_geometry *) arg;
4059+ int sectors = nbd_sizes[nbd << NBD_SHIFT] << 1;
4060+ unsigned short c;
4061+ unsigned char h, s;
4062+ if (sectors < (1 << 22)) {
4063+ h = 4;
4064+ s = 16;
4065+ c = sectors >> 6;
4066+ } else {
4067+ h = 255;
4068+ s = 63;
4069+ c = (sectors / h) / s;
4070+ }
4071+ err = 0;
4072+ if ((err = put_user (c, &geo->cylinders), err < 0)
4073+ || (err = put_user (h, &geo->heads), err < 0)
4074+ || (err = put_user (s, &geo->sectors), err < 0)
4075+ || (err = put_user (h, &geo->start), err < 0)) {
4076+ return err;
4077+ }
4078+ }
4079+ return 0;
4080+
4081+#ifndef BLKMDNTFY
4082+#define BLKMDNTFY _IOW(0x12,133,sizeof(int))
4083+#endif
4084+ case BLKMDNTFY:
4085+ NBD_INFO ("received BLKMDNTFY, am now in raid %x\n",
4086+ (unsigned) arg);
4087+ nbd_md.inc(&nbd_md);
4088+ return 0;
4089+
4090+#ifndef BLKMDUNTFY
4091+#define BLKMDUNTFY _IOW(0x12,134,sizeof(int))
4092+#endif
4093+ case BLKMDUNTFY:
4094+ NBD_INFO ("received BLKMDUNTFY, now out of raid %x\n",
4095+ (unsigned) arg);
4096+ nbd_md.dec(&nbd_md);
4097+ return 0;
4098+
4099+#ifndef BLKMDRGTR
4100+#define BLKMDRGTR _IOW(0x12,135,sizeof(unsigned long))
4101+#endif
4102+ case BLKMDRGTR:
4103+ nbd_md.reg(&nbd_md, (int(*)(kdev_t, int))arg);
4104+ return 0;
4105+
4106+ } // PTB endsw
4107+
4108+ if (nbd_remote_ioctl.remote != NULL) {
4109+ struct nbd_ioctl *remote_ioctl = nbd_remote_ioctl.remote;
4110+
4111+ if (remote_ioctl->convert_inplace (&cmd) < 0) {
4112+ NBD_ALERT ("unauthorized ioctl %#x\n", cmd);
4113+ return -EINVAL;
4114+ }
4115+
4116+ err = do_nbd_remote_ioctl(lo, minor, cmd, arg);
4117+ return err;
4118+ }
4119+ return -EINVAL;
4120+}
4121+
4122+/*
4123+ * PTB - release the device. This happens when the last process closes
4124+ * or dies.
4125+ */
4126+static int
4127+nbd_release (struct inode *inode, struct file *file)
4128+{
4129+ struct nbd_device *lo;
4130+ int dev;
4131+ int nbd;
4132+ int islot;
4133+
4134+ if (!inode) {
4135+ NBD_ALERT ("null inode.\n");
4136+ return -ENODEV;
4137+ }
4138+ dev = minor (inode->i_rdev);
4139+ nbd = dev >> NBD_SHIFT;
4140+
4141+ if (nbd >= MAX_NBD) {
4142+ // PTB impossible
4143+ NBD_ALERT ("too many open devices.\n");
4144+ return -ENODEV;
4145+ }
4146+
4147+ lo = &nbd_dev[nbd];
4148+
4149+ islot = dev % NBD_MAXCONN - 1;
4150+
4151+ // PTB it is a daemon closing the slot?
4152+ if (islot >= 0 || (islot = find_slot(lo, current->pid), islot >= 0)) {
4153+ struct nbd_slot *slot = &lo->slots[islot];
4154+ --slot->refcnt;
4155+ if (slot->pid == current->pid) {
4156+
4157+ nbd_clr_sock (slot);
4158+ NBD_ALERT ("(%d): erasing slot pid %d\n", islot, slot->pid);
4159+ slot->pid = 0;
4160+ if (slot->refcnt > 0) {
4161+ NBD_ALERT
4162+ ("slot owner process %d released slot nd%s%d while not last\n",
4163+ slot->pid, lo->devnam, islot + 1);
4164+ }
4165+ }
4166+ }
4167+
4168+ /* POSSIBLE change socket here PTB */
4169+
4170+ atomic_dec (&lo->refcnt);
4171+
4172+ // PTB invalidate buffers on last close if show_err set
4173+ if (atomic_read (&lo->refcnt) <= 0 || !module_is_live(THIS_MODULE)) {
4174+ struct nbd_seqno * seqno_out = &lo->seqno_out;
4175+ //invalidate_buffers (lo->inode->i_rdev);
4176+ if (atomic_read (&lo->flags) & NBD_SHOW_ERRS) {
4177+ invalidate_buffers (mk_kdev (major, nbd << NBD_SHIFT));
4178+ }
4179+ // PTB in any case the daemons are dead!
4180+ lo->bufsiz = 0;
4181+ seqno_out->reset(seqno_out);
4182+ }
4183+
4184+ if (file
4185+ && (file->f_flags & O_DIRECT)
4186+ // PTB we set this to show we made iobuf
4187+ && (file->f_flags & O_NOFOLLOW)) {
4188+ file->f_flags &= ~(O_DIRECT|O_NOFOLLOW);
4189+ }
4190+
4191+ return 0;
4192+}
4193+
4194+static int
4195+nbd_media_changed(struct gendisk *disk) {
4196+ struct nbd_device *lo = disk->private_data;
4197+ if (!lo || lo->magic != NBD_DEV_MAGIC)
4198+ return 0;
4199+ NBD_ALERT("nbd_media_changed called on nd%s\n", lo->devnam);
4200+ return (atomic_read (&lo->flags) & NBD_VALIDATED) == 0;
4201+}
4202+
4203+static int
4204+nbd_revalidate(struct gendisk *disk) {
4205+ struct nbd_device *lo = disk->private_data;
4206+ unsigned long flags;
4207+ int err = -EINVAL;
4208+
4209+ if (!lo || lo->magic != NBD_DEV_MAGIC){
4210+ return -EINVAL;
4211+ }
4212+ // PTB reenable part
4213+ NBD_ALERT("revalidate called on nd%s\n", lo->devnam);
4214+ write_lock_irqsave (&lo->meta_lock, flags);
4215+ if (! (atomic_read (&lo->flags) & NBD_REMOTE_INVALID)
4216+ && (atomic_read (&lo->flags) & NBD_ENABLED)) {
4217+ atomic_set_mask (NBD_VALIDATED, &lo->flags);
4218+ err = 0;
4219+ }
4220+ write_unlock_irqrestore (&lo->meta_lock, flags);
4221+
4222+ return err;
4223+}
4224+
4225+static struct block_device_operations nbd_blkops = {
4226+ owner: THIS_MODULE,
4227+ open: nbd_open,
4228+ release: nbd_release,
4229+ ioctl: nbd_ioctl,
4230+ media_changed: nbd_media_changed,
4231+ revalidate_disk: nbd_revalidate,
4232+};
4233+
4234+static struct gendisk *
4235+nbd_find (dev_t dev, int *part, void *data)
4236+{
4237+ struct nbd_device *lo = data;
4238+ if (!lo)
4239+ return NULL;
4240+ if (lo->magic != NBD_DEV_MAGIC)
4241+ return NULL;
4242+ if (!lo->disk)
4243+ return NULL;
4244+ if (part)
4245+ NBD_ALERT("nbd_find called with part = %#x\n", (unsigned)*part);
4246+ if (part && (*part < 0 || *part >= NBD_MAXCONN))
4247+ return NULL;
4248+ return get_disk (lo->disk);
4249+}
4250+
4251+
4252+static int
4253+nbd_set_disk (struct nbd_device *lo, unsigned first_minor, unsigned npart)
4254+{
4255+ struct gendisk * disk = lo->disk;
4256+ if (!disk)
4257+ lo->disk = disk = alloc_disk (npart);
4258+ if (disk) {
4259+ disk->major = major;
4260+ disk->first_minor = first_minor;
4261+ disk->fops = &nbd_blkops;
4262+ disk->private_data = lo;
4263+ disk->queue = lo->q;
4264+ sprintf (disk->disk_name, "nd%s", lo->devnam);
4265+ // have to set minors (or capacity) to 1 (0) to avoid check disk
4266+ set_capacity (disk, 0);
4267+ add_disk (disk);
4268+ blk_register_region(MKDEV(major, first_minor),
4269+ npart, THIS_MODULE, nbd_find, NULL, lo);
4270+ set_capacity (disk, lo->bytesize >> 9);
4271+ // we should rescan later. From userland?
4272+ return 0;
4273+ }
4274+
4275+ NBD_ERROR ("Insufficient memory for partition structs\n");
4276+ return -ENOMEM;
4277+}
4278+
4279+/*
4280+ * Pavel - And here should be modules and kernel interface
4281+ * (Just smiley confuses emacs :-)
4282+ */
4283+
4284+
4285+static void
4286+nbd_reset(struct nbd_device *lo, int i) {
4287+
4288+ int j;
4289+
4290+ if (i < 0 || i >= MAX_NBD)
4291+ return;
4292+ lo->magic = NBD_DEV_MAGIC;
4293+ strncpy (lo->devnam, device_letter (i), 4);
4294+ for (j = 0; j < NBD_MAXCONN; j++) { /* PTB */
4295+ struct nbd_slot *slot = &lo->slots[j];
4296+ slot->lo = lo;
4297+ slot->i = j;
4298+ INIT_LIST_HEAD (&slot->queue);
4299+ }
4300+ lo->blksize = 1024; /* PTB 132 */
4301+ lo->logblksize = 10; /* PTB */
4302+ lo->bytesize = 0x7fffffff00000; /* PTB 132 */
4303+ lo->size = 0x7fffffff; /* PTB (bytesizes >> 10) */
4304+ lo->sectors = 0xfffffffe; /* PTB sectors */
4305+ lo->nbd = i;
4306+ lo->req_timeo = NBD_REQ_TIMEO; /* PTB default pulse intvl */
4307+ lo->max_sectors = buf_sectors;
4308+
4309+ lo->enable = nbd_enable;
4310+ lo->reset = nbd_reset;
4311+ lo->disable = nbd_disable;
4312+ lo->read_only = nbd_read_only;
4313+ lo->set_speed = nbd_set_speed;
4314+ lo->hard_reset = nbd_hard_reset;
4315+ lo->soft_reset = nbd_soft_reset;
4316+ lo->reenable_delay = nbd_reenable_delay;
4317+
4318+ INIT_LIST_HEAD (&lo->queue);
4319+ INIT_LIST_HEAD (&lo->altqueue);
4320+ init_waitqueue_head (&lo->wq);
4321+ init_waitqueue_head (&lo->req_wq);
4322+ init_MUTEX(&lo->pid_sem);
4323+ rwlock_init (&lo->queue_lock);
4324+ rwlock_init (&lo->altqueue_lock);
4325+ rwlock_init (&lo->meta_lock);
4326+ for (j = 0; j < NBD_MAXCONN; j++) {
4327+ nbd_blksizes[i * NBD_MAXCONN + j] = lo->blksize;
4328+ nbd_bytesizes[i * NBD_MAXCONN + j] = lo->bytesize;
4329+ nbd_sizes[i * NBD_MAXCONN + j] = lo->size;
4330+ nbd_max_sectors[i * NBD_MAXCONN + j] = lo->max_sectors;
4331+ }
4332+ nbd_init_seqno(&lo->seqno_out);
4333+ nbd_init_speed(&lo->rspeed);
4334+ nbd_init_speed(&lo->wspeed);
4335+ nbd_init_speed(&lo->tspeed);
4336+
4337+ // PTB queuue has alreay been initialized, or will be
4338+ lo->q = nbd_queue;
4339+
4340+ if (md5sum) {
4341+ atomic_set_mask (NBD_MD5SUM, &lo->flags);
4342+ }
4343+ if (sync_intvl) {
4344+ atomic_set_mask (NBD_SYNC, &lo->flags);
4345+ }
4346+ if (show_errs) {
4347+ atomic_set_mask (NBD_SHOW_ERRS, &lo->flags);
4348+ }
4349+ if (direct) {
4350+ atomic_set_mask (NBD_DIRECT, &lo->flags);
4351+ }
4352+ if (buffer_writes) {
4353+ atomic_set_mask (NBD_BUFFERWR, &lo->flags);
4354+ }
4355+ if (merge_requests) {
4356+ atomic_set(&lo->merge_requests, merge_requests);
4357+ }
4358+}
4359+
4360+#ifdef MODULE
4361+MODULE_AUTHOR ("Peter T. Breuer, Andres Marin");
4362+MODULE_DESCRIPTION ("Enhanced Network Block Device " NBD_VERSION);
4363+MODULE_LICENSE ("GPL");
4364+#endif /* MODULE */
4365+
4366+// PTB we steal these from the queue struct at init
4367+static merge_requests_fn *ll_merge_requests_fn;
4368+static merge_request_fn *ll_front_merge_fn;
4369+static merge_request_fn *ll_back_merge_fn;
4370+
4371+/* PTB -
4372+ * These functions are needed when the kernel does request merging in
4373+ * order to stop it making requests that are bigger than our buffer.
4374+ *
4375+ * To turn OFF merging (once these functions are in place), set
4376+ * merge_requests=0.
4377+ */
4378+static int
4379+nbd_merge_requests_fn (request_queue_t * q, struct request *req,
4380+ struct request *req2)
4381+{
4382+ struct nbd_device *lo = req->rq_disk->private_data;
4383+
4384+ if (!atomic_read(&lo->merge_requests))
4385+ return 0;
4386+
4387+ if (!ll_merge_requests_fn)
4388+ return 0;
4389+
4390+ if (req->nr_sectors + req2->nr_sectors > lo->max_sectors)
4391+ return 0;
4392+
4393+ if (req->nr_sectors + req2->nr_sectors >
4394+ ((atomic_read(&lo->merge_requests) + 1) << (lo->logblksize - 9)))
4395+ return 0;
4396+
4397+ return ll_merge_requests_fn (q, req, req2);
4398+}
4399+static int
4400+nbd_front_merge_fn (request_queue_t * q, struct request *req, struct bio * bio)
4401+{
4402+ struct nbd_device *lo = req->rq_disk->private_data;
4403+
4404+ if (!atomic_read(&lo->merge_requests))
4405+ return 0;
4406+
4407+ if (!ll_front_merge_fn)
4408+ return 0;
4409+
4410+ if (req->nr_sectors > lo->max_sectors)
4411+ return 0;
4412+
4413+ if (req->nr_sectors > ((atomic_read(&lo->merge_requests) + 1) << (lo->logblksize - 9)))
4414+ return 0;
4415+
4416+ return ll_front_merge_fn (q, req, bio);
4417+}
4418+static int
4419+nbd_back_merge_fn (request_queue_t * q, struct request *req,
4420+ struct bio * bio)
4421+{
4422+ struct nbd_device *lo = req->rq_disk->private_data;
4423+
4424+ if (!atomic_read(&lo->merge_requests))
4425+ return 0;
4426+
4427+ if (!ll_back_merge_fn)
4428+ return 0;
4429+
4430+ if (req->nr_sectors > lo->max_sectors)
4431+ return 0;
4432+
4433+ if (req->nr_sectors >
4434+ ((atomic_read(&lo->merge_requests) + 1) << (lo->logblksize - 9))) return 0;
4435+
4436+ return ll_back_merge_fn (q, req, bio);
4437+}
4438+
4439+// PTB - and now to play with the sysctl interface ...
4440+static struct ctl_table_header *nbd_table_header;
4441+// the above was set by the register call of the root table
4442+static ctl_table nbd_table[] = {
4443+ {1, "rahead",
4444+ &rahead, sizeof (int), 0644, NULL, &proc_dointvec},
4445+ {2, "plug",
4446+ &plug, sizeof (int), 0644, NULL, &proc_dointvec},
4447+ {3, "sync_intvl",
4448+ &sync_intvl, sizeof (int), 0644, NULL, &proc_dointvec},
4449+ {4, "merge_requests",
4450+ &merge_requests, sizeof (int), 0644, NULL, &proc_dointvec},
4451+ {5, "md5sum",
4452+ &md5sum, sizeof (int), 0644, NULL, &proc_dointvec},
4453+ {8, "md5_on_threshold",
4454+ &md5_on_threshold, sizeof (int), 0644, NULL, &proc_dointvec},
4455+ {9, "md5_off_threshold",
4456+ &md5_off_threshold, sizeof (int), 0644, NULL, &proc_dointvec},
4457+ {0}
4458+};
4459+static ctl_table nbd_dir_table[] = {
4460+ {6, "enbd", NULL, 0, 0555, nbd_table},
4461+ {0}
4462+};
4463+static ctl_table nbd_root_table[] = {
4464+ {CTL_DEV, "dev", NULL, 0, 0555, nbd_dir_table},
4465+ {0}
4466+};
4467+
4468+#ifdef CONFIG_DEVFS_FS
4469+static devfs_handle_t devfs_handle;
4470+static devfs_handle_t devfs_handles[MAX_NBD];
4471+#endif
4472+
4473+
4474+int __init
4475+nbd_init (void)
4476+{
4477+ int i;
4478+ int err = 0;
4479+ struct proc_dir_entry *res;
4480+
4481+ NBD_INFO ("Network Block Device originally by pavel@elf.mj.gts.cz\n");
4482+ NBD_INFO ("Network Block Device port to 2.0 by ptb@it.uc3m.es\n");
4483+ NBD_INFO ("Network Block Device move networking to user space by "
4484+ "amarin@it.uc3m.es\n");
4485+ NBD_INFO ("Enhanced Network Block Device " NBD_VERSION " by "
4486+ "ptb@it.uc3m.es\n");
4487+
4488+ nbd_queue = kmalloc(sizeof(*nbd_queue), GFP_KERNEL);
4489+ if (!nbd_queue)
4490+ return -ENOMEM;
4491+
4492+ for (i = 0; i < MAX_NBD; i++) {
4493+ struct nbd_device *lo = &nbd_dev[i];
4494+ struct gendisk *disk = alloc_disk(NBD_MAXCONN);
4495+ memset (lo, 0, sizeof (*lo));
4496+ if (disk)
4497+ lo->disk = disk;
4498+ }
4499+
4500+ if (register_blkdev (major, "nbd", &nbd_blkops)) {
4501+ NBD_ERROR ("Unable to register major number %d for NBD\n",
4502+ major);
4503+ return -EIO;
4504+ }
4505+#ifdef MODULE
4506+ NBD_INFO ("registered device at major %d\n", major);
4507+#endif
4508+
4509+
4510+// PTB - set up kernel queue struct with default methods
4511+ blk_init_queue (nbd_queue, do_nbd_request, &nbd_lock);
4512+
4513+ blk_queue_max_sectors(nbd_queue, buf_sectors); /* max per request */
4514+
4515+/*
4516+ * PTB - I think that put:
4517+ * - q->plug_device_fn = generic_plug_device (static ll_rw_blk)
4518+ * - q->plug_tq.routine = generic_unplug_device (static ll_rw_blk)
4519+ * - q->back_merge_fn = ll_back_merge_fn (static ll_rw_blk)
4520+ * - q->front_merge_fn = ll_front_merge_fn (static ll_rw_blk)
4521+ * - q->merge_requests_fn = ll_merge_requests_fn (static ll_rw_blk)
4522+ * - q->request_fn = do_nbd_request (param)
4523+ */
4524+
4525+/*
4526+ * PTB - we have to do some more init magic in 2.4.*. This says that we
4527+ * - take all stuff off the kernel queue before processing it, so in
4528+ * - particular iti s OK for kernel to do merges with the queue head.
4529+ * blk_queue_headactive (nbd_queue, 0);
4530+ */
4531+
4532+/*
4533+ * LA - moved the next #if higher;
4534+ * - kernel 2.2.* doesn't know about plug_device_fn
4535+ */
4536+
4537+ // PTB control merge attempts so we do not overflow our buffer
4538+ ll_merge_requests_fn = nbd_queue->merge_requests_fn;
4539+ ll_front_merge_fn = nbd_queue->front_merge_fn;
4540+ ll_back_merge_fn = nbd_queue->back_merge_fn;
4541+
4542+// JSA - Add this line because under >=2.4.1, merge optimizations are in flux
4543+/*
4544+ * PTB - however it's not this which does damage, I believe. Data: plugging
4545+ * - simply has to be enabled in these kernels. Without it, requests just
4546+ * - sit on the kernel queue and never come off and into our request_fn.
4547+ * PTB - commented the ifdef again after talks with Jens Axboe.
4548+ * - Apparently plug_fn will disappear in 2.4.4 and merge functions are
4549+ * the only way to control merges, so they MUST be included.
4550+ */
4551+
4552+/*
4553+ * PTB - The functions below just impose our own stricter size limit before
4554+ * - calling the defaults if all seems OK sizewise.
4555+ */
4556+ nbd_queue->merge_requests_fn = &nbd_merge_requests_fn;
4557+ nbd_queue->front_merge_fn = &nbd_front_merge_fn;
4558+ nbd_queue->back_merge_fn = &nbd_back_merge_fn;
4559+
4560+ nbd_init_md(&nbd_md);
4561+ nbd_init_ioctl_stub(&nbd_remote_ioctl);
4562+
4563+ for (i = 0; i < MAX_NBD; i++) {
4564+ struct nbd_device *lo = &nbd_dev[i];
4565+ nbd_reset(lo, i);
4566+ }
4567+
4568+ /*
4569+ * PTB we do the disk and partition stuff after we have
4570+ * contact, when nbd_open is called for the first time?
4571+ */
4572+
4573+ res = create_proc_read_entry ("nbdinfo", 0, NULL, NULL, NULL);
4574+ if (!res) {
4575+ NBD_ALERT ("creation of proc entry failed\n");
4576+ return -EINVAL;
4577+ }
4578+ // PTB additional write_proc entry in struct
4579+ nbd_init_proc(res);
4580+
4581+ // PTB make the gendisk structs very late.
4582+ for (i = 0; i < MAX_NBD; i++) {
4583+ struct nbd_device *lo = &nbd_dev[i];
4584+ nbd_set_disk(lo, i * NBD_MAXCONN, NBD_MAXCONN);
4585+ }
4586+
4587+#ifdef CONFIG_DEVFS_FS
4588+
4589+ devfs_handle = devfs_mk_dir (NULL, "nd", NULL);
4590+ if (devfs_handle) {
4591+ for (i = 0; i < MAX_NBD; i++) {
4592+ struct nbd_device *lo = &nbd_dev[i];
4593+ int j;
4594+ // PTB make the subdirectory "a","b" etc.
4595+ devfs_handles[i] =
4596+ devfs_mk_dir (devfs_handle, lo->devnam, NULL);
4597+ // PTB add the blk specials, "0","1" to NBD_MAXCONN-1
4598+ if (!devfs_handles[i])
4599+ continue;
4600+ for (j = 0; j < MAX_NBD; j++) {
4601+ char name[4];
4602+ sprintf (name, "%u", j);
4603+ devfs_register(devfs_handles[i], name,
4604+ DEVFS_FL_DEFAULT,
4605+ major, i * NBD_MAXCONN + j,
4606+ S_IFBLK | S_IRUSR | S_IWUSR,
4607+ &nbd_blkops, NULL);
4608+ }
4609+ // PTB do the whole disk symlink ..
4610+ devfs_mk_symlink (devfs_handles[i], "disk",
4611+ DEVFS_FL_DEFAULT, "0",
4612+ NULL, NULL);
4613+ // PTB .. and the channel symlinks
4614+ for (j = 1; j < MAX_NBD; j++) {
4615+ char link[4];
4616+ char name[8];
4617+ sprintf (link, "%u", j);
4618+ sprintf (name, "chan%u", j);
4619+ devfs_mk_symlink (devfs_handles[i],
4620+ name,
4621+ DEVFS_FL_DEFAULT,
4622+ link, NULL, NULL);
4623+ }
4624+ }
4625+ }
4626+#endif /* CONFIG_DEVFS_FS */
4627+
4628+ // PTB - sysctl interface
4629+ nbd_table_header = register_sysctl_table (nbd_root_table, 1);
4630+
4631+ // PTB we have to wait for the open to complete init with inode val
4632+
4633+ return err;
4634+}
4635+
4636+void __exit
4637+nbd_cleanup (void)
4638+{
4639+ int i;
4640+
4641+ for (i = 0; i < MAX_NBD; i++) {
4642+
4643+ struct nbd_device *lo = &nbd_dev[i];
4644+ int j;
4645+
4646+ if (!(atomic_read (&lo->flags) & NBD_INITIALISED))
4647+ continue;
4648+
4649+ NBD_INFO ("invalidating buffers on device nd%s%d-%d\n",
4650+ lo->devnam, 0, NBD_MAXCONN);
4651+
4652+ for (j = 0; j < NBD_MAXCONN; j++) {
4653+ int minor = i * NBD_MAXCONN + j;
4654+ invalidate_buffers (mk_kdev (major, minor));
4655+ }
4656+
4657+ NBD_INFO ("destroying buffers on device nd%s%d-%d\n",
4658+ lo->devnam, 0, NBD_MAXCONN);
4659+
4660+ for (j = 0; j < NBD_MAXCONN; j++) {
4661+ int minor = i * NBD_MAXCONN + j;
4662+ __invalidate_buffers (mk_kdev (major, minor), 1);
4663+ }
4664+ }
4665+
4666+ unregister_sysctl_table (nbd_table_header);
4667+
4668+#ifdef CONFIG_DEVFS_FS
4669+ if (devfs_handle) {
4670+ for (i = 0; i < MAX_NBD; i++) {
4671+ int j;
4672+ if (!devfs_handles[i])
4673+ continue;
4674+ for (j = 0; j < NBD_MAXCONN; j++) {
4675+ char s[3];
4676+ s[0] = '0' + j;
4677+ s[1] = 0;
4678+ if (j >= 10) {
4679+ s[0] = '1';
4680+ s[1] = '0' + (j - 10);
4681+ s[2] = 0;
4682+ }
4683+ devfs_remove("nd/%s/%u", device_letter(i), j);
4684+ if (j == 0) {
4685+ devfs_remove("nd/%s/disk", device_letter(i));
4686+ } else {
4687+ devfs_remove("nd/%s/chan%u",device_letter(i),j);
4688+ }
4689+ }
4690+ devfs_remove("nd/%s", device_letter(i));
4691+ }
4692+ devfs_remove("nd");
4693+ }
4694+#endif
4695+
4696+ remove_proc_entry ("nbdinfo", &proc_root);
4697+
4698+ for (i = 0; i < MAX_NBD; i++) {
4699+ struct nbd_device *lo = &nbd_dev[i];
4700+ atomic_clear_mask (NBD_ENABLED, &lo->flags);
4701+ if (lo->disk) {
4702+ del_gendisk(lo->disk);
4703+ put_disk(lo->disk);
4704+ }
4705+ if (lo->blockmap) {
4706+ kfree (lo->blockmap);
4707+ lo->blockmap = NULL;
4708+ }
4709+ nbd_sync_sync (lo);
4710+ }
4711+
4712+ blk_cleanup_queue (nbd_queue);
4713+
4714+ if (unregister_blkdev (major, "nbd") != 0) {
4715+ NBD_ALERT ("cleanup_module failed\n");
4716+ } else {
4717+ NBD_INFO ("module cleaned up.\n");
4718+ }
4719+ kfree(nbd_queue);
4720+
4721+}
4722+
4723+module_init (nbd_init);
4724+module_exit (nbd_cleanup);
4725+
4726+EXPORT_SYMBOL(nbd_remote_ioctl);
4727+
4728+/* Compile line:
4729+
4730+ * gcc -O2 -D__KERNEL__ -DMODULE -DEXPORT_SYMTAB -xc -c enbd.c -o enbd.o
4731+ *
4732+ * (possibly with -DMODVERSIONS also). PTB
4733+ * (possibly with -I/usr/src/linux-x.y.z/include also). PTB
4734+ */
3e18f7ab 4735diff -Nur linux-2.6.0-test5.org/drivers/block/enbd/enbd_base.mod.c linux-2.6.0-test5/drivers/block/enbd/enbd_base.mod.c
4736--- linux-2.6.0-test5.org/drivers/block/enbd/enbd_base.mod.c Thu Jan 1 00:00:00 1970
4737+++ linux-2.6.0-test5/drivers/block/enbd/enbd_base.mod.c Mon Mar 24 21:51:59 2003
4738@@ -0,0 +1,13 @@
4739+#include <linux/module.h>
4740+#include <linux/vermagic.h>
4741+#include <linux/compiler.h>
4742+
4743+const char vermagic[]
4744+__attribute__((section("__vermagic"))) =
4745+VERMAGIC_STRING;
4746+
4747+static const char __module_depends[]
4748+__attribute_used__
4749+__attribute__((section(".modinfo"))) =
4750+"depends=";
4751+
4752diff -Nur linux-2.6.0-test5.org/drivers/block/enbd/enbd_ioctl.c linux-2.6.0-test5/drivers/block/enbd/enbd_ioctl.c
4753--- linux-2.6.0-test5.org/drivers/block/enbd/enbd_ioctl.c Thu Jan 1 00:00:00 1970
4754+++ linux-2.6.0-test5/drivers/block/enbd/enbd_ioctl.c Tue Mar 25 14:33:55 2003
d912b53b 4755@@ -0,0 +1,405 @@
4756+#ifndef __KERNEL__
4757+#include <sys/time.h>
4758+#include <unistd.h>
4759+#endif
4760+
4761+#include <linux/ioctl.h>
4762+#include <linux/fs.h>
4763+#include <linux/fd.h>
4764+#ifndef _CADDR_T
4765+#define caddr_t char*
4766+#endif
4767+#include <linux/cdrom.h>
4768+#include <asm/uaccess.h>
4769+#include <linux/module.h>
4770+#include <linux/version.h>
4771+#include <linux/init.h>
4772+#ifndef KERNEL_VERSION
4773+#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
4774+#endif
4775+#include <linux/blk.h>
4776+#include <linux/enbd.h>
4777+#include <linux/enbd_ioctl.h>
4778+
4779+
4780+/*
4781+ * This is the whitelist of remote ioctls - an entry here tells the
4782+ * driver that it's OK to send this ioctl out over the net, because we
4783+ * have the right info on it.
4784+ *
4785+ * "The right info" is what is on the right hand side of the table (a 0
4786+ * stands for a repetition of the LHS info). We have to fixup something
4787+ * that a lot of kernel authors forgot to do or got worng - namely
4788+ * declare their ioctls in a way that conveys information about their
4789+ * intended mode of use (see iotcl.h in the kernel sources).
4790+ *
4791+ * We need all ioctls to be delared as either
4792+ *
4793+ * _IO(class,id) -- default. Means no args. The call is enough.
4794+ * _IOW(class,id,type) -- we write a value to kernel that is sizeof(type)
4795+ * _IOR(class,id,type) -- we read a value from kernel sizeof(type)
4796+ * _IOWR(class,id,type) -- ibid, but both ways
4797+ *
4798+ * The "R" bit is crucial because it lets us know that the data is
4799+ * _indirected_. I.e. it's an address of somewhere in userspace where
4800+ * we want to read data from or write data to.
4801+ *
4802+ * The "type" part should be the type of the indirected argument, NOT
4803+ * the type of its address!
4804+ *
4805+ * Kernel authors typically make two mistakes:
4806+ *
4807+ * 1) they write _IO instead of _IOR or IOWR, and hence forget the
4808+ * type info. Well, not telling me if the argument data is
4809+ * direct or indirectly accessible was already bad enough!
4810+ * 2) they get the type argument _wrong_ when they do remember to
4811+ * put it. They write "int *" instead of "int", for example,
4812+ * when the argument to the ioctl is a pointer to an integer.
4813+ * OK, so it's a natural mistake to make! But in that case the
4814+ * argument should be "int" so that the kernel macro picks up
4815+ * sizeof(int) instead of sizeof(int*).
4816+ *
4817+ * Those "errors" have to be repaired via this table. Wrong at left,
4818+ * corrected at right. A 0 for the new entry indicates that the old
4819+ * was alright. If there isn't an entry, the ioctl won't be treated.
4820+ * If the size info works out at the max for the field (2^14 - 1)
4821+ * then a extra table is consulted for size and copy methods.
4822+ */
4823+
4824+
4825+/*
4826+ * PTB the space before the final comma is important as the ##
4827+ * discards the preceding token when D is empty
4828+ */
4829+#define _NEW_IO_(B,C,D...) C(_IOC_TYPE(B), _IOC_NR(B) , ## D)
4830+#define _NEW_IO(B,D...) _IO(_IOC_TYPE(B), _IOC_NR(B) , ## D)
4831+#define _NEW_IOW(B,D...) _IOW(_IOC_TYPE(B), _IOC_NR(B) , ## D)
4832+#define _NEW_IOR(B,D...) _IOR(_IOC_TYPE(B), _IOC_NR(B) , ## D)
4833+#define _NEW_IOWR(B,D...) _IOWR(_IOC_TYPE(B), _IOC_NR(B) , ## D)
4834+#define _NEW_IORS(B) _IOC(_IOC_READ,_IOC_TYPE(B), _IOC_NR(B), _IOC_SIZEMASK)
4835+#define _NEW_IOWRS(B) _IOC(_IOC_READ|_IOC_WRITE,_IOC_TYPE(B), _IOC_NR(B), _IOC_SIZEMASK)
4836+
4837+static struct ioctl_conv ioctl_conv_tab[] = {
4838+// fs.h
4839+ { BLKROSET, _NEW_IOW(BLKROSET,int), },
4840+ { BLKROGET, _NEW_IOR(BLKROGET,int), },
4841+//#define BLKRRPART _IO(0x12,95) /* re-read partition table */
4842+ { BLKRRPART, 0, },
4843+ { BLKGETSIZE, _NEW_IOR(BLKGETSIZE,int), },
4844+//#define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
4845+ { BLKFLSBUF, 0, },
4846+ { BLKRASET, _NEW_IOW(BLKRASET,int), },
4847+ { BLKRAGET, _NEW_IOR(BLKRAGET,int), },
4848+ { BLKFRASET, _NEW_IOW(BLKFRASET,int), },
4849+ { BLKFRAGET, _NEW_IOR(BLKFRAGET,int), },
4850+ { BLKSECTSET, _NEW_IOW(BLKSECTSET,int), },
4851+ { BLKSECTGET, _NEW_IOR(BLKSECTGET,int), },
4852+ { BLKSSZGET, _NEW_IOR(BLKSSZGET,int), },
4853+// fd.h
4854+ { FDCLRPRM, 0, },
4855+ { FDSETPRM, _NEW_IOWR(FDSETPRM, struct floppy_struct), },
4856+ { FDDEFPRM, _NEW_IOWR(FDDEFPRM, struct floppy_struct), },
4857+ { FDGETPRM, _NEW_IOR(FDGETPRM, struct floppy_struct), },
4858+ { FDMSGON, 0, },
4859+ { FDMSGOFF, 0, },
4860+ { FDFMTBEG, 0, },
4861+ { FDFMTTRK, _NEW_IOWR(FDFMTTRK, struct format_descr), },
4862+ { FDFMTEND, 0, },
4863+ { FDSETEMSGTRESH, _NEW_IOW(FDSETEMSGTRESH, unsigned), },
4864+ { FDFLUSH, 0, },
4865+ { FDSETMAXERRS, _NEW_IOWR(FDSETMAXERRS, struct floppy_max_errors), },
4866+ { FDGETMAXERRS, _NEW_IOR(FDGETMAXERRS, struct floppy_max_errors), },
4867+ { FDGETDRVTYP, _NEW_IOR(FDGETDRVTYP, floppy_drive_name), }, // 16 bytes
4868+ { FDSETDRVPRM, _NEW_IOWR(FDSETDRVPRM, struct floppy_drive_params), },
4869+ { FDGETDRVPRM, _NEW_IOR(FDGETDRVPRM, struct floppy_drive_params), },
4870+ { FDGETDRVSTAT, _NEW_IOR(FDGETDRVSTAT, struct floppy_drive_struct), },
4871+ { FDPOLLDRVSTAT, _NEW_IOR(FDPOLLDRVSTAT, struct floppy_drive_struct), },
4872+ { FDRESET, 0, },
4873+ { FDGETFDCSTAT, _NEW_IOR(FDGETFDCSTAT, struct floppy_fdc_state), },
4874+ { FDWERRORCLR, 0, },
4875+ { FDWERRORGET, _NEW_IOR(FDWERRORGET, struct floppy_write_errors), },
4876+ { FDRAWCMD, _NEW_IOWR(FDRAWCMD, struct floppy_raw_cmd[1]) }, // FIXME linked list
4877+ { FDTWADDLE, 0, },
4878+ { FDEJECT, 0, },
4879+// cdrom.h
4880+ { CDROMPAUSE, _NEW_IO(CDROMPAUSE), },
4881+ { CDROMRESUME, _NEW_IO(CDROMRESUME), },
4882+ { CDROMPLAYMSF, _NEW_IOR(CDROMPLAYMSF, struct cdrom_msf), },
4883+ { CDROMPLAYTRKIND, _NEW_IOR(CDROMPLAYTRKIND, struct cdrom_ti), },
4884+ { CDROMREADTOCHDR, _NEW_IOWR(CDROMREADTOCHDR, struct cdrom_tochdr), },
4885+ { CDROMREADTOCENTRY, _NEW_IOWR(CDROMREADTOCENTRY, struct cdrom_tocentry), },
4886+ { CDROMSTOP, _NEW_IO(CDROMSTOP), },
4887+ { CDROMSTART, _NEW_IO(CDROMSTART), },
4888+ { CDROMEJECT, _NEW_IO(CDROMEJECT), },
4889+ { CDROMVOLCTRL, _NEW_IOR(CDROMVOLCTRL, struct cdrom_volctrl), },
4890+ { CDROMSUBCHNL, _NEW_IOWR(CDROMSUBCHNL, struct cdrom_subchnl), },
4891+ { CDROMREADMODE2, _NEW_IOR(CDROMREADMODE2, struct cdrom_read), }, // INDIRECT 2336B
4892+ { CDROMREADMODE1, _NEW_IOR(CDROMREADMODE1, struct cdrom_read), }, // INDIRECT 2048B
4893+ { CDROMREADAUDIO, _NEW_IOR(CDROMREADAUDIO, struct cdrom_read_audio), },
4894+ { CDROMEJECT_SW, _NEW_IO(CDROMEJECT_SW), },
4895+ { CDROMMULTISESSION, _NEW_IOWR(CDROMMULTISESSION, struct cdrom_multisession), },
4896+ { CDROM_GET_MCN, _NEW_IOWR(CDROM_GET_MCN, struct cdrom_mcn), },
4897+ { CDROMRESET, _NEW_IO(CDROMRESET), },
4898+ { CDROMVOLREAD, _NEW_IOWR(CDROMVOLREAD, struct cdrom_volctrl), },
4899+ { CDROMREADRAW, _NEW_IOR(CDROMREADRAW, struct cdrom_read), }, // INDIRECT 2352B
4900+ // aztcd.c optcd.c
4901+ { CDROMREADCOOKED, _NEW_IOR(CDROMREADCOOKED, struct cdrom_msf), }, // INDIRECT FIXME
4902+ { CDROMSEEK, _NEW_IOR(CDROMSEEK, struct cdrom_msf), },
4903+ // scsi-cd.c
4904+ { CDROMPLAYBLK, _NEW_IOWR(CDROMPLAYBLK, struct cdrom_blk), },
4905+ // optcd.c
4906+ { CDROMREADALL, _NEW_IOR(CDROMREADALL, char[2646]), },
4907+ // ide-cd.c
4908+ { CDROMGETSPINDOWN, _NEW_IOWR(CDROMGETSPINDOWN, char), }, // one byte
4909+ { CDROMSETSPINDOWN, _NEW_IOWR(CDROMSETSPINDOWN, char), }, // one byte
4910+ // cdrom.c
4911+ { CDROMCLOSETRAY, _NEW_IO(CDROMCLOSETRAY), },
4912+ { CDROM_SET_OPTIONS, _NEW_IOW(CDROM_SET_OPTIONS, int), },
4913+ { CDROM_CLEAR_OPTIONS, _NEW_IOW(CDROM_CLEAR_OPTIONS, int), },
4914+ { CDROM_SELECT_SPEED, _NEW_IOW(CDROM_SELECT_SPEED, int), }, // FIXME
4915+ { CDROM_SELECT_DISC, _NEW_IOW(CDROM_SELECT_DISC, int), },
4916+ { CDROM_MEDIA_CHANGED, _NEW_IOW(CDROM_MEDIA_CHANGED, int), },
4917+ { CDROM_DRIVE_STATUS, _NEW_IOW(CDROM_DRIVE_STATUS, int), },
4918+ { CDROM_DISC_STATUS, _NEW_IO(CDROM_DISC_STATUS), },
4919+ { CDROM_CHANGER_NSLOTS, _NEW_IO(CDROM_CHANGER_NSLOTS), },
4920+ { CDROM_LOCKDOOR, _NEW_IOW(CDROM_LOCKDOOR, int), },
4921+ { CDROM_DEBUG, _NEW_IOW(CDROM_DEBUG, int), },
4922+ { CDROM_GET_CAPABILITY, _NEW_IO(CDROM_GET_CAPABILITY), },
4923+ // sbpcd
4924+ { CDROMAUDIOBUFSIZ, _NEW_IOW(CDROMAUDIOBUFSIZ, int), },
4925+ // dvd
4926+ { DVD_READ_STRUCT, _NEW_IOR(DVD_READ_STRUCT, dvd_struct), },
4927+ { DVD_WRITE_STRUCT, _NEW_IOWR(DVD_WRITE_STRUCT, dvd_struct), },
4928+ { DVD_AUTH, _NEW_IOWR(DVD_AUTH, dvd_authinfo), },
4929+ { CDROM_SEND_PACKET, _NEW_IOR(CDROM_SEND_PACKET, struct cdrom_generic_command), },
4930+ { CDROM_NEXT_WRITABLE, _NEW_IOWR(CDROM_NEXT_WRITABLE, long), },
4931+ { CDROM_LAST_WRITTEN, _NEW_IOWR(CDROM_LAST_WRITTEN, long), },
4932+ // PTB local test ioctls
4933+ { NBD_TEST_IOCTL1, 0, }, // write an int
4934+ { NBD_TEST_IOCTL2, 0, }, // read an int
4935+ { NBD_TEST_IOCTL3, 0, }, // write and read an int
4936+ { NBD_TEST_IOCTL4, 0, }, // read 256B
4937+ { NBD_TEST_IOCTL5, 0, }, // r/w 256B
4938+ { NBD_TEST_IOCTL6, _NEW_IORS(NBD_TEST_IOCTL6), }, // read special
4939+ { NBD_TEST_IOCTL7, _NEW_IORS(NBD_TEST_IOCTL7), }, // r/w special
4940+ // PTB we must terminate with a 0,0 entry.
4941+ {0 , 0, },
4942+};
4943+
4944+/*
4945+ * This should be the table of special methods for certain ioctls.
4946+ * The "new" code is the real index. It will have a size count of
4947+ * _IOC_SIZEMASK but the rest of it should be meaningful. The size is
4948+ * gotten by dynamic lookup using the size() function.
4949+ */
4950+static struct ioctl_special ioctl_special_tab[] = {
4951+ // PTB last entry must be all zeros
4952+ { 0, NULL, NULL, NULL, NULL, },
4953+};
4954+
4955+
4956+static struct ioctl_conv *
4957+ioctl_lookup_old (int ioctl)
4958+{
4959+ int i;
4960+ unsigned old;
4961+ if (ioctl == -1)
4962+ return NULL;
4963+ for (i = 0; old = ioctl_conv_tab[i].old, old; i++) {
4964+ if (old == ioctl)
4965+ return &ioctl_conv_tab[i];
4966+ }
4967+ // PTB not there
4968+ return NULL;
4969+}
4970+
4971+int
4972+nbd_ioctl_convert (int ioctl)
4973+{
4974+ struct ioctl_conv *conv = ioctl_lookup_old (ioctl);
4975+ if (!conv)
4976+ // PTB not there
4977+ return -1;
4978+ return conv->new ? : ioctl;
4979+}
4980+
4981+int
4982+nbd_ioctl_convert_inplace(int *ioctl) {
4983+
4984+ int new_ioctl;
4985+ if (!ioctl)
4986+ return -EINVAL;
4987+ new_ioctl = nbd_ioctl_convert(*ioctl);
4988+ if (new_ioctl == -1)
4989+ return -EINVAL;
4990+ *ioctl = new_ioctl;
4991+ return 0;
4992+}
4993+
4994+static struct ioctl_conv *
4995+ioctl_lookup_new (int ioctl)
4996+{
4997+ int i = 0;
4998+ unsigned old;
4999+ for (i = 0; old = ioctl_conv_tab[i].old, old; i++) {
5000+ unsigned new = ioctl_conv_tab[i].new;
5001+ if (new == ioctl || (new == 0 && old == ioctl))
5002+ return &ioctl_conv_tab[i];
5003+ }
5004+ // PTB not there
5005+ return NULL;
5006+}
5007+
5008+int
5009+nbd_ioctl_revert (int ioctl)
5010+{
5011+ struct ioctl_conv *conv = ioctl_lookup_new (ioctl);
5012+ if (!conv)
5013+ // PTB not there
5014+ return -1;
5015+ return conv->old;
5016+}
5017+
5018+static struct ioctl_special *
5019+ioctl_special_lookup_new (int ioctl)
5020+{
5021+ int i;
5022+ unsigned new;
5023+ for (i = 0; new = ioctl_special_tab[i].new, new; i++) {
5024+ if (new == ioctl)
5025+ return &ioctl_special_tab[i];
5026+ }
5027+ // PTB not there
5028+ return NULL;
5029+}
5030+
5031+int
5032+nbd_ioctl_size (int cmd, char *arg)
5033+{
5034+ int size = _IOC_SIZE (cmd);
5035+ if (size == _IOC_SIZEMASK) {
5036+ // PTB special hadling required.
5037+ struct ioctl_special *special = ioctl_special_lookup_new(cmd);
5038+ if (!special)
5039+ return -1;
5040+ return special->size (arg);
5041+ }
5042+ return size;
5043+}
5044+
5045+int
5046+nbd_ioctl_size_user (int cmd, char *arg)
5047+{
5048+ int size = _IOC_SIZE (cmd);
5049+ if (size == _IOC_SIZEMASK) {
5050+ // PTB special hadling required.
5051+ struct ioctl_special *special = ioctl_special_lookup_new(cmd);
5052+ if (!special)
5053+ return -1;
5054+ return special->size_user (arg);
5055+ }
5056+ return size;
5057+}
5058+
5059+
5060+#ifdef __KERNEL__
5061+int
5062+nbd_ioctl_copy_to_user (int cmd, char *arg, char *buf, int size)
5063+{
5064+
5065+ if (_IOC_SIZE (cmd) == _IOC_SIZEMASK) {
5066+ struct ioctl_special *special = ioctl_special_lookup_new(cmd);
5067+ if (!special)
5068+ return -1;
5069+ return special->ioctl_copy_to_user (arg, buf, size);
5070+ }
5071+
5072+ if (_IOC_DIR (cmd) & _IOC_READ) {
5073+ // indirect
5074+ copy_to_user (arg, buf, size);
5075+ return size;
5076+ }
5077+
5078+ return -1;
5079+}
5080+
5081+
5082+
5083+int
5084+nbd_ioctl_copy_from_user (int cmd, char *buf, char *arg, int size)
5085+{
5086+
5087+ if (_IOC_SIZE (cmd) == _IOC_SIZEMASK) {
5088+ struct ioctl_special *special = ioctl_special_lookup_new(cmd);
5089+ if (!special)
5090+ return -1;
5091+ return special->ioctl_copy_from_user (buf, arg, size);
5092+ }
5093+
5094+ if (_IOC_DIR (cmd) & _IOC_READ) {
5095+ // indirect
5096+ copy_from_user (buf, arg, size);
5097+ return size;
5098+ }
5099+
5100+ // direct
5101+ if (size > sizeof (arg)) {
5102+ return -1;
5103+ }
5104+
5105+ memcpy (buf, &arg, size);
5106+ return size;
5107+}
5108+
5109+static struct nbd_ioctl struct_ioctl = {
5110+ convert : nbd_ioctl_convert,
5111+ convert_inplace : nbd_ioctl_convert_inplace,
5112+ revert : nbd_ioctl_revert,
5113+ size : nbd_ioctl_size,
5114+ size_user : nbd_ioctl_size_user,
5115+ cp_to_user : nbd_ioctl_copy_to_user,
5116+ cp_from_user : nbd_ioctl_copy_from_user,
5117+};
5118+
5119+static int __init
5120+nbd_ioctl_init (void)
5121+{
5122+ struct nbd_ioctl_stub * remote_ioctl = &nbd_remote_ioctl;
5123+ remote_ioctl->reg(remote_ioctl, &struct_ioctl);
5124+ return 0;
5125+}
5126+
5127+static void __exit
5128+nbd_ioctl_cleanup (void) {
5129+ struct nbd_ioctl_stub * remote_ioctl = &nbd_remote_ioctl;
5130+ remote_ioctl->unreg(remote_ioctl, &struct_ioctl);
5131+}
5132+
5133+module_init (nbd_ioctl_init);
5134+module_exit (nbd_ioctl_cleanup);
5135+
5136+int linux_version_code = LINUX_VERSION_CODE;
5137+
5138+#ifdef MODULE
5139+ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0)
5140+ MODULE_AUTHOR ("Peter T. Breuer");
5141+ MODULE_DESCRIPTION ("Enhanced Network Block Device Remote Ioctl");
5142+ #ifdef MODULE_LICENSE
5143+ MODULE_LICENSE("GPL");
5144+ #endif
5145+ #endif
5146+#endif /* MODULE */
5147+
5148+#endif /* __KERNEL__ */
5149+
5150+
5151+/*
5152+static
5153+int ioctl_init(struct ioctl_conv *self, int old, int new) {
5154+ self->old = old;
5155+ self->new = new;
5156+ self->serialize = ioctl_serialize;
5157+ self->deserialize = ioctl_deserialize;
5158+ self->size = ioctl_size;
5159+}
5160+*/
3e18f7ab 5161diff -Nur linux-2.6.0-test5.org/drivers/block/enbd/enbd_ioctl.mod.c linux-2.6.0-test5/drivers/block/enbd/enbd_ioctl.mod.c
5162--- linux-2.6.0-test5.org/drivers/block/enbd/enbd_ioctl.mod.c Thu Jan 1 00:00:00 1970
5163+++ linux-2.6.0-test5/drivers/block/enbd/enbd_ioctl.mod.c Mon Mar 24 21:51:59 2003
5164@@ -0,0 +1,13 @@
5165+#include <linux/module.h>
5166+#include <linux/vermagic.h>
5167+#include <linux/compiler.h>
5168+
5169+const char vermagic[]
5170+__attribute__((section("__vermagic"))) =
5171+VERMAGIC_STRING;
5172+
5173+static const char __module_depends[]
5174+__attribute_used__
5175+__attribute__((section(".modinfo"))) =
5176+"depends=enbd";
5177+
5178diff -Nur linux-2.6.0-test5.org/drivers/block/enbd/enbd_ioctl_stub.c linux-2.6.0-test5/drivers/block/enbd/enbd_ioctl_stub.c
5179--- linux-2.6.0-test5.org/drivers/block/enbd/enbd_ioctl_stub.c Thu Jan 1 00:00:00 1970
5180+++ linux-2.6.0-test5/drivers/block/enbd/enbd_ioctl_stub.c Mon Mar 24 21:51:59 2003
d912b53b 5181@@ -0,0 +1,30 @@
5182+
5183+#include <linux/stddef.h>
5184+#include <linux/errno.h>
5185+#include <linux/enbd.h>
5186+#include <linux/enbd_ioctl.h>
5187+
5188+ /*
5189+ * PTB this is the hook for the enbd_ioctl extra module
5190+ */
5191+ static int register_remote_ioctl(struct nbd_ioctl_stub *remote_ioctl, struct nbd_ioctl *x) {
5192+ if (!remote_ioctl->remote) {
5193+ remote_ioctl->remote = x;
5194+ return 0;
5195+ }
5196+ return -EINVAL;
5197+ }
5198+ static int unregister_remote_ioctl(struct nbd_ioctl_stub *remote_ioctl, struct nbd_ioctl *x) {
5199+ if (remote_ioctl->remote != x)
5200+ return -EINVAL;
5201+ remote_ioctl->remote = NULL;
5202+ return 0;
5203+ }
5204+
5205+int nbd_init_ioctl_stub(struct nbd_ioctl_stub *remote_ioctl) {
5206+ memset(remote_ioctl, 0, sizeof(*remote_ioctl));
5207+ remote_ioctl->reg = register_remote_ioctl;
5208+ remote_ioctl->unreg = unregister_remote_ioctl;
5209+ return 0;
5210+}
5211+
3e18f7ab 5212diff -Nur linux-2.6.0-test5.org/drivers/block/enbd/enbd_md.c linux-2.6.0-test5/drivers/block/enbd/enbd_md.c
5213--- linux-2.6.0-test5.org/drivers/block/enbd/enbd_md.c Thu Jan 1 00:00:00 1970
5214+++ linux-2.6.0-test5/drivers/block/enbd/enbd_md.c Mon Mar 24 21:51:59 2003
d912b53b 5215@@ -0,0 +1,99 @@
5216+#include <linux/enbd.h>
5217+#include <linux/enbd_ioctl.h>
5218+
5219+/*
5220+ * PTB small driver wide support database for MDRGTR ioctl
5221+ */
5222+
5223+
5224+
5225+#ifndef HOT_ADD_DISK
5226+ #define HOT_ADD_DISK _IO (MD_MAJOR, 0x28)
5227+#endif
5228+#ifndef SET_DISK_FAULTY
5229+ #define SET_DISK_FAULTY _IO (MD_MAJOR, 0x29)
5230+#endif
5231+
5232+static void
5233+nbd_md_dec (struct nbd_md *md) {
5234+ down(&md->access_sem);
5235+ if (--md->count <= 0)
5236+ md->notify_fn = NULL;
5237+ up(&md->access_sem);
5238+}
5239+static void
5240+nbd_md_inc (struct nbd_md *md) {
5241+ down(&md->access_sem);
5242+ md->count++;
5243+ up(&md->access_sem);
5244+}
5245+static void
5246+nbd_md_reg (struct nbd_md *md, int(*fn)(kdev_t, int)) {
5247+ down(&md->access_sem);
5248+ if (!md->notify_fn) {
5249+ md->notify_fn = fn;
5250+ md->count++;
5251+ }
5252+ up(&md->access_sem);
5253+}
5254+
5255+/*
5256+ * PTB tell md devices in which we are embedded that we are alright
5257+ *
5258+ * @lo the nbd device to tell them about
5259+ */
5260+static int
5261+nbd_notify_md_devices (struct nbd_md *md, kdev_t nbd_dev)
5262+{
5263+ //kdev_t nbd_dev = mk_kdev (major, nbd << NBD_SHIFT);
5264+ int err;
5265+
5266+ down (&md->access_sem);
5267+ if (md->count > 0 && md->notify_fn) {
5268+ NBD_ALERT ("adding %x:%x to raid devices via fn\n",
5269+ major(nbd_dev), minor(nbd_dev));
5270+ err = md->notify_fn (nbd_dev, HOT_ADD_DISK);
5271+ if (err < 0) {
5272+ NBD_ALERT ("HOT_ADD to raid devices returned %d\n",
5273+ err);
5274+ }
5275+ }
5276+ up (&md->access_sem);
5277+
5278+ return 0;
5279+}
5280+
5281+static int
5282+nbd_unnotify_md_devices (struct nbd_md *md, kdev_t nbd_dev)
5283+{
5284+
5285+ // kdev_t nbd_dev = mk_kdev (major, lo->nbd << NBD_SHIFT);
5286+ int err;
5287+
5288+ down (&md->access_sem);
5289+ if (md->count > 0 && md->notify_fn) {
5290+ NBD_ALERT ("erasing %x:%x from raid devices via fn\n",
5291+ major(nbd_dev), minor(nbd_dev));
5292+ err = md->notify_fn (nbd_dev, SET_DISK_FAULTY);
5293+ if (err < 0) {
5294+ NBD_ALERT
5295+ ("SETFAULTY to raid devices returned %d\n", err);
5296+ }
5297+ }
5298+ up (&md->access_sem);
5299+ return 0;
5300+}
5301+
5302+void
5303+nbd_init_md(struct nbd_md *md)
5304+{
5305+ md->notify_fn = NULL;
5306+ md->count = 0;
5307+ init_MUTEX(&md->access_sem);
5308+ md->notify = nbd_notify_md_devices;
5309+ md->unnotify = nbd_unnotify_md_devices;
5310+ md->dec = nbd_md_dec;
5311+ md->inc = nbd_md_inc;
5312+ md->reg = nbd_md_reg;
5313+}
5314+
3e18f7ab 5315diff -Nur linux-2.6.0-test5.org/drivers/block/enbd/enbd_proc.c linux-2.6.0-test5/drivers/block/enbd/enbd_proc.c
5316--- linux-2.6.0-test5.org/drivers/block/enbd/enbd_proc.c Thu Jan 1 00:00:00 1970
5317+++ linux-2.6.0-test5/drivers/block/enbd/enbd_proc.c Tue Mar 25 22:23:57 2003
5318@@ -0,0 +1,1033 @@
d912b53b 5319+
5320+#include <linux/enbd.h>
5321+#include <linux/proc_fs.h>
5322+
5323+extern struct nbd_device * nbd_get(int i);
5324+
5325+static void
5326+do_reset (int reset, int i) {
5327+
5328+ void do_r (void) {
5329+ struct nbd_device *lo = nbd_get(i);
5330+ if (reset != 0) {
5331+ lo->reset (lo, i);
5332+ return;
5333+ };
5334+ };
5335+ if (i >= 0 && i < MAX_NBD) {
5336+ do_r ();
5337+ return;
5338+ }
5339+}
5340+
5341+/*
5342+ * PTB This is just to get a nice limited width integer printout in proc!
5343+ * use endpos (<= 8) spaces at most. We serve from a static buffer size 16.
5344+ */
5345+char *
5346+display (unsigned n, int endpos)
5347+{
5348+ // PTB use endpos (<= 8) spaces at most
5349+ static char buf[16];
5350+ int units = 0;
5351+ int decimals = 0;
5352+ int decpos = endpos;
5353+ int wholepart = n, fractionpart = 0;
5354+ buf[endpos--] = 0;
5355+ // PTB find the right units to display. U or K or M or G.
5356+ while (n >= 1 << 10) {
5357+ decimals = n & ((1 << 10) - 1);
5358+ n >>= 10;
5359+ units++;
5360+ }
5361+ switch (units) {
5362+ case 0:
5363+ break;
5364+ case 1:
5365+ buf[endpos--] = 'K';
5366+ break;
5367+ case 2:
5368+ buf[endpos--] = 'M';
5369+ break;
5370+ case 3:
5371+ buf[endpos--] = 'G';
5372+ break;
5373+ case 4:
5374+ buf[endpos--] = 'T';
5375+ break;
5376+ }
5377+ // after this wholepart = n && fractionpart = decimals
5378+ fractionpart = wholepart & ((1 << (units * 10)) - 1);
5379+ wholepart >>= units * 10;
5380+ // PTB write the whole digits (something between 0 and 1023 inclusive)
5381+ if (n == 0) {
5382+ buf[endpos--] = '0';
5383+ } else {
5384+ while (endpos >= 0 && n > 0) {
5385+ buf[endpos--] = '0' + n % 10;
5386+ n /= 10;
5387+ }
5388+ }
5389+ // PTB if there is space and cause, add decimal digits
5390+ if (endpos >= 1 && units > 0) {
5391+ int k = 0;
5392+ char unitchar = buf[--decpos];
5393+ buf[decpos + k++] = '.';
5394+ while (endpos >= k) {
5395+ int digit = (decimals * 10) >> 10;
5396+ buf[decpos + k++] = '0' + digit;
5397+ decimals -= (digit << 10) / 10;
5398+ decimals *= 10;
5399+ }
5400+ buf[decpos + k++] = unitchar;
5401+ buf[decpos + k] = 0;
5402+ }
5403+ // PTB report the start position
5404+ return buf + endpos + 1;
5405+}
5406+
5407+
5408+static void
5409+set_generic (int x, int i, int X)
5410+{
5411+ void set_x (void) {
5412+ struct nbd_device *lo = nbd_get(i);
5413+ if (lo->magic != NBD_DEV_MAGIC)
5414+ return;
5415+ if (x != 0) {
5416+ atomic_set_mask (X, &lo->flags);
5417+ return;
5418+ };
5419+ atomic_clear_mask (X, &lo->flags);
5420+ };
5421+
5422+ if (i >= 0 && i < MAX_NBD) {
5423+ set_x ();
5424+ return;
5425+ }
5426+ for (i = 0; i < MAX_NBD; i++) {
5427+ set_x ();
5428+ }
5429+}
5430+
5431+static void
5432+set_sync_intvl (int sync_intvl, int i)
5433+{
5434+ set_generic(sync_intvl, i, NBD_SYNC);
5435+}
5436+
5437+
5438+static void
5439+set_show_errs (int show_errs, int i)
5440+{
5441+ set_generic(show_errs, i, NBD_SHOW_ERRS);
5442+}
5443+
5444+static void
5445+set_md5sum (int md5sum, int i)
5446+{
5447+ set_generic(md5sum, i, NBD_MD5SUM);
5448+}
5449+
5450+
5451+static void
5452+set_enable (int enable, int i)
5453+{
5454+ void set_e (void) {
5455+ struct nbd_device *lo = nbd_get(i);
5456+ if (!lo || lo->magic != NBD_DEV_MAGIC)
5457+ return;
5458+ if (enable != 0) {
5459+ if (!(atomic_read (&lo->flags) & NBD_ENABLED)) {
5460+ lo->enable (lo);
5461+ return;
5462+ }
5463+ };
5464+ lo->disable (lo);
5465+ };
5466+
5467+ if (i >= 0 && i < MAX_NBD) {
5468+ set_e ();
5469+ return;
5470+ }
5471+ for (i = 0; i < MAX_NBD; i++) {
5472+ set_e ();
5473+ }
5474+}
5475+
5476+static void
5477+set_direct (int direct, int i)
5478+{
5479+ set_generic(direct, i, NBD_DIRECT);
5480+}
5481+
5482+#ifndef NO_BUFFERED_WRITES
5483+static void
5484+set_buffer_writes (int buffer_writes, int i)
5485+{
5486+ set_generic(buffer_writes, i, NBD_BUFFERWR);
5487+}
5488+#endif
5489+
5490+static void
5491+set_merge_requests (int mr, int i)
5492+{
5493+ void set_mr (void) {
5494+ struct nbd_device *lo = nbd_get(i);
5495+ if (lo->magic != NBD_DEV_MAGIC)
5496+ return;
5497+ atomic_set (&lo->merge_requests, mr);
5498+ }
5499+
5500+ if (i >= 0 && i < MAX_NBD) {
5501+ set_mr ();
5502+ return;
5503+ }
5504+ for (i = 0; i < MAX_NBD; i++) {
5505+ set_mr ();
5506+ }
5507+}
5508+
5509+int
5510+nbd_read_proc (char *buf, char **start, off_t offset, int len, int *eof,
5511+ void *data)
5512+{
5513+
5514+#ifndef MIN
5515+#define MIN(x,y) ((x)<(y)?(x):(y))
5516+#endif
5517+
5518+ const int limit = MIN (PAGE_SIZE, len) - 80;
5519+ static int i;
5520+ struct nbd_device *lo;
3e18f7ab 5521+ struct nbd_acct *acct;
d912b53b 5522+ static int last;
5523+ static void *next_label;
5524+ static char *next_label_name;
5525+ static int total;
5526+ unsigned long flags;
5527+
5528+ if (offset > 0 && !next_label) {
5529+ *eof = 1;
5530+ *start = buf;
5531+ return 0;
5532+ }
5533+
5534+ if (offset <= 0) {
5535+ // PTB do static inits first time through
5536+ last = -1;
5537+ i = 0;
5538+ next_label = NULL;
5539+ next_label_name = NULL;
5540+ total = 0;
5541+ }
5542+
5543+ // PTB start this bytecount
5544+ len = 0;
5545+
5546+#define NBD_PROC_LABEL(n) \
5547+ next_label = &&label_##n; \
5548+ next_label_name = "label_" #n; \
5549+ if (len > limit) { \
5550+ *start = (char *) (unsigned long) len; \
5551+ total += len; \
5552+ return len;\
5553+ } \
5554+ label_##n:
5555+
5556+ for ( /* static init */ ; i < MAX_NBD; i++) {
5557+
5558+ char *devnam;
5559+
5560+ lo = nbd_get(i);
5561+ devnam = lo->devnam;
3e18f7ab 5562+ acct = &lo->acct;
d912b53b 5563+ if (lo->nslot <= 0) {
5564+ next_label = NULL;
5565+ continue;
5566+ }
5567+
5568+ // PTB computed goto next not-done
5569+ if (next_label) {
5570+ void *label = next_label;
5571+ next_label = NULL;
5572+ next_label_name = NULL;
5573+ len = 0;
5574+ goto *label;
5575+ }
5576+
5577+ NBD_PROC_LABEL (1);
5578+
5579+ if (last == i - 2) {
5580+ struct nbd_device * lo = nbd_get (i - 1);
5581+ char *prevdevnam = lo->devnam;
5582+ len +=
5583+ sprintf (buf + len, "Device %s:\tClosed\n",
5584+ prevdevnam);
5585+ }
5586+ if (last < i - 2) {
5587+ struct nbd_device * llo = nbd_get (last + 1);
5588+ struct nbd_device * plo = nbd_get (i - 1);
5589+ char lastdevnam[3];
5590+ char prevdevnam[3];
5591+ strncpy (lastdevnam, llo->devnam, 3);
5592+ strncpy (prevdevnam, plo->devnam, 3);
5593+ len +=
5594+ sprintf (buf + len, "Device %s-%s:\tClosed\n",
5595+ lastdevnam, prevdevnam);
5596+ }
5597+
5598+ NBD_PROC_LABEL (2);
5599+
5600+ len +=
5601+ sprintf (buf + len, "Device %s:\tOpen " "\n", devnam);
5602+
5603+ NBD_PROC_LABEL (3);
5604+
5605+ len += sprintf (buf + len,
5606+ "[%s] State:\t%s%s%s%s%s%s%s%s%s%s%s%slast error %d, lives %d, bp %d\n",
3e18f7ab 5607+ devnam,
5608+ atomic_read (&lo->flags)
d912b53b 5609+ & NBD_INITIALISED ? "" : "uninitialized, ",
5610+ atomic_read (&lo->flags)
3e18f7ab 5611+ & NBD_WRITE_NOCHK ? "noverify, " : "verify, ",
5612+ atomic_read (&lo->flags)
5613+ & NBD_READ_ONLY ? "ro, " : "rw, ",
d912b53b 5614+ atomic_read(&lo->merge_requests) ? "merge requests, " : "",
5615+#ifndef NO_BUFFERED_WRITES
5616+ atomic_read (&lo->flags)
5617+ & NBD_BUFFERWR ? "buffer writes, " : "",
5618+#else
5619+ "",
5620+#endif /* NO_BUFFERED_WRITES */
5621+ atomic_read (&lo->flags)
5622+ & NBD_ENABLED ? "enabled, " : "disabled, ",
5623+ atomic_read (&lo->flags)
5624+ & NBD_VALIDATED ? "validated, " : "",
5625+ atomic_read (&lo->flags)
5626+ & NBD_REMOTE_INVALID ? "remote invalid, " : "",
5627+ atomic_read (&lo->flags)
5628+ & NBD_SHOW_ERRS ? "show_errs, " : "",
5629+ atomic_read (&lo->flags)
5630+ & NBD_DIRECT ? "direct, " : "",
5631+ atomic_read (&lo->flags)
5632+ & NBD_SYNC ? "sync, " : "",
5633+ atomic_read (&lo->flags)
5634+ & NBD_MD5SUM ? "md5sum, " : "",
5635+ lo->harderror,
3e18f7ab 5636+ lo->lives - ((atomic_read (&lo->flags) & NBD_ENABLED) ? 1 : 0), 0);
d912b53b 5637+
5638+ NBD_PROC_LABEL (4);
5639+
5640+ do { // PTB begin long do once block
5641+ int countq[2] = { 0, 0 };
5642+ int cmd;
5643+
5644+ struct list_head *pos;
5645+
5646+ read_lock_irqsave (&lo->queue_lock, flags);
5647+
5648+ list_for_each (pos, &lo->queue) {
5649+ struct request *req =
5650+ list_entry (pos, struct request, queuelist);
5651+ if (countq[READ] + countq[WRITE] > 1000)
5652+ break;
5653+
5654+ cmd = rq_data_dir (req);
5655+ countq[cmd]++;
5656+ }
5657+
5658+ read_unlock_irqrestore (&lo->queue_lock, flags);
5659+
5660+ len += sprintf (buf + len,
5661+ "[%s] Queued:\t+%dR/%dW curr (check %dR/%dW) +%dR/%dW max\n",
5662+ devnam,
3e18f7ab 5663+ atomic_read (&acct->countq[READ]),
5664+ atomic_read (&acct->countq[WRITE]),
d912b53b 5665+ countq[READ], countq[WRITE],
3e18f7ab 5666+ atomic_read (&acct->maxq[READ]),
5667+ atomic_read (&acct->maxq[WRITE]));
d912b53b 5668+ } while (0); // PTB end long do once block
5669+
5670+ NBD_PROC_LABEL (5);
5671+
5672+ len += sprintf (buf + len,
5673+ "[%s] Buffersize:\t%d\t(sectors=%d, blocks=%d)\n",
5674+ devnam, lo->bufsiz, lo->max_sectors,
5675+ lo->max_sectors / (lo->blksize >> 9));
5676+ len +=
5677+ sprintf (buf + len, "[%s] Blocksize:\t%d\t(log=%d)\n",
5678+ devnam, lo->blksize, lo->logblksize);
5679+ len +=
5680+ sprintf (buf + len, "[%s] Size:\t%luKB\n", devnam,
5681+ (unsigned long) (lo->bytesize >> 10));
5682+ len +=
5683+ sprintf (buf + len, "[%s] Blocks:\t%u\n", devnam,
5684+ lo->size >> (lo->logblksize - 10));
5685+
5686+ NBD_PROC_LABEL (6);
5687+
5688+ len +=
3e18f7ab 5689+ sprintf (buf + len, "[%s] Sockets:\t%d", devnam, lo->nslot);
d912b53b 5690+
5691+ NBD_PROC_LABEL (7);
5692+
5693+ do { // PTB begin short do once block
5694+ int j;
5695+ for (j = 0; j < lo->nslot; j++) {
5696+ struct nbd_slot *slotj = &lo->slots[j];
5697+ if (j != atomic_read (&lo->islot)) {
5698+ len +=
5699+ sprintf (buf + len, "\t(%s)",
5700+ slotj->file ? "+" : "-");
5701+ } else {
5702+ len +=
5703+ sprintf (buf + len, "\t(%s)",
5704+ slotj->file ? "*" : ".");
5705+ }
5706+ }
5707+ } while (0); // PTB end short do once block
5708+
5709+ len += sprintf (buf + len, "\n");
5710+
5711+ NBD_PROC_LABEL (8);
5712+
5713+ len += sprintf (buf + len, "[%s] Requested:\t%s", devnam,
3e18f7ab 5714+ display (atomic_read(&acct->requests_in[READ]) +
5715+ atomic_read(&acct->requests_in[WRITE]), 7));
d912b53b 5716+
5717+ NBD_PROC_LABEL (9);
5718+
5719+ do { // PTB begin short do once block
5720+ int j;
5721+ char buff[2][8];
5722+ for (j = 0; j < lo->nslot; j++) {
5723+ struct nbd_slot *slotj = &lo->slots[j];
5724+ len +=
5725+ sprintf (buf + len, "\t(%s)",
5726+ display (slotj->in, 5));
5727+ }
5728+ strncpy (buff[0],
5729+ display (atomic_read
3e18f7ab 5730+ (&acct->requests_in[READ]), 6), 7);
d912b53b 5731+ strncpy (buff[1],
5732+ display (atomic_read
3e18f7ab 5733+ (&acct->requests_in[WRITE]), 6),
d912b53b 5734+ 7);
5735+ len +=
5736+ sprintf (buf + len, "\t%sR/%sW", buff[0],
5737+ buff[1]);
5738+ lo->set_speed (lo);
5739+ len += sprintf (buf + len, "\tmax %d",
3e18f7ab 5740+ atomic_read (&acct->maxreqblks));
d912b53b 5741+ } while (0); // PTB end short do once block
5742+
5743+ len += sprintf (buf + len, "\n");
5744+ len += sprintf (buf + len, "[%s] Despatched:\t%s", devnam,
3e18f7ab 5745+ display (atomic_read(&acct->requests_out[READ]) +
5746+ atomic_read(&acct->requests_out[WRITE]), 7));
d912b53b 5747+
5748+ NBD_PROC_LABEL (10);
5749+
5750+ do { // PTB begin short do once block
5751+ int j;
5752+ char buff[2][8];
5753+ for (j = 0; j < lo->nslot; j++) {
5754+ struct nbd_slot *slotj = &lo->slots[j];
5755+ len +=
5756+ sprintf (buf + len, "\t(%s)",
5757+ display (slotj->out, 5));
5758+ }
5759+ strncpy (buff[0],
3e18f7ab 5760+ display (atomic_read(&acct->requests_out[READ]), 6), 7);
d912b53b 5761+ strncpy (buff[1],
3e18f7ab 5762+ display (atomic_read(&acct->requests_out[WRITE]), 6), 7);
d912b53b 5763+ len +=
3e18f7ab 5764+ sprintf (buf + len, "\t%sR/%sW", buff[0], buff[1]);
d912b53b 5765+ len +=
5766+ sprintf (buf + len, "\tmd5 %sW",
3e18f7ab 5767+ display (atomic_read(&lo->wrequests_5to), 5));
d912b53b 5768+ len +=
5769+ sprintf (buf + len, " (%s eq,",
3e18f7ab 5770+ display (atomic_read (&lo->wrequests_5so), 5));
d912b53b 5771+ len +=
5772+ sprintf (buf + len, " %s ne,",
3e18f7ab 5773+ display (atomic_read(&lo->wrequests_5wo), 5));
d912b53b 5774+ len +=
5775+ sprintf (buf + len, " %s dn)",
3e18f7ab 5776+ display (atomic_read (&lo->wrequests_5eo), 5));
d912b53b 5777+ } while (0); // PTB end short do once block
5778+
5779+ len += sprintf (buf + len, "\n");
5780+ len += sprintf (buf + len, "[%s] Errored:\t%s", devnam,
3e18f7ab 5781+ display (atomic_read (&acct->requests_err), 7));
d912b53b 5782+
5783+ NBD_PROC_LABEL (11);
5784+
5785+ do { // PTB begin short do once block
5786+ int j;
5787+ char buff[2][8];
5788+ int toterrs = 0;
5789+
5790+ for (j = 0; j < lo->nslot; j++) {
5791+ struct nbd_slot *slotj = &lo->slots[j];
5792+ len +=
5793+ sprintf (buf + len, "\t(%s)",
5794+ display (slotj->err, 5));
5795+ toterrs += slotj->err;
5796+ }
5797+ strncpy (buff[0], display (toterrs, 6), 7);
5798+ strncpy (buff[1],
3e18f7ab 5799+ display (atomic_read (&acct->requests_err)-toterrs, 6), 7);
d912b53b 5800+ len +=
5801+ sprintf (buf + len, "\t%s+%s\n", buff[0],
5802+ buff[1]);
5803+ } while (0); // PTB end short do once block
5804+
5805+ NBD_PROC_LABEL (12);
5806+
5807+ do { // PTB begin long do once block
5808+ int pending_rblks = 0; /* PTB reads not reached the slots yet */
5809+ int pending_wblks = 0; /* PTB writes not reached the slots yet */
5810+ int blks = 0;
5811+
5812+ read_lock_irqsave (&lo->queue_lock, flags);
5813+
5814+ do { // PTB begin short do once block
5815+ struct list_head *pos;
5816+
5817+ int count = 0;
5818+ struct request *req;
5819+
5820+ list_for_each (pos, &lo->queue) {
5821+ req =
5822+ list_entry (pos, struct request,
5823+ queuelist);
5824+ if (count++ > 1000)
5825+ break;
5826+ blks = req->nr_sectors / lo->blksize;
5827+ if (blks > 0) {
5828+ switch (rq_data_dir (req)) {
5829+ case READ:
5830+ pending_rblks +=
5831+ blks;
5832+ break;
5833+ case WRITE:
5834+ pending_wblks +=
5835+ blks;
5836+ break;
5837+ }
5838+ }
5839+ }
5840+ } while (0); // PTB end short do once block
5841+
5842+ read_unlock_irqrestore (&lo->queue_lock, flags);
5843+ len +=
5844+ sprintf (buf + len, "[%s] Pending:\t%d", devnam,
3e18f7ab 5845+ atomic_read (&acct->requests_req[READ]) +
5846+ atomic_read (&acct->requests_req[WRITE]));
d912b53b 5847+
5848+ do { // PTB begin short do once block
5849+ int j;
5850+ for (j = 0; j < lo->nslot; j++) {
5851+ struct nbd_slot *slotj =
5852+ &lo->slots[j];
5853+ len +=
5854+ sprintf (buf + len, "\t(%d)",
5855+ slotj->req);
5856+ }
5857+ } while (0); // PTB end short do once block
5858+
5859+ len += sprintf (buf + len,
5860+ "\t%dR/%dW+%dR/%dW\n",
3e18f7ab 5861+ atomic_read (&acct->requests_req[READ]),
5862+ atomic_read (&acct->requests_req[WRITE]),
d912b53b 5863+ pending_rblks, pending_wblks);
5864+
5865+ } while (0); // PTB end long do once block
5866+
5867+ NBD_PROC_LABEL (13);
5868+
5869+ do { // PTB begin long do once block
5870+ char buff[10][8];
5871+ int shift = lo->logblksize;
5872+
5873+ strncpy (buff[0],
3e18f7ab 5874+ display (atomic_read (&lo->wspeed.speed) << shift, 5), 7);
d912b53b 5875+ strncpy (buff[1],
3e18f7ab 5876+ display (atomic_read(&lo->wspeed.speedav) << shift, 5), 7);
d912b53b 5877+ strncpy (buff[2],
3e18f7ab 5878+ display (atomic_read(&lo->wspeed.speedmax) << shift,
d912b53b 5879+ 5), 7);
5880+
5881+ strncpy (buff[3],
3e18f7ab 5882+ display (atomic_read (&lo->rspeed.speed) << shift, 5), 7);
d912b53b 5883+ strncpy (buff[4],
3e18f7ab 5884+ display (atomic_read (&lo->rspeed.speedav) << shift, 5), 7);
d912b53b 5885+ strncpy (buff[5],
3e18f7ab 5886+ display (atomic_read (&lo->rspeed.speedmax) << shift, 5), 7);
d912b53b 5887+
5888+ strncpy (buff[6],
3e18f7ab 5889+ display (atomic_read (&lo->tspeed.speed) << shift, 5), 7);
d912b53b 5890+ strncpy (buff[7],
3e18f7ab 5891+ display (atomic_read (&lo->tspeed.speedav) << shift, 5), 7);
d912b53b 5892+ strncpy (buff[8],
3e18f7ab 5893+ display (atomic_read (&lo->tspeed.speedmax) << shift, 5), 7);
d912b53b 5894+
5895+ len +=
5896+ sprintf (buf + len, "[%s] B/s now:", devnam);
5897+ len +=
5898+ sprintf (buf + len, "\t%s\t(%sR+%sW)\n", buff[6],
5899+ buff[3], buff[0]);
5900+ len +=
5901+ sprintf (buf + len, "[%s] B/s ave:", devnam);
5902+ len +=
5903+ sprintf (buf + len, "\t%s\t(%sR+%sW)\n", buff[7],
5904+ buff[4], buff[1]);
5905+ len +=
5906+ sprintf (buf + len, "[%s] B/s max:", devnam);
5907+ len +=
5908+ sprintf (buf + len, "\t%s\t(%sR+%sW)\n", buff[8],
5909+ buff[5], buff[2]);
5910+ } while (0); // PTB end long do once block
5911+
5912+ do { // PTB begin short do once block
5913+ int blks;
5914+ int tot_reqs = 0;
5915+
5916+ len +=
5917+ sprintf (buf + len, "[%s] Spectrum:", devnam);
5918+ for (blks = 0;
3e18f7ab 5919+ blks <= atomic_read (&acct->maxreqblks); blks++) {
d912b53b 5920+ tot_reqs +=
3e18f7ab 5921+ atomic_read (&acct->req_in[READ][blks]) +
5922+ atomic_read (&acct->req_in[WRITE][blks]);
d912b53b 5923+ }
5924+
5925+ for (blks = 0;
3e18f7ab 5926+ blks <= atomic_read (&acct->maxreqblks); blks++) {
d912b53b 5927+ int req_blks =
3e18f7ab 5928+ atomic_read (&acct->req_in[READ][blks])
5929+ + atomic_read (&acct->req_in[WRITE][blks]);
d912b53b 5930+ int percent =
5931+ tot_reqs >
5932+ 0 ? (100 * req_blks) / tot_reqs : 0;
5933+ if (percent <= 0)
5934+ continue;
5935+ len +=
5936+ sprintf (buf + len, "\t%u%%%d", percent,
5937+ blks);
5938+ }
5939+ len += sprintf (buf + len, "\n");
5940+ } while (0); // PTB end short do once block
5941+
5942+ NBD_PROC_LABEL (14);
5943+
5944+ len += sprintf (buf + len, "[%s] Kthreads:\t%d", devnam,
3e18f7ab 5945+ atomic_read (&acct->kthreads));
d912b53b 5946+ len +=
5947+ sprintf (buf + len, "\t(%d waiting/%d running/%d max)\n",
3e18f7ab 5948+ atomic_read (&acct->kwaiters),
5949+ atomic_read (&acct->kthreads) -
5950+ atomic_read (&acct->kwaiters),
5951+ atomic_read (&acct->kmax));
d912b53b 5952+
5953+ NBD_PROC_LABEL (15);
5954+
5955+ len += sprintf (buf + len, "[%s] Cthreads:\t%d", devnam,
3e18f7ab 5956+ atomic_read (&acct->cthreads));
d912b53b 5957+
5958+ NBD_PROC_LABEL (16);
5959+
5960+ do {
5961+ int j;
5962+ for (j = 0; j < lo->nslot; j++) {
5963+ struct nbd_slot *slotj = &lo->slots[j];
5964+ int state =
5965+ ((slotj->flags & NBD_SLOT_RUNNING) ? 1 :
5966+ 0) +
5967+ ((slotj->flags & NBD_SLOT_WAITING) ? 2 :
5968+ 0);
5969+ char *desc = "?";
5970+ switch (state) {
5971+ case 0:
5972+ desc = "-";
5973+ break; /* PTB not in */
5974+ case 1:
5975+ desc = "*";
5976+ break; /* PTB in and not waiting */
5977+ case 2:
5978+ desc = "?";
5979+ break; /* PTB impossible */
5980+ case 3:
5981+ desc = "+";
5982+ break; /* PTB in and waiting */
5983+ }
5984+ len += sprintf (buf + len, "\t(%s)", desc);
5985+ }
5986+ } while (0);
5987+
5988+ len += sprintf (buf + len, "\n");
5989+
5990+ NBD_PROC_LABEL (17);
5991+
5992+ last = i;
5993+ len += sprintf (buf + len, "[%s] Cpids:\t%d", devnam,
3e18f7ab 5994+ atomic_read (&acct->cthreads));
d912b53b 5995+
5996+ do {
5997+ int j;
5998+ for (j = 0; j < lo->nslot; j++) {
5999+ struct nbd_slot *slotj = &lo->slots[j];
6000+ len +=
6001+ sprintf (buf + len, "\t(%u)", slotj->pid);
6002+ }
6003+ len += sprintf (buf + len, "\n");
6004+ } while (0);
6005+
6006+ do {
6007+ int j, k;
6008+ for (j = 0; j < lo->nslot; j++) {
6009+ struct nbd_slot *slotj = &lo->slots[j];
6010+ if (slotj->spid != 0)
6011+ break;
6012+ }
6013+ if (j < lo->nslot) {
6014+ len +=
6015+ sprintf (buf + len, "[%s] Kpids:\t%d",
6016+ devnam,
3e18f7ab 6017+ atomic_read (&acct->cthreads));
d912b53b 6018+ for (k = 0; k < lo->nslot; k++) {
6019+ struct nbd_slot *slotk =
6020+ &lo->slots[k];
6021+ len +=
6022+ sprintf (buf + len, "\t(%u)",
6023+ slotk->spid);
6024+ }
6025+ len += sprintf (buf + len, "\n");
6026+ }
6027+ } while (0);
6028+
6029+ NBD_PROC_LABEL (18);
6030+
6031+ NBD_PROC_LABEL (19);
6032+
6033+ // PTB have to tell loop head that we are not reentering
6034+ next_label = NULL;
6035+ next_label_name = NULL;
6036+ }
6037+
6038+ NBD_PROC_LABEL (20);
6039+
6040+ if (last == i - 2) {
6041+ struct nbd_device * lo = nbd_get (i - 1);
6042+ char *prevnam = lo->devnam;
6043+ len +=
6044+ sprintf (buf + len, "Device %s:\tClosed\n", prevnam);
6045+ }
6046+
6047+ if (last < i - 2) {
6048+ char lastnam[3];
6049+ char prevnam[3];
6050+ struct nbd_device * llo = nbd_get (last + 1);
6051+ struct nbd_device * plo = nbd_get (i - 1);
6052+ strncpy (lastnam, llo->devnam, 3);
6053+ strncpy (prevnam, plo->devnam, 3);
6054+ len += sprintf (buf + len, "Device %s-%s:\tClosed\n",
6055+ lastnam, prevnam);
6056+ }
6057+
6058+ NBD_PROC_LABEL (21);
6059+
6060+ // PTB re-init vital statistics for next time
6061+ next_label = NULL;
6062+ next_label_name = NULL;
6063+
6064+ *eof = 1;
6065+ *start = buf;
6066+ total += len;
6067+
6068+ return len;
6069+}
6070+
6071+/*
6072+ * PTB read an int from a string. Return number of ints read (0 or 1).
6073+ */
6074+static int
6075+sscani (char *buf, int len, int *n)
6076+{
6077+
6078+ int i, a = 0;
6079+ short has_digits = 0;
6080+ short is_signed = 0;
6081+
6082+ // PTB look for first significant character
6083+ for (i = 0; i < len; i++) {
6084+ char c = buf[i];
6085+ if (c == ' ' || c == '\t') {
6086+ if (is_signed)
6087+ return 0;
6088+ } else if (c == '-') {
6089+ if (is_signed)
6090+ return 0;
6091+ is_signed = -1;
6092+ } else if (c == '+') {
6093+ if (is_signed)
6094+ return 0;
6095+ is_signed = 1;
6096+ } else if (c >= '0' && c <= '9') {
6097+ is_signed = 1;
6098+ has_digits = 1;
6099+ break;
6100+ } else {
6101+ return 0;
6102+ }
6103+ }
6104+ // PTB i now points at first digit if there is one
6105+ if (!has_digits)
6106+ return 0;
6107+ for (; i < len; i++) {
6108+ char c = buf[i];
6109+ if (c < '0' || c > '9')
6110+ break;
6111+ a *= 10;
6112+ a += c - '0';
6113+ }
6114+ if (is_signed >= 0) {
6115+ *n = a;
6116+ } else {
6117+ *n = -a;
6118+ }
6119+ return 1;
6120+}
6121+
6122+/*
6123+ * look for a 1 or 2 letter device code ("a" or "aa") and save the
6124+ * device number to which it refers. Return number of device letter
6125+ * codes found (0 or 1).
6126+ */
6127+static int
6128+sscana (char *buf, int len, int *n)
6129+{
6130+
6131+ int i, a = 0;
6132+ short has_letters = 0;
6133+
6134+ for (i = 0; i < len; i++) {
6135+ char c = buf[i];
6136+ if (c >= 'a' && c <= 'z') {
6137+ has_letters = 1;
6138+ break;
6139+ } else if (c == ' ') {
6140+ if (has_letters)
6141+ return 0;
6142+ } else {
6143+ return 0;
6144+ }
6145+ }
6146+ if (!has_letters)
6147+ return 0;
6148+ for (; i < len; i++) {
6149+ char c = buf[i];
6150+ if (c < 'a' || c > 'z')
6151+ break;
6152+ a *= 26;
6153+ a += c - 'a';
6154+ }
6155+ *n = a;
6156+ return 1;
6157+}
6158+
6159+/*
6160+ * read an integer (or 2-letter ascii) arg into an int. Return numner
6161+ * of integers read (0 or 1) and -1 for no keymatch. The first arg is a
6162+ * preceding key.
6163+ * @i is the integer value that results
6164+ * @j is an index if one one supplied (foo[j] = i ), else -1
6165+ */
6166+static int
6167+getarg (const char *buffer, int buflen, const char *key, int *i, int *j)
6168+{
6169+
6170+ int keylen;
6171+
6172+ void skip_ws (void) {
6173+ while (buflen > 0) {
6174+ if (*buffer != ' ' && *buffer != '\t')
6175+ break;
6176+ buffer++;
6177+ buflen--;
6178+ }
6179+ };
6180+
6181+ skip_ws ();
6182+
6183+ keylen = strlen (key);
6184+ if (strncmp (buffer, key, keylen))
6185+ return -1;
6186+
6187+ buffer += keylen;
6188+ buflen -= keylen;
6189+
6190+ skip_ws ();
6191+
6192+ *j = -1;
6193+ if (*buffer == '[') {
6194+ char *closing;
6195+ int indexlen;
6196+
6197+ buffer++;
6198+ buflen--;
6199+
6200+ skip_ws ();
6201+
6202+ closing = strchr (buffer, ']');
6203+ if (!closing)
6204+ return -1;
6205+ indexlen = closing - buffer;
6206+ *closing = 0;
6207+
6208+ if (sscani ((char *) buffer, indexlen, j) < 1)
6209+ return 0;
6210+ if (sscana ((char *) buffer, buflen, j) < 1)
6211+ return 0;
6212+
6213+ buffer = closing;
6214+ buflen -= indexlen;
6215+
6216+ buffer++;
6217+ buflen--;
6218+
6219+ skip_ws ();
6220+ }
6221+
6222+ if (*buffer != '=')
6223+ return -1;
6224+
6225+ buffer++;
6226+ buflen--;
6227+
6228+ skip_ws ();
6229+
6230+ if (sscani ((char *) buffer, buflen, i) < 1)
6231+ return 0;
6232+ if (sscana ((char *) buffer, buflen, i) < 1)
6233+ return 0;
6234+ return 1;
6235+}
6236+
6237+/*
6238+ * PTB - write a 0 with echo -n 0 to /proc/nbdinfo to do a hard reset.
6239+ */
6240+static int
6241+nbd_write_proc (struct file *file, const char *buffer, unsigned long count,
6242+ void *data)
6243+{
6244+
6245+ switch (count) {
6246+
6247+ int i;
6248+
6249+ case 2:
6250+ if (buffer[1] != '\n')
6251+ break;
6252+ /* else fallthru to case 1 */
6253+ case 1:
6254+ switch (*buffer) {
6255+ case '1':
6256+ for (i = 0; i < MAX_NBD; i++) {
6257+ struct nbd_device *lo = nbd_get(i);
6258+ lo->hard_reset (lo);
6259+ }
6260+ break;
6261+ case '0':
6262+ for (i = 0; i < MAX_NBD; i++) {
6263+ // PTB this takes the io spinlock and our spinlock.
6264+ struct nbd_device *lo = nbd_get(i);
6265+ lo->soft_reset (lo);
6266+ lo->reenable_delay(lo, 5);
6267+ }
6268+ break;
6269+ }
6270+ break;
6271+ default:
6272+ do {
6273+ int index;
6274+ int merge_requests;
6275+ int sync_intvl;
6276+ int show_errs;
6277+ int md5sum;
6278+#ifndef NO_BUFFERED_WRITES
6279+ int buffer_writes;
6280+#endif
6281+ int enable;
6282+ int direct;
6283+ int reset;
6284+
6285+ if (getarg (buffer, count, "merge_requests",
6286+ &merge_requests, &index) >= 0) {
6287+ // merge_requests
6288+ set_merge_requests (merge_requests, index);
6289+ break;
6290+ }
6291+ if (getarg (buffer, count, "sync_intvl",
6292+ &sync_intvl, &index) >= 0
6293+ || getarg (buffer, count, "sync",
6294+ &sync_intvl, &index) >= 0) {
6295+ // sync_intvl
6296+ set_sync_intvl (sync_intvl, index);
6297+ break;
6298+ }
6299+ if (getarg (buffer, count, "show_errs",
6300+ &show_errs, &index) >= 0) {
6301+ // show_errs
6302+ set_show_errs (show_errs, index);
6303+ break;
6304+ }
6305+ if (getarg (buffer, count, "md5sum",
6306+ &md5sum, &index) >= 0) {
6307+ // md5sum
6308+ set_md5sum (md5sum, index);
6309+ break;
6310+ }
6311+#ifndef NO_BUFFERED_WRITES
6312+ if (getarg (buffer, count, "buffer_writes",
6313+ &buffer_writes, &index) >= 0) {
6314+ // buffer_writes
6315+ set_buffer_writes (buffer_writes, index);
6316+ break;
6317+ }
6318+#endif /* NO_BUFFERED_WRITES */
6319+ if (getarg (buffer, count, "enable",
6320+ &enable, &index) >= 0) {
6321+ // enable
6322+ set_enable (enable, index);
6323+ break;
6324+ }
6325+ if (getarg (buffer, count, "direct",
6326+ &direct, &index) >= 0) {
6327+ // enable
6328+ set_direct(direct, index);
6329+ break;
6330+ }
6331+ if (getarg (buffer, count, "reset",
6332+ &reset, &index) >= 0) {
6333+ // reset
6334+ do_reset(reset, index);
6335+ break;
6336+ }
6337+ NBD_ERROR ("illegal %ld character command\n",
6338+ count);
6339+ return -EINVAL;
6340+ } while (0);
6341+ break;
6342+ }
6343+ return count;
6344+}
6345+
6346+void
6347+nbd_init_proc(struct proc_dir_entry *res) {
6348+ res->read_proc = nbd_read_proc;
6349+ res->write_proc = nbd_write_proc;
6350+}
6351+
3e18f7ab 6352diff -Nur linux-2.6.0-test5.org/drivers/block/enbd/enbd_seqno.c linux-2.6.0-test5/drivers/block/enbd/enbd_seqno.c
6353--- linux-2.6.0-test5.org/drivers/block/enbd/enbd_seqno.c Thu Jan 1 00:00:00 1970
6354+++ linux-2.6.0-test5/drivers/block/enbd/enbd_seqno.c Mon Mar 24 22:28:41 2003
6355@@ -0,0 +1,75 @@
6356+#include <linux/enbd.h>
6357+
6358+
6359+#define _NBD_GENERATION (8*sizeof(int) - __REQ_NBDSEQNO)
6360+/*
6361+ * PTB increment the devices seqno
6362+ *
6363+ * @lo the nbd device to increment the seqno of
6364+ */
6365+static void
6366+seqno_inc(struct nbd_seqno *nseqno)
6367+{
6368+ if (nseqno->seqno < (1 << _NBD_GENERATION)) {
6369+ ++nseqno->seqno;
6370+ return;
6371+ }
6372+ // PTB next generation !
6373+ nseqno->seqno = 0;
6374+ atomic_inc (&nseqno->seqno_gen);
6375+}
6376+static int
6377+seqno_get (struct nbd_seqno *nseqno)
6378+{
6379+ return nseqno->seqno;
6380+}
6381+static void
6382+seqno_reset (struct nbd_seqno *nseqno)
6383+{
6384+ nseqno->seqno = 0;
6385+ atomic_set(&nseqno->seqno_gen,0);
6386+}
6387+/*
6388+ * PTB convert a seqno number into one with an extra generation number
6389+ * in the msb, so that it can be compared with others. return the
6390+ * result.
6391+ *
6392+ * We add the current generation no. to small seqnos, and we add the
6393+ * previous generation no. to large seqnos.
6394+ *
6395+ * @lo the nbd device to look at
6396+ * @seqno the small sequence number to return the full seq number for
6397+ */
6398+static unsigned int
6399+seqno_calc (struct nbd_seqno *nseqno, unsigned int seqno)
6400+{
6401+ unsigned int genno;
6402+ static unsigned int absdiff(unsigned int x, unsigned int y) {
6403+ if (x > y) {
6404+ return x - y;
6405+ } else {
6406+ return y - x;
6407+ }
6408+ };
6409+ genno = atomic_read (&nseqno->seqno_gen);
6410+ if (absdiff(seqno,nseqno->seqno) < (1 << (_NBD_GENERATION - 1))) {
6411+ return seqno + (genno << _NBD_GENERATION);
6412+ }
6413+ if (seqno < nseqno->seqno) {
6414+ return seqno + ((genno + 1) << _NBD_GENERATION);
6415+ }
6416+ return seqno + ((genno - 1) << _NBD_GENERATION);
6417+}
6418+
6419+void nbd_init_seqno (struct nbd_seqno *nseqno) {
6420+
6421+ seqno_reset(nseqno);
6422+
6423+ nseqno->inc = seqno_inc;
6424+ nseqno->get = seqno_get;
6425+ nseqno->reset = seqno_reset;
6426+ nseqno->calc = seqno_calc;
6427+}
6428+
6429+
6430+
6431diff -Nur linux-2.6.0-test5.org/drivers/block/enbd/enbd_speed.c linux-2.6.0-test5/drivers/block/enbd/enbd_speed.c
6432--- linux-2.6.0-test5.org/drivers/block/enbd/enbd_speed.c Thu Jan 1 00:00:00 1970
6433+++ linux-2.6.0-test5/drivers/block/enbd/enbd_speed.c Mon Mar 24 22:28:50 2003
6434@@ -0,0 +1,64 @@
6435+#include <linux/enbd.h>
6436+#include <linux/enbd_ioctl.h>
6437+
6438+/*
6439+ * PTB - update speed counters (if at least 5s has passed)
6440+ *
6441+ * @spd the speed struct to update
6442+ */
6443+static void
6444+spd_update (struct nbd_speed *spd, int distance)
6445+{
6446+
6447+ // last time we measured
6448+ int lastjiffy = atomic_read (&spd->jiffy);
6449+ // jiffies since last time
6450+ int djiffy = jiffies - lastjiffy;
6451+
6452+ // previous no we measured
6453+ int lastdist = atomic_read (&spd->distance);
6454+ // blocks since last time
6455+ int ddistance = distance - lastdist;
6456+
6457+ // write every 5 second in time
6458+ if (djiffy > 5 * HZ) {
6459+
6460+ // jiffies since first time
6461+ int tjiffy = jiffies - atomic_read (&spd->frstj);
6462+
6463+ // max tot speed measured so far
6464+ int speedmax = atomic_read (&spd->speedmax);
6465+
6466+ // last instantaneous speed we measured
6467+ int lastspeed = atomic_read (&spd->speed);
6468+
6469+ // instantaneous read blocks/s
6470+ int speed = djiffy ? (ddistance * HZ) / djiffy : 0;
6471+
6472+ // smoothed KB/s
6473+ int speedsmoothed =
6474+ (djiffy * speed + HZ * lastspeed) / (djiffy + HZ);
6475+
6476+ // average speed to now in KB/s
6477+ int speedav = tjiffy ? (distance * HZ) / tjiffy : 0;
6478+
6479+ // smoothing count for max
6480+ int speedhi =
6481+ (speedav > speedsmoothed) ? speedav : speedsmoothed;
6482+
6483+ // doing settings
6484+ atomic_set (&spd->speed, speedsmoothed);
6485+ if (speedhi > speedmax)
6486+ atomic_set (&spd->speedmax, speedhi);
6487+ atomic_set (&spd->distance, distance);
6488+ atomic_set (&spd->speedav, speedav);
6489+ atomic_set (&spd->jiffy, jiffies);
6490+ }
6491+}
6492+
6493+void
6494+nbd_init_speed(struct nbd_speed *spd) {
6495+ memset(spd, 0, sizeof(*spd));
6496+ spd->update = spd_update;
6497+}
6498+
6499diff -Nur linux-2.6.0-test5.org/include/linux/enbd.h linux-2.6.0-test5/include/linux/enbd.h
6500--- linux-2.6.0-test5.org/include/linux/enbd.h Thu Jan 1 00:00:00 1970
6501+++ linux-2.6.0-test5/include/linux/enbd.h Tue Mar 25 22:17:59 2003
6502@@ -0,0 +1,523 @@
d912b53b 6503+#ifndef LINUX_ENBD_H
6504+#define LINUX_ENBD_H
6505+
6506+/* unsigned comments are Pavel's originals for 2.1.*
6507+ * pavel@atrey.karlin.mff.cuni.cz (Pavel Machek)
6508+ * comments marked PTB are from
6509+ * ptb@it.uc3m.es (Peter T. Breuer)
6510+ * comments marked AMARIN are from
6511+ * amarin@it.uc3m.es (Andres Marin Lopez)
6512+ */
6513+
6514+#include <asm/types.h>
6515+
6516+#ifndef NBD_VERSION
6517+#define NBD_VERSION "2.4.30 $Date$"
6518+#endif /*NBD_VERSION*/
6519+
6520+ /*
6521+ * Third type of request apart from READ or WRITE
6522+ */
6523+ #ifndef IOCTL
6524+ # define IOCTL 2
6525+ #endif
6526+ /*
6527+ * and fourth ..
6528+ */
6529+ #ifndef MD5SUM
6530+ # define MD5SUM 3
6531+ #endif
6532+ /*
6533+ * and fifth ..
6534+ */
6535+ #ifndef SPECIAL
6536+ # define SPECIAL 4
6537+ #endif
6538+
6539+ /*
6540+ * We need extra bits of req->flags
6541+ * */
6542+ # define __REQ_NBD __REQ_NR_BITS
6543+ # define REQ_NBD (1 << __REQ_NBD)
6544+ # define __REQ_NBDSEQNO (__REQ_NR_BITS + 1)
6545+ # define REQ_NBDSEQNO (1 << __REQ_NBDSEQNO)
6546+ // PTB ... and all the other bits are seqno too!
6547+
6548+/* PTB - new style ioctl assignments */
6549+ #define NBD_SET_SOCK _IOW(0xab, 0x00, int)
6550+ #define NBD_TEST_IOCTL1 _IOW(0xab, 0x01, int)
6551+ #define NBD_SET_SIZE _IOW(0xab, 0x02, int)
6552+ #define NBD_DO_IT _IOW(0xab, 0x03, int)
6553+ #define NBD_CLEAR_SOCK _IOW(0xab, 0x04, int)
6554+ #define NBD_CLEAR_QUE _IO (0xab, 0x05)
6555+ #define NBD_PRINT_DEBUG _IO (0xab, 0x06)
6556+ #define NBD_TEST_IOCTL2 _IOR(0xab, 0x07, int)
6557+ #define NBD_HARD_RESET _IO (0xab, 0x09)
6558+ #define NBD_DEC_USE_COUNT _IO (0xab, 0x09)
6559+ #define MY_NBD_ACK _IOW(0xab, 0x0a, char *)
6560+ #define MY_NBD_GET_REQ _IOW(0xab, 0x0b, char *)
6561+ #define MY_NBD_REG_BUF _IOW(0xab, 0x0c, char *)
6562+ #define MY_NBD_CLR_REQ _IOW(0xab, 0x0d, int)
6563+ #define MY_NBD_SYNC _IOW(0xab, 0x0e, int)
6564+ #define NBD_SET_SECTORS _IOW(0xab, 0x0f, int)
6565+ #define MY_NBD_SET_SIG _IOW(0xab, 0x10, int *)
6566+ #define NBD_RESET _IO (0xab, 0x11)
6567+ #define NBD_TEST_IOCTL3 _IOWR(0xab, 0x12, int)
6568+ #define MY_NBD_ERR_REQ _IOW(0xab, 0x13, int)
6569+ #define MY_NBD_SET_INTVL _IOW(0xab, 0x14, int)
6570+ #define MY_NBD_SET_SHOW_ERRS _IOW(0xab, 0x15, int)
6571+ #define NBD_SET_MD5SUM _IOW(0xab, 0x16, int)
6572+ #define MY_NBD_SET_BUFFERWR _IOW(0xab, 0x17, int)
6573+ #define MY_NBD_INVALIDATE _IOW(0xab, 0x18, int)
6574+ #define MY_NBD_SET_SPID _IOW(0xab, 0x19, int)
6575+ #define MY_NBD_SET_RQ_HANDLE _IOW(0xab, 0x1a, void*)
6576+ #define MY_NBD_SET_RQ_SEQNO _IOW(0xab, 0x1b, int)
6577+ #define MY_NBD_SET_RQ_DIGEST _IOWR(0xab, 0x1d, nbd_digest_t)
6578+ #define NBD_TEST_IOCTL4 _IOR(0xab, 0x1e, char[256])
6579+ #define NBD_TEST_IOCTL5 _IOWR(0xab, 0x1f, char[256])
6580+ #define NBD_TEST_IOCTL6 _IO(0xab, 0x20) // special r 256B
6581+ #define NBD_TEST_IOCTL7 _IO(0xab, 0x21) // special rw 256B
6582+ #define NBD_SET_BLKSIZE _IOW(0xab, 0x22, int)
6583+ #define NBD_GET_BLKSIZE _IOR(0xab, 0x23, long)
6584+ #define NBD_SET_PF_MEMALLOC _IOW(0xab, 0x24, int)
6585+ #define MY_NBD_SET_DIRECT _IOW(0xab, 0x25, int)
6586+ #define MY_NBD_GET_NPORT _IOR(0xab, 0x26, int)
6587+
6588+#define MAX_NBD 16 /* PTB MAX was 128, but that's a lot */
6589+#define NBD_SHIFT 4 /* PTB 16 partitions/sockets/slots per device */
6590+ /* PTB number of socket slots per device */
6591+#define NBD_MAXCONN (1<<NBD_SHIFT)
6592+#define NBD_SIGLEN 128 /* PTB length of sig on device */
6593+#define NBD_MAX_SECTORS 512 /* PTB max number of 512B sectors in a buffer */
6594+
6595+
6596+#if defined(MAJOR_NR) || defined(__KERNEL__)
6597+ /* PTB we are included from the kernel nbd.c file so put kernel stuff here */
6598+
6599+ #include <linux/config.h>
6600+
6601+ #define ENDREQ_NOCURRENT
6602+ #define LOCAL_END_REQUEST
6603+ #include <linux/blk.h>
6604+
6605+
6606+ /* PTB various defaults */
6607+ #define NBD_RAHEAD_DFLT 24 /* PTB slow medium */
6608+ #define NBD_SYNC_INTVL 0 /* PTB sync every nK reqs (default disable) */
6609+ #define NBD_REQ_TIMEO 5 /* PTB client inactivity chk intvl (rollback) */
6610+ #define NBD_SPEED_LIM 100000 /* PTB limit to 100M write reqs/s */
6611+ #define NBD_MERGE_REQ_DFLT 0 /* PTB until accounting fixed! */
6612+ /* PTB Jens Axboe says that plug should always be set in 2.4.* */
6613+ #define NBD_PLUG_DFLT 1
6614+ #define NBD_MD5SUM_DFLT 0
6615+
6616+/*
6617+ * PTB User messaging defs.
6618+ */
6619+
6620+ #define NBD_ID "NBD #%d[%d]: %s "
6621+
6622+ #define NBD_DEBUG(level, s...) \
6623+ { static int icnt; printk( KERN_DEBUG NBD_ID, __LINE__, icnt++, __FUNCTION__); printk(s);}
6624+ #define NBD_ERROR( s...) \
6625+ { static int icnt; printk( KERN_ERR NBD_ID, __LINE__, icnt++, __FUNCTION__); printk(s);}
6626+ #define NBD_ALERT( s...) \
6627+ { static int icnt; printk( KERN_ALERT NBD_ID, __LINE__, icnt++, __FUNCTION__); printk(s);}
6628+ #define NBD_INFO( s...) \
6629+ { static int icnt; printk( KERN_INFO NBD_ID, __LINE__, icnt++, __FUNCTION__); printk(s);}
6630+
6631+
6632+
6633+ struct nbd_slot {
6634+ struct file * file; /* PTB add - for refcnt, NULL if slot empty */
6635+ struct socket * sock; /* PTB add */
6636+ int in; /* PTB add - tot blocks entered */
6637+ int out; /* PTB add - tot blocks released */
6638+ int err; /* PTB add - tot blocks errored */
6639+ int req; /* PTB add - tot blocks pending */
6640+ char * buffer; /* PTB add - user space buffer */
6641+ int bufsiz; /* PTB add - user space buffer size */
6642+ struct list_head queue;
6643+ unsigned long req_age; /* PTB add - age of pending req */
6644+ unsigned long cli_age; /* PTB add - age of client */
6645+ struct nbd_device *lo; /* PTB add - parent device */
6646+ #define NBD_SLOT_RUNNING 0x0001
6647+ #define NBD_SLOT_WAITING 0x0002
6648+ #define NBD_SLOT_BUFFERED 0x0004
6649+ #define NBD_SLOT_MD5SUM 0x8000 /* slot reply has a digest in it ..*/
6650+ #define NBD_SLOT_MD5_OK 0x10000 /* .. and equaled req's */
6651+ int flags; /* PTB add */
6652+ int i; /* PTB add - slot number */
6653+ int buflen; /* PTB add - buffer byte count */
6654+ int pid; /* PTB add - client process */
6655+ int refcnt; /* PTB add - so can set_sock/clr_sock ourself */
6656+ int nerrs; /* PTB add - local error count */
6657+ int spid; /* PTB add - server pid */
6658+ };
6659+
6660+ struct nbd_md;
6661+ struct nbd_md {
6662+ int count;
6663+ struct semaphore access_sem;
6664+ int (*notify_fn)(kdev_t, int);
6665+ int (*notify)(struct nbd_md *,kdev_t);
6666+ int (*unnotify)(struct nbd_md *,kdev_t);
6667+ void (*dec)(struct nbd_md *);
6668+ void (*inc)(struct nbd_md *);
6669+ void (*reg)(struct nbd_md *, int(*)(kdev_t, int));
6670+ };
6671+
6672+ struct nbd_speed {
6673+ atomic_t speed; /* PTB add - current speed in KB/s */
6674+ atomic_t speedmax; /* PTB add - max speed */
6675+ atomic_t speedav; /* PTB add - average speed */
6676+ atomic_t distance; /* PTB add - last distance measure */
6677+ atomic_t jiffy; /* PTB add - last jiffies speed set */
6678+ atomic_t frstj; /* PTB add - first jiffies */
6679+ void (*update)(struct nbd_speed*, int);
6680+ };
6681+
6682+ struct nbd_md_list {
6683+ struct list_head list;
6684+ kdev_t dev;
6685+ };
6686+
6687+ struct nbd_seqno; // forward decl
6688+ struct nbd_seqno {
6689+ unsigned int seqno; /* PTB add - sequence number */
6690+ atomic_t seqno_gen; /* PTB add - seqno genration */
6691+ void (*inc)(struct nbd_seqno *);
6692+ int (*get)(struct nbd_seqno *);
6693+ void (*reset)(struct nbd_seqno *);
6694+ unsigned (*calc)(struct nbd_seqno *, unsigned);
6695+ };
6696+
3e18f7ab 6697+
6698+ struct nbd_acct {
6699+ atomic_t requests_in[2]; /* PTB add - blocks put on queue */
6700+ atomic_t requests_out[2]; /* PTB add - blocks out from queue */
6701+ atomic_t requests_err; /* PTB add - blocks erred on queue */
6702+ atomic_t requests_req[2]; /* PTB add - read blocks pending */
6703+ atomic_t kwaiters; /* PTB add - kernel thrds waiting */
6704+ atomic_t kthreads; /* PTB add - kernel threads in */
6705+ atomic_t maxq[2]; /* PTB add - max req queue depth */
6706+ atomic_t countq[2]; /* PTB add - request queue depth */
6707+ atomic_t cwaiters; /* PTB add - client thrds waiting */
6708+ atomic_t cthreads; /* PTB add - client threads in */
6709+ atomic_t req_in[2][1 + NBD_MAX_SECTORS/2];
6710+ atomic_t maxreqblks; /* PTB add - maximum req size seen */
6711+ atomic_t kmax; /* PTB add - max kernel threads */
6712+ };
6713+
6714+
d912b53b 6715+ struct nbd_device {
6716+ atomic_t refcnt;
6717+
6718+ #define NBD_READ_ONLY 0x0001
6719+ #define NBD_WRITE_NOCHK 0x0002
6720+ #define NBD_INITIALISED 0x0004
6721+ #define NBD_SIGNED 0x0008
6722+
6723+ #define NBD_ENABLED 0x0010
6724+ #define NBD_SIZED 0x0020
6725+ #define NBD_BLKSIZED 0x0040
6726+
6727+ #define NBD_QBLOCKED 0x0100
6728+ #define NBD_SHOW_ERRS 0x0200
6729+ #define NBD_SYNC 0x0400
6730+ #define NBD_VALIDATED 0x0800 /* read partition table */
6731+
6732+ #define NBD_BUFFERWR 0x1000 /* buffer writes to device */
6733+ #define NBD_REMOTE_INVALID \
6734+ 0x2000 /* remote resource vanished */
6735+ #define NBD_DIRECT 0x4000 /* convert opens to O_DIRECT */
6736+ #define NBD_MD5SUM 0x8000
6737+
6738+
6739+ atomic_t flags;
6740+ int harderror; /* Code of hard error */
6741+ int magic; /* FIXME: not if debugging is off */
6742+ struct list_head queue;
6743+ rwlock_t queue_lock; /* PTB add - spinlock */
6744+ int nslot; /* PTB add - total slots */
6745+ atomic_t islot; /* PTB add - current slot */
6746+ int aslot; /* PTB add - total active slots*/
3e18f7ab 6747+ struct nbd_acct acct;
d912b53b 6748+ atomic_t wrequests_5so; /* PTB add - write blocks md5 skip */
6749+ atomic_t wrequests_5wo; /* PTB add - write blocks md5 wr */
6750+ atomic_t wrequests_5eo; /* PTB add - write blocks md5 refus*/
6751+ atomic_t wrequests_5to; /* PTB add - write blocks md5sum */
6752+ atomic_t wrequests_5co; /* PTB add - write blocks md5 tot */
6753+ atomic_t wrequests_5no; /* PTB add - write blocks not md5 */
d912b53b 6754+ struct nbd_seqno seqno_out; /* PTB add - seq number */
d912b53b 6755+ wait_queue_head_t wq; /* PTB add */
6756+ struct nbd_slot slots[NBD_MAXCONN]; /* PTB add - client array */
6757+ unsigned blksize; /* PTB add - device blksize in B */
6758+ u64 bytesize; /* PTB add - device size in B */
6759+ u64 sectors; /* PTB add - device size (sectors) */
6760+ unsigned size; /* PTB add - device size in blks */
6761+ unsigned logblksize; /* PTB add - log2 blksize */
6762+ unsigned nbd; /* PTB add - this array index */
6763+ int signature[NBD_SIGLEN/sizeof(int)];
6764+ /* PTB add - server sig */
6765+ struct file * file; /* PTB add - for ref */
6766+ struct inode * inode; /* PTB add - for ref */
6767+ int bufsiz; /* PTB add - userspace buffer size */
d912b53b 6768+ char *blockmap; /* PTB add - map of block states */
6769+ unsigned long disabled; /* PTB add - when was it disabled */
6770+ int req_timeo; /* PTB add - inactivity timeout */
6771+ struct timer_list run_queue; /* PTB add - run queue */
6772+ struct work_struct task_queue; /* PTB add - task queue */
6773+ char devnam[4]; /* PTB add - drive letters */
d912b53b 6774+ int max_sectors; /* PTB add - max req size allowed! */
6775+ int lives; /* PTB add - # times enabled */
6776+ // PTB speed measurement settings
6777+ struct nbd_speed tspeed;
6778+ struct nbd_speed wspeed;
6779+ struct nbd_speed rspeed;
6780+ int dummy; /* PTB add - unused */
6781+ struct request *req; /* PTB fake request for ioctls */
6782+ wait_queue_head_t req_wq; /* PTB req done notifications */
6783+ struct request *rq; /* PTB special request ptr */
6784+ struct list_head altqueue; /* PTB diverted requests */
6785+ rwlock_t altqueue_lock; /* PTB add - diverted reqs lock */
6786+ atomic_t seqno_in; /* PTB add - unacked reqs */
6787+ struct semaphore pid_sem; /* PTB control setting pid */
6788+ struct gendisk *disk; /* PTB for partitions */
6789+ struct request_queue *q; /* PTB make queue internal */
6790+ rwlock_t meta_lock; /* PTB add - spinlock meta data */
6791+ atomic_t merge_requests; /* PTB local req blks limit - 1 */
6792+ unsigned long reenable_time; /* PTB time to delayed reenable */
6793+ void (*enable) (struct nbd_device *lo);
6794+ void (*reset) (struct nbd_device *lo, int i);
6795+ int (*disable) (struct nbd_device *lo);
6796+ int (*read_only) (struct nbd_device *lo);
6797+ void (*set_speed) (struct nbd_device *lo);
6798+ int (*hard_reset)(struct nbd_device *lo);
6799+ int (*soft_reset)(struct nbd_device *lo);
6800+ int (*reenable_delay) (struct nbd_device *lo, int delay);
6801+ };
6802+
6803+#endif /* MAJOR_NR */
6804+
6805+
6806+
6807+/* Pavel - This now IS in some kind of include file... */
6808+
6809+/* PTB 132 */
6810+#define NBD_INIT_MAGIC 0x12345678 /* AMARIN */
6811+#define NBD_REQUEST_MAGIC 0x25609513
6812+#define NBD_REPLY_MAGIC 0x67446698
6813+/* Pavel - Do *not* use magics: 0x12560953 0x96744668.
6814+ */
6815+
6816+#define NBD_DEV_MAGIC 0x68797548
6817+
6818+#define NBD_REQUEST_MAGIC_T __u32
6819+#define NBD_REQUEST_TYPE_T __u32
6820+#define NBD_REQUEST_FROM_T __u64
6821+#define NBD_REQUEST_LEN_T __u32
6822+#define NBD_REQUEST_FLAGS_T __u32
6823+#define NBD_REQUEST_TIME_T __u64
6824+#define NBD_REQUEST_ZONE_T __u64
6825+#define NBD_REQUEST_SPECIAL_T __u32
6826+
6827+#define NBD_REPLY_MAGIC_T __u32
6828+#define NBD_REPLY_ERROR_T __s32
6829+#define NBD_REPLY_FLAGS_T __u32
6830+#define NBD_REPLY_TIME_T __u64
6831+#define NBD_REPLY_ZONE_T __u64
6832+
6833+#define NBD_REQUEST_HANDLE_T __u32
6834+#define NBD_REPLY_HANDLE_T __u32
6835+
6836+ typedef __u32 nbd_digest_t[4];
6837+
6838+ #define NBD_DIGEST_T nbd_digest_t
6839+
6840+#define NBD_REQUEST_DIGEST_T nbd_digest_t
6841+#define NBD_REPLY_DIGEST_T nbd_digest_t
6842+
6843+
6844+#define NBD_DIGEST_BITS 128
6845+#define NBD_DIGEST_LENGTH ((NBD_DIGEST_BITS)/8)
6846+#define NBD_REQUEST_SEQNO_T __u32
6847+
6848+struct nbd_request {
6849+ NBD_REQUEST_MAGIC_T magic;
6850+ NBD_REQUEST_TYPE_T type; /* == READ || == WRITE */
6851+ NBD_REQUEST_HANDLE_T handle;
6852+ NBD_REQUEST_FROM_T from; /* 64 bit PTB 132 */
6853+ NBD_REQUEST_LEN_T len;
6854+
6855+
6856+
6857+#define NBD_REQUEST_ERRORED 0x0800
6858+#define NBD_REQUEST_MD5SUM 0x8000 /* has a digest in it ..*/
6859+#define NBD_REQUEST_MD5_OK 0x10000 /* .. and equaled req's */
6860+#define NBD_REQUEST_IOCTL 0x40000 /* ioctl in len, arg in from */
6861+#define NBD_REQUEST_SPECIALRW 0x80000 /* 1 for w 0 for r on special */
6862+ NBD_REQUEST_FLAGS_T flags;
6863+ NBD_REQUEST_TIME_T time;
6864+ NBD_REQUEST_ZONE_T zone;
6865+ NBD_REQUEST_SEQNO_T seqno;
6866+ union {
6867+ NBD_REQUEST_DIGEST_T digest;
6868+ } data;
6869+ NBD_REQUEST_SPECIAL_T special;
6870+ char dummy0[0];
6871+ char dummy1[0] __attribute__ ((aligned (64)));
6872+} __attribute__ ((packed)) ;
6873+
6874+ #define NBD_REQUEST_LENGTH sizeof(struct nbd_request)
6875+
6876+struct nbd_reply {
6877+ NBD_REPLY_MAGIC_T magic;
6878+ NBD_REPLY_ERROR_T error; /* 0 = ok, else error */
6879+ NBD_REPLY_HANDLE_T handle; /* handle you got from request */
6880+
6881+
6882+
6883+#define NBD_REPLY_ERRORED 0x0800
6884+#define NBD_REPLY_MD5SUM 0x8000 /* has a digest in it .. */
6885+#define NBD_REPLY_MD5_OK 0x10000 /* .. and equaled req's */
6886+#define NBD_REPLY_CLOSE 0x20000 /* close cmd from server */
6887+#define NBD_REPLY_IOCTL 0x40000 /* ioctl in len, arg in from */
6888+ NBD_REPLY_FLAGS_T flags;
6889+ NBD_REPLY_TIME_T time;
6890+ NBD_REPLY_ZONE_T zone;
6891+ union {
6892+ NBD_REPLY_DIGEST_T digest;
6893+ } data;
6894+ char dummy0[0];
6895+ char dummy1[0] __attribute__ ((aligned (64)));
6896+} __attribute__ ((packed)) ;
6897+
6898+ #define NBD_REPLY_LENGTH sizeof(struct nbd_reply)
6899+
6900+ #define NBD_BUFFER_DATA_OFFSET \
6901+ ((NBD_REQUEST_LENGTH>NBD_REPLY_LENGTH)?NBD_REQUEST_LENGTH:NBD_REPLY_LENGTH)
6902+
6903+ #ifdef MAJOR_NR
6904+
6905+ // PTB forward declaration
6906+ static struct nbd_device nbd_dev[];
6907+
6908+
6909+ static long wait_for_completion_timeout(struct completion *x, long timeout)
6910+ {
6911+ spin_lock_irq(&x->wait.lock);
6912+ if (!x->done && timeout > 0) {
6913+ DECLARE_WAITQUEUE(wait, current);
6914+
6915+ wait.flags |= WQ_FLAG_EXCLUSIVE;
6916+ __add_wait_queue_tail(&x->wait, &wait);
6917+ do {
6918+ __set_current_state(TASK_UNINTERRUPTIBLE);
6919+ spin_unlock_irq(&x->wait.lock);
6920+ timeout = schedule_timeout(timeout);
6921+ spin_lock_irq(&x->wait.lock);
6922+ } while (!x->done && timeout > 0);
6923+ __remove_wait_queue(&x->wait, &wait);
6924+ }
6925+ if (x->done) {
6926+ x->done--;
6927+ if (timeout <= 0)
6928+ timeout = 1;
6929+ }
6930+ spin_unlock_irq(&x->wait.lock);
6931+ return timeout;
6932+ }
6933+
6934+ static void end_request(struct request *req, int uptodate) {
6935+
6936+ struct bio *bio;
6937+ struct nbd_device *lo = req->rq_disk->private_data;
6938+ static int rq_type(struct request *);
3e18f7ab 6939+ struct nbd_acct * acct = &lo->acct;
d912b53b 6940+
6941+ if (rq_type(req) == IOCTL) {
6942+ // PTB this is the devices ioctl request
6943+ complete(req->waiting);
6944+ // PTB let the driver code return the req, etc.
6945+ return;
6946+ }
6947+
6948+ /* unlock chained buffers */
6949+ while ((bio = req->bio) != NULL) {
6950+ unsigned nsect = bio_sectors(bio);
6951+ blk_finished_io(nsect);
6952+ req->bio = bio->bi_next;
6953+ bio->bi_next = NULL;
6954+ bio_endio(bio, nsect << 9, uptodate ? 0 : -EIO);
6955+ }
6956+
6957+ if (req->flags & REQ_SPECIAL)
6958+ // don't account specials
6959+ return;
6960+
6961+ write_lock(&lo->altqueue_lock);
3e18f7ab 6962+ if (atomic_read(&acct->countq[READ])
6963+ + atomic_read(&acct->countq[WRITE]) <= 0) {
d912b53b 6964+ if (atomic_read(&lo->flags) & NBD_QBLOCKED) {
6965+ static int nbd_requeue(struct nbd_device *);
6966+ nbd_requeue(lo);
6967+ atomic_clear_mask(NBD_QBLOCKED, &lo->flags);
3e18f7ab 6968+ }
6969+ }
d912b53b 6970+ write_unlock(&lo->altqueue_lock);
6971+ }
6972+
6973+ /*
6974+ * PTB This takes the spinlock itself! So call it with the io spinlock
6975+ * not held.
6976+ */
6977+ static void end_request_lock(struct request *req, int uptodate) {
6978+
6979+ unsigned long flags;
6980+ request_queue_t *q = req->q;
6981+
6982+ spin_lock_irqsave(q->queue_lock, flags);
6983+ end_request(req, uptodate);
6984+ spin_unlock_irqrestore(q->queue_lock, flags);
6985+ }
6986+
6987+ /*
6988+ * PTB Call this only with the io spinlock * held.
6989+ */
6990+ static inline void nbd_end_request(struct request *req) {
6991+
6992+ // PTB the kernel has only 2 queues, read and write, and it uses
6993+ // the cmd field to determine to which the req belongs. We add a
6994+ // seqno to it in nbd_do_req, so we reestablish it here.
6995+ static void rq_set_seqno(struct request *, int);
6996+
6997+ rq_set_seqno(req, 0); // PTB Zero extra seqno info
6998+ end_request( req, (req->errors == 0) ? 1 : 0 );
6999+ }
7000+
7001+ /*
7002+ * PTB This takes the spinlock itself! So call it with the io spinlock
7003+ * not held.
7004+ */
7005+ static void nbd_end_request_lock(struct request *req) {
7006+
7007+ // PTB the kernel has only 2 queues, read and write, and it uses
7008+ // the cmd field to determine to which the req belongs. We add a
7009+ // seqno to it in nbd_do_req, so we reestablish it here.
7010+ static void rq_set_seqno(struct request *, int);
7011+
7012+ rq_set_seqno(req, 0); // PTB Zero extra seqno info
7013+ end_request_lock( req, !req->errors );
7014+ }
7015+
7016+ extern int nbd_init_seqno(struct nbd_seqno *);
7017+ extern int nbd_init_speed(struct nbd_speed *);
7018+ extern int nbd_init_md(struct nbd_md *);
7019+ extern void nbd_init_proc(struct proc_dir_entry *res);
7020+
7021+ #endif /* MAJOR_NR */
7022+
7023+#endif /* LINUX_ENBD_H */
7024+
7025+
3e18f7ab 7026diff -Nur linux-2.6.0-test5.org/include/linux/enbd_ioctl.h linux-2.6.0-test5/include/linux/enbd_ioctl.h
7027--- linux-2.6.0-test5.org/include/linux/enbd_ioctl.h Thu Jan 1 00:00:00 1970
7028+++ linux-2.6.0-test5/include/linux/enbd_ioctl.h Mon Mar 24 17:48:05 2003
d912b53b 7029@@ -0,0 +1,56 @@
7030+#ifndef NBD_IOCTL_H
7031+#define NBD_IOCTL_H 1
7032+
7033+int nbd_ioctl_convert(int ioctl);
7034+int nbd_ioctl_convert_inplace(int *ioctl);
7035+int nbd_ioctl_revert(int ioctl);
7036+int nbd_ioctl_size (int cmd, char *arg);
7037+int nbd_ioctl_size_user (int cmd, char *arg);
7038+#ifdef __KERNEL__
7039+int nbd_ioctl_copy_to_user (int cmd, char *arg, char *buf, int size);
7040+int nbd_ioctl_copy_from_user (int cmd, char *buf, char *arg, int size);
7041+
7042+/*
7043+ * PTB object containing all the above methods, to be registered with
7044+ * the enbd.o module
7045+ */
7046+struct nbd_ioctl {
7047+#define NBD_REMOTE_IOCTL_ENABLED 0x01
7048+ unsigned long flags;
7049+ int (*convert) (int ioctl);
7050+ int (*convert_inplace)(int *ioctl);
7051+ int (*revert) (int ioctl);
7052+ int (*size) (int cmd, char *arg);
7053+ int (*size_user) (int cmd, char *arg);
7054+ int (*cp_to_user) (int cmd, char *arg, char *buf, int size);
7055+ int (*cp_from_user) (int cmd, char *buf, char *arg, int size);
7056+};
7057+
7058+struct nbd_ioctl_stub {
7059+ struct nbd_ioctl * remote;
7060+ int (*reg) (struct nbd_ioctl_stub *,struct nbd_ioctl *);
7061+ int (*unreg) (struct nbd_ioctl_stub *,struct nbd_ioctl *);
7062+};
7063+
7064+extern struct nbd_ioctl_stub nbd_remote_ioctl;
7065+extern int nbd_init_ioctl_stub(struct nbd_ioctl_stub *);
7066+#endif
7067+
7068+// PTB conversion table entries
7069+struct ioctl_conv {
7070+ unsigned int old; // ioctl id, _IO or _IOR or _IOW or _IOWR
7071+ unsigned int new; // ioctl id
7072+};
7073+
7074+// PTB extended conversion table entries
7075+struct ioctl_special {
7076+ int new;
7077+ int (*size) (char *arg);
7078+ int (*size_user) (char *arg);
7079+ int (*ioctl_copy_from_user)(char *buf, char*arg, int size);
7080+ int (*ioctl_copy_to_user)(char *arg, char*buf, int size);
7081+};
7082+
7083+extern int nbd_init_ioctl_stub(struct nbd_ioctl_stub *);
7084+
7085+#endif /* NBD_IOCTL_H */
This page took 1.486528 seconds and 4 git commands to generate.