1 diff -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
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/
12 diff -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
17 +# Makefile for the Linux kernel device drivers.
19 +# 15 Sep 2000, Christoph Hellwig <hch@infradead.org>
20 +# Rewritten to use lists instead of if-statements.
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/
30 +# char/ comes before serial/ etc so that the VT console is the boot-time
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/
67 diff -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
75 + bool 'Enhanced network block device'
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).
81 +source "drivers/block/enbd/Kconfig"
84 tristate "RAM disk support"
86 diff -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
91 +# Block device driver configuration
97 + tristate "Normal floppy disk support"
98 + depends on !X86_PC9800
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.
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>.
113 + tristate "Amiga floppy support"
117 + tristate "Atari floppy support"
121 + tristate "NEC PC-9800 floppy disk support"
122 + depends on X86_PC9800
124 + If you want to use the floppy disk drive(s) of NEC PC-9801/PC-9821,
127 +config BLK_DEV_SWIM_IOP
128 + bool "Macintosh IIfx/Quadra 900/Quadra 950 floppy support (EXPERIMENTAL)"
129 + depends on MAC && EXPERIMENTAL
131 + Say Y here to support the SWIM (Super Woz Integrated Machine) IOP
132 + floppy controller on the Macintosh IIfx and Quadra 900/950.
135 + tristate "PS/2 ESDI hard disk support"
136 + depends on MCA && MCA_LEGACY
138 + Say Y here if you have a PS/2 machine with a MCA bus and an ESDI
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.
147 + tristate "Amiga Zorro II ramdisk support"
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>.
159 + tristate "Atari ACSI support"
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.
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.
176 +comment "Some devices (e.g. CD jukebox) support multiple LUNs"
177 + depends on ATARI && ATARI_ACSI
179 +config ACSI_MULTI_LUN
180 + bool "Probe all LUNs on each ACSI device"
181 + depends on ATARI_ACSI
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.
191 + tristate "Atari SLM laser printer support"
192 + depends on ATARI && ATARI_ACSI!=n
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!
202 + tristate "XT hard disk support"
205 + Very old 8 bit hard disk controllers used in the IBM XT computer
206 + will be supported if you say Y here.
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
213 + It's pretty unlikely that you have one of these: say N.
216 + tristate "Parallel port IDE device support"
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.
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.
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"
242 +source "drivers/block/paride/Kconfig"
245 + tristate "Compaq SMART2 support"
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
254 +config BLK_CPQ_CISS_DA
255 + tristate "Compaq Smart Array 5xxx support"
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.
264 +config CISS_SCSI_TAPE
265 + bool "SCSI tape drive support for Smart Array 5xxx"
266 + depends on BLK_CPQ_CISS_DA && SCSI
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.)
272 + "SCSI support" and "SCSI tape support" must also be enabled for this
275 + When this option is disabled (N), the SCSI portion of the driver
278 +config BLK_DEV_DAC960
279 + tristate "Mylex DAC960/DAC1100 PCI RAID Controller support"
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
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.
293 + tristate "Micro Memory MM5415 Battery Backed RAM support (EXPERIMENTAL)"
294 + depends on PCI && EXPERIMENTAL
296 + Saying Y here will include support for the MM5415 family of
297 + battery backed (Non-volatile) RAM cards.
298 + http://www.umem.com/
300 + The cards appear as block devices that can be partitioned into
301 + as many as 15 partitions.
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
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
313 + tristate "Loopback device support"
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.
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
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/>.
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.
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.
344 + Note that this loop device has nothing to do with the loopback
345 + device used for network connections from the machine to itself.
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.
352 + Most users will answer N here.
354 +config BLK_DEV_CRYPTOLOOP
355 + tristate "Cryptoloop Support"
357 + depends on BLK_DEV_LOOP
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.
364 + tristate "Network block device support"
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.
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).
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.
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.
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.
393 + tristate "RAM disk support"
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.
402 + Note that the kernel command line option "ramdisk=XX" is now
403 + obsolete. For details, read <file:Documentation/ramdisk.txt>.
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
410 + Most normal users won't need the RAM disk functionality, and can
413 +config BLK_DEV_RAM_SIZE
414 + int "Default RAM disk size"
415 + depends on BLK_DEV_RAM
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.
421 +config BLK_DEV_INITRD
422 + bool "Initial RAM disk (initrd) support"
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>
431 + bool "Support for Large Block Devices"
432 + depends on X86 || MIPS32 || PPC32 || ARCH_S390_31 || SUPERH
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.
440 diff -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
445 +# ENBD configuration
447 +#comment "Enhanced network block device"
450 + tristate 'Enhanced network block device driver'
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.
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.
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.
475 +config BLK_DEV_ENBD_IOCTL
476 + tristate 'Enhanced network block device remote ioctl support'
477 + depends on BLK_DEV_ENBD
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.
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.
491 diff -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
496 +# Makefile for ENBD (Peter T. Breuer ptb@it.uc3m.es)
500 +obj-$(CONFIG_BLK_DEV_ENBD) += enbd.o
501 +obj-$(CONFIG_BLK_DEV_ENBD_IOCTL) += enbd_ioctl.o
503 +enbd-objs := enbd_base.o enbd_ioctl_stub.o enbd_seqno.o enbd_md.o enbd_speed.o enbd_proc.o
506 diff -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
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
522 diff -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
526 +#include <linux/module.h>
527 +#include <linux/vermagic.h>
528 +#include <linux/compiler.h>
530 +const char vermagic[]
531 +__attribute__((section("__vermagic"))) =
534 +static const char __module_depends[]
536 +__attribute__((section(".modinfo"))) =
539 diff -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
544 + * (Enhanced) Network block device - make block devices work over TCP
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>
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
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.
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
582 + * 97-9-13 Cosmetic changes
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
588 + * FIXME: not module-safe
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
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
742 +#include <linux/module.h>
744 +#if defined(__GNUC__) && __GNUC__ >= 2
745 +#define _LOOSE_KERNEL_NAMES
748 +#include <linux/version.h>
750 +#include <linux/fs.h>
751 +#include <linux/stat.h>
752 +#include <linux/errno.h>
753 +#include <asm/segment.h>
755 +#include <asm/uaccess.h> /* PTB - when did this arrive in kernel? */
756 +#include <asm/byteorder.h>
757 +#include <linux/wrapper.h>
759 +#define MAJOR_NR NBD_MAJOR
760 +static int major = MAJOR_NR;
762 +#include <linux/proc_fs.h>
763 +#include <linux/genhd.h>
764 +#include <linux/hdreg.h>
766 +#include <linux/file.h> /* PTB - when did this arrive in kernel? */
768 +#include <linux/smp_lock.h>
770 +#include <linux/devfs_fs_kernel.h>
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>
779 + * PTB --------------- compatibility ------------------- *
780 + * layer starts here. *
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!
788 +#ifndef mark_buffer_protected
789 + #define mark_buffer_protected(rbh) \
791 + mark_buffer_dirty (rbh); \
792 + mark_buffer_uptodate (rbh, 1); \
793 + refile_buffer (rbh); \
797 + /* PTB list interface extensions */
799 + #define list_head(ptr, type, member) \
800 + (list_empty(ptr)?NULL:list_entry(((struct list_head *)ptr)->next,type,member))
803 + #define list_tail(ptr, type, member) \
804 + (list_empty(ptr)?NULL:list_entry(((struct list_head *)ptr)->prev,type,member))
807 + /* PTB for arches without the atomic mask ops (and no smp, I think!)
808 + * - feel free to correct with assembler
810 +#ifndef atomic_set_mask
811 + #define atomic_set_mask(mask, x) (x)->counter |= (mask)
813 +#ifndef atomic_clear_mask
814 + #define atomic_clear_mask(mask, x) (x)->counter &= ~(mask)
818 + * PTB --------------- compatibility ------------------- *
819 + * layer ENDS here. *
822 +int linux_version_code = LINUX_VERSION_CODE;
824 +#include <linux/bio.h>
825 +#include <linux/enbd.h>
826 +#include <linux/enbd_ioctl.h>
829 + * PTB kernel data - 4KB worth
830 + * We need space for nda, nda1, .. nda15, ndb, ndb1, ..
831 + * The index is exactly the minor number.
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];
839 + * PTB our data - about 3KB
840 + * These are nda, ndb, ndc, ...
841 + * Divide the minor by NBD_MAXCONN to get this index.
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;
848 + struct nbd_device * nbd_get(int i) {
849 + return &nbd_dev[i];
852 + #define NBD_FAIL( s ) { \
853 + NBD_DEBUG(1, s " (result %d).\n" , result ); \
856 + #define NBD_HARDFAIL( s ) { \
857 + NBD_ERROR( s " (result %d).\n" , result ); \
858 + lo->harderror = result; \
859 + goto hard_error_out; \
863 + * PTB device parameters. These are module parameters too.
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;
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 */
880 +#ifndef NO_BUFFERED_WRITES
881 + static int buffer_writes = 0; /* PTB - act like ramd on write */
882 +#endif /* NO_BUFFERED_WRITES */
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");
900 + // PTB This pointer is initialised in nbd_init.
901 + static struct request_queue * nbd_queue;
903 +#define NO_BUFFERED_WRITES 1
906 + * PTB --------------- functions ----------------------- *
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.
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.
918 + * @req the request to get the type of.
922 +rq_type (struct request *req)
924 + if (req->flags & REQ_SPECIAL)
927 + switch ( ((req->flags & REQ_RW) ?1:0)
928 + | ((req->flags & REQ_NBD)?2:0)
939 + // PTB report what we can of the strangeness if it is strange
940 + return (req->flags < 4) ? -1: req->flags;
944 + * PTB code the request type into a request.
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.
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.
954 + * @req the request to set the type on
955 + * @type one of READ, WRITE, etc.
958 +set_rq_type (struct request *req, int type)
962 + req->flags &= ~(REQ_RW | REQ_NBD | REQ_SPECIAL);
965 + req->flags &= ~(REQ_NBD | REQ_SPECIAL);
966 + req->flags |= REQ_RW;
969 + req->flags &= ~(REQ_RW | REQ_SPECIAL);
970 + req->flags |= REQ_NBD;
973 + req->flags &= ~REQ_SPECIAL;
974 + req->flags |= REQ_RW | REQ_NBD;
977 + req->flags |= REQ_RW | REQ_NBD | REQ_SPECIAL;
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.
987 + * @req - request we want to count
990 +nr_blks (struct request *req)
992 + unsigned log_sectors_per_blk;
993 + unsigned sectors_per_blk;
996 + struct nbd_device *lo;
1001 + if (rq_type(req) == REQ_SPECIAL) // PTB contains no data
1004 + lo = req->rq_disk->private_data;
1006 + log_sectors_per_blk = lo->logblksize - 9;
1007 + sectors_per_blk = 1 << log_sectors_per_blk;
1009 + sectors = req->nr_sectors;
1010 + size = (sectors + sectors_per_blk - 1) >> log_sectors_per_blk;
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
1020 + * @i number to be translated to x[y] alphabetical form.
1023 +device_letter (int i)
1026 + static char buf[3];
1027 + static int cached_i = -1;
1029 + if (cached_i == i)
1040 + buf[0] = 'a' + i / 26;
1041 + buf[1] = 'a' + i % 26;
1047 + * PTB auxiliary functions for manipulating the sequence number. Isn't
1048 + * there anything private we can use in a request?
1050 + * This function returns the sequno
1052 + * @req the request to get the sequence number of
1055 +rq_seqno (struct request *req)
1057 + return req->flags >> __REQ_NBDSEQNO;
1060 +rq_set_seqno (struct request *req, int val)
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;
1069 + * PTB sync the device. Modes:
1070 + * @arg = 1: Do it sync
1071 + * @arg = 0: Do it async
1073 + * We can't call sync_dev outside a process context. I don't know why.
1074 + * Death results from a scheduled attempt.
1076 + * Call without the semaphore held, as we lock it and call sync_dev.
1079 +nbd_sync (struct nbd_device *lo, long arg)
1081 + struct inode *inode = lo->inode;
1082 + short minor, nbd, islot;
1084 + islot = atomic_read (&lo->islot);
1086 + if (!(atomic_read (&lo->flags) & NBD_INITIALISED) || !inode) {
1090 + minor = minor (inode->i_rdev);
1091 + nbd = minor >> NBD_SHIFT;
1093 + // PTB sync_dev is async. fsync_dev is sync.
1096 + // PTB 2.5.7 does not have async sync! FIXME
1099 + fsync_bdev (inode->i_bdev);
1100 + invalidate_buffers (mk_kdev (major, nbd << NBD_SHIFT));
1110 +nbd_async_sync (struct nbd_device *lo)
1115 +nbd_sync_sync (struct nbd_device *lo)
1121 + * Do sync async if we're enabled, sync if we're not.
1123 + * @lo the device to maybe sync (sync or async sync!)
1126 +nbd_maybe_sync_sync (struct nbd_device *lo)
1129 + if ((atomic_read (&lo->flags) & NBD_ENABLED)
1130 + && !(atomic_read (&lo->flags) & NBD_REMOTE_INVALID)) {
1131 + nbd_async_sync (lo);
1134 + nbd_sync_sync (lo);
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.
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
1150 +nbd_enqueue (struct nbd_device *lo, struct request *req)
1152 + unsigned long req_blks = nr_blks (req);
1154 + if (req_blks < 0) {
1155 + short islot = atomic_read (&lo->islot);
1156 + NBD_ERROR ("(%d): invalid req %p. Not touching!\n", islot, req);
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!
1166 + struct nbd_acct *acct = &lo->acct;
1168 + cmd = rq_data_dir (req);
1169 + atomic_add (req_blks, &acct->requests_in[cmd]);
1171 + // PTB do we need locks here? Apparently not.
1172 + atomic_inc (&acct->countq[cmd]);
1173 + countq = atomic_read (&acct->countq[cmd]);
1175 + // PTB the maxes are just noncritical stats
1176 + if (atomic_read (&acct->maxq[cmd]) < countq)
1177 + atomic_set (&acct->maxq[cmd], countq);
1178 + atomic_inc (&acct->req_in[cmd][req_blks]);
1179 + // PTB the maxes are just noncritical stats
1180 + if (atomic_read (&acct->maxreqblks) < req_blks)
1181 + atomic_set (&acct->maxreqblks, req_blks);
1184 + write_lock (&lo->queue_lock);
1186 + list_add (&req->queuelist, &lo->queue);
1188 + write_unlock (&lo->queue_lock);
1190 + wake_up_interruptible (&lo->wq);
1195 + * PTB - remove a request from anywhere in the nbd device general queue
1196 + * - return 0 for success, -ve for fail
1198 + * We need to hold the queue lock when calling this routine.
1199 + * It walks the queue.
1201 + * @lo the nbd device
1202 + * @req the request to be removed
1205 +nbd_remove (struct nbd_device *lo, struct request *req)
1208 + struct nbd_acct *acct = &lo->acct;
1213 + list_del_init (&req->queuelist);
1215 + /* PTB accounting and nothing more */
1216 + cmd = rq_data_dir (req);
1217 + atomic_dec (&acct->countq[cmd]);
1222 + * PTB - Open the device. This is the blkops function.
1225 +nbd_open (struct inode *inode, struct file *file)
1228 + struct nbd_device *lo;
1234 + if (!inode && file) { /* added by ptb for 2.0.35. Necessary? */
1235 + inode = file->f_dentry->d_inode;
1238 + NBD_ERROR ("null inode.\n");
1242 + dev = minor (inode->i_rdev);
1243 + nbd = dev >> NBD_SHIFT;
1244 + part = dev - (nbd << NBD_SHIFT);
1247 + if (nbd >= MAX_NBD) {
1248 + NBD_ERROR ("too many (%d) whole devices open\n", nbd);
1252 + lo = &nbd_dev[nbd];
1253 + devnam = lo->devnam;
1255 + /* PTB provision for opening for direct i/o - gives mount aid */
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;
1264 + /* PTB we have got the whole dev's file or inode for 1st time */
1265 + if (!lo->file || lo->file != file) {
1267 + atomic_set (&(&lo->wspeed)->frstj, jiffies);
1268 + atomic_set (&(&lo->rspeed)->frstj, jiffies);
1269 + atomic_set (&(&lo->tspeed)->frstj, jiffies);
1271 + if (!lo->inode || lo->inode != inode) {
1272 + lo->inode = inode;
1274 + if (!(atomic_read (&lo->flags) & NBD_INITIALISED)) {
1275 + atomic_set_mask (NBD_INITIALISED, &lo->flags);
1279 + atomic_inc (&lo->refcnt);
1281 + if (!(atomic_read (&lo->flags) & NBD_VALIDATED)
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);
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.
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
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.
1305 + * @slot the nbd_slot on which the req notionally was
1306 + * @req the poor defenceless kernel request about to be acked
1309 +nbd_commit (struct nbd_slot *slot, struct request *req)
1312 + struct nbd_device *lo = slot->lo;
1313 + unsigned long req_blks = nr_blks (req);
1315 + struct nbd_acct * acct = &lo->acct;
1317 + if (req_blks < 0) {
1318 + NBD_ERROR ("corrupted req %p. Not touching with bargepole.\n",
1323 + list_del_init (&req->queuelist);
1325 + nbd_end_request_lock (req);
1326 + blk_put_request (req);
1328 + slot->req_age = 0;
1329 + slot->req -= req_blks;
1331 + /* PTB accounting and nothing more */
1332 + cmd = rq_data_dir (req);
1334 + atomic_sub (req_blks, &acct->requests_req[cmd]);
1335 + if (req->errors != 0) {
1336 + /* PTB error exit */
1337 + atomic_add (req_blks, &acct->requests_err);
1338 + slot->err += req_blks;
1342 + atomic_add (req_blks, &acct->requests_out[cmd]);
1343 + slot->out += req_blks;
1346 + /* PTB everything but a write was easy */
1350 + * PTB now non error case writes
1352 + * account the 4 cases for a md5sum'd transaction
1355 + switch (slot->flags & (NBD_SLOT_MD5SUM | NBD_SLOT_MD5_OK)) {
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);
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);
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);
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);
1398 + // PTB clear the md5sum indicators from the slot afterwards!
1399 + slot->flags &= ~(NBD_SLOT_MD5SUM | NBD_SLOT_MD5_OK);
1401 + // PTB we ran out of difficult cases, so return
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
1408 + * We must be called without spinlocks held, as we take it in end req
1410 + * @slot the nbd_slot on which the req notionally was
1411 + * @req the poor defenceless kernel request about to be errored
1414 +nbd_error (struct nbd_slot *slot, struct request *req)
1416 + struct nbd_device *lo = slot->lo;
1417 + unsigned long req_blks = nr_blks (req);
1419 + struct nbd_acct * acct = &lo->acct;
1421 + if (req_blks < 0) {
1422 + NBD_ERROR ("passed illegal request %p\n", req);
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.
1431 + list_del_init (&req->queuelist);
1433 + NBD_ALERT ("error out req %p from slot %d!\n", req, slot->i);
1435 + nbd_end_request_lock (req);
1436 + blk_put_request (req);
1438 + /* PTB accounting and nothing more */
1439 + cmd = rq_data_dir (req);
1440 + atomic_sub (req_blks, &acct->requests_req[cmd]);
1442 + slot->in -= req_blks;
1443 + slot->req -= req_blks;
1445 + slot->req_age = 0;
1446 + slot->err += req_blks;
1447 + atomic_add (req_blks, &acct->requests_err);
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
1455 + * @slot the nbd slot on which to work
1456 + * @req the request
1459 +nbd_rollback (struct nbd_slot *slot, struct request *req)
1462 + struct nbd_device *lo = slot->lo;
1463 + unsigned long req_blks, flags;
1465 + struct list_head *pos;
1466 + struct request *xreq;
1468 + if (atomic_read (&lo->flags) & NBD_SHOW_ERRS) {
1469 + nbd_error (slot, req);
1473 + req_blks = nr_blks (req);
1475 + if (req_blks < 0) {
1476 + NBD_ERROR ("passed illegal request %p\n", req);
1480 + list_del_init (&req->queuelist);
1482 + NBD_ALERT ("rollback req %p from slot %d!\n", req, slot->i);
1484 + if (! (req->flags & REQ_SPECIAL)) {
1485 + /* PTB accounting */
1486 + slot->in -= req_blks;
1487 + slot->req -= req_blks;
1490 + seqno = rq_seqno(req);
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) {
1499 + list_add_tail (&req->queuelist, pos);
1500 + write_unlock_irqrestore(&lo->queue_lock, flags);
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
1510 + * @slot the nbd slot to scan
1513 +nbd_rollback_all (struct nbd_slot *slot)
1516 + struct request *req;
1519 + while (!list_empty (&slot->queue)) {
1521 + if (count++ > 1000)
1524 + req = list_head (&slot->queue, struct request, queuelist);
1529 + nbd_rollback (slot, req);
1535 + * PTB error out all the requests on a slot
1537 + * We must be called without the io spinlock held, as we take it in
1540 + * @slot the nbd slot to scan
1543 +nbd_error_all (struct nbd_slot *slot)
1546 + struct request *req;
1549 + while (!list_empty (&slot->queue)) {
1550 + if (count++ > 1000)
1552 + req = list_head (&slot->queue, struct request, queuelist);
1555 + nbd_error (slot, req);
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.
1566 + * @slot the nbd slot to let the request onto
1567 + * @req the request to move onto the slot queue
1570 +nbd_accept (struct nbd_slot *slot, struct request *req)
1573 + struct nbd_device *lo = slot->lo;
1574 + unsigned long req_blks = nr_blks (req);
1576 + struct nbd_acct * acct = &lo->acct;
1581 + /* PTB accounting and nothing more */
1582 + cmd = rq_data_dir (req);
1584 + atomic_add (req_blks, &acct->requests_req[cmd]);
1585 + /* PTB - Note that this really is slot and not lo.
1587 + list_add (&req->queuelist, &slot->queue);
1589 + slot->req_age = jiffies;
1590 + slot->in += req_blks;
1591 + slot->req += req_blks;
1595 + * PTB - read from userspace to a request buffer. Do it piecewuse
1596 + * - to cope with clustered requests.
1597 + * - return number of bytes read
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.
1605 +copy_from_user_to_req (struct request *req, char *user, int len)
1608 + unsigned size = 0;
1609 + struct bio *bio /* = req->bio */;
1611 + /* PTB assume user verified */
1613 + rq_for_each_bio(bio, req) {
1616 + struct bio_vec * bvl;
1618 + bio_for_each_segment(bvl, bio, i) {
1620 + struct page *page = bvl->bv_page;
1621 + int offset = bvl->bv_offset;
1622 + const unsigned current_size
1625 + buffer = page_address(page) + offset;
1627 + copy_from_user (buffer, user + size, current_size);
1629 + size += current_size;
1632 + if (size != len) {
1633 + NBD_ALERT ("requested %d and only read %d bytes to req %p\n",
1635 + NBD_ALERT ("request %p wanted to read user space buffer %p\n",
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.
1646 + * @slot the nbd slot being acted on
1650 +nbd_ack (struct nbd_slot *slot)
1652 + struct nbd_reply reply;
1653 + struct request *req, *xreq;
1657 + unsigned long req_blks = 1;
1658 + struct nbd_device *lo = slot->lo;
1659 + struct nbd_acct * acct = &lo->acct;
1660 + unsigned buflen = 0;
1663 + struct list_head *pos;
1666 + if (!(slot->flags & NBD_SLOT_BUFFERED)) {
1670 + atomic_inc (&acct->cthreads);
1671 + slot->flags |= NBD_SLOT_RUNNING;
1672 + slot->cli_age = jiffies;
1674 + user = slot->buffer;
1675 + copy_from_user ((char *) &reply, (char *) user,
1676 + sizeof (struct nbd_reply));
1678 + // PTB we keep tracking the write position in the input buffer
1679 + buflen += NBD_BUFFER_DATA_OFFSET;
1681 + // PTB save the reply handle (which is an address) as our req
1682 + memcpy (&req, &reply.handle, sizeof (req));
1685 + list_for_each (pos, &slot->queue) {
1686 + xreq = list_entry (pos, struct request, queuelist);
1687 + if (count++ > 1000)
1690 + /* PTB found it */
1694 + if (xreq != req) {
1696 + if (slot->nerrs++ < 3)
1697 + NBD_ALERT ("fatal: Bad handle %p != %p!\n",
1700 + atomic_dec (&acct->cthreads);
1701 + slot->flags &= ~NBD_SLOT_RUNNING;
1703 + NBD_ALERT("ignoring ack of req %p which slot does not have\n",
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
1714 + if (reply.magic != NBD_REPLY_MAGIC) {
1716 + if (slot->nerrs++ < 3)
1717 + NBD_ALERT ("Not enough reply magic in %s\n",
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.
1727 + if (reply.error > 0 || req->errors > 0) {
1728 + /* PTB wasn't error++'ed before */
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");
1736 + req_blks = nr_blks (req);
1738 + reqlen = req->nr_sectors;
1741 + cmd = rq_type (req);
1745 + unsigned long rcmd;
1751 + // PTB We have to copy the buffer bit by bit in
1752 + // case the request is clustered.
1755 + copy_from_user_to_req (req, ((char *) user) + buflen, reqlen);
1756 + if (size < reqlen) {
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.
1762 + ("exited because of bad copy from user\n");
1763 + // PTB FIXME - think we want to discard and retry
1766 + // PTB we keep tracking the write position in the buffer
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.
1781 + switch (reply.flags &
1782 + (NBD_REPLY_MD5SUM | NBD_REPLY_MD5_OK)) {
1784 + case NBD_REPLY_MD5SUM | NBD_REPLY_MD5_OK:
1786 + * PTB we asked for an md5sum comparison and
1787 + * the two matched, so we skipped writing the request
1789 + slot->flags |= (NBD_SLOT_MD5SUM | NBD_SLOT_MD5_OK); //11
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
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
1803 + // PTB mobody asked for an md5sum comparison
1804 + slot->flags &= ~(NBD_SLOT_MD5SUM | NBD_SLOT_MD5_OK);//00
1807 + // PTB now we are all set up to do the accounting in commit etc.
1811 + // PTB FIXME. Just temporary.
1812 + NBD_ALERT ("special req %p on slot %d\n", req, slot->i);
1820 + if (!(reply.flags & NBD_REPLY_IOCTL))
1821 + NBD_ALERT ("ioctl reply to req %p has no ioctl flag\n",
1824 + // PTB the commit should emit the request notification
1826 + rcmd = (long) req->special;
1827 + arg = req->buffer;
1831 + NBD_FAIL ("unauthorized remote ioctl\n");
1834 + if (!(_IOC_DIR (cmd) & _IOC_READ)) {
1839 + * PTB We saved ioctl size in req .. but only approximately,
1844 + * PTB if we are reading, it should be to the local
1845 + * buffer arg, which points at lo->ctldata or other buffer
1848 + // PTB we are treating a saved local address or direct val
1849 + if (req->nr_sectors > 0) {
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.
1855 + int size = req->nr_sectors << 9;
1856 + copy_from_user (arg, (char *) user + buflen, size);
1868 + * PTB - completion (or erroring) of transaction.
1869 + * note that nbd_commit will take a lock to do end_req
1871 + nbd_commit (slot, req);
1872 + atomic_dec (&acct->cthreads);
1873 + slot->flags &= ~NBD_SLOT_RUNNING;
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.
1882 + if (result != -EAGAIN && result != 0) {
1883 + req->errors += req_blks;
1884 + slot->err += req_blks;
1886 + result = result < 0 ? result : -ENODEV;
1887 + // PTB one client thread leaves
1888 + atomic_dec (&acct->cthreads);
1889 + slot->flags &= ~NBD_SLOT_RUNNING;
1894 + * PTB - write to userspace from a request buffer. Do it piecewuse
1895 + * - to cope with clustered requests.
1896 + * - return number of bytes written
1899 +copy_to_user_from_req (struct request *req, char *user, int len)
1902 + unsigned size = 0;
1903 + struct bio *bio /* = req->bio */;
1905 + /* PTB assume user verified */
1907 + rq_for_each_bio(bio, req) {
1910 + struct bio_vec * bvl;
1912 + bio_for_each_segment(bvl, bio, i) {
1914 + struct page *page = bvl->bv_page;
1915 + int offset = bvl->bv_offset;
1916 + const unsigned current_size
1919 + buffer = page_address(page) + offset;
1921 + copy_to_user (user + size, buffer, current_size);
1923 + size += current_size;
1931 + * PTB do the devices three speed updates
1933 + * @lo the nbd device to do the update on
1936 +nbd_set_speed (struct nbd_device *lo)
1939 + struct nbd_speed *wspd = &lo->wspeed;
1940 + struct nbd_speed *rspd = &lo->rspeed;
1941 + struct nbd_speed *tspd = &lo->tspeed;
1942 + struct nbd_acct *acct = &lo->acct;
1943 + w = atomic_read (&acct->requests_in[WRITE]);
1944 + wspd->update (wspd, w);
1945 + r = atomic_read (&acct->requests_in[READ]);
1946 + rspd->update (rspd, r);
1948 + tspd->update (tspd, t);
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
1960 + * @slot the nbd slot to act on.
1963 +nbd_get_req (struct nbd_slot *slot)
1965 + struct nbd_request request;
1966 + struct request *req;
1968 + static atomic_t count;
1969 + unsigned start_time = jiffies;
1970 + struct nbd_device *lo = slot->lo;
1971 + struct nbd_acct * acct = &lo->acct;
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;
1980 + atomic_inc (&acct->cthreads); // PTB - client thread enters
1981 + slot->flags |= NBD_SLOT_RUNNING;
1982 + slot->cli_age = jiffies;
1984 + if (!(slot->flags & NBD_SLOT_BUFFERED)) {
1985 + NBD_FAIL ("Our slot has no buffer");
1988 + atomic_set (&lo->islot, islot);
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
1994 + if (!slot->file) {
1996 + NBD_FAIL ("Our slot has been nofiled");
1998 + if (!(atomic_read (&lo->flags) & NBD_ENABLED)) {
2000 + NBD_FAIL ("Our slot has been vamooshed");
2003 + atomic_inc (&acct->cwaiters);
2004 + slot->flags |= NBD_SLOT_WAITING;
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);
2009 + atomic_dec (&acct->cwaiters);
2010 + slot->flags &= ~NBD_SLOT_WAITING;
2012 + // PTB - now spin until request arrives to treat
2013 + while (slot->file && list_empty (&lo->queue)) {
2015 + static int nbd_clr_sock (struct nbd_slot *slot); // forward decl
2017 + int time_left = start_time + timeout - jiffies;
2019 + read_unlock_irqrestore (&lo->queue_lock, flags);
2021 + // PTB one client thread goes to sleep
2022 + atomic_inc (&acct->cwaiters);
2023 + slot->flags |= NBD_SLOT_WAITING;
2025 + interruptible_sleep_on_timeout (&lo->wq, time_left);
2027 + slot->flags &= ~NBD_SLOT_WAITING;
2028 + // PTB one client thread reactivates
2029 + atomic_dec (&acct->cwaiters);
2030 + atomic_inc (&count);
2032 + // PTB Have to take the spinlock again to check at the queue
2033 + atomic_inc (&acct->cwaiters);
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);
2037 + atomic_dec (&acct->cwaiters);
2038 + slot->flags &= ~NBD_SLOT_WAITING;
2040 + // PTB fail for recheck if we are inactive too long
2042 + time_left = start_time + timeout - jiffies;
2043 + if (time_left > 0 || !list_empty (&lo->queue))
2046 + // PTB bad. timeout with nothing on queue. Error out.
2049 + // PTB we will exit with fail, so up spinlock now
2050 + read_unlock_irqrestore (&lo->queue_lock, flags);
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))
2057 + // PTB buffer is invalid
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");
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.
2071 + } // end while loop
2073 + // PTB we still have the (read) spinlock here
2075 + if (!(atomic_read (&lo->flags) & NBD_ENABLED)) {
2076 + read_unlock_irqrestore (&lo->queue_lock, flags);
2078 + NBD_FAIL ("Our slot vaporized while we slept!");
2080 + if (!slot->file) {
2081 + read_unlock_irqrestore (&lo->queue_lock, flags);
2083 + NBD_FAIL ("Our slot nofiled itself while we slept!");
2085 + if (!list_empty (&slot->queue)) {
2086 + read_unlock_irqrestore (&lo->queue_lock, flags);
2088 + NBD_FAIL ("impossible! already treating one request");
2089 + // PTB we do a nontrivial rollback from the user daemon
2092 + // PTB now relinquish the read lock and try for the write lock
2093 + read_unlock_irqrestore (&lo->queue_lock, flags);
2095 + write_lock_irqsave (&lo->queue_lock, flags);
2096 + // PTB got the write lock
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
2102 + NBD_FAIL ("ho hum beaten to the punch");
2103 + // PTB we may do a trivial rollback from the user daemon
2106 + // PTB cli/sti here looks unnec. hardware interrupts return here
2107 + // AMARIN begin uninterruptible code
2109 + // PTB we have the (write) spinlock
2111 + // PTB oldest=last element in queue
2112 + req = list_tail (&lo->queue, struct request, queuelist);
2114 + // PTB this is where we free the req from our queue. We need to be
2115 + // holding our spinlock at this point
2117 + // PTB - must succeed as have the spinlock
2118 + result = nbd_remove (lo, req);
2119 + // PTB now holding irqs off in nbd_remove
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.
2125 + write_unlock_irqrestore (&lo->queue_lock, flags);
2127 + request.magic = NBD_REQUEST_MAGIC;
2128 + request.flags = 0;
2130 + switch (rq_type (req)) {
2132 + unsigned long cmd;
2138 + request.type = IOCTL;
2140 + // PTB this is our special ioctl kernel request
2142 + cmd = (unsigned long) req->special;
2143 + arg = req->buffer;
2144 + size = req->nr_sectors << 9;
2146 + // PTB the arg was a literal
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;
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);
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;
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;
2190 + NBD_ALERT ("received unknown req %p type %#x\n",
2191 + req, rq_type (req));
2195 + request.seqno = seqno_out->calc(seqno_out, rq_seqno (req));
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
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;
2209 + // PTB tz_dsttime = 0 always in linux
2211 + memcpy (&request.handle, &req, sizeof (request.handle));
2213 + copy_to_user (slot->buffer, (char *) &request, sizeof (request));
2215 + switch (request.type) {
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);
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)
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) {
2241 + nbd_end_request_lock (req);
2242 + blk_put_request (req);
2244 + NBD_FAIL ("kernel failed to keep req while we copied from it");
2249 + // PTB temporary. We do not treat specials at the moment.
2253 + NBD_ERROR ("req %p was type %#x\n", req, rq_type(req));
2254 + NBD_FAIL ("unknown req type");
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.
2264 + nbd_accept (slot, req);
2266 + atomic_dec (&acct->cthreads); // PTB - client thread leaves normally
2267 + slot->flags &= ~NBD_SLOT_RUNNING;
2272 + // PTB accounting - a fail to get a request is not an errored request
2273 + atomic_dec (&acct->cthreads); // PTB - client thread leaves abnormally
2274 + slot->flags &= ~NBD_SLOT_RUNNING;
2275 + result = result < 0 ? result : -ENODEV;
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".
2285 + * @lo the nbd device to scan
2288 +nbd_clr_kernel_queue (struct nbd_device *lo)
2292 + unsigned long flags;
2293 + request_queue_t *q = lo->q;
2295 + spin_lock_irqsave (q->queue_lock, flags);
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);
2303 + ("impossible! kernel queue empty after tested nonemty!\n");
2306 + blkdev_dequeue_request (req);
2307 + spin_unlock_irqrestore (q->queue_lock, flags);
2311 + nbd_end_request_lock (req);
2312 + blk_put_request (req);
2313 + spin_lock_irqsave (q->queue_lock, flags);
2315 + spin_unlock_irqrestore (q->queue_lock, flags);
2319 + /* PTB fall thru */
2321 + NBD_ALERT ("removed %d requests\n", count);
2327 + * PTB error out the pending requests on the nbd queue and kernel queue
2328 + * Note that we take the queue spinlock for this
2330 + * @lo the nbd device to scan
2333 +nbd_clr_queue (struct nbd_device *lo)
2336 + struct nbd_acct * acct = &lo->acct;
2338 + while (count < 1000) {
2340 + struct request *req;
2341 + unsigned long req_blks = 1;
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);
2349 + req = list_head (&lo->queue, struct request, queuelist);
2351 + write_unlock(&lo->queue_lock);
2355 + req_blks = nr_blks (req);
2357 + req->errors += req_blks + 1;
2358 + atomic_add (req_blks, &acct->requests_err);
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);
2366 + nbd_end_request_lock (req);
2367 + blk_put_request (req);
2370 + NBD_ALERT ("unqueued %d reqs\n", count);
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.
2382 + * @lo the nbd device being treated
2385 +nbd_requeue (struct nbd_device *lo)
2389 + while (count < 1000) {
2391 + struct request *req;
2393 + // PTB cannot allow new requests via interrupts
2394 + if (list_empty (&lo->altqueue)) {
2397 + req = list_tail (&lo->altqueue, struct request, queuelist);
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);
2406 + if (req->queuelist.next == NULL) {
2407 + NBD_ALERT ("req %p has 0 next ptr! Abort\n", req);
2410 + /* PTB - must succeed as have the spinlock */
2411 + list_del_init (&req->queuelist);
2412 + /* PTB now hold irqs off in nbd_remove */
2415 + nbd_enqueue (lo, req);
2423 +#define NBD_FAIL( s... ) { \
2424 + NBD_ERROR( s); printk("\n"); \
2428 +#ifndef NO_BUFFERED_WRITES
2430 + * Magic function from rd.c that we hope saves a buffer head
2431 + * permanently somewhere in the kernel VM system.
2434 +buffered_write_pagecache_IO (struct buffer_head *sbh, int nbd)
2436 + struct address_space *mapping;
2437 + unsigned long index;
2438 + int offset, size, err;
2439 + struct nbd_device *lo = &nbd_dev[nbd];
2442 + // PTB we need to save the /dev/nda inode
2447 + mapping = lo->inode->i_mapping;
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;
2457 + // PTB we mark each page that we should write to Uptodate
2460 + struct page **hash;
2461 + struct page *page;
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
2471 + // PTB say NOW? that we have traversed what we want of the page
2474 + hash = page_hash (mapping, index);
2475 + page = __find_get_page (mapping, index, hash);
2478 + // PTB we get to make a new page
2479 + page = grab_cache_page (mapping, index);
2481 + // PTB failed to get new page
2486 + if (!Page_Uptodate (page)) {
2487 + memset (kmap (page), 0, PAGE_CACHE_SIZE);
2489 + SetPageUptodate (page);
2491 + // PTB the new page is locked. We need to unlock it later
2495 + // PTB prepare already for next page
2498 + // PTB set up for copy
2499 + dst = kmap (page);
2501 + src = bh_kmap (sbh);
2503 + // PTB prepare for next round
2507 + memcpy (dst, src, count);
2513 + UnlockPage (page);
2515 + SetPageDirty (page);
2516 + __free_page (page);
2518 + } while (size > 0);
2525 +buffered_write (struct request *req)
2528 + struct buffer_head *bh;
2529 + int dev = minor (req->rq_dev);
2530 + int nbd = dev >> NBD_SHIFT;
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;
2537 + getblk (bh->b_rdev, bh->b_rsector / (bh->b_size >> 9),
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",
2546 + mark_buffer_protected (rbh); // PTB equals dirty, uptodate
2547 + err = buffered_write_pagecache_IO (bh, nbd);
2556 +#endif /* NO_BUFFERED_WRITES */
2559 + * PTB check if the device is read only according to int flags
2561 + * @lo the nbd device to be checked
2564 +nbd_read_only(struct nbd_device *lo) {
2565 + return (atomic_read(&lo->flags) & NBD_READ_ONLY) != 0;
2568 + * PTB set the device readonly (or not)
2570 + * @lo the nbd device to be set up
2571 + * @ro 1 for read only, 0 for read write.
2574 +nbd_set_read_only(struct nbd_device * lo, int ro) {
2577 + atomic_set_mask (NBD_READ_ONLY, &lo->flags);
2579 + atomic_clear_mask (NBD_READ_ONLY, &lo->flags);
2582 + // PTB which device really does not matter. We do the checking.
2583 + set_disk_ro (lo->disk, ro != 0);
2587 + * PTB - kernel function to take reqs off the kernel queue. Runs with
2588 + * io lock held. This is the "request function".
2591 +do_nbd_request (request_queue_t * q)
2593 + struct request *req;
2594 + unsigned long flags;
2596 + while (! blk_queue_empty(q)) {
2598 + struct nbd_device *lo;
2599 + struct nbd_acct * acct;
2601 + req = elv_next_request(q);
2603 + lo = req->rq_disk->private_data;
2606 + /* PTB - one kernel thread enters */
2607 + atomic_inc (&acct->kthreads);
2608 + if (atomic_read (&acct->kthreads) > atomic_read (&acct->kmax))
2609 + atomic_set (&acct->kmax, atomic_read (&acct->kthreads));
2611 + if (!lo->inode || !lo->file) {
2612 + NBD_FAIL ("Request when device not ready.");
2615 + if (rq_data_dir (req) == WRITE && nbd_read_only(lo)) {
2616 + NBD_FAIL ("write on read-only device");
2618 + flags = atomic_read (&lo->flags);
2619 + if (!(flags & NBD_INITIALISED)) {
2620 + NBD_FAIL ("device not initialised.");
2622 + if (!(flags & NBD_ENABLED)) {
2623 + NBD_FAIL ("device not enabled.");
2625 + if (flags & NBD_REMOTE_INVALID) {
2626 + NBD_FAIL ("remote device invalidated.");
2628 + if (req->sector + req->nr_sectors > lo->sectors) {
2629 + NBD_FAIL ("overrange request");
2631 + if (req->sector < 0) {
2632 + NBD_FAIL ("underrange request");
2634 + if (req->rq_disk->major != major) {
2635 + NBD_FAIL ("request for wrong major");
2638 + blkdev_dequeue_request (req);
2640 + // PTB in 2.5 we can release the iolock briefly here
2641 + spin_unlock_irq(q->queue_lock);
2643 + if (req->flags & REQ_SPECIAL) {
2644 + // PTB temporary successful end here for SPECIALS
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
2651 + if (atomic_read(&acct->countq[READ])
2652 + + atomic_read(&acct->countq[WRITE]) > 0) {
2653 + atomic_set_mask(NBD_QBLOCKED, &lo->flags);
2655 + write_unlock(&lo->altqueue_lock);
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);
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.
2669 + rq_set_seqno (req, seqno_out->get(seqno_out));
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);
2679 + write_unlock(&lo->altqueue_lock);
2681 + // PTB normal sequence is to queue request locally
2682 + nbd_enqueue (lo, req);
2686 + atomic_dec (&acct->kthreads);
2687 + // PTB regain the iolock for another turn
2688 + spin_lock_irq(q->queue_lock);
2689 + continue; // PTB next request
2692 + // PTB can rely on req being nonnull here
2693 + NBD_ALERT ("ending req %p with prejudice\n", req);
2695 + blkdev_dequeue_request (req);
2696 + spin_unlock_irq(q->queue_lock);
2698 + nbd_end_request_lock (req);
2699 + blk_put_request (req);
2701 + // PTB more accounting
2703 + int req_blks = nr_blks (req);
2704 + struct nbd_acct * acct = &lo->acct;
2705 + atomic_add (req_blks, &acct->requests_err);
2706 + atomic_dec (&acct->kthreads);
2708 + NBD_ALERT("failed to account one orphan errored req\n");
2710 + // PTB regain the queue lock for another turn
2711 + spin_lock_irq(q->queue_lock);
2718 + * PTB pair of helpful additional functions, only good for 1 bit in the
2719 + * mask, however. Modify if you want more.
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
2726 +atomic_test_and_set_mask (atomic_t * a, unsigned mask)
2728 + int i = ffs (mask);
2732 + #ifdef __LITTLE_ENDIAN
2733 + return test_and_set_bit (i - 1, (unsigned long *)&a->counter);
2735 + #ifndef __BIGENDIAN
2736 + #error help, I only know about bigendian or littlendian machines
2738 + return test_and_set_bit
2739 + (i - 1 + (sizeof(long)-sizeof(a->counter))*8,
2740 + (unsigned long *)&a->counter);
2744 +atomic_test_and_clear_mask (atomic_t * a, unsigned mask)
2746 + int i = ffs (mask);
2750 + #ifdef __LITTLE_ENDIAN
2751 + return test_and_clear_bit (i - 1, (unsigned long *)&a->counter);
2753 + #ifndef __BIGENDIAN
2754 + #error help, I only know about bigendian or littlendian machines
2756 + return test_and_clear_bit
2757 + (i - 1 + (sizeof(long)-sizeof(a->counter))*8,
2758 + (unsigned long *)&a->counter);
2764 + * PTB - set the enabled flag on a device (call without the spinlock held)
2766 + * @lo the nbd device being treated
2769 +nbd_enable (struct nbd_device *lo) {
2770 + unsigned long flags;
2771 + int did_enabled = 0;
2772 + struct nbd_md *md = &nbd_md;
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);
2782 + write_unlock_irqrestore (&lo->meta_lock, flags);
2785 + md->notify(&nbd_md, mk_kdev (major, lo->nbd << NBD_SHIFT));
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.
2796 + * @slot the nbd slot being treated
2799 +nbd_clr_sock (struct nbd_slot *slot)
2802 + struct nbd_device *lo = slot->lo;
2803 + int islot = slot->i;
2804 + unsigned long flags;
2806 + int do_enable = 0;
2807 + static int nbd_soft_reset (struct nbd_device*);
2809 + nbd_rollback_all (slot);
2811 + slot->file = NULL;
2814 + slot->buffer = NULL;
2816 + write_lock_irqsave (&lo->meta_lock, flags);
2818 + /* PTB reset lo->aslot */
2820 + if (lo->aslot > 0) {
2822 + /* PTB grr .. do this the hard way */
2824 + for (i = 0; i < lo->nslot; i++) {
2825 + struct nbd_slot *sloti = &lo->slots[i];
2829 + lo->aslot = aslot;
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);
2838 + } else if (!(atomic_read (&lo->flags) & NBD_ENABLED)) {
2839 + // PTB must not call reenable as that clears the queue
2845 + // PTB lift the lock temporarily
2846 + write_unlock_irqrestore(&lo->meta_lock, flags);
2848 + nbd_soft_reset (lo);
2852 + NBD_ALERT ("enabled device nd%s\n", lo->devnam);
2854 + write_lock_irqsave(&lo->meta_lock, flags);
2856 + /* PTB reset lo->islot, for no good reason */
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)
2867 + lo->harderror = 0;
2868 + write_unlock_irqrestore (&lo->meta_lock, flags);
2870 + /* PTB don't clear whole device queue as we might still be open */
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.
2880 + * @lo the nbd device to scan
2883 +nbd_rollback_old (struct nbd_device *lo)
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);
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.
2903 + * @slot the nbd slot being registered
2906 +nbd_set_sock (struct nbd_slot *slot, int arg)
2909 + struct nbd_device *lo = slot->lo;
2910 + int islot = slot->i;
2911 + unsigned long flags;
2912 + int do_enable = 0;
2914 + if (!(atomic_read (&lo->flags) & NBD_INITIALISED)) {
2915 + NBD_ALERT ("(%d) device nd%s not initialised yet!\n",
2916 + islot, lo->devnam);
2919 + if (!(atomic_read (&lo->flags) & NBD_SIZED)) {
2920 + NBD_ALERT ("(%d) device nd%s not sized yet!\n", islot,
2924 + if (!(atomic_read (&lo->flags) & NBD_BLKSIZED)) {
2925 + NBD_ALERT ("(%d) device nd%s not blksized yet!\n", islot,
2929 + if (!(atomic_read (&lo->flags) & NBD_SIGNED)) {
2930 + NBD_ALERT ("(%d) setting unsigned device nd%s! But harmless.\n",
2931 + islot, lo->devnam);
2935 + down (&lo->pid_sem);
2937 + if (slot->pid != current->pid) {
2938 + if (jiffies > slot->cli_age + 2 * HZ * lo->req_timeo) {
2940 + ("(%d) dead client process %d has nd%s%d, erasing pid!\n",
2941 + islot, slot->pid, lo->devnam, islot + 1);
2945 + ("(%d) other live client process %d has nd%s%d!\n",
2946 + islot, slot->pid, lo->devnam, islot + 1);
2948 + up (&lo->pid_sem);
2951 + up (&lo->pid_sem);
2953 + slot = &lo->slots[islot];
2955 + // PTB this is a queue critical code region for the flags business
2956 + write_lock_irqsave (&lo->meta_lock, flags);
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);
2961 + if (islot >= lo->nslot) {
2962 + lo->nslot = islot + 1;
2963 + NBD_INFO ("increased socket count to %d\n", lo->nslot);
2966 + lo->harderror = 0;
2968 + if (lo->disk && !get_capacity(lo->disk)) {
2969 + set_capacity(lo->disk, lo->sectors);
2971 + if (++lo->aslot > 0) {
2974 + // PTB end of queue critical region
2975 + write_unlock_irqrestore (&lo->meta_lock, flags);
2978 + * PTB if this is the first slot, we might call reenable and
2979 + * thus clr queue too, but reenable takes the spinlock
2988 + * PTB - return the index i of 2^i + j, 0 <= j < 2^i
2990 +static inline unsigned
2991 +log2 (unsigned arg)
2994 + while ((arg >>= 1) > 0)
3000 + * PTB - set the blksize in bytes of the block device. Return 0 for
3001 + * - success and -ve for failure.
3004 +nbd_set_blksize (struct nbd_device *lo, unsigned int arg)
3006 + int nbd = lo->nbd;
3007 + if (arg > PAGE_SIZE || arg < 512 || (arg & (arg - 1))) {
3008 + NBD_ERROR ("blksize too big (%u)\n", arg);
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);
3019 + * PTB - set the size in bytes of the block device. Return 0 for
3020 + * - success and -ve for failure.
3023 +nbd_set_size (struct nbd_device *lo, __u64 arg)
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;
3032 + set_capacity (lo->disk, arg >> 9);
3033 + atomic_set_mask (NBD_SIZED, &lo->flags);
3039 +nbd_set_intvl (struct nbd_device *lo, int arg)
3042 + NBD_ERROR ("bad pulse interval/req timeout value (%d)\n", arg);
3045 + lo->req_timeo = arg;
3050 +nbd_set_spid (struct nbd_slot *slot, int arg)
3053 + if (arg < 0 || arg >= (1 << (sizeof (short) * 8))) {
3054 + NBD_ERROR ("bad spid value (%d)\n", arg);
3057 + slot->spid = spid;
3062 +nbd_set_bufferwr (struct nbd_device *lo, int arg)
3065 + atomic_set_mask (NBD_BUFFERWR, &lo->flags);
3067 + atomic_clear_mask (NBD_BUFFERWR, &lo->flags);
3073 +nbd_set_remote_invalid (struct nbd_device *lo, int arg)
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)
3080 + unsigned long flags;
3081 + int do_invalidate = 0;
3082 + kdev_t dev = mk_kdev (major, lo->nbd << NBD_SHIFT);
3085 + atomic_clear_mask (NBD_REMOTE_INVALID, &lo->flags);
3089 + write_lock_irqsave (&lo->meta_lock, flags);
3090 + if (!(atomic_test_and_set_mask (&lo->flags, NBD_REMOTE_INVALID))) {
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
3096 + atomic_clear_mask (NBD_VALIDATED, &lo->flags);
3097 + // PTB test removing partitions
3098 + do_invalidate = 1;
3100 + write_unlock_irqrestore (&lo->meta_lock, flags);
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);
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.
3119 +nbd_get_nport (struct nbd_device *lo, int *arg)
3121 + int err, nslot, i;
3123 + if (arg == NULL) {
3128 + err = copy_from_user ((char *) &nslot, arg, sizeof (int));
3133 + for (i = 0; i < NBD_MAXCONN; i++) {
3134 + struct nbd_slot *sloti = &lo->slots[i];
3136 + if (sloti->file) {
3140 + for (j = i; j < NBD_MAXCONN && j < i + nslot; j++) {
3144 + if (j == i + nslot) {
3150 + err = copy_to_user (arg, (char *) &i, sizeof (int));
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.
3160 + * @slot the slot we're working on
3161 + * @sig the string of signature chars (accessed as int *)
3164 +nbd_set_sig (struct nbd_slot *slot, int *sig)
3167 + int buf[NBD_SIGLEN / sizeof (int)];
3168 + int islot = slot->i;
3169 + struct nbd_device *lo = slot->lo;
3171 + if (!access_ok (VERIFY_READ, (char *) sig, NBD_SIGLEN)) {
3172 + NBD_ALERT ("(%d): failed sigcheck with bad user address %p\n",
3177 + down (&lo->pid_sem);
3179 + if (slot->pid == 0) {
3180 + slot->pid = current->pid;
3181 + slot->cli_age = jiffies;
3183 + if (slot->pid != current->pid) {
3184 + if (jiffies > slot->cli_age + 2 * HZ * lo->req_timeo) {
3186 + ("(%d): dead process %d was setting sig, erasing pid\n",
3187 + islot, slot->pid);
3191 + ("(%d): live process %d is trying to set sig\n",
3192 + islot, slot->pid);
3194 + up (&lo->pid_sem);
3198 + if (!(atomic_read (&lo->flags) & NBD_SIGNED)) {
3199 + /* PTB first time grab sig */
3200 + copy_from_user ((char *) lo->signature, (char *) &sig[0],
3202 + atomic_set_mask (NBD_SIGNED, &lo->flags);
3203 + up (&lo->pid_sem);
3206 + copy_from_user ((char *) buf, (char *) &sig[0], NBD_SIGLEN);
3208 + /* PTB test for equality */
3210 + if (memcmp (&buf[0], &lo->signature[0], NBD_SIGLEN / sizeof (int))
3213 + up (&lo->pid_sem);
3214 + NBD_ALERT ("(%d): failed sigcheck wth %d\n", islot, err);
3217 + up (&lo->pid_sem);
3223 + * PTB - register a userspace buffer to a slot. Return 0 for success
3224 + * - and -ve for failure. Null arg acts as erase.
3227 +nbd_reg_buf (struct nbd_slot *slot, char *buffer)
3231 + struct nbd_device *lo = slot->lo;
3234 + slot->flags &= ~NBD_SLOT_BUFFERED;
3235 + slot->buffer = NULL;
3240 + siz = lo->max_sectors << 9;
3242 + /* verify the buffer is in the process space */
3243 + if (!access_ok (VERIFY_WRITE, buffer, siz)) {
3247 + /* PTB hope the buffer is as big as it should be - FIXME */
3248 + slot->buffer = buffer;
3249 + slot->bufsiz = siz;
3251 + /* PTB let the device bufsiz be min of registered nonzero bufsizes */
3252 + if (!lo->bufsiz) {
3256 + if (lo->bufsiz > siz)
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)) {
3264 + lo->max_sectors = lo->bufsiz >> 9;
3265 + for (j = 0; j < NBD_MAXCONN; j++) {
3266 + nbd_max_sectors[(lo->nbd << NBD_SHIFT) + j] =
3271 + slot->flags |= NBD_SLOT_BUFFERED;
3276 + * PTB - this unsets the enabled flag on the device and then clears the
3277 + * - queue for the device.. Call without spinlock.
3279 + * @lo the nbd device to scan
3282 +nbd_disable (struct nbd_device *lo)
3284 + struct nbd_md * md = &nbd_md;
3286 + if (!lo || !(atomic_read (&lo->flags) & NBD_INITIALISED)) {
3287 + NBD_ALERT("nbd_disable called on bad device\n");
3291 + if (atomic_test_and_clear_mask (&lo->flags, NBD_ENABLED)) {
3292 + NBD_ALERT ("disabled device nd%s\n", lo->devnam);
3295 + md->unnotify(md, mk_kdev (major, lo->nbd << NBD_SHIFT));
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);
3306 + * PTB - reset the enabled flag on a device and then clear all queues
3307 + * ( call without the spinlock held ) and then enable again.
3310 +nbd_reenable (struct nbd_device *lo)
3315 + if (!(atomic_read (&lo->flags) & NBD_INITIALISED))
3317 + if (lo->aslot <= 0)
3319 + if ((atomic_read (&lo->flags) & NBD_ENABLED))
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);
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.
3334 +nbd_reenable_delay (struct nbd_device *lo, int delay)
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);
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.
3352 +nbd_soft_reset (struct nbd_device *lo)
3355 + const int max_clrq_retries = 100;
3356 + if (!(atomic_read (&lo->flags) & NBD_INITIALISED) || lo->nslot <= 0) {
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.
3364 + for (j = 0; j < lo->nslot; j++) {
3365 + struct nbd_slot *slot = &lo->slots[j];
3366 + nbd_rollback_all (slot);
3368 + // PTB disable unsets the nabled flag and clears the queue
3370 + for (j = 0; j < max_clrq_retries; j++) {
3371 + int m = nbd_clr_queue (lo);
3375 + // PTB this would unsign the device: lo->flags &= ~NBD_SIGNED;
3378 + * PTB put back invalidate buffers for use when called from
3379 + * clr_sock from nbd_release on request of Rogier Wolff.
3381 + for (j = 0; j < lo->nslot; j++) {
3382 + invalidate_buffers (mk_kdev(major, (lo->nbd << NBD_SHIFT) + j));
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
3397 +nbd_hard_reset (struct nbd_device *lo)
3402 + for (i = 0; i < MAX_NBD; i++) {
3403 + struct nbd_device *lo = &nbd_dev[i];
3405 + if (!lo->file || !lo->inode)
3407 + if (!(atomic_read(&lo->flags)&NBD_INITIALISED))
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);
3415 + // PTB - call clr_kernel_queue without the io_spinlock held
3416 + nbd_clr_kernel_queue (lo);
3423 +indirect_ioctl_load (struct request *req, int cmd, char * buf)
3428 + struct nbd_ioctl *remote_ioctl = nbd_remote_ioctl.remote;
3430 + if (!remote_ioctl)
3433 + size = remote_ioctl->size_user (cmd, buf);
3436 + // PTB unauthorized ioctl
3442 + // PTB we never use the nbd devices small buffer now
3443 + req->nr_sectors = 0;
3444 + req->buffer = NULL;
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);
3453 + if (!req->buffer) {
3458 + if (_IOC_DIR (cmd) & _IOC_WRITE) {
3460 + remote_ioctl->cp_from_user (cmd, req->buffer, buf, size);
3462 + kfree (req->buffer);
3469 + req->buffer = NULL;
3470 + req->nr_sectors =0;
3475 +indirect_ioctl_store (struct request *req, int cmd, char * buf,
3479 + struct nbd_ioctl * remote_ioctl = nbd_remote_ioctl.remote;
3481 + if (!remote_ioctl)
3487 + // PTB if we are reading, it should be to the local buffer
3488 + // PTB the buffer points at a kmalloced area
3492 + err = remote_ioctl->cp_to_user (cmd, buf, req->buffer, size);
3493 + kfree (req->buffer);
3500 +do_nbd_remote_ioctl(struct nbd_device *lo, int minor, int cmd, unsigned long arg) {
3502 + unsigned start_time, timeout;
3505 + struct request * req;
3506 + struct completion x;
3507 + struct nbd_acct * acct = &lo->acct;
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 ...
3518 + timeout = lo->req_timeo * HZ;
3519 + start_time = jiffies;
3521 + while (!(req = blk_get_request(lo->q,WRITE,0))) {
3522 + if (jiffies >= start_time + timeout) {
3523 + // PTB it takes too long
3525 + ("took too long to get a spare ioctl req: TIMEOUT\n");
3528 + err = interruptible_sleep_on_timeout (&lo->req_wq,
3530 + timeout - jiffies);
3533 + set_rq_type(req, IOCTL);
3537 + // PTB this is the fixed-up command
3538 + req->special = (void *) cmd;
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.
3548 + if (_IOC_DIR (cmd) & _IOC_READ) {
3550 + size = indirect_ioctl_load (req, cmd, (char *)arg);
3555 + // PTB direct - we just need to remember the value
3557 + req->buffer = (char *) arg;
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;
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);
3569 + for (err = 0; err <= 0; err = wait_for_completion_timeout(&x, 1)) {
3572 + * PTB on slot or queue? Don't know. Only want
3573 + * to vamoosh it if its on queue, not slot
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) {
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
3584 + atomic_dec (&acct->countq[rq_data_dir(req)]);
3585 + write_unlock(&lo->altqueue_lock);
3588 + list_del_init (&req->queuelist);
3590 + req->errors = -ETIME;
3591 + if (req->nr_sectors > 0 && req->buffer) {
3592 + kfree (req->buffer);
3593 + req->buffer = NULL;
3597 + if (time_left > 0)
3600 + // PTB find req on list and delete it
3601 + write_lock (&lo->queue_lock);
3602 + list_for_each (pos, &lo->queue) {
3604 + if (req != list_entry (pos, struct request, queuelist))
3608 + write_unlock (&lo->queue_lock);
3610 + ("took too long to treat queued ioctl: TIMEOUT\n");
3614 + write_unlock (&lo->queue_lock);
3616 + } // end while loop
3619 + if (_IOC_DIR (cmd) & _IOC_READ) {
3620 + err = indirect_ioctl_store(req, cmd, (char *)arg, size);
3626 + if (req->errors != 0) {
3627 + err = req->errors;
3628 + err = err < 0 ? err : -EINVAL;
3633 + blk_put_request(req);
3639 +find_slot (struct nbd_device *lo, int pid)
3643 + for (i = 0; i < NBD_MAXCONN; i++) {
3644 + struct nbd_slot * slot = &lo->slots[i];
3645 + if (slot->pid == pid)
3648 + if (i < NBD_MAXCONN)
3649 + return i; // found it
3655 +fixup_slot (struct nbd_device *lo, int islot, unsigned int cmd, unsigned long *arg)
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);
3672 + ("failed to find slot for pid %d for ioctl %x arg %lx\n",
3673 + current->pid, cmd, *arg);
3674 + return islot = -1;
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);
3686 + // PTB change arg !!
3687 + *arg &= (1 << (sizeof (short) * 8)) - 1;
3688 + return islot; // found it
3693 + ("failed to find slot for pid %d for ioctl %x arg %lx\n",
3694 + current->pid, cmd, *arg);
3695 + return islot = -1;
3698 + case MY_NBD_GET_REQ:
3700 + islot = find_slot (lo, current->pid);
3704 + ("failed to find slot for pid %d for ioctl %x arg %lx\n",
3705 + current->pid, cmd, *arg);
3709 + case MY_NBD_REG_BUF:
3710 + case MY_NBD_SET_SIG:
3711 + islot = find_slot (lo, current->pid);
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!
3723 + if (!arg || !*arg || get_user (intval, (int *) *arg)
3725 + || intval > NBD_MAXCONN) {
3727 + ("failed to find slot for pid %d ioctl %x arg %lx\n",
3728 + current->pid, cmd, *arg);
3729 + return islot = -1;
3731 + islot = intval - 1;
3733 + // PTB CHANGE ARG !!!!
3734 + *arg += sizeof (int);
3739 + return islot = -1;
3743 + * PTB - generic ioctl handling
3746 +nbd_ioctl (struct inode *inode, struct file *file,
3747 + unsigned int cmd, unsigned long arg)
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
3757 + struct nbd_acct *acct = &lo->acct;
3759 + if (!capable(CAP_SYS_ADMIN)) {
3760 + NBD_ERROR ("caller must be root.\n");
3764 + NBD_ERROR ("given bad inode.\n");
3767 + if (major (inode->i_rdev) != major) {
3768 + NBD_ERROR ("pseudo-major %d != %d\n",
3769 + major (inode->i_rdev), major);
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);
3778 + lo = &nbd_dev[nbd];
3779 + lo->harderror = 0;
3780 + islot = minor % NBD_MAXCONN - 1;
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.
3788 + islot = fixup_slot(lo, islot, cmd, &arg);
3791 + slot = & lo->slots[islot];
3794 + // PTB these are all always local ioctls
3800 + case NBD_CLEAR_SOCK:
3802 + NBD_ALERT ("CLEAR_SOCK called on full device nd%s arg %lx\n",
3806 + err = nbd_clr_sock (slot);
3809 + case NBD_SET_SOCK:
3811 + NBD_ALERT ("SET_SOCK called on full device nd%s arg %lx\n",
3815 + err = nbd_set_sock (slot, arg);
3819 + // PTB The kernel should intercept this
3820 + NBD_ALERT ("attempted get_blksize with BLKBSZGET\n");
3823 + case NBD_GET_BLKSIZE:
3824 + if (!(atomic_read (&lo->flags) & NBD_BLKSIZED)) {
3827 + err = put_user (lo->blksize, (long *) arg);
3831 + // PTB The kernel should have intercepted this
3832 + NBD_ALERT ("attempted set_blksize with BLKBSZSET\n");
3835 + case NBD_SET_BLKSIZE:
3839 + if (get_user (intval, (int *)arg))
3841 + if (intval == -1) {
3842 + NBD_ALERT ("BLKBSZSET got %d from user\n", intval);
3844 + err = nbd_set_blksize (lo, intval);
3847 + case NBD_SET_SIZE:
3848 + err = nbd_set_size (lo, (__u64) arg);
3851 + case NBD_SET_SECTORS:
3852 + err = nbd_set_size (lo, ((__u64) arg) << 9);
3855 + case MY_NBD_SET_INTVL: /* WG */
3856 + err = nbd_set_intvl (lo, arg);
3859 + case MY_NBD_SET_SPID:
3861 + NBD_ALERT ("SET_SPID called on full device nd%s\n",
3865 + err = nbd_set_spid (slot, arg);
3868 + case MY_NBD_SET_BUFFERWR:
3869 + err = nbd_set_bufferwr (lo, arg);
3872 + case MY_NBD_REG_BUF: /* PTB register your buffer per socket here */
3874 + /* PTB serves as existence check for this ioctl */
3878 + NBD_ALERT ("REG_BUF called on full device nd%s\n",
3882 + err = nbd_reg_buf (slot, (char *) arg);
3885 + case MY_NBD_SET_SIG:
3887 + NBD_ALERT ("SET_SIG called on full device nd%s\n",
3891 + err = nbd_set_sig (slot, (int *) arg);
3894 + case MY_NBD_GET_REQ:
3896 + NBD_ALERT ("GET_REQ called on full device nd%s\n",
3901 + arg = (unsigned)slot->buffer;
3905 + err = nbd_get_req (slot);
3908 + case MY_NBD_GET_NPORT:
3909 + err = nbd_get_nport (lo, (int *) arg);
3912 + case MY_NBD_CLR_REQ:
3914 + NBD_ALERT ("CLR_REQ called on full device nd%s\n",
3918 + nbd_rollback_all (slot);
3921 + case MY_NBD_ERR_REQ:
3923 + NBD_ALERT ("ERR_REQ called on full device nd%s\n",
3927 + nbd_error_all (slot);
3932 + // PTB maybe run the reenable function
3934 + write_lock(&lo->meta_lock);
3935 + if (lo->reenable_time != 0
3936 + && time_before(lo->reenable_time,jiffies)) {
3937 + lo->reenable_time = 0;
3940 + write_unlock(&lo->meta_lock);
3944 + // PTB error too old reqs if show_errs set, else roll them back
3945 + nbd_rollback_old (lo);
3947 + // PTB opportunity to calculate speed
3948 + nbd_set_speed (lo);
3954 + NBD_ALERT ("NBD_ACK called on full device nd%s\n",
3958 + err = nbd_ack (slot);
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",
3965 + list_head (&lo->queue, struct request, queuelist),
3966 + list_tail (&lo->queue, struct request, queuelist),
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])
3974 + case NBD_HARD_RESET: /* PTB - debugging */
3975 + err = nbd_hard_reset (lo);
3978 + case NBD_RESET: /* PTB - debugging */
3979 + err = nbd_soft_reset (lo);
3980 + // PTB we reenable in 5s
3981 + nbd_reenable_delay(lo, 5);
3984 + case NBD_SET_MD5SUM: /* PTB - change to do/plead md5summing */
3986 + atomic_set_mask (NBD_MD5SUM, &lo->flags);
3988 + atomic_clear_mask (NBD_MD5SUM, &lo->flags);
3993 + case MY_NBD_SET_SHOW_ERRS: /* PTB/WG - change show error status */
3995 + atomic_set_mask (NBD_SHOW_ERRS, &lo->flags);
3997 + atomic_clear_mask (NBD_SHOW_ERRS, &lo->flags);
4001 + case MY_NBD_SET_DIRECT: /* PTB - change o_direct status */
4003 + atomic_set_mask (NBD_DIRECT, &lo->flags);
4005 + atomic_clear_mask (NBD_DIRECT, &lo->flags);
4009 + case MY_NBD_INVALIDATE:
4010 + err = nbd_set_remote_invalid (lo, (int) arg);
4013 + case NBD_SET_PF_MEMALLOC:
4015 + current->flags |= PF_MEMALLOC;
4017 + current->flags &= ~PF_MEMALLOC;
4022 + // PTB these are the standard ioctls, and we might get them from
4029 + case BLKROSET: /* PTB - change ro status */
4030 + if (get_user(intval, (int*)arg))
4032 + // PTB local flags
4033 + nbd_set_read_only(lo, intval);
4037 + intval = nbd_read_only(lo);
4038 + return put_user(intval, (int*)arg);
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);
4050 +#endif /* NO_BUFFERED_WRITES */
4057 + struct hd_geometry *geo =
4058 + (struct hd_geometry *) arg;
4059 + int sectors = nbd_sizes[nbd << NBD_SHIFT] << 1;
4061 + unsigned char h, s;
4062 + if (sectors < (1 << 22)) {
4069 + c = (sectors / h) / s;
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)) {
4082 +#define BLKMDNTFY _IOW(0x12,133,sizeof(int))
4085 + NBD_INFO ("received BLKMDNTFY, am now in raid %x\n",
4087 + nbd_md.inc(&nbd_md);
4091 +#define BLKMDUNTFY _IOW(0x12,134,sizeof(int))
4094 + NBD_INFO ("received BLKMDUNTFY, now out of raid %x\n",
4096 + nbd_md.dec(&nbd_md);
4100 +#define BLKMDRGTR _IOW(0x12,135,sizeof(unsigned long))
4103 + nbd_md.reg(&nbd_md, (int(*)(kdev_t, int))arg);
4108 + if (nbd_remote_ioctl.remote != NULL) {
4109 + struct nbd_ioctl *remote_ioctl = nbd_remote_ioctl.remote;
4111 + if (remote_ioctl->convert_inplace (&cmd) < 0) {
4112 + NBD_ALERT ("unauthorized ioctl %#x\n", cmd);
4116 + err = do_nbd_remote_ioctl(lo, minor, cmd, arg);
4123 + * PTB - release the device. This happens when the last process closes
4127 +nbd_release (struct inode *inode, struct file *file)
4129 + struct nbd_device *lo;
4135 + NBD_ALERT ("null inode.\n");
4138 + dev = minor (inode->i_rdev);
4139 + nbd = dev >> NBD_SHIFT;
4141 + if (nbd >= MAX_NBD) {
4143 + NBD_ALERT ("too many open devices.\n");
4147 + lo = &nbd_dev[nbd];
4149 + islot = dev % NBD_MAXCONN - 1;
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];
4155 + if (slot->pid == current->pid) {
4157 + nbd_clr_sock (slot);
4158 + NBD_ALERT ("(%d): erasing slot pid %d\n", islot, slot->pid);
4160 + if (slot->refcnt > 0) {
4162 + ("slot owner process %d released slot nd%s%d while not last\n",
4163 + slot->pid, lo->devnam, islot + 1);
4168 + /* POSSIBLE change socket here PTB */
4170 + atomic_dec (&lo->refcnt);
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));
4179 + // PTB in any case the daemons are dead!
4181 + seqno_out->reset(seqno_out);
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);
4195 +nbd_media_changed(struct gendisk *disk) {
4196 + struct nbd_device *lo = disk->private_data;
4197 + if (!lo || lo->magic != NBD_DEV_MAGIC)
4199 + NBD_ALERT("nbd_media_changed called on nd%s\n", lo->devnam);
4200 + return (atomic_read (&lo->flags) & NBD_VALIDATED) == 0;
4204 +nbd_revalidate(struct gendisk *disk) {
4205 + struct nbd_device *lo = disk->private_data;
4206 + unsigned long flags;
4207 + int err = -EINVAL;
4209 + if (!lo || lo->magic != NBD_DEV_MAGIC){
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);
4220 + write_unlock_irqrestore (&lo->meta_lock, flags);
4225 +static struct block_device_operations nbd_blkops = {
4226 + owner: THIS_MODULE,
4228 + release: nbd_release,
4230 + media_changed: nbd_media_changed,
4231 + revalidate_disk: nbd_revalidate,
4234 +static struct gendisk *
4235 +nbd_find (dev_t dev, int *part, void *data)
4237 + struct nbd_device *lo = data;
4240 + if (lo->magic != NBD_DEV_MAGIC)
4245 + NBD_ALERT("nbd_find called with part = %#x\n", (unsigned)*part);
4246 + if (part && (*part < 0 || *part >= NBD_MAXCONN))
4248 + return get_disk (lo->disk);
4253 +nbd_set_disk (struct nbd_device *lo, unsigned first_minor, unsigned npart)
4255 + struct gendisk * disk = lo->disk;
4257 + lo->disk = disk = alloc_disk (npart);
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);
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?
4275 + NBD_ERROR ("Insufficient memory for partition structs\n");
4280 + * Pavel - And here should be modules and kernel interface
4281 + * (Just smiley confuses emacs :-)
4286 +nbd_reset(struct nbd_device *lo, int i) {
4290 + if (i < 0 || i >= MAX_NBD)
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];
4298 + INIT_LIST_HEAD (&slot->queue);
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 */
4306 + lo->req_timeo = NBD_REQ_TIMEO; /* PTB default pulse intvl */
4307 + lo->max_sectors = buf_sectors;
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;
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;
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);
4337 + // PTB queuue has alreay been initialized, or will be
4338 + lo->q = nbd_queue;
4341 + atomic_set_mask (NBD_MD5SUM, &lo->flags);
4344 + atomic_set_mask (NBD_SYNC, &lo->flags);
4347 + atomic_set_mask (NBD_SHOW_ERRS, &lo->flags);
4350 + atomic_set_mask (NBD_DIRECT, &lo->flags);
4352 + if (buffer_writes) {
4353 + atomic_set_mask (NBD_BUFFERWR, &lo->flags);
4355 + if (merge_requests) {
4356 + atomic_set(&lo->merge_requests, merge_requests);
4361 +MODULE_AUTHOR ("Peter T. Breuer, Andres Marin");
4362 +MODULE_DESCRIPTION ("Enhanced Network Block Device " NBD_VERSION);
4363 +MODULE_LICENSE ("GPL");
4364 +#endif /* MODULE */
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;
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.
4375 + * To turn OFF merging (once these functions are in place), set
4376 + * merge_requests=0.
4379 +nbd_merge_requests_fn (request_queue_t * q, struct request *req,
4380 + struct request *req2)
4382 + struct nbd_device *lo = req->rq_disk->private_data;
4384 + if (!atomic_read(&lo->merge_requests))
4387 + if (!ll_merge_requests_fn)
4390 + if (req->nr_sectors + req2->nr_sectors > lo->max_sectors)
4393 + if (req->nr_sectors + req2->nr_sectors >
4394 + ((atomic_read(&lo->merge_requests) + 1) << (lo->logblksize - 9)))
4397 + return ll_merge_requests_fn (q, req, req2);
4400 +nbd_front_merge_fn (request_queue_t * q, struct request *req, struct bio * bio)
4402 + struct nbd_device *lo = req->rq_disk->private_data;
4404 + if (!atomic_read(&lo->merge_requests))
4407 + if (!ll_front_merge_fn)
4410 + if (req->nr_sectors > lo->max_sectors)
4413 + if (req->nr_sectors > ((atomic_read(&lo->merge_requests) + 1) << (lo->logblksize - 9)))
4416 + return ll_front_merge_fn (q, req, bio);
4419 +nbd_back_merge_fn (request_queue_t * q, struct request *req,
4422 + struct nbd_device *lo = req->rq_disk->private_data;
4424 + if (!atomic_read(&lo->merge_requests))
4427 + if (!ll_back_merge_fn)
4430 + if (req->nr_sectors > lo->max_sectors)
4433 + if (req->nr_sectors >
4434 + ((atomic_read(&lo->merge_requests) + 1) << (lo->logblksize - 9))) return 0;
4436 + return ll_back_merge_fn (q, req, bio);
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[] = {
4444 + &rahead, sizeof (int), 0644, NULL, &proc_dointvec},
4446 + &plug, sizeof (int), 0644, NULL, &proc_dointvec},
4448 + &sync_intvl, sizeof (int), 0644, NULL, &proc_dointvec},
4449 + {4, "merge_requests",
4450 + &merge_requests, sizeof (int), 0644, NULL, &proc_dointvec},
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},
4459 +static ctl_table nbd_dir_table[] = {
4460 + {6, "enbd", NULL, 0, 0555, nbd_table},
4463 +static ctl_table nbd_root_table[] = {
4464 + {CTL_DEV, "dev", NULL, 0, 0555, nbd_dir_table},
4468 +#ifdef CONFIG_DEVFS_FS
4469 +static devfs_handle_t devfs_handle;
4470 +static devfs_handle_t devfs_handles[MAX_NBD];
4479 + struct proc_dir_entry *res;
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");
4488 + nbd_queue = kmalloc(sizeof(*nbd_queue), GFP_KERNEL);
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));
4500 + if (register_blkdev (major, "nbd", &nbd_blkops)) {
4501 + NBD_ERROR ("Unable to register major number %d for NBD\n",
4506 + NBD_INFO ("registered device at major %d\n", major);
4510 +// PTB - set up kernel queue struct with default methods
4511 + blk_init_queue (nbd_queue, do_nbd_request, &nbd_lock);
4513 + blk_queue_max_sectors(nbd_queue, buf_sectors); /* max per request */
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)
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);
4533 + * LA - moved the next #if higher;
4534 + * - kernel 2.2.* doesn't know about plug_device_fn
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;
4542 +// JSA - Add this line because under >=2.4.1, merge optimizations are in flux
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.
4553 + * PTB - The functions below just impose our own stricter size limit before
4554 + * - calling the defaults if all seems OK sizewise.
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;
4560 + nbd_init_md(&nbd_md);
4561 + nbd_init_ioctl_stub(&nbd_remote_ioctl);
4563 + for (i = 0; i < MAX_NBD; i++) {
4564 + struct nbd_device *lo = &nbd_dev[i];
4569 + * PTB we do the disk and partition stuff after we have
4570 + * contact, when nbd_open is called for the first time?
4573 + res = create_proc_read_entry ("nbdinfo", 0, NULL, NULL, NULL);
4575 + NBD_ALERT ("creation of proc entry failed\n");
4578 + // PTB additional write_proc entry in struct
4579 + nbd_init_proc(res);
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);
4587 +#ifdef CONFIG_DEVFS_FS
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];
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])
4600 + for (j = 0; j < MAX_NBD; j++) {
4602 + sprintf (name, "%u", j);
4603 + devfs_register(devfs_handles[i], name,
4605 + major, i * NBD_MAXCONN + j,
4606 + S_IFBLK | S_IRUSR | S_IWUSR,
4607 + &nbd_blkops, NULL);
4609 + // PTB do the whole disk symlink ..
4610 + devfs_mk_symlink (devfs_handles[i], "disk",
4611 + DEVFS_FL_DEFAULT, "0",
4613 + // PTB .. and the channel symlinks
4614 + for (j = 1; j < MAX_NBD; j++) {
4617 + sprintf (link, "%u", j);
4618 + sprintf (name, "chan%u", j);
4619 + devfs_mk_symlink (devfs_handles[i],
4622 + link, NULL, NULL);
4626 +#endif /* CONFIG_DEVFS_FS */
4628 + // PTB - sysctl interface
4629 + nbd_table_header = register_sysctl_table (nbd_root_table, 1);
4631 + // PTB we have to wait for the open to complete init with inode val
4641 + for (i = 0; i < MAX_NBD; i++) {
4643 + struct nbd_device *lo = &nbd_dev[i];
4646 + if (!(atomic_read (&lo->flags) & NBD_INITIALISED))
4649 + NBD_INFO ("invalidating buffers on device nd%s%d-%d\n",
4650 + lo->devnam, 0, NBD_MAXCONN);
4652 + for (j = 0; j < NBD_MAXCONN; j++) {
4653 + int minor = i * NBD_MAXCONN + j;
4654 + invalidate_buffers (mk_kdev (major, minor));
4657 + NBD_INFO ("destroying buffers on device nd%s%d-%d\n",
4658 + lo->devnam, 0, NBD_MAXCONN);
4660 + for (j = 0; j < NBD_MAXCONN; j++) {
4661 + int minor = i * NBD_MAXCONN + j;
4662 + __invalidate_buffers (mk_kdev (major, minor), 1);
4666 + unregister_sysctl_table (nbd_table_header);
4668 +#ifdef CONFIG_DEVFS_FS
4669 + if (devfs_handle) {
4670 + for (i = 0; i < MAX_NBD; i++) {
4672 + if (!devfs_handles[i])
4674 + for (j = 0; j < NBD_MAXCONN; j++) {
4680 + s[1] = '0' + (j - 10);
4683 + devfs_remove("nd/%s/%u", device_letter(i), j);
4685 + devfs_remove("nd/%s/disk", device_letter(i));
4687 + devfs_remove("nd/%s/chan%u",device_letter(i),j);
4690 + devfs_remove("nd/%s", device_letter(i));
4692 + devfs_remove("nd");
4696 + remove_proc_entry ("nbdinfo", &proc_root);
4698 + for (i = 0; i < MAX_NBD; i++) {
4699 + struct nbd_device *lo = &nbd_dev[i];
4700 + atomic_clear_mask (NBD_ENABLED, &lo->flags);
4702 + del_gendisk(lo->disk);
4703 + put_disk(lo->disk);
4705 + if (lo->blockmap) {
4706 + kfree (lo->blockmap);
4707 + lo->blockmap = NULL;
4709 + nbd_sync_sync (lo);
4712 + blk_cleanup_queue (nbd_queue);
4714 + if (unregister_blkdev (major, "nbd") != 0) {
4715 + NBD_ALERT ("cleanup_module failed\n");
4717 + NBD_INFO ("module cleaned up.\n");
4723 +module_init (nbd_init);
4724 +module_exit (nbd_cleanup);
4726 +EXPORT_SYMBOL(nbd_remote_ioctl);
4730 + * gcc -O2 -D__KERNEL__ -DMODULE -DEXPORT_SYMTAB -xc -c enbd.c -o enbd.o
4732 + * (possibly with -DMODVERSIONS also). PTB
4733 + * (possibly with -I/usr/src/linux-x.y.z/include also). PTB
4735 diff -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
4739 +#include <linux/module.h>
4740 +#include <linux/vermagic.h>
4741 +#include <linux/compiler.h>
4743 +const char vermagic[]
4744 +__attribute__((section("__vermagic"))) =
4747 +static const char __module_depends[]
4749 +__attribute__((section(".modinfo"))) =
4752 diff -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
4757 +#include <sys/time.h>
4758 +#include <unistd.h>
4761 +#include <linux/ioctl.h>
4762 +#include <linux/fs.h>
4763 +#include <linux/fd.h>
4765 +#define caddr_t char*
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))
4775 +#include <linux/blk.h>
4776 +#include <linux/enbd.h>
4777 +#include <linux/enbd_ioctl.h>
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.
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).
4791 + * We need all ioctls to be delared as either
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
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.
4802 + * The "type" part should be the type of the indirected argument, NOT
4803 + * the type of its address!
4805 + * Kernel authors typically make two mistakes:
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*).
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.
4826 + * PTB the space before the final comma is important as the ##
4827 + * discards the preceding token when D is empty
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)
4837 +static struct ioctl_conv ioctl_conv_tab[] = {
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), },
4855 + { FDSETPRM, _NEW_IOWR(FDSETPRM, struct floppy_struct), },
4856 + { FDDEFPRM, _NEW_IOWR(FDDEFPRM, struct floppy_struct), },
4857 + { FDGETPRM, _NEW_IOR(FDGETPRM, struct floppy_struct), },
4861 + { FDFMTTRK, _NEW_IOWR(FDFMTTRK, struct format_descr), },
4863 + { FDSETEMSGTRESH, _NEW_IOW(FDSETEMSGTRESH, unsigned), },
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), },
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, },
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), },
4904 + { CDROMPLAYBLK, _NEW_IOWR(CDROMPLAYBLK, struct cdrom_blk), },
4906 + { CDROMREADALL, _NEW_IOR(CDROMREADALL, char[2646]), },
4908 + { CDROMGETSPINDOWN, _NEW_IOWR(CDROMGETSPINDOWN, char), }, // one byte
4909 + { CDROMSETSPINDOWN, _NEW_IOWR(CDROMSETSPINDOWN, char), }, // one byte
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), },
4924 + { CDROMAUDIOBUFSIZ, _NEW_IOW(CDROMAUDIOBUFSIZ, int), },
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.
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.
4950 +static struct ioctl_special ioctl_special_tab[] = {
4951 + // PTB last entry must be all zeros
4952 + { 0, NULL, NULL, NULL, NULL, },
4956 +static struct ioctl_conv *
4957 +ioctl_lookup_old (int ioctl)
4963 + for (i = 0; old = ioctl_conv_tab[i].old, old; i++) {
4965 + return &ioctl_conv_tab[i];
4972 +nbd_ioctl_convert (int ioctl)
4974 + struct ioctl_conv *conv = ioctl_lookup_old (ioctl);
4978 + return conv->new ? : ioctl;
4982 +nbd_ioctl_convert_inplace(int *ioctl) {
4987 + new_ioctl = nbd_ioctl_convert(*ioctl);
4988 + if (new_ioctl == -1)
4990 + *ioctl = new_ioctl;
4994 +static struct ioctl_conv *
4995 +ioctl_lookup_new (int ioctl)
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];
5009 +nbd_ioctl_revert (int ioctl)
5011 + struct ioctl_conv *conv = ioctl_lookup_new (ioctl);
5018 +static struct ioctl_special *
5019 +ioctl_special_lookup_new (int ioctl)
5023 + for (i = 0; new = ioctl_special_tab[i].new, new; i++) {
5025 + return &ioctl_special_tab[i];
5032 +nbd_ioctl_size (int cmd, char *arg)
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);
5040 + return special->size (arg);
5046 +nbd_ioctl_size_user (int cmd, char *arg)
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);
5054 + return special->size_user (arg);
5062 +nbd_ioctl_copy_to_user (int cmd, char *arg, char *buf, int size)
5065 + if (_IOC_SIZE (cmd) == _IOC_SIZEMASK) {
5066 + struct ioctl_special *special = ioctl_special_lookup_new(cmd);
5069 + return special->ioctl_copy_to_user (arg, buf, size);
5072 + if (_IOC_DIR (cmd) & _IOC_READ) {
5074 + copy_to_user (arg, buf, size);
5084 +nbd_ioctl_copy_from_user (int cmd, char *buf, char *arg, int size)
5087 + if (_IOC_SIZE (cmd) == _IOC_SIZEMASK) {
5088 + struct ioctl_special *special = ioctl_special_lookup_new(cmd);
5091 + return special->ioctl_copy_from_user (buf, arg, size);
5094 + if (_IOC_DIR (cmd) & _IOC_READ) {
5096 + copy_from_user (buf, arg, size);
5101 + if (size > sizeof (arg)) {
5105 + memcpy (buf, &arg, size);
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,
5120 +nbd_ioctl_init (void)
5122 + struct nbd_ioctl_stub * remote_ioctl = &nbd_remote_ioctl;
5123 + remote_ioctl->reg(remote_ioctl, &struct_ioctl);
5128 +nbd_ioctl_cleanup (void) {
5129 + struct nbd_ioctl_stub * remote_ioctl = &nbd_remote_ioctl;
5130 + remote_ioctl->unreg(remote_ioctl, &struct_ioctl);
5133 +module_init (nbd_ioctl_init);
5134 +module_exit (nbd_ioctl_cleanup);
5136 +int linux_version_code = LINUX_VERSION_CODE;
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");
5146 +#endif /* MODULE */
5148 +#endif /* __KERNEL__ */
5153 +int ioctl_init(struct ioctl_conv *self, int old, int new) {
5156 + self->serialize = ioctl_serialize;
5157 + self->deserialize = ioctl_deserialize;
5158 + self->size = ioctl_size;
5161 diff -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
5165 +#include <linux/module.h>
5166 +#include <linux/vermagic.h>
5167 +#include <linux/compiler.h>
5169 +const char vermagic[]
5170 +__attribute__((section("__vermagic"))) =
5173 +static const char __module_depends[]
5175 +__attribute__((section(".modinfo"))) =
5178 diff -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
5183 +#include <linux/stddef.h>
5184 +#include <linux/errno.h>
5185 +#include <linux/enbd.h>
5186 +#include <linux/enbd_ioctl.h>
5189 + * PTB this is the hook for the enbd_ioctl extra module
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;
5198 + static int unregister_remote_ioctl(struct nbd_ioctl_stub *remote_ioctl, struct nbd_ioctl *x) {
5199 + if (remote_ioctl->remote != x)
5201 + remote_ioctl->remote = NULL;
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;
5212 diff -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
5216 +#include <linux/enbd.h>
5217 +#include <linux/enbd_ioctl.h>
5220 + * PTB small driver wide support database for MDRGTR ioctl
5225 +#ifndef HOT_ADD_DISK
5226 + #define HOT_ADD_DISK _IO (MD_MAJOR, 0x28)
5228 +#ifndef SET_DISK_FAULTY
5229 + #define SET_DISK_FAULTY _IO (MD_MAJOR, 0x29)
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);
5240 +nbd_md_inc (struct nbd_md *md) {
5241 + down(&md->access_sem);
5243 + up(&md->access_sem);
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;
5252 + up(&md->access_sem);
5256 + * PTB tell md devices in which we are embedded that we are alright
5258 + * @lo the nbd device to tell them about
5261 +nbd_notify_md_devices (struct nbd_md *md, kdev_t nbd_dev)
5263 + //kdev_t nbd_dev = mk_kdev (major, nbd << NBD_SHIFT);
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);
5272 + NBD_ALERT ("HOT_ADD to raid devices returned %d\n",
5276 + up (&md->access_sem);
5282 +nbd_unnotify_md_devices (struct nbd_md *md, kdev_t nbd_dev)
5285 + // kdev_t nbd_dev = mk_kdev (major, lo->nbd << NBD_SHIFT);
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);
5295 + ("SETFAULTY to raid devices returned %d\n", err);
5298 + up (&md->access_sem);
5303 +nbd_init_md(struct nbd_md *md)
5305 + md->notify_fn = NULL;
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;
5315 diff -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
5320 +#include <linux/enbd.h>
5321 +#include <linux/proc_fs.h>
5323 +extern struct nbd_device * nbd_get(int i);
5326 +do_reset (int reset, int i) {
5328 + void do_r (void) {
5329 + struct nbd_device *lo = nbd_get(i);
5331 + lo->reset (lo, i);
5335 + if (i >= 0 && i < MAX_NBD) {
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.
5346 +display (unsigned n, int endpos)
5348 + // PTB use endpos (<= 8) spaces at most
5349 + static char buf[16];
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);
5365 + buf[endpos--] = 'K';
5368 + buf[endpos--] = 'M';
5371 + buf[endpos--] = 'G';
5374 + buf[endpos--] = 'T';
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)
5382 + buf[endpos--] = '0';
5384 + while (endpos >= 0 && n > 0) {
5385 + buf[endpos--] = '0' + n % 10;
5389 + // PTB if there is space and cause, add decimal digits
5390 + if (endpos >= 1 && units > 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;
5400 + buf[decpos + k++] = unitchar;
5401 + buf[decpos + k] = 0;
5403 + // PTB report the start position
5404 + return buf + endpos + 1;
5409 +set_generic (int x, int i, int X)
5411 + void set_x (void) {
5412 + struct nbd_device *lo = nbd_get(i);
5413 + if (lo->magic != NBD_DEV_MAGIC)
5416 + atomic_set_mask (X, &lo->flags);
5419 + atomic_clear_mask (X, &lo->flags);
5422 + if (i >= 0 && i < MAX_NBD) {
5426 + for (i = 0; i < MAX_NBD; i++) {
5432 +set_sync_intvl (int sync_intvl, int i)
5434 + set_generic(sync_intvl, i, NBD_SYNC);
5439 +set_show_errs (int show_errs, int i)
5441 + set_generic(show_errs, i, NBD_SHOW_ERRS);
5445 +set_md5sum (int md5sum, int i)
5447 + set_generic(md5sum, i, NBD_MD5SUM);
5452 +set_enable (int enable, int i)
5454 + void set_e (void) {
5455 + struct nbd_device *lo = nbd_get(i);
5456 + if (!lo || lo->magic != NBD_DEV_MAGIC)
5458 + if (enable != 0) {
5459 + if (!(atomic_read (&lo->flags) & NBD_ENABLED)) {
5467 + if (i >= 0 && i < MAX_NBD) {
5471 + for (i = 0; i < MAX_NBD; i++) {
5477 +set_direct (int direct, int i)
5479 + set_generic(direct, i, NBD_DIRECT);
5482 +#ifndef NO_BUFFERED_WRITES
5484 +set_buffer_writes (int buffer_writes, int i)
5486 + set_generic(buffer_writes, i, NBD_BUFFERWR);
5491 +set_merge_requests (int mr, int i)
5493 + void set_mr (void) {
5494 + struct nbd_device *lo = nbd_get(i);
5495 + if (lo->magic != NBD_DEV_MAGIC)
5497 + atomic_set (&lo->merge_requests, mr);
5500 + if (i >= 0 && i < MAX_NBD) {
5504 + for (i = 0; i < MAX_NBD; i++) {
5510 +nbd_read_proc (char *buf, char **start, off_t offset, int len, int *eof,
5515 +#define MIN(x,y) ((x)<(y)?(x):(y))
5518 + const int limit = MIN (PAGE_SIZE, len) - 80;
5520 + struct nbd_device *lo;
5521 + struct nbd_acct *acct;
5523 + static void *next_label;
5524 + static char *next_label_name;
5526 + unsigned long flags;
5528 + if (offset > 0 && !next_label) {
5534 + if (offset <= 0) {
5535 + // PTB do static inits first time through
5538 + next_label = NULL;
5539 + next_label_name = NULL;
5543 + // PTB start this bytecount
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; \
5556 + for ( /* static init */ ; i < MAX_NBD; i++) {
5561 + devnam = lo->devnam;
5563 + if (lo->nslot <= 0) {
5564 + next_label = NULL;
5568 + // PTB computed goto next not-done
5570 + void *label = next_label;
5571 + next_label = NULL;
5572 + next_label_name = NULL;
5577 + NBD_PROC_LABEL (1);
5579 + if (last == i - 2) {
5580 + struct nbd_device * lo = nbd_get (i - 1);
5581 + char *prevdevnam = lo->devnam;
5583 + sprintf (buf + len, "Device %s:\tClosed\n",
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);
5594 + sprintf (buf + len, "Device %s-%s:\tClosed\n",
5595 + lastdevnam, prevdevnam);
5598 + NBD_PROC_LABEL (2);
5601 + sprintf (buf + len, "Device %s:\tOpen " "\n", devnam);
5603 + NBD_PROC_LABEL (3);
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",
5608 + atomic_read (&lo->flags)
5609 + & NBD_INITIALISED ? "" : "uninitialized, ",
5610 + atomic_read (&lo->flags)
5611 + & NBD_WRITE_NOCHK ? "noverify, " : "verify, ",
5612 + atomic_read (&lo->flags)
5613 + & NBD_READ_ONLY ? "ro, " : "rw, ",
5614 + atomic_read(&lo->merge_requests) ? "merge requests, " : "",
5615 +#ifndef NO_BUFFERED_WRITES
5616 + atomic_read (&lo->flags)
5617 + & NBD_BUFFERWR ? "buffer writes, " : "",
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, " : "",
5636 + lo->lives - ((atomic_read (&lo->flags) & NBD_ENABLED) ? 1 : 0), 0);
5638 + NBD_PROC_LABEL (4);
5640 + do { // PTB begin long do once block
5641 + int countq[2] = { 0, 0 };
5644 + struct list_head *pos;
5646 + read_lock_irqsave (&lo->queue_lock, flags);
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)
5654 + cmd = rq_data_dir (req);
5658 + read_unlock_irqrestore (&lo->queue_lock, flags);
5660 + len += sprintf (buf + len,
5661 + "[%s] Queued:\t+%dR/%dW curr (check %dR/%dW) +%dR/%dW max\n",
5663 + atomic_read (&acct->countq[READ]),
5664 + atomic_read (&acct->countq[WRITE]),
5665 + countq[READ], countq[WRITE],
5666 + atomic_read (&acct->maxq[READ]),
5667 + atomic_read (&acct->maxq[WRITE]));
5668 + } while (0); // PTB end long do once block
5670 + NBD_PROC_LABEL (5);
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));
5677 + sprintf (buf + len, "[%s] Blocksize:\t%d\t(log=%d)\n",
5678 + devnam, lo->blksize, lo->logblksize);
5680 + sprintf (buf + len, "[%s] Size:\t%luKB\n", devnam,
5681 + (unsigned long) (lo->bytesize >> 10));
5683 + sprintf (buf + len, "[%s] Blocks:\t%u\n", devnam,
5684 + lo->size >> (lo->logblksize - 10));
5686 + NBD_PROC_LABEL (6);
5689 + sprintf (buf + len, "[%s] Sockets:\t%d", devnam, lo->nslot);
5691 + NBD_PROC_LABEL (7);
5693 + do { // PTB begin short do once block
5695 + for (j = 0; j < lo->nslot; j++) {
5696 + struct nbd_slot *slotj = &lo->slots[j];
5697 + if (j != atomic_read (&lo->islot)) {
5699 + sprintf (buf + len, "\t(%s)",
5700 + slotj->file ? "+" : "-");
5703 + sprintf (buf + len, "\t(%s)",
5704 + slotj->file ? "*" : ".");
5707 + } while (0); // PTB end short do once block
5709 + len += sprintf (buf + len, "\n");
5711 + NBD_PROC_LABEL (8);
5713 + len += sprintf (buf + len, "[%s] Requested:\t%s", devnam,
5714 + display (atomic_read(&acct->requests_in[READ]) +
5715 + atomic_read(&acct->requests_in[WRITE]), 7));
5717 + NBD_PROC_LABEL (9);
5719 + do { // PTB begin short do once block
5722 + for (j = 0; j < lo->nslot; j++) {
5723 + struct nbd_slot *slotj = &lo->slots[j];
5725 + sprintf (buf + len, "\t(%s)",
5726 + display (slotj->in, 5));
5729 + display (atomic_read
5730 + (&acct->requests_in[READ]), 6), 7);
5732 + display (atomic_read
5733 + (&acct->requests_in[WRITE]), 6),
5736 + sprintf (buf + len, "\t%sR/%sW", buff[0],
5738 + lo->set_speed (lo);
5739 + len += sprintf (buf + len, "\tmax %d",
5740 + atomic_read (&acct->maxreqblks));
5741 + } while (0); // PTB end short do once block
5743 + len += sprintf (buf + len, "\n");
5744 + len += sprintf (buf + len, "[%s] Despatched:\t%s", devnam,
5745 + display (atomic_read(&acct->requests_out[READ]) +
5746 + atomic_read(&acct->requests_out[WRITE]), 7));
5748 + NBD_PROC_LABEL (10);
5750 + do { // PTB begin short do once block
5753 + for (j = 0; j < lo->nslot; j++) {
5754 + struct nbd_slot *slotj = &lo->slots[j];
5756 + sprintf (buf + len, "\t(%s)",
5757 + display (slotj->out, 5));
5760 + display (atomic_read(&acct->requests_out[READ]), 6), 7);
5762 + display (atomic_read(&acct->requests_out[WRITE]), 6), 7);
5764 + sprintf (buf + len, "\t%sR/%sW", buff[0], buff[1]);
5766 + sprintf (buf + len, "\tmd5 %sW",
5767 + display (atomic_read(&lo->wrequests_5to), 5));
5769 + sprintf (buf + len, " (%s eq,",
5770 + display (atomic_read (&lo->wrequests_5so), 5));
5772 + sprintf (buf + len, " %s ne,",
5773 + display (atomic_read(&lo->wrequests_5wo), 5));
5775 + sprintf (buf + len, " %s dn)",
5776 + display (atomic_read (&lo->wrequests_5eo), 5));
5777 + } while (0); // PTB end short do once block
5779 + len += sprintf (buf + len, "\n");
5780 + len += sprintf (buf + len, "[%s] Errored:\t%s", devnam,
5781 + display (atomic_read (&acct->requests_err), 7));
5783 + NBD_PROC_LABEL (11);
5785 + do { // PTB begin short do once block
5790 + for (j = 0; j < lo->nslot; j++) {
5791 + struct nbd_slot *slotj = &lo->slots[j];
5793 + sprintf (buf + len, "\t(%s)",
5794 + display (slotj->err, 5));
5795 + toterrs += slotj->err;
5797 + strncpy (buff[0], display (toterrs, 6), 7);
5799 + display (atomic_read (&acct->requests_err)-toterrs, 6), 7);
5801 + sprintf (buf + len, "\t%s+%s\n", buff[0],
5803 + } while (0); // PTB end short do once block
5805 + NBD_PROC_LABEL (12);
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 */
5812 + read_lock_irqsave (&lo->queue_lock, flags);
5814 + do { // PTB begin short do once block
5815 + struct list_head *pos;
5818 + struct request *req;
5820 + list_for_each (pos, &lo->queue) {
5822 + list_entry (pos, struct request,
5824 + if (count++ > 1000)
5826 + blks = req->nr_sectors / lo->blksize;
5828 + switch (rq_data_dir (req)) {
5840 + } while (0); // PTB end short do once block
5842 + read_unlock_irqrestore (&lo->queue_lock, flags);
5844 + sprintf (buf + len, "[%s] Pending:\t%d", devnam,
5845 + atomic_read (&acct->requests_req[READ]) +
5846 + atomic_read (&acct->requests_req[WRITE]));
5848 + do { // PTB begin short do once block
5850 + for (j = 0; j < lo->nslot; j++) {
5851 + struct nbd_slot *slotj =
5854 + sprintf (buf + len, "\t(%d)",
5857 + } while (0); // PTB end short do once block
5859 + len += sprintf (buf + len,
5860 + "\t%dR/%dW+%dR/%dW\n",
5861 + atomic_read (&acct->requests_req[READ]),
5862 + atomic_read (&acct->requests_req[WRITE]),
5863 + pending_rblks, pending_wblks);
5865 + } while (0); // PTB end long do once block
5867 + NBD_PROC_LABEL (13);
5869 + do { // PTB begin long do once block
5871 + int shift = lo->logblksize;
5874 + display (atomic_read (&lo->wspeed.speed) << shift, 5), 7);
5876 + display (atomic_read(&lo->wspeed.speedav) << shift, 5), 7);
5878 + display (atomic_read(&lo->wspeed.speedmax) << shift,
5882 + display (atomic_read (&lo->rspeed.speed) << shift, 5), 7);
5884 + display (atomic_read (&lo->rspeed.speedav) << shift, 5), 7);
5886 + display (atomic_read (&lo->rspeed.speedmax) << shift, 5), 7);
5889 + display (atomic_read (&lo->tspeed.speed) << shift, 5), 7);
5891 + display (atomic_read (&lo->tspeed.speedav) << shift, 5), 7);
5893 + display (atomic_read (&lo->tspeed.speedmax) << shift, 5), 7);
5896 + sprintf (buf + len, "[%s] B/s now:", devnam);
5898 + sprintf (buf + len, "\t%s\t(%sR+%sW)\n", buff[6],
5899 + buff[3], buff[0]);
5901 + sprintf (buf + len, "[%s] B/s ave:", devnam);
5903 + sprintf (buf + len, "\t%s\t(%sR+%sW)\n", buff[7],
5904 + buff[4], buff[1]);
5906 + sprintf (buf + len, "[%s] B/s max:", devnam);
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
5912 + do { // PTB begin short do once block
5917 + sprintf (buf + len, "[%s] Spectrum:", devnam);
5919 + blks <= atomic_read (&acct->maxreqblks); blks++) {
5921 + atomic_read (&acct->req_in[READ][blks]) +
5922 + atomic_read (&acct->req_in[WRITE][blks]);
5926 + blks <= atomic_read (&acct->maxreqblks); blks++) {
5928 + atomic_read (&acct->req_in[READ][blks])
5929 + + atomic_read (&acct->req_in[WRITE][blks]);
5932 + 0 ? (100 * req_blks) / tot_reqs : 0;
5936 + sprintf (buf + len, "\t%u%%%d", percent,
5939 + len += sprintf (buf + len, "\n");
5940 + } while (0); // PTB end short do once block
5942 + NBD_PROC_LABEL (14);
5944 + len += sprintf (buf + len, "[%s] Kthreads:\t%d", devnam,
5945 + atomic_read (&acct->kthreads));
5947 + sprintf (buf + len, "\t(%d waiting/%d running/%d max)\n",
5948 + atomic_read (&acct->kwaiters),
5949 + atomic_read (&acct->kthreads) -
5950 + atomic_read (&acct->kwaiters),
5951 + atomic_read (&acct->kmax));
5953 + NBD_PROC_LABEL (15);
5955 + len += sprintf (buf + len, "[%s] Cthreads:\t%d", devnam,
5956 + atomic_read (&acct->cthreads));
5958 + NBD_PROC_LABEL (16);
5962 + for (j = 0; j < lo->nslot; j++) {
5963 + struct nbd_slot *slotj = &lo->slots[j];
5965 + ((slotj->flags & NBD_SLOT_RUNNING) ? 1 :
5967 + ((slotj->flags & NBD_SLOT_WAITING) ? 2 :
5973 + break; /* PTB not in */
5976 + break; /* PTB in and not waiting */
5979 + break; /* PTB impossible */
5982 + break; /* PTB in and waiting */
5984 + len += sprintf (buf + len, "\t(%s)", desc);
5988 + len += sprintf (buf + len, "\n");
5990 + NBD_PROC_LABEL (17);
5993 + len += sprintf (buf + len, "[%s] Cpids:\t%d", devnam,
5994 + atomic_read (&acct->cthreads));
5998 + for (j = 0; j < lo->nslot; j++) {
5999 + struct nbd_slot *slotj = &lo->slots[j];
6001 + sprintf (buf + len, "\t(%u)", slotj->pid);
6003 + len += sprintf (buf + len, "\n");
6008 + for (j = 0; j < lo->nslot; j++) {
6009 + struct nbd_slot *slotj = &lo->slots[j];
6010 + if (slotj->spid != 0)
6013 + if (j < lo->nslot) {
6015 + sprintf (buf + len, "[%s] Kpids:\t%d",
6017 + atomic_read (&acct->cthreads));
6018 + for (k = 0; k < lo->nslot; k++) {
6019 + struct nbd_slot *slotk =
6022 + sprintf (buf + len, "\t(%u)",
6025 + len += sprintf (buf + len, "\n");
6029 + NBD_PROC_LABEL (18);
6031 + NBD_PROC_LABEL (19);
6033 + // PTB have to tell loop head that we are not reentering
6034 + next_label = NULL;
6035 + next_label_name = NULL;
6038 + NBD_PROC_LABEL (20);
6040 + if (last == i - 2) {
6041 + struct nbd_device * lo = nbd_get (i - 1);
6042 + char *prevnam = lo->devnam;
6044 + sprintf (buf + len, "Device %s:\tClosed\n", prevnam);
6047 + if (last < i - 2) {
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);
6058 + NBD_PROC_LABEL (21);
6060 + // PTB re-init vital statistics for next time
6061 + next_label = NULL;
6062 + next_label_name = NULL;
6072 + * PTB read an int from a string. Return number of ints read (0 or 1).
6075 +sscani (char *buf, int len, int *n)
6079 + short has_digits = 0;
6080 + short is_signed = 0;
6082 + // PTB look for first significant character
6083 + for (i = 0; i < len; i++) {
6085 + if (c == ' ' || c == '\t') {
6088 + } else if (c == '-') {
6092 + } else if (c == '+') {
6096 + } else if (c >= '0' && c <= '9') {
6104 + // PTB i now points at first digit if there is one
6107 + for (; i < len; i++) {
6109 + if (c < '0' || c > '9')
6114 + if (is_signed >= 0) {
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).
6128 +sscana (char *buf, int len, int *n)
6132 + short has_letters = 0;
6134 + for (i = 0; i < len; i++) {
6136 + if (c >= 'a' && c <= 'z') {
6139 + } else if (c == ' ') {
6148 + for (; i < len; i++) {
6150 + if (c < 'a' || c > 'z')
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
6163 + * @i is the integer value that results
6164 + * @j is an index if one one supplied (foo[j] = i ), else -1
6167 +getarg (const char *buffer, int buflen, const char *key, int *i, int *j)
6172 + void skip_ws (void) {
6173 + while (buflen > 0) {
6174 + if (*buffer != ' ' && *buffer != '\t')
6183 + keylen = strlen (key);
6184 + if (strncmp (buffer, key, keylen))
6193 + if (*buffer == '[') {
6202 + closing = strchr (buffer, ']');
6205 + indexlen = closing - buffer;
6208 + if (sscani ((char *) buffer, indexlen, j) < 1)
6210 + if (sscana ((char *) buffer, buflen, j) < 1)
6214 + buflen -= indexlen;
6222 + if (*buffer != '=')
6230 + if (sscani ((char *) buffer, buflen, i) < 1)
6232 + if (sscana ((char *) buffer, buflen, i) < 1)
6238 + * PTB - write a 0 with echo -n 0 to /proc/nbdinfo to do a hard reset.
6241 +nbd_write_proc (struct file *file, const char *buffer, unsigned long count,
6250 + if (buffer[1] != '\n')
6252 + /* else fallthru to case 1 */
6254 + switch (*buffer) {
6256 + for (i = 0; i < MAX_NBD; i++) {
6257 + struct nbd_device *lo = nbd_get(i);
6258 + lo->hard_reset (lo);
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);
6274 + int merge_requests;
6278 +#ifndef NO_BUFFERED_WRITES
6279 + int buffer_writes;
6285 + if (getarg (buffer, count, "merge_requests",
6286 + &merge_requests, &index) >= 0) {
6288 + set_merge_requests (merge_requests, index);
6291 + if (getarg (buffer, count, "sync_intvl",
6292 + &sync_intvl, &index) >= 0
6293 + || getarg (buffer, count, "sync",
6294 + &sync_intvl, &index) >= 0) {
6296 + set_sync_intvl (sync_intvl, index);
6299 + if (getarg (buffer, count, "show_errs",
6300 + &show_errs, &index) >= 0) {
6302 + set_show_errs (show_errs, index);
6305 + if (getarg (buffer, count, "md5sum",
6306 + &md5sum, &index) >= 0) {
6308 + set_md5sum (md5sum, index);
6311 +#ifndef NO_BUFFERED_WRITES
6312 + if (getarg (buffer, count, "buffer_writes",
6313 + &buffer_writes, &index) >= 0) {
6315 + set_buffer_writes (buffer_writes, index);
6318 +#endif /* NO_BUFFERED_WRITES */
6319 + if (getarg (buffer, count, "enable",
6320 + &enable, &index) >= 0) {
6322 + set_enable (enable, index);
6325 + if (getarg (buffer, count, "direct",
6326 + &direct, &index) >= 0) {
6328 + set_direct(direct, index);
6331 + if (getarg (buffer, count, "reset",
6332 + &reset, &index) >= 0) {
6334 + do_reset(reset, index);
6337 + NBD_ERROR ("illegal %ld character command\n",
6347 +nbd_init_proc(struct proc_dir_entry *res) {
6348 + res->read_proc = nbd_read_proc;
6349 + res->write_proc = nbd_write_proc;
6352 diff -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
6356 +#include <linux/enbd.h>
6359 +#define _NBD_GENERATION (8*sizeof(int) - __REQ_NBDSEQNO)
6361 + * PTB increment the devices seqno
6363 + * @lo the nbd device to increment the seqno of
6366 +seqno_inc(struct nbd_seqno *nseqno)
6368 + if (nseqno->seqno < (1 << _NBD_GENERATION)) {
6372 + // PTB next generation !
6373 + nseqno->seqno = 0;
6374 + atomic_inc (&nseqno->seqno_gen);
6377 +seqno_get (struct nbd_seqno *nseqno)
6379 + return nseqno->seqno;
6382 +seqno_reset (struct nbd_seqno *nseqno)
6384 + nseqno->seqno = 0;
6385 + atomic_set(&nseqno->seqno_gen,0);
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
6392 + * We add the current generation no. to small seqnos, and we add the
6393 + * previous generation no. to large seqnos.
6395 + * @lo the nbd device to look at
6396 + * @seqno the small sequence number to return the full seq number for
6398 +static unsigned int
6399 +seqno_calc (struct nbd_seqno *nseqno, unsigned int seqno)
6401 + unsigned int genno;
6402 + static unsigned int absdiff(unsigned int x, unsigned int y) {
6409 + genno = atomic_read (&nseqno->seqno_gen);
6410 + if (absdiff(seqno,nseqno->seqno) < (1 << (_NBD_GENERATION - 1))) {
6411 + return seqno + (genno << _NBD_GENERATION);
6413 + if (seqno < nseqno->seqno) {
6414 + return seqno + ((genno + 1) << _NBD_GENERATION);
6416 + return seqno + ((genno - 1) << _NBD_GENERATION);
6419 +void nbd_init_seqno (struct nbd_seqno *nseqno) {
6421 + seqno_reset(nseqno);
6423 + nseqno->inc = seqno_inc;
6424 + nseqno->get = seqno_get;
6425 + nseqno->reset = seqno_reset;
6426 + nseqno->calc = seqno_calc;
6431 diff -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
6435 +#include <linux/enbd.h>
6436 +#include <linux/enbd_ioctl.h>
6439 + * PTB - update speed counters (if at least 5s has passed)
6441 + * @spd the speed struct to update
6444 +spd_update (struct nbd_speed *spd, int distance)
6447 + // last time we measured
6448 + int lastjiffy = atomic_read (&spd->jiffy);
6449 + // jiffies since last time
6450 + int djiffy = jiffies - lastjiffy;
6452 + // previous no we measured
6453 + int lastdist = atomic_read (&spd->distance);
6454 + // blocks since last time
6455 + int ddistance = distance - lastdist;
6457 + // write every 5 second in time
6458 + if (djiffy > 5 * HZ) {
6460 + // jiffies since first time
6461 + int tjiffy = jiffies - atomic_read (&spd->frstj);
6463 + // max tot speed measured so far
6464 + int speedmax = atomic_read (&spd->speedmax);
6466 + // last instantaneous speed we measured
6467 + int lastspeed = atomic_read (&spd->speed);
6469 + // instantaneous read blocks/s
6470 + int speed = djiffy ? (ddistance * HZ) / djiffy : 0;
6473 + int speedsmoothed =
6474 + (djiffy * speed + HZ * lastspeed) / (djiffy + HZ);
6476 + // average speed to now in KB/s
6477 + int speedav = tjiffy ? (distance * HZ) / tjiffy : 0;
6479 + // smoothing count for max
6481 + (speedav > speedsmoothed) ? speedav : speedsmoothed;
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);
6494 +nbd_init_speed(struct nbd_speed *spd) {
6495 + memset(spd, 0, sizeof(*spd));
6496 + spd->update = spd_update;
6499 diff -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
6503 +#ifndef LINUX_ENBD_H
6504 +#define LINUX_ENBD_H
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)
6514 +#include <asm/types.h>
6516 +#ifndef NBD_VERSION
6517 +#define NBD_VERSION "2.4.30 $Date$"
6518 +#endif /*NBD_VERSION*/
6521 + * Third type of request apart from READ or WRITE
6536 + # define SPECIAL 4
6540 + * We need extra bits of req->flags
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!
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)
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 */
6596 +#if defined(MAJOR_NR) || defined(__KERNEL__)
6597 + /* PTB we are included from the kernel nbd.c file so put kernel stuff here */
6599 + #include <linux/config.h>
6601 + #define ENDREQ_NOCURRENT
6602 + #define LOCAL_END_REQUEST
6603 + #include <linux/blk.h>
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
6617 + * PTB User messaging defs.
6620 + #define NBD_ID "NBD #%d[%d]: %s "
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);}
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 */
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));
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);
6682 + struct nbd_md_list {
6683 + struct list_head list;
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);
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 */
6715 + struct nbd_device {
6718 + #define NBD_READ_ONLY 0x0001
6719 + #define NBD_WRITE_NOCHK 0x0002
6720 + #define NBD_INITIALISED 0x0004
6721 + #define NBD_SIGNED 0x0008
6723 + #define NBD_ENABLED 0x0010
6724 + #define NBD_SIZED 0x0020
6725 + #define NBD_BLKSIZED 0x0040
6727 + #define NBD_QBLOCKED 0x0100
6728 + #define NBD_SHOW_ERRS 0x0200
6729 + #define NBD_SYNC 0x0400
6730 + #define NBD_VALIDATED 0x0800 /* read partition table */
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
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*/
6747 + struct nbd_acct acct;
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 */
6754 + struct nbd_seqno seqno_out; /* PTB add - seq number */
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 */
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 */
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);
6803 +#endif /* MAJOR_NR */
6807 +/* Pavel - This now IS in some kind of include file... */
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.
6816 +#define NBD_DEV_MAGIC 0x68797548
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
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
6833 +#define NBD_REQUEST_HANDLE_T __u32
6834 +#define NBD_REPLY_HANDLE_T __u32
6836 + typedef __u32 nbd_digest_t[4];
6838 + #define NBD_DIGEST_T nbd_digest_t
6840 +#define NBD_REQUEST_DIGEST_T nbd_digest_t
6841 +#define NBD_REPLY_DIGEST_T nbd_digest_t
6844 +#define NBD_DIGEST_BITS 128
6845 +#define NBD_DIGEST_LENGTH ((NBD_DIGEST_BITS)/8)
6846 +#define NBD_REQUEST_SEQNO_T __u32
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;
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;
6867 + NBD_REQUEST_DIGEST_T digest;
6869 + NBD_REQUEST_SPECIAL_T special;
6871 + char dummy1[0] __attribute__ ((aligned (64)));
6872 +} __attribute__ ((packed)) ;
6874 + #define NBD_REQUEST_LENGTH sizeof(struct nbd_request)
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 */
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;
6892 + NBD_REPLY_DIGEST_T digest;
6895 + char dummy1[0] __attribute__ ((aligned (64)));
6896 +} __attribute__ ((packed)) ;
6898 + #define NBD_REPLY_LENGTH sizeof(struct nbd_reply)
6900 + #define NBD_BUFFER_DATA_OFFSET \
6901 + ((NBD_REQUEST_LENGTH>NBD_REPLY_LENGTH)?NBD_REQUEST_LENGTH:NBD_REPLY_LENGTH)
6905 + // PTB forward declaration
6906 + static struct nbd_device nbd_dev[];
6909 + static long wait_for_completion_timeout(struct completion *x, long timeout)
6911 + spin_lock_irq(&x->wait.lock);
6912 + if (!x->done && timeout > 0) {
6913 + DECLARE_WAITQUEUE(wait, current);
6915 + wait.flags |= WQ_FLAG_EXCLUSIVE;
6916 + __add_wait_queue_tail(&x->wait, &wait);
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);
6930 + spin_unlock_irq(&x->wait.lock);
6934 + static void end_request(struct request *req, int uptodate) {
6937 + struct nbd_device *lo = req->rq_disk->private_data;
6938 + static int rq_type(struct request *);
6939 + struct nbd_acct * acct = &lo->acct;
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.
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);
6957 + if (req->flags & REQ_SPECIAL)
6958 + // don't account specials
6961 + write_lock(&lo->altqueue_lock);
6962 + if (atomic_read(&acct->countq[READ])
6963 + + atomic_read(&acct->countq[WRITE]) <= 0) {
6964 + if (atomic_read(&lo->flags) & NBD_QBLOCKED) {
6965 + static int nbd_requeue(struct nbd_device *);
6967 + atomic_clear_mask(NBD_QBLOCKED, &lo->flags);
6970 + write_unlock(&lo->altqueue_lock);
6974 + * PTB This takes the spinlock itself! So call it with the io spinlock
6977 + static void end_request_lock(struct request *req, int uptodate) {
6979 + unsigned long flags;
6980 + request_queue_t *q = req->q;
6982 + spin_lock_irqsave(q->queue_lock, flags);
6983 + end_request(req, uptodate);
6984 + spin_unlock_irqrestore(q->queue_lock, flags);
6988 + * PTB Call this only with the io spinlock * held.
6990 + static inline void nbd_end_request(struct request *req) {
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);
6997 + rq_set_seqno(req, 0); // PTB Zero extra seqno info
6998 + end_request( req, (req->errors == 0) ? 1 : 0 );
7002 + * PTB This takes the spinlock itself! So call it with the io spinlock
7005 + static void nbd_end_request_lock(struct request *req) {
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);
7012 + rq_set_seqno(req, 0); // PTB Zero extra seqno info
7013 + end_request_lock( req, !req->errors );
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);
7021 + #endif /* MAJOR_NR */
7023 +#endif /* LINUX_ENBD_H */
7026 diff -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
7030 +#ifndef NBD_IOCTL_H
7031 +#define NBD_IOCTL_H 1
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);
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);
7043 + * PTB object containing all the above methods, to be registered with
7044 + * the enbd.o module
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);
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 *);
7064 +extern struct nbd_ioctl_stub nbd_remote_ioctl;
7065 +extern int nbd_init_ioctl_stub(struct nbd_ioctl_stub *);
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
7074 +// PTB extended conversion table entries
7075 +struct ioctl_special {
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);
7083 +extern int nbd_init_ioctl_stub(struct nbd_ioctl_stub *);
7085 +#endif /* NBD_IOCTL_H */