]> git.karo-electronics.de Git - mv-sheeva.git/commitdiff
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 6 Jan 2009 02:45:06 +0000 (18:45 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 6 Jan 2009 02:45:06 +0000 (18:45 -0800)
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6: (30 commits)
  sparc: Fix minor SPARC32 compile error
  sparc: Remove reg*.h from Kbuild
  sparc: Clean arch-specific code in prom_common.c
  sparc: Kill asm/reg*.h
  sparc: Use 64BIT config entry
  MAINTAINERS: update sparc maintainer
  sparc: unify ipcbuf.h
  sparc: Update 64-bit defconfig.
  sparc: remove NO_PROC_ID - it is no longer used
  sparc: drop get_tbr() in traps.h
  sparc: fix warning in userspace header traps.h
  sparc: fix warnings in userspace header byteorder.h
  sparc: fix warning in userspace header jsflash.h
  sparc: unify openprom.h
  sparc64: delete unused linux_prom64_ranges from openprom_64.h
  sparc: prepare openprom for unification
  sparc: remove linux_prom_pci_assigned_addresses from openprom_32.h
  sparc: remove ebus definitions from openprom*.h
  sparc: unify siginfo.h
  sparc: unify ptrace.h
  ...

696 files changed:
CREDITS
Documentation/cputopology.txt
Documentation/filesystems/ocfs2.txt
Documentation/filesystems/ubifs.txt
Documentation/ioctl/ioctl-number.txt
Documentation/kbuild/00-INDEX
Documentation/kbuild/kbuild.txt [new file with mode: 0644]
Documentation/kbuild/kconfig.txt [new file with mode: 0644]
Documentation/video4linux/CARDLIST.saa7134
Documentation/video4linux/si470x.txt
Documentation/video4linux/v4l2-framework.txt
Makefile
README
arch/alpha/include/asm/topology.h
arch/alpha/kernel/Makefile
arch/alpha/kernel/binfmt_loader.c [new file with mode: 0644]
arch/alpha/kernel/irq.c
arch/alpha/kernel/setup.c
arch/avr32/include/asm/bitops.h
arch/blackfin/include/asm/bitops.h
arch/cris/include/asm/bitops.h
arch/h8300/include/asm/bitops.h
arch/ia64/Kconfig
arch/ia64/include/asm/irq.h
arch/ia64/include/asm/kvm_host.h
arch/ia64/include/asm/topology.h
arch/ia64/kernel/acpi.c
arch/ia64/kernel/iosapic.c
arch/ia64/kernel/irq.c
arch/ia64/kernel/time.c
arch/ia64/kvm/Makefile
arch/ia64/kvm/kvm-ia64.c
arch/ia64/sn/kernel/sn2/sn_hwperf.c
arch/m32r/kernel/smpboot.c
arch/m68k/Kconfig
arch/m68knommu/include/asm/bitops.h
arch/mips/include/asm/mach-ip27/topology.h
arch/parisc/include/asm/smp.h
arch/powerpc/include/asm/topology.h
arch/powerpc/kernel/process.c
arch/powerpc/kernel/time.c
arch/powerpc/platforms/cell/spu_priv1_mmio.c
arch/powerpc/platforms/cell/spufs/inode.c
arch/powerpc/platforms/cell/spufs/sched.c
arch/s390/hypfs/inode.c
arch/s390/include/asm/cpu.h
arch/s390/include/asm/cputime.h
arch/s390/include/asm/lowcore.h
arch/s390/include/asm/system.h
arch/s390/include/asm/thread_info.h
arch/s390/include/asm/timer.h
arch/s390/include/asm/topology.h
arch/s390/include/asm/vdso.h
arch/s390/kernel/asm-offsets.c
arch/s390/kernel/entry.S
arch/s390/kernel/entry64.S
arch/s390/kernel/head64.S
arch/s390/kernel/process.c
arch/s390/kernel/s390_ext.c
arch/s390/kernel/setup.c
arch/s390/kernel/smp.c
arch/s390/kernel/topology.c
arch/s390/kernel/vdso.c
arch/s390/kernel/vdso64/clock_getres.S
arch/s390/kernel/vdso64/clock_gettime.S
arch/s390/kernel/vtime.c
arch/sh/include/asm/topology.h
arch/sparc/include/asm/topology_64.h
arch/sparc/kernel/of_device_64.c
arch/sparc/kernel/pci_msi.c
arch/um/Makefile
arch/um/include/asm/system.h
arch/x86/Kconfig
arch/x86/Kconfig.cpu
arch/x86/ia32/ia32_signal.c
arch/x86/ia32/ipc32.c
arch/x86/ia32/sys_ia32.c
arch/x86/include/asm/amd_iommu_types.h
arch/x86/include/asm/apic.h
arch/x86/include/asm/efi.h
arch/x86/include/asm/es7000/apic.h
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/lguest.h
arch/x86/include/asm/mpspec.h
arch/x86/include/asm/numaq/apic.h
arch/x86/include/asm/pci.h
arch/x86/include/asm/pci_x86.h [moved from arch/x86/pci/pci.h with 88% similarity]
arch/x86/include/asm/summit/apic.h
arch/x86/include/asm/sys_ia32.h [new file with mode: 0644]
arch/x86/include/asm/topology.h
arch/x86/include/asm/uv/uv_bau.h
arch/x86/kernel/acpi/boot.c
arch/x86/kernel/amd_iommu.c
arch/x86/kernel/amd_iommu_init.c
arch/x86/kernel/apic.c
arch/x86/kernel/bios_uv.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
arch/x86/kernel/cpu/cpufreq/p4-clockmod.c
arch/x86/kernel/cpu/cpufreq/powernow-k7.c
arch/x86/kernel/cpu/cpufreq/powernow-k8.c
arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c
arch/x86/kernel/cpu/cpufreq/speedstep-lib.c
arch/x86/kernel/cpu/intel_cacheinfo.c
arch/x86/kernel/cpu/mtrr/main.c
arch/x86/kernel/cpuid.c
arch/x86/kernel/early_printk.c
arch/x86/kernel/genx2apic_phys.c
arch/x86/kernel/head64.c
arch/x86/kernel/io_apic.c
arch/x86/kernel/ldt.c
arch/x86/kernel/mmconf-fam10h_64.c
arch/x86/kernel/mpparse.c
arch/x86/kernel/msr.c
arch/x86/kernel/nmi.c
arch/x86/kernel/pci-gart_64.c
arch/x86/kernel/reboot.c
arch/x86/kernel/setup_percpu.c
arch/x86/kernel/smpboot.c
arch/x86/kernel/tlb_uv.c
arch/x86/kernel/traps.c
arch/x86/kernel/xsave.c
arch/x86/kvm/Makefile
arch/x86/kvm/x86.c
arch/x86/mach-default/setup.c
arch/x86/mach-voyager/voyager_smp.c
arch/x86/pci/acpi.c
arch/x86/pci/amd_bus.c
arch/x86/pci/common.c
arch/x86/pci/direct.c
arch/x86/pci/early.c
arch/x86/pci/fixup.c
arch/x86/pci/i386.c
arch/x86/pci/init.c
arch/x86/pci/irq.c
arch/x86/pci/legacy.c
arch/x86/pci/mmconfig-shared.c
arch/x86/pci/mmconfig_32.c
arch/x86/pci/mmconfig_64.c
arch/x86/pci/numaq_32.c
arch/x86/pci/olpc.c
arch/x86/pci/pcbios.c
arch/x86/pci/visws.c
arch/x86/xen/time.c
block/blk.h
drivers/acpi/processor_core.c
drivers/acpi/processor_perflib.c
drivers/acpi/processor_throttling.c
drivers/base/Makefile
drivers/base/cpu.c
drivers/base/iommu.c [new file with mode: 0644]
drivers/char/random.c
drivers/cpufreq/cpufreq.c
drivers/infiniband/hw/ehca/ehca_irq.c
drivers/infiniband/hw/ipath/ipath_file_ops.c
drivers/infiniband/hw/ipath/ipath_fs.c
drivers/isdn/capi/capidrv.c
drivers/isdn/capi/capifs.c
drivers/media/common/saa7146_fops.c
drivers/media/common/saa7146_video.c
drivers/media/common/tuners/tuner-simple.c
drivers/media/dvb/dvb-core/dvbdev.c
drivers/media/dvb/dvb-usb/gp8psk.c
drivers/media/dvb/frontends/cx24116.c
drivers/media/dvb/frontends/cx24116.h
drivers/media/dvb/frontends/stb0899_drv.c
drivers/media/dvb/frontends/zl10353.c
drivers/media/dvb/siano/sms-cards.c
drivers/media/dvb/ttpci/av7110_v4l.c
drivers/media/dvb/ttpci/budget-av.c
drivers/media/dvb/ttusb-budget/Kconfig
drivers/media/dvb/ttusb-dec/Kconfig
drivers/media/radio/Kconfig
drivers/media/radio/Makefile
drivers/media/radio/dsbr100.c
drivers/media/radio/radio-aimslab.c
drivers/media/radio/radio-aztech.c
drivers/media/radio/radio-cadet.c
drivers/media/radio/radio-gemtek-pci.c
drivers/media/radio/radio-gemtek.c
drivers/media/radio/radio-maestro.c
drivers/media/radio/radio-maxiradio.c
drivers/media/radio/radio-mr800.c
drivers/media/radio/radio-rtrack2.c
drivers/media/radio/radio-sf16fmi.c
drivers/media/radio/radio-sf16fmr2.c
drivers/media/radio/radio-si470x.c
drivers/media/radio/radio-tea5764.c [new file with mode: 0644]
drivers/media/radio/radio-terratec.c
drivers/media/radio/radio-trust.c
drivers/media/radio/radio-typhoon.c
drivers/media/radio/radio-zoltrix.c
drivers/media/video/Makefile
drivers/media/video/arv.c
drivers/media/video/bt8xx/bttv-driver.c
drivers/media/video/bw-qcam.c
drivers/media/video/c-qcam.c
drivers/media/video/cafe_ccic.c
drivers/media/video/cpia.c
drivers/media/video/cpia2/cpia2_v4l.c
drivers/media/video/cs5345.c
drivers/media/video/cs53l32a.c
drivers/media/video/cx18/cx18-fileops.c
drivers/media/video/cx18/cx18-fileops.h
drivers/media/video/cx18/cx18-i2c.c
drivers/media/video/cx18/cx18-i2c.h
drivers/media/video/cx18/cx18-ioctl.c
drivers/media/video/cx18/cx18-ioctl.h
drivers/media/video/cx18/cx18-streams.c
drivers/media/video/cx23885/cx23885-417.c
drivers/media/video/cx23885/cx23885-video.c
drivers/media/video/cx25840/cx25840-core.c
drivers/media/video/cx88/cx88-blackbird.c
drivers/media/video/cx88/cx88-mpeg.c
drivers/media/video/cx88/cx88-video.c
drivers/media/video/cx88/cx88.h
drivers/media/video/em28xx/em28xx-audio.c
drivers/media/video/em28xx/em28xx-core.c
drivers/media/video/em28xx/em28xx-reg.h
drivers/media/video/em28xx/em28xx-video.c
drivers/media/video/em28xx/em28xx.h
drivers/media/video/et61x251/et61x251_core.c
drivers/media/video/gspca/gspca.c
drivers/media/video/hexium_gemini.c
drivers/media/video/hexium_orion.c
drivers/media/video/ivtv/ivtv-driver.c
drivers/media/video/ivtv/ivtv-fileops.c
drivers/media/video/ivtv/ivtv-fileops.h
drivers/media/video/ivtv/ivtv-ioctl.c
drivers/media/video/ivtv/ivtv-streams.c
drivers/media/video/m52790.c
drivers/media/video/meye.c
drivers/media/video/msp3400-driver.c
drivers/media/video/mt9m001.c
drivers/media/video/mt9m111.c
drivers/media/video/mt9t031.c
drivers/media/video/mt9v022.c
drivers/media/video/mxb.c
drivers/media/video/omap24xxcam.c
drivers/media/video/ov511.c
drivers/media/video/ov7670.c
drivers/media/video/ov772x.c
drivers/media/video/pms.c
drivers/media/video/pvrusb2/pvrusb2-hdw.c
drivers/media/video/pvrusb2/pvrusb2-hdw.h
drivers/media/video/pvrusb2/pvrusb2-v4l2.c
drivers/media/video/pwc/pwc-ctrl.c
drivers/media/video/pwc/pwc-if.c
drivers/media/video/pwc/pwc-v4l.c
drivers/media/video/pwc/pwc.h
drivers/media/video/s2255drv.c
drivers/media/video/saa5246a.c
drivers/media/video/saa5249.c
drivers/media/video/saa7115.c
drivers/media/video/saa7127.c
drivers/media/video/saa7134/saa6752hs.c
drivers/media/video/saa7134/saa7134-cards.c
drivers/media/video/saa7134/saa7134-dvb.c
drivers/media/video/saa7134/saa7134-empress.c
drivers/media/video/saa7134/saa7134-input.c
drivers/media/video/saa7134/saa7134-video.c
drivers/media/video/saa7134/saa7134.h
drivers/media/video/saa717x.c
drivers/media/video/se401.c
drivers/media/video/sn9c102/sn9c102_core.c
drivers/media/video/soc_camera.c
drivers/media/video/stk-webcam.c
drivers/media/video/stradis.c
drivers/media/video/stv680.c
drivers/media/video/tda9840.c
drivers/media/video/tea6415c.c
drivers/media/video/tea6420.c
drivers/media/video/tuner-core.c
drivers/media/video/tvaudio.c
drivers/media/video/tvp5150.c
drivers/media/video/tw9910.c
drivers/media/video/upd64031a.c
drivers/media/video/upd64083.c
drivers/media/video/usbvideo/usbvideo.c
drivers/media/video/usbvideo/vicam.c
drivers/media/video/usbvision/usbvision-video.c
drivers/media/video/uvc/uvc_v4l2.c
drivers/media/video/uvc/uvcvideo.h
drivers/media/video/v4l1-compat.c
drivers/media/video/v4l2-common.c
drivers/media/video/v4l2-compat-ioctl32.c
drivers/media/video/v4l2-dev.c
drivers/media/video/v4l2-ioctl.c
drivers/media/video/v4l2-subdev.c
drivers/media/video/vino.c
drivers/media/video/vivi.c
drivers/media/video/vp27smpx.c
drivers/media/video/w9966.c
drivers/media/video/w9968cf.c
drivers/media/video/wm8739.c
drivers/media/video/wm8775.c
drivers/media/video/zc0301/zc0301_core.c
drivers/media/video/zoran/zoran_driver.c
drivers/media/video/zr364xx.c
drivers/message/i2o/exec-osm.c
drivers/message/i2o/i2o_config.c
drivers/message/i2o/iop.c
drivers/message/i2o/pci.c
drivers/misc/ibmasm/ibmasmfs.c
drivers/mmc/card/block.c
drivers/mmc/core/core.c
drivers/mmc/core/mmc.c
drivers/mmc/host/Makefile
drivers/mmc/host/at91_mci.c
drivers/mmc/host/mmc_spi.c
drivers/mmc/host/of_mmc_spi.c [new file with mode: 0644]
drivers/mmc/host/pxamci.c
drivers/mmc/host/ricoh_mmc.c
drivers/mmc/host/sdhci-pci.c
drivers/mmc/host/sdhci.c
drivers/mmc/host/sdhci.h
drivers/mmc/host/sdricoh_cs.c
drivers/mmc/host/tmio_mmc.c
drivers/mtd/ubi/build.c
drivers/mtd/ubi/cdev.c
drivers/mtd/ubi/debug.h
drivers/mtd/ubi/eba.c
drivers/mtd/ubi/io.c
drivers/mtd/ubi/ubi.h
drivers/mtd/ubi/wl.c
drivers/net/acenic.c
drivers/net/acenic.h
drivers/net/e100.c
drivers/net/ehea/ehea.h
drivers/net/ehea/ehea_main.c
drivers/net/enc28j60.c
drivers/net/myri10ge/myri10ge.c
drivers/net/qlge/qlge.h
drivers/net/qlge/qlge_dbg.c
drivers/net/qlge/qlge_ethtool.c
drivers/net/qlge/qlge_main.c
drivers/net/starfire.c
drivers/net/starfire_firmware.h [deleted file]
drivers/net/starfire_firmware.pl [deleted file]
drivers/net/tg3.c
drivers/net/tg3.h
drivers/net/tun.c
drivers/oprofile/oprofilefs.c
drivers/pci/dmar.c
drivers/pci/hotplug/cpqphp_core.c
drivers/pci/hotplug/cpqphp_pci.c
drivers/pci/hotplug/ibmphp_core.c
drivers/pci/intel-iommu.c
drivers/pnp/pnpbios/bioscalls.c
drivers/rtc/Kconfig
drivers/rtc/interface.c
drivers/rtc/rtc-dev.c
drivers/s390/cio/cio.c
drivers/s390/net/qeth_core.h
drivers/s390/net/qeth_core_main.c
drivers/s390/net/qeth_l2_main.c
drivers/s390/net/qeth_l3_main.c
drivers/s390/s390mach.c
drivers/usb/core/inode.c
drivers/usb/gadget/file_storage.c
drivers/usb/gadget/inode.c
drivers/video/via/viafbdev.c
drivers/watchdog/Kconfig
drivers/watchdog/Makefile
drivers/watchdog/ib700wdt.c
drivers/watchdog/sch311x_wdt.c [new file with mode: 0644]
drivers/watchdog/wm8350_wdt.c [new file with mode: 0644]
firmware/Makefile
firmware/WHENCE
firmware/acenic/tg1.bin.ihex [new file with mode: 0644]
firmware/acenic/tg2.bin.ihex [new file with mode: 0644]
firmware/adaptec/starfire_rx.bin.ihex [new file with mode: 0644]
firmware/adaptec/starfire_tx.bin.ihex [new file with mode: 0644]
firmware/tigon/tg3.bin.ihex [new file with mode: 0644]
firmware/tigon/tg3_tso.bin.ihex [new file with mode: 0644]
firmware/tigon/tg3_tso5.bin.ihex [new file with mode: 0644]
fs/Kconfig
fs/Makefile
fs/affs/file.c
fs/affs/inode.c
fs/afs/write.c
fs/autofs/inode.c
fs/autofs4/inode.c
fs/binfmt_aout.c
fs/binfmt_misc.c
fs/buffer.c
fs/cifs/file.c
fs/cifs/inode.c
fs/coda/file.c
fs/configfs/inode.c
fs/cramfs/inode.c
fs/debugfs/inode.c
fs/devpts/inode.c
fs/dquot.c
fs/ecryptfs/file.c
fs/ecryptfs/inode.c
fs/ecryptfs/mmap.c
fs/exec.c
fs/ext3/inode.c
fs/ext3/namei.c
fs/ext3/super.c
fs/ext4/ext4_sb.h
fs/ext4/inode.c
fs/ext4/namei.c
fs/ext4/super.c
fs/filesystems.c
fs/fuse/file.c
fs/gfs2/ops_address.c
fs/hostfs/hostfs_kern.c
fs/hugetlbfs/inode.c
fs/inode.c
fs/isofs/inode.c
fs/jbd2/commit.c
fs/jbd2/journal.c
fs/jbd2/transaction.c
fs/jffs2/file.c
fs/jfs/jfs_imap.c
fs/libfs.c
fs/namei.c
fs/nfs/file.c
fs/nfsd/vfs.c
fs/notify/inotify/inotify_user.c
fs/ntfs/inode.c
fs/ocfs2/Makefile
fs/ocfs2/acl.c [new file with mode: 0644]
fs/ocfs2/acl.h [new file with mode: 0644]
fs/ocfs2/alloc.c
fs/ocfs2/alloc.h
fs/ocfs2/aops.c
fs/ocfs2/blockcheck.c [new file with mode: 0644]
fs/ocfs2/blockcheck.h [new file with mode: 0644]
fs/ocfs2/buffer_head_io.c
fs/ocfs2/buffer_head_io.h
fs/ocfs2/cluster/masklog.c
fs/ocfs2/cluster/masklog.h
fs/ocfs2/dir.c
fs/ocfs2/dir.h
fs/ocfs2/dlm/dlmast.c
fs/ocfs2/dlm/dlmcommon.h
fs/ocfs2/dlm/dlmdebug.c
fs/ocfs2/dlm/dlmdomain.c
fs/ocfs2/dlm/dlmfs.c
fs/ocfs2/dlm/dlmmaster.c
fs/ocfs2/dlm/dlmthread.c
fs/ocfs2/dlmglue.c
fs/ocfs2/dlmglue.h
fs/ocfs2/extent_map.c
fs/ocfs2/extent_map.h
fs/ocfs2/file.c
fs/ocfs2/file.h
fs/ocfs2/inode.c
fs/ocfs2/inode.h
fs/ocfs2/journal.c
fs/ocfs2/journal.h
fs/ocfs2/localalloc.c
fs/ocfs2/namei.c
fs/ocfs2/ocfs2.h
fs/ocfs2/ocfs2_fs.h
fs/ocfs2/ocfs2_jbd_compat.h [deleted file]
fs/ocfs2/ocfs2_lockid.h
fs/ocfs2/quota.h [new file with mode: 0644]
fs/ocfs2/quota_global.c [new file with mode: 0644]
fs/ocfs2/quota_local.c [new file with mode: 0644]
fs/ocfs2/resize.c
fs/ocfs2/slot_map.c
fs/ocfs2/suballoc.c
fs/ocfs2/suballoc.h
fs/ocfs2/super.c
fs/ocfs2/symlink.c
fs/ocfs2/xattr.c
fs/ocfs2/xattr.h
fs/omfs/inode.c
fs/open.c
fs/openpromfs/inode.c
fs/pipe.c
fs/proc/base.c
fs/proc/proc_sysctl.c
fs/quota.c
fs/quota_tree.c [new file with mode: 0644]
fs/quota_tree.h [new file with mode: 0644]
fs/quota_v1.c
fs/quota_v2.c
fs/quotaio_v1.h [moved from include/linux/quotaio_v1.h with 100% similarity]
fs/quotaio_v2.h [moved from include/linux/quotaio_v2.h with 68% similarity]
fs/ramfs/inode.c
fs/read_write.c
fs/reiserfs/inode.c
fs/reiserfs/super.c
fs/romfs/inode.c
fs/seq_file.c
fs/smbfs/file.c
fs/stat.c
fs/sync.c
fs/sysfs/inode.c
fs/ubifs/budget.c
fs/ubifs/commit.c
fs/ubifs/compress.c
fs/ubifs/debug.c
fs/ubifs/debug.h
fs/ubifs/file.c
fs/ubifs/ioctl.c
fs/ubifs/journal.c
fs/ubifs/key.h
fs/ubifs/lprops.c
fs/ubifs/lpt.c
fs/ubifs/lpt_commit.c
fs/ubifs/orphan.c
fs/ubifs/replay.c
fs/ubifs/sb.c
fs/ubifs/super.c
fs/ubifs/tnc.c
fs/ubifs/tnc_commit.c
fs/ubifs/ubifs-media.h
fs/ubifs/ubifs.h
fs/xattr.c
include/acpi/processor.h
include/asm-frv/bitops.h
include/asm-m32r/bitops.h
include/asm-m68k/bitops.h
include/asm-mn10300/bitops.h
include/asm-xtensa/bitops.h
include/linux/Kbuild
include/linux/audit.h
include/linux/bitmap.h
include/linux/bitops.h
include/linux/blockgroup_lock.h
include/linux/cpufreq.h
include/linux/cpumask.h
include/linux/dma_remapping.h
include/linux/dmar.h
include/linux/dqblk_qtree.h [new file with mode: 0644]
include/linux/dqblk_v1.h
include/linux/dqblk_v2.h
include/linux/dvb/frontend.h
include/linux/ext2_fs_sb.h
include/linux/ext3_fs_sb.h
include/linux/fs.h
include/linux/intel-iommu.h
include/linux/interrupt.h
include/linux/iommu.h [new file with mode: 0644]
include/linux/jbd2.h
include/linux/journal-head.h
include/linux/kernel_stat.h
include/linux/kvm_host.h
include/linux/mmc/core.h
include/linux/mmc/host.h
include/linux/netdevice.h
include/linux/pagemap.h
include/linux/quota.h
include/linux/quotaops.h
include/linux/radix-tree.h
include/linux/random.h
include/linux/rcuclassic.h
include/linux/rtc.h
include/linux/sched.h
include/linux/seq_file.h
include/linux/smp.h
include/linux/spi/mmc_spi.h
include/linux/spi/spi.h
include/linux/stop_machine.h
include/linux/syscalls.h
include/linux/threads.h
include/linux/tick.h
include/linux/videodev2.h
include/media/saa7146_vv.h
include/media/soc_camera.h
include/media/v4l2-chip-ident.h
include/media/v4l2-common.h
include/media/v4l2-dev.h
include/media/v4l2-device.h
include/media/v4l2-int-device.h
include/media/v4l2-ioctl.h
include/media/v4l2-subdev.h
include/net/ndisc.h
include/sound/tea575x-tuner.h
init/main.c
ipc/mqueue.c
ipc/sem.c
ipc/shm.c
ipc/util.c
kernel/audit.h
kernel/audit_tree.c
kernel/auditfilter.c
kernel/auditsc.c
kernel/capability.c
kernel/cgroup.c
kernel/compat.c
kernel/cpu.c
kernel/irq/manage.c
kernel/irq/proc.c
kernel/kexec.c
kernel/power/poweroff.c
kernel/profile.c
kernel/rcuclassic.c
kernel/rcupreempt.c
kernel/rcutorture.c
kernel/sched.c
kernel/sched_rt.c
kernel/smp.c
kernel/softirq.c
kernel/softlockup.c
kernel/stop_machine.c
kernel/taskstats.c
kernel/time/clocksource.c
kernel/time/tick-broadcast.c
kernel/time/tick-common.c
kernel/time/tick-sched.c
kernel/timer.c
kernel/trace/ring_buffer.c
kernel/trace/trace.c
kernel/trace/trace.h
kernel/trace/trace_boot.c
kernel/trace/trace_functions_graph.c
kernel/trace/trace_hw_branches.c
kernel/trace/trace_power.c
kernel/trace/trace_sysprof.c
kernel/workqueue.c
lib/Kconfig
lib/Makefile
lib/cpumask.c
lib/find_last_bit.c [new file with mode: 0644]
lib/vsprintf.c
mm/filemap.c
mm/memory.c
mm/mmap.c
mm/mprotect.c
mm/mremap.c
mm/msync.c
mm/nommu.c
mm/pdflush.c
mm/slab.c
mm/slub.c
mm/vmalloc.c
mm/vmscan.c
mm/vmstat.c
net/can/bcm.c
net/core/dev.c
net/core/skbuff.c
net/dcb/dcbnl.c
net/dccp/Kconfig
net/dccp/Makefile
net/dccp/ackvec.h
net/dccp/ccid.c
net/dccp/ccid.h
net/dccp/ccids/Kconfig
net/dccp/ccids/Makefile [deleted file]
net/dccp/ccids/ccid2.c
net/dccp/ccids/ccid3.c
net/dccp/ccids/lib/Makefile [deleted file]
net/dccp/ccids/lib/loss_interval.c
net/dccp/ccids/lib/packet_history.c
net/dccp/ccids/lib/tfrc.c
net/dccp/ccids/lib/tfrc.h
net/dccp/ccids/lib/tfrc_equation.c
net/dccp/dccp.h
net/dccp/feat.c
net/dccp/input.c
net/dccp/proto.c
net/ipv4/tcp.c
net/ipv6/ipv6_sockglue.c
net/ipv6/route.c
net/iucv/af_iucv.c
net/iucv/iucv.c
net/rfkill/rfkill.c
net/sched/cls_u32.c
net/socket.c
net/sunrpc/rpc_pipe.c
scripts/headers_check.pl
scripts/headers_install.pl
scripts/kconfig/expr.h
scripts/kconfig/lex.zconf.c_shipped
scripts/kconfig/zconf.l
scripts/tags.sh
security/commoncap.c
security/inode.c
security/selinux/selinuxfs.c
security/selinux/ss/services.c
security/smack/smack_lsm.c
sound/i2c/other/tea575x-tuner.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_realtek.c
sound/pci/ice1712/ice1724.c
sound/soc/codecs/twl4030.c
sound/soc/codecs/twl4030.h
sound/soc/davinci/davinci-sffsdr.c
sound/soc/pxa/pxa2xx-pcm.c
sound/soc/soc-core.c
sound/soc/soc-dapm.c
sound/usb/caiaq/caiaq-device.c
sound/usb/usbaudio.c
sound/usb/usbmidi.c
sound/usb/usbmixer.c
sound/usb/usx2y/us122l.c
sound/usb/usx2y/usbusx2y.c
virt/kvm/iommu.c [moved from virt/kvm/vtd.c with 58% similarity]
virt/kvm/kvm_main.c

diff --git a/CREDITS b/CREDITS
index b50db1767554bf2cb63e9f5b4fdb4864af0ce5b9..abe05a0be4ed0db849c9fc00818ee39cbd338857 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -369,10 +369,10 @@ P: 1024/8462A731 4C 55 86 34 44 59 A7 99  2B 97 88 4A 88 9A 0D 97
 D: sun4 port, Sparc hacker
 
 N: Hugh Blemings
-E: hugh@misc.nu
-W: http://misc.nu/hugh/
-D: Author and maintainer of the Keyspan USB to Serial drivers
-S: Po Box 234
+E: hugh@blemings.org
+W: http://blemings.org/hugh
+D: Original author of the Keyspan USB to serial drivers, random PowerPC hacker
+S: PO Box 234
 S: Belconnen ACT 2616
 S: Australia
 
index bd699da246666a503195ed0d8240fb531b90f746..45932ec21cee7cc2fadc11c96b831d435e4d9728 100644 (file)
@@ -31,3 +31,51 @@ not defined by include/asm-XXX/topology.h:
 2) core_id: 0
 3) thread_siblings: just the given CPU
 4) core_siblings: just the given CPU
+
+Additionally, cpu topology information is provided under
+/sys/devices/system/cpu and includes these files.  The internal
+source for the output is in brackets ("[]").
+
+    kernel_max: the maximum cpu index allowed by the kernel configuration.
+               [NR_CPUS-1]
+
+    offline:   cpus that are not online because they have been
+               HOTPLUGGED off (see cpu-hotplug.txt) or exceed the limit
+               of cpus allowed by the kernel configuration (kernel_max
+               above). [~cpu_online_mask + cpus >= NR_CPUS]
+
+    online:    cpus that are online and being scheduled [cpu_online_mask]
+
+    possible:  cpus that have been allocated resources and can be
+               brought online if they are present. [cpu_possible_mask]
+
+    present:   cpus that have been identified as being present in the
+               system. [cpu_present_mask]
+
+The format for the above output is compatible with cpulist_parse()
+[see <linux/cpumask.h>].  Some examples follow.
+
+In this example, there are 64 cpus in the system but cpus 32-63 exceed
+the kernel max which is limited to 0..31 by the NR_CPUS config option
+being 32.  Note also that cpus 2 and 4-31 are not online but could be
+brought online as they are both present and possible.
+
+     kernel_max: 31
+        offline: 2,4-31,32-63
+         online: 0-1,3
+       possible: 0-31
+        present: 0-31
+
+In this example, the NR_CPUS config option is 128, but the kernel was
+started with possible_cpus=144.  There are 4 cpus in the system and cpu2
+was manually taken offline (and is the only cpu that can be brought
+online.)
+
+     kernel_max: 127
+        offline: 2,4-127,128-143
+         online: 0-1,3
+       possible: 0-127
+        present: 0-3
+
+See cpu-hotplug.txt for the possible_cpus=NUM kernel start parameter
+as well as more information on the various cpumask's.
index 67310fbbb7dfe86e62f9ae28ebf1b188b4c1d4e2..c2a0871280a02eeaa6c027300207881b4a8825cf 100644 (file)
@@ -31,7 +31,6 @@ Features which OCFS2 does not support yet:
        - quotas
        - Directory change notification (F_NOTIFY)
        - Distributed Caching (F_SETLEASE/F_GETLEASE/break_lease)
-       - POSIX ACLs
 
 Mount options
 =============
@@ -79,3 +78,5 @@ inode64                       Indicates that Ocfs2 is allowed to create inodes at
                        bits of significance.
 user_xattr     (*)     Enables Extended User Attributes.
 nouser_xattr           Disables Extended User Attributes.
+acl                    Enables POSIX Access Control Lists support.
+noacl          (*)     Disables POSIX Access Control Lists support.
index dd84ea3c10daf00cf78a2361dce9f8b691095e4d..84da2a4ba25ab698b8788e03d33d1678f86eba22 100644 (file)
@@ -95,6 +95,9 @@ no_chk_data_crc               skip checking of CRCs on data nodes in order to
                        of this option is that corruption of the contents
                        of a file can go unnoticed.
 chk_data_crc (*)       do not skip checking CRCs on data nodes
+compr=none              override default compressor and set it to "none"
+compr=lzo               override default compressor and set it to "lzo"
+compr=zlib              override default compressor and set it to "zlib"
 
 
 Quick usage instructions
index b880ce5dbd33f2b08b5bd0affbb685b6ec59759b..824699174436d9a49912873196e27f0d2a51c49a 100644 (file)
@@ -97,6 +97,7 @@ Code  Seq#    Include File            Comments
                                        <http://linux01.gwdg.de/~alatham/ppdd.html>
 'M'    all     linux/soundcard.h
 'N'    00-1F   drivers/usb/scanner.h
+'O'     00-02   include/mtd/ubi-user.h UBI
 'P'    all     linux/soundcard.h
 'Q'    all     linux/soundcard.h
 'R'    00-1F   linux/random.h
@@ -142,6 +143,9 @@ Code        Seq#    Include File            Comments
 'n'    00-7F   linux/ncp_fs.h
 'n'    E0-FF   video/matrox.h          matroxfb
 'o'    00-1F   fs/ocfs2/ocfs2_fs.h     OCFS2
+'o'     00-03   include/mtd/ubi-user.h  conflict! (OCFS2 and UBI overlaps)
+'o'     40-41   include/mtd/ubi-user.h  UBI
+'o'     01-A1   include/linux/dvb/*.h DVB
 'p'    00-0F   linux/phantom.h         conflict! (OpenHaptics needs this)
 'p'    00-3F   linux/mc146818rtc.h     conflict!
 'p'    40-7F   linux/nvram.h
index 1146442854543325625508c9764ad53a1d708fbf..e8d2b6d83a3d9045eec563d7bc2a4043ec358be4 100644 (file)
@@ -1,5 +1,9 @@
 00-INDEX
-       - this file: info on the kernel build process
+       - this file: info on the kernel build process
+kbuild.txt
+       - developer information on kbuild
+kconfig.txt
+       - usage help for make *config
 kconfig-language.txt
        - specification of Config Language, the language in Kconfig files
 makefiles.txt
diff --git a/Documentation/kbuild/kbuild.txt b/Documentation/kbuild/kbuild.txt
new file mode 100644 (file)
index 0000000..5177184
--- /dev/null
@@ -0,0 +1,126 @@
+Environment variables
+
+KCPPFLAGS
+--------------------------------------------------
+Additional options to pass when preprocessing. The preprocessing options
+will be used in all cases where kbuild do preprocessing including
+building C files and assembler files.
+
+KAFLAGS
+--------------------------------------------------
+Additional options to the assembler.
+
+KCFLAGS
+--------------------------------------------------
+Additional options to the C compiler.
+
+KBUILD_VERBOSE
+--------------------------------------------------
+Set the kbuild verbosity. Can be assinged same values as "V=...".
+See make help for the full list.
+Setting "V=..." takes precedence over KBUILD_VERBOSE.
+
+KBUILD_EXTMOD
+--------------------------------------------------
+Set the directory to look for the kernel source when building external
+modules.
+The directory can be specified in several ways:
+1) Use "M=..." on the command line
+2) Environmnet variable KBUILD_EXTMOD
+3) Environmnet variable SUBDIRS
+The possibilities are listed in the order they take precedence.
+Using "M=..." will always override the others.
+
+KBUILD_OUTPUT
+--------------------------------------------------
+Specify the output directory when building the kernel.
+The output directory can also be specificed using "O=...".
+Setting "O=..." takes precedence over KBUILD_OUTPUT
+
+ARCH
+--------------------------------------------------
+Set ARCH to the architecture to be built.
+In most cases the name of the architecture is the same as the
+directory name found in the arch/ directory.
+But some architectures suach as x86 and sparc has aliases.
+x86: i386 for 32 bit, x86_64 for 64 bit
+sparc: sparc for 32 bit, sparc64 for 64 bit
+
+CROSS_COMPILE
+--------------------------------------------------
+Specify an optional fixed part of the binutils filename.
+CROSS_COMPILE can be a part of the filename or the full path.
+
+CROSS_COMPILE is also used for ccache is some setups.
+
+CF
+--------------------------------------------------
+Additional options for sparse.
+CF is often used on the command-line like this:
+
+    make CF=-Wbitwise C=2
+
+INSTALL_PATH
+--------------------------------------------------
+INSTALL_PATH specifies where to place the updated kernel and system map
+images. Default is /boot, but you can set it to other values
+
+
+MODLIB
+--------------------------------------------------
+Specify where to install modules.
+The default value is:
+
+     $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)
+
+The value can be overridden in which case the default value is ignored.
+
+INSTALL_MOD_PATH
+--------------------------------------------------
+INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory
+relocations required by build roots.  This is not defined in the
+makefile but the argument can be passed to make if needed.
+
+INSTALL_MOD_STRIP
+--------------------------------------------------
+INSTALL_MOD_STRIP, if defined, will cause modules to be
+stripped after they are installed.  If INSTALL_MOD_STRIP is '1', then
+the default option --strip-debug will be used.  Otherwise,
+INSTALL_MOD_STRIP will used as the options to the strip command.
+
+INSTALL_FW_PATH
+--------------------------------------------------
+INSTALL_FW_PATH specify where to install the firmware blobs.
+The default value is:
+
+    $(INSTALL_MOD_PATH)/lib/firmware
+
+The value can be overridden in which case the default value is ignored.
+
+INSTALL_HDR_PATH
+--------------------------------------------------
+INSTALL_HDR_PATH specify where to install user space headers when
+executing "make headers_*".
+The default value is:
+
+    $(objtree)/usr
+
+$(objtree) is the directory where output files are saved.
+The output directory is often set using "O=..." on the commandline.
+
+The value can be overridden in which case the default value is ignored.
+
+KBUILD_MODPOST_WARN
+--------------------------------------------------
+KBUILD_MODPOST_WARN can be set to avoid error out in case of undefined
+symbols in the final module linking stage.
+
+KBUILD_MODPOST_FINAL
+--------------------------------------------------
+KBUILD_MODPOST_NOFINAL can be set to skip the final link of modules.
+This is solely usefull to speed up test compiles.
+
+KBUILD_EXTRA_SYMBOLS
+--------------------------------------------------
+For modules use symbols from another modules.
+See more details in modules.txt.
diff --git a/Documentation/kbuild/kconfig.txt b/Documentation/kbuild/kconfig.txt
new file mode 100644 (file)
index 0000000..26a7c0a
--- /dev/null
@@ -0,0 +1,188 @@
+This file contains some assistance for using "make *config".
+
+Use "make help" to list all of the possible configuration targets.
+
+The xconfig ('qconf') and menuconfig ('mconf') programs also
+have embedded help text.  Be sure to check it for navigation,
+search, and other general help text.
+
+======================================================================
+General
+--------------------------------------------------
+
+New kernel releases often introduce new config symbols.  Often more
+important, new kernel releases may rename config symbols.  When
+this happens, using a previously working .config file and running
+"make oldconfig" won't necessarily produce a working new kernel
+for you, so you may find that you need to see what NEW kernel
+symbols have been introduced.
+
+To see a list of new config symbols when using "make oldconfig", use
+
+       cp user/some/old.config .config
+       yes "" | make oldconfig >conf.new
+
+and the config program will list as (NEW) any new symbols that have
+unknown values.  Of course, the .config file is also updated with
+new (default) values, so you can use:
+
+       grep "(NEW)" conf.new
+
+to see the new config symbols or you can 'diff' the previous and
+new .config files to see the differences:
+
+       diff .config.old .config | less
+
+(Yes, we need something better here.)
+
+
+======================================================================
+menuconfig
+--------------------------------------------------
+
+SEARCHING for CONFIG symbols
+
+Searching in menuconfig:
+
+       The Search function searches for kernel configuration symbol
+       names, so you have to know something close to what you are
+       looking for.
+
+       Example:
+               /hotplug
+               This lists all config symbols that contain "hotplug",
+               e.g., HOTPLUG, HOTPLUG_CPU, MEMORY_HOTPLUG.
+
+       For search help, enter / followed TAB-TAB-TAB (to highlight
+       <Help>) and Enter.  This will tell you that you can also use
+       regular expressions (regexes) in the search string, so if you
+       are not interested in MEMORY_HOTPLUG, you could try
+
+               /^hotplug
+
+
+______________________________________________________________________
+Color Themes for 'menuconfig'
+
+It is possible to select different color themes using the variable
+MENUCONFIG_COLOR.  To select a theme use:
+
+       make MENUCONFIG_COLOR=<theme> menuconfig
+
+Available themes are:
+  mono       => selects colors suitable for monochrome displays
+  blackbg    => selects a color scheme with black background
+  classic    => theme with blue background. The classic look
+  bluetitle  => a LCD friendly version of classic. (default)
+
+______________________________________________________________________
+Environment variables in 'menuconfig'
+
+KCONFIG_ALLCONFIG
+--------------------------------------------------
+(partially based on lkml email from/by Rob Landley, re: miniconfig)
+--------------------------------------------------
+The allyesconfig/allmodconfig/allnoconfig/randconfig variants can
+also use the environment variable KCONFIG_ALLCONFIG as a flag or a
+filename that contains config symbols that the user requires to be
+set to a specific value.  If KCONFIG_ALLCONFIG is used without a
+filename, "make *config" checks for a file named
+"all{yes/mod/no/random}.config" (corresponding to the *config command
+that was used) for symbol values that are to be forced.  If this file
+is not found, it checks for a file named "all.config" to contain forced
+values.
+
+This enables you to create "miniature" config (miniconfig) or custom
+config files containing just the config symbols that you are interested
+in.  Then the kernel config system generates the full .config file,
+including dependencies of your miniconfig file, based on the miniconfig
+file.
+
+This 'KCONFIG_ALLCONFIG' file is a config file which contains
+(usually a subset of all) preset config symbols.  These variable
+settings are still subject to normal dependency checks.
+
+Examples:
+       KCONFIG_ALLCONFIG=custom-notebook.config make allnoconfig
+or
+       KCONFIG_ALLCONFIG=mini.config make allnoconfig
+or
+       make KCONFIG_ALLCONFIG=mini.config allnoconfig
+
+These examples will disable most options (allnoconfig) but enable or
+disable the options that are explicitly listed in the specified
+mini-config files.
+
+KCONFIG_NOSILENTUPDATE
+--------------------------------------------------
+If this variable has a non-blank value, it prevents silent kernel
+config udpates (requires explicit updates).
+
+KCONFIG_CONFIG
+--------------------------------------------------
+This environment variable can be used to specify a default kernel config
+file name to override the default name of ".config".
+
+KCONFIG_OVERWRITECONFIG
+--------------------------------------------------
+If you set KCONFIG_OVERWRITECONFIG in the environment, Kconfig will not
+break symlinks when .config is a symlink to somewhere else.
+
+KCONFIG_NOTIMESTAMP
+--------------------------------------------------
+If this environment variable exists and is non-null, the timestamp line
+in generated .config files is omitted.
+
+KCONFIG_AUTOCONFIG
+--------------------------------------------------
+This environment variable can be set to specify the path & name of the
+"auto.conf" file.  Its default value is "include/config/auto.conf".
+
+KCONFIG_AUTOHEADER
+--------------------------------------------------
+This environment variable can be set to specify the path & name of the
+"autoconf.h" (header) file.  Its default value is "include/linux/autoconf.h".
+
+______________________________________________________________________
+menuconfig User Interface Options
+----------------------------------------------------------------------
+MENUCONFIG_MODE
+--------------------------------------------------
+This mode shows all sub-menus in one large tree.
+
+Example:
+       MENUCONFIG_MODE=single_menu make menuconfig
+
+======================================================================
+xconfig
+--------------------------------------------------
+
+Searching in xconfig:
+
+       The Search function searches for kernel configuration symbol
+       names, so you have to know something close to what you are
+       looking for.
+
+       Example:
+               Ctrl-F hotplug
+       or
+               Menu: File, Search, hotplug
+
+       lists all config symbol entries that contain "hotplug" in
+       the symbol name.  In this Search dialog, you may change the
+       config setting for any of the entries that are not grayed out.
+       You can also enter a different search string without having
+       to return to the main menu.
+
+
+======================================================================
+gconfig
+--------------------------------------------------
+
+Searching in gconfig:
+
+       None (gconfig isn't maintained as well as xconfig or menuconfig);
+       however, gconfig does have a few more viewing choices than
+       xconfig does.
+
+###
index 335aef4dcaebdaa0acf87477865a0b0cea9be377..b8d470596b0cceadc9b74ed7005d3cb3d144aeed 100644 (file)
 151 -> ADS Tech Instant HDTV                    [1421:0380]
 152 -> Asus Tiger Rev:1.00                      [1043:4857]
 153 -> Kworld Plus TV Analog Lite PCI           [17de:7128]
+154 -> Avermedia AVerTV GO 007 FM Plus          [1461:f31d]
index 11c5fd22a3322e5ac3d568bb354ee62d283489da..49679e6aaa7617daa69d72d7034cf5ebd0e63c20 100644 (file)
@@ -41,6 +41,7 @@ chips are known to work:
 - 10c4:818a: Silicon Labs USB FM Radio Reference Design
 - 06e1:a155: ADS/Tech FM Radio Receiver (formerly Instant FM Music) (RDX-155-EF)
 - 1b80:d700: KWorld USB FM Radio SnapMusic Mobile 700 (FM700)
+- 10c5:819a: DealExtreme USB Radio
 
 
 Software
index eeae76c22a9310229ed46d5092f7db6e29888228..ff124374e9ba3211a078b0ec042a21e6e55ec001 100644 (file)
@@ -184,7 +184,7 @@ may be NULL if the subdev driver does not support anything from that category.
 It looks like this:
 
 struct v4l2_subdev_core_ops {
-       int (*g_chip_ident)(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip);
+       int (*g_chip_ident)(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip);
        int (*log_status)(struct v4l2_subdev *sd);
        int (*init)(struct v4l2_subdev *sd, u32 val);
        ...
@@ -390,16 +390,18 @@ allocated memory.
 
 You should also set these fields:
 
-- parent: set to the parent device (same device as was used to register
-  v4l2_device).
+- v4l2_dev: set to the v4l2_device parent device.
 - name: set to something descriptive and unique.
-- fops: set to the file_operations struct.
+- fops: set to the v4l2_file_operations struct.
 - ioctl_ops: if you use the v4l2_ioctl_ops to simplify ioctl maintenance
   (highly recommended to use this and it might become compulsory in the
   future!), then set this to your v4l2_ioctl_ops struct.
 
-If you use v4l2_ioctl_ops, then you should set .unlocked_ioctl to
-__video_ioctl2 or .ioctl to video_ioctl2 in your file_operations struct.
+If you use v4l2_ioctl_ops, then you should set either .unlocked_ioctl or
+.ioctl to video_ioctl2 in your v4l2_file_operations struct.
+
+The v4l2_file_operations struct is a subset of file_operations. The main
+difference is that the inode argument is omitted since it is never used.
 
 
 video_device registration
@@ -410,7 +412,7 @@ for you.
 
        err = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
        if (err) {
-               video_device_release(vdev); // or kfree(my_vdev);
+               video_device_release(vdev); /* or kfree(my_vdev); */
                return err;
        }
 
@@ -516,5 +518,4 @@ void *video_drvdata(struct file *file);
 
 You can go from a video_device struct to the v4l2_device struct using:
 
-struct v4l2_device *v4l2_dev = dev_get_drvdata(vdev->parent);
-
+struct v4l2_device *v4l2_dev = vdev->v4l2_dev;
index d13a9694e159ca092dd6a2dc044729bd1ddc7760..f9006663f01e428ec13a39fb215914e750ab66de 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -321,7 +321,8 @@ KALLSYMS    = scripts/kallsyms
 PERL           = perl
 CHECK          = sparse
 
-CHECKFLAGS     := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ -Wbitwise $(CF)
+CHECKFLAGS     := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \
+                 -Wbitwise -Wno-return-void $(CF)
 MODFLAGS       = -DMODULE
 CFLAGS_MODULE   = $(MODFLAGS)
 AFLAGS_MODULE   = $(MODFLAGS)
diff --git a/README b/README
index 159912cf515549455ed5f579b8825d28962bd22e..90a07658ede14840346eee6610648bcf4ec79997 100644 (file)
--- a/README
+++ b/README
@@ -52,11 +52,11 @@ DOCUMENTATION:
 
  - The Documentation/DocBook/ subdirectory contains several guides for
    kernel developers and users.  These guides can be rendered in a
-   number of formats:  PostScript (.ps), PDF, and HTML, among others.
-   After installation, "make psdocs", "make pdfdocs", or "make htmldocs"
-   will render the documentation in the requested format.
+   number of formats:  PostScript (.ps), PDF, HTML, & man-pages, among others.
+   After installation, "make psdocs", "make pdfdocs", "make htmldocs",
+   or "make mandocs" will render the documentation in the requested format.
 
-INSTALLING the kernel:
+INSTALLING the kernel source:
 
  - If you install the full sources, put the kernel tarball in a
    directory where you have permissions (eg. your home directory) and
@@ -187,14 +187,9 @@ CONFIGURING the kernel:
        "make randconfig"  Create a ./.config file by setting symbol
                           values to random values.
 
-   The allyesconfig/allmodconfig/allnoconfig/randconfig variants can
-   also use the environment variable KCONFIG_ALLCONFIG to specify a
-   filename that contains config options that the user requires to be
-   set to a specific value.  If KCONFIG_ALLCONFIG=filename is not used,
-   "make *config" checks for a file named "all{yes/mod/no/random}.config"
-   for symbol values that are to be forced.  If this file is not found,
-   it checks for a file named "all.config" to contain forced values.
-   
+   You can find more information on using the Linux kernel config tools
+   in Documentation/kbuild/make-configs.txt.
+
        NOTES on "make config":
        - having unnecessary drivers will make the kernel bigger, and can
          under some circumstances lead to problems: probing for a
@@ -231,6 +226,19 @@ COMPILING the kernel:
  - If you configured any of the parts of the kernel as `modules', you
    will also have to do "make modules_install".
 
+ - Verbose kernel compile/build output:
+
+   Normally the kernel build system runs in a fairly quiet mode (but not
+   totally silent).  However, sometimes you or other kernel developers need
+   to see compile, link, or other commands exactly as they are executed.
+   For this, use "verbose" build mode.  This is done by inserting
+   "V=1" in the "make" command.  E.g.:
+
+       make V=1 all
+
+   To have the build system also tell the reason for the rebuild of each
+   target, use "V=2".  The default is "V=0".
+
  - Keep a backup kernel handy in case something goes wrong.  This is 
    especially true for the development releases, since each new release
    contains new code which has not been debugged.  Make sure you keep a
index 149532e162c4f4293decb64e8e73aab339c13521..b4f284c72ff3ed303425ac437df0b74f75defc90 100644 (file)
@@ -39,7 +39,24 @@ static inline cpumask_t node_to_cpumask(int node)
        return node_cpu_mask;
 }
 
+extern struct cpumask node_to_cpumask_map[];
+/* FIXME: This is dumb, recalculating every time.  But simple. */
+static const struct cpumask *cpumask_of_node(int node)
+{
+       int cpu;
+
+       cpumask_clear(&node_to_cpumask_map[node]);
+
+       for_each_online_cpu(cpu) {
+               if (cpu_to_node(cpu) == node)
+                       cpumask_set_cpu(cpu, node_to_cpumask_map[node]);
+       }
+
+       return &node_to_cpumask_map[node];
+}
+
 #define pcibus_to_cpumask(bus) (cpu_online_map)
+#define cpumask_of_pcibus(bus) (cpu_online_mask)
 
 #endif /* !CONFIG_NUMA */
 # include <asm-generic/topology.h>
index ac706c1d7ada2a7b7be760487a2de910fda03ef0..b4697759a1235ad60ce5458fcd6b896fb4f24e1d 100644 (file)
@@ -8,7 +8,7 @@ EXTRA_CFLAGS    := -Werror -Wno-sign-compare
 
 obj-y    := entry.o traps.o process.o init_task.o osf_sys.o irq.o \
            irq_alpha.o signal.o setup.o ptrace.o time.o \
-           alpha_ksyms.o systbls.o err_common.o io.o
+           alpha_ksyms.o systbls.o err_common.o io.o binfmt_loader.o
 
 obj-$(CONFIG_VGA_HOSE) += console.o
 obj-$(CONFIG_SMP)      += smp.o
diff --git a/arch/alpha/kernel/binfmt_loader.c b/arch/alpha/kernel/binfmt_loader.c
new file mode 100644 (file)
index 0000000..4a0af90
--- /dev/null
@@ -0,0 +1,51 @@
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/mm_types.h>
+#include <linux/binfmts.h>
+#include <linux/a.out.h>
+
+static int load_binary(struct linux_binprm *bprm, struct pt_regs *regs)
+{
+       struct exec *eh = (struct exec *)bprm->buf;
+       unsigned long loader;
+       struct file *file;
+       int retval;
+
+       if (eh->fh.f_magic != 0x183 || (eh->fh.f_flags & 0x3000) != 0x3000)
+               return -ENOEXEC;
+
+       if (bprm->loader)
+               return -ENOEXEC;
+
+       allow_write_access(bprm->file);
+       fput(bprm->file);
+       bprm->file = NULL;
+
+       loader = bprm->vma->vm_end - sizeof(void *);
+
+       file = open_exec("/sbin/loader");
+       retval = PTR_ERR(file);
+       if (IS_ERR(file))
+               return retval;
+
+       /* Remember if the application is TASO.  */
+       bprm->taso = eh->ah.entry < 0x100000000UL;
+
+       bprm->file = file;
+       bprm->loader = loader;
+       retval = prepare_binprm(bprm);
+       if (retval < 0)
+               return retval;
+       return search_binary_handler(bprm,regs);
+}
+
+static struct linux_binfmt loader_format = {
+       .load_binary    = load_binary,
+};
+
+static int __init init_loader_binfmt(void)
+{
+       return register_binfmt(&loader_format);
+}
+arch_initcall(init_loader_binfmt);
index d0f1620007f7de83d72f76257fb778791518d587..703731accda6d515e6879afe276e68818eaddd4b 100644 (file)
@@ -50,7 +50,8 @@ int irq_select_affinity(unsigned int irq)
        if (!irq_desc[irq].chip->set_affinity || irq_user_affinity[irq])
                return 1;
 
-       while (!cpu_possible(cpu) || !cpu_isset(cpu, irq_default_affinity))
+       while (!cpu_possible(cpu) ||
+              !cpumask_test_cpu(cpu, irq_default_affinity))
                cpu = (cpu < (NR_CPUS-1) ? cpu + 1 : 0);
        last_cpu = cpu;
 
index a449e999027c8e663af133f956996c94a70197fc..02bee6983ce2e7f9a91cd57a264ec189671c073e 100644 (file)
@@ -79,6 +79,11 @@ int alpha_l3_cacheshape;
 unsigned long alpha_verbose_mcheck = CONFIG_VERBOSE_MCHECK_ON;
 #endif
 
+#ifdef CONFIG_NUMA
+struct cpumask node_to_cpumask_map[MAX_NUMNODES] __read_mostly;
+EXPORT_SYMBOL(node_to_cpumask_map);
+#endif
+
 /* Which processor we booted from.  */
 int boot_cpuid;
 
index 1a50b69b1a192de23bd6bdf88881a5181082faeb..f7dd5f71edf7e497537a31725cf05f514f7de5ca 100644 (file)
@@ -263,6 +263,11 @@ static inline int fls(unsigned long word)
        return 32 - result;
 }
 
+static inline int __fls(unsigned long word)
+{
+       return fls(word) - 1;
+}
+
 unsigned long find_first_zero_bit(const unsigned long *addr,
                                  unsigned long size);
 unsigned long find_next_zero_bit(const unsigned long *addr,
index b39a175c79c1bcaba34f4decfefc337166992698..c428e4106f898382ca198e2ff37b36b4bf144650 100644 (file)
@@ -213,6 +213,7 @@ static __inline__ int __test_bit(int nr, const void *addr)
 #endif                         /* __KERNEL__ */
 
 #include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/__fls.h>
 #include <asm-generic/bitops/fls64.h>
 
 #endif                         /* _BLACKFIN_BITOPS_H */
index c0e62f811e094a4aa09e788129e306c6e2647580..9e69cfb7f1342a86c4e22617d36cefbf6289de80 100644 (file)
@@ -148,6 +148,7 @@ static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
 #define ffs kernel_ffs
 
 #include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/__fls.h>
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/hweight.h>
 #include <asm-generic/bitops/find.h>
index cb18e3b0aa948520b8f7321e6ead3d00eb1d5cf2..cb9ddf5fc54ff3837c8393a8e891a8e4766216f9 100644 (file)
@@ -207,6 +207,7 @@ static __inline__ unsigned long __ffs(unsigned long word)
 #endif /* __KERNEL__ */
 
 #include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/__fls.h>
 #include <asm-generic/bitops/fls64.h>
 
 #endif /* _H8300_BITOPS_H */
index 7fa8f615ba6e7edaec647959f8d4623fcab4bad5..3d31636cbafb584d25995e6ae6ff9d253a95901d 100644 (file)
@@ -687,3 +687,6 @@ config IRQ_PER_CPU
 
 config IOMMU_HELPER
        def_bool (IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB || IA64_GENERIC || SWIOTLB)
+
+config IOMMU_API
+       def_bool (DMAR)
index 3627116fb0e25238567fb68c42afe9c6381a8801..36429a5326302f4497893fae67d7dfb88dea916e 100644 (file)
@@ -27,7 +27,7 @@ irq_canonicalize (int irq)
 }
 
 extern void set_irq_affinity_info (unsigned int irq, int dest, int redir);
-bool is_affinity_mask_valid(cpumask_t cpumask);
+bool is_affinity_mask_valid(cpumask_var_t cpumask);
 
 #define is_affinity_mask_valid is_affinity_mask_valid
 
index 0560f3fae5380eae6b877822f82c047f49ada011..348663661659907320aca0889863d6f6867ed0f1 100644 (file)
@@ -467,7 +467,7 @@ struct kvm_arch {
        struct kvm_sal_data rdv_sal_data;
 
        struct list_head assigned_dev_head;
-       struct dmar_domain *intel_iommu_domain;
+       struct iommu_domain *iommu_domain;
        struct hlist_head irq_ack_notifier_list;
 
        unsigned long irq_sources_bitmap;
index a3cc9f65f954e7231a6fe0cba79ee5a0a22f5dc1..76a33a91ca697e73a24a13605e5700469e0ded88 100644 (file)
@@ -34,6 +34,7 @@
  * Returns a bitmask of CPUs on Node 'node'.
  */
 #define node_to_cpumask(node) (node_to_cpu_mask[node])
+#define cpumask_of_node(node) (&node_to_cpu_mask[node])
 
 /*
  * Returns the number of the node containing Node 'nid'.
@@ -45,7 +46,7 @@
 /*
  * Returns the number of the first CPU on Node 'node'.
  */
-#define node_to_first_cpu(node) (first_cpu(node_to_cpumask(node)))
+#define node_to_first_cpu(node) (cpumask_first(cpumask_of_node(node)))
 
 /*
  * Determines the node for a given pci bus
@@ -109,6 +110,8 @@ void build_cpu_to_node_map(void);
 #define topology_core_id(cpu)                  (cpu_data(cpu)->core_id)
 #define topology_core_siblings(cpu)            (cpu_core_map[cpu])
 #define topology_thread_siblings(cpu)          (per_cpu(cpu_sibling_map, cpu))
+#define topology_core_cpumask(cpu)             (&cpu_core_map[cpu])
+#define topology_thread_cpumask(cpu)           (&per_cpu(cpu_sibling_map, cpu))
 #define smt_capable()                          (smp_num_siblings > 1)
 #endif
 
@@ -119,6 +122,10 @@ extern void arch_fix_phys_package_id(int num, u32 slot);
                                        node_to_cpumask(pcibus_to_node(bus)) \
                                )
 
+#define cpumask_of_pcibus(bus) (pcibus_to_node(bus) == -1 ?            \
+                                cpu_all_mask :                         \
+                                cpumask_from_node(pcibus_to_node(bus)))
+
 #include <asm-generic/topology.h>
 
 #endif /* _ASM_IA64_TOPOLOGY_H */
index bd7acc71e8a9e4d408e50102e513bbe4a948a064..0553648b7595742f5e19bc99ff6e6eca0c7b0284 100644 (file)
@@ -202,7 +202,6 @@ char *__init __acpi_map_table(unsigned long phys_addr, unsigned long size)
                             Boot-time Table Parsing
    -------------------------------------------------------------------------- */
 
-static int total_cpus __initdata;
 static int available_cpus __initdata;
 struct acpi_table_madt *acpi_madt __initdata;
 static u8 has_8259;
@@ -1001,7 +1000,7 @@ acpi_map_iosapic(acpi_handle handle, u32 depth, void *context, void **ret)
        node = pxm_to_node(pxm);
 
        if (node >= MAX_NUMNODES || !node_online(node) ||
-           cpus_empty(node_to_cpumask(node)))
+           cpumask_empty(cpumask_of_node(node)))
                return AE_OK;
 
        /* We know a gsi to node mapping! */
index c8adecd5b4164a5e48264fc252c5dc8b43e6d9fd..5cfd3d91001aed8043764c88778d2df3e91681cf 100644 (file)
@@ -695,32 +695,31 @@ get_target_cpu (unsigned int gsi, int irq)
 #ifdef CONFIG_NUMA
        {
                int num_cpus, cpu_index, iosapic_index, numa_cpu, i = 0;
-               cpumask_t cpu_mask;
+               const struct cpumask *cpu_mask;
 
                iosapic_index = find_iosapic(gsi);
                if (iosapic_index < 0 ||
                    iosapic_lists[iosapic_index].node == MAX_NUMNODES)
                        goto skip_numa_setup;
 
-               cpu_mask = node_to_cpumask(iosapic_lists[iosapic_index].node);
-               cpus_and(cpu_mask, cpu_mask, domain);
-               for_each_cpu_mask(numa_cpu, cpu_mask) {
-                       if (!cpu_online(numa_cpu))
-                               cpu_clear(numa_cpu, cpu_mask);
+               cpu_mask = cpumask_of_node(iosapic_lists[iosapic_index].node);
+               num_cpus = 0;
+               for_each_cpu_and(numa_cpu, cpu_mask, &domain) {
+                       if (cpu_online(numa_cpu))
+                               num_cpus++;
                }
 
-               num_cpus = cpus_weight(cpu_mask);
-
                if (!num_cpus)
                        goto skip_numa_setup;
 
                /* Use irq assignment to distribute across cpus in node */
                cpu_index = irq % num_cpus;
 
-               for (numa_cpu = first_cpu(cpu_mask) ; i < cpu_index ; i++)
-                       numa_cpu = next_cpu(numa_cpu, cpu_mask);
+               for_each_cpu_and(numa_cpu, cpu_mask, &domain)
+                       if (cpu_online(numa_cpu) && i++ >= cpu_index)
+                               break;
 
-               if (numa_cpu != NR_CPUS)
+               if (numa_cpu < nr_cpu_ids)
                        return cpu_physical_id(numa_cpu);
        }
 skip_numa_setup:
@@ -731,7 +730,7 @@ skip_numa_setup:
         * case of NUMA.)
         */
        do {
-               if (++cpu >= NR_CPUS)
+               if (++cpu >= nr_cpu_ids)
                        cpu = 0;
        } while (!cpu_online(cpu) || !cpu_isset(cpu, domain));
 
index 0b6db53fedcf3b05a8417d71572143bb993752da..95ff16cb05d82501c45ac8533a250845d19e818a 100644 (file)
@@ -112,11 +112,11 @@ void set_irq_affinity_info (unsigned int irq, int hwid, int redir)
        }
 }
 
-bool is_affinity_mask_valid(cpumask_t cpumask)
+bool is_affinity_mask_valid(cpumask_var_t cpumask)
 {
        if (ia64_platform_is("sn2")) {
                /* Only allow one CPU to be specified in the smp_affinity mask */
-               if (cpus_weight(cpumask) != 1)
+               if (cpumask_weight(cpumask) != 1)
                        return false;
        }
        return true;
index 65c10a42c88f37fbb998012a8f293bd4003f1485..f0ebb342409d0b4ab3cd5d9ba470aa3284ef2667 100644 (file)
@@ -93,13 +93,14 @@ void ia64_account_on_switch(struct task_struct *prev, struct task_struct *next)
        now = ia64_get_itc();
 
        delta_stime = cycle_to_cputime(pi->ac_stime + (now - pi->ac_stamp));
-       account_system_time(prev, 0, delta_stime);
-       account_system_time_scaled(prev, delta_stime);
+       if (idle_task(smp_processor_id()) != prev)
+               account_system_time(prev, 0, delta_stime, delta_stime);
+       else
+               account_idle_time(delta_stime);
 
        if (pi->ac_utime) {
                delta_utime = cycle_to_cputime(pi->ac_utime);
-               account_user_time(prev, delta_utime);
-               account_user_time_scaled(prev, delta_utime);
+               account_user_time(prev, delta_utime, delta_utime);
        }
 
        pi->ac_stamp = ni->ac_stamp = now;
@@ -122,8 +123,10 @@ void account_system_vtime(struct task_struct *tsk)
        now = ia64_get_itc();
 
        delta_stime = cycle_to_cputime(ti->ac_stime + (now - ti->ac_stamp));
-       account_system_time(tsk, 0, delta_stime);
-       account_system_time_scaled(tsk, delta_stime);
+       if (irq_count() || idle_task(smp_processor_id()) != tsk)
+               account_system_time(tsk, 0, delta_stime, delta_stime);
+       else
+               account_idle_time(delta_stime);
        ti->ac_stime = 0;
 
        ti->ac_stamp = now;
@@ -143,8 +146,7 @@ void account_process_tick(struct task_struct *p, int user_tick)
 
        if (ti->ac_utime) {
                delta_utime = cycle_to_cputime(ti->ac_utime);
-               account_user_time(p, delta_utime);
-               account_user_time_scaled(p, delta_utime);
+               account_user_time(p, delta_utime, delta_utime);
                ti->ac_utime = 0;
        }
 }
index 76464dc312e63f781ded9f8abcbcfb8322c29a89..0bb99b732908b9b27ec724fcb3f9509c9b68fddc 100644 (file)
@@ -51,8 +51,8 @@ EXTRA_AFLAGS += -Ivirt/kvm -Iarch/ia64/kvm/
 common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o ioapic.o \
                coalesced_mmio.o irq_comm.o)
 
-ifeq ($(CONFIG_DMAR),y)
-common-objs += $(addprefix ../../../virt/kvm/, vtd.o)
+ifeq ($(CONFIG_IOMMU_API),y)
+common-objs += $(addprefix ../../../virt/kvm/, iommu.o)
 endif
 
 kvm-objs := $(common-objs) kvm-ia64.o kvm_fw.o
index 0f5ebd94843725e11277603dcb87924fd0bd2df0..4e586f6110aa08c4d2df47f8aa16a053748f8268 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/bitops.h>
 #include <linux/hrtimer.h>
 #include <linux/uaccess.h>
+#include <linux/iommu.h>
 #include <linux/intel-iommu.h>
 
 #include <asm/pgtable.h>
@@ -188,7 +189,7 @@ int kvm_dev_ioctl_check_extension(long ext)
                r = KVM_COALESCED_MMIO_PAGE_OFFSET;
                break;
        case KVM_CAP_IOMMU:
-               r = intel_iommu_found();
+               r = iommu_found();
                break;
        default:
                r = 0;
index 636588e7e0684bbce76e6c304e694af7c19c2a32..be339477f90603f8a5186dc5a634165dcd3b5e3e 100644 (file)
@@ -385,7 +385,6 @@ static int sn_topology_show(struct seq_file *s, void *d)
        int j;
        const char *slabname;
        int ordinal;
-       cpumask_t cpumask;
        char slice;
        struct cpuinfo_ia64 *c;
        struct sn_hwperf_port_info *ptdata;
@@ -473,23 +472,21 @@ static int sn_topology_show(struct seq_file *s, void *d)
                 * CPUs on this node, if any
                 */
                if (!SN_HWPERF_IS_IONODE(obj)) {
-                       cpumask = node_to_cpumask(ordinal);
-                       for_each_online_cpu(i) {
-                               if (cpu_isset(i, cpumask)) {
-                                       slice = 'a' + cpuid_to_slice(i);
-                                       c = cpu_data(i);
-                                       seq_printf(s, "cpu %d %s%c local"
-                                               " freq %luMHz, arch ia64",
-                                               i, obj->location, slice,
-                                               c->proc_freq / 1000000);
-                                       for_each_online_cpu(j) {
-                                               seq_printf(s, j ? ":%d" : ", dist %d",
-                                                       node_distance(
+                       for_each_cpu_and(i, cpu_online_mask,
+                                        cpumask_of_node(ordinal)) {
+                               slice = 'a' + cpuid_to_slice(i);
+                               c = cpu_data(i);
+                               seq_printf(s, "cpu %d %s%c local"
+                                          " freq %luMHz, arch ia64",
+                                          i, obj->location, slice,
+                                          c->proc_freq / 1000000);
+                               for_each_online_cpu(j) {
+                                       seq_printf(s, j ? ":%d" : ", dist %d",
+                                                  node_distance(
                                                        cpu_to_node(i),
                                                        cpu_to_node(j)));
-                                       }
-                                       seq_putc(s, '\n');
                                }
+                               seq_putc(s, '\n');
                        }
                }
        }
index 0f06b3722e960518bc275b1167b6948e5eb35914..2547d6c4a827c3096290a65de4a708fc0279fd20 100644 (file)
@@ -592,7 +592,7 @@ int setup_profiling_timer(unsigned int multiplier)
         * accounting. At that time they also adjust their APIC timers
         * accordingly.
         */
-       for (i = 0; i < NR_CPUS; ++i)
+       for_each_possible_cpu(i)
                per_cpu(prof_multiplier, i) = multiplier;
 
        return 0;
index 836fb66f080dcbadeb5f6d96fba8f01679d85d02..c825bde17cb363ac510bc28b83deb631fada8e8c 100644 (file)
@@ -280,7 +280,6 @@ config M68060
 
 config MMU_MOTOROLA
        bool
-       depends on MMU && !MMU_SUN3
 
 config MMU_SUN3
        bool
index 6f3685eab44c7f88818451d76599f934661a8785..9d3cbe5fad1efa3e9d9c4bb974a79aa63dd99718 100644 (file)
@@ -331,6 +331,7 @@ found_middle:
 #endif /* __KERNEL__ */
 
 #include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/__fls.h>
 #include <asm-generic/bitops/fls64.h>
 
 #endif /* _M68KNOMMU_BITOPS_H */
index 1fb959f98982c70c192e1f1fe731cc3c92f849b9..55d481569a1f494e1c33a71fe22bbfb8b88f9af4 100644 (file)
@@ -25,11 +25,13 @@ extern struct cpuinfo_ip27 sn_cpu_info[NR_CPUS];
 #define cpu_to_node(cpu)       (sn_cpu_info[(cpu)].p_nodeid)
 #define parent_node(node)      (node)
 #define node_to_cpumask(node)  (hub_data(node)->h_cpus)
-#define node_to_first_cpu(node)        (first_cpu(node_to_cpumask(node)))
+#define cpumask_of_node(node)  (&hub_data(node)->h_cpus)
+#define node_to_first_cpu(node)        (cpumask_first(cpumask_of_node(node)))
 struct pci_bus;
 extern int pcibus_to_node(struct pci_bus *);
 
 #define pcibus_to_cpumask(bus) (cpu_online_map)
+#define cpumask_of_pcibus(bus) (cpu_online_mask)
 
 extern unsigned char __node_distances[MAX_COMPACT_NODES][MAX_COMPACT_NODES];
 
index 409e698f436117bd2a18468f8a26ead3cf400d16..6ef4b7867b1b356a933ebf1744e65739adc87838 100644 (file)
@@ -16,8 +16,6 @@
 #include <linux/cpumask.h>
 typedef unsigned long address_t;
 
-extern cpumask_t cpu_online_map;
-
 
 /*
  *     Private routines/data
index 373fca394a54a1a1841d06d2ebec20440aa4ca7d..375258559ae64fa26e09452c4e80ca978b2a3fe3 100644 (file)
@@ -22,11 +22,11 @@ static inline cpumask_t node_to_cpumask(int node)
        return numa_cpumask_lookup_table[node];
 }
 
+#define cpumask_of_node(node) (&numa_cpumask_lookup_table[node])
+
 static inline int node_to_first_cpu(int node)
 {
-       cpumask_t tmp;
-       tmp = node_to_cpumask(node);
-       return first_cpu(tmp);
+       return cpumask_first(cpumask_of_node(node));
 }
 
 int of_node_to_nid(struct device_node *device);
@@ -46,6 +46,10 @@ static inline int pcibus_to_node(struct pci_bus *bus)
                                        node_to_cpumask(pcibus_to_node(bus)) \
                                )
 
+#define cpumask_of_pcibus(bus) (pcibus_to_node(bus) == -1 ?            \
+                                cpu_all_mask :                         \
+                                cpumask_of_node(pcibus_to_node(bus)))
+
 /* sched_domains SD_NODE_INIT for PPC64 machines */
 #define SD_NODE_INIT (struct sched_domain) {           \
        .parent                 = NULL,                 \
@@ -108,6 +112,8 @@ static inline void sysfs_remove_device_from_node(struct sys_device *dev,
 
 #define topology_thread_siblings(cpu)  (per_cpu(cpu_sibling_map, cpu))
 #define topology_core_siblings(cpu)    (per_cpu(cpu_core_map, cpu))
+#define topology_thread_cpumask(cpu)   (&per_cpu(cpu_sibling_map, cpu))
+#define topology_core_cpumask(cpu)     (&per_cpu(cpu_core_map, cpu))
 #define topology_core_id(cpu)          (cpu_to_core_id(cpu))
 #endif
 #endif
index 51b201ddf9a160002d10ff3c61cd9bb2e40119a5..fb7049c054c061765feae824d635da3477d1b624 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/mqueue.h>
 #include <linux/hardirq.h>
 #include <linux/utsname.h>
+#include <linux/kernel_stat.h>
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
index 99f1ddd68582e9628456f8d8e7f8fe3fb0c5b25f..c9564031a2a9c7878f9e9a694fe8e9ca3622a85e 100644 (file)
@@ -256,8 +256,10 @@ void account_system_vtime(struct task_struct *tsk)
                delta += sys_time;
                get_paca()->system_time = 0;
        }
-       account_system_time(tsk, 0, delta);
-       account_system_time_scaled(tsk, deltascaled);
+       if (in_irq() || idle_task(smp_processor_id()) != tsk)
+               account_system_time(tsk, 0, delta, deltascaled);
+       else
+               account_idle_time(delta);
        per_cpu(cputime_last_delta, smp_processor_id()) = delta;
        per_cpu(cputime_scaled_last_delta, smp_processor_id()) = deltascaled;
        local_irq_restore(flags);
@@ -275,10 +277,8 @@ void account_process_tick(struct task_struct *tsk, int user_tick)
 
        utime = get_paca()->user_time;
        get_paca()->user_time = 0;
-       account_user_time(tsk, utime);
-
        utimescaled = cputime_to_scaled(utime);
-       account_user_time_scaled(tsk, utimescaled);
+       account_user_time(tsk, utime, utimescaled);
 }
 
 /*
@@ -338,8 +338,12 @@ void calculate_steal_time(void)
        tb = mftb();
        purr = mfspr(SPRN_PURR);
        stolen = (tb - pme->tb) - (purr - pme->purr);
-       if (stolen > 0)
-               account_steal_time(current, stolen);
+       if (stolen > 0) {
+               if (idle_task(smp_processor_id()) != current)
+                       account_steal_time(stolen);
+               else
+                       account_idle_time(stolen);
+       }
        pme->tb = tb;
        pme->purr = purr;
 }
index 906a0a2a9fe18fc4273be7916f18df118c824dc1..1410443731eb8b6aab3f7fae2f64b35ca92c5e2a 100644 (file)
@@ -80,10 +80,10 @@ static void cpu_affinity_set(struct spu *spu, int cpu)
        u64 route;
 
        if (nr_cpus_node(spu->node)) {
-               cpumask_t spumask = node_to_cpumask(spu->node);
-               cpumask_t cpumask = node_to_cpumask(cpu_to_node(cpu));
+               const struct cpumask *spumask = cpumask_of_node(spu->node),
+                       *cpumask = cpumask_of_node(cpu_to_node(cpu));
 
-               if (!cpus_intersects(spumask, cpumask))
+               if (!cpumask_intersects(spumask, cpumask))
                        return;
        }
 
index 6296bfd9cb0b5646ce7b1cd8d195041f8ed239bf..e309ef70a53140b4e156fbfb1f38f06863b7eee2 100644 (file)
@@ -97,7 +97,6 @@ spufs_new_inode(struct super_block *sb, int mode)
        inode->i_mode = mode;
        inode->i_uid = current_fsuid();
        inode->i_gid = current_fsgid();
-       inode->i_blocks = 0;
        inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 out:
        return inode;
index 2ad914c47493fbd870cc6eaf1acd70991f256440..6a0ad196aeb348243e904aedba3804c0081e431e 100644 (file)
@@ -166,9 +166,9 @@ void spu_update_sched_info(struct spu_context *ctx)
 static int __node_allowed(struct spu_context *ctx, int node)
 {
        if (nr_cpus_node(node)) {
-               cpumask_t mask = node_to_cpumask(node);
+               const struct cpumask *mask = cpumask_of_node(node);
 
-               if (cpus_intersects(mask, ctx->cpus_allowed))
+               if (cpumask_intersects(mask, &ctx->cpus_allowed))
                        return 1;
        }
 
index 9d4f8e6c0800e635c8f10b69b9b81400409b75a9..5a805df216bb22927f8b344c5d2fe8e719913b1c 100644 (file)
@@ -106,7 +106,6 @@ static struct inode *hypfs_make_inode(struct super_block *sb, int mode)
                ret->i_mode = mode;
                ret->i_uid = hypfs_info->uid;
                ret->i_gid = hypfs_info->gid;
-               ret->i_blocks = 0;
                ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
                if (mode & S_IFDIR)
                        ret->i_nlink = 2;
index e5a6a9ba3adfb6574153e72d75a67f50eda1b896..d60a2eefb17b46fc04e69a71c5707a010672c078 100644 (file)
@@ -14,7 +14,6 @@
 
 struct s390_idle_data {
        spinlock_t lock;
-       unsigned int in_idle;
        unsigned long long idle_count;
        unsigned long long idle_enter;
        unsigned long long idle_time;
@@ -22,12 +21,12 @@ struct s390_idle_data {
 
 DECLARE_PER_CPU(struct s390_idle_data, s390_idle);
 
-void s390_idle_leave(void);
+void vtime_start_cpu(void);
 
 static inline void s390_idle_check(void)
 {
-       if ((&__get_cpu_var(s390_idle))->in_idle)
-               s390_idle_leave();
+       if ((&__get_cpu_var(s390_idle))->idle_enter != 0ULL)
+               vtime_start_cpu();
 }
 
 #endif /* _ASM_S390_CPU_H_ */
index 133ce054fc8945dbe4d18a7fe8fd031908410c3b..521726430afac81fcb19e870e4765a44fa85e528 100644 (file)
@@ -11,7 +11,7 @@
 
 #include <asm/div64.h>
 
-/* We want to use micro-second resolution. */
+/* We want to use full resolution of the CPU timer: 2**-12 micro-seconds. */
 
 typedef unsigned long long cputime_t;
 typedef unsigned long long cputime64_t;
@@ -53,9 +53,9 @@ __div(unsigned long long n, unsigned int base)
 #define cputime_ge(__a, __b)           ((__a) >= (__b))
 #define cputime_lt(__a, __b)           ((__a) <  (__b))
 #define cputime_le(__a, __b)           ((__a) <= (__b))
-#define cputime_to_jiffies(__ct)       (__div((__ct), 1000000 / HZ))
+#define cputime_to_jiffies(__ct)       (__div((__ct), 4096000000ULL / HZ))
 #define cputime_to_scaled(__ct)                (__ct)
-#define jiffies_to_cputime(__hz)       ((cputime_t)(__hz) * (1000000 / HZ))
+#define jiffies_to_cputime(__hz)       ((cputime_t)(__hz) * (4096000000ULL / HZ))
 
 #define cputime64_zero                 (0ULL)
 #define cputime64_add(__a, __b)                ((__a) + (__b))
@@ -64,7 +64,7 @@ __div(unsigned long long n, unsigned int base)
 static inline u64
 cputime64_to_jiffies64(cputime64_t cputime)
 {
-       do_div(cputime, 1000000 / HZ);
+       do_div(cputime, 4096000000ULL / HZ);
        return cputime;
 }
 
@@ -74,13 +74,13 @@ cputime64_to_jiffies64(cputime64_t cputime)
 static inline unsigned int
 cputime_to_msecs(const cputime_t cputime)
 {
-       return __div(cputime, 1000);
+       return __div(cputime, 4096000);
 }
 
 static inline cputime_t
 msecs_to_cputime(const unsigned int m)
 {
-       return (cputime_t) m * 1000;
+       return (cputime_t) m * 4096000;
 }
 
 /*
@@ -89,13 +89,13 @@ msecs_to_cputime(const unsigned int m)
 static inline unsigned int
 cputime_to_secs(const cputime_t cputime)
 {
-       return __div(cputime, 1000000);
+       return __div(cputime, 2048000000) >> 1;
 }
 
 static inline cputime_t
 secs_to_cputime(const unsigned int s)
 {
-       return (cputime_t) s * 1000000;
+       return (cputime_t) s * 4096000000ULL;
 }
 
 /*
@@ -104,7 +104,7 @@ secs_to_cputime(const unsigned int s)
 static inline cputime_t
 timespec_to_cputime(const struct timespec *value)
 {
-        return value->tv_nsec / 1000 + (u64) value->tv_sec * 1000000;
+       return value->tv_nsec * 4096 / 1000 + (u64) value->tv_sec * 4096000000ULL;
 }
 
 static inline void
@@ -114,12 +114,12 @@ cputime_to_timespec(const cputime_t cputime, struct timespec *value)
        register_pair rp;
 
        rp.pair = cputime >> 1;
-       asm ("dr %0,%1" : "+d" (rp) : "d" (1000000 >> 1));
-       value->tv_nsec = rp.subreg.even * 1000;
+       asm ("dr %0,%1" : "+d" (rp) : "d" (2048000000UL));
+       value->tv_nsec = rp.subreg.even * 1000 / 4096;
        value->tv_sec = rp.subreg.odd;
 #else
-       value->tv_nsec = (cputime % 1000000) * 1000;
-       value->tv_sec = cputime / 1000000;
+       value->tv_nsec = (cputime % 4096000000ULL) * 1000 / 4096;
+       value->tv_sec = cputime / 4096000000ULL;
 #endif
 }
 
@@ -131,7 +131,7 @@ cputime_to_timespec(const cputime_t cputime, struct timespec *value)
 static inline cputime_t
 timeval_to_cputime(const struct timeval *value)
 {
-        return value->tv_usec + (u64) value->tv_sec * 1000000;
+       return value->tv_usec * 4096 + (u64) value->tv_sec * 4096000000ULL;
 }
 
 static inline void
@@ -141,12 +141,12 @@ cputime_to_timeval(const cputime_t cputime, struct timeval *value)
        register_pair rp;
 
        rp.pair = cputime >> 1;
-       asm ("dr %0,%1" : "+d" (rp) : "d" (1000000 >> 1));
-       value->tv_usec = rp.subreg.even;
+       asm ("dr %0,%1" : "+d" (rp) : "d" (2048000000UL));
+       value->tv_usec = rp.subreg.even / 4096;
        value->tv_sec = rp.subreg.odd;
 #else
-       value->tv_usec = cputime % 1000000;
-       value->tv_sec = cputime / 1000000;
+       value->tv_usec = cputime % 4096000000ULL;
+       value->tv_sec = cputime / 4096000000ULL;
 #endif
 }
 
@@ -156,13 +156,13 @@ cputime_to_timeval(const cputime_t cputime, struct timeval *value)
 static inline clock_t
 cputime_to_clock_t(cputime_t cputime)
 {
-       return __div(cputime, 1000000 / USER_HZ);
+       return __div(cputime, 4096000000ULL / USER_HZ);
 }
 
 static inline cputime_t
 clock_t_to_cputime(unsigned long x)
 {
-       return (cputime_t) x * (1000000 / USER_HZ);
+       return (cputime_t) x * (4096000000ULL / USER_HZ);
 }
 
 /*
@@ -171,7 +171,7 @@ clock_t_to_cputime(unsigned long x)
 static inline clock_t
 cputime64_to_clock_t(cputime64_t cputime)
 {
-       return __div(cputime, 1000000 / USER_HZ);
+       return __div(cputime, 4096000000ULL / USER_HZ);
 }
 
 #endif /* _S390_CPUTIME_H */
index 0bc51d52a899d5b1d07b3bd1dceafa6858a0a3ef..ffdef5fe8587017a6b25aa2ba44c37a5aa1f9ce6 100644 (file)
 #define __LC_SYNC_ENTER_TIMER          0x248
 #define __LC_ASYNC_ENTER_TIMER         0x250
 #define __LC_EXIT_TIMER                        0x258
-#define __LC_LAST_UPDATE_TIMER         0x260
-#define __LC_USER_TIMER                        0x268
-#define __LC_SYSTEM_TIMER              0x270
-#define __LC_LAST_UPDATE_CLOCK         0x278
-#define __LC_STEAL_CLOCK               0x280
+#define __LC_USER_TIMER                        0x260
+#define __LC_SYSTEM_TIMER              0x268
+#define __LC_STEAL_TIMER               0x270
+#define __LC_LAST_UPDATE_TIMER         0x278
+#define __LC_LAST_UPDATE_CLOCK         0x280
 #define __LC_RETURN_MCCK_PSW            0x288
 #define __LC_KERNEL_STACK               0xC40
 #define __LC_THREAD_INFO               0xC44
 #define __LC_SYNC_ENTER_TIMER          0x250
 #define __LC_ASYNC_ENTER_TIMER         0x258
 #define __LC_EXIT_TIMER                        0x260
-#define __LC_LAST_UPDATE_TIMER         0x268
-#define __LC_USER_TIMER                        0x270
-#define __LC_SYSTEM_TIMER              0x278
-#define __LC_LAST_UPDATE_CLOCK         0x280
-#define __LC_STEAL_CLOCK               0x288
+#define __LC_USER_TIMER                        0x268
+#define __LC_SYSTEM_TIMER              0x270
+#define __LC_STEAL_TIMER               0x278
+#define __LC_LAST_UPDATE_TIMER         0x280
+#define __LC_LAST_UPDATE_CLOCK         0x288
 #define __LC_RETURN_MCCK_PSW            0x290
 #define __LC_KERNEL_STACK               0xD40
 #define __LC_THREAD_INFO               0xD48
 #define __LC_IPLDEV                     0xDB8
 #define __LC_CURRENT                   0xDD8
 #define __LC_INT_CLOCK                 0xDE8
+#define __LC_VDSO_PER_CPU              0xE38
 #endif /* __s390x__ */
 
+#define __LC_PASTE                     0xE40
 
 #define __LC_PANIC_MAGIC               0xE00
 #ifndef __s390x__
@@ -252,11 +254,11 @@ struct _lowcore
        __u64        sync_enter_timer;         /* 0x248 */
        __u64        async_enter_timer;        /* 0x250 */
        __u64        exit_timer;               /* 0x258 */
-       __u64        last_update_timer;        /* 0x260 */
-       __u64        user_timer;               /* 0x268 */
-       __u64        system_timer;             /* 0x270 */
-       __u64        last_update_clock;        /* 0x278 */
-       __u64        steal_clock;              /* 0x280 */
+       __u64        user_timer;               /* 0x260 */
+       __u64        system_timer;             /* 0x268 */
+       __u64        steal_timer;              /* 0x270 */
+       __u64        last_update_timer;        /* 0x278 */
+       __u64        last_update_clock;        /* 0x280 */
         psw_t        return_mcck_psw;          /* 0x288 */
        __u8         pad8[0xc00-0x290];        /* 0x290 */
 
@@ -343,11 +345,11 @@ struct _lowcore
        __u64        sync_enter_timer;         /* 0x250 */
        __u64        async_enter_timer;        /* 0x258 */
        __u64        exit_timer;               /* 0x260 */
-       __u64        last_update_timer;        /* 0x268 */
-       __u64        user_timer;               /* 0x270 */
-       __u64        system_timer;             /* 0x278 */
-       __u64        last_update_clock;        /* 0x280 */
-       __u64        steal_clock;              /* 0x288 */
+       __u64        user_timer;               /* 0x268 */
+       __u64        system_timer;             /* 0x270 */
+       __u64        steal_timer;              /* 0x278 */
+       __u64        last_update_timer;        /* 0x280 */
+       __u64        last_update_clock;        /* 0x288 */
         psw_t        return_mcck_psw;          /* 0x290 */
         __u8         pad8[0xc00-0x2a0];        /* 0x2a0 */
         /* System info area */
@@ -381,7 +383,12 @@ struct _lowcore
         /* whether the kernel died with panic() or not */
         __u32        panic_magic;              /* 0xe00 */
 
-       __u8         pad13[0x11b8-0xe04];      /* 0xe04 */
+       /* Per cpu primary space access list */
+       __u8         pad_0xe04[0xe3c-0xe04];   /* 0xe04 */
+       __u32        vdso_per_cpu_data;        /* 0xe3c */
+       __u32        paste[16];                /* 0xe40 */
+
+       __u8         pad13[0x11b8-0xe80];      /* 0xe80 */
 
        /* 64 bit extparam used for pfault, diag 250 etc  */
        __u64        ext_params2;               /* 0x11B8 */
index 024ef42ed6d73e44d510466680f7fbc54710b05c..3a8b26eb1f2e827d3d6de72b508dd307c08de6a0 100644 (file)
@@ -99,7 +99,7 @@ static inline void restore_access_regs(unsigned int *acrs)
        prev = __switch_to(prev,next);                                       \
 } while (0)
 
-extern void account_vtime(struct task_struct *);
+extern void account_vtime(struct task_struct *, struct task_struct *);
 extern void account_tick_vtime(struct task_struct *);
 extern void account_system_vtime(struct task_struct *);
 
@@ -121,7 +121,7 @@ static inline void cmma_init(void) { }
 
 #define finish_arch_switch(prev) do {                                       \
        set_fs(current->thread.mm_segment);                                  \
-       account_vtime(prev);                                                 \
+       account_vtime(prev, current);                                        \
 } while (0)
 
 #define nop() asm volatile("nop")
index c1eaf9604da73363832a88756f7a4118af5c4023..c544aa5245350c2e517c8712352b3b54648df569 100644 (file)
@@ -47,6 +47,8 @@ struct thread_info {
        unsigned int            cpu;            /* current CPU */
        int                     preempt_count;  /* 0 => preemptable, <0 => BUG */
        struct restart_block    restart_block;
+       __u64                   user_timer;
+       __u64                   system_timer;
 };
 
 /*
index 61705d60f9955a2dc0d217a445b8be6f0a34b174..e4bcab739c196a86233a1ca38292d130be0703df 100644 (file)
@@ -23,20 +23,18 @@ struct vtimer_list {
        __u64 expires;
        __u64 interval;
 
-       spinlock_t lock;
-       unsigned long magic;
-
        void (*function)(unsigned long);
        unsigned long data;
 };
 
-/* the offset value will wrap after ca. 71 years */
+/* the vtimer value will wrap after ca. 71 years */
 struct vtimer_queue {
        struct list_head list;
        spinlock_t lock;
-       __u64 to_expire;          /* current event expire time */
-       __u64 offset;             /* list offset to zero */
-       __u64 idle;               /* temp var for idle */
+       __u64 timer;            /* last programmed timer */
+       __u64 elapsed;          /* elapsed time of timer expire values */
+       __u64 idle;             /* temp var for idle */
+       int do_spt;             /* =1: reprogram cpu timer in idle */
 };
 
 extern void init_virt_timer(struct vtimer_list *timer);
@@ -48,8 +46,8 @@ extern int del_virt_timer(struct vtimer_list *timer);
 extern void init_cpu_vtimer(void);
 extern void vtime_init(void);
 
-extern void vtime_start_cpu_timer(void);
-extern void vtime_stop_cpu_timer(void);
+extern void vtime_stop_cpu(void);
+extern void vtime_start_leave(void);
 
 #endif /* __KERNEL__ */
 
index d96c916434586c3ea05abdac4ff451f0caa08465..c93eb50e1d09f5f1f4e897cc930e3b9d6098f735 100644 (file)
@@ -6,10 +6,12 @@
 #define mc_capable()   (1)
 
 cpumask_t cpu_coregroup_map(unsigned int cpu);
+const struct cpumask *cpu_coregroup_mask(unsigned int cpu);
 
 extern cpumask_t cpu_core_map[NR_CPUS];
 
 #define topology_core_siblings(cpu)    (cpu_core_map[cpu])
+#define topology_core_cpumask(cpu)     (&cpu_core_map[cpu])
 
 int topology_set_cpu_management(int fc);
 void topology_schedule_update(void);
index a44f4fe16a352286eb66b44fdd7e8eade17c4398..7bdd7c8ebc91410f6d3eb616fab0d3660a13add7 100644 (file)
@@ -12,9 +12,9 @@
 #ifndef __ASSEMBLY__
 
 /*
- * Note about this structure:
+ * Note about the vdso_data and vdso_per_cpu_data structures:
  *
- * NEVER USE THIS IN USERSPACE CODE DIRECTLY. The layout of this
+ * NEVER USE THEM IN USERSPACE CODE DIRECTLY. The layout of the
  * structure is supposed to be known only to the function in the vdso
  * itself and may change without notice.
  */
@@ -28,10 +28,21 @@ struct vdso_data {
        __u64 wtom_clock_nsec;          /*                              0x28 */
        __u32 tz_minuteswest;           /* Minutes west of Greenwich    0x30 */
        __u32 tz_dsttime;               /* Type of dst correction       0x34 */
+       __u32 ectg_available;
+};
+
+struct vdso_per_cpu_data {
+       __u64 ectg_timer_base;
+       __u64 ectg_user_time;
 };
 
 extern struct vdso_data *vdso_data;
 
+#ifdef CONFIG_64BIT
+int vdso_alloc_per_cpu(int cpu, struct _lowcore *lowcore);
+void vdso_free_per_cpu(int cpu, struct _lowcore *lowcore);
+#endif
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* __KERNEL__ */
index e641f60bac99db29aa252e8cc5b33186277c1cfb..67a60016babbc628afe7c7d980114d85c21068f5 100644 (file)
@@ -48,6 +48,11 @@ int main(void)
        DEFINE(__VDSO_WTOM_SEC, offsetof(struct vdso_data, wtom_clock_sec));
        DEFINE(__VDSO_WTOM_NSEC, offsetof(struct vdso_data, wtom_clock_nsec));
        DEFINE(__VDSO_TIMEZONE, offsetof(struct vdso_data, tz_minuteswest));
+       DEFINE(__VDSO_ECTG_OK, offsetof(struct vdso_data, ectg_available));
+       DEFINE(__VDSO_ECTG_BASE,
+              offsetof(struct vdso_per_cpu_data, ectg_timer_base));
+       DEFINE(__VDSO_ECTG_USER,
+              offsetof(struct vdso_per_cpu_data, ectg_user_time));
        /* constants used by the vdso */
        DEFINE(CLOCK_REALTIME, CLOCK_REALTIME);
        DEFINE(CLOCK_MONOTONIC, CLOCK_MONOTONIC);
index 55de521aef773f813d8f8228d504c45ece216dfa..1268aa2991bfb34eac601236e6515ea9719bfa4b 100644 (file)
@@ -583,8 +583,8 @@ kernel_per:
 
        .globl io_int_handler
 io_int_handler:
-       stpt    __LC_ASYNC_ENTER_TIMER
        stck    __LC_INT_CLOCK
+       stpt    __LC_ASYNC_ENTER_TIMER
        SAVE_ALL_BASE __LC_SAVE_AREA+16
        SAVE_ALL_ASYNC __LC_IO_OLD_PSW,__LC_SAVE_AREA+16
        CREATE_STACK_FRAME __LC_IO_OLD_PSW,__LC_SAVE_AREA+16
@@ -723,8 +723,8 @@ io_notify_resume:
 
        .globl  ext_int_handler
 ext_int_handler:
-       stpt    __LC_ASYNC_ENTER_TIMER
        stck    __LC_INT_CLOCK
+       stpt    __LC_ASYNC_ENTER_TIMER
        SAVE_ALL_BASE __LC_SAVE_AREA+16
        SAVE_ALL_ASYNC __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16
        CREATE_STACK_FRAME __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16
@@ -750,6 +750,7 @@ __critical_end:
 
        .globl mcck_int_handler
 mcck_int_handler:
+       stck    __LC_INT_CLOCK
        spt     __LC_CPU_TIMER_SAVE_AREA        # revalidate cpu timer
        lm      %r0,%r15,__LC_GPREGS_SAVE_AREA  # revalidate gprs
        SAVE_ALL_BASE __LC_SAVE_AREA+32
index 16bb4fd1a403bc2061d0afe55e63611985471a7c..c6fbde13971a5180ec1b2d33a845f031b0cccbeb 100644 (file)
@@ -177,8 +177,11 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
        .if !\sync
        ni      \psworg+1,0xfd          # clear wait state bit
        .endif
-       lmg     %r0,%r15,SP_R0(%r15)    # load gprs 0-15 of user
+       lg      %r14,__LC_VDSO_PER_CPU
+       lmg     %r0,%r13,SP_R0(%r15)    # load gprs 0-13 of user
        stpt    __LC_EXIT_TIMER
+       mvc     __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER
+       lmg     %r14,%r15,SP_R14(%r15)  # load grps 14-15 of user
        lpswe   \psworg                 # back to caller
        .endm
 
@@ -559,8 +562,8 @@ kernel_per:
  */
        .globl io_int_handler
 io_int_handler:
-       stpt    __LC_ASYNC_ENTER_TIMER
        stck    __LC_INT_CLOCK
+       stpt    __LC_ASYNC_ENTER_TIMER
        SAVE_ALL_BASE __LC_SAVE_AREA+32
        SAVE_ALL_ASYNC __LC_IO_OLD_PSW,__LC_SAVE_AREA+32
        CREATE_STACK_FRAME __LC_IO_OLD_PSW,__LC_SAVE_AREA+32
@@ -721,8 +724,8 @@ io_notify_resume:
  */
        .globl  ext_int_handler
 ext_int_handler:
-       stpt    __LC_ASYNC_ENTER_TIMER
        stck    __LC_INT_CLOCK
+       stpt    __LC_ASYNC_ENTER_TIMER
        SAVE_ALL_BASE __LC_SAVE_AREA+32
        SAVE_ALL_ASYNC __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32
        CREATE_STACK_FRAME __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32
@@ -746,6 +749,7 @@ __critical_end:
  */
        .globl mcck_int_handler
 mcck_int_handler:
+       stck    __LC_INT_CLOCK
        la      %r1,4095                # revalidate r1
        spt     __LC_CPU_TIMER_SAVE_AREA-4095(%r1)      # revalidate cpu timer
        lmg     %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs
@@ -979,23 +983,23 @@ cleanup_sysc_return:
 
 cleanup_sysc_leave:
        clc     8(8,%r12),BASED(cleanup_sysc_leave_insn)
-       je      2f
-       mvc     __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER
+       je      3f
        clc     8(8,%r12),BASED(cleanup_sysc_leave_insn+8)
-       je      2f
-       mvc     __LC_RETURN_PSW(16),SP_PSW(%r15)
+       jhe     0f
+       mvc     __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER
+0:     mvc     __LC_RETURN_PSW(16),SP_PSW(%r15)
        cghi    %r12,__LC_MCK_OLD_PSW
-       jne     0f
+       jne     1f
        mvc     __LC_SAVE_AREA+64(32),SP_R12(%r15)
-       j       1f
-0:     mvc     __LC_SAVE_AREA+32(32),SP_R12(%r15)
-1:     lmg     %r0,%r11,SP_R0(%r15)
+       j       2f
+1:     mvc     __LC_SAVE_AREA+32(32),SP_R12(%r15)
+2:     lmg     %r0,%r11,SP_R0(%r15)
        lg      %r15,SP_R15(%r15)
-2:     la      %r12,__LC_RETURN_PSW
+3:     la      %r12,__LC_RETURN_PSW
        br      %r14
 cleanup_sysc_leave_insn:
        .quad   sysc_done - 4
-       .quad   sysc_done - 8
+       .quad   sysc_done - 16
 
 cleanup_io_return:
        mvc     __LC_RETURN_PSW(8),0(%r12)
@@ -1005,23 +1009,23 @@ cleanup_io_return:
 
 cleanup_io_leave:
        clc     8(8,%r12),BASED(cleanup_io_leave_insn)
-       je      2f
-       mvc     __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER
+       je      3f
        clc     8(8,%r12),BASED(cleanup_io_leave_insn+8)
-       je      2f
-       mvc     __LC_RETURN_PSW(16),SP_PSW(%r15)
+       jhe     0f
+       mvc     __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER
+0:     mvc     __LC_RETURN_PSW(16),SP_PSW(%r15)
        cghi    %r12,__LC_MCK_OLD_PSW
-       jne     0f
+       jne     1f
        mvc     __LC_SAVE_AREA+64(32),SP_R12(%r15)
-       j       1f
-0:     mvc     __LC_SAVE_AREA+32(32),SP_R12(%r15)
-1:     lmg     %r0,%r11,SP_R0(%r15)
+       j       2f
+1:     mvc     __LC_SAVE_AREA+32(32),SP_R12(%r15)
+2:     lmg     %r0,%r11,SP_R0(%r15)
        lg      %r15,SP_R15(%r15)
-2:     la      %r12,__LC_RETURN_PSW
+3:     la      %r12,__LC_RETURN_PSW
        br      %r14
 cleanup_io_leave_insn:
        .quad   io_done - 4
-       .quad   io_done - 8
+       .quad   io_done - 16
 
 /*
  * Integer constants
index 3ccd36b24b8f82b10efe7ccb37d92bf31bf9fb10..f9f70aa15244152423cd3ff0182224e6158197ab 100644 (file)
@@ -87,6 +87,8 @@ startup_continue:
        lg      %r12,.Lparmaddr-.LPG1(%r13)     # pointer to parameter area
                                        # move IPL device to lowcore
        mvc     __LC_IPLDEV(4),IPL_DEVICE+4-PARMAREA(%r12)
+       lghi    %r0,__LC_PASTE
+       stg     %r0,__LC_VDSO_PER_CPU
 #
 # Setup stack
 #
index 04f8c67a610180413788684390d64bc613b8ca30..b6110bdf8dc27b13d7f1d672086db1738bb4d5ef 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/utsname.h>
 #include <linux/tick.h>
 #include <linux/elfcore.h>
+#include <linux/kernel_stat.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
@@ -45,7 +46,6 @@
 #include <asm/processor.h>
 #include <asm/irq.h>
 #include <asm/timer.h>
-#include <asm/cpu.h>
 #include "entry.h"
 
 asmlinkage void ret_from_fork(void) asm ("ret_from_fork");
@@ -75,36 +75,6 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
        return sf->gprs[8];
 }
 
-DEFINE_PER_CPU(struct s390_idle_data, s390_idle) = {
-       .lock = __SPIN_LOCK_UNLOCKED(s390_idle.lock)
-};
-
-static int s390_idle_enter(void)
-{
-       struct s390_idle_data *idle;
-
-       idle = &__get_cpu_var(s390_idle);
-       spin_lock(&idle->lock);
-       idle->idle_count++;
-       idle->in_idle = 1;
-       idle->idle_enter = get_clock();
-       spin_unlock(&idle->lock);
-       vtime_stop_cpu_timer();
-       return NOTIFY_OK;
-}
-
-void s390_idle_leave(void)
-{
-       struct s390_idle_data *idle;
-
-       vtime_start_cpu_timer();
-       idle = &__get_cpu_var(s390_idle);
-       spin_lock(&idle->lock);
-       idle->idle_time += get_clock() - idle->idle_enter;
-       idle->in_idle = 0;
-       spin_unlock(&idle->lock);
-}
-
 extern void s390_handle_mcck(void);
 /*
  * The idle loop on a S390...
@@ -117,10 +87,6 @@ static void default_idle(void)
                local_irq_enable();
                return;
        }
-       if (s390_idle_enter() == NOTIFY_BAD) {
-               local_irq_enable();
-               return;
-       }
 #ifdef CONFIG_HOTPLUG_CPU
        if (cpu_is_offline(smp_processor_id())) {
                preempt_enable_no_resched();
@@ -130,7 +96,6 @@ static void default_idle(void)
        local_mcck_disable();
        if (test_thread_flag(TIF_MCCK_PENDING)) {
                local_mcck_enable();
-               s390_idle_leave();
                local_irq_enable();
                s390_handle_mcck();
                return;
@@ -138,9 +103,9 @@ static void default_idle(void)
        trace_hardirqs_on();
        /* Don't trace preempt off for idle. */
        stop_critical_timings();
-       /* Wait for external, I/O or machine check interrupt. */
-       __load_psw_mask(psw_kernel_bits | PSW_MASK_WAIT |
-                       PSW_MASK_IO | PSW_MASK_EXT);
+       /* Stop virtual timer and halt the cpu. */
+       vtime_stop_cpu();
+       /* Reenable preemption tracer. */
        start_critical_timings();
 }
 
index e019b419efc64011bd5d48e0c95ec82efe5ffdd9..a0d2d55d7fb3996faae1fcaf686b44d1ef353863 100644 (file)
@@ -119,8 +119,8 @@ void do_extint(struct pt_regs *regs, unsigned short code)
        struct pt_regs *old_regs;
 
        old_regs = set_irq_regs(regs);
-       irq_enter();
        s390_idle_check();
+       irq_enter();
        if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator)
                /* Serve timer interrupts first. */
                clock_comparator_work();
index b7a1efd5522cac0d972dde9a9d73f5f8114c51bc..d825f4950e4e2f721e89de76fc98fe3dad91971b 100644 (file)
@@ -427,6 +427,8 @@ setup_lowcore(void)
                /* enable extended save area */
                __ctl_set_bit(14, 29);
        }
+#else
+       lc->vdso_per_cpu_data = (unsigned long) &lc->paste[0];
 #endif
        set_prefix((u32)(unsigned long) lc);
 }
index 3ed5c7a83c6c477e242ab411de06f7af35121f7a..9c0ccb532a4564fa5457a97e64bffbaf41ea4a79 100644 (file)
@@ -47,6 +47,7 @@
 #include <asm/lowcore.h>
 #include <asm/sclp.h>
 #include <asm/cpu.h>
+#include <asm/vdso.h>
 #include "entry.h"
 
 /*
@@ -500,6 +501,9 @@ static int __cpuinit smp_alloc_lowcore(int cpu)
                        goto out;
                lowcore->extended_save_area_addr = (u32) save_area;
        }
+#else
+       if (vdso_alloc_per_cpu(cpu, lowcore))
+               goto out;
 #endif
        lowcore_ptr[cpu] = lowcore;
        return 0;
@@ -522,6 +526,8 @@ static void smp_free_lowcore(int cpu)
 #ifndef CONFIG_64BIT
        if (MACHINE_HAS_IEEE)
                free_page((unsigned long) lowcore->extended_save_area_addr);
+#else
+       vdso_free_per_cpu(cpu, lowcore);
 #endif
        free_page(lowcore->panic_stack - PAGE_SIZE);
        free_pages(lowcore->async_stack - ASYNC_SIZE, ASYNC_ORDER);
@@ -664,6 +670,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
        lowcore = (void *) __get_free_pages(GFP_KERNEL | GFP_DMA, lc_order);
        panic_stack = __get_free_page(GFP_KERNEL);
        async_stack = __get_free_pages(GFP_KERNEL, ASYNC_ORDER);
+       BUG_ON(!lowcore || !panic_stack || !async_stack);
 #ifndef CONFIG_64BIT
        if (MACHINE_HAS_IEEE)
                save_area = get_zeroed_page(GFP_KERNEL);
@@ -677,6 +684,8 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
 #ifndef CONFIG_64BIT
        if (MACHINE_HAS_IEEE)
                lowcore->extended_save_area_addr = (u32) save_area;
+#else
+       BUG_ON(vdso_alloc_per_cpu(smp_processor_id(), lowcore));
 #endif
        set_prefix((u32)(unsigned long) lowcore);
        local_mcck_enable();
@@ -845,9 +854,11 @@ static ssize_t show_idle_count(struct sys_device *dev,
        unsigned long long idle_count;
 
        idle = &per_cpu(s390_idle, dev->id);
-       spin_lock_irq(&idle->lock);
+       spin_lock(&idle->lock);
        idle_count = idle->idle_count;
-       spin_unlock_irq(&idle->lock);
+       if (idle->idle_enter)
+               idle_count++;
+       spin_unlock(&idle->lock);
        return sprintf(buf, "%llu\n", idle_count);
 }
 static SYSDEV_ATTR(idle_count, 0444, show_idle_count, NULL);
@@ -856,18 +867,17 @@ static ssize_t show_idle_time(struct sys_device *dev,
                                struct sysdev_attribute *attr, char *buf)
 {
        struct s390_idle_data *idle;
-       unsigned long long new_time;
+       unsigned long long now, idle_time, idle_enter;
 
        idle = &per_cpu(s390_idle, dev->id);
-       spin_lock_irq(&idle->lock);
-       if (idle->in_idle) {
-               new_time = get_clock();
-               idle->idle_time += new_time - idle->idle_enter;
-               idle->idle_enter = new_time;
-       }
-       new_time = idle->idle_time;
-       spin_unlock_irq(&idle->lock);
-       return sprintf(buf, "%llu\n", new_time >> 12);
+       spin_lock(&idle->lock);
+       now = get_clock();
+       idle_time = idle->idle_time;
+       idle_enter = idle->idle_enter;
+       if (idle_enter != 0ULL && idle_enter < now)
+               idle_time += now - idle_enter;
+       spin_unlock(&idle->lock);
+       return sprintf(buf, "%llu\n", idle_time >> 12);
 }
 static SYSDEV_ATTR(idle_time_us, 0444, show_idle_time, NULL);
 
index 90e9ba11eba1940db367d3b23a95187b4b371c70..cc362c9ea8f1acc42d001d957a35e881868b4e0b 100644 (file)
@@ -97,6 +97,11 @@ cpumask_t cpu_coregroup_map(unsigned int cpu)
        return mask;
 }
 
+const struct cpumask *cpu_coregroup_mask(unsigned int cpu)
+{
+       return &cpu_core_map[cpu];
+}
+
 static void add_cpus_to_core(struct tl_cpu *tl_cpu, struct core_info *core)
 {
        unsigned int cpu;
index 10a6ccef441224d5f0166767200f3918063fe2a8..25a6a82f1c02309e8258553435112e44d9ec4b64 100644 (file)
@@ -31,9 +31,6 @@
 #include <asm/sections.h>
 #include <asm/vdso.h>
 
-/* Max supported size for symbol names */
-#define MAX_SYMNAME    64
-
 #if defined(CONFIG_32BIT) || defined(CONFIG_COMPAT)
 extern char vdso32_start, vdso32_end;
 static void *vdso32_kbase = &vdso32_start;
@@ -70,6 +67,119 @@ static union {
 } vdso_data_store __attribute__((__section__(".data.page_aligned")));
 struct vdso_data *vdso_data = &vdso_data_store.data;
 
+/*
+ * Setup vdso data page.
+ */
+static void vdso_init_data(struct vdso_data *vd)
+{
+       unsigned int facility_list;
+
+       facility_list = stfl();
+       vd->ectg_available = switch_amode && (facility_list & 1);
+}
+
+#ifdef CONFIG_64BIT
+/*
+ * Setup per cpu vdso data page.
+ */
+static void vdso_init_per_cpu_data(int cpu, struct vdso_per_cpu_data *vpcd)
+{
+}
+
+/*
+ * Allocate/free per cpu vdso data.
+ */
+#ifdef CONFIG_64BIT
+#define SEGMENT_ORDER  2
+#else
+#define SEGMENT_ORDER  1
+#endif
+
+int vdso_alloc_per_cpu(int cpu, struct _lowcore *lowcore)
+{
+       unsigned long segment_table, page_table, page_frame;
+       u32 *psal, *aste;
+       int i;
+
+       lowcore->vdso_per_cpu_data = __LC_PASTE;
+
+       if (!switch_amode || !vdso_enabled)
+               return 0;
+
+       segment_table = __get_free_pages(GFP_KERNEL, SEGMENT_ORDER);
+       page_table = get_zeroed_page(GFP_KERNEL | GFP_DMA);
+       page_frame = get_zeroed_page(GFP_KERNEL);
+       if (!segment_table || !page_table || !page_frame)
+               goto out;
+
+       clear_table((unsigned long *) segment_table, _SEGMENT_ENTRY_EMPTY,
+                   PAGE_SIZE << SEGMENT_ORDER);
+       clear_table((unsigned long *) page_table, _PAGE_TYPE_EMPTY,
+                   256*sizeof(unsigned long));
+
+       *(unsigned long *) segment_table = _SEGMENT_ENTRY + page_table;
+       *(unsigned long *) page_table = _PAGE_RO + page_frame;
+
+       psal = (u32 *) (page_table + 256*sizeof(unsigned long));
+       aste = psal + 32;
+
+       for (i = 4; i < 32; i += 4)
+               psal[i] = 0x80000000;
+
+       lowcore->paste[4] = (u32)(addr_t) psal;
+       psal[0] = 0x20000000;
+       psal[2] = (u32)(addr_t) aste;
+       *(unsigned long *) (aste + 2) = segment_table +
+               _ASCE_TABLE_LENGTH + _ASCE_USER_BITS + _ASCE_TYPE_SEGMENT;
+       aste[4] = (u32)(addr_t) psal;
+       lowcore->vdso_per_cpu_data = page_frame;
+
+       vdso_init_per_cpu_data(cpu, (struct vdso_per_cpu_data *) page_frame);
+       return 0;
+
+out:
+       free_page(page_frame);
+       free_page(page_table);
+       free_pages(segment_table, SEGMENT_ORDER);
+       return -ENOMEM;
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+void vdso_free_per_cpu(int cpu, struct _lowcore *lowcore)
+{
+       unsigned long segment_table, page_table, page_frame;
+       u32 *psal, *aste;
+
+       if (!switch_amode || !vdso_enabled)
+               return;
+
+       psal = (u32 *)(addr_t) lowcore->paste[4];
+       aste = (u32 *)(addr_t) psal[2];
+       segment_table = *(unsigned long *)(aste + 2) & PAGE_MASK;
+       page_table = *(unsigned long *) segment_table;
+       page_frame = *(unsigned long *) page_table;
+
+       free_page(page_frame);
+       free_page(page_table);
+       free_pages(segment_table, SEGMENT_ORDER);
+}
+#endif /* CONFIG_HOTPLUG_CPU */
+
+static void __vdso_init_cr5(void *dummy)
+{
+       unsigned long cr5;
+
+       cr5 = offsetof(struct _lowcore, paste);
+       __ctl_load(cr5, 5, 5);
+}
+
+static void vdso_init_cr5(void)
+{
+       if (switch_amode && vdso_enabled)
+               on_each_cpu(__vdso_init_cr5, NULL, 1);
+}
+#endif /* CONFIG_64BIT */
+
 /*
  * This is called from binfmt_elf, we create the special vma for the
  * vDSO and insert it into the mm struct tree
@@ -172,6 +282,9 @@ static int __init vdso_init(void)
 {
        int i;
 
+       if (!vdso_enabled)
+               return 0;
+       vdso_init_data(vdso_data);
 #if defined(CONFIG_32BIT) || defined(CONFIG_COMPAT)
        /* Calculate the size of the 32 bit vDSO */
        vdso32_pages = ((&vdso32_end - &vdso32_start
@@ -208,6 +321,10 @@ static int __init vdso_init(void)
        }
        vdso64_pagelist[vdso64_pages - 1] = virt_to_page(vdso_data);
        vdso64_pagelist[vdso64_pages] = NULL;
+#ifndef CONFIG_SMP
+       BUG_ON(vdso_alloc_per_cpu(0, S390_lowcore));
+#endif
+       vdso_init_cr5();
 #endif /* CONFIG_64BIT */
 
        get_page(virt_to_page(vdso_data));
index 488e31a3c0e7ba1714542f3d7010d8fd449088e7..9ce8caafdb4ea98cef8e451aa6366d52100ef812 100644 (file)
@@ -22,7 +22,12 @@ __kernel_clock_getres:
        cghi    %r2,CLOCK_REALTIME
        je      0f
        cghi    %r2,CLOCK_MONOTONIC
+       je      0f
+       cghi    %r2,-2          /* CLOCK_THREAD_CPUTIME_ID for this thread */
        jne     2f
+       larl    %r5,_vdso_data
+       icm     %r0,15,__LC_ECTG_OK(%r5)
+       jz      2f
 0:     ltgr    %r3,%r3
        jz      1f                              /* res == NULL */
        larl    %r1,3f
index 738a410b7eb28ec27d7185e1a5a70633a3380b8a..79dbfee831ec00cf05e0fef2c8b993f1da911697 100644 (file)
@@ -22,8 +22,10 @@ __kernel_clock_gettime:
        larl    %r5,_vdso_data
        cghi    %r2,CLOCK_REALTIME
        je      4f
+       cghi    %r2,-2          /* CLOCK_THREAD_CPUTIME_ID for this thread */
+       je      9f
        cghi    %r2,CLOCK_MONOTONIC
-       jne     9f
+       jne     12f
 
        /* CLOCK_MONOTONIC */
        ltgr    %r3,%r3
@@ -42,7 +44,7 @@ __kernel_clock_gettime:
        alg     %r0,__VDSO_WTOM_SEC(%r5)
        clg     %r4,__VDSO_UPD_COUNT(%r5)       /* check update counter */
        jne     0b
-       larl    %r5,10f
+       larl    %r5,13f
 1:     clg     %r1,0(%r5)
        jl      2f
        slg     %r1,0(%r5)
@@ -68,7 +70,7 @@ __kernel_clock_gettime:
        lg      %r0,__VDSO_XTIME_SEC(%r5)
        clg     %r4,__VDSO_UPD_COUNT(%r5)       /* check update counter */
        jne     5b
-       larl    %r5,10f
+       larl    %r5,13f
 6:     clg     %r1,0(%r5)
        jl      7f
        slg     %r1,0(%r5)
@@ -79,11 +81,38 @@ __kernel_clock_gettime:
 8:     lghi    %r2,0
        br      %r14
 
+       /* CLOCK_THREAD_CPUTIME_ID for this thread */
+9:     icm     %r0,15,__VDSO_ECTG_OK(%r5)
+       jz      12f
+       ear     %r2,%a4
+       llilh   %r4,0x0100
+       sar     %a4,%r4
+       lghi    %r4,0
+       sacf    512                             /* Magic ectg instruction */
+       .insn   ssf,0xc80100000000,__VDSO_ECTG_BASE(4),__VDSO_ECTG_USER(4),4
+       sacf    0
+       sar     %a4,%r2
+       algr    %r1,%r0                         /* r1 = cputime as TOD value */
+       mghi    %r1,1000                        /* convert to nanoseconds */
+       srlg    %r1,%r1,12                      /* r1 = cputime in nanosec */
+       lgr     %r4,%r1
+       larl    %r5,13f
+       srlg    %r1,%r1,9                       /* divide by 1000000000 */
+       mlg     %r0,8(%r5)
+       srlg    %r0,%r0,11                      /* r0 = tv_sec */
+       stg     %r0,0(%r3)
+       msg     %r0,0(%r5)                      /* calculate tv_nsec */
+       slgr    %r4,%r0                         /* r4 = tv_nsec */
+       stg     %r4,8(%r3)
+       lghi    %r2,0
+       br      %r14
+
        /* Fallback to system call */
-9:     lghi    %r1,__NR_clock_gettime
+12:    lghi    %r1,__NR_clock_gettime
        svc     0
        br      %r14
 
-10:    .quad   1000000000
+13:    .quad   1000000000
+14:    .quad   19342813113834067
        .cfi_endproc
        .size   __kernel_clock_gettime,.-__kernel_clock_gettime
index 75a6e62ea9737e09471fcfd57d13b0c8fcfbed01..2fb36e462194134f53d3a7a2886938be36bf1548 100644 (file)
 #include <asm/s390_ext.h>
 #include <asm/timer.h>
 #include <asm/irq_regs.h>
+#include <asm/cpu.h>
 
 static ext_int_info_t ext_int_info_timer;
+
 static DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer);
 
+DEFINE_PER_CPU(struct s390_idle_data, s390_idle) = {
+       .lock = __SPIN_LOCK_UNLOCKED(s390_idle.lock)
+};
+
+static inline __u64 get_vtimer(void)
+{
+       __u64 timer;
+
+       asm volatile("STPT %0" : "=m" (timer));
+       return timer;
+}
+
+static inline void set_vtimer(__u64 expires)
+{
+       __u64 timer;
+
+       asm volatile ("  STPT %0\n"  /* Store current cpu timer value */
+                     "  SPT %1"     /* Set new value immediatly afterwards */
+                     : "=m" (timer) : "m" (expires) );
+       S390_lowcore.system_timer += S390_lowcore.last_update_timer - timer;
+       S390_lowcore.last_update_timer = expires;
+}
+
 /*
  * Update process times based on virtual cpu times stored by entry.S
  * to the lowcore fields user_timer, system_timer & steal_clock.
  */
-void account_process_tick(struct task_struct *tsk, int user_tick)
+static void do_account_vtime(struct task_struct *tsk, int hardirq_offset)
 {
-       cputime_t cputime;
-       __u64 timer, clock;
-       int rcu_user_flag;
+       struct thread_info *ti = task_thread_info(tsk);
+       __u64 timer, clock, user, system, steal;
 
        timer = S390_lowcore.last_update_timer;
        clock = S390_lowcore.last_update_clock;
@@ -44,50 +68,41 @@ void account_process_tick(struct task_struct *tsk, int user_tick)
                      : "=m" (S390_lowcore.last_update_timer),
                        "=m" (S390_lowcore.last_update_clock) );
        S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer;
-       S390_lowcore.steal_clock += S390_lowcore.last_update_clock - clock;
-
-       cputime = S390_lowcore.user_timer >> 12;
-       rcu_user_flag = cputime != 0;
-       S390_lowcore.user_timer -= cputime << 12;
-       S390_lowcore.steal_clock -= cputime << 12;
-       account_user_time(tsk, cputime);
-
-       cputime =  S390_lowcore.system_timer >> 12;
-       S390_lowcore.system_timer -= cputime << 12;
-       S390_lowcore.steal_clock -= cputime << 12;
-       account_system_time(tsk, HARDIRQ_OFFSET, cputime);
-
-       cputime = S390_lowcore.steal_clock;
-       if ((__s64) cputime > 0) {
-               cputime >>= 12;
-               S390_lowcore.steal_clock -= cputime << 12;
-               account_steal_time(tsk, cputime);
+       S390_lowcore.steal_timer += S390_lowcore.last_update_clock - clock;
+
+       user = S390_lowcore.user_timer - ti->user_timer;
+       S390_lowcore.steal_timer -= user;
+       ti->user_timer = S390_lowcore.user_timer;
+       account_user_time(tsk, user, user);
+
+       system = S390_lowcore.system_timer - ti->system_timer;
+       S390_lowcore.steal_timer -= system;
+       ti->system_timer = S390_lowcore.system_timer;
+       account_system_time(tsk, hardirq_offset, system, system);
+
+       steal = S390_lowcore.steal_timer;
+       if ((s64) steal > 0) {
+               S390_lowcore.steal_timer = 0;
+               account_steal_time(steal);
        }
 }
 
-/*
- * Update process times based on virtual cpu times stored by entry.S
- * to the lowcore fields user_timer, system_timer & steal_clock.
- */
-void account_vtime(struct task_struct *tsk)
+void account_vtime(struct task_struct *prev, struct task_struct *next)
 {
-       cputime_t cputime;
-       __u64 timer;
-
-       timer = S390_lowcore.last_update_timer;
-       asm volatile ("  STPT %0"    /* Store current cpu timer value */
-                     : "=m" (S390_lowcore.last_update_timer) );
-       S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer;
-
-       cputime = S390_lowcore.user_timer >> 12;
-       S390_lowcore.user_timer -= cputime << 12;
-       S390_lowcore.steal_clock -= cputime << 12;
-       account_user_time(tsk, cputime);
+       struct thread_info *ti;
+
+       do_account_vtime(prev, 0);
+       ti = task_thread_info(prev);
+       ti->user_timer = S390_lowcore.user_timer;
+       ti->system_timer = S390_lowcore.system_timer;
+       ti = task_thread_info(next);
+       S390_lowcore.user_timer = ti->user_timer;
+       S390_lowcore.system_timer = ti->system_timer;
+}
 
-       cputime =  S390_lowcore.system_timer >> 12;
-       S390_lowcore.system_timer -= cputime << 12;
-       S390_lowcore.steal_clock -= cputime << 12;
-       account_system_time(tsk, 0, cputime);
+void account_process_tick(struct task_struct *tsk, int user_tick)
+{
+       do_account_vtime(tsk, HARDIRQ_OFFSET);
 }
 
 /*
@@ -96,80 +111,131 @@ void account_vtime(struct task_struct *tsk)
  */
 void account_system_vtime(struct task_struct *tsk)
 {
-       cputime_t cputime;
-       __u64 timer;
+       struct thread_info *ti = task_thread_info(tsk);
+       __u64 timer, system;
 
        timer = S390_lowcore.last_update_timer;
-       asm volatile ("  STPT %0"    /* Store current cpu timer value */
-                     : "=m" (S390_lowcore.last_update_timer) );
+       S390_lowcore.last_update_timer = get_vtimer();
        S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer;
 
-       cputime =  S390_lowcore.system_timer >> 12;
-       S390_lowcore.system_timer -= cputime << 12;
-       S390_lowcore.steal_clock -= cputime << 12;
-       account_system_time(tsk, 0, cputime);
+       system = S390_lowcore.system_timer - ti->system_timer;
+       S390_lowcore.steal_timer -= system;
+       ti->system_timer = S390_lowcore.system_timer;
+       account_system_time(tsk, 0, system, system);
 }
 EXPORT_SYMBOL_GPL(account_system_vtime);
 
-static inline void set_vtimer(__u64 expires)
-{
-       __u64 timer;
-
-       asm volatile ("  STPT %0\n"  /* Store current cpu timer value */
-                     "  SPT %1"     /* Set new value immediatly afterwards */
-                     : "=m" (timer) : "m" (expires) );
-       S390_lowcore.system_timer += S390_lowcore.last_update_timer - timer;
-       S390_lowcore.last_update_timer = expires;
-
-       /* store expire time for this CPU timer */
-       __get_cpu_var(virt_cpu_timer).to_expire = expires;
-}
-
-void vtime_start_cpu_timer(void)
+void vtime_start_cpu(void)
 {
-       struct vtimer_queue *vt_list;
-
-       vt_list = &__get_cpu_var(virt_cpu_timer);
-
-       /* CPU timer interrupt is pending, don't reprogramm it */
-       if (vt_list->idle & 1LL<<63)
-               return;
+       struct s390_idle_data *idle = &__get_cpu_var(s390_idle);
+       struct vtimer_queue *vq = &__get_cpu_var(virt_cpu_timer);
+       __u64 idle_time, expires;
+
+       /* Account time spent with enabled wait psw loaded as idle time. */
+       idle_time = S390_lowcore.int_clock - idle->idle_enter;
+       account_idle_time(idle_time);
+       S390_lowcore.last_update_clock = S390_lowcore.int_clock;
+
+       /* Account system time spent going idle. */
+       S390_lowcore.system_timer += S390_lowcore.last_update_timer - vq->idle;
+       S390_lowcore.last_update_timer = S390_lowcore.async_enter_timer;
+
+       /* Restart vtime CPU timer */
+       if (vq->do_spt) {
+               /* Program old expire value but first save progress. */
+               expires = vq->idle - S390_lowcore.async_enter_timer;
+               expires += get_vtimer();
+               set_vtimer(expires);
+       } else {
+               /* Don't account the CPU timer delta while the cpu was idle. */
+               vq->elapsed -= vq->idle - S390_lowcore.async_enter_timer;
+       }
 
-       if (!list_empty(&vt_list->list))
-               set_vtimer(vt_list->idle);
+       spin_lock(&idle->lock);
+       idle->idle_time += idle_time;
+       idle->idle_enter = 0ULL;
+       idle->idle_count++;
+       spin_unlock(&idle->lock);
 }
 
-void vtime_stop_cpu_timer(void)
+void vtime_stop_cpu(void)
 {
-       struct vtimer_queue *vt_list;
-
-       vt_list = &__get_cpu_var(virt_cpu_timer);
-
-       /* nothing to do */
-       if (list_empty(&vt_list->list)) {
-               vt_list->idle = VTIMER_MAX_SLICE;
-               goto fire;
+       struct s390_idle_data *idle = &__get_cpu_var(s390_idle);
+       struct vtimer_queue *vq = &__get_cpu_var(virt_cpu_timer);
+       psw_t psw;
+
+       /* Wait for external, I/O or machine check interrupt. */
+       psw.mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_IO | PSW_MASK_EXT;
+
+       /* Check if the CPU timer needs to be reprogrammed. */
+       if (vq->do_spt) {
+               __u64 vmax = VTIMER_MAX_SLICE;
+               /*
+                * The inline assembly is equivalent to
+                *      vq->idle = get_cpu_timer();
+                *      set_cpu_timer(VTIMER_MAX_SLICE);
+                *      idle->idle_enter = get_clock();
+                *      __load_psw_mask(psw_kernel_bits | PSW_MASK_WAIT |
+                *                         PSW_MASK_IO | PSW_MASK_EXT);
+                * The difference is that the inline assembly makes sure that
+                * the last three instruction are stpt, stck and lpsw in that
+                * order. This is done to increase the precision.
+                */
+               asm volatile(
+#ifndef CONFIG_64BIT
+                       "       basr    1,0\n"
+                       "0:     ahi     1,1f-0b\n"
+                       "       st      1,4(%2)\n"
+#else /* CONFIG_64BIT */
+                       "       larl    1,1f\n"
+                       "       stg     1,8(%2)\n"
+#endif /* CONFIG_64BIT */
+                       "       stpt    0(%4)\n"
+                       "       spt     0(%5)\n"
+                       "       stck    0(%3)\n"
+#ifndef CONFIG_64BIT
+                       "       lpsw    0(%2)\n"
+#else /* CONFIG_64BIT */
+                       "       lpswe   0(%2)\n"
+#endif /* CONFIG_64BIT */
+                       "1:"
+                       : "=m" (idle->idle_enter), "=m" (vq->idle)
+                       : "a" (&psw), "a" (&idle->idle_enter),
+                         "a" (&vq->idle), "a" (&vmax), "m" (vmax), "m" (psw)
+                       : "memory", "cc", "1");
+       } else {
+               /*
+                * The inline assembly is equivalent to
+                *      vq->idle = get_cpu_timer();
+                *      idle->idle_enter = get_clock();
+                *      __load_psw_mask(psw_kernel_bits | PSW_MASK_WAIT |
+                *                         PSW_MASK_IO | PSW_MASK_EXT);
+                * The difference is that the inline assembly makes sure that
+                * the last three instruction are stpt, stck and lpsw in that
+                * order. This is done to increase the precision.
+                */
+               asm volatile(
+#ifndef CONFIG_64BIT
+                       "       basr    1,0\n"
+                       "0:     ahi     1,1f-0b\n"
+                       "       st      1,4(%2)\n"
+#else /* CONFIG_64BIT */
+                       "       larl    1,1f\n"
+                       "       stg     1,8(%2)\n"
+#endif /* CONFIG_64BIT */
+                       "       stpt    0(%4)\n"
+                       "       stck    0(%3)\n"
+#ifndef CONFIG_64BIT
+                       "       lpsw    0(%2)\n"
+#else /* CONFIG_64BIT */
+                       "       lpswe   0(%2)\n"
+#endif /* CONFIG_64BIT */
+                       "1:"
+                       : "=m" (idle->idle_enter), "=m" (vq->idle)
+                       : "a" (&psw), "a" (&idle->idle_enter),
+                         "a" (&vq->idle), "m" (psw)
+                       : "memory", "cc", "1");
        }
-
-       /* store the actual expire value */
-       asm volatile ("STPT %0" : "=m" (vt_list->idle));
-
-       /*
-        * If the CPU timer is negative we don't reprogramm
-        * it because we will get instantly an interrupt.
-        */
-       if (vt_list->idle & 1LL<<63)
-               return;
-
-       vt_list->offset += vt_list->to_expire - vt_list->idle;
-
-       /*
-        * We cannot halt the CPU timer, we just write a value that
-        * nearly never expires (only after 71 years) and re-write
-        * the stored expire value if we continue the timer
-        */
- fire:
-       set_vtimer(VTIMER_MAX_SLICE);
 }
 
 /*
@@ -195,30 +261,23 @@ static void list_add_sorted(struct vtimer_list *timer, struct list_head *head)
  */
 static void do_callbacks(struct list_head *cb_list)
 {
-       struct vtimer_queue *vt_list;
+       struct vtimer_queue *vq;
        struct vtimer_list *event, *tmp;
-       void (*fn)(unsigned long);
-       unsigned long data;
 
        if (list_empty(cb_list))
                return;
 
-       vt_list = &__get_cpu_var(virt_cpu_timer);
+       vq = &__get_cpu_var(virt_cpu_timer);
 
        list_for_each_entry_safe(event, tmp, cb_list, entry) {
-               fn = event->function;
-               data = event->data;
-               fn(data);
-
-               if (!event->interval)
-                       /* delete one shot timer */
-                       list_del_init(&event->entry);
-               else {
-                       /* move interval timer back to list */
-                       spin_lock(&vt_list->lock);
-                       list_del_init(&event->entry);
-                       list_add_sorted(event, &vt_list->list);
-                       spin_unlock(&vt_list->lock);
+               list_del_init(&event->entry);
+               (event->function)(event->data);
+               if (event->interval) {
+                       /* Recharge interval timer */
+                       event->expires = event->interval + vq->elapsed;
+                       spin_lock(&vq->lock);
+                       list_add_sorted(event, &vq->list);
+                       spin_unlock(&vq->lock);
                }
        }
 }
@@ -228,64 +287,57 @@ static void do_callbacks(struct list_head *cb_list)
  */
 static void do_cpu_timer_interrupt(__u16 error_code)
 {
-       __u64 next, delta;
-       struct vtimer_queue *vt_list;
+       struct vtimer_queue *vq;
        struct vtimer_list *event, *tmp;
-       struct list_head *ptr;
-       /* the callback queue */
-       struct list_head cb_list;
+       struct list_head cb_list;       /* the callback queue */
+       __u64 elapsed, next;
 
        INIT_LIST_HEAD(&cb_list);
-       vt_list = &__get_cpu_var(virt_cpu_timer);
+       vq = &__get_cpu_var(virt_cpu_timer);
 
        /* walk timer list, fire all expired events */
-       spin_lock(&vt_list->lock);
-
-       if (vt_list->to_expire < VTIMER_MAX_SLICE)
-               vt_list->offset += vt_list->to_expire;
-
-       list_for_each_entry_safe(event, tmp, &vt_list->list, entry) {
-               if (event->expires > vt_list->offset)
-                       /* found first unexpired event, leave */
-                       break;
-
-               /* re-charge interval timer, we have to add the offset */
-               if (event->interval)
-                       event->expires = event->interval + vt_list->offset;
-
-               /* move expired timer to the callback queue */
-               list_move_tail(&event->entry, &cb_list);
+       spin_lock(&vq->lock);
+
+       elapsed = vq->elapsed + (vq->timer - S390_lowcore.async_enter_timer);
+       BUG_ON((s64) elapsed < 0);
+       vq->elapsed = 0;
+       list_for_each_entry_safe(event, tmp, &vq->list, entry) {
+               if (event->expires < elapsed)
+                       /* move expired timer to the callback queue */
+                       list_move_tail(&event->entry, &cb_list);
+               else
+                       event->expires -= elapsed;
        }
-       spin_unlock(&vt_list->lock);
+       spin_unlock(&vq->lock);
+
+       vq->do_spt = list_empty(&cb_list);
        do_callbacks(&cb_list);
 
        /* next event is first in list */
-       spin_lock(&vt_list->lock);
-       if (!list_empty(&vt_list->list)) {
-               ptr = vt_list->list.next;
-               event = list_entry(ptr, struct vtimer_list, entry);
-               next = event->expires - vt_list->offset;
-
-               /* add the expired time from this interrupt handler
-                * and the callback functions
-                */
-               asm volatile ("STPT %0" : "=m" (delta));
-               delta = 0xffffffffffffffffLL - delta + 1;
-               vt_list->offset += delta;
-               next -= delta;
-       } else {
-               vt_list->offset = 0;
-               next = VTIMER_MAX_SLICE;
-       }
-       spin_unlock(&vt_list->lock);
-       set_vtimer(next);
+       next = VTIMER_MAX_SLICE;
+       spin_lock(&vq->lock);
+       if (!list_empty(&vq->list)) {
+               event = list_first_entry(&vq->list, struct vtimer_list, entry);
+               next = event->expires;
+       } else
+               vq->do_spt = 0;
+       spin_unlock(&vq->lock);
+       /*
+        * To improve precision add the time spent by the
+        * interrupt handler to the elapsed time.
+        * Note: CPU timer counts down and we got an interrupt,
+        *       the current content is negative
+        */
+       elapsed = S390_lowcore.async_enter_timer - get_vtimer();
+       set_vtimer(next - elapsed);
+       vq->timer = next - elapsed;
+       vq->elapsed = elapsed;
 }
 
 void init_virt_timer(struct vtimer_list *timer)
 {
        timer->function = NULL;
        INIT_LIST_HEAD(&timer->entry);
-       spin_lock_init(&timer->lock);
 }
 EXPORT_SYMBOL(init_virt_timer);
 
@@ -299,44 +351,40 @@ static inline int vtimer_pending(struct vtimer_list *timer)
  */
 static void internal_add_vtimer(struct vtimer_list *timer)
 {
+       struct vtimer_queue *vq;
        unsigned long flags;
-       __u64 done;
-       struct vtimer_list *event;
-       struct vtimer_queue *vt_list;
+       __u64 left, expires;
 
-       vt_list = &per_cpu(virt_cpu_timer, timer->cpu);
-       spin_lock_irqsave(&vt_list->lock, flags);
+       vq = &per_cpu(virt_cpu_timer, timer->cpu);
+       spin_lock_irqsave(&vq->lock, flags);
 
        BUG_ON(timer->cpu != smp_processor_id());
 
-       /* if list is empty we only have to set the timer */
-       if (list_empty(&vt_list->list)) {
-               /* reset the offset, this may happen if the last timer was
-                * just deleted by mod_virt_timer and the interrupt
-                * didn't happen until here
-                */
-               vt_list->offset = 0;
-               goto fire;
+       if (list_empty(&vq->list)) {
+               /* First timer on this cpu, just program it. */
+               list_add(&timer->entry, &vq->list);
+               set_vtimer(timer->expires);
+               vq->timer = timer->expires;
+               vq->elapsed = 0;
+       } else {
+               /* Check progress of old timers. */
+               expires = timer->expires;
+               left = get_vtimer();
+               if (likely((s64) expires < (s64) left)) {
+                       /* The new timer expires before the current timer. */
+                       set_vtimer(expires);
+                       vq->elapsed += vq->timer - left;
+                       vq->timer = expires;
+               } else {
+                       vq->elapsed += vq->timer - left;
+                       vq->timer = left;
+               }
+               /* Insert new timer into per cpu list. */
+               timer->expires += vq->elapsed;
+               list_add_sorted(timer, &vq->list);
        }
 
-       /* save progress */
-       asm volatile ("STPT %0" : "=m" (done));
-
-       /* calculate completed work */
-       done = vt_list->to_expire - done + vt_list->offset;
-       vt_list->offset = 0;
-
-       list_for_each_entry(event, &vt_list->list, entry)
-               event->expires -= done;
-
- fire:
-       list_add_sorted(timer, &vt_list->list);
-
-       /* get first element, which is the next vtimer slice */
-       event = list_entry(vt_list->list.next, struct vtimer_list, entry);
-
-       set_vtimer(event->expires);
-       spin_unlock_irqrestore(&vt_list->lock, flags);
+       spin_unlock_irqrestore(&vq->lock, flags);
        /* release CPU acquired in prepare_vtimer or mod_virt_timer() */
        put_cpu();
 }
@@ -381,14 +429,15 @@ EXPORT_SYMBOL(add_virt_timer_periodic);
  * If we change a pending timer the function must be called on the CPU
  * where the timer is running on, e.g. by smp_call_function_single()
  *
- * The original mod_timer adds the timer if it is not pending. For compatibility
- * we do the same. The timer will be added on the current CPU as a oneshot timer.
+ * The original mod_timer adds the timer if it is not pending. For
+ * compatibility we do the same. The timer will be added on the current
+ * CPU as a oneshot timer.
  *
  * returns whether it has modified a pending timer (1) or not (0)
  */
 int mod_virt_timer(struct vtimer_list *timer, __u64 expires)
 {
-       struct vtimer_queue *vt_list;
+       struct vtimer_queue *vq;
        unsigned long flags;
        int cpu;
 
@@ -404,17 +453,17 @@ int mod_virt_timer(struct vtimer_list *timer, __u64 expires)
                return 1;
 
        cpu = get_cpu();
-       vt_list = &per_cpu(virt_cpu_timer, cpu);
+       vq = &per_cpu(virt_cpu_timer, cpu);
 
        /* check if we run on the right CPU */
        BUG_ON(timer->cpu != cpu);
 
        /* disable interrupts before test if timer is pending */
-       spin_lock_irqsave(&vt_list->lock, flags);
+       spin_lock_irqsave(&vq->lock, flags);
 
        /* if timer isn't pending add it on the current CPU */
        if (!vtimer_pending(timer)) {
-               spin_unlock_irqrestore(&vt_list->lock, flags);
+               spin_unlock_irqrestore(&vq->lock, flags);
                /* we do not activate an interval timer with mod_virt_timer */
                timer->interval = 0;
                timer->expires = expires;
@@ -431,7 +480,7 @@ int mod_virt_timer(struct vtimer_list *timer, __u64 expires)
                timer->interval = expires;
 
        /* the timer can't expire anymore so we can release the lock */
-       spin_unlock_irqrestore(&vt_list->lock, flags);
+       spin_unlock_irqrestore(&vq->lock, flags);
        internal_add_vtimer(timer);
        return 1;
 }
@@ -445,25 +494,19 @@ EXPORT_SYMBOL(mod_virt_timer);
 int del_virt_timer(struct vtimer_list *timer)
 {
        unsigned long flags;
-       struct vtimer_queue *vt_list;
+       struct vtimer_queue *vq;
 
        /* check if timer is pending */
        if (!vtimer_pending(timer))
                return 0;
 
-       vt_list = &per_cpu(virt_cpu_timer, timer->cpu);
-       spin_lock_irqsave(&vt_list->lock, flags);
+       vq = &per_cpu(virt_cpu_timer, timer->cpu);
+       spin_lock_irqsave(&vq->lock, flags);
 
        /* we don't interrupt a running timer, just let it expire! */
        list_del_init(&timer->entry);
 
-       /* last timer removed */
-       if (list_empty(&vt_list->list)) {
-               vt_list->to_expire = 0;
-               vt_list->offset = 0;
-       }
-
-       spin_unlock_irqrestore(&vt_list->lock, flags);
+       spin_unlock_irqrestore(&vq->lock, flags);
        return 1;
 }
 EXPORT_SYMBOL(del_virt_timer);
@@ -473,24 +516,19 @@ EXPORT_SYMBOL(del_virt_timer);
  */
 void init_cpu_vtimer(void)
 {
-       struct vtimer_queue *vt_list;
+       struct vtimer_queue *vq;
 
        /* kick the virtual timer */
-       S390_lowcore.exit_timer = VTIMER_MAX_SLICE;
-       S390_lowcore.last_update_timer = VTIMER_MAX_SLICE;
-       asm volatile ("SPT %0" : : "m" (S390_lowcore.last_update_timer));
        asm volatile ("STCK %0" : "=m" (S390_lowcore.last_update_clock));
+       asm volatile ("STPT %0" : "=m" (S390_lowcore.last_update_timer));
+
+       /* initialize per cpu vtimer structure */
+       vq = &__get_cpu_var(virt_cpu_timer);
+       INIT_LIST_HEAD(&vq->list);
+       spin_lock_init(&vq->lock);
 
        /* enable cpu timer interrupts */
        __ctl_set_bit(0,10);
-
-       vt_list = &__get_cpu_var(virt_cpu_timer);
-       INIT_LIST_HEAD(&vt_list->list);
-       spin_lock_init(&vt_list->lock);
-       vt_list->to_expire = 0;
-       vt_list->offset = 0;
-       vt_list->idle = 0;
-
 }
 
 void __init vtime_init(void)
index 279d9cc4a007672a403dcfce9eb4d8fe5ab25114..066f0fba590e228e0467681dd8b1c4c5c22f6e36 100644 (file)
@@ -32,6 +32,7 @@
 #define parent_node(node)      ((void)(node),0)
 
 #define node_to_cpumask(node)  ((void)node, cpu_online_map)
+#define cpumask_of_node(node)  ((void)node, cpu_online_mask)
 #define node_to_first_cpu(node)        ((void)(node),0)
 
 #define pcibus_to_node(bus)    ((void)(bus), -1)
index 001c04027c82b3f774a8c4aaeed12f5eff8c8835..b8a65b64e1dfc3275c41f33d74c993ba527e5843 100644 (file)
@@ -16,8 +16,12 @@ static inline cpumask_t node_to_cpumask(int node)
 {
        return numa_cpumask_lookup_table[node];
 }
+#define cpumask_of_node(node) (&numa_cpumask_lookup_table[node])
 
-/* Returns a pointer to the cpumask of CPUs on Node 'node'. */
+/*
+ * Returns a pointer to the cpumask of CPUs on Node 'node'.
+ * Deprecated: use "const struct cpumask *mask = cpumask_of_node(node)"
+ */
 #define node_to_cpumask_ptr(v, node)           \
                cpumask_t *v = &(numa_cpumask_lookup_table[node])
 
@@ -26,9 +30,7 @@ static inline cpumask_t node_to_cpumask(int node)
 
 static inline int node_to_first_cpu(int node)
 {
-       cpumask_t tmp;
-       tmp = node_to_cpumask(node);
-       return first_cpu(tmp);
+       return cpumask_first(cpumask_of_node(node));
 }
 
 struct pci_bus;
@@ -77,10 +79,13 @@ static inline int pcibus_to_node(struct pci_bus *pbus)
 #define topology_core_id(cpu)                  (cpu_data(cpu).core_id)
 #define topology_core_siblings(cpu)            (cpu_core_map[cpu])
 #define topology_thread_siblings(cpu)          (per_cpu(cpu_sibling_map, cpu))
+#define topology_core_cpumask(cpu)             (&cpu_core_map[cpu])
+#define topology_thread_cpumask(cpu)           (&per_cpu(cpu_sibling_map, cpu))
 #define mc_capable()                           (sparc64_multi_core)
 #define smt_capable()                          (sparc64_multi_core)
 #endif /* CONFIG_SMP */
 
 #define cpu_coregroup_map(cpu)                 (cpu_core_map[cpu])
+#define cpu_coregroup_mask(cpu)                        (&cpu_core_map[cpu])
 
 #endif /* _ASM_SPARC64_TOPOLOGY_H */
index 322046cdf85f2298da755944d381537c585188be..4873f28905b082b07859d15389984b8f7dff55a8 100644 (file)
@@ -778,7 +778,7 @@ static unsigned int __init build_one_device_irq(struct of_device *op,
 out:
        nid = of_node_to_nid(dp);
        if (nid != -1) {
-               cpumask_t numa_mask = node_to_cpumask(nid);
+               cpumask_t numa_mask = *cpumask_of_node(nid);
 
                irq_set_affinity(irq, &numa_mask);
        }
index 0d0cd815e83e505b24e4b12a14f276fa37be892a..4ef282e8191208b4bc954614d8f1b9d675385177 100644 (file)
@@ -286,7 +286,7 @@ static int bringup_one_msi_queue(struct pci_pbm_info *pbm,
 
        nid = pbm->numa_node;
        if (nid != -1) {
-               cpumask_t numa_mask = node_to_cpumask(nid);
+               cpumask_t numa_mask = *cpumask_of_node(nid);
 
                irq_set_affinity(irq, &numa_mask);
        }
index d944c343acdb26ab68a9d3243fa58c95ee090868..0728def322342b8d0438cf4129893883f9daddea 100644 (file)
@@ -22,10 +22,11 @@ MODE_INCLUDE        += -I$(srctree)/$(ARCH_DIR)/include/shared/skas
 
 include $(srctree)/$(ARCH_DIR)/Makefile-skas
 
-ARCH_INCLUDE   := -I$(srctree)/$(ARCH_DIR)/include/shared
+SHARED_HEADERS := $(ARCH_DIR)/include/shared
+ARCH_INCLUDE   := -I$(srctree)/$(SHARED_HEADERS)
 ARCH_INCLUDE   += -I$(srctree)/$(ARCH_DIR)/sys-$(SUBARCH)/shared
 ifneq ($(KBUILD_SRC),)
-ARCH_INCLUDE   += -I$(ARCH_DIR)/include/shared # for two generated files
+ARCH_INCLUDE   += -I$(SHARED_HEADERS)
 endif
 KBUILD_CPPFLAGS += -I$(srctree)/$(ARCH_DIR)/sys-$(SUBARCH)
 
@@ -85,8 +86,8 @@ endef
 
 KBUILD_KCONFIG := arch/um/Kconfig.$(HEADER_ARCH)
 
-archprepare: $(ARCH_DIR)/include/shared/user_constants.h
-prepare: $(ARCH_DIR)/include/shared/kern_constants.h
+archprepare: $(SHARED_HEADERS)/user_constants.h
+archprepare: $(SHARED_HEADERS)/kern_constants.h
 
 LINK-$(CONFIG_LD_SCRIPT_STATIC) += -static
 LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib
@@ -119,17 +120,13 @@ endef
 # When cleaning we don't include .config, so we don't include
 # TT or skas makefiles and don't clean skas_ptregs.h.
 CLEAN_FILES += linux x.i gmon.out \
-       $(ARCH_DIR)/include/shared/user_constants.h \
-       $(ARCH_DIR)/include/shared/kern_constants.h
+       $(SHARED_HEADERS)/user_constants.h \
+       $(SHARED_HEADERS)/kern_constants.h
 
 archclean:
        @find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \
                -o -name '*.gcov' \) -type f -print | xargs rm -f
 
-$(objtree)/$(ARCH_DIR)/include/shared:
-       @echo '  MKDIR $@'
-       $(Q)mkdir -p $@
-
 # Generated files
 
 $(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.s: FORCE
@@ -148,11 +145,11 @@ define filechk_gen-asm-offsets
          echo ""; )
 endef
 
-$(ARCH_DIR)/include/shared/user_constants.h: $(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.s
+$(SHARED_HEADERS)/user_constants.h: $(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.s
        $(call filechk,gen-asm-offsets)
 
-$(ARCH_DIR)/include/shared/kern_constants.h: $(objtree)/$(ARCH_DIR)/include/shared
-       @echo '  SYMLINK $@'
-       $(Q)ln -sf ../../../../include/asm/asm-offsets.h $@
+$(SHARED_HEADERS)/kern_constants.h:
+       $(Q)mkdir -p $(dir $@)
+       $(Q)echo '#include "../../../../include/asm/asm-offsets.h"' >$@
 
 export SUBARCH USER_CFLAGS CFLAGS_NO_HARDENING OS HEADER_ARCH DEV_NULL_PATH
index ae5f94d6317d584c051fbcea83533431e4b635d7..753346e2cdfd64d5d472f3388014952f5d0ca4ff 100644 (file)
@@ -11,21 +11,21 @@ extern int get_signals(void);
 extern void block_signals(void);
 extern void unblock_signals(void);
 
-#define raw_local_save_flags(flags) do { typecheck(unsigned long, flags); \
+#define local_save_flags(flags) do { typecheck(unsigned long, flags); \
                                     (flags) = get_signals(); } while(0)
-#define raw_local_irq_restore(flags) do { typecheck(unsigned long, flags); \
+#define local_irq_restore(flags) do { typecheck(unsigned long, flags); \
                                      set_signals(flags); } while(0)
 
-#define raw_local_irq_save(flags) do { raw_local_save_flags(flags); \
-                                   raw_local_irq_disable(); } while(0)
+#define local_irq_save(flags) do { local_save_flags(flags); \
+                                   local_irq_disable(); } while(0)
 
-#define raw_local_irq_enable() unblock_signals()
-#define raw_local_irq_disable() block_signals()
+#define local_irq_enable() unblock_signals()
+#define local_irq_disable() block_signals()
 
 #define irqs_disabled()                 \
 ({                                      \
         unsigned long flags;            \
-        raw_local_save_flags(flags);        \
+        local_save_flags(flags);        \
         (flags == 0);                   \
 })
 
index 249d1e0824b523e0a1e51a613a86a497649cc089..862adb9bf0d49886d1f20c72f1277287306d5685 100644 (file)
@@ -586,6 +586,16 @@ config AMD_IOMMU
          your BIOS for an option to enable it or if you have an IVRS ACPI
          table.
 
+config AMD_IOMMU_STATS
+       bool "Export AMD IOMMU statistics to debugfs"
+       depends on AMD_IOMMU
+       select DEBUG_FS
+       help
+         This option enables code in the AMD IOMMU driver to collect various
+         statistics about whats happening in the driver and exports that
+         information to userspace via debugfs.
+         If unsure, say N.
+
 # need this always selected by IOMMU for the VIA workaround
 config SWIOTLB
        def_bool y if X86_64
@@ -599,6 +609,9 @@ config SWIOTLB
 config IOMMU_HELPER
        def_bool (CALGARY_IOMMU || GART_IOMMU || SWIOTLB || AMD_IOMMU)
 
+config IOMMU_API
+       def_bool (AMD_IOMMU || DMAR)
+
 config MAXSMP
        bool "Configure Maximum number of SMP Processors and NUMA Nodes"
        depends on X86_64 && SMP && DEBUG_KERNEL && EXPERIMENTAL
index 85a78575956cb0bdf473c4694f29eb7d497a154e..8078955845ae8778482f0f0662c1e2a50bae5713 100644 (file)
@@ -408,7 +408,7 @@ config X86_MINIMUM_CPU_FAMILY
 
 config X86_DEBUGCTLMSR
        def_bool y
-       depends on !(MK6 || MWINCHIPC6 || MWINCHIP3D || MCYRIXIII || M586MMX || M586TSC || M586 || M486 || M386)
+       depends on !(MK6 || MWINCHIPC6 || MWINCHIP3D || MCYRIXIII || M586MMX || M586TSC || M586 || M486 || M386) && !UML
 
 menuconfig PROCESSOR_SELECT
        bool "Supported processor vendors" if EMBEDDED
index b195f85526e35813e08e93b2553587a37896af2f..9dabd00e98055c8d21526e6f86a63deced16a98b 100644 (file)
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
 #include <asm/i387.h>
-#include <asm/ia32.h>
 #include <asm/ptrace.h>
 #include <asm/ia32_unistd.h>
 #include <asm/user32.h>
 #include <asm/sigcontext32.h>
 #include <asm/proto.h>
 #include <asm/vdso.h>
-
 #include <asm/sigframe.h>
+#include <asm/sys_ia32.h>
 
 #define DEBUG_SIG 0
 
index d21991ce606cc54dc4a3c71745049364bda26582..29cdcd02ead30524c4394a7b558cc3223ffc986c 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/shm.h>
 #include <linux/ipc.h>
 #include <linux/compat.h>
+#include <asm/sys_ia32.h>
 
 asmlinkage long sys32_ipc(u32 call, int first, int second, int third,
                          compat_uptr_t ptr, u32 fifth)
index 2e09dcd3c0a6034d46e3345efa40736e49941d13..6c0d7f6231af26e3eb3fb26821d4dbf493233fc2 100644 (file)
@@ -44,8 +44,8 @@
 #include <asm/types.h>
 #include <asm/uaccess.h>
 #include <asm/atomic.h>
-#include <asm/ia32.h>
 #include <asm/vgtod.h>
+#include <asm/sys_ia32.h>
 
 #define AA(__x)                ((unsigned long)(__x))
 
index ac302a2fa3397f3ae9a65a4553a2731706b34e18..95c8cd9d22b54401fc8de9cf734512126b34a05f 100644 (file)
 /* FIXME: move this macro to <linux/pci.h> */
 #define PCI_BUS(x) (((x) >> 8) & 0xff)
 
+/* Protection domain flags */
+#define PD_DMA_OPS_MASK                (1UL << 0) /* domain used for dma_ops */
+#define PD_DEFAULT_MASK                (1UL << 1) /* domain is a default dma_ops
+                                             domain for an IOMMU */
+
 /*
  * This structure contains generic data for  IOMMU protection domains
  * independent of their use.
  */
 struct protection_domain {
-       spinlock_t lock; /* mostly used to lock the page table*/
-       u16 id;          /* the domain id written to the device table */
-       int mode;        /* paging mode (0-6 levels) */
-       u64 *pt_root;    /* page table root pointer */
-       void *priv;      /* private data */
+       spinlock_t lock;        /* mostly used to lock the page table*/
+       u16 id;                 /* the domain id written to the device table */
+       int mode;               /* paging mode (0-6 levels) */
+       u64 *pt_root;           /* page table root pointer */
+       unsigned long flags;    /* flags to find out type of domain */
+       unsigned dev_cnt;       /* devices assigned to this domain */
+       void *priv;             /* private data */
 };
 
 /*
@@ -295,7 +302,7 @@ struct amd_iommu {
        bool int_enabled;
 
        /* if one, we need to send a completion wait command */
-       int need_sync;
+       bool need_sync;
 
        /* default dma_ops domain for that IOMMU */
        struct dma_ops_domain *default_dom;
@@ -374,7 +381,7 @@ extern struct protection_domain **amd_iommu_pd_table;
 extern unsigned long *amd_iommu_pd_alloc_bitmap;
 
 /* will be 1 if device isolation is enabled */
-extern int amd_iommu_isolate;
+extern bool amd_iommu_isolate;
 
 /*
  * If true, the addresses will be flushed on unmap time, not when
@@ -382,18 +389,6 @@ extern int amd_iommu_isolate;
  */
 extern bool amd_iommu_unmap_flush;
 
-/* takes a PCI device id and prints it out in a readable form */
-static inline void print_devid(u16 devid, int nl)
-{
-       int bus = devid >> 8;
-       int dev = devid >> 3 & 0x1f;
-       int fn  = devid & 0x07;
-
-       printk("%02x:%02x.%x", bus, dev, fn);
-       if (nl)
-               printk("\n");
-}
-
 /* takes bus and device/function and returns the device id
  * FIXME: should that be in generic PCI code? */
 static inline u16 calc_devid(u8 bus, u8 devfn)
@@ -401,4 +396,32 @@ static inline u16 calc_devid(u8 bus, u8 devfn)
        return (((u16)bus) << 8) | devfn;
 }
 
+#ifdef CONFIG_AMD_IOMMU_STATS
+
+struct __iommu_counter {
+       char *name;
+       struct dentry *dent;
+       u64 value;
+};
+
+#define DECLARE_STATS_COUNTER(nm) \
+       static struct __iommu_counter nm = {    \
+               .name = #nm,                    \
+       }
+
+#define INC_STATS_COUNTER(name)                name.value += 1
+#define ADD_STATS_COUNTER(name, x)     name.value += (x)
+#define SUB_STATS_COUNTER(name, x)     name.value -= (x)
+
+#else /* CONFIG_AMD_IOMMU_STATS */
+
+#define DECLARE_STATS_COUNTER(name)
+#define INC_STATS_COUNTER(name)
+#define ADD_STATS_COUNTER(name, x)
+#define SUB_STATS_COUNTER(name, x)
+
+static inline void amd_iommu_stats_init(void) { }
+
+#endif /* CONFIG_AMD_IOMMU_STATS */
+
 #endif /* _ASM_X86_AMD_IOMMU_TYPES_H */
index 25caa0738af5f9d99399d3c2f36405bc62d7115b..ab1d51a8855e18e80ca4cb24b9ef330e749c13dd 100644 (file)
@@ -54,7 +54,6 @@ extern int disable_apic;
 extern int is_vsmp_box(void);
 extern void xapic_wait_icr_idle(void);
 extern u32 safe_xapic_wait_icr_idle(void);
-extern u64 xapic_icr_read(void);
 extern void xapic_icr_write(u32, u32);
 extern int setup_profiling_timer(unsigned int);
 
@@ -93,7 +92,7 @@ static inline u32 native_apic_msr_read(u32 reg)
 }
 
 #ifndef CONFIG_X86_32
-extern int x2apic, x2apic_preenabled;
+extern int x2apic;
 extern void check_x2apic(void);
 extern void enable_x2apic(void);
 extern void enable_IR_x2apic(void);
index a2e545c91c359682e4583f1e4bdabd76ed91e7ed..ca5ffb2856b6810ec399a48ec98cc36d020edd69 100644 (file)
@@ -90,6 +90,7 @@ extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size);
 
 #endif /* CONFIG_X86_32 */
 
+extern int add_efi_memmap;
 extern void efi_reserve_early(void);
 extern void efi_call_phys_prelog(void);
 extern void efi_call_phys_epilog(void);
index 51ac1230294e53561e176904a5d37d05bdfa712b..bc53d5ef13868407466cd8c5eb8efe8b27e20341 100644 (file)
@@ -157,7 +157,7 @@ cpu_mask_to_apicid_cluster(const struct cpumask *cpumask)
 
        num_bits_set = cpumask_weight(cpumask);
        /* Return id to all */
-       if (num_bits_set == NR_CPUS)
+       if (num_bits_set == nr_cpu_ids)
                return 0xFF;
        /*
         * The cpus in the mask must all be on the apic cluster.  If are not
@@ -190,7 +190,7 @@ static inline unsigned int cpu_mask_to_apicid(const cpumask_t *cpumask)
 
        num_bits_set = cpus_weight(*cpumask);
        /* Return id to all */
-       if (num_bits_set == NR_CPUS)
+       if (num_bits_set == nr_cpu_ids)
                return cpu_to_logical_apicid(0);
        /*
         * The cpus in the mask must all be on the apic cluster.  If are not
@@ -218,9 +218,6 @@ static inline unsigned int cpu_mask_to_apicid(const cpumask_t *cpumask)
 static inline unsigned int cpu_mask_to_apicid_and(const struct cpumask *inmask,
                                                  const struct cpumask *andmask)
 {
-       int num_bits_set;
-       int cpus_found = 0;
-       int cpu;
        int apicid = cpu_to_logical_apicid(0);
        cpumask_var_t cpumask;
 
@@ -229,31 +226,8 @@ static inline unsigned int cpu_mask_to_apicid_and(const struct cpumask *inmask,
 
        cpumask_and(cpumask, inmask, andmask);
        cpumask_and(cpumask, cpumask, cpu_online_mask);
+       apicid = cpu_mask_to_apicid(cpumask);
 
-       num_bits_set = cpumask_weight(cpumask);
-       /* Return id to all */
-       if (num_bits_set == NR_CPUS)
-               goto exit;
-       /*
-        * The cpus in the mask must all be on the apic cluster.  If are not
-        * on the same apicid cluster return default value of TARGET_CPUS.
-        */
-       cpu = cpumask_first(cpumask);
-       apicid = cpu_to_logical_apicid(cpu);
-       while (cpus_found < num_bits_set) {
-               if (cpumask_test_cpu(cpu, cpumask)) {
-                       int new_apicid = cpu_to_logical_apicid(cpu);
-                       if (apicid_cluster(apicid) !=
-                                       apicid_cluster(new_apicid)){
-                               printk ("%s: Not a valid mask!\n", __func__);
-                               return cpu_to_logical_apicid(0);
-                       }
-                       apicid = new_apicid;
-                       cpus_found++;
-               }
-               cpu++;
-       }
-exit:
        free_cpumask_var(cpumask);
        return apicid;
 }
index 97215a458e5f4fe3ccf6ad5a0a33a041bada43a5..730843d1d2fbe5e54fd5d64d7c0873113af94bb4 100644 (file)
@@ -360,7 +360,7 @@ struct kvm_arch{
        struct list_head active_mmu_pages;
        struct list_head assigned_dev_head;
        struct list_head oos_global_pages;
-       struct dmar_domain *intel_iommu_domain;
+       struct iommu_domain *iommu_domain;
        struct kvm_pic *vpic;
        struct kvm_ioapic *vioapic;
        struct kvm_pit *vpit;
index d28a507cef3957eeccf5154d1e9b6b29103e21cc..1caf57628b9c8c750dccbf2e8d60c29a250b39c9 100644 (file)
@@ -15,7 +15,7 @@
 #define SHARED_SWITCHER_PAGES \
        DIV_ROUND_UP(end_switcher_text - start_switcher_text, PAGE_SIZE)
 /* Pages for switcher itself, then two pages per cpu */
-#define TOTAL_SWITCHER_PAGES (SHARED_SWITCHER_PAGES + 2 * NR_CPUS)
+#define TOTAL_SWITCHER_PAGES (SHARED_SWITCHER_PAGES + 2 * nr_cpu_ids)
 
 /* We map at -4M for ease of mapping into the guest (one PTE page). */
 #define SWITCHER_ADDR 0xFFC00000
index 91885c28f66b3ae909b402886682202b5280b6a1..62d14ce3cd0050f2fc3e36beb0ffbe98cc08dcb5 100644 (file)
@@ -6,13 +6,13 @@
 #include <asm/mpspec_def.h>
 
 extern int apic_version[MAX_APICS];
+extern int pic_mode;
 
 #ifdef CONFIG_X86_32
 #include <mach_mpspec.h>
 
 extern unsigned int def_to_bigsmp;
 extern u8 apicid_2_node[];
-extern int pic_mode;
 
 #ifdef CONFIG_X86_NUMAQ
 extern int mp_bus_id_to_node[MAX_MP_BUSSES];
index c80f00d299656278baedc68be829650ec1b5c53c..bf37bc49bd8e4f11fc43acdde6dfee52f9b8c43b 100644 (file)
@@ -63,8 +63,8 @@ static inline physid_mask_t ioapic_phys_id_map(physid_mask_t phys_map)
 extern u8 cpu_2_logical_apicid[];
 static inline int cpu_to_logical_apicid(int cpu)
 {
-       if (cpu >= NR_CPUS)
-              return BAD_APICID;
+       if (cpu >= nr_cpu_ids)
+               return BAD_APICID;
        return (int)cpu_2_logical_apicid[cpu];
 }
 
index 66834c41c0493eccf1b117b1565443c10ec706b6..a977de23cb4d83320e5255de21ffc073a0859403 100644 (file)
@@ -102,9 +102,9 @@ extern void pci_iommu_alloc(void);
 
 #ifdef CONFIG_NUMA
 /* Returns the node based on pci bus */
-static inline int __pcibus_to_node(struct pci_bus *bus)
+static inline int __pcibus_to_node(const struct pci_bus *bus)
 {
-       struct pci_sysdata *sd = bus->sysdata;
+       const struct pci_sysdata *sd = bus->sysdata;
 
        return sd->node;
 }
@@ -113,6 +113,12 @@ static inline cpumask_t __pcibus_to_cpumask(struct pci_bus *bus)
 {
        return node_to_cpumask(__pcibus_to_node(bus));
 }
+
+static inline const struct cpumask *
+cpumask_of_pcibus(const struct pci_bus *bus)
+{
+       return cpumask_of_node(__pcibus_to_node(bus));
+}
 #endif
 
 #endif /* _ASM_X86_PCI_H */
similarity index 88%
rename from arch/x86/pci/pci.h
rename to arch/x86/include/asm/pci_x86.h
index 1959018aac025ea3a38048973e6cc7a107396684..e60fd3e14bdf2c720f3c890f945a80e1828d087b 100644 (file)
@@ -57,7 +57,8 @@ extern struct pci_ops pci_root_ops;
 struct irq_info {
        u8 bus, devfn;                  /* Bus, device and function */
        struct {
-               u8 link;                /* IRQ line ID, chipset dependent, 0=not routed */
+               u8 link;                /* IRQ line ID, chipset dependent,
+                                          0 = not routed */
                u16 bitmap;             /* Available IRQs */
        } __attribute__((packed)) irq[4];
        u8 slot;                        /* Slot number, 0=onboard */
@@ -69,11 +70,13 @@ struct irq_routing_table {
        u16 version;                    /* PIRQ_VERSION */
        u16 size;                       /* Table size in bytes */
        u8 rtr_bus, rtr_devfn;          /* Where the interrupt router lies */
-       u16 exclusive_irqs;             /* IRQs devoted exclusively to PCI usage */
-       u16 rtr_vendor, rtr_device;     /* Vendor and device ID of interrupt router */
+       u16 exclusive_irqs;             /* IRQs devoted exclusively to
+                                          PCI usage */
+       u16 rtr_vendor, rtr_device;     /* Vendor and device ID of
+                                          interrupt router */
        u32 miniport_data;              /* Crap */
        u8 rfu[11];
-       u8 checksum;                    /* Modulo 256 checksum must give zero */
+       u8 checksum;                    /* Modulo 256 checksum must give 0 */
        struct irq_info slots[0];
 } __attribute__((packed));
 
@@ -148,15 +151,15 @@ static inline unsigned int mmio_config_readl(void __iomem *pos)
 
 static inline void mmio_config_writeb(void __iomem *pos, u8 val)
 {
-       asm volatile("movb %%al,(%1)" :: "a" (val), "r" (pos) : "memory");
+       asm volatile("movb %%al,(%1)" : : "a" (val), "r" (pos) : "memory");
 }
 
 static inline void mmio_config_writew(void __iomem *pos, u16 val)
 {
-       asm volatile("movw %%ax,(%1)" :: "a" (val), "r" (pos) : "memory");
+       asm volatile("movw %%ax,(%1)" : : "a" (val), "r" (pos) : "memory");
 }
 
 static inline void mmio_config_writel(void __iomem *pos, u32 val)
 {
-       asm volatile("movl %%eax,(%1)" :: "a" (val), "r" (pos) : "memory");
+       asm volatile("movl %%eax,(%1)" : : "a" (val), "r" (pos) : "memory");
 }
index 99327d1be49f0bd0fed4ecd5ca189af6bde63188..4bb5fb34f030256fe4eb6ed875defea34c89bf32 100644 (file)
@@ -52,7 +52,7 @@ static inline void init_apic_ldr(void)
        int i;
 
        /* Create logical APIC IDs by counting CPUs already in cluster. */
-       for (count = 0, i = NR_CPUS; --i >= 0; ) {
+       for (count = 0, i = nr_cpu_ids; --i >= 0; ) {
                lid = cpu_2_logical_apicid[i];
                if (lid != BAD_APICID && apicid_cluster(lid) == my_cluster)
                        ++count;
@@ -97,8 +97,8 @@ static inline int apicid_to_node(int logical_apicid)
 static inline int cpu_to_logical_apicid(int cpu)
 {
 #ifdef CONFIG_SMP
-       if (cpu >= NR_CPUS)
-              return BAD_APICID;
+       if (cpu >= nr_cpu_ids)
+               return BAD_APICID;
        return (int)cpu_2_logical_apicid[cpu];
 #else
        return logical_smp_processor_id();
@@ -107,7 +107,7 @@ static inline int cpu_to_logical_apicid(int cpu)
 
 static inline int cpu_present_to_apicid(int mps_cpu)
 {
-       if (mps_cpu < NR_CPUS)
+       if (mps_cpu < nr_cpu_ids)
                return (int)per_cpu(x86_bios_cpu_apicid, mps_cpu);
        else
                return BAD_APICID;
@@ -146,7 +146,7 @@ static inline unsigned int cpu_mask_to_apicid(const cpumask_t *cpumask)
 
        num_bits_set = cpus_weight(*cpumask);
        /* Return id to all */
-       if (num_bits_set == NR_CPUS)
+       if (num_bits_set >= nr_cpu_ids)
                return (int) 0xFF;
        /*
         * The cpus in the mask must all be on the apic cluster.  If are not
@@ -173,42 +173,16 @@ static inline unsigned int cpu_mask_to_apicid(const cpumask_t *cpumask)
 static inline unsigned int cpu_mask_to_apicid_and(const struct cpumask *inmask,
                                                  const struct cpumask *andmask)
 {
-       int num_bits_set;
-       int cpus_found = 0;
-       int cpu;
-       int apicid = 0xFF;
+       int apicid = cpu_to_logical_apicid(0);
        cpumask_var_t cpumask;
 
        if (!alloc_cpumask_var(&cpumask, GFP_ATOMIC))
-               return (int) 0xFF;
+               return apicid;
 
        cpumask_and(cpumask, inmask, andmask);
        cpumask_and(cpumask, cpumask, cpu_online_mask);
+       apicid = cpu_mask_to_apicid(cpumask);
 
-       num_bits_set = cpumask_weight(cpumask);
-       /* Return id to all */
-       if (num_bits_set == nr_cpu_ids)
-               goto exit;
-       /*
-        * The cpus in the mask must all be on the apic cluster.  If are not
-        * on the same apicid cluster return default value of TARGET_CPUS.
-        */
-       cpu = cpumask_first(cpumask);
-       apicid = cpu_to_logical_apicid(cpu);
-       while (cpus_found < num_bits_set) {
-               if (cpumask_test_cpu(cpu, cpumask)) {
-                       int new_apicid = cpu_to_logical_apicid(cpu);
-                       if (apicid_cluster(apicid) !=
-                                       apicid_cluster(new_apicid)){
-                               printk ("%s: Not a valid mask!\n", __func__);
-                               return 0xFF;
-                       }
-                       apicid = apicid | new_apicid;
-                       cpus_found++;
-               }
-               cpu++;
-       }
-exit:
        free_cpumask_var(cpumask);
        return apicid;
 }
diff --git a/arch/x86/include/asm/sys_ia32.h b/arch/x86/include/asm/sys_ia32.h
new file mode 100644 (file)
index 0000000..ffb08be
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * sys_ia32.h - Linux ia32 syscall interfaces
+ *
+ * Copyright (c) 2008 Jaswinder Singh Rajput
+ *
+ * This file is released under the GPLv2.
+ * See the file COPYING for more details.
+ */
+
+#ifndef _ASM_X86_SYS_IA32_H
+#define _ASM_X86_SYS_IA32_H
+
+#include <linux/compiler.h>
+#include <linux/linkage.h>
+#include <linux/types.h>
+#include <linux/signal.h>
+#include <asm/compat.h>
+#include <asm/ia32.h>
+
+/* ia32/sys_ia32.c */
+asmlinkage long sys32_truncate64(char __user *, unsigned long, unsigned long);
+asmlinkage long sys32_ftruncate64(unsigned int, unsigned long, unsigned long);
+
+asmlinkage long sys32_stat64(char __user *, struct stat64 __user *);
+asmlinkage long sys32_lstat64(char __user *, struct stat64 __user *);
+asmlinkage long sys32_fstat64(unsigned int, struct stat64 __user *);
+asmlinkage long sys32_fstatat(unsigned int, char __user *,
+                             struct stat64 __user *, int);
+struct mmap_arg_struct;
+asmlinkage long sys32_mmap(struct mmap_arg_struct __user *);
+asmlinkage long sys32_mprotect(unsigned long, size_t, unsigned long);
+
+asmlinkage long sys32_pipe(int __user *);
+struct sigaction32;
+struct old_sigaction32;
+asmlinkage long sys32_rt_sigaction(int, struct sigaction32 __user *,
+                                  struct sigaction32 __user *, unsigned int);
+asmlinkage long sys32_sigaction(int, struct old_sigaction32 __user *,
+                               struct old_sigaction32 __user *);
+asmlinkage long sys32_rt_sigprocmask(int, compat_sigset_t __user *,
+                                    compat_sigset_t __user *, unsigned int);
+asmlinkage long sys32_alarm(unsigned int);
+
+struct sel_arg_struct;
+asmlinkage long sys32_old_select(struct sel_arg_struct __user *);
+asmlinkage long sys32_waitpid(compat_pid_t, unsigned int *, int);
+asmlinkage long sys32_sysfs(int, u32, u32);
+
+asmlinkage long sys32_sched_rr_get_interval(compat_pid_t,
+                                           struct compat_timespec __user *);
+asmlinkage long sys32_rt_sigpending(compat_sigset_t __user *, compat_size_t);
+asmlinkage long sys32_rt_sigqueueinfo(int, int, compat_siginfo_t __user *);
+
+#ifdef CONFIG_SYSCTL_SYSCALL
+struct sysctl_ia32;
+asmlinkage long sys32_sysctl(struct sysctl_ia32 __user *);
+#endif
+
+asmlinkage long sys32_pread(unsigned int, char __user *, u32, u32, u32);
+asmlinkage long sys32_pwrite(unsigned int, char __user *, u32, u32, u32);
+
+asmlinkage long sys32_personality(unsigned long);
+asmlinkage long sys32_sendfile(int, int, compat_off_t __user *, s32);
+
+asmlinkage long sys32_mmap2(unsigned long, unsigned long, unsigned long,
+                           unsigned long, unsigned long, unsigned long);
+
+struct oldold_utsname;
+struct old_utsname;
+asmlinkage long sys32_olduname(struct oldold_utsname __user *);
+long sys32_uname(struct old_utsname __user *);
+
+long sys32_ustat(unsigned, struct ustat32 __user *);
+
+asmlinkage long sys32_execve(char __user *, compat_uptr_t __user *,
+                            compat_uptr_t __user *, struct pt_regs *);
+asmlinkage long sys32_clone(unsigned int, unsigned int, struct pt_regs *);
+
+long sys32_lseek(unsigned int, int, unsigned int);
+long sys32_kill(int, int);
+long sys32_fadvise64_64(int, __u32, __u32, __u32, __u32, int);
+long sys32_vm86_warning(void);
+long sys32_lookup_dcookie(u32, u32, char __user *, size_t);
+
+asmlinkage ssize_t sys32_readahead(int, unsigned, unsigned, size_t);
+asmlinkage long sys32_sync_file_range(int, unsigned, unsigned,
+                                     unsigned, unsigned, int);
+asmlinkage long sys32_fadvise64(int, unsigned, unsigned, size_t, int);
+asmlinkage long sys32_fallocate(int, int, unsigned,
+                               unsigned, unsigned, unsigned);
+
+/* ia32/ia32_signal.c */
+asmlinkage long sys32_sigsuspend(int, int, old_sigset_t);
+asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *,
+                                 stack_ia32_t __user *, struct pt_regs *);
+asmlinkage long sys32_sigreturn(struct pt_regs *);
+asmlinkage long sys32_rt_sigreturn(struct pt_regs *);
+
+/* ia32/ipc32.c */
+asmlinkage long sys32_ipc(u32, int, int, int, compat_uptr_t, u32);
+#endif /* _ASM_X86_SYS_IA32_H */
index 79e31e9dcdda9f924d17489dc1e0b134995c764b..4e2f2e0aab27b277eaff75a285b60d495cd2e1db 100644 (file)
@@ -61,13 +61,19 @@ static inline int cpu_to_node(int cpu)
  *
  * Side note: this function creates the returned cpumask on the stack
  * so with a high NR_CPUS count, excessive stack space is used.  The
- * node_to_cpumask_ptr function should be used whenever possible.
+ * cpumask_of_node function should be used whenever possible.
  */
 static inline cpumask_t node_to_cpumask(int node)
 {
        return node_to_cpumask_map[node];
 }
 
+/* Returns a bitmask of CPUs on Node 'node'. */
+static inline const struct cpumask *cpumask_of_node(int node)
+{
+       return &node_to_cpumask_map[node];
+}
+
 #else /* CONFIG_X86_64 */
 
 /* Mappings between node number and cpus on that node. */
@@ -82,7 +88,7 @@ DECLARE_EARLY_PER_CPU(int, x86_cpu_to_node_map);
 #ifdef CONFIG_DEBUG_PER_CPU_MAPS
 extern int cpu_to_node(int cpu);
 extern int early_cpu_to_node(int cpu);
-extern const cpumask_t *_node_to_cpumask_ptr(int node);
+extern const cpumask_t *cpumask_of_node(int node);
 extern cpumask_t node_to_cpumask(int node);
 
 #else  /* !CONFIG_DEBUG_PER_CPU_MAPS */
@@ -103,7 +109,7 @@ static inline int early_cpu_to_node(int cpu)
 }
 
 /* Returns a pointer to the cpumask of CPUs on Node 'node'. */
-static inline const cpumask_t *_node_to_cpumask_ptr(int node)
+static inline const cpumask_t *cpumask_of_node(int node)
 {
        return &node_to_cpumask_map[node];
 }
@@ -116,12 +122,15 @@ static inline cpumask_t node_to_cpumask(int node)
 
 #endif /* !CONFIG_DEBUG_PER_CPU_MAPS */
 
-/* Replace default node_to_cpumask_ptr with optimized version */
+/*
+ * Replace default node_to_cpumask_ptr with optimized version
+ * Deprecated: use "const struct cpumask *mask = cpumask_of_node(node)"
+ */
 #define node_to_cpumask_ptr(v, node)           \
-               const cpumask_t *v = _node_to_cpumask_ptr(node)
+               const cpumask_t *v = cpumask_of_node(node)
 
 #define node_to_cpumask_ptr_next(v, node)      \
-                          v = _node_to_cpumask_ptr(node)
+                          v = cpumask_of_node(node)
 
 #endif /* CONFIG_X86_64 */
 
@@ -187,7 +196,7 @@ extern int __node_distance(int, int);
 #define        cpu_to_node(cpu)        0
 #define        early_cpu_to_node(cpu)  0
 
-static inline const cpumask_t *_node_to_cpumask_ptr(int node)
+static inline const cpumask_t *cpumask_of_node(int node)
 {
        return &cpu_online_map;
 }
@@ -200,12 +209,15 @@ static inline int node_to_first_cpu(int node)
        return first_cpu(cpu_online_map);
 }
 
-/* Replace default node_to_cpumask_ptr with optimized version */
+/*
+ * Replace default node_to_cpumask_ptr with optimized version
+ * Deprecated: use "const struct cpumask *mask = cpumask_of_node(node)"
+ */
 #define node_to_cpumask_ptr(v, node)           \
-               const cpumask_t *v = _node_to_cpumask_ptr(node)
+               const cpumask_t *v = cpumask_of_node(node)
 
 #define node_to_cpumask_ptr_next(v, node)      \
-                          v = _node_to_cpumask_ptr(node)
+                          v = cpumask_of_node(node)
 #endif
 
 #include <asm-generic/topology.h>
@@ -214,12 +226,12 @@ static inline int node_to_first_cpu(int node)
 /* Returns the number of the first CPU on Node 'node'. */
 static inline int node_to_first_cpu(int node)
 {
-       node_to_cpumask_ptr(mask, node);
-       return first_cpu(*mask);
+       return cpumask_first(cpumask_of_node(node));
 }
 #endif
 
 extern cpumask_t cpu_coregroup_map(int cpu);
+extern const struct cpumask *cpu_coregroup_mask(int cpu);
 
 #ifdef ENABLE_TOPO_DEFINES
 #define topology_physical_package_id(cpu)      (cpu_data(cpu).phys_proc_id)
index e2363253bbbf21431467516d99404c64eaeaec34..50423c7b56b2eed9ddce519fac35c0a478dd5f81 100644 (file)
@@ -133,61 +133,61 @@ struct bau_msg_payload {
  * see table 4.2.3.0.1 in broacast_assist spec.
  */
 struct bau_msg_header {
-       int dest_subnodeid:6;   /* must be zero */
+       unsigned int dest_subnodeid:6;  /* must be zero */
        /* bits 5:0 */
-       int base_dest_nodeid:15; /* nasid>>1 (pnode) of first bit in node_map */
-       /* bits 20:6 */
-       int command:8;          /* message type */
+       unsigned int base_dest_nodeid:15; /* nasid>>1 (pnode) of */
+       /* bits 20:6 */                   /* first bit in node_map */
+       unsigned int command:8; /* message type */
        /* bits 28:21 */
                                /* 0x38: SN3net EndPoint Message */
-       int rsvd_1:3;           /* must be zero */
+       unsigned int rsvd_1:3;  /* must be zero */
        /* bits 31:29 */
                                /* int will align on 32 bits */
-       int rsvd_2:9;           /* must be zero */
+       unsigned int rsvd_2:9;  /* must be zero */
        /* bits 40:32 */
                                /* Suppl_A is 56-41 */
-       int payload_2a:8;       /* becomes byte 16 of msg */
+       unsigned int payload_2a:8;/* becomes byte 16 of msg */
        /* bits 48:41 */        /* not currently using */
-       int payload_2b:8;       /* becomes byte 17 of msg */
+       unsigned int payload_2b:8;/* becomes byte 17 of msg */
        /* bits 56:49 */        /* not currently using */
                                /* Address field (96:57) is never used as an
                                   address (these are address bits 42:3) */
-       int rsvd_3:1;           /* must be zero */
+       unsigned int rsvd_3:1;  /* must be zero */
        /* bit 57 */
                                /* address bits 27:4 are payload */
                                /* these 24 bits become bytes 12-14 of msg */
-       int replied_to:1;       /* sent as 0 by the source to byte 12 */
+       unsigned int replied_to:1;/* sent as 0 by the source to byte 12 */
        /* bit 58 */
 
-       int payload_1a:5;       /* not currently used */
+       unsigned int payload_1a:5;/* not currently used */
        /* bits 63:59 */
-       int payload_1b:8;       /* not currently used */
+       unsigned int payload_1b:8;/* not currently used */
        /* bits 71:64 */
-       int payload_1c:8;       /* not currently used */
+       unsigned int payload_1c:8;/* not currently used */
        /* bits 79:72 */
-       int payload_1d:2;       /* not currently used */
+       unsigned int payload_1d:2;/* not currently used */
        /* bits 81:80 */
 
-       int rsvd_4:7;           /* must be zero */
+       unsigned int rsvd_4:7;  /* must be zero */
        /* bits 88:82 */
-       int sw_ack_flag:1;      /* software acknowledge flag */
+       unsigned int sw_ack_flag:1;/* software acknowledge flag */
        /* bit 89 */
                                /* INTD trasactions at destination are to
                                   wait for software acknowledge */
-       int rsvd_5:6;           /* must be zero */
+       unsigned int rsvd_5:6;  /* must be zero */
        /* bits 95:90 */
-       int rsvd_6:5;           /* must be zero */
+       unsigned int rsvd_6:5;  /* must be zero */
        /* bits 100:96 */
-       int int_both:1;         /* if 1, interrupt both sockets on the blade */
+       unsigned int int_both:1;/* if 1, interrupt both sockets on the blade */
        /* bit 101*/
-       int fairness:3;         /* usually zero */
+       unsigned int fairness:3;/* usually zero */
        /* bits 104:102 */
-       int multilevel:1;       /* multi-level multicast format */
+       unsigned int multilevel:1;      /* multi-level multicast format */
        /* bit 105 */
                                /* 0 for TLB: endpoint multi-unicast messages */
-       int chaining:1;         /* next descriptor is part of this activation*/
+       unsigned int chaining:1;/* next descriptor is part of this activation*/
        /* bit 106 */
-       int rsvd_7:21;          /* must be zero */
+       unsigned int rsvd_7:21; /* must be zero */
        /* bits 127:107 */
 };
 
index 65d0b72777ea099a99ced450bec404220af6e2e2..29dc0c89d4afc076654a5f62c1056c219944f156 100644 (file)
@@ -538,9 +538,10 @@ static int __cpuinit _acpi_map_lsapic(acpi_handle handle, int *pcpu)
        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
        union acpi_object *obj;
        struct acpi_madt_local_apic *lapic;
-       cpumask_t tmp_map, new_map;
+       cpumask_var_t tmp_map, new_map;
        u8 physid;
        int cpu;
+       int retval = -ENOMEM;
 
        if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))
                return -EINVAL;
@@ -569,23 +570,37 @@ static int __cpuinit _acpi_map_lsapic(acpi_handle handle, int *pcpu)
        buffer.length = ACPI_ALLOCATE_BUFFER;
        buffer.pointer = NULL;
 
-       tmp_map = cpu_present_map;
+       if (!alloc_cpumask_var(&tmp_map, GFP_KERNEL))
+               goto out;
+
+       if (!alloc_cpumask_var(&new_map, GFP_KERNEL))
+               goto free_tmp_map;
+
+       cpumask_copy(tmp_map, cpu_present_mask);
        acpi_register_lapic(physid, lapic->lapic_flags & ACPI_MADT_ENABLED);
 
        /*
         * If mp_register_lapic successfully generates a new logical cpu
         * number, then the following will get us exactly what was mapped
         */
-       cpus_andnot(new_map, cpu_present_map, tmp_map);
-       if (cpus_empty(new_map)) {
+       cpumask_andnot(new_map, cpu_present_mask, tmp_map);
+       if (cpumask_empty(new_map)) {
                printk ("Unable to map lapic to logical cpu number\n");
-               return -EINVAL;
+               retval = -EINVAL;
+               goto free_new_map;
        }
 
-       cpu = first_cpu(new_map);
+       cpu = cpumask_first(new_map);
 
        *pcpu = cpu;
-       return 0;
+       retval = 0;
+
+free_new_map:
+       free_cpumask_var(new_map);
+free_tmp_map:
+       free_cpumask_var(tmp_map);
+out:
+       return retval;
 }
 
 /* wrapper to silence section mismatch warning */
@@ -598,7 +613,7 @@ EXPORT_SYMBOL(acpi_map_lsapic);
 int acpi_unmap_lsapic(int cpu)
 {
        per_cpu(x86_cpu_to_apicid, cpu) = -1;
-       cpu_clear(cpu, cpu_present_map);
+       set_cpu_present(cpu, false);
        num_processors--;
 
        return (0);
index 2e2da717b350bbd30cba12cfee11d06b12f6e1b8..5113c080f0c442093db228b759946766f59afb06 100644 (file)
 #include <linux/pci.h>
 #include <linux/gfp.h>
 #include <linux/bitops.h>
+#include <linux/debugfs.h>
 #include <linux/scatterlist.h>
 #include <linux/iommu-helper.h>
+#ifdef CONFIG_IOMMU_API
+#include <linux/iommu.h>
+#endif
 #include <asm/proto.h>
 #include <asm/iommu.h>
 #include <asm/gart.h>
@@ -38,6 +42,10 @@ static DEFINE_RWLOCK(amd_iommu_devtable_lock);
 static LIST_HEAD(iommu_pd_list);
 static DEFINE_SPINLOCK(iommu_pd_list_lock);
 
+#ifdef CONFIG_IOMMU_API
+static struct iommu_ops amd_iommu_ops;
+#endif
+
 /*
  * general struct to manage commands send to an IOMMU
  */
@@ -47,6 +55,68 @@ struct iommu_cmd {
 
 static int dma_ops_unity_map(struct dma_ops_domain *dma_dom,
                             struct unity_map_entry *e);
+static struct dma_ops_domain *find_protection_domain(u16 devid);
+
+
+#ifdef CONFIG_AMD_IOMMU_STATS
+
+/*
+ * Initialization code for statistics collection
+ */
+
+DECLARE_STATS_COUNTER(compl_wait);
+DECLARE_STATS_COUNTER(cnt_map_single);
+DECLARE_STATS_COUNTER(cnt_unmap_single);
+DECLARE_STATS_COUNTER(cnt_map_sg);
+DECLARE_STATS_COUNTER(cnt_unmap_sg);
+DECLARE_STATS_COUNTER(cnt_alloc_coherent);
+DECLARE_STATS_COUNTER(cnt_free_coherent);
+DECLARE_STATS_COUNTER(cross_page);
+DECLARE_STATS_COUNTER(domain_flush_single);
+DECLARE_STATS_COUNTER(domain_flush_all);
+DECLARE_STATS_COUNTER(alloced_io_mem);
+DECLARE_STATS_COUNTER(total_map_requests);
+
+static struct dentry *stats_dir;
+static struct dentry *de_isolate;
+static struct dentry *de_fflush;
+
+static void amd_iommu_stats_add(struct __iommu_counter *cnt)
+{
+       if (stats_dir == NULL)
+               return;
+
+       cnt->dent = debugfs_create_u64(cnt->name, 0444, stats_dir,
+                                      &cnt->value);
+}
+
+static void amd_iommu_stats_init(void)
+{
+       stats_dir = debugfs_create_dir("amd-iommu", NULL);
+       if (stats_dir == NULL)
+               return;
+
+       de_isolate = debugfs_create_bool("isolation", 0444, stats_dir,
+                                        (u32 *)&amd_iommu_isolate);
+
+       de_fflush  = debugfs_create_bool("fullflush", 0444, stats_dir,
+                                        (u32 *)&amd_iommu_unmap_flush);
+
+       amd_iommu_stats_add(&compl_wait);
+       amd_iommu_stats_add(&cnt_map_single);
+       amd_iommu_stats_add(&cnt_unmap_single);
+       amd_iommu_stats_add(&cnt_map_sg);
+       amd_iommu_stats_add(&cnt_unmap_sg);
+       amd_iommu_stats_add(&cnt_alloc_coherent);
+       amd_iommu_stats_add(&cnt_free_coherent);
+       amd_iommu_stats_add(&cross_page);
+       amd_iommu_stats_add(&domain_flush_single);
+       amd_iommu_stats_add(&domain_flush_all);
+       amd_iommu_stats_add(&alloced_io_mem);
+       amd_iommu_stats_add(&total_map_requests);
+}
+
+#endif
 
 /* returns !0 if the IOMMU is caching non-present entries in its TLB */
 static int iommu_has_npcache(struct amd_iommu *iommu)
@@ -189,12 +259,54 @@ static int iommu_queue_command(struct amd_iommu *iommu, struct iommu_cmd *cmd)
        spin_lock_irqsave(&iommu->lock, flags);
        ret = __iommu_queue_command(iommu, cmd);
        if (!ret)
-               iommu->need_sync = 1;
+               iommu->need_sync = true;
        spin_unlock_irqrestore(&iommu->lock, flags);
 
        return ret;
 }
 
+/*
+ * This function waits until an IOMMU has completed a completion
+ * wait command
+ */
+static void __iommu_wait_for_completion(struct amd_iommu *iommu)
+{
+       int ready = 0;
+       unsigned status = 0;
+       unsigned long i = 0;
+
+       INC_STATS_COUNTER(compl_wait);
+
+       while (!ready && (i < EXIT_LOOP_COUNT)) {
+               ++i;
+               /* wait for the bit to become one */
+               status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET);
+               ready = status & MMIO_STATUS_COM_WAIT_INT_MASK;
+       }
+
+       /* set bit back to zero */
+       status &= ~MMIO_STATUS_COM_WAIT_INT_MASK;
+       writel(status, iommu->mmio_base + MMIO_STATUS_OFFSET);
+
+       if (unlikely(i == EXIT_LOOP_COUNT))
+               panic("AMD IOMMU: Completion wait loop failed\n");
+}
+
+/*
+ * This function queues a completion wait command into the command
+ * buffer of an IOMMU
+ */
+static int __iommu_completion_wait(struct amd_iommu *iommu)
+{
+       struct iommu_cmd cmd;
+
+        memset(&cmd, 0, sizeof(cmd));
+        cmd.data[0] = CMD_COMPL_WAIT_INT_MASK;
+        CMD_SET_TYPE(&cmd, CMD_COMPL_WAIT);
+
+        return __iommu_queue_command(iommu, &cmd);
+}
+
 /*
  * This function is called whenever we need to ensure that the IOMMU has
  * completed execution of all commands we sent. It sends a
@@ -204,40 +316,22 @@ static int iommu_queue_command(struct amd_iommu *iommu, struct iommu_cmd *cmd)
  */
 static int iommu_completion_wait(struct amd_iommu *iommu)
 {
-       int ret = 0, ready = 0;
-       unsigned status = 0;
-       struct iommu_cmd cmd;
-       unsigned long flags, i = 0;
-
-       memset(&cmd, 0, sizeof(cmd));
-       cmd.data[0] = CMD_COMPL_WAIT_INT_MASK;
-       CMD_SET_TYPE(&cmd, CMD_COMPL_WAIT);
+       int ret = 0;
+       unsigned long flags;
 
        spin_lock_irqsave(&iommu->lock, flags);
 
        if (!iommu->need_sync)
                goto out;
 
-       iommu->need_sync = 0;
+       ret = __iommu_completion_wait(iommu);
 
-       ret = __iommu_queue_command(iommu, &cmd);
+       iommu->need_sync = false;
 
        if (ret)
                goto out;
 
-       while (!ready && (i < EXIT_LOOP_COUNT)) {
-               ++i;
-               /* wait for the bit to become one */
-               status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET);
-               ready = status & MMIO_STATUS_COM_WAIT_INT_MASK;
-       }
-
-       /* set bit back to zero */
-       status &= ~MMIO_STATUS_COM_WAIT_INT_MASK;
-       writel(status, iommu->mmio_base + MMIO_STATUS_OFFSET);
-
-       if (unlikely(i == EXIT_LOOP_COUNT))
-               panic("AMD IOMMU: Completion wait loop failed\n");
+       __iommu_wait_for_completion(iommu);
 
 out:
        spin_unlock_irqrestore(&iommu->lock, flags);
@@ -264,6 +358,21 @@ static int iommu_queue_inv_dev_entry(struct amd_iommu *iommu, u16 devid)
        return ret;
 }
 
+static void __iommu_build_inv_iommu_pages(struct iommu_cmd *cmd, u64 address,
+                                         u16 domid, int pde, int s)
+{
+       memset(cmd, 0, sizeof(*cmd));
+       address &= PAGE_MASK;
+       CMD_SET_TYPE(cmd, CMD_INV_IOMMU_PAGES);
+       cmd->data[1] |= domid;
+       cmd->data[2] = lower_32_bits(address);
+       cmd->data[3] = upper_32_bits(address);
+       if (s) /* size bit - we flush more than one 4kb page */
+               cmd->data[2] |= CMD_INV_IOMMU_PAGES_SIZE_MASK;
+       if (pde) /* PDE bit - we wan't flush everything not only the PTEs */
+               cmd->data[2] |= CMD_INV_IOMMU_PAGES_PDE_MASK;
+}
+
 /*
  * Generic command send function for invalidaing TLB entries
  */
@@ -273,16 +382,7 @@ static int iommu_queue_inv_iommu_pages(struct amd_iommu *iommu,
        struct iommu_cmd cmd;
        int ret;
 
-       memset(&cmd, 0, sizeof(cmd));
-       address &= PAGE_MASK;
-       CMD_SET_TYPE(&cmd, CMD_INV_IOMMU_PAGES);
-       cmd.data[1] |= domid;
-       cmd.data[2] = lower_32_bits(address);
-       cmd.data[3] = upper_32_bits(address);
-       if (s) /* size bit - we flush more than one 4kb page */
-               cmd.data[2] |= CMD_INV_IOMMU_PAGES_SIZE_MASK;
-       if (pde) /* PDE bit - we wan't flush everything not only the PTEs */
-               cmd.data[2] |= CMD_INV_IOMMU_PAGES_PDE_MASK;
+       __iommu_build_inv_iommu_pages(&cmd, address, domid, pde, s);
 
        ret = iommu_queue_command(iommu, &cmd);
 
@@ -321,9 +421,35 @@ static void iommu_flush_tlb(struct amd_iommu *iommu, u16 domid)
 {
        u64 address = CMD_INV_IOMMU_ALL_PAGES_ADDRESS;
 
+       INC_STATS_COUNTER(domain_flush_single);
+
        iommu_queue_inv_iommu_pages(iommu, address, domid, 0, 1);
 }
 
+/*
+ * This function is used to flush the IO/TLB for a given protection domain
+ * on every IOMMU in the system
+ */
+static void iommu_flush_domain(u16 domid)
+{
+       unsigned long flags;
+       struct amd_iommu *iommu;
+       struct iommu_cmd cmd;
+
+       INC_STATS_COUNTER(domain_flush_all);
+
+       __iommu_build_inv_iommu_pages(&cmd, CMD_INV_IOMMU_ALL_PAGES_ADDRESS,
+                                     domid, 1, 1);
+
+       list_for_each_entry(iommu, &amd_iommu_list, list) {
+               spin_lock_irqsave(&iommu->lock, flags);
+               __iommu_queue_command(iommu, &cmd);
+               __iommu_completion_wait(iommu);
+               __iommu_wait_for_completion(iommu);
+               spin_unlock_irqrestore(&iommu->lock, flags);
+       }
+}
+
 /****************************************************************************
  *
  * The functions below are used the create the page table mappings for
@@ -338,10 +464,10 @@ static void iommu_flush_tlb(struct amd_iommu *iommu, u16 domid)
  * supporting all features of AMD IOMMU page tables like level skipping
  * and full 64 bit address spaces.
  */
-static int iommu_map(struct protection_domain *dom,
-                    unsigned long bus_addr,
-                    unsigned long phys_addr,
-                    int prot)
+static int iommu_map_page(struct protection_domain *dom,
+                         unsigned long bus_addr,
+                         unsigned long phys_addr,
+                         int prot)
 {
        u64 __pte, *pte, *page;
 
@@ -388,6 +514,28 @@ static int iommu_map(struct protection_domain *dom,
        return 0;
 }
 
+static void iommu_unmap_page(struct protection_domain *dom,
+                            unsigned long bus_addr)
+{
+       u64 *pte;
+
+       pte = &dom->pt_root[IOMMU_PTE_L2_INDEX(bus_addr)];
+
+       if (!IOMMU_PTE_PRESENT(*pte))
+               return;
+
+       pte = IOMMU_PTE_PAGE(*pte);
+       pte = &pte[IOMMU_PTE_L1_INDEX(bus_addr)];
+
+       if (!IOMMU_PTE_PRESENT(*pte))
+               return;
+
+       pte = IOMMU_PTE_PAGE(*pte);
+       pte = &pte[IOMMU_PTE_L1_INDEX(bus_addr)];
+
+       *pte = 0;
+}
+
 /*
  * This function checks if a specific unity mapping entry is needed for
  * this specific IOMMU.
@@ -440,7 +588,7 @@ static int dma_ops_unity_map(struct dma_ops_domain *dma_dom,
 
        for (addr = e->address_start; addr < e->address_end;
             addr += PAGE_SIZE) {
-               ret = iommu_map(&dma_dom->domain, addr, addr, e->prot);
+               ret = iommu_map_page(&dma_dom->domain, addr, addr, e->prot);
                if (ret)
                        return ret;
                /*
@@ -571,6 +719,16 @@ static u16 domain_id_alloc(void)
        return id;
 }
 
+static void domain_id_free(int id)
+{
+       unsigned long flags;
+
+       write_lock_irqsave(&amd_iommu_devtable_lock, flags);
+       if (id > 0 && id < MAX_DOMAIN_ID)
+               __clear_bit(id, amd_iommu_pd_alloc_bitmap);
+       write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
+}
+
 /*
  * Used to reserve address ranges in the aperture (e.g. for exclusion
  * ranges.
@@ -587,12 +745,12 @@ static void dma_ops_reserve_addresses(struct dma_ops_domain *dom,
        iommu_area_reserve(dom->bitmap, start_page, pages);
 }
 
-static void dma_ops_free_pagetable(struct dma_ops_domain *dma_dom)
+static void free_pagetable(struct protection_domain *domain)
 {
        int i, j;
        u64 *p1, *p2, *p3;
 
-       p1 = dma_dom->domain.pt_root;
+       p1 = domain->pt_root;
 
        if (!p1)
                return;
@@ -613,6 +771,8 @@ static void dma_ops_free_pagetable(struct dma_ops_domain *dma_dom)
        }
 
        free_page((unsigned long)p1);
+
+       domain->pt_root = NULL;
 }
 
 /*
@@ -624,7 +784,7 @@ static void dma_ops_domain_free(struct dma_ops_domain *dom)
        if (!dom)
                return;
 
-       dma_ops_free_pagetable(dom);
+       free_pagetable(&dom->domain);
 
        kfree(dom->pte_pages);
 
@@ -663,6 +823,7 @@ static struct dma_ops_domain *dma_ops_domain_alloc(struct amd_iommu *iommu,
                goto free_dma_dom;
        dma_dom->domain.mode = PAGE_MODE_3_LEVEL;
        dma_dom->domain.pt_root = (void *)get_zeroed_page(GFP_KERNEL);
+       dma_dom->domain.flags = PD_DMA_OPS_MASK;
        dma_dom->domain.priv = dma_dom;
        if (!dma_dom->domain.pt_root)
                goto free_dma_dom;
@@ -724,6 +885,15 @@ free_dma_dom:
        return NULL;
 }
 
+/*
+ * little helper function to check whether a given protection domain is a
+ * dma_ops domain
+ */
+static bool dma_ops_domain(struct protection_domain *domain)
+{
+       return domain->flags & PD_DMA_OPS_MASK;
+}
+
 /*
  * Find out the protection domain structure for a given PCI device. This
  * will give us the pointer to the page table root for example.
@@ -744,14 +914,15 @@ static struct protection_domain *domain_for_device(u16 devid)
  * If a device is not yet associated with a domain, this function does
  * assigns it visible for the hardware
  */
-static void set_device_domain(struct amd_iommu *iommu,
-                             struct protection_domain *domain,
-                             u16 devid)
+static void attach_device(struct amd_iommu *iommu,
+                         struct protection_domain *domain,
+                         u16 devid)
 {
        unsigned long flags;
-
        u64 pte_root = virt_to_phys(domain->pt_root);
 
+       domain->dev_cnt += 1;
+
        pte_root |= (domain->mode & DEV_ENTRY_MODE_MASK)
                    << DEV_ENTRY_MODE_SHIFT;
        pte_root |= IOMMU_PTE_IR | IOMMU_PTE_IW | IOMMU_PTE_P | IOMMU_PTE_TV;
@@ -767,6 +938,116 @@ static void set_device_domain(struct amd_iommu *iommu,
        iommu_queue_inv_dev_entry(iommu, devid);
 }
 
+/*
+ * Removes a device from a protection domain (unlocked)
+ */
+static void __detach_device(struct protection_domain *domain, u16 devid)
+{
+
+       /* lock domain */
+       spin_lock(&domain->lock);
+
+       /* remove domain from the lookup table */
+       amd_iommu_pd_table[devid] = NULL;
+
+       /* remove entry from the device table seen by the hardware */
+       amd_iommu_dev_table[devid].data[0] = IOMMU_PTE_P | IOMMU_PTE_TV;
+       amd_iommu_dev_table[devid].data[1] = 0;
+       amd_iommu_dev_table[devid].data[2] = 0;
+
+       /* decrease reference counter */
+       domain->dev_cnt -= 1;
+
+       /* ready */
+       spin_unlock(&domain->lock);
+}
+
+/*
+ * Removes a device from a protection domain (with devtable_lock held)
+ */
+static void detach_device(struct protection_domain *domain, u16 devid)
+{
+       unsigned long flags;
+
+       /* lock device table */
+       write_lock_irqsave(&amd_iommu_devtable_lock, flags);
+       __detach_device(domain, devid);
+       write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
+}
+
+static int device_change_notifier(struct notifier_block *nb,
+                                 unsigned long action, void *data)
+{
+       struct device *dev = data;
+       struct pci_dev *pdev = to_pci_dev(dev);
+       u16 devid = calc_devid(pdev->bus->number, pdev->devfn);
+       struct protection_domain *domain;
+       struct dma_ops_domain *dma_domain;
+       struct amd_iommu *iommu;
+       int order = amd_iommu_aperture_order;
+       unsigned long flags;
+
+       if (devid > amd_iommu_last_bdf)
+               goto out;
+
+       devid = amd_iommu_alias_table[devid];
+
+       iommu = amd_iommu_rlookup_table[devid];
+       if (iommu == NULL)
+               goto out;
+
+       domain = domain_for_device(devid);
+
+       if (domain && !dma_ops_domain(domain))
+               WARN_ONCE(1, "AMD IOMMU WARNING: device %s already bound "
+                         "to a non-dma-ops domain\n", dev_name(dev));
+
+       switch (action) {
+       case BUS_NOTIFY_BOUND_DRIVER:
+               if (domain)
+                       goto out;
+               dma_domain = find_protection_domain(devid);
+               if (!dma_domain)
+                       dma_domain = iommu->default_dom;
+               attach_device(iommu, &dma_domain->domain, devid);
+               printk(KERN_INFO "AMD IOMMU: Using protection domain %d for "
+                      "device %s\n", dma_domain->domain.id, dev_name(dev));
+               break;
+       case BUS_NOTIFY_UNBIND_DRIVER:
+               if (!domain)
+                       goto out;
+               detach_device(domain, devid);
+               break;
+       case BUS_NOTIFY_ADD_DEVICE:
+               /* allocate a protection domain if a device is added */
+               dma_domain = find_protection_domain(devid);
+               if (dma_domain)
+                       goto out;
+               dma_domain = dma_ops_domain_alloc(iommu, order);
+               if (!dma_domain)
+                       goto out;
+               dma_domain->target_dev = devid;
+
+               spin_lock_irqsave(&iommu_pd_list_lock, flags);
+               list_add_tail(&dma_domain->list, &iommu_pd_list);
+               spin_unlock_irqrestore(&iommu_pd_list_lock, flags);
+
+               break;
+       default:
+               goto out;
+       }
+
+       iommu_queue_inv_dev_entry(iommu, devid);
+       iommu_completion_wait(iommu);
+
+out:
+       return 0;
+}
+
+struct notifier_block device_nb = {
+       .notifier_call = device_change_notifier,
+};
+
 /*****************************************************************************
  *
  * The next functions belong to the dma_ops mapping/unmapping code.
@@ -802,7 +1083,6 @@ static struct dma_ops_domain *find_protection_domain(u16 devid)
        list_for_each_entry(entry, &iommu_pd_list, list) {
                if (entry->target_dev == devid) {
                        ret = entry;
-                       list_del(&ret->list);
                        break;
                }
        }
@@ -853,14 +1133,13 @@ static int get_device_resources(struct device *dev,
                if (!dma_dom)
                        dma_dom = (*iommu)->default_dom;
                *domain = &dma_dom->domain;
-               set_device_domain(*iommu, *domain, *bdf);
+               attach_device(*iommu, *domain, *bdf);
                printk(KERN_INFO "AMD IOMMU: Using protection domain %d for "
-                               "device ", (*domain)->id);
-               print_devid(_bdf, 1);
+                               "device %s\n", (*domain)->id, dev_name(dev));
        }
 
        if (domain_for_device(_bdf) == NULL)
-               set_device_domain(*iommu, *domain, _bdf);
+               attach_device(*iommu, *domain, _bdf);
 
        return 1;
 }
@@ -946,6 +1225,11 @@ static dma_addr_t __map_single(struct device *dev,
        pages = iommu_num_pages(paddr, size, PAGE_SIZE);
        paddr &= PAGE_MASK;
 
+       INC_STATS_COUNTER(total_map_requests);
+
+       if (pages > 1)
+               INC_STATS_COUNTER(cross_page);
+
        if (align)
                align_mask = (1UL << get_order(size)) - 1;
 
@@ -962,6 +1246,8 @@ static dma_addr_t __map_single(struct device *dev,
        }
        address += offset;
 
+       ADD_STATS_COUNTER(alloced_io_mem, size);
+
        if (unlikely(dma_dom->need_flush && !amd_iommu_unmap_flush)) {
                iommu_flush_tlb(iommu, dma_dom->domain.id);
                dma_dom->need_flush = false;
@@ -998,6 +1284,8 @@ static void __unmap_single(struct amd_iommu *iommu,
                start += PAGE_SIZE;
        }
 
+       SUB_STATS_COUNTER(alloced_io_mem, size);
+
        dma_ops_free_addresses(dma_dom, dma_addr, pages);
 
        if (amd_iommu_unmap_flush || dma_dom->need_flush) {
@@ -1019,6 +1307,8 @@ static dma_addr_t map_single(struct device *dev, phys_addr_t paddr,
        dma_addr_t addr;
        u64 dma_mask;
 
+       INC_STATS_COUNTER(cnt_map_single);
+
        if (!check_device(dev))
                return bad_dma_address;
 
@@ -1030,6 +1320,9 @@ static dma_addr_t map_single(struct device *dev, phys_addr_t paddr,
                /* device not handled by any AMD IOMMU */
                return (dma_addr_t)paddr;
 
+       if (!dma_ops_domain(domain))
+               return bad_dma_address;
+
        spin_lock_irqsave(&domain->lock, flags);
        addr = __map_single(dev, iommu, domain->priv, paddr, size, dir, false,
                            dma_mask);
@@ -1055,11 +1348,16 @@ static void unmap_single(struct device *dev, dma_addr_t dma_addr,
        struct protection_domain *domain;
        u16 devid;
 
+       INC_STATS_COUNTER(cnt_unmap_single);
+
        if (!check_device(dev) ||
            !get_device_resources(dev, &iommu, &domain, &devid))
                /* device not handled by any AMD IOMMU */
                return;
 
+       if (!dma_ops_domain(domain))
+               return;
+
        spin_lock_irqsave(&domain->lock, flags);
 
        __unmap_single(iommu, domain->priv, dma_addr, size, dir);
@@ -1104,6 +1402,8 @@ static int map_sg(struct device *dev, struct scatterlist *sglist,
        int mapped_elems = 0;
        u64 dma_mask;
 
+       INC_STATS_COUNTER(cnt_map_sg);
+
        if (!check_device(dev))
                return 0;
 
@@ -1114,6 +1414,9 @@ static int map_sg(struct device *dev, struct scatterlist *sglist,
        if (!iommu || !domain)
                return map_sg_no_iommu(dev, sglist, nelems, dir);
 
+       if (!dma_ops_domain(domain))
+               return 0;
+
        spin_lock_irqsave(&domain->lock, flags);
 
        for_each_sg(sglist, s, nelems, i) {
@@ -1163,10 +1466,15 @@ static void unmap_sg(struct device *dev, struct scatterlist *sglist,
        u16 devid;
        int i;
 
+       INC_STATS_COUNTER(cnt_unmap_sg);
+
        if (!check_device(dev) ||
            !get_device_resources(dev, &iommu, &domain, &devid))
                return;
 
+       if (!dma_ops_domain(domain))
+               return;
+
        spin_lock_irqsave(&domain->lock, flags);
 
        for_each_sg(sglist, s, nelems, i) {
@@ -1194,6 +1502,8 @@ static void *alloc_coherent(struct device *dev, size_t size,
        phys_addr_t paddr;
        u64 dma_mask = dev->coherent_dma_mask;
 
+       INC_STATS_COUNTER(cnt_alloc_coherent);
+
        if (!check_device(dev))
                return NULL;
 
@@ -1212,6 +1522,9 @@ static void *alloc_coherent(struct device *dev, size_t size,
                return virt_addr;
        }
 
+       if (!dma_ops_domain(domain))
+               goto out_free;
+
        if (!dma_mask)
                dma_mask = *dev->dma_mask;
 
@@ -1220,18 +1533,20 @@ static void *alloc_coherent(struct device *dev, size_t size,
        *dma_addr = __map_single(dev, iommu, domain->priv, paddr,
                                 size, DMA_BIDIRECTIONAL, true, dma_mask);
 
-       if (*dma_addr == bad_dma_address) {
-               free_pages((unsigned long)virt_addr, get_order(size));
-               virt_addr = NULL;
-               goto out;
-       }
+       if (*dma_addr == bad_dma_address)
+               goto out_free;
 
        iommu_completion_wait(iommu);
 
-out:
        spin_unlock_irqrestore(&domain->lock, flags);
 
        return virt_addr;
+
+out_free:
+
+       free_pages((unsigned long)virt_addr, get_order(size));
+
+       return NULL;
 }
 
 /*
@@ -1245,6 +1560,8 @@ static void free_coherent(struct device *dev, size_t size,
        struct protection_domain *domain;
        u16 devid;
 
+       INC_STATS_COUNTER(cnt_free_coherent);
+
        if (!check_device(dev))
                return;
 
@@ -1253,6 +1570,9 @@ static void free_coherent(struct device *dev, size_t size,
        if (!iommu || !domain)
                goto free_mem;
 
+       if (!dma_ops_domain(domain))
+               goto free_mem;
+
        spin_lock_irqsave(&domain->lock, flags);
 
        __unmap_single(iommu, domain->priv, dma_addr, size, DMA_BIDIRECTIONAL);
@@ -1296,7 +1616,7 @@ static int amd_iommu_dma_supported(struct device *dev, u64 mask)
  * we don't need to preallocate the protection domains anymore.
  * For now we have to.
  */
-void prealloc_protection_domains(void)
+static void prealloc_protection_domains(void)
 {
        struct pci_dev *dev = NULL;
        struct dma_ops_domain *dma_dom;
@@ -1305,7 +1625,7 @@ void prealloc_protection_domains(void)
        u16 devid;
 
        while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-               devid = (dev->bus->number << 8) | dev->devfn;
+               devid = calc_devid(dev->bus->number, dev->devfn);
                if (devid > amd_iommu_last_bdf)
                        continue;
                devid = amd_iommu_alias_table[devid];
@@ -1352,6 +1672,7 @@ int __init amd_iommu_init_dma_ops(void)
                iommu->default_dom = dma_ops_domain_alloc(iommu, order);
                if (iommu->default_dom == NULL)
                        return -ENOMEM;
+               iommu->default_dom->domain.flags |= PD_DEFAULT_MASK;
                ret = iommu_init_unity_mappings(iommu);
                if (ret)
                        goto free_domains;
@@ -1375,6 +1696,12 @@ int __init amd_iommu_init_dma_ops(void)
        /* Make the driver finally visible to the drivers */
        dma_ops = &amd_iommu_dma_ops;
 
+       register_iommu(&amd_iommu_ops);
+
+       bus_register_notifier(&pci_bus_type, &device_nb);
+
+       amd_iommu_stats_init();
+
        return 0;
 
 free_domains:
@@ -1386,3 +1713,224 @@ free_domains:
 
        return ret;
 }
+
+/*****************************************************************************
+ *
+ * The following functions belong to the exported interface of AMD IOMMU
+ *
+ * This interface allows access to lower level functions of the IOMMU
+ * like protection domain handling and assignement of devices to domains
+ * which is not possible with the dma_ops interface.
+ *
+ *****************************************************************************/
+
+static void cleanup_domain(struct protection_domain *domain)
+{
+       unsigned long flags;
+       u16 devid;
+
+       write_lock_irqsave(&amd_iommu_devtable_lock, flags);
+
+       for (devid = 0; devid <= amd_iommu_last_bdf; ++devid)
+               if (amd_iommu_pd_table[devid] == domain)
+                       __detach_device(domain, devid);
+
+       write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
+}
+
+static int amd_iommu_domain_init(struct iommu_domain *dom)
+{
+       struct protection_domain *domain;
+
+       domain = kzalloc(sizeof(*domain), GFP_KERNEL);
+       if (!domain)
+               return -ENOMEM;
+
+       spin_lock_init(&domain->lock);
+       domain->mode = PAGE_MODE_3_LEVEL;
+       domain->id = domain_id_alloc();
+       if (!domain->id)
+               goto out_free;
+       domain->pt_root = (void *)get_zeroed_page(GFP_KERNEL);
+       if (!domain->pt_root)
+               goto out_free;
+
+       dom->priv = domain;
+
+       return 0;
+
+out_free:
+       kfree(domain);
+
+       return -ENOMEM;
+}
+
+static void amd_iommu_domain_destroy(struct iommu_domain *dom)
+{
+       struct protection_domain *domain = dom->priv;
+
+       if (!domain)
+               return;
+
+       if (domain->dev_cnt > 0)
+               cleanup_domain(domain);
+
+       BUG_ON(domain->dev_cnt != 0);
+
+       free_pagetable(domain);
+
+       domain_id_free(domain->id);
+
+       kfree(domain);
+
+       dom->priv = NULL;
+}
+
+static void amd_iommu_detach_device(struct iommu_domain *dom,
+                                   struct device *dev)
+{
+       struct protection_domain *domain = dom->priv;
+       struct amd_iommu *iommu;
+       struct pci_dev *pdev;
+       u16 devid;
+
+       if (dev->bus != &pci_bus_type)
+               return;
+
+       pdev = to_pci_dev(dev);
+
+       devid = calc_devid(pdev->bus->number, pdev->devfn);
+
+       if (devid > 0)
+               detach_device(domain, devid);
+
+       iommu = amd_iommu_rlookup_table[devid];
+       if (!iommu)
+               return;
+
+       iommu_queue_inv_dev_entry(iommu, devid);
+       iommu_completion_wait(iommu);
+}
+
+static int amd_iommu_attach_device(struct iommu_domain *dom,
+                                  struct device *dev)
+{
+       struct protection_domain *domain = dom->priv;
+       struct protection_domain *old_domain;
+       struct amd_iommu *iommu;
+       struct pci_dev *pdev;
+       u16 devid;
+
+       if (dev->bus != &pci_bus_type)
+               return -EINVAL;
+
+       pdev = to_pci_dev(dev);
+
+       devid = calc_devid(pdev->bus->number, pdev->devfn);
+
+       if (devid >= amd_iommu_last_bdf ||
+                       devid != amd_iommu_alias_table[devid])
+               return -EINVAL;
+
+       iommu = amd_iommu_rlookup_table[devid];
+       if (!iommu)
+               return -EINVAL;
+
+       old_domain = domain_for_device(devid);
+       if (old_domain)
+               return -EBUSY;
+
+       attach_device(iommu, domain, devid);
+
+       iommu_completion_wait(iommu);
+
+       return 0;
+}
+
+static int amd_iommu_map_range(struct iommu_domain *dom,
+                              unsigned long iova, phys_addr_t paddr,
+                              size_t size, int iommu_prot)
+{
+       struct protection_domain *domain = dom->priv;
+       unsigned long i,  npages = iommu_num_pages(paddr, size, PAGE_SIZE);
+       int prot = 0;
+       int ret;
+
+       if (iommu_prot & IOMMU_READ)
+               prot |= IOMMU_PROT_IR;
+       if (iommu_prot & IOMMU_WRITE)
+               prot |= IOMMU_PROT_IW;
+
+       iova  &= PAGE_MASK;
+       paddr &= PAGE_MASK;
+
+       for (i = 0; i < npages; ++i) {
+               ret = iommu_map_page(domain, iova, paddr, prot);
+               if (ret)
+                       return ret;
+
+               iova  += PAGE_SIZE;
+               paddr += PAGE_SIZE;
+       }
+
+       return 0;
+}
+
+static void amd_iommu_unmap_range(struct iommu_domain *dom,
+                                 unsigned long iova, size_t size)
+{
+
+       struct protection_domain *domain = dom->priv;
+       unsigned long i,  npages = iommu_num_pages(iova, size, PAGE_SIZE);
+
+       iova  &= PAGE_MASK;
+
+       for (i = 0; i < npages; ++i) {
+               iommu_unmap_page(domain, iova);
+               iova  += PAGE_SIZE;
+       }
+
+       iommu_flush_domain(domain->id);
+}
+
+static phys_addr_t amd_iommu_iova_to_phys(struct iommu_domain *dom,
+                                         unsigned long iova)
+{
+       struct protection_domain *domain = dom->priv;
+       unsigned long offset = iova & ~PAGE_MASK;
+       phys_addr_t paddr;
+       u64 *pte;
+
+       pte = &domain->pt_root[IOMMU_PTE_L2_INDEX(iova)];
+
+       if (!IOMMU_PTE_PRESENT(*pte))
+               return 0;
+
+       pte = IOMMU_PTE_PAGE(*pte);
+       pte = &pte[IOMMU_PTE_L1_INDEX(iova)];
+
+       if (!IOMMU_PTE_PRESENT(*pte))
+               return 0;
+
+       pte = IOMMU_PTE_PAGE(*pte);
+       pte = &pte[IOMMU_PTE_L0_INDEX(iova)];
+
+       if (!IOMMU_PTE_PRESENT(*pte))
+               return 0;
+
+       paddr  = *pte & IOMMU_PAGE_MASK;
+       paddr |= offset;
+
+       return paddr;
+}
+
+static struct iommu_ops amd_iommu_ops = {
+       .domain_init = amd_iommu_domain_init,
+       .domain_destroy = amd_iommu_domain_destroy,
+       .attach_dev = amd_iommu_attach_device,
+       .detach_dev = amd_iommu_detach_device,
+       .map = amd_iommu_map_range,
+       .unmap = amd_iommu_unmap_range,
+       .iova_to_phys = amd_iommu_iova_to_phys,
+};
+
index c625800c55caeb411211607983ab4e7f22e3c731..42c33cebf00f5c6cbc17b0394f94801a79d64d7e 100644 (file)
@@ -122,7 +122,8 @@ u16 amd_iommu_last_bdf;                     /* largest PCI device id we have
 LIST_HEAD(amd_iommu_unity_map);                /* a list of required unity mappings
                                           we find in ACPI */
 unsigned amd_iommu_aperture_order = 26; /* size of aperture in power of 2 */
-int amd_iommu_isolate = 1;             /* if 1, device isolation is enabled */
+bool amd_iommu_isolate = true;         /* if true, device isolation is
+                                          enabled */
 bool amd_iommu_unmap_flush;            /* if true, flush on every unmap */
 
 LIST_HEAD(amd_iommu_list);             /* list of all AMD IOMMUs in the
@@ -243,20 +244,16 @@ static void __init iommu_feature_disable(struct amd_iommu *iommu, u8 bit)
 }
 
 /* Function to enable the hardware */
-void __init iommu_enable(struct amd_iommu *iommu)
+static void __init iommu_enable(struct amd_iommu *iommu)
 {
-       printk(KERN_INFO "AMD IOMMU: Enabling IOMMU "
-              "at %02x:%02x.%x cap 0x%hx\n",
-              iommu->dev->bus->number,
-              PCI_SLOT(iommu->dev->devfn),
-              PCI_FUNC(iommu->dev->devfn),
-              iommu->cap_ptr);
+       printk(KERN_INFO "AMD IOMMU: Enabling IOMMU at %s cap 0x%hx\n",
+              dev_name(&iommu->dev->dev), iommu->cap_ptr);
 
        iommu_feature_enable(iommu, CONTROL_IOMMU_EN);
 }
 
 /* Function to enable IOMMU event logging and event interrupts */
-void __init iommu_enable_event_logging(struct amd_iommu *iommu)
+static void __init iommu_enable_event_logging(struct amd_iommu *iommu)
 {
        iommu_feature_enable(iommu, CONTROL_EVT_LOG_EN);
        iommu_feature_enable(iommu, CONTROL_EVT_INT_EN);
@@ -1218,9 +1215,9 @@ static int __init parse_amd_iommu_options(char *str)
 {
        for (; *str; ++str) {
                if (strncmp(str, "isolate", 7) == 0)
-                       amd_iommu_isolate = 1;
+                       amd_iommu_isolate = true;
                if (strncmp(str, "share", 5) == 0)
-                       amd_iommu_isolate = 0;
+                       amd_iommu_isolate = false;
                if (strncmp(str, "fullflush", 9) == 0)
                        amd_iommu_unmap_flush = true;
        }
index 6b7f824db16003a89dd2fca8786c130459e26dda..b13d3c4dbd42255b9e0e041d7ce913ad10f80d1f 100644 (file)
@@ -98,8 +98,8 @@ __setup("apicpmtimer", setup_apicpmtimer);
 #ifdef HAVE_X2APIC
 int x2apic;
 /* x2apic enabled before OS handover */
-int x2apic_preenabled;
-int disable_x2apic;
+static int x2apic_preenabled;
+static int disable_x2apic;
 static __init int setup_nox2apic(char *str)
 {
        disable_x2apic = 1;
@@ -140,7 +140,7 @@ static int lapic_next_event(unsigned long delta,
                            struct clock_event_device *evt);
 static void lapic_timer_setup(enum clock_event_mode mode,
                              struct clock_event_device *evt);
-static void lapic_timer_broadcast(const cpumask_t *mask);
+static void lapic_timer_broadcast(const struct cpumask *mask);
 static void apic_pm_activate(void);
 
 /*
@@ -226,7 +226,7 @@ void xapic_icr_write(u32 low, u32 id)
        apic_write(APIC_ICR, low);
 }
 
-u64 xapic_icr_read(void)
+static u64 xapic_icr_read(void)
 {
        u32 icr1, icr2;
 
@@ -266,7 +266,7 @@ void x2apic_icr_write(u32 low, u32 id)
        wrmsrl(APIC_BASE_MSR + (APIC_ICR >> 4), ((__u64) id) << 32 | low);
 }
 
-u64 x2apic_icr_read(void)
+static u64 x2apic_icr_read(void)
 {
        unsigned long val;
 
@@ -453,7 +453,7 @@ static void lapic_timer_setup(enum clock_event_mode mode,
 /*
  * Local APIC timer broadcast function
  */
-static void lapic_timer_broadcast(const cpumask_t *mask)
+static void lapic_timer_broadcast(const struct cpumask *mask)
 {
 #ifdef CONFIG_SMP
        send_IPI_mask(mask, LOCAL_TIMER_VECTOR);
index 2a0a2a3cac263a87edc38f12894185749a1b9dd5..f63882728d91868d3ce392aa87bc7965e8e9145c 100644 (file)
@@ -25,7 +25,7 @@
 #include <asm/uv/bios.h>
 #include <asm/uv/uv_hub.h>
 
-struct uv_systab uv_systab;
+static struct uv_systab uv_systab;
 
 s64 uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5)
 {
index 42e0853030cbe43275cc596c3f5896388dd30cae..3f95a40f718a43e0f07da0a5c1a22e68c42b55f4 100644 (file)
@@ -355,7 +355,7 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c)
                printk(KERN_INFO  "CPU: Hyper-Threading is disabled\n");
        } else if (smp_num_siblings > 1) {
 
-               if (smp_num_siblings > NR_CPUS) {
+               if (smp_num_siblings > nr_cpu_ids) {
                        printk(KERN_WARNING "CPU: Unsupported number of siblings %d",
                                        smp_num_siblings);
                        smp_num_siblings = 1;
index 88ea02dcb622fe5bf3ef4f2d7a28fc31bdf938e0..28102ad1a36360a2ceff7d1692f1e4309db075bb 100644 (file)
@@ -517,6 +517,17 @@ acpi_cpufreq_guess_freq(struct acpi_cpufreq_data *data, unsigned int cpu)
        }
 }
 
+static void free_acpi_perf_data(void)
+{
+       unsigned int i;
+
+       /* Freeing a NULL pointer is OK, and alloc_percpu zeroes. */
+       for_each_possible_cpu(i)
+               free_cpumask_var(per_cpu_ptr(acpi_perf_data, i)
+                                ->shared_cpu_map);
+       free_percpu(acpi_perf_data);
+}
+
 /*
  * acpi_cpufreq_early_init - initialize ACPI P-States library
  *
@@ -527,6 +538,7 @@ acpi_cpufreq_guess_freq(struct acpi_cpufreq_data *data, unsigned int cpu)
  */
 static int __init acpi_cpufreq_early_init(void)
 {
+       unsigned int i;
        dprintk("acpi_cpufreq_early_init\n");
 
        acpi_perf_data = alloc_percpu(struct acpi_processor_performance);
@@ -534,6 +546,16 @@ static int __init acpi_cpufreq_early_init(void)
                dprintk("Memory allocation error for acpi_perf_data.\n");
                return -ENOMEM;
        }
+       for_each_possible_cpu(i) {
+               if (!alloc_cpumask_var_node(
+                       &per_cpu_ptr(acpi_perf_data, i)->shared_cpu_map,
+                       GFP_KERNEL, cpu_to_node(i))) {
+
+                       /* Freeing a NULL pointer is OK: alloc_percpu zeroes. */
+                       free_acpi_perf_data();
+                       return -ENOMEM;
+               }
+       }
 
        /* Do initialization in ACPI core */
        acpi_processor_preregister_performance(acpi_perf_data);
@@ -604,9 +626,9 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
         */
        if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL ||
            policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) {
-               policy->cpus = perf->shared_cpu_map;
+               cpumask_copy(&policy->cpus, perf->shared_cpu_map);
        }
-       policy->related_cpus = perf->shared_cpu_map;
+       cpumask_copy(&policy->related_cpus, perf->shared_cpu_map);
 
 #ifdef CONFIG_SMP
        dmi_check_system(sw_any_bug_dmi_table);
@@ -795,7 +817,7 @@ static int __init acpi_cpufreq_init(void)
 
        ret = cpufreq_register_driver(&acpi_cpufreq_driver);
        if (ret)
-               free_percpu(acpi_perf_data);
+               free_acpi_perf_data();
 
        return ret;
 }
index b8e05ee4f7361a1dc57ce28ff9d2e5e5526f776d..beea4466b0633a359be3d3461a9e16b83c36e85d 100644 (file)
@@ -160,6 +160,7 @@ static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c)
                switch (c->x86_model) {
                case 0x0E: /* Core */
                case 0x0F: /* Core Duo */
+               case 0x16: /* Celeron Core */
                        p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS;
                        return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_PCORE);
                case 0x0D: /* Pentium M (Dothan) */
@@ -171,7 +172,9 @@ static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c)
        }
 
        if (c->x86 != 0xF) {
-               printk(KERN_WARNING PFX "Unknown p4-clockmod-capable CPU. Please send an e-mail to <cpufreq@vger.kernel.org>\n");
+               if (!cpu_has(c, X86_FEATURE_EST))
+                       printk(KERN_WARNING PFX "Unknown p4-clockmod-capable CPU. "
+                               "Please send an e-mail to <cpufreq@vger.kernel.org>\n");
                return 0;
        }
 
@@ -274,6 +277,7 @@ static struct cpufreq_driver p4clockmod_driver = {
        .name           = "p4-clockmod",
        .owner          = THIS_MODULE,
        .attr           = p4clockmod_attr,
+       .hide_interface = 1,
 };
 
 
index 7c7d56b43136a6a416085fb7cc4b27f25839ec3c..1b446d79a8fdd2d2a92f8ea04dbaa41da57a4f88 100644 (file)
@@ -310,6 +310,12 @@ static int powernow_acpi_init(void)
                goto err0;
        }
 
+       if (!alloc_cpumask_var(&acpi_processor_perf->shared_cpu_map,
+                                                               GFP_KERNEL)) {
+               retval = -ENOMEM;
+               goto err05;
+       }
+
        if (acpi_processor_register_performance(acpi_processor_perf, 0)) {
                retval = -EIO;
                goto err1;
@@ -412,6 +418,8 @@ static int powernow_acpi_init(void)
 err2:
        acpi_processor_unregister_performance(acpi_processor_perf, 0);
 err1:
+       free_cpumask_var(acpi_processor_perf->shared_cpu_map);
+err05:
        kfree(acpi_processor_perf);
 err0:
        printk(KERN_WARNING PFX "ACPI perflib can not be used in this platform\n");
@@ -652,6 +660,7 @@ static int powernow_cpu_exit (struct cpufreq_policy *policy) {
 #ifdef CONFIG_X86_POWERNOW_K7_ACPI
        if (acpi_processor_perf) {
                acpi_processor_unregister_performance(acpi_processor_perf, 0);
+               free_cpumask_var(acpi_processor_perf->shared_cpu_map);
                kfree(acpi_processor_perf);
        }
 #endif
index 7f05f44b97e95c72447c0538f19e06185c0a18b1..c3c9adbaa26f6c321a5fbe85e8006a1ed533e8cb 100644 (file)
@@ -766,7 +766,7 @@ static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned
 static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
 {
        struct cpufreq_frequency_table *powernow_table;
-       int ret_val;
+       int ret_val = -ENODEV;
 
        if (acpi_processor_register_performance(&data->acpi_data, data->cpu)) {
                dprintk("register performance failed: bad ACPI data\n");
@@ -815,6 +815,13 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
        /* notify BIOS that we exist */
        acpi_processor_notify_smm(THIS_MODULE);
 
+       if (!alloc_cpumask_var(&data->acpi_data.shared_cpu_map, GFP_KERNEL)) {
+               printk(KERN_ERR PFX
+                               "unable to alloc powernow_k8_data cpumask\n");
+               ret_val = -ENOMEM;
+               goto err_out_mem;
+       }
+
        return 0;
 
 err_out_mem:
@@ -826,7 +833,7 @@ err_out:
        /* data->acpi_data.state_count informs us at ->exit() whether ACPI was used */
        data->acpi_data.state_count = 0;
 
-       return -ENODEV;
+       return ret_val;
 }
 
 static int fill_powernow_table_pstate(struct powernow_k8_data *data, struct cpufreq_frequency_table *powernow_table)
@@ -929,6 +936,7 @@ static void powernow_k8_cpu_exit_acpi(struct powernow_k8_data *data)
 {
        if (data->acpi_data.state_count)
                acpi_processor_unregister_performance(&data->acpi_data, data->cpu);
+       free_cpumask_var(data->acpi_data.shared_cpu_map);
 }
 
 #else
@@ -1134,7 +1142,8 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
        data->cpu = pol->cpu;
        data->currpstate = HW_PSTATE_INVALID;
 
-       if (powernow_k8_cpu_init_acpi(data)) {
+       rc = powernow_k8_cpu_init_acpi(data);
+       if (rc) {
                /*
                 * Use the PSB BIOS structure. This is only availabe on
                 * an UP version, and is deprecated by AMD.
@@ -1152,20 +1161,17 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
                               "ACPI maintainers and complain to your BIOS "
                               "vendor.\n");
 #endif
-                       kfree(data);
-                       return -ENODEV;
+                       goto err_out;
                }
                if (pol->cpu != 0) {
                        printk(KERN_ERR FW_BUG PFX "No ACPI _PSS objects for "
                               "CPU other than CPU0. Complain to your BIOS "
                               "vendor.\n");
-                       kfree(data);
-                       return -ENODEV;
+                       goto err_out;
                }
                rc = find_psb_table(data);
                if (rc) {
-                       kfree(data);
-                       return -ENODEV;
+                       goto err_out;
                }
        }
 
index 3b5f06423e7774f2801e31e811c631df90344e36..f0ea6fa2f53c8a58ad1982c88c5b5869b9428c60 100644 (file)
@@ -459,9 +459,7 @@ static int centrino_verify (struct cpufreq_policy *policy)
  * Sets a new CPUFreq policy.
  */
 struct allmasks {
-       cpumask_t               online_policy_cpus;
        cpumask_t               saved_mask;
-       cpumask_t               set_mask;
        cpumask_t               covered_cpus;
 };
 
@@ -475,9 +473,7 @@ static int centrino_target (struct cpufreq_policy *policy,
        int                     retval = 0;
        unsigned int            j, k, first_cpu, tmp;
        CPUMASK_ALLOC(allmasks);
-       CPUMASK_PTR(online_policy_cpus, allmasks);
        CPUMASK_PTR(saved_mask, allmasks);
-       CPUMASK_PTR(set_mask, allmasks);
        CPUMASK_PTR(covered_cpus, allmasks);
 
        if (unlikely(allmasks == NULL))
@@ -497,30 +493,28 @@ static int centrino_target (struct cpufreq_policy *policy,
                goto out;
        }
 
-#ifdef CONFIG_HOTPLUG_CPU
-       /* cpufreq holds the hotplug lock, so we are safe from here on */
-       cpus_and(*online_policy_cpus, cpu_online_map, policy->cpus);
-#else
-       *online_policy_cpus = policy->cpus;
-#endif
-
        *saved_mask = current->cpus_allowed;
        first_cpu = 1;
        cpus_clear(*covered_cpus);
-       for_each_cpu_mask_nr(j, *online_policy_cpus) {
+       for_each_cpu_mask_nr(j, policy->cpus) {
+               const cpumask_t *mask;
+
+               /* cpufreq holds the hotplug lock, so we are safe here */
+               if (!cpu_online(j))
+                       continue;
+
                /*
                 * Support for SMP systems.
                 * Make sure we are running on CPU that wants to change freq
                 */
-               cpus_clear(*set_mask);
                if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY)
-                       cpus_or(*set_mask, *set_mask, *online_policy_cpus);
+                       mask = &policy->cpus;
                else
-                       cpu_set(j, *set_mask);
+                       mask = &cpumask_of_cpu(j);
 
-               set_cpus_allowed_ptr(current, set_mask);
+               set_cpus_allowed_ptr(current, mask);
                preempt_disable();
-               if (unlikely(!cpu_isset(smp_processor_id(), *set_mask))) {
+               if (unlikely(!cpu_isset(smp_processor_id(), *mask))) {
                        dprintk("couldn't limit to CPUs in this domain\n");
                        retval = -EAGAIN;
                        if (first_cpu) {
@@ -548,7 +542,9 @@ static int centrino_target (struct cpufreq_policy *policy,
                        dprintk("target=%dkHz old=%d new=%d msr=%04x\n",
                                target_freq, freqs.old, freqs.new, msr);
 
-                       for_each_cpu_mask_nr(k, *online_policy_cpus) {
+                       for_each_cpu_mask_nr(k, policy->cpus) {
+                               if (!cpu_online(k))
+                                       continue;
                                freqs.cpu = k;
                                cpufreq_notify_transition(&freqs,
                                        CPUFREQ_PRECHANGE);
@@ -571,7 +567,9 @@ static int centrino_target (struct cpufreq_policy *policy,
                preempt_enable();
        }
 
-       for_each_cpu_mask_nr(k, *online_policy_cpus) {
+       for_each_cpu_mask_nr(k, policy->cpus) {
+               if (!cpu_online(k))
+                       continue;
                freqs.cpu = k;
                cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
        }
@@ -584,18 +582,17 @@ static int centrino_target (struct cpufreq_policy *policy,
                 * Best effort undo..
                 */
 
-               if (!cpus_empty(*covered_cpus))
-                       for_each_cpu_mask_nr(j, *covered_cpus) {
-                               set_cpus_allowed_ptr(current,
-                                                    &cpumask_of_cpu(j));
-                               wrmsr(MSR_IA32_PERF_CTL, oldmsr, h);
-                       }
+               for_each_cpu_mask_nr(j, *covered_cpus) {
+                       set_cpus_allowed_ptr(current, &cpumask_of_cpu(j));
+                       wrmsr(MSR_IA32_PERF_CTL, oldmsr, h);
+               }
 
                tmp = freqs.new;
                freqs.new = freqs.old;
                freqs.old = tmp;
-               for_each_cpu_mask_nr(j, *online_policy_cpus) {
-                       freqs.cpu = j;
+               for_each_cpu_mask_nr(j, policy->cpus) {
+                       if (!cpu_online(j))
+                               continue;
                        cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
                        cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
                }
index 98d4fdb7dc046b73cfc00402be21da9a9d303686..cdac7d62369b645a00b15c41c4d617e78b86c3b1 100644 (file)
@@ -139,6 +139,15 @@ static unsigned int pentium_core_get_frequency(void)
        case 3:
                fsb = 166667;
                break;
+       case 2:
+               fsb = 200000;
+               break;
+       case 0:
+               fsb = 266667;
+               break;
+       case 4:
+               fsb = 333333;
+               break;
        default:
                printk(KERN_ERR "PCORE - MSR_FSB_FREQ undefined value");
        }
index c6ecda64f5f125b1ba358edac6d9e5693414b020..48533d77be7850c786a0482968ab5ef0d4f4ac51 100644 (file)
@@ -534,7 +534,7 @@ static void __cpuinit free_cache_attributes(unsigned int cpu)
        per_cpu(cpuid4_info, cpu) = NULL;
 }
 
-static void get_cpu_leaves(void *_retval)
+static void __cpuinit get_cpu_leaves(void *_retval)
 {
        int j, *retval = _retval, cpu = smp_processor_id();
 
index d6ec7ec30274fc35d95440d9dcb819f0a4504d84..d259e5d2e0546adbec36d55f63b7f2a81f88e002 100644 (file)
@@ -824,16 +824,14 @@ static int enable_mtrr_cleanup __initdata =
 
 static int __init disable_mtrr_cleanup_setup(char *str)
 {
-       if (enable_mtrr_cleanup != -1)
-               enable_mtrr_cleanup = 0;
+       enable_mtrr_cleanup = 0;
        return 0;
 }
 early_param("disable_mtrr_cleanup", disable_mtrr_cleanup_setup);
 
 static int __init enable_mtrr_cleanup_setup(char *str)
 {
-       if (enable_mtrr_cleanup != -1)
-               enable_mtrr_cleanup = 1;
+       enable_mtrr_cleanup = 1;
        return 0;
 }
 early_param("enable_mtrr_cleanup", enable_mtrr_cleanup_setup);
index 72cefd1e649ba4be254b5ec497f442160dab1752..2ac1f0c2beb3ba54088d4e0c4e89622dbc03094d 100644 (file)
 #include <linux/device.h>
 #include <linux/cpu.h>
 #include <linux/notifier.h>
+#include <linux/uaccess.h>
 
 #include <asm/processor.h>
 #include <asm/msr.h>
-#include <asm/uaccess.h>
 #include <asm/system.h>
 
 static struct class *cpuid_class;
@@ -82,7 +82,7 @@ static loff_t cpuid_seek(struct file *file, loff_t offset, int orig)
 }
 
 static ssize_t cpuid_read(struct file *file, char __user *buf,
-                         size_t count, loff_t * ppos)
+                         size_t count, loff_t *ppos)
 {
        char __user *tmp = buf;
        struct cpuid_regs cmd;
@@ -117,11 +117,11 @@ static int cpuid_open(struct inode *inode, struct file *file)
        unsigned int cpu;
        struct cpuinfo_x86 *c;
        int ret = 0;
-       
+
        lock_kernel();
 
        cpu = iminor(file->f_path.dentry->d_inode);
-       if (cpu >= NR_CPUS || !cpu_online(cpu)) {
+       if (cpu >= nr_cpu_ids || !cpu_online(cpu)) {
                ret = -ENXIO;   /* No such CPU */
                goto out;
        }
index 23b138e31e9c2fe229c42050ab2c5e864cac4710..504ad198e4ad0f999b43dfbb16f1957305e71ffe 100644 (file)
@@ -886,7 +886,7 @@ asmlinkage void early_printk(const char *fmt, ...)
        va_list ap;
 
        va_start(ap, fmt);
-       n = vscnprintf(buf, 512, fmt, ap);
+       n = vscnprintf(buf, sizeof(buf), fmt, ap);
        early_console->write(early_console, buf, n);
        va_end(ap);
 }
index 62895cf315ffb1041e57364cd35d385a62826b25..21bcc0e098ba48c3cd78b068f88dd858c97d98dd 100644 (file)
@@ -161,12 +161,12 @@ static unsigned int phys_pkg_id(int index_msb)
        return current_cpu_data.initial_apicid >> index_msb;
 }
 
-void x2apic_send_IPI_self(int vector)
+static void x2apic_send_IPI_self(int vector)
 {
        apic_write(APIC_SELF_IPI, vector);
 }
 
-void init_x2apic_ldr(void)
+static void init_x2apic_ldr(void)
 {
        return;
 }
index 388e05a5fc17ec05dc68fc881c169608390538b5..b9a4d8c4b93529b3c568c054755d04d1f2534581 100644 (file)
@@ -27,7 +27,7 @@
 #include <asm/trampoline.h>
 
 /* boot cpu pda */
-static struct x8664_pda _boot_cpu_pda __read_mostly;
+static struct x8664_pda _boot_cpu_pda;
 
 #ifdef CONFIG_SMP
 /*
index 62ecfc991e1e61b747567cb2ada8f8d68d0774b2..3639442aa7a4a363afba43b759cfb2984dddba28 100644 (file)
@@ -214,11 +214,11 @@ static struct irq_cfg *get_one_free_irq_cfg(int cpu)
 
        cfg = kzalloc_node(sizeof(*cfg), GFP_ATOMIC, node);
        if (cfg) {
-               /* FIXME: needs alloc_cpumask_var_node() */
-               if (!alloc_cpumask_var(&cfg->domain, GFP_ATOMIC)) {
+               if (!alloc_cpumask_var_node(&cfg->domain, GFP_ATOMIC, node)) {
                        kfree(cfg);
                        cfg = NULL;
-               } else if (!alloc_cpumask_var(&cfg->old_domain, GFP_ATOMIC)) {
+               } else if (!alloc_cpumask_var_node(&cfg->old_domain,
+                                                         GFP_ATOMIC, node)) {
                        free_cpumask_var(cfg->domain);
                        kfree(cfg);
                        cfg = NULL;
@@ -706,7 +706,7 @@ static void __unmask_IO_APIC_irq(struct irq_cfg *cfg)
 }
 
 #ifdef CONFIG_X86_64
-void io_apic_sync(struct irq_pin_list *entry)
+static void io_apic_sync(struct irq_pin_list *entry)
 {
        /*
         * Synchronize the IO-APIC and the CPU by doing
index eee32b43fee3e59b5ab8e3a2243bb6f6a56fb21e..71f1d99a635d75dd7f30ee1f1876b91112d2a82c 100644 (file)
@@ -12,8 +12,8 @@
 #include <linux/mm.h>
 #include <linux/smp.h>
 #include <linux/vmalloc.h>
+#include <linux/uaccess.h>
 
-#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/ldt.h>
 #include <asm/desc.h>
@@ -93,7 +93,7 @@ static inline int copy_ldt(mm_context_t *new, mm_context_t *old)
        if (err < 0)
                return err;
 
-       for(i = 0; i < old->size; i++)
+       for (i = 0; i < old->size; i++)
                write_ldt_entry(new->ldt, i, old->ldt + i * LDT_ENTRY_SIZE);
        return 0;
 }
index efc2f361fe85f0c1280cfce1aeafefa572a5c83d..666e43df51f99ce58b92c844149e1f8efcfa258f 100644 (file)
@@ -13,8 +13,7 @@
 #include <asm/msr.h>
 #include <asm/acpi.h>
 #include <asm/mmconfig.h>
-
-#include "../pci/pci.h"
+#include <asm/pci_x86.h>
 
 struct pci_hostbridge_probe {
        u32 bus;
index 45e3b69808ba6722bcc9617cdd0c883cab1a8ee2..c5c5b8df1dbcc2ef40caa3f11451112102a65fb1 100644 (file)
 #include <linux/bitops.h>
 #include <linux/acpi.h>
 #include <linux/module.h>
+#include <linux/smp.h>
+#include <linux/acpi.h>
 
-#include <asm/smp.h>
 #include <asm/mtrr.h>
 #include <asm/mpspec.h>
 #include <asm/pgalloc.h>
 #include <asm/io_apic.h>
 #include <asm/proto.h>
-#include <asm/acpi.h>
 #include <asm/bios_ebda.h>
 #include <asm/e820.h>
 #include <asm/trampoline.h>
@@ -95,8 +95,8 @@ static void __init MP_bus_info(struct mpc_config_bus *m)
 #endif
 
        if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA) - 1) == 0) {
-                set_bit(m->mpc_busid, mp_bus_not_pci);
-#if defined(CONFIG_EISA) || defined (CONFIG_MCA)
+               set_bit(m->mpc_busid, mp_bus_not_pci);
+#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
                mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
 #endif
        } else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI) - 1) == 0) {
@@ -104,7 +104,7 @@ static void __init MP_bus_info(struct mpc_config_bus *m)
                        x86_quirks->mpc_oem_pci_bus(m);
 
                clear_bit(m->mpc_busid, mp_bus_not_pci);
-#if defined(CONFIG_EISA) || defined (CONFIG_MCA)
+#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
                mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI;
        } else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA) - 1) == 0) {
                mp_bus_id_to_type[m->mpc_busid] = MP_BUS_EISA;
index 82a7c7ed6d456401ef1776a53030a4db7890443e..726266695b2cb4304221989744fb29fbb3e1bb78 100644 (file)
@@ -136,7 +136,7 @@ static int msr_open(struct inode *inode, struct file *file)
        lock_kernel();
        cpu = iminor(file->f_path.dentry->d_inode);
 
-       if (cpu >= NR_CPUS || !cpu_online(cpu)) {
+       if (cpu >= nr_cpu_ids || !cpu_online(cpu)) {
                ret = -ENXIO;   /* No such CPU */
                goto out;
        }
index 8bd1bf9622a7cf1062f33e039c37a2167e5f2918..45a09ccdc2145e4c1b10b4cf1d0ce0715a7a5fc8 100644 (file)
 #include <linux/kernel_stat.h>
 #include <linux/kdebug.h>
 #include <linux/smp.h>
+#include <linux/nmi.h>
 
 #include <asm/i8259.h>
 #include <asm/io_apic.h>
-#include <asm/smp.h>
-#include <asm/nmi.h>
 #include <asm/proto.h>
 #include <asm/timer.h>
 
index a35eaa379ff632fb142367df58a8fdeaaad81267..00c2bcd41463e325976a74cbee0fa06f4b6fe85c 100644 (file)
@@ -52,7 +52,7 @@ static u32 *iommu_gatt_base;          /* Remapping table */
  * to trigger bugs with some popular PCI cards, in particular 3ware (but
  * has been also also seen with Qlogic at least).
  */
-int iommu_fullflush = 1;
+static int iommu_fullflush = 1;
 
 /* Allocation bitmap for the remapping area: */
 static DEFINE_SPINLOCK(iommu_bitmap_lock);
index 39643b1df061d5ae049e8814a0abf126a430f362..2b46eb41643b291a182bc2b868ef1481e1db727b 100644 (file)
@@ -12,6 +12,7 @@
 #include <asm/proto.h>
 #include <asm/reboot_fixups.h>
 #include <asm/reboot.h>
+#include <asm/pci_x86.h>
 #include <asm/virtext.h>
 
 #ifdef CONFIG_X86_32
@@ -24,7 +25,6 @@
 
 #include <mach_ipi.h>
 
-
 /*
  * Power off function, if any
  */
@@ -501,7 +501,7 @@ void native_machine_shutdown(void)
 
 #ifdef CONFIG_X86_32
        /* See if there has been given a command line override */
-       if ((reboot_cpu != -1) && (reboot_cpu < NR_CPUS) &&
+       if ((reboot_cpu != -1) && (reboot_cpu < nr_cpu_ids) &&
                cpu_online(reboot_cpu))
                reboot_cpu_id = reboot_cpu;
 #endif
@@ -511,7 +511,7 @@ void native_machine_shutdown(void)
                reboot_cpu_id = smp_processor_id();
 
        /* Make certain I only run on the appropriate processor */
-       set_cpus_allowed_ptr(current, &cpumask_of_cpu(reboot_cpu_id));
+       set_cpus_allowed_ptr(current, cpumask_of(reboot_cpu_id));
 
        /* O.K Now that I'm on the appropriate processor,
         * stop all of the others.
index 0b63b08e75304a1da386a1686b7ed0d647541081..a4b619c3310684a124bc723526ce8809c3fa4870 100644 (file)
@@ -153,12 +153,10 @@ void __init setup_per_cpu_areas(void)
        align = max_t(unsigned long, PAGE_SIZE, align);
        size = roundup(old_size, align);
 
-       printk(KERN_INFO
-               "NR_CPUS:%d nr_cpumask_bits:%d nr_cpu_ids:%d nr_node_ids:%d\n",
+       pr_info("NR_CPUS:%d nr_cpumask_bits:%d nr_cpu_ids:%d nr_node_ids:%d\n",
                NR_CPUS, nr_cpumask_bits, nr_cpu_ids, nr_node_ids);
 
-       printk(KERN_INFO "PERCPU: Allocating %zd bytes of per cpu data\n",
-                         size);
+       pr_info("PERCPU: Allocating %zd bytes of per cpu data\n", size);
 
        for_each_possible_cpu(cpu) {
 #ifndef CONFIG_NEED_MULTIPLE_NODES
@@ -169,22 +167,15 @@ void __init setup_per_cpu_areas(void)
                if (!node_online(node) || !NODE_DATA(node)) {
                        ptr = __alloc_bootmem(size, align,
                                         __pa(MAX_DMA_ADDRESS));
-                       printk(KERN_INFO
-                              "cpu %d has no node %d or node-local memory\n",
+                       pr_info("cpu %d has no node %d or node-local memory\n",
                                cpu, node);
-                       if (ptr)
-                               printk(KERN_DEBUG
-                                       "per cpu data for cpu%d at %016lx\n",
-                                        cpu, __pa(ptr));
-               }
-               else {
+                       pr_debug("per cpu data for cpu%d at %016lx\n",
+                                cpu, __pa(ptr));
+               } else {
                        ptr = __alloc_bootmem_node(NODE_DATA(node), size, align,
                                                        __pa(MAX_DMA_ADDRESS));
-                       if (ptr)
-                               printk(KERN_DEBUG
-                                       "per cpu data for cpu%d on node%d "
-                                       "at %016lx\n",
-                                       cpu, node, __pa(ptr));
+                       pr_debug("per cpu data for cpu%d on node%d at %016lx\n",
+                               cpu, node, __pa(ptr));
                }
 #endif
                per_cpu_offset(cpu) = ptr - __per_cpu_start;
@@ -339,25 +330,25 @@ static const cpumask_t cpu_mask_none;
 /*
  * Returns a pointer to the bitmask of CPUs on Node 'node'.
  */
-const cpumask_t *_node_to_cpumask_ptr(int node)
+const cpumask_t *cpumask_of_node(int node)
 {
        if (node_to_cpumask_map == NULL) {
                printk(KERN_WARNING
-                       "_node_to_cpumask_ptr(%d): no node_to_cpumask_map!\n",
+                       "cpumask_of_node(%d): no node_to_cpumask_map!\n",
                        node);
                dump_stack();
                return (const cpumask_t *)&cpu_online_map;
        }
        if (node >= nr_node_ids) {
                printk(KERN_WARNING
-                       "_node_to_cpumask_ptr(%d): node > nr_node_ids(%d)\n",
+                       "cpumask_of_node(%d): node > nr_node_ids(%d)\n",
                        node, nr_node_ids);
                dump_stack();
                return &cpu_mask_none;
        }
        return &node_to_cpumask_map[node];
 }
-EXPORT_SYMBOL(_node_to_cpumask_ptr);
+EXPORT_SYMBOL(cpumask_of_node);
 
 /*
  * Returns a bitmask of CPUs on Node 'node'.
index 31869bf5fabd68a187fe36799a3cff7fa9b5f0a9..6bd4d9b73870965da6c3002846f144d0666b677b 100644 (file)
@@ -496,7 +496,7 @@ void __cpuinit set_cpu_sibling_map(int cpu)
 }
 
 /* maps the cpu to the sched domain representing multi-core */
-cpumask_t cpu_coregroup_map(int cpu)
+const struct cpumask *cpu_coregroup_mask(int cpu)
 {
        struct cpuinfo_x86 *c = &cpu_data(cpu);
        /*
@@ -504,9 +504,14 @@ cpumask_t cpu_coregroup_map(int cpu)
         * And for power savings, we return cpu_core_map
         */
        if (sched_mc_power_savings || sched_smt_power_savings)
-               return per_cpu(cpu_core_map, cpu);
+               return &per_cpu(cpu_core_map, cpu);
        else
-               return c->llc_shared_map;
+               return &c->llc_shared_map;
+}
+
+cpumask_t cpu_coregroup_map(int cpu)
+{
+       return *cpu_coregroup_mask(cpu);
 }
 
 static void impress_friends(void)
@@ -1149,7 +1154,7 @@ static void __init smp_cpu_index_default(void)
        for_each_possible_cpu(i) {
                c = &cpu_data(i);
                /* mark all to hotplug */
-               c->cpu_index = NR_CPUS;
+               c->cpu_index = nr_cpu_ids;
        }
 }
 
@@ -1293,6 +1298,8 @@ __init void prefill_possible_map(void)
        else
                possible = setup_possible_cpus;
 
+       total_cpus = max_t(int, possible, num_processors + disabled_cpus);
+
        if (possible > CONFIG_NR_CPUS) {
                printk(KERN_WARNING
                        "%d Processors exceeds NR_CPUS limit of %d\n",
index 6a00e5faaa74375d5b709488a0b9c371c3fe5c79..f885023167e042073cc3f37721cb7a0d3e1b2941 100644 (file)
@@ -582,7 +582,6 @@ static int __init uv_ptc_init(void)
 static struct bau_control * __init uv_table_bases_init(int blade, int node)
 {
        int i;
-       int *ip;
        struct bau_msg_status *msp;
        struct bau_control *bau_tabp;
 
@@ -599,13 +598,6 @@ static struct bau_control * __init uv_table_bases_init(int blade, int node)
                bau_cpubits_clear(&msp->seen_by, (int)
                                  uv_blade_nr_possible_cpus(blade));
 
-       bau_tabp->watching =
-           kmalloc_node(sizeof(int) * DEST_NUM_RESOURCES, GFP_KERNEL, node);
-       BUG_ON(!bau_tabp->watching);
-
-       for (i = 0, ip = bau_tabp->watching; i < DEST_Q_SIZE; i++, ip++)
-               *ip = 0;
-
        uv_bau_table_bases[blade] = bau_tabp;
 
        return bau_tabp;
@@ -628,7 +620,6 @@ uv_table_bases_finish(int blade, int node, int cur_cpu,
                bcp->bau_msg_head       = bau_tablesp->va_queue_first;
                bcp->va_queue_first     = bau_tablesp->va_queue_first;
                bcp->va_queue_last      = bau_tablesp->va_queue_last;
-               bcp->watching           = bau_tablesp->watching;
                bcp->msg_statuses       = bau_tablesp->msg_statuses;
                bcp->descriptor_base    = adp;
        }
index 2d1f4c7e40524ba7c3d0847583f0b5041ccdba30..ce6650eb64e976e120cbefa87adae9b4675e94ed 100644 (file)
@@ -292,8 +292,10 @@ dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code)
        tsk->thread.error_code = error_code;
        tsk->thread.trap_no = 8;
 
-       /* This is always a kernel trap and never fixable (and thus must
-          never return). */
+       /*
+        * This is always a kernel trap and never fixable (and thus must
+        * never return).
+        */
        for (;;)
                die(str, regs, error_code);
 }
@@ -520,9 +522,11 @@ dotraplinkage void __kprobes do_int3(struct pt_regs *regs, long error_code)
 }
 
 #ifdef CONFIG_X86_64
-/* Help handler running on IST stack to switch back to user stack
-   for scheduling or signal handling. The actual stack switch is done in
-   entry.S */
+/*
+ * Help handler running on IST stack to switch back to user stack
+ * for scheduling or signal handling. The actual stack switch is done in
+ * entry.S
+ */
 asmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs)
 {
        struct pt_regs *regs = eregs;
@@ -532,8 +536,10 @@ asmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs)
        /* Exception from user space */
        else if (user_mode(eregs))
                regs = task_pt_regs(current);
-       /* Exception from kernel and interrupts are enabled. Move to
-          kernel process stack. */
+       /*
+        * Exception from kernel and interrupts are enabled. Move to
+        * kernel process stack.
+        */
        else if (eregs->flags & X86_EFLAGS_IF)
                regs = (struct pt_regs *)(eregs->sp -= sizeof(struct pt_regs));
        if (eregs != regs)
@@ -685,12 +691,7 @@ void math_error(void __user *ip)
        cwd = get_fpu_cwd(task);
        swd = get_fpu_swd(task);
 
-       err = swd & ~cwd & 0x3f;
-
-#ifdef CONFIG_X86_32
-       if (!err)
-               return;
-#endif
+       err = swd & ~cwd;
 
        if (err & 0x001) {      /* Invalid op */
                /*
@@ -708,7 +709,11 @@ void math_error(void __user *ip)
        } else if (err & 0x020) { /* Precision */
                info.si_code = FPE_FLTRES;
        } else {
-               info.si_code = __SI_FAULT|SI_KERNEL; /* WTF? */
+               /*
+                * If we're using IRQ 13, or supposedly even some trap 16
+                * implementations, it's possible we get a spurious trap...
+                */
+               return;         /* Spurious trap, no error */
        }
        force_sig_info(SIGFPE, &info, task);
 }
index 15c3e699918221487429508113173f692794a943..2b54fe002e94e490db9a0e8ec3d4b89ec76524ab 100644 (file)
@@ -159,7 +159,7 @@ int save_i387_xstate(void __user *buf)
  * Restore the extended state if present. Otherwise, restore the FP/SSE
  * state.
  */
-int restore_user_xstate(void __user *buf)
+static int restore_user_xstate(void __user *buf)
 {
        struct _fpx_sw_bytes fx_sw_user;
        u64 mask;
index c02343594b4de95bb79ce31bf78de03fb48ed636..d3ec292f00f248e9d41e67813775f1867de8b0a5 100644 (file)
@@ -7,8 +7,8 @@ common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o ioapic.o \
 ifeq ($(CONFIG_KVM_TRACE),y)
 common-objs += $(addprefix ../../../virt/kvm/, kvm_trace.o)
 endif
-ifeq ($(CONFIG_DMAR),y)
-common-objs += $(addprefix ../../../virt/kvm/, vtd.o)
+ifeq ($(CONFIG_IOMMU_API),y)
+common-objs += $(addprefix ../../../virt/kvm/, iommu.o)
 endif
 
 EXTRA_CFLAGS += -Ivirt/kvm -Iarch/x86/kvm
index 0e6aa8141dcd936e860b4576c9e0af28d380d49c..cc17546a2406af860329ea28d1ae85b7ebb4aa23 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/module.h>
 #include <linux/mman.h>
 #include <linux/highmem.h>
+#include <linux/iommu.h>
 #include <linux/intel-iommu.h>
 
 #include <asm/uaccess.h>
@@ -989,7 +990,7 @@ int kvm_dev_ioctl_check_extension(long ext)
                r = !tdp_enabled;
                break;
        case KVM_CAP_IOMMU:
-               r = intel_iommu_found();
+               r = iommu_found();
                break;
        default:
                r = 0;
index 37b9ae4d44c5b755470cb3661328b073e951b068..df167f2656228c83eb58ce2ebd4600074d766e77 100644 (file)
@@ -133,29 +133,28 @@ void __init time_init_hook(void)
  **/
 void mca_nmi_hook(void)
 {
-       /* If I recall correctly, there's a whole bunch of other things that
+       /*
+        * If I recall correctly, there's a whole bunch of other things that
         * we can do to check for NMI problems, but that's all I know about
         * at the moment.
         */
-
-       printk("NMI generated from unknown source!\n");
+       pr_warning("NMI generated from unknown source!\n");
 }
 #endif
 
 static __init int no_ipi_broadcast(char *str)
 {
        get_option(&str, &no_broadcast);
-       printk ("Using %s mode\n", no_broadcast ? "No IPI Broadcast" :
-                                                                                       "IPI Broadcast");
+       pr_info("Using %s mode\n",
+               no_broadcast ? "No IPI Broadcast" : "IPI Broadcast");
        return 1;
 }
-
 __setup("no_ipi_broadcast=", no_ipi_broadcast);
 
 static int __init print_ipi_mode(void)
 {
-       printk ("Using IPI %s mode\n", no_broadcast ? "No-Shortcut" :
-                                                                                       "Shortcut");
+       pr_info("Using IPI %s mode\n",
+               no_broadcast ? "No-Shortcut" : "Shortcut");
        return 0;
 }
 
index a5bc05492b1ee17c3cdfc04894cfe706047ef4f7..9840b7ec749a00dfc7a906e8a9045b76d545650d 100644 (file)
@@ -357,9 +357,8 @@ void __init find_smp_config(void)
        printk("VOYAGER SMP: Boot cpu is %d\n", boot_cpu_id);
 
        /* initialize the CPU structures (moved from smp_boot_cpus) */
-       for (i = 0; i < NR_CPUS; i++) {
+       for (i = 0; i < nr_cpu_ids; i++)
                cpu_irq_affinity[i] = ~0;
-       }
        cpu_online_map = cpumask_of_cpu(boot_cpu_id);
 
        /* The boot CPU must be extended */
@@ -1227,7 +1226,7 @@ int setup_profiling_timer(unsigned int multiplier)
         * new values until the next timer interrupt in which they do process
         * accounting.
         */
-       for (i = 0; i < NR_CPUS; ++i)
+       for (i = 0; i < nr_cpu_ids; ++i)
                per_cpu(prof_multiplier, i) = multiplier;
 
        return 0;
@@ -1257,7 +1256,7 @@ void __init voyager_smp_intr_init(void)
        int i;
 
        /* initialize the per cpu irq mask to all disabled */
-       for (i = 0; i < NR_CPUS; i++)
+       for (i = 0; i < nr_cpu_ids; i++)
                vic_irq_mask[i] = 0xFFFF;
 
        VIC_SET_GATE(VIC_CPI_LEVEL0, vic_cpi_interrupt);
index 1d88d2b39771e2a89e0cb4ac53e98886354f4956..9e5752fe4d153d3c3a472b392363846f0de3a51a 100644 (file)
@@ -4,7 +4,7 @@
 #include <linux/irq.h>
 #include <linux/dmi.h>
 #include <asm/numa.h>
-#include "pci.h"
+#include <asm/pci_x86.h>
 
 struct pci_root_info {
        char *name;
index 22e057665e5517971a67b84a0e60e2ffe87ad151..9bb09823b3622410542753309cd3f546e207f923 100644 (file)
@@ -2,7 +2,7 @@
 #include <linux/pci.h>
 #include <linux/topology.h>
 #include <linux/cpu.h>
-#include "pci.h"
+#include <asm/pci_x86.h>
 
 #ifdef CONFIG_X86_64
 #include <asm/pci-direct.h>
index bb1a01f089e29c817432907a820ca7a06f727347..62ddb73e09ed5767affbc3f1657a25ff67a3912e 100644 (file)
@@ -14,8 +14,7 @@
 #include <asm/segment.h>
 #include <asm/io.h>
 #include <asm/smp.h>
-
-#include "pci.h"
+#include <asm/pci_x86.h>
 
 unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 |
                                PCI_PROBE_MMCONF;
index 9a5af6c8fbe9fc445fdca3358b90666c9ecae7bb..bd13c3e4c6db6687f8336d1471575fea006d6728 100644 (file)
@@ -5,7 +5,7 @@
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/dmi.h>
-#include "pci.h"
+#include <asm/pci_x86.h>
 
 /*
  * Functions for accessing PCI base (first 256 bytes) and extended
index 86631ccbc25a6f7e9975f0c3f4999e6d022d84b6..f6adf2c6d7514148eb7e6221dea010f55158f97d 100644 (file)
@@ -2,7 +2,7 @@
 #include <linux/pci.h>
 #include <asm/pci-direct.h>
 #include <asm/io.h>
-#include "pci.h"
+#include <asm/pci_x86.h>
 
 /* Direct PCI access. This is used for PCI accesses in early boot before
    the PCI subsystem works. */
index 2051dc96b8e94aee2b63af14d3d2a8a9486cfdcd..7d388d5cf54852136da06d0ca08b04c646fc7199 100644 (file)
@@ -6,8 +6,7 @@
 #include <linux/dmi.h>
 #include <linux/pci.h>
 #include <linux/init.h>
-#include "pci.h"
-
+#include <asm/pci_x86.h>
 
 static void __devinit pci_fixup_i450nx(struct pci_dev *d)
 {
index 844df0cbbd3e011784531ddb6e6ff1a06e7ec83c..e51bf2cda4b0279fbf1502dfadbe9eb4ba9bbe2f 100644 (file)
@@ -34,8 +34,8 @@
 
 #include <asm/pat.h>
 #include <asm/e820.h>
+#include <asm/pci_x86.h>
 
-#include "pci.h"
 
 static int
 skip_isa_ioresource_align(struct pci_dev *dev) {
index d6c950f818585aea6df65e38e18c2f85ab217941..bec3b048e72b6b0148efad321b6c24279b73e8df 100644 (file)
@@ -1,6 +1,6 @@
 #include <linux/pci.h>
 #include <linux/init.h>
-#include "pci.h"
+#include <asm/pci_x86.h>
 
 /* arch_initcall has too random ordering, so call the initializers
    in the right sequence from here. */
index bf69dbe08bff66b19b8e9a7558d152fd4fce62f7..373b9afe6d4445b08efee66dfb4856519b434bd1 100644 (file)
@@ -16,8 +16,7 @@
 #include <asm/io_apic.h>
 #include <linux/irq.h>
 #include <linux/acpi.h>
-
-#include "pci.h"
+#include <asm/pci_x86.h>
 
 #define PIRQ_SIGNATURE (('$' << 0) + ('P' << 8) + ('I' << 16) + ('R' << 24))
 #define PIRQ_VERSION 0x0100
index b722dd481b3975b2b9b171203a42f6406b9cafed..f1065b129e9cf981fa52c374dcf3bf2c4987fe36 100644 (file)
@@ -3,7 +3,7 @@
  */
 #include <linux/init.h>
 #include <linux/pci.h>
-#include "pci.h"
+#include <asm/pci_x86.h>
 
 /*
  * Discover remaining PCI buses in case there are peer host bridges.
index 654a2234f8f3ba8adbcba6e644c7b7d4935488bc..89bf9242c80a3b068fa2c1fcf3f6cba4b447193d 100644 (file)
@@ -15,8 +15,7 @@
 #include <linux/acpi.h>
 #include <linux/bitmap.h>
 #include <asm/e820.h>
-
-#include "pci.h"
+#include <asm/pci_x86.h>
 
 /* aperture is up to 256MB but BIOS may reserve less */
 #define MMCONFIG_APER_MIN      (2 * 1024*1024)
index f3c761dce6957118494ff8f2492edae9c7d9e651..8b2d561046a3bba83ef3953171fb1abdd5a195b5 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/init.h>
 #include <linux/acpi.h>
 #include <asm/e820.h>
-#include "pci.h"
+#include <asm/pci_x86.h>
 
 /* Assume systems with more busses have correct MCFG */
 #define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG))
index a1994163c99dd328e3c542d1bc0f5dd246e583cf..30007ffc8e11d203922d2c8304c5d0bdb909ef33 100644 (file)
@@ -10,8 +10,7 @@
 #include <linux/acpi.h>
 #include <linux/bitmap.h>
 #include <asm/e820.h>
-
-#include "pci.h"
+#include <asm/pci_x86.h>
 
 /* Static virtual mapping of the MMCONFIG aperture */
 struct mmcfg_virt {
index 1177845d31863602e9bf0dbf8bc4e031db3f6487..2089354968a21f67ed3fe59e1e1cf26e777a1095 100644 (file)
@@ -7,7 +7,7 @@
 #include <linux/nodemask.h>
 #include <mach_apic.h>
 #include <asm/mpspec.h>
-#include "pci.h"
+#include <asm/pci_x86.h>
 
 #define XQUAD_PORTIO_BASE 0xfe400000
 #define XQUAD_PORTIO_QUAD 0x40000  /* 256k per quad. */
index e11e9e803d5fd2acd8135d73e2f07c33c6684b99..b889d824f7c6aee4eba1a54ba0404609c3d8fbd5 100644 (file)
@@ -29,7 +29,7 @@
 #include <linux/init.h>
 #include <asm/olpc.h>
 #include <asm/geode.h>
-#include "pci.h"
+#include <asm/pci_x86.h>
 
 /*
  * In the tables below, the first two line (8 longwords) are the
index 37472fc6f72949b2d54910702962f7361e12bed6..b82cae970dfd6d1d2dc9d5bbef3801841f57d1a8 100644 (file)
@@ -6,9 +6,8 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/uaccess.h>
-#include "pci.h"
-#include "pci-functions.h"
-
+#include <asm/pci_x86.h>
+#include <asm/mach-default/pci-functions.h>
 
 /* BIOS32 signature: "_32_" */
 #define BIOS32_SIGNATURE       (('_' << 0) + ('3' << 8) + ('2' << 16) + ('_' << 24))
index 42f4cb19facab8a47b70c85fcfd819cb086ade3b..16d0c0eb0d19670692aedf958a05b381ee47b7c1 100644 (file)
@@ -9,11 +9,10 @@
 #include <linux/init.h>
 
 #include <asm/setup.h>
+#include <asm/pci_x86.h>
 #include <asm/visws/cobalt.h>
 #include <asm/visws/lithium.h>
 
-#include "pci.h"
-
 static int pci_visws_enable_irq(struct pci_dev *dev) { return 0; }
 static void pci_visws_disable_irq(struct pci_dev *dev) { }
 
index 65d75a6be0ba586eeaf22faffd466b1ec109eb5d..14f24062349752a268a7584efcc538431c371152 100644 (file)
@@ -132,8 +132,7 @@ static void do_stolen_accounting(void)
        *snap = state;
 
        /* Add the appropriate number of ticks of stolen time,
-          including any left-overs from last time.  Passing NULL to
-          account_steal_time accounts the time as stolen. */
+          including any left-overs from last time. */
        stolen = runnable + offline + __get_cpu_var(residual_stolen);
 
        if (stolen < 0)
@@ -141,11 +140,10 @@ static void do_stolen_accounting(void)
 
        ticks = iter_div_u64_rem(stolen, NS_PER_TICK, &stolen);
        __get_cpu_var(residual_stolen) = stolen;
-       account_steal_time(NULL, ticks);
+       account_steal_ticks(ticks);
 
        /* Add the appropriate number of ticks of blocked time,
-          including any left-overs from last time.  Passing idle to
-          account_steal_time accounts the time as idle/wait. */
+          including any left-overs from last time. */
        blocked += __get_cpu_var(residual_blocked);
 
        if (blocked < 0)
@@ -153,7 +151,7 @@ static void do_stolen_accounting(void)
 
        ticks = iter_div_u64_rem(blocked, NS_PER_TICK, &blocked);
        __get_cpu_var(residual_blocked) = blocked;
-       account_steal_time(idle_task(smp_processor_id()), ticks);
+       account_idle_ticks(ticks);
 }
 
 /*
index d2e49af90db548ffa68e950bd800a48fdde79a1d..6e1ed40534e97e78ff0263268b2826344f2207b7 100644 (file)
@@ -99,8 +99,8 @@ static inline int queue_congestion_off_threshold(struct request_queue *q)
 static inline int blk_cpu_to_group(int cpu)
 {
 #ifdef CONFIG_SCHED_MC
-       cpumask_t mask = cpu_coregroup_map(cpu);
-       return first_cpu(mask);
+       const struct cpumask *mask = cpu_coregroup_mask(cpu);
+       return cpumask_first(mask);
 #elif defined(CONFIG_SCHED_SMT)
        return first_cpu(per_cpu(cpu_sibling_map, cpu));
 #else
index 34948362f41d0f820880b6ef723f783487b7e800..0cc2fd31e3765f7c9b945460345533dfebf1424b 100644 (file)
@@ -826,6 +826,11 @@ static int acpi_processor_add(struct acpi_device *device)
        if (!pr)
                return -ENOMEM;
 
+       if (!alloc_cpumask_var(&pr->throttling.shared_cpu_map, GFP_KERNEL)) {
+               kfree(pr);
+               return -ENOMEM;
+       }
+
        pr->handle = device->handle;
        strcpy(acpi_device_name(device), ACPI_PROCESSOR_DEVICE_NAME);
        strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS);
@@ -845,10 +850,8 @@ static int acpi_processor_remove(struct acpi_device *device, int type)
 
        pr = acpi_driver_data(device);
 
-       if (pr->id >= nr_cpu_ids) {
-               kfree(pr);
-               return 0;
-       }
+       if (pr->id >= nr_cpu_ids)
+               goto free;
 
        if (type == ACPI_BUS_REMOVAL_EJECT) {
                if (acpi_processor_handle_eject(pr))
@@ -873,6 +876,9 @@ static int acpi_processor_remove(struct acpi_device *device, int type)
 
        per_cpu(processors, pr->id) = NULL;
        per_cpu(processor_device_array, pr->id) = NULL;
+
+free:
+       free_cpumask_var(pr->throttling.shared_cpu_map);
        kfree(pr);
 
        return 0;
index 0d7b772bef50269545b0cf602f72958d9fdf4c23..846e227592d48770787672223a4c37c37ec6468c 100644 (file)
@@ -588,12 +588,15 @@ int acpi_processor_preregister_performance(
        int count, count_target;
        int retval = 0;
        unsigned int i, j;
-       cpumask_t covered_cpus;
+       cpumask_var_t covered_cpus;
        struct acpi_processor *pr;
        struct acpi_psd_package *pdomain;
        struct acpi_processor *match_pr;
        struct acpi_psd_package *match_pdomain;
 
+       if (!alloc_cpumask_var(&covered_cpus, GFP_KERNEL))
+               return -ENOMEM;
+
        mutex_lock(&performance_mutex);
 
        retval = 0;
@@ -617,7 +620,7 @@ int acpi_processor_preregister_performance(
                }
 
                pr->performance = percpu_ptr(performance, i);
-               cpu_set(i, pr->performance->shared_cpu_map);
+               cpumask_set_cpu(i, pr->performance->shared_cpu_map);
                if (acpi_processor_get_psd(pr)) {
                        retval = -EINVAL;
                        continue;
@@ -650,18 +653,18 @@ int acpi_processor_preregister_performance(
                }
        }
 
-       cpus_clear(covered_cpus);
+       cpumask_clear(covered_cpus);
        for_each_possible_cpu(i) {
                pr = per_cpu(processors, i);
                if (!pr)
                        continue;
 
-               if (cpu_isset(i, covered_cpus))
+               if (cpumask_test_cpu(i, covered_cpus))
                        continue;
 
                pdomain = &(pr->performance->domain_info);
-               cpu_set(i, pr->performance->shared_cpu_map);
-               cpu_set(i, covered_cpus);
+               cpumask_set_cpu(i, pr->performance->shared_cpu_map);
+               cpumask_set_cpu(i, covered_cpus);
                if (pdomain->num_processors <= 1)
                        continue;
 
@@ -699,8 +702,8 @@ int acpi_processor_preregister_performance(
                                goto err_ret;
                        }
 
-                       cpu_set(j, covered_cpus);
-                       cpu_set(j, pr->performance->shared_cpu_map);
+                       cpumask_set_cpu(j, covered_cpus);
+                       cpumask_set_cpu(j, pr->performance->shared_cpu_map);
                        count++;
                }
 
@@ -718,8 +721,8 @@ int acpi_processor_preregister_performance(
 
                        match_pr->performance->shared_type = 
                                        pr->performance->shared_type;
-                       match_pr->performance->shared_cpu_map =
-                               pr->performance->shared_cpu_map;
+                       cpumask_copy(match_pr->performance->shared_cpu_map,
+                                    pr->performance->shared_cpu_map);
                }
        }
 
@@ -731,14 +734,15 @@ err_ret:
 
                /* Assume no coordination on any error parsing domain info */
                if (retval) {
-                       cpus_clear(pr->performance->shared_cpu_map);
-                       cpu_set(i, pr->performance->shared_cpu_map);
+                       cpumask_clear(pr->performance->shared_cpu_map);
+                       cpumask_set_cpu(i, pr->performance->shared_cpu_map);
                        pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ALL;
                }
                pr->performance = NULL; /* Will be set for real in register */
        }
 
        mutex_unlock(&performance_mutex);
+       free_cpumask_var(covered_cpus);
        return retval;
 }
 EXPORT_SYMBOL(acpi_processor_preregister_performance);
index a0c38c94a8a08d0ace6d8b5b05bc2c4caf671965..d27838171f4ad2b48dcfc916a1c2cc31e92b721f 100644 (file)
@@ -61,11 +61,14 @@ static int acpi_processor_update_tsd_coord(void)
        int count, count_target;
        int retval = 0;
        unsigned int i, j;
-       cpumask_t covered_cpus;
+       cpumask_var_t covered_cpus;
        struct acpi_processor *pr, *match_pr;
        struct acpi_tsd_package *pdomain, *match_pdomain;
        struct acpi_processor_throttling *pthrottling, *match_pthrottling;
 
+       if (!alloc_cpumask_var(&covered_cpus, GFP_KERNEL))
+               return -ENOMEM;
+
        /*
         * Now that we have _TSD data from all CPUs, lets setup T-state
         * coordination between all CPUs.
@@ -91,19 +94,19 @@ static int acpi_processor_update_tsd_coord(void)
        if (retval)
                goto err_ret;
 
-       cpus_clear(covered_cpus);
+       cpumask_clear(covered_cpus);
        for_each_possible_cpu(i) {
                pr = per_cpu(processors, i);
                if (!pr)
                        continue;
 
-               if (cpu_isset(i, covered_cpus))
+               if (cpumask_test_cpu(i, covered_cpus))
                        continue;
                pthrottling = &pr->throttling;
 
                pdomain = &(pthrottling->domain_info);
-               cpu_set(i, pthrottling->shared_cpu_map);
-               cpu_set(i, covered_cpus);
+               cpumask_set_cpu(i, pthrottling->shared_cpu_map);
+               cpumask_set_cpu(i, covered_cpus);
                /*
                 * If the number of processor in the TSD domain is 1, it is
                 * unnecessary to parse the coordination for this CPU.
@@ -144,8 +147,8 @@ static int acpi_processor_update_tsd_coord(void)
                                goto err_ret;
                        }
 
-                       cpu_set(j, covered_cpus);
-                       cpu_set(j, pthrottling->shared_cpu_map);
+                       cpumask_set_cpu(j, covered_cpus);
+                       cpumask_set_cpu(j, pthrottling->shared_cpu_map);
                        count++;
                }
                for_each_possible_cpu(j) {
@@ -165,12 +168,14 @@ static int acpi_processor_update_tsd_coord(void)
                         * If some CPUS have the same domain, they
                         * will have the same shared_cpu_map.
                         */
-                       match_pthrottling->shared_cpu_map =
-                               pthrottling->shared_cpu_map;
+                       cpumask_copy(match_pthrottling->shared_cpu_map,
+                                    pthrottling->shared_cpu_map);
                }
        }
 
 err_ret:
+       free_cpumask_var(covered_cpus);
+
        for_each_possible_cpu(i) {
                pr = per_cpu(processors, i);
                if (!pr)
@@ -182,8 +187,8 @@ err_ret:
                 */
                if (retval) {
                        pthrottling = &(pr->throttling);
-                       cpus_clear(pthrottling->shared_cpu_map);
-                       cpu_set(i, pthrottling->shared_cpu_map);
+                       cpumask_clear(pthrottling->shared_cpu_map);
+                       cpumask_set_cpu(i, pthrottling->shared_cpu_map);
                        pthrottling->shared_type = DOMAIN_COORD_TYPE_SW_ALL;
                }
        }
@@ -567,7 +572,7 @@ static int acpi_processor_get_tsd(struct acpi_processor *pr)
        pthrottling = &pr->throttling;
        pthrottling->tsd_valid_flag = 1;
        pthrottling->shared_type = pdomain->coord_type;
-       cpu_set(pr->id, pthrottling->shared_cpu_map);
+       cpumask_set_cpu(pr->id, pthrottling->shared_cpu_map);
        /*
         * If the coordination type is not defined in ACPI spec,
         * the tsd_valid_flag will be clear and coordination type
@@ -826,7 +831,7 @@ static int acpi_processor_get_throttling_ptc(struct acpi_processor *pr)
 
 static int acpi_processor_get_throttling(struct acpi_processor *pr)
 {
-       cpumask_t saved_mask;
+       cpumask_var_t saved_mask;
        int ret;
 
        if (!pr)
@@ -834,14 +839,20 @@ static int acpi_processor_get_throttling(struct acpi_processor *pr)
 
        if (!pr->flags.throttling)
                return -ENODEV;
+
+       if (!alloc_cpumask_var(&saved_mask, GFP_KERNEL))
+               return -ENOMEM;
+
        /*
         * Migrate task to the cpu pointed by pr.
         */
-       saved_mask = current->cpus_allowed;
-       set_cpus_allowed_ptr(current, &cpumask_of_cpu(pr->id));
+       cpumask_copy(saved_mask, &current->cpus_allowed);
+       /* FIXME: use work_on_cpu() */
+       set_cpus_allowed_ptr(current, cpumask_of(pr->id));
        ret = pr->throttling.acpi_processor_get_throttling(pr);
        /* restore the previous state */
-       set_cpus_allowed_ptr(current, &saved_mask);
+       set_cpus_allowed_ptr(current, saved_mask);
+       free_cpumask_var(saved_mask);
 
        return ret;
 }
@@ -986,13 +997,13 @@ static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr,
 
 int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
 {
-       cpumask_t saved_mask;
+       cpumask_var_t saved_mask;
        int ret = 0;
        unsigned int i;
        struct acpi_processor *match_pr;
        struct acpi_processor_throttling *p_throttling;
        struct throttling_tstate t_state;
-       cpumask_t online_throttling_cpus;
+       cpumask_var_t online_throttling_cpus;
 
        if (!pr)
                return -EINVAL;
@@ -1003,17 +1014,25 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
        if ((state < 0) || (state > (pr->throttling.state_count - 1)))
                return -EINVAL;
 
-       saved_mask = current->cpus_allowed;
+       if (!alloc_cpumask_var(&saved_mask, GFP_KERNEL))
+               return -ENOMEM;
+
+       if (!alloc_cpumask_var(&online_throttling_cpus, GFP_KERNEL)) {
+               free_cpumask_var(saved_mask);
+               return -ENOMEM;
+       }
+
+       cpumask_copy(saved_mask, &current->cpus_allowed);
        t_state.target_state = state;
        p_throttling = &(pr->throttling);
-       cpus_and(online_throttling_cpus, cpu_online_map,
-                       p_throttling->shared_cpu_map);
+       cpumask_and(online_throttling_cpus, cpu_online_mask,
+                   p_throttling->shared_cpu_map);
        /*
         * The throttling notifier will be called for every
         * affected cpu in order to get one proper T-state.
         * The notifier event is THROTTLING_PRECHANGE.
         */
-       for_each_cpu_mask_nr(i, online_throttling_cpus) {
+       for_each_cpu(i, online_throttling_cpus) {
                t_state.cpu = i;
                acpi_processor_throttling_notifier(THROTTLING_PRECHANGE,
                                                        &t_state);
@@ -1025,7 +1044,8 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
         * it can be called only for the cpu pointed by pr.
         */
        if (p_throttling->shared_type == DOMAIN_COORD_TYPE_SW_ANY) {
-               set_cpus_allowed_ptr(current, &cpumask_of_cpu(pr->id));
+               /* FIXME: use work_on_cpu() */
+               set_cpus_allowed_ptr(current, cpumask_of(pr->id));
                ret = p_throttling->acpi_processor_set_throttling(pr,
                                                t_state.target_state);
        } else {
@@ -1034,7 +1054,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
                 * it is necessary to set T-state for every affected
                 * cpus.
                 */
-               for_each_cpu_mask_nr(i, online_throttling_cpus) {
+               for_each_cpu(i, online_throttling_cpus) {
                        match_pr = per_cpu(processors, i);
                        /*
                         * If the pointer is invalid, we will report the
@@ -1056,7 +1076,8 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
                                continue;
                        }
                        t_state.cpu = i;
-                       set_cpus_allowed_ptr(current, &cpumask_of_cpu(i));
+                       /* FIXME: use work_on_cpu() */
+                       set_cpus_allowed_ptr(current, cpumask_of(i));
                        ret = match_pr->throttling.
                                acpi_processor_set_throttling(
                                match_pr, t_state.target_state);
@@ -1068,13 +1089,16 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
         * affected cpu to update the T-states.
         * The notifier event is THROTTLING_POSTCHANGE
         */
-       for_each_cpu_mask_nr(i, online_throttling_cpus) {
+       for_each_cpu(i, online_throttling_cpus) {
                t_state.cpu = i;
                acpi_processor_throttling_notifier(THROTTLING_POSTCHANGE,
                                                        &t_state);
        }
        /* restore the previous state */
-       set_cpus_allowed_ptr(current, &saved_mask);
+       /* FIXME: use work_on_cpu() */
+       set_cpus_allowed_ptr(current, saved_mask);
+       free_cpumask_var(online_throttling_cpus);
+       free_cpumask_var(saved_mask);
        return ret;
 }
 
@@ -1120,7 +1144,7 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr)
        if (acpi_processor_get_tsd(pr)) {
                pthrottling = &pr->throttling;
                pthrottling->tsd_valid_flag = 0;
-               cpu_set(pr->id, pthrottling->shared_cpu_map);
+               cpumask_set_cpu(pr->id, pthrottling->shared_cpu_map);
                pthrottling->shared_type = DOMAIN_COORD_TYPE_SW_ALL;
        }
 
index c66637392bbc71756731941a50253240d0da3b9a..b5b8ba512b282028afd61dbf32892ba4018e862d 100644 (file)
@@ -11,6 +11,7 @@ obj-$(CONFIG_FW_LOADER)       += firmware_class.o
 obj-$(CONFIG_NUMA)     += node.o
 obj-$(CONFIG_MEMORY_HOTPLUG_SPARSE) += memory.o
 obj-$(CONFIG_SMP)      += topology.o
+obj-$(CONFIG_IOMMU_API) += iommu.o
 ifeq ($(CONFIG_SYSFS),y)
 obj-$(CONFIG_MODULES)  += module.o
 endif
index 4259072f5bd0960e113bb97d0f8aaa1818a8ab58..719ee5c1c8d94d97bfb4841ee9e82c1f9760ffda 100644 (file)
@@ -128,10 +128,54 @@ print_cpus_func(online);
 print_cpus_func(possible);
 print_cpus_func(present);
 
+/*
+ * Print values for NR_CPUS and offlined cpus
+ */
+static ssize_t print_cpus_kernel_max(struct sysdev_class *class, char *buf)
+{
+       int n = snprintf(buf, PAGE_SIZE-2, "%d\n", NR_CPUS - 1);
+       return n;
+}
+static SYSDEV_CLASS_ATTR(kernel_max, 0444, print_cpus_kernel_max, NULL);
+
+/* arch-optional setting to enable display of offline cpus >= nr_cpu_ids */
+unsigned int total_cpus;
+
+static ssize_t print_cpus_offline(struct sysdev_class *class, char *buf)
+{
+       int n = 0, len = PAGE_SIZE-2;
+       cpumask_var_t offline;
+
+       /* display offline cpus < nr_cpu_ids */
+       if (!alloc_cpumask_var(&offline, GFP_KERNEL))
+               return -ENOMEM;
+       cpumask_complement(offline, cpu_online_mask);
+       n = cpulist_scnprintf(buf, len, offline);
+       free_cpumask_var(offline);
+
+       /* display offline cpus >= nr_cpu_ids */
+       if (total_cpus && nr_cpu_ids < total_cpus) {
+               if (n && n < len)
+                       buf[n++] = ',';
+
+               if (nr_cpu_ids == total_cpus-1)
+                       n += snprintf(&buf[n], len - n, "%d", nr_cpu_ids);
+               else
+                       n += snprintf(&buf[n], len - n, "%d-%d",
+                                                     nr_cpu_ids, total_cpus-1);
+       }
+
+       n += snprintf(&buf[n], len - n, "\n");
+       return n;
+}
+static SYSDEV_CLASS_ATTR(offline, 0444, print_cpus_offline, NULL);
+
 static struct sysdev_class_attribute *cpu_state_attr[] = {
        &attr_online_map,
        &attr_possible_map,
        &attr_present_map,
+       &attr_kernel_max,
+       &attr_offline,
 };
 
 static int cpu_states_init(void)
diff --git a/drivers/base/iommu.c b/drivers/base/iommu.c
new file mode 100644 (file)
index 0000000..5e039d4
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2007-2008 Advanced Micro Devices, Inc.
+ * Author: Joerg Roedel <joerg.roedel@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <linux/bug.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/iommu.h>
+
+static struct iommu_ops *iommu_ops;
+
+void register_iommu(struct iommu_ops *ops)
+{
+       if (iommu_ops)
+               BUG();
+
+       iommu_ops = ops;
+}
+
+bool iommu_found()
+{
+       return iommu_ops != NULL;
+}
+EXPORT_SYMBOL_GPL(iommu_found);
+
+struct iommu_domain *iommu_domain_alloc(void)
+{
+       struct iommu_domain *domain;
+       int ret;
+
+       domain = kmalloc(sizeof(*domain), GFP_KERNEL);
+       if (!domain)
+               return NULL;
+
+       ret = iommu_ops->domain_init(domain);
+       if (ret)
+               goto out_free;
+
+       return domain;
+
+out_free:
+       kfree(domain);
+
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(iommu_domain_alloc);
+
+void iommu_domain_free(struct iommu_domain *domain)
+{
+       iommu_ops->domain_destroy(domain);
+       kfree(domain);
+}
+EXPORT_SYMBOL_GPL(iommu_domain_free);
+
+int iommu_attach_device(struct iommu_domain *domain, struct device *dev)
+{
+       return iommu_ops->attach_dev(domain, dev);
+}
+EXPORT_SYMBOL_GPL(iommu_attach_device);
+
+void iommu_detach_device(struct iommu_domain *domain, struct device *dev)
+{
+       iommu_ops->detach_dev(domain, dev);
+}
+EXPORT_SYMBOL_GPL(iommu_detach_device);
+
+int iommu_map_range(struct iommu_domain *domain, unsigned long iova,
+                   phys_addr_t paddr, size_t size, int prot)
+{
+       return iommu_ops->map(domain, iova, paddr, size, prot);
+}
+EXPORT_SYMBOL_GPL(iommu_map_range);
+
+void iommu_unmap_range(struct iommu_domain *domain, unsigned long iova,
+                     size_t size)
+{
+       iommu_ops->unmap(domain, iova, size);
+}
+EXPORT_SYMBOL_GPL(iommu_unmap_range);
+
+phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain,
+                              unsigned long iova)
+{
+       return iommu_ops->iova_to_phys(domain, iova);
+}
+EXPORT_SYMBOL_GPL(iommu_iova_to_phys);
index d26891bfcd4154effba426421322ed053acb9d9b..c7afc068c28dcf6a64306754953682b0f9cfb70e 100644 (file)
@@ -559,7 +559,40 @@ struct timer_rand_state {
 };
 
 #ifndef CONFIG_SPARSE_IRQ
-struct timer_rand_state *irq_timer_state[NR_IRQS];
+
+static struct timer_rand_state *irq_timer_state[NR_IRQS];
+
+static struct timer_rand_state *get_timer_rand_state(unsigned int irq)
+{
+       return irq_timer_state[irq];
+}
+
+static void set_timer_rand_state(unsigned int irq,
+                                struct timer_rand_state *state)
+{
+       irq_timer_state[irq] = state;
+}
+
+#else
+
+static struct timer_rand_state *get_timer_rand_state(unsigned int irq)
+{
+       struct irq_desc *desc;
+
+       desc = irq_to_desc(irq);
+
+       return desc->timer_rand_state;
+}
+
+static void set_timer_rand_state(unsigned int irq,
+                                struct timer_rand_state *state)
+{
+       struct irq_desc *desc;
+
+       desc = irq_to_desc(irq);
+
+       desc->timer_rand_state = state;
+}
 #endif
 
 static struct timer_rand_state input_timer_state;
@@ -919,11 +952,6 @@ void rand_initialize_irq(int irq)
 {
        struct timer_rand_state *state;
 
-#ifndef CONFIG_SPARSE_IRQ
-       if (irq >= nr_irqs)
-               return;
-#endif
-
        state = get_timer_rand_state(irq);
 
        if (state)
index 31d6f535a79de51d322d8d76af3eccfd2bf11140..01dde80597f7e35248c3c8fd0dbdc29faa795743 100644 (file)
@@ -754,6 +754,11 @@ static struct kobj_type ktype_cpufreq = {
        .release        = cpufreq_sysfs_release,
 };
 
+static struct kobj_type ktype_empty_cpufreq = {
+       .sysfs_ops      = &sysfs_ops,
+       .release        = cpufreq_sysfs_release,
+};
+
 
 /**
  * cpufreq_add_dev - add a CPU device
@@ -822,8 +827,8 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
                dprintk("initialization failed\n");
                goto err_out;
        }
-       policy->user_policy.min = policy->cpuinfo.min_freq;
-       policy->user_policy.max = policy->cpuinfo.max_freq;
+       policy->user_policy.min = policy->min;
+       policy->user_policy.max = policy->max;
 
        blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
                                     CPUFREQ_START, policy);
@@ -876,26 +881,36 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
        memcpy(&new_policy, policy, sizeof(struct cpufreq_policy));
 
        /* prepare interface data */
-       ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq, &sys_dev->kobj,
-                                  "cpufreq");
-       if (ret)
-               goto err_out_driver_exit;
-
-       /* set up files for this cpu device */
-       drv_attr = cpufreq_driver->attr;
-       while ((drv_attr) && (*drv_attr)) {
-               ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr));
+       if (!cpufreq_driver->hide_interface) {
+               ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq,
+                                          &sys_dev->kobj, "cpufreq");
                if (ret)
                        goto err_out_driver_exit;
-               drv_attr++;
-       }
-       if (cpufreq_driver->get) {
-               ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr);
-               if (ret)
-                       goto err_out_driver_exit;
-       }
-       if (cpufreq_driver->target) {
-               ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr);
+
+               /* set up files for this cpu device */
+               drv_attr = cpufreq_driver->attr;
+               while ((drv_attr) && (*drv_attr)) {
+                       ret = sysfs_create_file(&policy->kobj,
+                                               &((*drv_attr)->attr));
+                       if (ret)
+                               goto err_out_driver_exit;
+                       drv_attr++;
+               }
+               if (cpufreq_driver->get) {
+                       ret = sysfs_create_file(&policy->kobj,
+                                               &cpuinfo_cur_freq.attr);
+                       if (ret)
+                               goto err_out_driver_exit;
+               }
+               if (cpufreq_driver->target) {
+                       ret = sysfs_create_file(&policy->kobj,
+                                               &scaling_cur_freq.attr);
+                       if (ret)
+                               goto err_out_driver_exit;
+               }
+       } else {
+               ret = kobject_init_and_add(&policy->kobj, &ktype_empty_cpufreq,
+                                          &sys_dev->kobj, "cpufreq");
                if (ret)
                        goto err_out_driver_exit;
        }
index 757035ea246faff58225747668d38a53f5362e59..3128a5090dbd4a909c54aa4e6704b561adda8718 100644 (file)
@@ -659,12 +659,12 @@ static inline int find_next_online_cpu(struct ehca_comp_pool *pool)
 
        WARN_ON_ONCE(!in_interrupt());
        if (ehca_debug_level >= 3)
-               ehca_dmp(&cpu_online_map, sizeof(cpumask_t), "");
+               ehca_dmp(cpu_online_mask, cpumask_size(), "");
 
        spin_lock_irqsave(&pool->last_cpu_lock, flags);
-       cpu = next_cpu_nr(pool->last_cpu, cpu_online_map);
+       cpu = cpumask_next(pool->last_cpu, cpu_online_mask);
        if (cpu >= nr_cpu_ids)
-               cpu = first_cpu(cpu_online_map);
+               cpu = cpumask_first(cpu_online_mask);
        pool->last_cpu = cpu;
        spin_unlock_irqrestore(&pool->last_cpu_lock, flags);
 
@@ -855,7 +855,7 @@ static int __cpuinit comp_pool_callback(struct notifier_block *nfb,
        case CPU_UP_CANCELED_FROZEN:
                ehca_gen_dbg("CPU: %x (CPU_CANCELED)", cpu);
                cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu);
-               kthread_bind(cct->task, any_online_cpu(cpu_online_map));
+               kthread_bind(cct->task, cpumask_any(cpu_online_mask));
                destroy_comp_task(pool, cpu);
                break;
        case CPU_ONLINE:
@@ -902,7 +902,7 @@ int ehca_create_comp_pool(void)
                return -ENOMEM;
 
        spin_lock_init(&pool->last_cpu_lock);
-       pool->last_cpu = any_online_cpu(cpu_online_map);
+       pool->last_cpu = cpumask_any(cpu_online_mask);
 
        pool->cpu_comp_tasks = alloc_percpu(struct ehca_cpu_comp_task);
        if (pool->cpu_comp_tasks == NULL) {
@@ -934,10 +934,9 @@ void ehca_destroy_comp_pool(void)
 
        unregister_hotcpu_notifier(&comp_pool_callback_nb);
 
-       for (i = 0; i < NR_CPUS; i++) {
-               if (cpu_online(i))
-                       destroy_comp_task(pool, i);
-       }
+       for_each_online_cpu(i)
+               destroy_comp_task(pool, i);
+
        free_percpu(pool->cpu_comp_tasks);
        kfree(pool);
 }
index 239d4e8068ac14e5ce39c52218726f1ed1d732da..23173982b32c1c636fdc2bbc398ad1168e3ff10d 100644 (file)
@@ -1679,7 +1679,7 @@ static int find_best_unit(struct file *fp,
         * InfiniPath chip to that processor (we assume reasonable connectivity,
         * for now).  This code assumes that if affinity has been set
         * before this point, that at most one cpu is set; for now this
-        * is reasonable.  I check for both cpus_empty() and cpus_full(),
+        * is reasonable.  I check for both cpumask_empty() and cpumask_full(),
         * in case some kernel variant sets none of the bits when no
         * affinity is set.  2.6.11 and 12 kernels have all present
         * cpus set.  Some day we'll have to fix it up further to handle
@@ -1688,11 +1688,11 @@ static int find_best_unit(struct file *fp,
         * information.  There may be some issues with dual core numbering
         * as well.  This needs more work prior to release.
         */
-       if (!cpus_empty(current->cpus_allowed) &&
-           !cpus_full(current->cpus_allowed)) {
+       if (!cpumask_empty(&current->cpus_allowed) &&
+           !cpumask_full(&current->cpus_allowed)) {
                int ncpus = num_online_cpus(), curcpu = -1, nset = 0;
                for (i = 0; i < ncpus; i++)
-                       if (cpu_isset(i, current->cpus_allowed)) {
+                       if (cpumask_test_cpu(i, &current->cpus_allowed)) {
                                ipath_cdbg(PROC, "%s[%u] affinity set for "
                                           "cpu %d/%d\n", current->comm,
                                           current->pid, i, ncpus);
index 53912c327bfea25dc4bab902d788042973441140..8dc2bb781605d5bda70851249234687ea08f62be 100644 (file)
@@ -57,9 +57,6 @@ static int ipathfs_mknod(struct inode *dir, struct dentry *dentry,
        }
 
        inode->i_mode = mode;
-       inode->i_uid = 0;
-       inode->i_gid = 0;
-       inode->i_blocks = 0;
        inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
        inode->i_private = data;
        if ((mode & S_IFMT) == S_IFDIR) {
index d5b4cc357a3c77dff03b704070063e2bed0ac11c..650120261abfbac9816386927fed562bf6ab37d4 100644 (file)
@@ -1519,7 +1519,7 @@ static int decodeFVteln(char *teln, unsigned long *bmaskp, int *activep)
                int digit2 = 0;
                if (!isdigit(*s)) return -3;
                while (isdigit(*s)) { digit1 = digit1*10 + (*s - '0'); s++; }
-               if (digit1 <= 0 && digit1 > 30) return -4;
+               if (digit1 <= 0 || digit1 > 30) return -4;
                if (*s == 0 || *s == ',' || *s == ' ') {
                        bmask |= (1 << digit1);
                        digit1 = 0;
@@ -1530,7 +1530,7 @@ static int decodeFVteln(char *teln, unsigned long *bmaskp, int *activep)
                s++;
                if (!isdigit(*s)) return -3;
                while (isdigit(*s)) { digit2 = digit2*10 + (*s - '0'); s++; }
-               if (digit2 <= 0 && digit2 > 30) return -4;
+               if (digit2 <= 0 || digit2 > 30) return -4;
                if (*s == 0 || *s == ',' || *s == ' ') {
                        if (digit1 > digit2)
                                for (i = digit2; i <= digit1 ; i++)
index 0aa66ec4cbdd216789e11c30f8024a219b2e587c..b129409925af59b86c448fafca9ed88266ddd6ff 100644 (file)
@@ -111,8 +111,6 @@ capifs_fill_super(struct super_block *s, void *data, int silent)
                goto fail;
        inode->i_ino = 1;
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
-       inode->i_blocks = 0;
-       inode->i_uid = inode->i_gid = 0;
        inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
        inode->i_op = &simple_dir_inode_operations;
        inode->i_fop = &simple_dir_operations;
index 7d844af883848a46c5eb99b8b25afbef6fbe46c3..cf06f4d10ad4229332d5d0b0146b630c4342fb09 100644 (file)
@@ -192,9 +192,9 @@ void saa7146_buffer_timeout(unsigned long data)
 /********************************************************************************/
 /* file operations */
 
-static int fops_open(struct inode *inode, struct file *file)
+static int fops_open(struct file *file)
 {
-       unsigned int minor = iminor(inode);
+       unsigned int minor = video_devdata(file)->minor;
        struct saa7146_dev *h = NULL, *dev = NULL;
        struct list_head *list;
        struct saa7146_fh *fh = NULL;
@@ -202,7 +202,7 @@ static int fops_open(struct inode *inode, struct file *file)
 
        enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
-       DEB_EE(("inode:%p, file:%p, minor:%d\n",inode,file,minor));
+       DEB_EE(("file:%p, minor:%d\n", file, minor));
 
        if (mutex_lock_interruptible(&saa7146_devices_lock))
                return -ERESTARTSYS;
@@ -255,7 +255,7 @@ static int fops_open(struct inode *inode, struct file *file)
                if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
                        result = saa7146_vbi_uops.open(dev,file);
                if (dev->ext_vv_data->vbi_fops.open)
-                       dev->ext_vv_data->vbi_fops.open(inode, file);
+                       dev->ext_vv_data->vbi_fops.open(file);
        } else {
                DEB_S(("initializing video...\n"));
                result = saa7146_video_uops.open(dev,file);
@@ -280,12 +280,12 @@ out:
        return result;
 }
 
-static int fops_release(struct inode *inode, struct file *file)
+static int fops_release(struct file *file)
 {
        struct saa7146_fh  *fh  = file->private_data;
        struct saa7146_dev *dev = fh->dev;
 
-       DEB_EE(("inode:%p, file:%p\n",inode,file));
+       DEB_EE(("file:%p\n", file));
 
        if (mutex_lock_interruptible(&saa7146_devices_lock))
                return -ERESTARTSYS;
@@ -294,7 +294,7 @@ static int fops_release(struct inode *inode, struct file *file)
                if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
                        saa7146_vbi_uops.release(dev,file);
                if (dev->ext_vv_data->vbi_fops.release)
-                       dev->ext_vv_data->vbi_fops.release(inode, file);
+                       dev->ext_vv_data->vbi_fops.release(file);
        } else {
                saa7146_video_uops.release(dev,file);
        }
@@ -308,10 +308,10 @@ static int fops_release(struct inode *inode, struct file *file)
        return 0;
 }
 
-static int fops_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static long fops_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 /*
-       DEB_EE(("inode:%p, file:%p, cmd:%d, arg:%li\n",inode, file, cmd, arg));
+       DEB_EE(("file:%p, cmd:%d, arg:%li\n", file, cmd, arg));
 */
        return video_usercopy(file, cmd, arg, saa7146_video_do_ioctl);
 }
@@ -416,7 +416,7 @@ static ssize_t fops_write(struct file *file, const char __user *data, size_t cou
        }
 }
 
-static const struct file_operations video_fops =
+static const struct v4l2_file_operations video_fops =
 {
        .owner          = THIS_MODULE,
        .open           = fops_open,
@@ -426,7 +426,6 @@ static const struct file_operations video_fops =
        .poll           = fops_poll,
        .mmap           = fops_mmap,
        .ioctl          = fops_ioctl,
-       .llseek         = no_llseek,
 };
 
 static void vv_callback(struct saa7146_dev *dev, unsigned long status)
index 101b01dbb8eaf11b3c8960ea31e8ec42182e0cad..6098b626811fac4baa0e89f40b0e45e371c9b56f 100644 (file)
@@ -834,13 +834,14 @@ static int video_end(struct saa7146_fh *fh, struct file *file)
  * copying is done already, arg is a kernel pointer.
  */
 
-int saa7146_video_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+long saa7146_video_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 {
        struct saa7146_fh *fh  = file->private_data;
        struct saa7146_dev *dev = fh->dev;
        struct saa7146_vv *vv = dev->vv_data;
 
-       int err = 0, result = 0, ee = 0;
+       long err = 0;
+       int result = 0, ee = 0;
 
        struct saa7146_use_ops *ops;
        struct videobuf_queue *q;
index fb3f3b3adaba27c9fb2b1244f99914122f7c7364..de7adaf5fa5b1d186c8c05b8c46925bea1c52d65 100644 (file)
@@ -820,6 +820,15 @@ static u32 simple_dvb_configure(struct dvb_frontend *fe, u8 *buf,
        int ret;
        unsigned frequency = params->frequency / 62500;
 
+       if (!tun->stepsize) {
+               /* tuner-core was loaded before the digital tuner was
+                * configured and somehow picked the wrong tuner type */
+               tuner_err("attempt to treat tuner %d (%s) as digital tuner "
+                         "without stepsize defined.\n",
+                         priv->type, priv->tun->name);
+               return 0; /* failure */
+       }
+
        t_params = simple_tuner_params(fe, TUNER_PARAM_TYPE_DIGITAL);
        ret = simple_config_lookup(fe, t_params, &frequency, &config, &cb);
        if (ret < 0)
@@ -1059,7 +1068,12 @@ struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,
        memcpy(&fe->ops.tuner_ops, &simple_tuner_ops,
               sizeof(struct dvb_tuner_ops));
 
-       tuner_info("type set to %d (%s)\n", type, priv->tun->name);
+       if (type != priv->type)
+               tuner_warn("couldn't set type to %d. Using %d (%s) instead\n",
+                           type, priv->type, priv->tun->name);
+       else
+               tuner_info("type set to %d (%s)\n",
+                          priv->type, priv->tun->name);
 
        if ((debug) || ((atv_input[priv->nr] > 0) ||
                        (dtv_input[priv->nr] > 0))) {
index 6c571d9f011c6df050c23230c399390e5c3e7334..65d69665f1fc5b87251c1af795e9cefb4b507eaf 100644 (file)
@@ -436,8 +436,9 @@ static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
        struct dvb_device *dvbdev = dev_get_drvdata(dev);
 
-       add_uevent_var(env, "DVB_DEVICE_NUM=%d", dvbdev->id);
        add_uevent_var(env, "DVB_ADAPTER_NUM=%d", dvbdev->adapter->num);
+       add_uevent_var(env, "DVB_DEVICE_TYPE=%s", dnames[dvbdev->type]);
+       add_uevent_var(env, "DVB_DEVICE_NUM=%d", dvbdev->id);
        return 0;
 }
 
index c1da962cc8863261fa5a833c72451055b79b4c6b..3dd6843864ed8a05f33baedd437af45bff412c86 100644 (file)
@@ -187,7 +187,7 @@ int gp8psk_bcm4500_reload(struct dvb_usb_device *d)
        /* load BCM4500 firmware */
        if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM)
                if (gp8psk_load_bcm4500fw(d))
-                       return EINVAL;
+                       return -EINVAL;
        return 0;
 }
 
index 9b6c89e93f1696570c7bc7194d6deb04a5b21846..4f514d39b98fd8cec5fbeb234e464e7806f454c1 100644 (file)
@@ -1463,6 +1463,7 @@ static struct dvb_frontend_ops cx24116_ops = {
                        FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
                        FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
                        FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+                       FE_CAN_2G_MODULATION |
                        FE_CAN_QPSK | FE_CAN_RECOVER
        },
 
index 4cb3ddd6c6261f7ce3c15d96550b2c56832ce651..b1b76b47a14cf2c97941a0e5721c85541742c645 100644 (file)
@@ -37,7 +37,8 @@ struct cx24116_config {
        u8 mpg_clk_pos_pol:0x02;
 };
 
-#if defined(CONFIG_DVB_CX24116) || defined(CONFIG_DVB_CX24116_MODULE)
+#if defined(CONFIG_DVB_CX24116) || \
+       (defined(CONFIG_DVB_CX24116_MODULE) && defined(MODULE))
 extern struct dvb_frontend *cx24116_attach(
        const struct cx24116_config *config,
        struct i2c_adapter *i2c);
index 52882017022862e373142b193b416f77a4d4c02d..bee28f77b93f9b3adff2ed7295f37ca9f4754fd7 100644 (file)
@@ -1618,6 +1618,7 @@ static struct dvb_frontend_ops stb0899_ops = {
 
                .caps                   = FE_CAN_INVERSION_AUTO |
                                          FE_CAN_FEC_AUTO       |
+                                         FE_CAN_2G_MODULATION  |
                                          FE_CAN_QPSK
        },
 
index 5506f80e180eeddd8c7bf575b963ea280abd3a94..170720b02815268c54b348d319d4a66d0532e454 100644 (file)
@@ -587,8 +587,15 @@ static int zl10353_init(struct dvb_frontend *fe)
 
 static int zl10353_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
 {
+       struct zl10353_state *state = fe->demodulator_priv;
        u8 val = 0x0a;
 
+       if (state->config.no_tuner) {
+               /* No tuner attached to the internal I2C bus */
+               /* If set enable I2C bridge, the main I2C bus stopped hardly */
+               return 0;
+       }
+
        if (enable)
                val |= 0x10;
 
index fd62e0b856213d15029262c293f05a63cb1a9ee7..4307e4e8aa34d7cddb232643b371756f2583f078 100644 (file)
@@ -120,7 +120,7 @@ static struct sms_board sms_boards[] = {
                .name   = "Hauppauge WinTV MiniCard",
                .type   = SMS_NOVA_B0,
                .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw",
-               .lna_ctrl  = 1,
+               .lna_ctrl  = -1,
        },
 };
 
@@ -131,9 +131,10 @@ struct sms_board *sms_get_board(int id)
        return &sms_boards[id];
 }
 
-static int sms_set_gpio(struct smscore_device_t *coredev, u32 pin, int enable)
+static int sms_set_gpio(struct smscore_device_t *coredev, int pin, int enable)
 {
-       int ret;
+       int lvl, ret;
+       u32 gpio;
        struct smscore_gpio_config gpioconfig = {
                .direction            = SMS_GPIO_DIRECTION_OUTPUT,
                .pullupdown           = SMS_GPIO_PULLUPDOWN_NONE,
@@ -145,12 +146,20 @@ static int sms_set_gpio(struct smscore_device_t *coredev, u32 pin, int enable)
        if (pin == 0)
                return -EINVAL;
 
-       ret = smscore_configure_gpio(coredev, pin, &gpioconfig);
+       if (pin < 0) {
+               /* inverted gpio */
+               gpio = pin * -1;
+               lvl = enable ? 0 : 1;
+       } else {
+               gpio = pin;
+               lvl = enable ? 1 : 0;
+       }
 
+       ret = smscore_configure_gpio(coredev, gpio, &gpioconfig);
        if (ret < 0)
                return ret;
 
-       return smscore_set_gpio(coredev, pin, enable);
+       return smscore_set_gpio(coredev, gpio, lvl);
 }
 
 int sms_board_setup(struct smscore_device_t *coredev)
index b4a0cc5dc935ffec2c9310385c7816d1e24f40a4..c5b9c70563dc699eb149ae7c6f7f510228623f77 100644 (file)
@@ -316,7 +316,7 @@ static int av7110_dvb_c_switch(struct saa7146_fh *fh)
        return 0;
 }
 
-static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
+static long av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
 {
        struct saa7146_dev *dev = fh->dev;
        struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
@@ -567,7 +567,7 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
        return 0;
 }
 
-static int av7110_vbi_reset(struct inode *inode, struct file *file)
+static int av7110_vbi_reset(struct file *file)
 {
        struct saa7146_fh *fh = file->private_data;
        struct saa7146_dev *dev = fh->dev;
index f996cef79ec1ff0930060f338aa43135074eeb07..4182121d7e5dcd848ce40d67dc279ffaa076473f 100644 (file)
@@ -1493,7 +1493,7 @@ static struct saa7146_extension_ioctls ioctls[] = {
        {0, 0}
 };
 
-static int av_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
+static long av_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
 {
        struct saa7146_dev *dev = fh->dev;
        struct budget_av *budget_av = (struct budget_av *) dev->ext_priv;
index f546bccdb997d80235ac08895c9185034978fbb7..2663ae39b88692f5eada3b73730b68fc756e7db9 100644 (file)
@@ -1,6 +1,6 @@
 config DVB_TTUSB_BUDGET
        tristate "Technotrend/Hauppauge Nova-USB devices"
-       depends on DVB_CORE && USB && I2C
+       depends on DVB_CORE && USB && I2C && PCI
        select DVB_CX22700 if !DVB_FE_CUSTOMISE
        select DVB_TDA1004X if !DVB_FE_CUSTOMISE
        select DVB_VES1820 if !DVB_FE_CUSTOMISE
index d5f48a3102bdf5183d939d6be3002325fa1c8123..290254ab06dbb01edac5ddc362b3d89eebf1662d 100644 (file)
@@ -1,6 +1,6 @@
 config DVB_TTUSB_DEC
        tristate "Technotrend/Hauppauge USB DEC devices"
-       depends on DVB_CORE && USB && INPUT
+       depends on DVB_CORE && USB && INPUT && PCI
        select CRC32
        help
          Support for external USB adapters designed by Technotrend and
index 5189c4eb439f705c98a2a35c7949fb2059ef380c..3315cac875e518996b4f02a1a2cd791fc5e45f6a 100644 (file)
@@ -387,4 +387,23 @@ config USB_MR800
          To compile this driver as a module, choose M here: the
          module will be called radio-mr800.
 
+config RADIO_TEA5764
+       tristate "TEA5764 I2C FM radio support"
+       depends on I2C && VIDEO_V4L2
+       ---help---
+         Say Y here if you want to use the TEA5764 FM chip found in
+         EZX phones. This FM chip is present in EZX phones from Motorola,
+         connected to internal pxa I2C bus.
+
+         To compile this driver as a module, choose M here: the
+         module will be called radio-tea5764.
+
+config RADIO_TEA5764_XTAL
+       bool "TEA5764 crystal reference"
+       depends on RADIO_TEA5764=y
+       default y
+       help
+         Say Y here if TEA5764 have a 32768 Hz crystal in circuit, say N
+         here if TEA5764 reference frequency is connected in FREQIN.
+
 endif # RADIO_ADAPTERS
index 240ec63cdafc490c88612dbc091742cfe714ff32..0f2b35b3e5608a2fdb5a19d6ea78f12f5b3f5791 100644 (file)
@@ -19,5 +19,6 @@ obj-$(CONFIG_RADIO_MAESTRO) += radio-maestro.o
 obj-$(CONFIG_USB_DSBR) += dsbr100.o
 obj-$(CONFIG_USB_SI470X) += radio-si470x.o
 obj-$(CONFIG_USB_MR800) += radio-mr800.o
+obj-$(CONFIG_RADIO_TEA5764) += radio-tea5764.o
 
 EXTRA_CFLAGS += -Isound
index 5474a22c1b2235ef627163c73ba27fe519d1b471..2014ebc4e984f12cb33f1c1a83f5c9e39b56abda 100644 (file)
@@ -154,8 +154,8 @@ devices, that would be 76 and 91.  */
 static int usb_dsbr100_probe(struct usb_interface *intf,
                             const struct usb_device_id *id);
 static void usb_dsbr100_disconnect(struct usb_interface *intf);
-static int usb_dsbr100_open(struct inode *inode, struct file *file);
-static int usb_dsbr100_close(struct inode *inode, struct file *file);
+static int usb_dsbr100_open(struct file *file);
+static int usb_dsbr100_close(struct file *file);
 static int usb_dsbr100_suspend(struct usb_interface *intf,
                                                pm_message_t message);
 static int usb_dsbr100_resume(struct usb_interface *intf);
@@ -566,7 +566,7 @@ static int vidioc_s_audio(struct file *file, void *priv,
        return 0;
 }
 
-static int usb_dsbr100_open(struct inode *inode, struct file *file)
+static int usb_dsbr100_open(struct file *file)
 {
        struct dsbr100_device *radio = video_drvdata(file);
        int retval;
@@ -593,7 +593,7 @@ static int usb_dsbr100_open(struct inode *inode, struct file *file)
        return 0;
 }
 
-static int usb_dsbr100_close(struct inode *inode, struct file *file)
+static int usb_dsbr100_close(struct file *file)
 {
        struct dsbr100_device *radio = video_drvdata(file);
        int retval;
@@ -653,15 +653,11 @@ static void usb_dsbr100_video_device_release(struct video_device *videodev)
 }
 
 /* File system interface */
-static const struct file_operations usb_dsbr100_fops = {
+static const struct v4l2_file_operations usb_dsbr100_fops = {
        .owner          = THIS_MODULE,
        .open           = usb_dsbr100_open,
        .release        = usb_dsbr100_close,
        .ioctl          = video_ioctl2,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = v4l_compat_ioctl32,
-#endif
-       .llseek         = no_llseek,
 };
 
 static const struct v4l2_ioctl_ops usb_dsbr100_ioctl_ops = {
index dd6d3dfcd7d256bee7f8554175f5ec7b2c7021eb..bfa13b8b3043b33aeb3c0fdeaae3fe947b06b1f0 100644 (file)
@@ -374,26 +374,22 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static struct rt_device rtrack_unit;
 
-static int rtrack_exclusive_open(struct inode *inode, struct file *file)
+static int rtrack_exclusive_open(struct file *file)
 {
        return test_and_set_bit(0, &rtrack_unit.in_use) ? -EBUSY : 0;
 }
 
-static int rtrack_exclusive_release(struct inode *inode, struct file *file)
+static int rtrack_exclusive_release(struct file *file)
 {
        clear_bit(0, &rtrack_unit.in_use);
        return 0;
 }
 
-static const struct file_operations rtrack_fops = {
+static const struct v4l2_file_operations rtrack_fops = {
        .owner          = THIS_MODULE,
        .open           = rtrack_exclusive_open,
        .release        = rtrack_exclusive_release,
        .ioctl          = video_ioctl2,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = v4l_compat_ioctl32,
-#endif
-       .llseek         = no_llseek,
 };
 
 static const struct v4l2_ioctl_ops rtrack_ioctl_ops = {
index d78489573230c259086711245d35775af57ed94a..5604e881e96c26292badc92c08e8afbb4017bb9a 100644 (file)
@@ -338,26 +338,22 @@ static int vidioc_s_ctrl (struct file *file, void *priv,
 
 static struct az_device aztech_unit;
 
-static int aztech_exclusive_open(struct inode *inode, struct file *file)
+static int aztech_exclusive_open(struct file *file)
 {
        return test_and_set_bit(0, &aztech_unit.in_use) ? -EBUSY : 0;
 }
 
-static int aztech_exclusive_release(struct inode *inode, struct file *file)
+static int aztech_exclusive_release(struct file *file)
 {
        clear_bit(0, &aztech_unit.in_use);
        return 0;
 }
 
-static const struct file_operations aztech_fops = {
+static const struct v4l2_file_operations aztech_fops = {
        .owner          = THIS_MODULE,
        .open           = aztech_exclusive_open,
        .release        = aztech_exclusive_release,
        .ioctl          = video_ioctl2,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = v4l_compat_ioctl32,
-#endif
-       .llseek         = no_llseek,
 };
 
 static const struct v4l2_ioctl_ops aztech_ioctl_ops = {
index bfd37f38b9ab3ad68df8430d16e6807dbf284654..cb3075ac104c211c281af8c77660749735a8f7ad 100644 (file)
@@ -529,7 +529,7 @@ static int vidioc_s_audio(struct file *file, void *priv,
 }
 
 static int
-cadet_open(struct inode *inode, struct file *file)
+cadet_open(struct file *file)
 {
        users++;
        if (1 == users) init_waitqueue_head(&read_queue);
@@ -537,7 +537,7 @@ cadet_open(struct inode *inode, struct file *file)
 }
 
 static int
-cadet_release(struct inode *inode, struct file *file)
+cadet_release(struct file *file)
 {
        users--;
        if (0 == users){
@@ -557,17 +557,13 @@ cadet_poll(struct file *file, struct poll_table_struct *wait)
 }
 
 
-static const struct file_operations cadet_fops = {
+static const struct v4l2_file_operations cadet_fops = {
        .owner          = THIS_MODULE,
        .open           = cadet_open,
        .release        = cadet_release,
        .read           = cadet_read,
        .ioctl          = video_ioctl2,
        .poll           = cadet_poll,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = v4l_compat_ioctl32,
-#endif
-       .llseek         = no_llseek,
 };
 
 static const struct v4l2_ioctl_ops cadet_ioctl_ops = {
index e15bee6d7cfcb874fedab31a35730af81a75b19b..0c96bf8525b056fbbb17d36c13ea2e1c267ff2c0 100644 (file)
@@ -358,26 +358,22 @@ MODULE_DEVICE_TABLE( pci, gemtek_pci_id );
 
 static int mx = 1;
 
-static int gemtek_pci_exclusive_open(struct inode *inode, struct file *file)
+static int gemtek_pci_exclusive_open(struct file *file)
 {
        return test_and_set_bit(0, &in_use) ? -EBUSY : 0;
 }
 
-static int gemtek_pci_exclusive_release(struct inode *inode, struct file *file)
+static int gemtek_pci_exclusive_release(struct file *file)
 {
        clear_bit(0, &in_use);
        return 0;
 }
 
-static const struct file_operations gemtek_pci_fops = {
+static const struct v4l2_file_operations gemtek_pci_fops = {
        .owner          = THIS_MODULE,
        .open           = gemtek_pci_exclusive_open,
        .release        = gemtek_pci_exclusive_release,
        .ioctl          = video_ioctl2,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = v4l_compat_ioctl32,
-#endif
-       .llseek         = no_llseek,
 };
 
 static const struct v4l2_ioctl_ops gemtek_pci_ioctl_ops = {
index e13118da307bb313eab757c9cead6046c59aa2ee..2b68be773f1381c443421fdf4ab8f40fe94009d3 100644 (file)
@@ -394,26 +394,22 @@ static struct v4l2_queryctrl radio_qctrl[] = {
        }
 };
 
-static int gemtek_exclusive_open(struct inode *inode, struct file *file)
+static int gemtek_exclusive_open(struct file *file)
 {
        return test_and_set_bit(0, &in_use) ? -EBUSY : 0;
 }
 
-static int gemtek_exclusive_release(struct inode *inode, struct file *file)
+static int gemtek_exclusive_release(struct file *file)
 {
        clear_bit(0, &in_use);
        return 0;
 }
 
-static const struct file_operations gemtek_fops = {
+static const struct v4l2_file_operations gemtek_fops = {
        .owner          = THIS_MODULE,
        .open           = gemtek_exclusive_open,
        .release        = gemtek_exclusive_release,
        .ioctl          = video_ioctl2,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = v4l_compat_ioctl32,
-#endif
-       .llseek         = no_llseek
 };
 
 static int vidioc_querycap(struct file *file, void *priv,
index 4bf4d007bcfa2b62db846c29f3c035831c5f0433..ba3a13a90013e4c58e232afe7b50baff892410a8 100644 (file)
@@ -79,12 +79,12 @@ static unsigned long in_use;
 
 static int maestro_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
 
-static int maestro_exclusive_open(struct inode *inode, struct file *file)
+static int maestro_exclusive_open(struct file *file)
 {
        return test_and_set_bit(0, &in_use) ? -EBUSY : 0;
 }
 
-static int maestro_exclusive_release(struct inode *inode, struct file *file)
+static int maestro_exclusive_release(struct file *file)
 {
        clear_bit(0, &in_use);
        return 0;
@@ -110,15 +110,11 @@ static struct pci_driver maestro_r_driver = {
        .remove         = __devexit_p(maestro_remove),
 };
 
-static const struct file_operations maestro_fops = {
+static const struct v4l2_file_operations maestro_fops = {
        .owner          = THIS_MODULE,
        .open           = maestro_exclusive_open,
        .release        = maestro_exclusive_release,
        .ioctl          = video_ioctl2,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = v4l_compat_ioctl32,
-#endif
-       .llseek         = no_llseek,
 };
 
 struct radio_device {
index c777a17b00bc21c986b08b756080a995eeeb990e..c5dc00aa9c9f467f2704ca3f13ef531b36248e93 100644 (file)
@@ -100,26 +100,22 @@ static unsigned long in_use;
 #define BITS2FREQ(x)   ((x) * FREQ_STEP - FREQ_IF)
 
 
-static int maxiradio_exclusive_open(struct inode *inode, struct file *file)
+static int maxiradio_exclusive_open(struct file *file)
 {
        return test_and_set_bit(0, &in_use) ? -EBUSY : 0;
 }
 
-static int maxiradio_exclusive_release(struct inode *inode, struct file *file)
+static int maxiradio_exclusive_release(struct file *file)
 {
        clear_bit(0, &in_use);
        return 0;
 }
 
-static const struct file_operations maxiradio_fops = {
+static const struct v4l2_file_operations maxiradio_fops = {
        .owner          = THIS_MODULE,
        .open           = maxiradio_exclusive_open,
        .release        = maxiradio_exclusive_release,
        .ioctl          = video_ioctl2,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = v4l_compat_ioctl32,
-#endif
-       .llseek         = no_llseek,
 };
 
 static struct radio_device
index e730eddb2bb5b0077c6c43fb693620262e055f17..0747dc8862b095718e3dba02bd32be898227f829 100644 (file)
@@ -127,8 +127,8 @@ static struct v4l2_queryctrl radio_qctrl[] = {
 static int usb_amradio_probe(struct usb_interface *intf,
                             const struct usb_device_id *id);
 static void usb_amradio_disconnect(struct usb_interface *intf);
-static int usb_amradio_open(struct inode *inode, struct file *file);
-static int usb_amradio_close(struct inode *inode, struct file *file);
+static int usb_amradio_open(struct file *file);
+static int usb_amradio_close(struct file *file);
 static int usb_amradio_suspend(struct usb_interface *intf,
                                pm_message_t message);
 static int usb_amradio_resume(struct usb_interface *intf);
@@ -500,7 +500,7 @@ static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
 }
 
 /* open device - amradio_start() and amradio_setfreq() */
-static int usb_amradio_open(struct inode *inode, struct file *file)
+static int usb_amradio_open(struct file *file)
 {
        struct amradio_device *radio = video_get_drvdata(video_devdata(file));
 
@@ -525,7 +525,7 @@ static int usb_amradio_open(struct inode *inode, struct file *file)
 }
 
 /*close device */
-static int usb_amradio_close(struct inode *inode, struct file *file)
+static int usb_amradio_close(struct file *file)
 {
        struct amradio_device *radio = video_get_drvdata(video_devdata(file));
        int retval;
@@ -572,15 +572,11 @@ static int usb_amradio_resume(struct usb_interface *intf)
 }
 
 /* File system interface */
-static const struct file_operations usb_amradio_fops = {
+static const struct v4l2_file_operations usb_amradio_fops = {
        .owner          = THIS_MODULE,
        .open           = usb_amradio_open,
        .release        = usb_amradio_close,
        .ioctl          = video_ioctl2,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = v4l_compat_ioctl32,
-#endif
-       .llseek         = no_llseek,
 };
 
 static const struct v4l2_ioctl_ops usb_amradio_ioctl_ops = {
index 7704f243b6f0cf99c3fb05e4f249de2ed1147ae3..2587227214bf8cfe54f0120f87683006239f2d02 100644 (file)
@@ -280,26 +280,22 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static struct rt_device rtrack2_unit;
 
-static int rtrack2_exclusive_open(struct inode *inode, struct file *file)
+static int rtrack2_exclusive_open(struct file *file)
 {
        return test_and_set_bit(0, &rtrack2_unit.in_use) ? -EBUSY : 0;
 }
 
-static int rtrack2_exclusive_release(struct inode *inode, struct file *file)
+static int rtrack2_exclusive_release(struct file *file)
 {
        clear_bit(0, &rtrack2_unit.in_use);
        return 0;
 }
 
-static const struct file_operations rtrack2_fops = {
+static const struct v4l2_file_operations rtrack2_fops = {
        .owner          = THIS_MODULE,
        .open           = rtrack2_exclusive_open,
        .release        = rtrack2_exclusive_release,
        .ioctl          = video_ioctl2,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = v4l_compat_ioctl32,
-#endif
-       .llseek         = no_llseek,
 };
 
 static const struct v4l2_ioctl_ops rtrack2_ioctl_ops = {
index 834d43651c70fc1017ee65fa371ef3e18c86d11f..d358e48c242286d0d9cf45768236e8473d64e8a0 100644 (file)
@@ -280,26 +280,22 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static struct fmi_device fmi_unit;
 
-static int fmi_exclusive_open(struct inode *inode, struct file *file)
+static int fmi_exclusive_open(struct file *file)
 {
        return test_and_set_bit(0, &fmi_unit.in_use) ? -EBUSY : 0;
 }
 
-static int fmi_exclusive_release(struct inode *inode, struct file *file)
+static int fmi_exclusive_release(struct file *file)
 {
        clear_bit(0, &fmi_unit.in_use);
        return 0;
 }
 
-static const struct file_operations fmi_fops = {
+static const struct v4l2_file_operations fmi_fops = {
        .owner          = THIS_MODULE,
        .open           = fmi_exclusive_open,
        .release        = fmi_exclusive_release,
        .ioctl          = video_ioctl2,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = v4l_compat_ioctl32,
-#endif
-       .llseek         = no_llseek,
 };
 
 static const struct v4l2_ioctl_ops fmi_ioctl_ops = {
index b1f47c322e02637e58b2117a3c7df2e51656dd76..92f17a347fa73baf2fa12fe7524d2cacd9dbd6a7 100644 (file)
@@ -396,26 +396,22 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static struct fmr2_device fmr2_unit;
 
-static int fmr2_exclusive_open(struct inode *inode, struct file *file)
+static int fmr2_exclusive_open(struct file *file)
 {
        return test_and_set_bit(0, &fmr2_unit.in_use) ? -EBUSY : 0;
 }
 
-static int fmr2_exclusive_release(struct inode *inode, struct file *file)
+static int fmr2_exclusive_release(struct file *file)
 {
        clear_bit(0, &fmr2_unit.in_use);
        return 0;
 }
 
-static const struct file_operations fmr2_fops = {
+static const struct v4l2_file_operations fmr2_fops = {
        .owner          = THIS_MODULE,
        .open           = fmr2_exclusive_open,
        .release        = fmr2_exclusive_release,
        .ioctl          = video_ioctl2,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = v4l_compat_ioctl32,
-#endif
-       .llseek         = no_llseek,
 };
 
 static const struct v4l2_ioctl_ops fmr2_ioctl_ops = {
index 3e1830293de5ebd8c2e1d0a86bc4d6b5d62fe7db..67cbce82cb913a0619f3a72fb8a4e519076cbf96 100644 (file)
@@ -96,6 +96,8 @@
  * 2008-10-20  Alexey Klimov <klimov.linux@gmail.com>
  *             - add support for KWorld USB FM Radio FM700
  *             - blacklisted KWorld radio in hid-core.c and hid-ids.h
+ * 2008-12-03  Mark Lord <mlord@pobox.com>
+ *             - add support for DealExtreme USB Radio
  *
  * ToDo:
  * - add firmware download/update support
@@ -138,6 +140,8 @@ static struct usb_device_id si470x_usb_driver_id_table[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(0x06e1, 0xa155, USB_CLASS_HID, 0, 0) },
        /* KWorld USB FM Radio SnapMusic Mobile 700 (FM700) */
        { USB_DEVICE_AND_INTERFACE_INFO(0x1b80, 0xd700, USB_CLASS_HID, 0, 0) },
+       /* DealExtreme USB Radio */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x10c5, 0x819a, USB_CLASS_HID, 0, 0) },
        /* Terminating entry */
        { }
 };
@@ -1075,7 +1079,7 @@ static unsigned int si470x_fops_poll(struct file *file,
 /*
  * si470x_fops_open - file open
  */
-static int si470x_fops_open(struct inode *inode, struct file *file)
+static int si470x_fops_open(struct file *file)
 {
        struct si470x_device *radio = video_drvdata(file);
        int retval;
@@ -1105,7 +1109,7 @@ done:
 /*
  * si470x_fops_release - file release
  */
-static int si470x_fops_release(struct inode *inode, struct file *file)
+static int si470x_fops_release(struct file *file)
 {
        struct si470x_device *radio = video_drvdata(file);
        int retval = 0;
@@ -1147,15 +1151,11 @@ done:
 /*
  * si470x_fops - file operations interface
  */
-static const struct file_operations si470x_fops = {
+static const struct v4l2_file_operations si470x_fops = {
        .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
        .read           = si470x_fops_read,
        .poll           = si470x_fops_poll,
        .ioctl          = video_ioctl2,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = v4l_compat_ioctl32,
-#endif
        .open           = si470x_fops_open,
        .release        = si470x_fops_release,
 };
diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c
new file mode 100644 (file)
index 0000000..4d35308
--- /dev/null
@@ -0,0 +1,634 @@
+/*
+ * driver/media/radio/radio-tea5764.c
+ *
+ * Driver for TEA5764 radio chip for linux 2.6.
+ * This driver is for TEA5764 chip from NXP, used in EZX phones from Motorola.
+ * The I2C protocol is used for communicate with chip.
+ *
+ * Based in radio-tea5761.c Copyright (C) 2005 Nokia Corporation
+ *
+ *  Copyright (c) 2008 Fabio Belavenuto <belavenuto@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * History:
+ * 2008-12-06   Fabio Belavenuto <belavenuto@gmail.com>
+ *              initial code
+ *
+ * TODO:
+ *  add platform_data support for IRQs platform dependencies
+ *  add RDS support
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>                        /* Initdata                     */
+#include <linux/videodev2.h>           /* kernel radio structs         */
+#include <linux/i2c.h>                 /* I2C                          */
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <linux/version.h>             /* for KERNEL_VERSION MACRO     */
+
+#define DRIVER_VERSION "v0.01"
+#define RADIO_VERSION  KERNEL_VERSION(0, 0, 1)
+
+#define DRIVER_AUTHOR  "Fabio Belavenuto <belavenuto@gmail.com>"
+#define DRIVER_DESC    "A driver for the TEA5764 radio chip for EZX Phones."
+
+#define PINFO(format, ...)\
+       printk(KERN_INFO KBUILD_MODNAME ": "\
+               DRIVER_VERSION ": " format "\n", ## __VA_ARGS__)
+#define PWARN(format, ...)\
+       printk(KERN_WARNING KBUILD_MODNAME ": "\
+               DRIVER_VERSION ": " format "\n", ## __VA_ARGS__)
+# define PDEBUG(format, ...)\
+       printk(KERN_DEBUG KBUILD_MODNAME ": "\
+               DRIVER_VERSION ": " format "\n", ## __VA_ARGS__)
+
+/* Frequency limits in MHz -- these are European values.  For Japanese
+devices, that would be 76000 and 91000.  */
+#define FREQ_MIN  87500
+#define FREQ_MAX 108000
+#define FREQ_MUL 16
+
+/* TEA5764 registers */
+#define TEA5764_MANID          0x002b
+#define TEA5764_CHIPID         0x5764
+
+#define TEA5764_INTREG_BLMSK   0x0001
+#define TEA5764_INTREG_FRRMSK  0x0002
+#define TEA5764_INTREG_LEVMSK  0x0008
+#define TEA5764_INTREG_IFMSK   0x0010
+#define TEA5764_INTREG_BLMFLAG 0x0100
+#define TEA5764_INTREG_FRRFLAG 0x0200
+#define TEA5764_INTREG_LEVFLAG 0x0800
+#define TEA5764_INTREG_IFFLAG  0x1000
+
+#define TEA5764_FRQSET_SUD     0x8000
+#define TEA5764_FRQSET_SM      0x4000
+
+#define TEA5764_TNCTRL_PUPD1   0x8000
+#define TEA5764_TNCTRL_PUPD0   0x4000
+#define TEA5764_TNCTRL_BLIM    0x2000
+#define TEA5764_TNCTRL_SWPM    0x1000
+#define TEA5764_TNCTRL_IFCTC   0x0800
+#define TEA5764_TNCTRL_AFM     0x0400
+#define TEA5764_TNCTRL_SMUTE   0x0200
+#define TEA5764_TNCTRL_SNC     0x0100
+#define TEA5764_TNCTRL_MU      0x0080
+#define TEA5764_TNCTRL_SSL1    0x0040
+#define TEA5764_TNCTRL_SSL0    0x0020
+#define TEA5764_TNCTRL_HLSI    0x0010
+#define TEA5764_TNCTRL_MST     0x0008
+#define TEA5764_TNCTRL_SWP     0x0004
+#define TEA5764_TNCTRL_DTC     0x0002
+#define TEA5764_TNCTRL_AHLSI   0x0001
+
+#define TEA5764_TUNCHK_LEVEL(x)        (((x) & 0x00F0) >> 4)
+#define TEA5764_TUNCHK_IFCNT(x) (((x) & 0xFE00) >> 9)
+#define TEA5764_TUNCHK_TUNTO   0x0100
+#define TEA5764_TUNCHK_LD      0x0008
+#define TEA5764_TUNCHK_STEREO  0x0004
+
+#define TEA5764_TESTREG_TRIGFR 0x0800
+
+struct tea5764_regs {
+       u16 intreg;                             /* INTFLAG & INTMSK */
+       u16 frqset;                             /* FRQSETMSB & FRQSETLSB */
+       u16 tnctrl;                             /* TNCTRL1 & TNCTRL2 */
+       u16 frqchk;                             /* FRQCHKMSB & FRQCHKLSB */
+       u16 tunchk;                             /* IFCHK & LEVCHK */
+       u16 testreg;                            /* TESTBITS & TESTMODE */
+       u16 rdsstat;                            /* RDSSTAT1 & RDSSTAT2 */
+       u16 rdslb;                              /* RDSLBMSB & RDSLBLSB */
+       u16 rdspb;                              /* RDSPBMSB & RDSPBLSB */
+       u16 rdsbc;                              /* RDSBBC & RDSGBC */
+       u16 rdsctrl;                            /* RDSCTRL1 & RDSCTRL2 */
+       u16 rdsbbl;                             /* PAUSEDET & RDSBBL */
+       u16 manid;                              /* MANID1 & MANID2 */
+       u16 chipid;                             /* CHIPID1 & CHIPID2 */
+} __attribute__ ((packed));
+
+struct tea5764_write_regs {
+       u8 intreg;                              /* INTMSK */
+       u16 frqset;                             /* FRQSETMSB & FRQSETLSB */
+       u16 tnctrl;                             /* TNCTRL1 & TNCTRL2 */
+       u16 testreg;                            /* TESTBITS & TESTMODE */
+       u16 rdsctrl;                            /* RDSCTRL1 & RDSCTRL2 */
+       u16 rdsbbl;                             /* PAUSEDET & RDSBBL */
+} __attribute__ ((packed));
+
+#ifndef RADIO_TEA5764_XTAL
+#define RADIO_TEA5764_XTAL 1
+#endif
+
+static int radio_nr = -1;
+static int use_xtal = RADIO_TEA5764_XTAL;
+
+struct tea5764_device {
+       struct i2c_client               *i2c_client;
+       struct video_device             *videodev;
+       struct tea5764_regs             regs;
+       struct mutex                    mutex;
+       int                             users;
+};
+
+/* I2C code related */
+int tea5764_i2c_read(struct tea5764_device *radio)
+{
+       int i;
+       u16 *p = (u16 *) &radio->regs;
+
+       struct i2c_msg msgs[1] = {
+               { radio->i2c_client->addr, I2C_M_RD, sizeof(radio->regs),
+                       (void *)&radio->regs },
+       };
+       if (i2c_transfer(radio->i2c_client->adapter, msgs, 1) != 1)
+               return -EIO;
+       for (i = 0; i < sizeof(struct tea5764_regs) / sizeof(u16); i++)
+               p[i] = __be16_to_cpu(p[i]);
+
+       return 0;
+}
+
+int tea5764_i2c_write(struct tea5764_device *radio)
+{
+       struct tea5764_write_regs wr;
+       struct tea5764_regs *r = &radio->regs;
+       struct i2c_msg msgs[1] = {
+               { radio->i2c_client->addr, 0, sizeof(wr), (void *) &wr },
+       };
+       wr.intreg  = r->intreg & 0xff;
+       wr.frqset  = __cpu_to_be16(r->frqset);
+       wr.tnctrl  = __cpu_to_be16(r->tnctrl);
+       wr.testreg = __cpu_to_be16(r->testreg);
+       wr.rdsctrl = __cpu_to_be16(r->rdsctrl);
+       wr.rdsbbl  = __cpu_to_be16(r->rdsbbl);
+       if (i2c_transfer(radio->i2c_client->adapter, msgs, 1) != 1)
+               return -EIO;
+       return 0;
+}
+
+/* V4L2 code related */
+static struct v4l2_queryctrl radio_qctrl[] = {
+       {
+               .id            = V4L2_CID_AUDIO_MUTE,
+               .name          = "Mute",
+               .minimum       = 0,
+               .maximum       = 1,
+               .default_value = 1,
+               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+       }
+};
+
+static void tea5764_power_up(struct tea5764_device *radio)
+{
+       struct tea5764_regs *r = &radio->regs;
+
+       if (!(r->tnctrl & TEA5764_TNCTRL_PUPD0)) {
+               r->tnctrl &= ~(TEA5764_TNCTRL_AFM | TEA5764_TNCTRL_MU |
+                              TEA5764_TNCTRL_HLSI);
+               if (!use_xtal)
+                       r->testreg |= TEA5764_TESTREG_TRIGFR;
+               else
+                       r->testreg &= ~TEA5764_TESTREG_TRIGFR;
+
+               r->tnctrl |= TEA5764_TNCTRL_PUPD0;
+               tea5764_i2c_write(radio);
+       }
+}
+
+static void tea5764_power_down(struct tea5764_device *radio)
+{
+       struct tea5764_regs *r = &radio->regs;
+
+       if (r->tnctrl & TEA5764_TNCTRL_PUPD0) {
+               r->tnctrl &= ~TEA5764_TNCTRL_PUPD0;
+               tea5764_i2c_write(radio);
+       }
+}
+
+static void tea5764_set_freq(struct tea5764_device *radio, int freq)
+{
+       struct tea5764_regs *r = &radio->regs;
+
+       /* formula: (freq [+ or -] 225000) / 8192 */
+       if (r->tnctrl & TEA5764_TNCTRL_HLSI)
+               r->frqset = (freq + 225000) / 8192;
+       else
+               r->frqset = (freq - 225000) / 8192;
+}
+
+static int tea5764_get_freq(struct tea5764_device *radio)
+{
+       struct tea5764_regs *r = &radio->regs;
+
+       if (r->tnctrl & TEA5764_TNCTRL_HLSI)
+               return (r->frqchk * 8192) - 225000;
+       else
+               return (r->frqchk * 8192) + 225000;
+}
+
+/* tune an frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */
+static void tea5764_tune(struct tea5764_device *radio, int freq)
+{
+       tea5764_set_freq(radio, freq);
+       if (tea5764_i2c_write(radio))
+               PWARN("Could not set frequency!");
+}
+
+static void tea5764_set_audout_mode(struct tea5764_device *radio, int audmode)
+{
+       struct tea5764_regs *r = &radio->regs;
+       int tnctrl = r->tnctrl;
+
+       if (audmode == V4L2_TUNER_MODE_MONO)
+               r->tnctrl |= TEA5764_TNCTRL_MST;
+       else
+               r->tnctrl &= ~TEA5764_TNCTRL_MST;
+       if (tnctrl != r->tnctrl)
+               tea5764_i2c_write(radio);
+}
+
+static int tea5764_get_audout_mode(struct tea5764_device *radio)
+{
+       struct tea5764_regs *r = &radio->regs;
+
+       if (r->tnctrl & TEA5764_TNCTRL_MST)
+               return V4L2_TUNER_MODE_MONO;
+       else
+               return V4L2_TUNER_MODE_STEREO;
+}
+
+static void tea5764_mute(struct tea5764_device *radio, int on)
+{
+       struct tea5764_regs *r = &radio->regs;
+       int tnctrl = r->tnctrl;
+
+       if (on)
+               r->tnctrl |= TEA5764_TNCTRL_MU;
+       else
+               r->tnctrl &= ~TEA5764_TNCTRL_MU;
+       if (tnctrl != r->tnctrl)
+               tea5764_i2c_write(radio);
+}
+
+static int tea5764_is_muted(struct tea5764_device *radio)
+{
+       return radio->regs.tnctrl & TEA5764_TNCTRL_MU;
+}
+
+/* V4L2 vidioc */
+static int vidioc_querycap(struct file *file, void  *priv,
+                                       struct v4l2_capability *v)
+{
+       struct tea5764_device *radio = video_drvdata(file);
+       struct video_device *dev = radio->videodev;
+
+       strlcpy(v->driver, dev->dev.driver->name, sizeof(v->driver));
+       strlcpy(v->card, dev->name, sizeof(v->card));
+       snprintf(v->bus_info, sizeof(v->bus_info), "I2C:%s", dev->dev.bus_id);
+       v->version = RADIO_VERSION;
+       v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
+       return 0;
+}
+
+static int vidioc_g_tuner(struct file *file, void *priv,
+                               struct v4l2_tuner *v)
+{
+       struct tea5764_device *radio = video_drvdata(file);
+       struct tea5764_regs *r = &radio->regs;
+
+       if (v->index > 0)
+               return -EINVAL;
+
+       memset(v, 0, sizeof(v));
+       strcpy(v->name, "FM");
+       v->type = V4L2_TUNER_RADIO;
+       tea5764_i2c_read(radio);
+       v->rangelow   = FREQ_MIN * FREQ_MUL;
+       v->rangehigh  = FREQ_MAX * FREQ_MUL;
+       v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
+       if (r->tunchk & TEA5764_TUNCHK_STEREO)
+                       v->rxsubchans = V4L2_TUNER_SUB_STEREO;
+       v->audmode = tea5764_get_audout_mode(radio);
+       v->signal = TEA5764_TUNCHK_LEVEL(r->tunchk) * 0xffff / 0xf;
+       v->afc = TEA5764_TUNCHK_IFCNT(r->tunchk);
+
+       return 0;
+}
+
+static int vidioc_s_tuner(struct file *file, void *priv,
+                               struct v4l2_tuner *v)
+{
+       struct tea5764_device *radio = video_drvdata(file);
+
+       if (v->index > 0)
+               return -EINVAL;
+
+       tea5764_set_audout_mode(radio, v->audmode);
+       return 0;
+}
+
+static int vidioc_s_frequency(struct file *file, void *priv,
+                               struct v4l2_frequency *f)
+{
+       struct tea5764_device *radio = video_drvdata(file);
+
+       if (f->tuner != 0)
+               return -EINVAL;
+       if (f->frequency == 0) {
+               /* We special case this as a power down control. */
+               tea5764_power_down(radio);
+       }
+       if (f->frequency < (FREQ_MIN * FREQ_MUL))
+               return -EINVAL;
+       if (f->frequency > (FREQ_MAX * FREQ_MUL))
+               return -EINVAL;
+       tea5764_power_up(radio);
+       tea5764_tune(radio, (f->frequency * 125) / 2);
+       return 0;
+}
+
+static int vidioc_g_frequency(struct file *file, void *priv,
+                               struct v4l2_frequency *f)
+{
+       struct tea5764_device *radio = video_drvdata(file);
+       struct tea5764_regs *r = &radio->regs;
+
+       tea5764_i2c_read(radio);
+       memset(f, 0, sizeof(f));
+       f->type = V4L2_TUNER_RADIO;
+       if (r->tnctrl & TEA5764_TNCTRL_PUPD0)
+               f->frequency = (tea5764_get_freq(radio) * 2) / 125;
+       else
+               f->frequency = 0;
+
+       return 0;
+}
+
+static int vidioc_queryctrl(struct file *file, void *priv,
+                           struct v4l2_queryctrl *qc)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
+               if (qc->id && qc->id == radio_qctrl[i].id) {
+                       memcpy(qc, &(radio_qctrl[i]), sizeof(*qc));
+                       return 0;
+               }
+       }
+       return -EINVAL;
+}
+
+static int vidioc_g_ctrl(struct file *file, void *priv,
+                           struct v4l2_control *ctrl)
+{
+       struct tea5764_device *radio = video_drvdata(file);
+
+       switch (ctrl->id) {
+       case V4L2_CID_AUDIO_MUTE:
+               tea5764_i2c_read(radio);
+               ctrl->value = tea5764_is_muted(radio) ? 1 : 0;
+               return 0;
+       }
+       return -EINVAL;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+                           struct v4l2_control *ctrl)
+{
+       struct tea5764_device *radio = video_drvdata(file);
+
+       switch (ctrl->id) {
+       case V4L2_CID_AUDIO_MUTE:
+               tea5764_mute(radio, ctrl->value);
+               return 0;
+       }
+       return -EINVAL;
+}
+
+static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
+{
+       *i = 0;
+       return 0;
+}
+
+static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
+{
+       if (i != 0)
+               return -EINVAL;
+       return 0;
+}
+
+static int vidioc_g_audio(struct file *file, void *priv,
+                          struct v4l2_audio *a)
+{
+       if (a->index > 1)
+               return -EINVAL;
+
+       strcpy(a->name, "Radio");
+       a->capability = V4L2_AUDCAP_STEREO;
+       return 0;
+}
+
+static int vidioc_s_audio(struct file *file, void *priv,
+                          struct v4l2_audio *a)
+{
+       if (a->index != 0)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int tea5764_open(struct file *file)
+{
+       /* Currently we support only one device */
+       int minor = video_devdata(file)->minor;
+       struct tea5764_device *radio = video_drvdata(file);
+
+       if (radio->videodev->minor != minor)
+               return -ENODEV;
+
+       mutex_lock(&radio->mutex);
+       /* Only exclusive access */
+       if (radio->users) {
+               mutex_unlock(&radio->mutex);
+               return -EBUSY;
+       }
+       radio->users++;
+       mutex_unlock(&radio->mutex);
+       file->private_data = radio;
+       return 0;
+}
+
+static int tea5764_close(struct file *file)
+{
+       struct tea5764_device *radio = video_drvdata(file);
+
+       if (!radio)
+               return -ENODEV;
+       mutex_lock(&radio->mutex);
+       radio->users--;
+       mutex_unlock(&radio->mutex);
+       return 0;
+}
+
+/* File system interface */
+static const struct v4l2_file_operations tea5764_fops = {
+       .owner          = THIS_MODULE,
+       .open           = tea5764_open,
+       .release        = tea5764_close,
+       .ioctl          = video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops tea5764_ioctl_ops = {
+       .vidioc_querycap    = vidioc_querycap,
+       .vidioc_g_tuner     = vidioc_g_tuner,
+       .vidioc_s_tuner     = vidioc_s_tuner,
+       .vidioc_g_audio     = vidioc_g_audio,
+       .vidioc_s_audio     = vidioc_s_audio,
+       .vidioc_g_input     = vidioc_g_input,
+       .vidioc_s_input     = vidioc_s_input,
+       .vidioc_g_frequency = vidioc_g_frequency,
+       .vidioc_s_frequency = vidioc_s_frequency,
+       .vidioc_queryctrl   = vidioc_queryctrl,
+       .vidioc_g_ctrl      = vidioc_g_ctrl,
+       .vidioc_s_ctrl      = vidioc_s_ctrl,
+};
+
+/* V4L2 interface */
+static struct video_device tea5764_radio_template = {
+       .name           = "TEA5764 FM-Radio",
+       .fops           = &tea5764_fops,
+       .ioctl_ops      = &tea5764_ioctl_ops,
+       .release        = video_device_release,
+};
+
+/* I2C probe: check if the device exists and register with v4l if it is */
+static int __devinit tea5764_i2c_probe(struct i2c_client *client,
+                                       const struct i2c_device_id *id)
+{
+       struct tea5764_device *radio;
+       struct tea5764_regs *r;
+       int ret;
+
+       PDEBUG("probe");
+       radio = kmalloc(sizeof(struct tea5764_device), GFP_KERNEL);
+       if (!radio)
+               return -ENOMEM;
+
+       mutex_init(&radio->mutex);
+       radio->i2c_client = client;
+       ret = tea5764_i2c_read(radio);
+       if (ret)
+               goto errfr;
+       r = &radio->regs;
+       PDEBUG("chipid = %04X, manid = %04X", r->chipid, r->manid);
+       if (r->chipid != TEA5764_CHIPID ||
+               (r->manid & 0x0fff) != TEA5764_MANID) {
+               PWARN("This chip is not a TEA5764!");
+               ret = -EINVAL;
+               goto errfr;
+       }
+
+       radio->videodev = video_device_alloc();
+       if (!(radio->videodev)) {
+               ret = -ENOMEM;
+               goto errfr;
+       }
+       memcpy(radio->videodev, &tea5764_radio_template,
+               sizeof(tea5764_radio_template));
+
+       i2c_set_clientdata(client, radio);
+       video_set_drvdata(radio->videodev, radio);
+
+       ret = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr);
+       if (ret < 0) {
+               PWARN("Could not register video device!");
+               goto errrel;
+       }
+
+       /* initialize and power off the chip */
+       tea5764_i2c_read(radio);
+       tea5764_set_audout_mode(radio, V4L2_TUNER_MODE_STEREO);
+       tea5764_mute(radio, 1);
+       tea5764_power_down(radio);
+
+       PINFO("registered.");
+       return 0;
+errrel:
+       video_device_release(radio->videodev);
+errfr:
+       kfree(radio);
+       return ret;
+}
+
+static int __devexit tea5764_i2c_remove(struct i2c_client *client)
+{
+       struct tea5764_device *radio = i2c_get_clientdata(client);
+
+       PDEBUG("remove");
+       if (radio) {
+               tea5764_power_down(radio);
+               video_unregister_device(radio->videodev);
+               kfree(radio);
+       }
+       return 0;
+}
+
+/* I2C subsystem interface */
+static const struct i2c_device_id tea5764_id[] = {
+       { "radio-tea5764", 0 },
+       { }                                     /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(i2c, tea5764_id);
+
+static struct i2c_driver tea5764_i2c_driver = {
+       .driver = {
+               .name = "radio-tea5764",
+               .owner = THIS_MODULE,
+       },
+       .probe = tea5764_i2c_probe,
+       .remove = __devexit_p(tea5764_i2c_remove),
+       .id_table = tea5764_id,
+};
+
+/* init the driver */
+static int __init tea5764_init(void)
+{
+       int ret = i2c_add_driver(&tea5764_i2c_driver);
+
+       printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ": "
+               DRIVER_DESC "\n");
+       return ret;
+}
+
+/* cleanup the driver */
+static void __exit tea5764_exit(void)
+{
+       i2c_del_driver(&tea5764_i2c_driver);
+}
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+module_param(use_xtal, int, 1);
+MODULE_PARM_DESC(use_xtal, "Chip have a xtal connected in board");
+module_param(radio_nr, int, 0);
+MODULE_PARM_DESC(radio_nr, "video4linux device number to use");
+
+module_init(tea5764_init);
+module_exit(tea5764_exit);
index 0abb186a9473e5661dd1a117e83acdc9fe034a98..0798d71abd005d67f5a44c924da99a2da06c0330 100644 (file)
@@ -352,26 +352,22 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static struct tt_device terratec_unit;
 
-static int terratec_exclusive_open(struct inode *inode, struct file *file)
+static int terratec_exclusive_open(struct file *file)
 {
        return test_and_set_bit(0, &terratec_unit.in_use) ? -EBUSY : 0;
 }
 
-static int terratec_exclusive_release(struct inode *inode, struct file *file)
+static int terratec_exclusive_release(struct file *file)
 {
        clear_bit(0, &terratec_unit.in_use);
        return 0;
 }
 
-static const struct file_operations terratec_fops = {
+static const struct v4l2_file_operations terratec_fops = {
        .owner          = THIS_MODULE,
        .open           = terratec_exclusive_open,
        .release        = terratec_exclusive_release,
        .ioctl          = video_ioctl2,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = v4l_compat_ioctl32,
-#endif
-       .llseek         = no_llseek,
 };
 
 static const struct v4l2_ioctl_ops terratec_ioctl_ops = {
index e7b111fcd105b6fc79a3a11c922d6edf2a0542e1..bdf9cb6a75f47c7634d99a615cabbf925cbdf740 100644 (file)
@@ -337,26 +337,22 @@ static int vidioc_s_audio(struct file *file, void *priv,
        return 0;
 }
 
-static int trust_exclusive_open(struct inode *inode, struct file *file)
+static int trust_exclusive_open(struct file *file)
 {
        return test_and_set_bit(0, &in_use) ? -EBUSY : 0;
 }
 
-static int trust_exclusive_release(struct inode *inode, struct file *file)
+static int trust_exclusive_release(struct file *file)
 {
        clear_bit(0, &in_use);
        return 0;
 }
 
-static const struct file_operations trust_fops = {
+static const struct v4l2_file_operations trust_fops = {
        .owner          = THIS_MODULE,
        .open           = trust_exclusive_open,
        .release        = trust_exclusive_release,
        .ioctl          = video_ioctl2,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = v4l_compat_ioctl32,
-#endif
-       .llseek         = no_llseek,
 };
 
 static const struct v4l2_ioctl_ops trust_ioctl_ops = {
index 952ec35a8415129100ae56564ee2e956facbccd7..5c3b319dab37cadaadc64c576bc18482e943d444 100644 (file)
@@ -330,26 +330,22 @@ static struct typhoon_device typhoon_unit =
        .mutefreq       = CONFIG_RADIO_TYPHOON_MUTEFREQ,
 };
 
-static int typhoon_exclusive_open(struct inode *inode, struct file *file)
+static int typhoon_exclusive_open(struct file *file)
 {
        return test_and_set_bit(0, &typhoon_unit.in_use) ? -EBUSY : 0;
 }
 
-static int typhoon_exclusive_release(struct inode *inode, struct file *file)
+static int typhoon_exclusive_release(struct file *file)
 {
        clear_bit(0, &typhoon_unit.in_use);
        return 0;
 }
 
-static const struct file_operations typhoon_fops = {
+static const struct v4l2_file_operations typhoon_fops = {
        .owner          = THIS_MODULE,
        .open           = typhoon_exclusive_open,
        .release        = typhoon_exclusive_release,
        .ioctl          = video_ioctl2,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = v4l_compat_ioctl32,
-#endif
-       .llseek         = no_llseek,
 };
 
 static const struct v4l2_ioctl_ops typhoon_ioctl_ops = {
index 15b10bad679660efa22b59bc3d70f161841c07f0..d2ac17eeec5ffeb30c77a3c528cea291af6ec134 100644 (file)
@@ -401,27 +401,23 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static struct zol_device zoltrix_unit;
 
-static int zoltrix_exclusive_open(struct inode *inode, struct file *file)
+static int zoltrix_exclusive_open(struct file *file)
 {
        return test_and_set_bit(0, &zoltrix_unit.in_use) ? -EBUSY : 0;
 }
 
-static int zoltrix_exclusive_release(struct inode *inode, struct file *file)
+static int zoltrix_exclusive_release(struct file *file)
 {
        clear_bit(0, &zoltrix_unit.in_use);
        return 0;
 }
 
-static const struct file_operations zoltrix_fops =
+static const struct v4l2_file_operations zoltrix_fops =
 {
        .owner          = THIS_MODULE,
        .open           = zoltrix_exclusive_open,
        .release        = zoltrix_exclusive_release,
        .ioctl          = video_ioctl2,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = v4l_compat_ioctl32,
-#endif
-       .llseek         = no_llseek,
 };
 
 static const struct v4l2_ioctl_ops zoltrix_ioctl_ops = {
index 1611c33b1aee3593d9a15515a35c971179101d5b..72f6d03d2d8f472600d60208b75d8e9d30d2f691 100644 (file)
@@ -12,7 +12,10 @@ omap2cam-objs        :=      omap24xxcam.o omap24xxcam-dma.o
 
 videodev-objs  :=      v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-subdev.o
 
-obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-compat-ioctl32.o v4l2-int-device.o
+obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-int-device.o
+ifeq ($(CONFIG_COMPAT),y)
+  obj-$(CONFIG_VIDEO_DEV) += v4l2-compat-ioctl32.o
+endif
 
 obj-$(CONFIG_VIDEO_V4L2_COMMON) += v4l2-common.o
 
index 2ba6abd92b6f2932f4dd4c0e9ff3317ca224971c..d137bac84511eb9c3dfdb7c61aef5140a163ec5a 100644 (file)
@@ -396,7 +396,7 @@ out_up:
        return ret;
 }
 
-static int ar_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+static long ar_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 {
        struct video_device *dev = video_devdata(file);
        struct ar_device *ar = video_get_drvdata(dev);
@@ -539,7 +539,7 @@ static int ar_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        return 0;
 }
 
-static int ar_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+static long ar_ioctl(struct file *file, unsigned int cmd,
                    unsigned long arg)
 {
        return video_usercopy(file, cmd, arg, ar_do_ioctl);
@@ -744,27 +744,23 @@ void ar_release(struct video_device *vfd)
  ****************************************************************************/
 static struct ar_device ardev;
 
-static int ar_exclusive_open(struct inode *inode, struct file *file)
+static int ar_exclusive_open(struct file *file)
 {
        return test_and_set_bit(0, &ardev.in_use) ? -EBUSY : 0;
 }
 
-static int ar_exclusive_release(struct inode *inode, struct file *file)
+static int ar_exclusive_release(struct file *file)
 {
        clear_bit(0, &ardev.in_use);
        return 0;
 }
 
-static const struct file_operations ar_fops = {
+static const struct v4l2_file_operations ar_fops = {
        .owner          = THIS_MODULE,
        .open           = ar_exclusive_open,
        .release        = ar_exclusive_release,
        .read           = ar_read,
        .ioctl          = ar_ioctl,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = v4l_compat_ioctl32,
-#endif
-       .llseek         = no_llseek,
 };
 
 static struct video_device ar_template = {
index 9ec4cec2e52dada612a8857a1033325f6cb5415a..c71f394fc0ead807e04b166b2a300c4bf2978326 100644 (file)
@@ -2039,7 +2039,7 @@ static int bttv_log_status(struct file *file, void *f)
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 static int bttv_g_register(struct file *file, void *f,
-                                       struct v4l2_register *reg)
+                                       struct v4l2_dbg_register *reg)
 {
        struct bttv_fh *fh = f;
        struct bttv *btv = fh->btv;
@@ -2047,18 +2047,19 @@ static int bttv_g_register(struct file *file, void *f,
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
-       if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
+       if (!v4l2_chip_match_host(&reg->match))
                return -EINVAL;
 
        /* bt848 has a 12-bit register space */
        reg->reg &= 0xfff;
        reg->val = btread(reg->reg);
+       reg->size = 1;
 
        return 0;
 }
 
 static int bttv_s_register(struct file *file, void *f,
-                                       struct v4l2_register *reg)
+                                       struct v4l2_dbg_register *reg)
 {
        struct bttv_fh *fh = f;
        struct bttv *btv = fh->btv;
@@ -2066,7 +2067,7 @@ static int bttv_s_register(struct file *file, void *f,
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
-       if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
+       if (!v4l2_chip_match_host(&reg->match))
                return -EINVAL;
 
        /* bt848 has a 12-bit register space */
@@ -3208,9 +3209,9 @@ err:
        return POLLERR;
 }
 
-static int bttv_open(struct inode *inode, struct file *file)
+static int bttv_open(struct file *file)
 {
-       int minor = iminor(inode);
+       int minor = video_devdata(file)->minor;
        struct bttv *btv = NULL;
        struct bttv_fh *fh;
        enum v4l2_buf_type type = 0;
@@ -3291,7 +3292,7 @@ static int bttv_open(struct inode *inode, struct file *file)
        return 0;
 }
 
-static int bttv_release(struct inode *inode, struct file *file)
+static int bttv_release(struct file *file)
 {
        struct bttv_fh *fh = file->private_data;
        struct bttv *btv = fh->btv;
@@ -3346,14 +3347,12 @@ bttv_mmap(struct file *file, struct vm_area_struct *vma)
        return videobuf_mmap_mapper(bttv_queue(fh),vma);
 }
 
-static const struct file_operations bttv_fops =
+static const struct v4l2_file_operations bttv_fops =
 {
        .owner    = THIS_MODULE,
        .open     = bttv_open,
        .release  = bttv_release,
        .ioctl    = video_ioctl2,
-       .compat_ioctl   = v4l_compat_ioctl32,
-       .llseek   = no_llseek,
        .read     = bttv_read,
        .mmap     = bttv_mmap,
        .poll     = bttv_poll,
@@ -3422,9 +3421,9 @@ static struct video_device bttv_video_template = {
 /* ----------------------------------------------------------------------- */
 /* radio interface                                                         */
 
-static int radio_open(struct inode *inode, struct file *file)
+static int radio_open(struct file *file)
 {
-       int minor = iminor(inode);
+       int minor = video_devdata(file)->minor;
        struct bttv *btv = NULL;
        struct bttv_fh *fh;
        unsigned int i;
@@ -3467,12 +3466,13 @@ static int radio_open(struct inode *inode, struct file *file)
        return 0;
 }
 
-static int radio_release(struct inode *inode, struct file *file)
+static int radio_release(struct file *file)
 {
        struct bttv_fh *fh = file->private_data;
        struct bttv *btv = fh->btv;
        struct rds_command cmd;
 
+       v4l2_prio_close(&btv->prio,&fh->prio);
        file->private_data = NULL;
        kfree(fh);
 
@@ -3633,15 +3633,13 @@ static unsigned int radio_poll(struct file *file, poll_table *wait)
        return cmd.result;
 }
 
-static const struct file_operations radio_fops =
+static const struct v4l2_file_operations radio_fops =
 {
        .owner    = THIS_MODULE,
        .open     = radio_open,
        .read     = radio_read,
        .release  = radio_release,
-       .compat_ioctl   = v4l_compat_ioctl32,
        .ioctl    = video_ioctl2,
-       .llseek   = no_llseek,
        .poll     = radio_poll,
 };
 
index 17f80d03f38e4e2f6780fa1d10e63aa2b40e9126..10dbd4a11b30f8e4aaf7e0ac2fad97f69bb56dbb 100644 (file)
@@ -706,7 +706,7 @@ static long qc_capture(struct qcam_device * q, char __user *buf, unsigned long l
  *     Video4linux interfacing
  */
 
-static int qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+static long qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 {
        struct video_device *dev = video_devdata(file);
        struct qcam_device *qcam=(struct qcam_device *)dev;
@@ -863,7 +863,7 @@ static int qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        return 0;
 }
 
-static int qcam_ioctl(struct inode *inode, struct file *file,
+static long qcam_ioctl(struct file *file,
                     unsigned int cmd, unsigned long arg)
 {
        return video_usercopy(file, cmd, arg, qcam_do_ioctl);
@@ -893,7 +893,7 @@ static ssize_t qcam_read(struct file *file, char __user *buf,
        return len;
 }
 
-static int qcam_exclusive_open(struct inode *inode, struct file *file)
+static int qcam_exclusive_open(struct file *file)
 {
        struct video_device *dev = video_devdata(file);
        struct qcam_device *qcam = (struct qcam_device *)dev;
@@ -901,7 +901,7 @@ static int qcam_exclusive_open(struct inode *inode, struct file *file)
        return test_and_set_bit(0, &qcam->in_use) ? -EBUSY : 0;
 }
 
-static int qcam_exclusive_release(struct inode *inode, struct file *file)
+static int qcam_exclusive_release(struct file *file)
 {
        struct video_device *dev = video_devdata(file);
        struct qcam_device *qcam = (struct qcam_device *)dev;
@@ -910,16 +910,12 @@ static int qcam_exclusive_release(struct inode *inode, struct file *file)
        return 0;
 }
 
-static const struct file_operations qcam_fops = {
+static const struct v4l2_file_operations qcam_fops = {
        .owner          = THIS_MODULE,
        .open           = qcam_exclusive_open,
        .release        = qcam_exclusive_release,
        .ioctl          = qcam_ioctl,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = v4l_compat_ioctl32,
-#endif
        .read           = qcam_read,
-       .llseek         = no_llseek,
 };
 static struct video_device qcam_template=
 {
index 21c71eb085db53ba232d17fb73c4ba868f936e19..85cf1778827adee718ba6ad930bfec12d37be25d 100644 (file)
@@ -500,7 +500,7 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le
  *     Video4linux interfacing
  */
 
-static int qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+static long qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 {
        struct video_device *dev = video_devdata(file);
        struct qcam_device *qcam=(struct qcam_device *)dev;
@@ -665,7 +665,7 @@ static int qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        return 0;
 }
 
-static int qcam_ioctl(struct inode *inode, struct file *file,
+static long qcam_ioctl(struct file *file,
                      unsigned int cmd, unsigned long arg)
 {
        return video_usercopy(file, cmd, arg, qcam_do_ioctl);
@@ -687,7 +687,7 @@ static ssize_t qcam_read(struct file *file, char __user *buf,
        return len;
 }
 
-static int qcam_exclusive_open(struct inode *inode, struct file *file)
+static int qcam_exclusive_open(struct file *file)
 {
        struct video_device *dev = video_devdata(file);
        struct qcam_device *qcam = (struct qcam_device *)dev;
@@ -695,7 +695,7 @@ static int qcam_exclusive_open(struct inode *inode, struct file *file)
        return test_and_set_bit(0, &qcam->in_use) ? -EBUSY : 0;
 }
 
-static int qcam_exclusive_release(struct inode *inode, struct file *file)
+static int qcam_exclusive_release(struct file *file)
 {
        struct video_device *dev = video_devdata(file);
        struct qcam_device *qcam = (struct qcam_device *)dev;
@@ -705,16 +705,12 @@ static int qcam_exclusive_release(struct inode *inode, struct file *file)
 }
 
 /* video device template */
-static const struct file_operations qcam_fops = {
+static const struct v4l2_file_operations qcam_fops = {
        .owner          = THIS_MODULE,
        .open           = qcam_exclusive_open,
        .release        = qcam_exclusive_release,
        .ioctl          = qcam_ioctl,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = v4l_compat_ioctl32,
-#endif
        .read           = qcam_read,
-       .llseek         = no_llseek,
 };
 
 static struct video_device qcam_template=
index 1740b9ebdcefef613c0c2287a854798380c9a4e0..34a39d2e4703843bc7a0dfd2dc9431f5de149907 100644 (file)
@@ -859,7 +859,7 @@ static int __cafe_cam_reset(struct cafe_camera *cam)
  */
 static int cafe_cam_init(struct cafe_camera *cam)
 {
-       struct v4l2_chip_ident chip = { V4L2_CHIP_MATCH_I2C_ADDR, 0, 0, 0 };
+       struct v4l2_dbg_chip_ident chip;
        int ret;
 
        mutex_lock(&cam->s_mutex);
@@ -869,8 +869,9 @@ static int cafe_cam_init(struct cafe_camera *cam)
        ret = __cafe_cam_reset(cam);
        if (ret)
                goto out;
-       chip.match_chip = cam->sensor->addr;
-       ret = __cafe_cam_cmd(cam, VIDIOC_G_CHIP_IDENT, &chip);
+       chip.match.type = V4L2_CHIP_MATCH_I2C_ADDR;
+       chip.match.addr = cam->sensor->addr;
+       ret = __cafe_cam_cmd(cam, VIDIOC_DBG_G_CHIP_IDENT, &chip);
        if (ret)
                goto out;
        cam->sensor_type = chip.ident;
@@ -1472,11 +1473,11 @@ static int cafe_v4l_mmap(struct file *filp, struct vm_area_struct *vma)
 
 
 
-static int cafe_v4l_open(struct inode *inode, struct file *filp)
+static int cafe_v4l_open(struct file *filp)
 {
        struct cafe_camera *cam;
 
-       cam = cafe_find_dev(iminor(inode));
+       cam = cafe_find_dev(video_devdata(filp)->minor);
        if (cam == NULL)
                return -ENODEV;
        filp->private_data = cam;
@@ -1494,7 +1495,7 @@ static int cafe_v4l_open(struct inode *inode, struct file *filp)
 }
 
 
-static int cafe_v4l_release(struct inode *inode, struct file *filp)
+static int cafe_v4l_release(struct file *filp)
 {
        struct cafe_camera *cam = filp->private_data;
 
@@ -1759,7 +1760,7 @@ static void cafe_v4l_dev_release(struct video_device *vd)
  * clone it for specific real devices.
  */
 
-static const struct file_operations cafe_v4l_fops = {
+static const struct v4l2_file_operations cafe_v4l_fops = {
        .owner = THIS_MODULE,
        .open = cafe_v4l_open,
        .release = cafe_v4l_release,
@@ -1767,7 +1768,6 @@ static const struct file_operations cafe_v4l_fops = {
        .poll = cafe_v4l_poll,
        .mmap = cafe_v4l_mmap,
        .ioctl = video_ioctl2,
-       .llseek = no_llseek,
 };
 
 static const struct v4l2_ioctl_ops cafe_v4l_ioctl_ops = {
index 028a400d2453b64f4658091cfa0c86eb71b833db..c3b0c8c63c7642601a2b14feceb5a1f55ff86a78 100644 (file)
@@ -3148,7 +3148,7 @@ static void put_cam(struct cpia_camera_ops* ops)
 }
 
 /* ------------------------- V4L interface --------------------- */
-static int cpia_open(struct inode *inode, struct file *file)
+static int cpia_open(struct file *file)
 {
        struct video_device *dev = video_devdata(file);
        struct cam_data *cam = video_get_drvdata(dev);
@@ -3225,7 +3225,7 @@ static int cpia_open(struct inode *inode, struct file *file)
        return err;
 }
 
-static int cpia_close(struct inode *inode, struct file *file)
+static int cpia_close(struct file *file)
 {
        struct  video_device *dev = file->private_data;
        struct cam_data *cam = video_get_drvdata(dev);
@@ -3333,7 +3333,7 @@ static ssize_t cpia_read(struct file *file, char __user *buf,
        return cam->decompressed_frame.count;
 }
 
-static int cpia_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+static long cpia_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 {
        struct video_device *dev = file->private_data;
        struct cam_data *cam = video_get_drvdata(dev);
@@ -3720,7 +3720,7 @@ static int cpia_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        return retval;
 }
 
-static int cpia_ioctl(struct inode *inode, struct file *file,
+static long cpia_ioctl(struct file *file,
                     unsigned int cmd, unsigned long arg)
 {
        return video_usercopy(file, cmd, arg, cpia_do_ioctl);
@@ -3780,17 +3780,13 @@ static int cpia_mmap(struct file *file, struct vm_area_struct *vma)
        return 0;
 }
 
-static const struct file_operations cpia_fops = {
+static const struct v4l2_file_operations cpia_fops = {
        .owner          = THIS_MODULE,
        .open           = cpia_open,
        .release        = cpia_close,
        .read           = cpia_read,
        .mmap           = cpia_mmap,
        .ioctl          = cpia_ioctl,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = v4l_compat_ioctl32,
-#endif
-       .llseek         = no_llseek,
 };
 
 static struct video_device cpia_template = {
index 3c2d7eac119713d5704075e054ed5b21fa52f040..9c25894fdd8e7b19050ae7c3e58d67d45c5b11d7 100644 (file)
@@ -239,7 +239,7 @@ static struct v4l2_queryctrl controls[] = {
  *  cpia2_open
  *
  *****************************************************************************/
-static int cpia2_open(struct inode *inode, struct file *file)
+static int cpia2_open(struct file *file)
 {
        struct camera_data *cam = video_drvdata(file);
        int retval = 0;
@@ -302,7 +302,7 @@ err_return:
  *  cpia2_close
  *
  *****************************************************************************/
-static int cpia2_close(struct inode *inode, struct file *file)
+static int cpia2_close(struct file *file)
 {
        struct video_device *dev = video_devdata(file);
        struct camera_data *cam = video_get_drvdata(dev);
@@ -1572,10 +1572,10 @@ static int ioctl_dqbuf(void *arg,struct camera_data *cam, struct file *file)
  *  cpia2_ioctl
  *
  *****************************************************************************/
-static int cpia2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+static long cpia2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 {
        struct camera_data *cam = video_drvdata(file);
-       int retval = 0;
+       long retval = 0;
 
        if (!cam)
                return -ENOTTY;
@@ -1841,7 +1841,7 @@ static int cpia2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        return retval;
 }
 
-static int cpia2_ioctl(struct inode *inode, struct file *file,
+static long cpia2_ioctl(struct file *file,
                       unsigned int cmd, unsigned long arg)
 {
        return video_usercopy(file, cmd, arg, cpia2_do_ioctl);
@@ -1912,17 +1912,13 @@ static void reset_camera_struct_v4l(struct camera_data *cam)
 /***
  * The v4l video device structure initialized for this device
  ***/
-static const struct file_operations fops_template = {
+static const struct v4l2_file_operations fops_template = {
        .owner          = THIS_MODULE,
        .open           = cpia2_open,
        .release        = cpia2_close,
        .read           = cpia2_v4l_read,
        .poll           = cpia2_v4l_poll,
        .ioctl          = cpia2_ioctl,
-       .llseek         = no_llseek,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = v4l_compat_ioctl32,
-#endif
        .mmap           = cpia2_mmap,
 };
 
index 70fcd0d5de13bf50b968d14ba522d545a1e813ff..14bebf8a116ffe2b4afc6546bc80eb66ef2b110d 100644 (file)
@@ -95,25 +95,24 @@ static int cs5345_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
 }
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-static int cs5345_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
+static int cs5345_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
 
-       if (!v4l2_chip_match_i2c_client(client,
-                               reg->match_type, reg->match_chip))
+       if (!v4l2_chip_match_i2c_client(client, &reg->match))
                return -EINVAL;
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
+       reg->size = 1;
        reg->val = cs5345_read(sd, reg->reg & 0x1f);
        return 0;
 }
 
-static int cs5345_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
+static int cs5345_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
 
-       if (!v4l2_chip_match_i2c_client(client,
-                               reg->match_type, reg->match_chip))
+       if (!v4l2_chip_match_i2c_client(client, &reg->match))
                return -EINVAL;
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
@@ -122,7 +121,7 @@ static int cs5345_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
 }
 #endif
 
-static int cs5345_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip)
+static int cs5345_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
 
index cb65d519cf78e463c0fa71b806521334c17ede3f..7292a6316e63baa8cf278411b61591ff6f39a237 100644 (file)
@@ -102,7 +102,7 @@ static int cs53l32a_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
        return 0;
 }
 
-static int cs53l32a_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip)
+static int cs53l32a_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
 
index 425271a29517e91534e6762163ced38f61a0cbe7..055f6e004b2dccd8d6daf7e877b23b07733bed2d 100644 (file)
@@ -552,7 +552,7 @@ void cx18_stop_capture(struct cx18_open_id *id, int gop_end)
        }
 }
 
-int cx18_v4l2_close(struct inode *inode, struct file *filp)
+int cx18_v4l2_close(struct file *filp)
 {
        struct cx18_open_id *id = filp->private_data;
        struct cx18 *cx = id->cx;
@@ -650,12 +650,12 @@ static int cx18_serialized_open(struct cx18_stream *s, struct file *filp)
        return 0;
 }
 
-int cx18_v4l2_open(struct inode *inode, struct file *filp)
+int cx18_v4l2_open(struct file *filp)
 {
        int res, x, y = 0;
        struct cx18 *cx = NULL;
        struct cx18_stream *s = NULL;
-       int minor = iminor(inode);
+       int minor = video_devdata(filp)->minor;
 
        /* Find which card this open was on */
        spin_lock(&cx18_cards_lock);
index 46da0282fc7d71bf9b1c324226989e29229c665e..92e2d5dab936e15897b1652e1ab6737b368dd21d 100644 (file)
  */
 
 /* Testing/Debugging */
-int cx18_v4l2_open(struct inode *inode, struct file *filp);
+int cx18_v4l2_open(struct file *filp);
 ssize_t cx18_v4l2_read(struct file *filp, char __user *buf, size_t count,
                      loff_t *pos);
 ssize_t cx18_v4l2_write(struct file *filp, const char __user *buf, size_t count,
                       loff_t *pos);
-int cx18_v4l2_close(struct inode *inode, struct file *filp);
+int cx18_v4l2_close(struct file *filp);
 unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait);
 int cx18_start_capture(struct cx18_open_id *id);
 void cx18_stop_capture(struct cx18_open_id *id, int gop_end);
index 8941f58bed7f042ce5cce8a97bbfeb33ef20bd79..83e1c6333126eabf84da60d05d0a45fc6274a6cf 100644 (file)
@@ -242,7 +242,7 @@ int cx18_call_i2c_client(struct cx18 *cx, int addr, unsigned cmd, void *arg)
                        return retval;
                }
        }
-       if (cmd != VIDIOC_G_CHIP_IDENT)
+       if (cmd != VIDIOC_DBG_G_CHIP_IDENT)
                CX18_ERR("i2c addr 0x%02x not found for cmd 0x%x!\n",
                               addr, cmd);
        return -ENODEV;
@@ -268,17 +268,6 @@ static int cx18_i2c_id_addr(struct cx18 *cx, u32 id)
        return retval;
 }
 
-/* Find the i2c device name matching the DRIVERID */
-static const char *cx18_i2c_id_name(u32 id)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(hw_driverids); i++)
-               if (hw_driverids[i] == id)
-                       return hw_devicenames[i];
-       return "unknown device";
-}
-
 /* Find the i2c device name matching the CX18_HW_ flag */
 static const char *cx18_i2c_hw_name(u32 hw)
 {
@@ -326,21 +315,6 @@ int cx18_i2c_hw(struct cx18 *cx, u32 hw, unsigned int cmd, void *arg)
        return cx18_call_i2c_client(cx, addr, cmd, arg);
 }
 
-/* Calls i2c device based on I2C driver ID. */
-int cx18_i2c_id(struct cx18 *cx, u32 id, unsigned int cmd, void *arg)
-{
-       int addr;
-
-       addr = cx18_i2c_id_addr(cx, id);
-       if (addr < 0) {
-               if (cmd != VIDIOC_G_CHIP_IDENT)
-                       CX18_ERR("i2c ID 0x%08x (%s) not found for cmd 0x%x!\n",
-                               id, cx18_i2c_id_name(id), cmd);
-               return addr;
-       }
-       return cx18_call_i2c_client(cx, addr, cmd, arg);
-}
-
 /* broadcast cmd for all I2C clients and for the gpio subsystem */
 void cx18_call_i2c_clients(struct cx18 *cx, unsigned int cmd, void *arg)
 {
index 113c3f9a2cc0781ad6dc3d4c7c3000c32d645401..4869739013bdf3fbd68f37696f890256f89961d6 100644 (file)
@@ -23,7 +23,6 @@
 
 int cx18_i2c_hw_addr(struct cx18 *cx, u32 hw);
 int cx18_i2c_hw(struct cx18 *cx, u32 hw, unsigned int cmd, void *arg);
-int cx18_i2c_id(struct cx18 *cx, u32 id, unsigned int cmd, void *arg);
 int cx18_call_i2c_client(struct cx18 *cx, int addr, unsigned cmd, void *arg);
 void cx18_call_i2c_clients(struct cx18 *cx, unsigned int cmd, void *arg);
 int cx18_i2c_register(struct cx18 *cx, unsigned idx);
index e6087486f889d77b997c9eafd62ae01d69f0fbfa..7086aaba77d677ed5cc9f8d697b0206be56d4f17 100644 (file)
@@ -254,30 +254,24 @@ static int cx18_s_fmt_sliced_vbi_cap(struct file *file, void *fh,
 }
 
 static int cx18_g_chip_ident(struct file *file, void *fh,
-                               struct v4l2_chip_ident *chip)
+                               struct v4l2_dbg_chip_ident *chip)
 {
        struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
 
        chip->ident = V4L2_IDENT_NONE;
        chip->revision = 0;
-       if (chip->match_type == V4L2_CHIP_MATCH_HOST) {
-               if (v4l2_chip_match_host(chip->match_type, chip->match_chip))
-                       chip->ident = V4L2_IDENT_CX23418;
+       if (v4l2_chip_match_host(&chip->match)) {
+               chip->ident = V4L2_IDENT_CX23418;
                return 0;
        }
-       if (chip->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
-               return cx18_i2c_id(cx, chip->match_chip, VIDIOC_G_CHIP_IDENT,
-                                       chip);
-       if (chip->match_type == V4L2_CHIP_MATCH_I2C_ADDR)
-               return cx18_call_i2c_client(cx, chip->match_chip,
-                                               VIDIOC_G_CHIP_IDENT, chip);
-       return -EINVAL;
+       cx18_call_i2c_clients(cx, VIDIOC_DBG_G_CHIP_IDENT, chip);
+       return 0;
 }
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 static int cx18_cxc(struct cx18 *cx, unsigned int cmd, void *arg)
 {
-       struct v4l2_register *regs = arg;
+       struct v4l2_dbg_register *regs = arg;
        unsigned long flags;
 
        if (!capable(CAP_SYS_ADMIN))
@@ -286,6 +280,7 @@ static int cx18_cxc(struct cx18 *cx, unsigned int cmd, void *arg)
                return -EINVAL;
 
        spin_lock_irqsave(&cx18_cards_lock, flags);
+       regs->size = 4;
        if (cmd == VIDIOC_DBG_G_REGISTER)
                regs->val = cx18_read_enc(cx, regs->reg);
        else
@@ -295,31 +290,25 @@ static int cx18_cxc(struct cx18 *cx, unsigned int cmd, void *arg)
 }
 
 static int cx18_g_register(struct file *file, void *fh,
-                               struct v4l2_register *reg)
+                               struct v4l2_dbg_register *reg)
 {
        struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
 
-       if (v4l2_chip_match_host(reg->match_type, reg->match_chip))
+       if (v4l2_chip_match_host(&reg->match))
                return cx18_cxc(cx, VIDIOC_DBG_G_REGISTER, reg);
-       if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
-               return cx18_i2c_id(cx, reg->match_chip, VIDIOC_DBG_G_REGISTER,
-                                       reg);
-       return cx18_call_i2c_client(cx, reg->match_chip, VIDIOC_DBG_G_REGISTER,
-                                       reg);
+       cx18_call_i2c_clients(cx, VIDIOC_DBG_G_REGISTER, reg);
+       return 0;
 }
 
 static int cx18_s_register(struct file *file, void *fh,
-                               struct v4l2_register *reg)
+                               struct v4l2_dbg_register *reg)
 {
        struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
 
-       if (v4l2_chip_match_host(reg->match_type, reg->match_chip))
+       if (v4l2_chip_match_host(&reg->match))
                return cx18_cxc(cx, VIDIOC_DBG_S_REGISTER, reg);
-       if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
-               return cx18_i2c_id(cx, reg->match_chip, VIDIOC_DBG_S_REGISTER,
-                                       reg);
-       return cx18_call_i2c_client(cx, reg->match_chip, VIDIOC_DBG_S_REGISTER,
-                                       reg);
+       cx18_call_i2c_clients(cx, VIDIOC_DBG_S_REGISTER, reg);
+       return 0;
 }
 #endif
 
@@ -755,7 +744,7 @@ static int cx18_log_status(struct file *file, void *fh)
        return 0;
 }
 
-static int cx18_default(struct file *file, void *fh, int cmd, void *arg)
+static long cx18_default(struct file *file, void *fh, int cmd, void *arg)
 {
        struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
 
@@ -783,19 +772,19 @@ static int cx18_default(struct file *file, void *fh, int cmd, void *arg)
        return 0;
 }
 
-int cx18_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+long cx18_v4l2_ioctl(struct file *filp, unsigned int cmd,
                    unsigned long arg)
 {
        struct video_device *vfd = video_devdata(filp);
        struct cx18_open_id *id = (struct cx18_open_id *)filp->private_data;
        struct cx18 *cx = id->cx;
-       int res;
+       long res;
 
        mutex_lock(&cx->serialize_lock);
 
        if (cx18_debug & CX18_DBGFLG_IOCTL)
                vfd->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
-       res = video_ioctl2(inode, filp, cmd, arg);
+       res = video_ioctl2(filp, cmd, arg);
        vfd->debug = 0;
        mutex_unlock(&cx->serialize_lock);
        return res;
index 08fe24e9510e816926b54714bd964271134ca28c..e2ca0d1521165fd210a14e8f535724e0a38d249f 100644 (file)
@@ -29,5 +29,5 @@ void cx18_set_funcs(struct video_device *vdev);
 int cx18_s_std(struct file *file, void *fh, v4l2_std_id *std);
 int cx18_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf);
 int cx18_s_input(struct file *file, void *fh, unsigned int inp);
-int cx18_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+long cx18_v4l2_ioctl(struct file *filp, unsigned int cmd,
                    unsigned long arg);
index 63c336c95ff5005e9220361b55c6347fdb7ec401..89c1ec94f33593b590ae0039b09597e72d29b5fa 100644 (file)
 
 #define CX18_DSP0_INTERRUPT_MASK       0xd0004C
 
-static struct file_operations cx18_v4l2_enc_fops = {
+static struct v4l2_file_operations cx18_v4l2_enc_fops = {
        .owner = THIS_MODULE,
        .read = cx18_v4l2_read,
        .open = cx18_v4l2_open,
        /* FIXME change to video_ioctl2 if serialization lock can be removed */
        .ioctl = cx18_v4l2_ioctl,
-       .compat_ioctl = v4l_compat_ioctl32,
        .release = cx18_v4l2_close,
        .poll = cx18_v4l2_enc_poll,
 };
@@ -61,49 +60,41 @@ static struct {
        int num_offset;
        int dma;
        enum v4l2_buf_type buf_type;
-       struct file_operations *fops;
 } cx18_stream_info[] = {
        {       /* CX18_ENC_STREAM_TYPE_MPG */
                "encoder MPEG",
                VFL_TYPE_GRABBER, 0,
                PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
-               &cx18_v4l2_enc_fops
        },
        {       /* CX18_ENC_STREAM_TYPE_TS */
                "TS",
                VFL_TYPE_GRABBER, -1,
                PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
-               &cx18_v4l2_enc_fops
        },
        {       /* CX18_ENC_STREAM_TYPE_YUV */
                "encoder YUV",
                VFL_TYPE_GRABBER, CX18_V4L2_ENC_YUV_OFFSET,
                PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
-               &cx18_v4l2_enc_fops
        },
        {       /* CX18_ENC_STREAM_TYPE_VBI */
                "encoder VBI",
                VFL_TYPE_VBI, 0,
                PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VBI_CAPTURE,
-               &cx18_v4l2_enc_fops
        },
        {       /* CX18_ENC_STREAM_TYPE_PCM */
                "encoder PCM audio",
                VFL_TYPE_GRABBER, CX18_V4L2_ENC_PCM_OFFSET,
                PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_PRIVATE,
-               &cx18_v4l2_enc_fops
        },
        {       /* CX18_ENC_STREAM_TYPE_IDX */
                "encoder IDX",
                VFL_TYPE_GRABBER, -1,
                PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
-               &cx18_v4l2_enc_fops
        },
        {       /* CX18_ENC_STREAM_TYPE_RAD */
                "encoder radio",
                VFL_TYPE_RADIO, 0,
                PCI_DMA_NONE, V4L2_BUF_TYPE_PRIVATE,
-               &cx18_v4l2_enc_fops
        },
 };
 
@@ -184,7 +175,7 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
 
        s->v4l2dev->num = num;
        s->v4l2dev->parent = &cx->dev->dev;
-       s->v4l2dev->fops = cx18_stream_info[type].fops;
+       s->v4l2dev->fops = &cx18_v4l2_enc_fops;
        s->v4l2dev->release = video_device_release;
        s->v4l2dev->tvnorms = V4L2_STD_ALL;
        cx18_set_funcs(s->v4l2dev);
index 798d240243536a2f79fcf218a2616ccd154ad629..8f1db57bd1dd8cefc4fcd7b55865429ec04491bd 100644 (file)
@@ -1027,12 +1027,13 @@ static int cx23885_initialize_codec(struct cx23885_dev *dev)
                        printk(KERN_ERR "%s() f/w load failed\n", __func__);
                        return retval;
                }
-               dev->cx23417_mailbox = cx23885_find_mailbox(dev);
-               if (dev->cx23417_mailbox < 0) {
+               retval = cx23885_find_mailbox(dev);
+               if (retval < 0) {
                        printk(KERN_ERR "%s() mailbox < 0, error\n",
                                __func__);
                        return -1;
                }
+               dev->cx23417_mailbox = retval;
                retval = cx23885_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0);
                if (retval < 0) {
                        printk(KERN_ERR
@@ -1573,9 +1574,9 @@ static int vidioc_queryctrl(struct file *file, void *priv,
        return cx23885_queryctrl(dev, c);
 }
 
-static int mpeg_open(struct inode *inode, struct file *file)
+static int mpeg_open(struct file *file)
 {
-       int minor = iminor(inode);
+       int minor = video_devdata(file)->minor;
        struct cx23885_dev *h, *dev = NULL;
        struct list_head *list;
        struct cx23885_fh *fh;
@@ -1617,7 +1618,7 @@ static int mpeg_open(struct inode *inode, struct file *file)
        return 0;
 }
 
-static int mpeg_release(struct inode *inode, struct file *file)
+static int mpeg_release(struct file *file)
 {
        struct cx23885_fh  *fh  = file->private_data;
        struct cx23885_dev *dev = fh->dev;
@@ -1694,15 +1695,13 @@ static int mpeg_mmap(struct file *file, struct vm_area_struct *vma)
        return videobuf_mmap_mapper(&fh->mpegq, vma);
 }
 
-static struct file_operations mpeg_fops = {
+static struct v4l2_file_operations mpeg_fops = {
        .owner         = THIS_MODULE,
        .open          = mpeg_open,
        .release       = mpeg_release,
        .read          = mpeg_read,
        .poll          = mpeg_poll,
        .mmap          = mpeg_mmap,
-       .ioctl         = video_ioctl2,
-       .llseek        = no_llseek,
 };
 
 static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
index c742a10be5cb2f9a94972b5f20d9eeb5ad355063..2d81c4d043403297b504a2b77b5a17560cde31c7 100644 (file)
@@ -718,9 +718,9 @@ static int get_resource(struct cx23885_fh *fh)
        }
 }
 
-static int video_open(struct inode *inode, struct file *file)
+static int video_open(struct file *file)
 {
-       int minor = iminor(inode);
+       int minor = video_devdata(file)->minor;
        struct cx23885_dev *h, *dev = NULL;
        struct cx23885_fh *fh;
        struct list_head *list;
@@ -834,7 +834,7 @@ static unsigned int video_poll(struct file *file,
        return 0;
 }
 
-static int video_release(struct inode *inode, struct file *file)
+static int video_release(struct file *file)
 {
        struct cx23885_fh *fh = file->private_data;
        struct cx23885_dev *dev = fh->dev;
@@ -1326,11 +1326,11 @@ static int vidioc_s_frequency(struct file *file, void *priv,
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 static int vidioc_g_register(struct file *file, void *fh,
-                               struct v4l2_register *reg)
+                               struct v4l2_dbg_register *reg)
 {
        struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev;
 
-       if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
+       if (!v4l2_chip_match_host(&reg->match))
                return -EINVAL;
 
        cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_DBG_G_REGISTER, reg);
@@ -1339,11 +1339,11 @@ static int vidioc_g_register(struct file *file, void *fh,
 }
 
 static int vidioc_s_register(struct file *file, void *fh,
-                               struct v4l2_register *reg)
+                               struct v4l2_dbg_register *reg)
 {
        struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev;
 
-       if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
+       if (!v4l2_chip_match_host(&reg->match))
                return -EINVAL;
 
        cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_DBG_S_REGISTER, reg);
@@ -1422,7 +1422,7 @@ int cx23885_video_irq(struct cx23885_dev *dev, u32 status)
 /* ----------------------------------------------------------- */
 /* exported stuff                                              */
 
-static const struct file_operations video_fops = {
+static const struct v4l2_file_operations video_fops = {
        .owner         = THIS_MODULE,
        .open          = video_open,
        .release       = video_release,
@@ -1430,8 +1430,6 @@ static const struct file_operations video_fops = {
        .poll          = video_poll,
        .mmap          = video_mmap,
        .ioctl         = video_ioctl2,
-       .compat_ioctl  = v4l_compat_ioctl32,
-       .llseek        = no_llseek,
 };
 
 static const struct v4l2_ioctl_ops video_ioctl_ops = {
@@ -1479,13 +1477,11 @@ static struct video_device cx23885_video_template = {
        .current_norm         = V4L2_STD_NTSC_M,
 };
 
-static const struct file_operations radio_fops = {
+static const struct v4l2_file_operations radio_fops = {
        .owner         = THIS_MODULE,
        .open          = video_open,
        .release       = video_release,
        .ioctl         = video_ioctl2,
-       .compat_ioctl  = v4l_compat_ioctl32,
-       .llseek        = no_llseek,
 };
 
 
index 2ad277189da820fd83478fb5d0369959f1de3ae6..88f2fd32bfe357617f82f011df18a9c31ddf7997 100644 (file)
@@ -1120,25 +1120,24 @@ static int cx25840_init(struct v4l2_subdev *sd, u32 val)
 }
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-static int cx25840_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
+static int cx25840_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
 
-       if (!v4l2_chip_match_i2c_client(client,
-                               reg->match_type, reg->match_chip))
+       if (!v4l2_chip_match_i2c_client(client, &reg->match))
                return -EINVAL;
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
+       reg->size = 1;
        reg->val = cx25840_read(client, reg->reg & 0x0fff);
        return 0;
 }
 
-static int cx25840_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
+static int cx25840_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
 
-       if (!v4l2_chip_match_i2c_client(client,
-                               reg->match_type, reg->match_chip))
+       if (!v4l2_chip_match_i2c_client(client, &reg->match))
                return -EINVAL;
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
@@ -1362,7 +1361,7 @@ static int cx25840_reset(struct v4l2_subdev *sd, u32 val)
        return 0;
 }
 
-static int cx25840_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip)
+static int cx25840_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
 {
        struct cx25840_state *state = to_state(sd);
        struct i2c_client *client = v4l2_get_subdevdata(sd);
index e162a70748c5fa6458655daf8591f94b2d3fff63..7f5b8bfd08ac74aa01ec0657c0641ccc25348000 100644 (file)
@@ -1049,16 +1049,16 @@ static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id)
 
 /* FIXME: cx88_ioctl_hook not implemented */
 
-static int mpeg_open(struct inode *inode, struct file *file)
+static int mpeg_open(struct file *file)
 {
-       int minor = iminor(inode);
+       int minor = video_devdata(file)->minor;
        struct cx8802_dev *dev = NULL;
        struct cx8802_fh *fh;
        struct cx8802_driver *drv = NULL;
        int err;
 
        lock_kernel();
-       dev = cx8802_get_device(inode);
+       dev = cx8802_get_device(minor);
 
        dprintk( 1, "%s\n", __func__);
 
@@ -1114,7 +1114,7 @@ static int mpeg_open(struct inode *inode, struct file *file)
        return 0;
 }
 
-static int mpeg_release(struct inode *inode, struct file *file)
+static int mpeg_release(struct file *file)
 {
        struct cx8802_fh  *fh  = file->private_data;
        struct cx8802_dev *dev = fh->dev;
@@ -1132,7 +1132,7 @@ static int mpeg_release(struct inode *inode, struct file *file)
        kfree(fh);
 
        /* Make sure we release the hardware */
-       dev = cx8802_get_device(inode);
+       dev = cx8802_get_device(video_devdata(file)->minor);
        if (dev == NULL)
                return -ENODEV;
 
@@ -1178,7 +1178,7 @@ mpeg_mmap(struct file *file, struct vm_area_struct * vma)
        return videobuf_mmap_mapper(&fh->mpegq, vma);
 }
 
-static const struct file_operations mpeg_fops =
+static const struct v4l2_file_operations mpeg_fops =
 {
        .owner         = THIS_MODULE,
        .open          = mpeg_open,
@@ -1187,7 +1187,6 @@ static const struct file_operations mpeg_fops =
        .poll          = mpeg_poll,
        .mmap          = mpeg_mmap,
        .ioctl         = video_ioctl2,
-       .llseek        = no_llseek,
 };
 
 static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
index a04fee235db6c487c162434e75d20a05b4e9b463..59164fc94f5f09581d26cf96d25a7ff83d1ae6d6 100644 (file)
@@ -578,9 +578,8 @@ static int cx8802_resume_common(struct pci_dev *pci_dev)
 
 #if defined(CONFIG_VIDEO_CX88_BLACKBIRD) || \
     defined(CONFIG_VIDEO_CX88_BLACKBIRD_MODULE)
-struct cx8802_dev * cx8802_get_device(struct inode *inode)
+struct cx8802_dev *cx8802_get_device(int minor)
 {
-       int minor = iminor(inode);
        struct cx8802_dev *dev;
 
        list_for_each_entry(dev, &cx8802_devlist, devlist)
index b96ce991d968cca4b2995f99918affb7696b5cd2..791e69d804f97d89ae37f42520fc34536675072c 100644 (file)
@@ -757,9 +757,9 @@ static int get_ressource(struct cx8800_fh *fh)
        }
 }
 
-static int video_open(struct inode *inode, struct file *file)
+static int video_open(struct file *file)
 {
-       int minor = iminor(inode);
+       int minor = video_devdata(file)->minor;
        struct cx8800_dev *h,*dev = NULL;
        struct cx88_core *core;
        struct cx8800_fh *fh;
@@ -904,7 +904,7 @@ video_poll(struct file *file, struct poll_table_struct *wait)
        return 0;
 }
 
-static int video_release(struct inode *inode, struct file *file)
+static int video_release(struct file *file)
 {
        struct cx8800_fh  *fh  = file->private_data;
        struct cx8800_dev *dev = fh->dev;
@@ -1447,25 +1447,26 @@ static int vidioc_s_frequency (struct file *file, void *priv,
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 static int vidioc_g_register (struct file *file, void *fh,
-                               struct v4l2_register *reg)
+                               struct v4l2_dbg_register *reg)
 {
        struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core;
 
-       if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
+       if (!v4l2_chip_match_host(&reg->match))
                return -EINVAL;
        /* cx2388x has a 24-bit register space */
-       reg->val = cx_read(reg->reg&0xffffff);
+       reg->val = cx_read(reg->reg & 0xffffff);
+       reg->size = 4;
        return 0;
 }
 
 static int vidioc_s_register (struct file *file, void *fh,
-                               struct v4l2_register *reg)
+                               struct v4l2_dbg_register *reg)
 {
        struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core;
 
-       if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
+       if (!v4l2_chip_match_host(&reg->match))
                return -EINVAL;
-       cx_write(reg->reg&0xffffff, reg->val);
+       cx_write(reg->reg & 0xffffff, reg->val);
        return 0;
 }
 #endif
@@ -1693,7 +1694,7 @@ static irqreturn_t cx8800_irq(int irq, void *dev_id)
 /* ----------------------------------------------------------- */
 /* exported stuff                                              */
 
-static const struct file_operations video_fops =
+static const struct v4l2_file_operations video_fops =
 {
        .owner         = THIS_MODULE,
        .open          = video_open,
@@ -1702,8 +1703,6 @@ static const struct file_operations video_fops =
        .poll          = video_poll,
        .mmap          = video_mmap,
        .ioctl         = video_ioctl2,
-       .compat_ioctl  = v4l_compat_ioctl32,
-       .llseek        = no_llseek,
 };
 
 static const struct v4l2_ioctl_ops video_ioctl_ops = {
@@ -1752,14 +1751,12 @@ static struct video_device cx8800_video_template = {
        .current_norm         = V4L2_STD_NTSC_M,
 };
 
-static const struct file_operations radio_fops =
+static const struct v4l2_file_operations radio_fops =
 {
        .owner         = THIS_MODULE,
        .open          = video_open,
        .release       = video_release,
        .ioctl         = video_ioctl2,
-       .compat_ioctl  = v4l_compat_ioctl32,
-       .llseek        = no_llseek,
 };
 
 static const struct v4l2_ioctl_ops radio_ioctl_ops = {
index 20649b25f7baf522a95a659d65da13ba7369805f..eb9ce30dc5e696a0e0e33605deec485630199cc2 100644 (file)
@@ -643,7 +643,7 @@ int cx88_audio_thread(void *data);
 
 int cx8802_register_driver(struct cx8802_driver *drv);
 int cx8802_unregister_driver(struct cx8802_driver *drv);
-struct cx8802_dev * cx8802_get_device(struct inode *inode);
+struct cx8802_dev *cx8802_get_device(int minor);
 struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype);
 
 /* ----------------------------------------------------------- */
index 15c03f0e69ad63fe1a5c2015a8210e31698b21cd..94378ccb7505845d157920e4f81d9154eee6f35f 100644 (file)
@@ -62,9 +62,9 @@ static int em28xx_isoc_audio_deinit(struct em28xx *dev)
 
        dprintk("Stopping isoc\n");
        for (i = 0; i < EM28XX_AUDIO_BUFS; i++) {
-               usb_unlink_urb(dev->adev->urb[i]);
-               usb_free_urb(dev->adev->urb[i]);
-               dev->adev->urb[i] = NULL;
+               usb_unlink_urb(dev->adev.urb[i]);
+               usb_free_urb(dev->adev.urb[i]);
+               dev->adev.urb[i] = NULL;
        }
 
        return 0;
@@ -81,8 +81,8 @@ static void em28xx_audio_isocirq(struct urb *urb)
        unsigned int             stride;
        struct snd_pcm_substream *substream;
        struct snd_pcm_runtime   *runtime;
-       if (dev->adev->capture_pcm_substream) {
-               substream = dev->adev->capture_pcm_substream;
+       if (dev->adev.capture_pcm_substream) {
+               substream = dev->adev.capture_pcm_substream;
                runtime = substream->runtime;
                stride = runtime->frame_bits >> 3;
 
@@ -95,7 +95,7 @@ static void em28xx_audio_isocirq(struct urb *urb)
                        if (!length)
                                continue;
 
-                       oldptr = dev->adev->hwptr_done_capture;
+                       oldptr = dev->adev.hwptr_done_capture;
                        if (oldptr + length >= runtime->buffer_size) {
                                unsigned int cnt =
                                    runtime->buffer_size - oldptr;
@@ -110,16 +110,16 @@ static void em28xx_audio_isocirq(struct urb *urb)
 
                        snd_pcm_stream_lock(substream);
 
-                       dev->adev->hwptr_done_capture += length;
-                       if (dev->adev->hwptr_done_capture >=
+                       dev->adev.hwptr_done_capture += length;
+                       if (dev->adev.hwptr_done_capture >=
                            runtime->buffer_size)
-                               dev->adev->hwptr_done_capture -=
+                               dev->adev.hwptr_done_capture -=
                                    runtime->buffer_size;
 
-                       dev->adev->capture_transfer_done += length;
-                       if (dev->adev->capture_transfer_done >=
+                       dev->adev.capture_transfer_done += length;
+                       if (dev->adev.capture_transfer_done >=
                            runtime->period_size) {
-                               dev->adev->capture_transfer_done -=
+                               dev->adev.capture_transfer_done -=
                                    runtime->period_size;
                                period_elapsed = 1;
                        }
@@ -131,7 +131,7 @@ static void em28xx_audio_isocirq(struct urb *urb)
        }
        urb->status = 0;
 
-       if (dev->adev->shutdown)
+       if (dev->adev.shutdown)
                return;
 
        status = usb_submit_urb(urb, GFP_ATOMIC);
@@ -154,17 +154,17 @@ static int em28xx_init_audio_isoc(struct em28xx *dev)
                struct urb *urb;
                int j, k;
 
-               dev->adev->transfer_buffer[i] = kmalloc(sb_size, GFP_ATOMIC);
-               if (!dev->adev->transfer_buffer[i])
+               dev->adev.transfer_buffer[i] = kmalloc(sb_size, GFP_ATOMIC);
+               if (!dev->adev.transfer_buffer[i])
                        return -ENOMEM;
 
-               memset(dev->adev->transfer_buffer[i], 0x80, sb_size);
+               memset(dev->adev.transfer_buffer[i], 0x80, sb_size);
                urb = usb_alloc_urb(EM28XX_NUM_AUDIO_PACKETS, GFP_ATOMIC);
                if (!urb) {
                        em28xx_errdev("usb_alloc_urb failed!\n");
                        for (j = 0; j < i; j++) {
-                               usb_free_urb(dev->adev->urb[j]);
-                               kfree(dev->adev->transfer_buffer[j]);
+                               usb_free_urb(dev->adev.urb[j]);
+                               kfree(dev->adev.transfer_buffer[j]);
                        }
                        return -ENOMEM;
                }
@@ -173,7 +173,7 @@ static int em28xx_init_audio_isoc(struct em28xx *dev)
                urb->context = dev;
                urb->pipe = usb_rcvisocpipe(dev->udev, 0x83);
                urb->transfer_flags = URB_ISO_ASAP;
-               urb->transfer_buffer = dev->adev->transfer_buffer[i];
+               urb->transfer_buffer = dev->adev.transfer_buffer[i];
                urb->interval = 1;
                urb->complete = em28xx_audio_isocirq;
                urb->number_of_packets = EM28XX_NUM_AUDIO_PACKETS;
@@ -185,11 +185,11 @@ static int em28xx_init_audio_isoc(struct em28xx *dev)
                        urb->iso_frame_desc[j].length =
                            EM28XX_AUDIO_MAX_PACKET_SIZE;
                }
-               dev->adev->urb[i] = urb;
+               dev->adev.urb[i] = urb;
        }
 
        for (i = 0; i < EM28XX_AUDIO_BUFS; i++) {
-               errCode = usb_submit_urb(dev->adev->urb[i], GFP_ATOMIC);
+               errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC);
                if (errCode) {
                        em28xx_isoc_audio_deinit(dev);
 
@@ -202,16 +202,16 @@ static int em28xx_init_audio_isoc(struct em28xx *dev)
 
 static int em28xx_cmd(struct em28xx *dev, int cmd, int arg)
 {
-       dprintk("%s transfer\n", (dev->adev->capture_stream == STREAM_ON)?
+       dprintk("%s transfer\n", (dev->adev.capture_stream == STREAM_ON) ?
                                 "stop" : "start");
 
        switch (cmd) {
        case EM28XX_CAPTURE_STREAM_EN:
-               if (dev->adev->capture_stream == STREAM_OFF && arg == 1) {
-                       dev->adev->capture_stream = STREAM_ON;
+               if (dev->adev.capture_stream == STREAM_OFF && arg == 1) {
+                       dev->adev.capture_stream = STREAM_ON;
                        em28xx_init_audio_isoc(dev);
-               } else if (dev->adev->capture_stream == STREAM_ON && arg == 0) {
-                       dev->adev->capture_stream = STREAM_OFF;
+               } else if (dev->adev.capture_stream == STREAM_ON && arg == 0) {
+                       dev->adev.capture_stream = STREAM_OFF;
                        em28xx_isoc_audio_deinit(dev);
                } else {
                        printk(KERN_ERR "An underrun very likely occurred. "
@@ -289,17 +289,17 @@ static int snd_em28xx_capture_open(struct snd_pcm_substream *substream)
                goto err;
 
        runtime->hw = snd_em28xx_hw_capture;
-       if (dev->alt == 0 && dev->adev->users == 0) {
+       if (dev->alt == 0 && dev->adev.users == 0) {
                int errCode;
                dev->alt = 7;
                errCode = usb_set_interface(dev->udev, 0, 7);
                dprintk("changing alternate number to 7\n");
        }
 
-       dev->adev->users++;
+       dev->adev.users++;
 
        snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
-       dev->adev->capture_pcm_substream = substream;
+       dev->adev.capture_pcm_substream = substream;
        runtime->private_data = dev;
 
        return 0;
@@ -311,7 +311,7 @@ err:
 static int snd_em28xx_pcm_close(struct snd_pcm_substream *substream)
 {
        struct em28xx *dev = snd_pcm_substream_chip(substream);
-       dev->adev->users--;
+       dev->adev.users--;
 
        dprintk("closing device\n");
 
@@ -320,10 +320,10 @@ static int snd_em28xx_pcm_close(struct snd_pcm_substream *substream)
        em28xx_audio_analog_set(dev);
        mutex_unlock(&dev->lock);
 
-       if (dev->adev->users == 0 && dev->adev->shutdown == 1) {
-               dprintk("audio users: %d\n", dev->adev->users);
+       if (dev->adev.users == 0 && dev->adev.shutdown == 1) {
+               dprintk("audio users: %d\n", dev->adev.users);
                dprintk("disabling audio stream!\n");
-               dev->adev->shutdown = 0;
+               dev->adev.shutdown = 0;
                dprintk("released lock\n");
                em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 0);
        }
@@ -356,7 +356,7 @@ static int snd_em28xx_hw_capture_free(struct snd_pcm_substream *substream)
 
        dprintk("Stop capture, if needed\n");
 
-       if (dev->adev->capture_stream == STREAM_ON)
+       if (dev->adev.capture_stream == STREAM_ON)
                em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 0);
 
        return 0;
@@ -379,7 +379,7 @@ static int snd_em28xx_capture_trigger(struct snd_pcm_substream *substream,
                em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 1);
                return 0;
        case SNDRV_PCM_TRIGGER_STOP:
-               dev->adev->shutdown = 1;
+               dev->adev.shutdown = 1;
                return 0;
        default:
                return -EINVAL;
@@ -393,7 +393,7 @@ static snd_pcm_uframes_t snd_em28xx_capture_pointer(struct snd_pcm_substream
 
        snd_pcm_uframes_t hwptr_done;
        dev = snd_pcm_substream_chip(substream);
-       hwptr_done = dev->adev->hwptr_done_capture;
+       hwptr_done = dev->adev.hwptr_done_capture;
 
        return hwptr_done;
 }
@@ -420,7 +420,7 @@ static struct snd_pcm_ops snd_em28xx_pcm_capture = {
 
 static int em28xx_audio_init(struct em28xx *dev)
 {
-       struct em28xx_audio *adev;
+       struct em28xx_audio *adev = &dev->adev;
        struct snd_pcm      *pcm;
        struct snd_card     *card;
        static int          devnr;
@@ -438,16 +438,9 @@ static int em28xx_audio_init(struct em28xx *dev)
        printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2006 Markus "
                         "Rechberger\n");
 
-       adev = kzalloc(sizeof(*adev), GFP_KERNEL);
-       if (!adev) {
-               printk(KERN_ERR "em28xx-audio.c: out of memory\n");
-               return -1;
-       }
        card = snd_card_new(index[devnr], "Em28xx Audio", THIS_MODULE, 0);
-       if (card == NULL) {
-               kfree(adev);
+       if (card == NULL)
                return -ENOMEM;
-       }
 
        spin_lock_init(&adev->slock);
        err = snd_pcm_new(card, "Em28xx Audio", 0, 0, 1, &pcm);
@@ -471,7 +464,6 @@ static int em28xx_audio_init(struct em28xx *dev)
        }
        adev->sndcard = card;
        adev->udev = dev->udev;
-       dev->adev = adev;
 
        return 0;
 }
@@ -488,10 +480,9 @@ static int em28xx_audio_fini(struct em28xx *dev)
                return 0;
        }
 
-       if (dev->adev) {
-               snd_card_free(dev->adev->sndcard);
-               kfree(dev->adev);
-               dev->adev = NULL;
+       if (dev->adev.sndcard) {
+               snd_card_free(dev->adev.sndcard);
+               dev->adev.sndcard = NULL;
        }
 
        return 0;
index f8504518586abadc2fb27208b331c2010327596b..819cceaa6ef41fa709fc152c172dc87d20580ef2 100644 (file)
@@ -1000,12 +1000,11 @@ void em28xx_wake_i2c(struct em28xx *dev)
 static LIST_HEAD(em28xx_devlist);
 static DEFINE_MUTEX(em28xx_devlist_mutex);
 
-struct em28xx *em28xx_get_device(struct inode *inode,
+struct em28xx *em28xx_get_device(int minor,
                                 enum v4l2_buf_type *fh_type,
                                 int *has_radio)
 {
        struct em28xx *h, *dev = NULL;
-       int minor = iminor(inode);
 
        *fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        *has_radio = 0;
index 65dcb91bdcc2046baa7d3070224e5c71245a5f04..24e39c56811e98713f8497cca6f46fbd48409209 100644 (file)
 
 /* FIXME: Need to be populated with the other chip ID's */
 enum em28xx_chip_id {
-       CHIP_ID_EM2820 = 18,
+       CHIP_ID_EM2820 = 18,    /* Also used by em2710 */
        CHIP_ID_EM2840 = 20,
        CHIP_ID_EM2750 = 33,
        CHIP_ID_EM2860 = 34,
index 53527536481e6946b1432b2b08b4590ac0620596..416b691c33c1eafd382420fbc7dbb1af79ff64f3 100644 (file)
@@ -1154,7 +1154,7 @@ static int em28xx_reg_len(int reg)
 }
 
 static int vidioc_g_chip_ident(struct file *file, void *priv,
-              struct v4l2_chip_ident *chip)
+              struct v4l2_dbg_chip_ident *chip)
 {
        struct em28xx_fh      *fh  = priv;
        struct em28xx         *dev = fh->dev;
@@ -1162,20 +1162,20 @@ static int vidioc_g_chip_ident(struct file *file, void *priv,
        chip->ident = V4L2_IDENT_NONE;
        chip->revision = 0;
 
-       em28xx_i2c_call_clients(dev, VIDIOC_G_CHIP_IDENT, chip);
+       em28xx_i2c_call_clients(dev, VIDIOC_DBG_G_CHIP_IDENT, chip);
 
        return 0;
 }
 
 
 static int vidioc_g_register(struct file *file, void *priv,
-                            struct v4l2_register *reg)
+                            struct v4l2_dbg_register *reg)
 {
        struct em28xx_fh      *fh  = priv;
        struct em28xx         *dev = fh->dev;
        int ret;
 
-       switch (reg->match_type) {
+       switch (reg->match.type) {
        case V4L2_CHIP_MATCH_AC97:
                mutex_lock(&dev->lock);
                ret = em28xx_read_ac97(dev, reg->reg);
@@ -1184,6 +1184,7 @@ static int vidioc_g_register(struct file *file, void *priv,
                        return ret;
 
                reg->val = ret;
+               reg->size = 1;
                return 0;
        case V4L2_CHIP_MATCH_I2C_DRIVER:
                em28xx_i2c_call_clients(dev, VIDIOC_DBG_G_REGISTER, reg);
@@ -1192,12 +1193,13 @@ static int vidioc_g_register(struct file *file, void *priv,
                /* Not supported yet */
                return -EINVAL;
        default:
-               if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
+               if (!v4l2_chip_match_host(&reg->match))
                        return -EINVAL;
        }
 
        /* Match host */
-       if (em28xx_reg_len(reg->reg) == 1) {
+       reg->size = em28xx_reg_len(reg->reg);
+       if (reg->size == 1) {
                mutex_lock(&dev->lock);
                ret = em28xx_read_reg(dev, reg->reg);
                mutex_unlock(&dev->lock);
@@ -1207,7 +1209,7 @@ static int vidioc_g_register(struct file *file, void *priv,
 
                reg->val = ret;
        } else {
-               __le64 val = 0;
+               __le16 val = 0;
                mutex_lock(&dev->lock);
                ret = em28xx_read_reg_req_len(dev, USB_REQ_GET_STATUS,
                                                   reg->reg, (char *)&val, 2);
@@ -1215,21 +1217,21 @@ static int vidioc_g_register(struct file *file, void *priv,
                if (ret < 0)
                        return ret;
 
-               reg->val = le64_to_cpu(val);
+               reg->val = le16_to_cpu(val);
        }
 
        return 0;
 }
 
 static int vidioc_s_register(struct file *file, void *priv,
-                            struct v4l2_register *reg)
+                            struct v4l2_dbg_register *reg)
 {
        struct em28xx_fh      *fh  = priv;
        struct em28xx         *dev = fh->dev;
-       __le64 buf;
+       __le16 buf;
        int    rc;
 
-       switch (reg->match_type) {
+       switch (reg->match.type) {
        case V4L2_CHIP_MATCH_AC97:
                mutex_lock(&dev->lock);
                rc = em28xx_write_ac97(dev, reg->reg, reg->val);
@@ -1243,12 +1245,12 @@ static int vidioc_s_register(struct file *file, void *priv,
                /* Not supported yet */
                return -EINVAL;
        default:
-               if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
+               if (!v4l2_chip_match_host(&reg->match))
                        return -EINVAL;
        }
 
        /* Match host */
-       buf = cpu_to_le64(reg->val);
+       buf = cpu_to_le16(reg->val);
 
        mutex_lock(&dev->lock);
        rc = em28xx_write_regs(dev, reg->reg, (char *)&buf,
@@ -1582,15 +1584,15 @@ static int radio_queryctrl(struct file *file, void *priv,
  * em28xx_v4l2_open()
  * inits the device and starts isoc transfer
  */
-static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
+static int em28xx_v4l2_open(struct file *filp)
 {
-       int minor = iminor(inode);
+       int minor = video_devdata(filp)->minor;
        int errCode = 0, radio;
        struct em28xx *dev;
        enum v4l2_buf_type fh_type;
        struct em28xx_fh *fh;
 
-       dev = em28xx_get_device(inode, &fh_type, &radio);
+       dev = em28xx_get_device(minor, &fh_type, &radio);
 
        if (NULL == dev)
                return -ENODEV;
@@ -1686,7 +1688,7 @@ void em28xx_release_analog_resources(struct em28xx *dev)
  * stops streaming and deallocates all resources allocated by the v4l2
  * calls and ioctls
  */
-static int em28xx_v4l2_close(struct inode *inode, struct file *filp)
+static int em28xx_v4l2_close(struct file *filp)
 {
        struct em28xx_fh *fh  = filp->private_data;
        struct em28xx    *dev = fh->dev;
@@ -1826,7 +1828,7 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
        return rc;
 }
 
-static const struct file_operations em28xx_v4l_fops = {
+static const struct v4l2_file_operations em28xx_v4l_fops = {
        .owner         = THIS_MODULE,
        .open          = em28xx_v4l2_open,
        .release       = em28xx_v4l2_close,
@@ -1834,8 +1836,6 @@ static const struct file_operations em28xx_v4l_fops = {
        .poll          = em28xx_v4l2_poll,
        .mmap          = em28xx_v4l2_mmap,
        .ioctl         = video_ioctl2,
-       .llseek        = no_llseek,
-       .compat_ioctl  = v4l_compat_ioctl32,
 };
 
 static const struct v4l2_ioctl_ops video_ioctl_ops = {
@@ -1890,13 +1890,11 @@ static const struct video_device em28xx_video_template = {
        .current_norm               = V4L2_STD_PAL,
 };
 
-static const struct file_operations radio_fops = {
+static const struct v4l2_file_operations radio_fops = {
        .owner         = THIS_MODULE,
        .open          = em28xx_v4l2_open,
        .release       = em28xx_v4l2_close,
        .ioctl         = video_ioctl2,
-       .compat_ioctl  = v4l_compat_ioctl32,
-       .llseek        = no_llseek,
 };
 
 static const struct v4l2_ioctl_ops radio_ioctl_ops = {
index b5eddc26388e476d4174149b824185482f1c7281..6c6b94aa05b2ca2377d0672c3149095cd38661e1 100644 (file)
@@ -473,7 +473,7 @@ struct em28xx {
        unsigned long i2c_hash; /* i2c devicelist hash -
                                   for boards with generic ID */
 
-       struct em28xx_audio *adev;
+       struct em28xx_audio adev;
 
        /* states */
        enum em28xx_dev_state state;
@@ -583,7 +583,7 @@ int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio);
 void em28xx_wake_i2c(struct em28xx *dev);
 void em28xx_remove_from_devlist(struct em28xx *dev);
 void em28xx_add_into_devlist(struct em28xx *dev);
-struct em28xx *em28xx_get_device(struct inode *inode,
+struct em28xx *em28xx_get_device(int minor,
                                 enum v4l2_buf_type *fh_type,
                                 int *has_radio);
 int em28xx_register_extension(struct em28xx_ops *dev);
index 83c07112c59d64c4fb6832b01a5d1cedc174c07c..d1c1e457f0b95a937a135920d07b1b474317dc3f 100644 (file)
@@ -1206,7 +1206,7 @@ static void et61x251_release_resources(struct kref *kref)
 }
 
 
-static int et61x251_open(struct inode* inode, struct file* filp)
+static int et61x251_open(struct file *filp)
 {
        struct et61x251_device* cam;
        int err = 0;
@@ -1291,7 +1291,7 @@ out:
 }
 
 
-static int et61x251_release(struct inode* inode, struct file* filp)
+static int et61x251_release(struct file *filp)
 {
        struct et61x251_device* cam;
 
@@ -2392,8 +2392,8 @@ et61x251_vidioc_s_parm(struct et61x251_device* cam, void __user * arg)
 }
 
 
-static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp,
-                              unsigned int cmd, void __user * arg)
+static long et61x251_ioctl_v4l2(struct file *filp,
+                              unsigned int cmd, void __user *arg)
 {
        struct et61x251_device *cam = video_drvdata(filp);
 
@@ -2487,11 +2487,11 @@ static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp,
 }
 
 
-static int et61x251_ioctl(struct inode* inode, struct file* filp,
+static long et61x251_ioctl(struct file *filp,
                         unsigned int cmd, unsigned long arg)
 {
        struct et61x251_device *cam = video_drvdata(filp);
-       int err = 0;
+       long err = 0;
 
        if (mutex_lock_interruptible(&cam->fileop_mutex))
                return -ERESTARTSYS;
@@ -2511,7 +2511,7 @@ static int et61x251_ioctl(struct inode* inode, struct file* filp,
 
        V4LDBG(3, "et61x251", cmd);
 
-       err = et61x251_ioctl_v4l2(inode, filp, cmd, (void __user *)arg);
+       err = et61x251_ioctl_v4l2(filp, cmd, (void __user *)arg);
 
        mutex_unlock(&cam->fileop_mutex);
 
@@ -2519,18 +2519,14 @@ static int et61x251_ioctl(struct inode* inode, struct file* filp,
 }
 
 
-static const struct file_operations et61x251_fops = {
+static const struct v4l2_file_operations et61x251_fops = {
        .owner = THIS_MODULE,
        .open =    et61x251_open,
        .release = et61x251_release,
        .ioctl =   et61x251_ioctl,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl = v4l_compat_ioctl32,
-#endif
        .read =    et61x251_read,
        .poll =    et61x251_poll,
        .mmap =    et61x251_mmap,
-       .llseek =  no_llseek,
 };
 
 /*****************************************************************************/
index 8b9f3bde5740dd7edcf60270b7c5b5be3a0230fc..5e36b9a4ae3ea289ee016af8041230ef622ef0bf 100644 (file)
@@ -875,7 +875,7 @@ static void gspca_release(struct video_device *vfd)
        kfree(gspca_dev);
 }
 
-static int dev_open(struct inode *inode, struct file *file)
+static int dev_open(struct file *file)
 {
        struct gspca_dev *gspca_dev;
        int ret;
@@ -922,7 +922,7 @@ out:
        return ret;
 }
 
-static int dev_close(struct inode *inode, struct file *file)
+static int dev_close(struct file *file)
 {
        struct gspca_dev *gspca_dev = file->private_data;
 
@@ -1802,17 +1802,13 @@ out:
        return ret;
 }
 
-static struct file_operations dev_fops = {
+static struct v4l2_file_operations dev_fops = {
        .owner = THIS_MODULE,
        .open = dev_open,
        .release = dev_close,
        .read = dev_read,
        .mmap = dev_mmap,
-       .unlocked_ioctl = __video_ioctl2,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl = v4l_compat_ioctl32,
-#endif
-       .llseek = no_llseek,
+       .unlocked_ioctl = video_ioctl2,
        .poll   = dev_poll,
 };
 
index 352f84d440fb64272e6818fc2439122fa0c43230..79393d1772e40163a7e4bcfa1f971ef88faaacd8 100644 (file)
@@ -306,7 +306,7 @@ static int hexium_detach(struct saa7146_dev *dev)
        return 0;
 }
 
-static int hexium_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
+static long hexium_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
 {
        struct saa7146_dev *dev = fh->dev;
        struct hexium *hexium = (struct hexium *) dev->ext_priv;
index 8d3c1482e7ea376b5ae9919f7107b7eded09e185..074bec711fe0a621b1894f50c35246195b7bc3bf 100644 (file)
@@ -370,7 +370,7 @@ static int hexium_detach(struct saa7146_dev *dev)
        return 0;
 }
 
-static int hexium_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
+static long hexium_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
 {
        struct saa7146_dev *dev = fh->dev;
        struct hexium *hexium = (struct hexium *) dev->ext_priv;
index 08b762951759eab53949ea35c13b40f77f2eca95..e8e5921cdc346dd8b26efa1ad93cc01f1791acdb 100644 (file)
@@ -902,18 +902,19 @@ static void ivtv_load_and_init_modules(struct ivtv *itv)
        }
 
        if (hw & IVTV_HW_SAA711X) {
-               struct v4l2_chip_ident v = { V4L2_CHIP_MATCH_I2C_DRIVER, I2C_DRIVERID_SAA711X };
+               struct v4l2_dbg_chip_ident v;
 
                /* determine the exact saa711x model */
                itv->hw_flags &= ~IVTV_HW_SAA711X;
 
+               v.match.type = V4L2_CHIP_MATCH_I2C_DRIVER;
+               strlcpy(v.match.name, "saa7115", sizeof(v.match.name));
                ivtv_call_hw(itv, IVTV_HW_SAA711X, core, g_chip_ident, &v);
                if (v.ident == V4L2_IDENT_SAA7114) {
                        itv->hw_flags |= IVTV_HW_SAA7114;
                        /* VBI is not yet supported by the saa7114 driver. */
                        itv->v4l2_cap &= ~(V4L2_CAP_SLICED_VBI_CAPTURE|V4L2_CAP_VBI_CAPTURE);
-               }
-               else {
+               } else {
                        itv->hw_flags |= IVTV_HW_SAA7115;
                }
                itv->vbi.raw_decoder_line_size = 1443;
index 5eb587592e9dbdfc27a6c2d0e18c0a4e082f85b1..d594bc29f07f48a4293f0e1b7e753719e30e9f2a 100644 (file)
@@ -831,7 +831,7 @@ static void ivtv_stop_decoding(struct ivtv_open_id *id, int flags, u64 pts)
        ivtv_release_stream(s);
 }
 
-int ivtv_v4l2_close(struct inode *inode, struct file *filp)
+int ivtv_v4l2_close(struct file *filp)
 {
        struct ivtv_open_id *id = filp->private_data;
        struct ivtv *itv = id->itv;
@@ -978,7 +978,7 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp)
        return 0;
 }
 
-int ivtv_v4l2_open(struct inode *inode, struct file *filp)
+int ivtv_v4l2_open(struct file *filp)
 {
        int res;
        struct ivtv *itv = NULL;
index df81e790147f71a9e839d5efda508a614778ef77..049a2923965d9259713230f5612f150d69773f79 100644 (file)
 #define IVTV_FILEOPS_H
 
 /* Testing/Debugging */
-int ivtv_v4l2_open(struct inode *inode, struct file *filp);
+int ivtv_v4l2_open(struct file *filp);
 ssize_t ivtv_v4l2_read(struct file *filp, char __user *buf, size_t count,
                      loff_t * pos);
 ssize_t ivtv_v4l2_write(struct file *filp, const char __user *buf, size_t count,
                       loff_t * pos);
-int ivtv_v4l2_close(struct inode *inode, struct file *filp);
+int ivtv_v4l2_close(struct file *filp);
 unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait);
 unsigned int ivtv_v4l2_dec_poll(struct file *filp, poll_table * wait);
 int ivtv_start_capture(struct ivtv_open_id *id);
index cd990a4b81a9e338ba97219f824113cd6c833169..f6b3ef6e691be8465ab82b397b7c796bd27b0cf4 100644 (file)
@@ -674,19 +674,19 @@ static int ivtv_s_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_f
        return ret;
 }
 
-static int ivtv_g_chip_ident(struct file *file, void *fh, struct v4l2_chip_ident *chip)
+static int ivtv_g_chip_ident(struct file *file, void *fh, struct v4l2_dbg_chip_ident *chip)
 {
        struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
 
        chip->ident = V4L2_IDENT_NONE;
        chip->revision = 0;
-       if (chip->match_type == V4L2_CHIP_MATCH_HOST) {
-               if (v4l2_chip_match_host(chip->match_type, chip->match_chip))
+       if (chip->match.type == V4L2_CHIP_MATCH_HOST) {
+               if (v4l2_chip_match_host(&chip->match))
                        chip->ident = itv->has_cx23415 ? V4L2_IDENT_CX23415 : V4L2_IDENT_CX23416;
                return 0;
        }
-       if (chip->match_type != V4L2_CHIP_MATCH_I2C_DRIVER &&
-           chip->match_type != V4L2_CHIP_MATCH_I2C_ADDR)
+       if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER &&
+           chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
                return -EINVAL;
        /* TODO: is this correct? */
        return ivtv_call_all_err(itv, core, g_chip_ident, chip);
@@ -695,7 +695,7 @@ static int ivtv_g_chip_ident(struct file *file, void *fh, struct v4l2_chip_ident
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 static int ivtv_itvc(struct ivtv *itv, unsigned int cmd, void *arg)
 {
-       struct v4l2_register *regs = arg;
+       struct v4l2_dbg_register *regs = arg;
        volatile u8 __iomem *reg_start;
 
        if (!capable(CAP_SYS_ADMIN))
@@ -710,6 +710,7 @@ static int ivtv_itvc(struct ivtv *itv, unsigned int cmd, void *arg)
        else
                return -EINVAL;
 
+       regs->size = 4;
        if (cmd == VIDIOC_DBG_G_REGISTER)
                regs->val = readl(regs->reg + reg_start);
        else
@@ -717,11 +718,11 @@ static int ivtv_itvc(struct ivtv *itv, unsigned int cmd, void *arg)
        return 0;
 }
 
-static int ivtv_g_register(struct file *file, void *fh, struct v4l2_register *reg)
+static int ivtv_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
 {
        struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
 
-       if (v4l2_chip_match_host(reg->match_type, reg->match_chip))
+       if (v4l2_chip_match_host(&reg->match))
                return ivtv_itvc(itv, VIDIOC_DBG_G_REGISTER, reg);
        /* TODO: subdev errors should not be ignored, this should become a
           subdev helper function. */
@@ -729,11 +730,11 @@ static int ivtv_g_register(struct file *file, void *fh, struct v4l2_register *re
        return 0;
 }
 
-static int ivtv_s_register(struct file *file, void *fh, struct v4l2_register *reg)
+static int ivtv_s_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
 {
        struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
 
-       if (v4l2_chip_match_host(reg->match_type, reg->match_chip))
+       if (v4l2_chip_match_host(&reg->match))
                return ivtv_itvc(itv, VIDIOC_DBG_S_REGISTER, reg);
        /* TODO: subdev errors should not be ignored, this should become a
           subdev helper function. */
@@ -1725,7 +1726,7 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg)
        return 0;
 }
 
-static int ivtv_default(struct file *file, void *fh, int cmd, void *arg)
+static long ivtv_default(struct file *file, void *fh, int cmd, void *arg)
 {
        struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
 
@@ -1827,7 +1828,7 @@ static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp,
 
        if (ivtv_debug & IVTV_DBGFLG_IOCTL)
                vfd->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
-       ret = __video_ioctl2(filp, cmd, arg);
+       ret = video_ioctl2(filp, cmd, arg);
        vfd->debug = 0;
        return ret;
 }
index f77d764707b2a1f81b7bef2953de5c920918e3d7..854a950af78c757ae95ff9f8a39a6a7a6f1d3ede 100644 (file)
 #include "ivtv-cards.h"
 #include "ivtv-streams.h"
 
-static const struct file_operations ivtv_v4l2_enc_fops = {
+static const struct v4l2_file_operations ivtv_v4l2_enc_fops = {
        .owner = THIS_MODULE,
        .read = ivtv_v4l2_read,
        .write = ivtv_v4l2_write,
        .open = ivtv_v4l2_open,
        .unlocked_ioctl = ivtv_v4l2_ioctl,
-       .compat_ioctl = v4l_compat_ioctl32,
        .release = ivtv_v4l2_close,
        .poll = ivtv_v4l2_enc_poll,
 };
 
-static const struct file_operations ivtv_v4l2_dec_fops = {
+static const struct v4l2_file_operations ivtv_v4l2_dec_fops = {
        .owner = THIS_MODULE,
        .read = ivtv_v4l2_read,
        .write = ivtv_v4l2_write,
        .open = ivtv_v4l2_open,
        .unlocked_ioctl = ivtv_v4l2_ioctl,
-       .compat_ioctl = v4l_compat_ioctl32,
        .release = ivtv_v4l2_close,
        .poll = ivtv_v4l2_dec_poll,
 };
@@ -78,7 +76,7 @@ static struct {
        int num_offset;
        int dma, pio;
        enum v4l2_buf_type buf_type;
-       const struct file_operations *fops;
+       const struct v4l2_file_operations *fops;
 } ivtv_stream_info[] = {
        {       /* IVTV_ENC_STREAM_TYPE_MPG */
                "encoder MPG",
index 07be14a9fe7b7cd49b4fe95a21d9fd2cf3b7942b..de397ef57b44d7aefa843a2e5f6fbd761e24a6ac 100644 (file)
@@ -80,29 +80,28 @@ static int m52790_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *r
 }
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-static int m52790_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
+static int m52790_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
 {
        struct m52790_state *state = to_state(sd);
        struct i2c_client *client = v4l2_get_subdevdata(sd);
 
-       if (!v4l2_chip_match_i2c_client(client,
-                               reg->match_type, reg->match_chip))
+       if (!v4l2_chip_match_i2c_client(client, &reg->match))
                return -EINVAL;
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
        if (reg->reg != 0)
                return -EINVAL;
+       reg->size = 1;
        reg->val = state->input | state->output;
        return 0;
 }
 
-static int m52790_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
+static int m52790_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
 {
        struct m52790_state *state = to_state(sd);
        struct i2c_client *client = v4l2_get_subdevdata(sd);
 
-       if (!v4l2_chip_match_i2c_client(client,
-                               reg->match_type, reg->match_chip))
+       if (!v4l2_chip_match_i2c_client(client, &reg->match))
                return -EINVAL;
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
@@ -115,7 +114,7 @@ static int m52790_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
 }
 #endif
 
-static int m52790_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip)
+static int m52790_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
 
index 6418f4a78f2a86afc716ff9e6e4d377ceceb434d..b76e33d5c867bad4430035ac952765497fc128ee 100644 (file)
@@ -841,7 +841,7 @@ again:
 /* video4linux integration                                                  */
 /****************************************************************************/
 
-static int meye_open(struct inode *inode, struct file *file)
+static int meye_open(struct file *file)
 {
        int i;
 
@@ -863,7 +863,7 @@ static int meye_open(struct inode *inode, struct file *file)
        return 0;
 }
 
-static int meye_release(struct inode *inode, struct file *file)
+static int meye_release(struct file *file)
 {
        mchip_hic_stop();
        mchip_dma_free();
@@ -1577,7 +1577,7 @@ static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i)
        return 0;
 }
 
-static int vidioc_default(struct file *file, void *fh, int cmd, void *arg)
+static long vidioc_default(struct file *file, void *fh, int cmd, void *arg)
 {
        switch (cmd) {
        case MEYEIOC_G_PARAMS:
@@ -1684,17 +1684,13 @@ static int meye_mmap(struct file *file, struct vm_area_struct *vma)
        return 0;
 }
 
-static const struct file_operations meye_fops = {
+static const struct v4l2_file_operations meye_fops = {
        .owner          = THIS_MODULE,
        .open           = meye_open,
        .release        = meye_release,
        .mmap           = meye_mmap,
        .ioctl          = video_ioctl2,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = v4l_compat_ioctl32,
-#endif
        .poll           = meye_poll,
-       .llseek         = no_llseek,
 };
 
 static const struct v4l2_ioctl_ops meye_ioctl_ops = {
index a622dbb72ed89e166fec1566f40abcc825e27c23..4d7a91852117920b6dfe38b5d9ed7f1f9278f5c6 100644 (file)
@@ -483,7 +483,7 @@ static int msp_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
 }
 
 #ifdef CONFIG_VIDEO_ALLOW_V4L1
-static int msp_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
+static long msp_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
 {
        struct msp_state *state = to_state(sd);
        struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -733,7 +733,7 @@ static int msp_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
        return 0;
 }
 
-static int msp_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip)
+static int msp_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
 {
        struct msp_state *state = to_state(sd);
        struct i2c_client *client = v4l2_get_subdevdata(sd);
index 1a1a12453672984b903e1bb96461d48aa881242c..c1bf75ef2741389576f167c65ccbda8254fa4c40 100644 (file)
@@ -343,14 +343,14 @@ static int mt9m001_try_fmt(struct soc_camera_device *icd,
 }
 
 static int mt9m001_get_chip_id(struct soc_camera_device *icd,
-                              struct v4l2_chip_ident *id)
+                              struct v4l2_dbg_chip_ident *id)
 {
        struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
 
-       if (id->match_type != V4L2_CHIP_MATCH_I2C_ADDR)
+       if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
                return -EINVAL;
 
-       if (id->match_chip != mt9m001->client->addr)
+       if (id->match.addr != mt9m001->client->addr)
                return -ENODEV;
 
        id->ident       = mt9m001->model;
@@ -361,16 +361,17 @@ static int mt9m001_get_chip_id(struct soc_camera_device *icd,
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 static int mt9m001_get_register(struct soc_camera_device *icd,
-                               struct v4l2_register *reg)
+                               struct v4l2_dbg_register *reg)
 {
        struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
 
-       if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
+       if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
                return -EINVAL;
 
-       if (reg->match_chip != mt9m001->client->addr)
+       if (reg->match.addr != mt9m001->client->addr)
                return -ENODEV;
 
+       reg->size = 2;
        reg->val = reg_read(icd, reg->reg);
 
        if (reg->val > 0xffff)
@@ -380,14 +381,14 @@ static int mt9m001_get_register(struct soc_camera_device *icd,
 }
 
 static int mt9m001_set_register(struct soc_camera_device *icd,
-                               struct v4l2_register *reg)
+                               struct v4l2_dbg_register *reg)
 {
        struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
 
-       if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
+       if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
                return -EINVAL;
 
-       if (reg->match_chip != mt9m001->client->addr)
+       if (reg->match.addr != mt9m001->client->addr)
                return -ENODEV;
 
        if (reg_write(icd, reg->reg, reg->val) < 0)
index c89ea41fe25948d216535ac34ed5d1604c7a76e1..5b8e20979cceeb94288a328b8cde1c3ee6a27a4c 100644 (file)
@@ -514,14 +514,14 @@ static int mt9m111_try_fmt(struct soc_camera_device *icd,
 }
 
 static int mt9m111_get_chip_id(struct soc_camera_device *icd,
-                              struct v4l2_chip_ident *id)
+                              struct v4l2_dbg_chip_ident *id)
 {
        struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
 
-       if (id->match_type != V4L2_CHIP_MATCH_I2C_ADDR)
+       if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
                return -EINVAL;
 
-       if (id->match_chip != mt9m111->client->addr)
+       if (id->match.addr != mt9m111->client->addr)
                return -ENODEV;
 
        id->ident       = mt9m111->model;
@@ -532,18 +532,19 @@ static int mt9m111_get_chip_id(struct soc_camera_device *icd,
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 static int mt9m111_get_register(struct soc_camera_device *icd,
-                               struct v4l2_register *reg)
+                               struct v4l2_dbg_register *reg)
 {
        int val;
 
        struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
 
-       if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff)
+       if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff)
                return -EINVAL;
-       if (reg->match_chip != mt9m111->client->addr)
+       if (reg->match.addr != mt9m111->client->addr)
                return -ENODEV;
 
        val = mt9m111_reg_read(icd, reg->reg);
+       reg->size = 2;
        reg->val = (u64)val;
 
        if (reg->val > 0xffff)
@@ -553,14 +554,14 @@ static int mt9m111_get_register(struct soc_camera_device *icd,
 }
 
 static int mt9m111_set_register(struct soc_camera_device *icd,
-                               struct v4l2_register *reg)
+                               struct v4l2_dbg_register *reg)
 {
        struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
 
-       if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff)
+       if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff)
                return -EINVAL;
 
-       if (reg->match_chip != mt9m111->client->addr)
+       if (reg->match.addr != mt9m111->client->addr)
                return -ENODEV;
 
        if (mt9m111_reg_write(icd, reg->reg, reg->val) < 0)
index 1a9d53966d06cf251816488c780f3a347fed3d84..349d8e36553087886354ff8771cf4b1cab12c4c5 100644 (file)
@@ -326,14 +326,14 @@ static int mt9t031_try_fmt(struct soc_camera_device *icd,
 }
 
 static int mt9t031_get_chip_id(struct soc_camera_device *icd,
-                              struct v4l2_chip_ident *id)
+                              struct v4l2_dbg_chip_ident *id)
 {
        struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
 
-       if (id->match_type != V4L2_CHIP_MATCH_I2C_ADDR)
+       if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
                return -EINVAL;
 
-       if (id->match_chip != mt9t031->client->addr)
+       if (id->match.addr != mt9t031->client->addr)
                return -ENODEV;
 
        id->ident       = mt9t031->model;
@@ -344,14 +344,14 @@ static int mt9t031_get_chip_id(struct soc_camera_device *icd,
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 static int mt9t031_get_register(struct soc_camera_device *icd,
-                               struct v4l2_register *reg)
+                               struct v4l2_dbg_register *reg)
 {
        struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
 
-       if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
+       if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
                return -EINVAL;
 
-       if (reg->match_chip != mt9t031->client->addr)
+       if (reg->match.addr != mt9t031->client->addr)
                return -ENODEV;
 
        reg->val = reg_read(icd, reg->reg);
@@ -363,14 +363,14 @@ static int mt9t031_get_register(struct soc_camera_device *icd,
 }
 
 static int mt9t031_set_register(struct soc_camera_device *icd,
-                               struct v4l2_register *reg)
+                               struct v4l2_dbg_register *reg)
 {
        struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
 
-       if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
+       if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
                return -EINVAL;
 
-       if (reg->match_chip != mt9t031->client->addr)
+       if (reg->match.addr != mt9t031->client->addr)
                return -ENODEV;
 
        if (reg_write(icd, reg->reg, reg->val) < 0)
index 14a5f9c21ffa22d76cd10e76f52825fe5d9f9a33..b04c8cb1644d1193cf3d59ef7b6df597fb7b6933 100644 (file)
@@ -422,14 +422,14 @@ static int mt9v022_try_fmt(struct soc_camera_device *icd,
 }
 
 static int mt9v022_get_chip_id(struct soc_camera_device *icd,
-                              struct v4l2_chip_ident *id)
+                              struct v4l2_dbg_chip_ident *id)
 {
        struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
 
-       if (id->match_type != V4L2_CHIP_MATCH_I2C_ADDR)
+       if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
                return -EINVAL;
 
-       if (id->match_chip != mt9v022->client->addr)
+       if (id->match.addr != mt9v022->client->addr)
                return -ENODEV;
 
        id->ident       = mt9v022->model;
@@ -440,16 +440,17 @@ static int mt9v022_get_chip_id(struct soc_camera_device *icd,
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 static int mt9v022_get_register(struct soc_camera_device *icd,
-                               struct v4l2_register *reg)
+                               struct v4l2_dbg_register *reg)
 {
        struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
 
-       if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
+       if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
                return -EINVAL;
 
-       if (reg->match_chip != mt9v022->client->addr)
+       if (reg->match.addr != mt9v022->client->addr)
                return -ENODEV;
 
+       reg->size = 2;
        reg->val = reg_read(icd, reg->reg);
 
        if (reg->val > 0xffff)
@@ -459,14 +460,14 @@ static int mt9v022_get_register(struct soc_camera_device *icd,
 }
 
 static int mt9v022_set_register(struct soc_camera_device *icd,
-                               struct v4l2_register *reg)
+                               struct v4l2_dbg_register *reg)
 {
        struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
 
-       if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
+       if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
                return -EINVAL;
 
-       if (reg->match_chip != mt9v022->client->addr)
+       if (reg->match.addr != mt9v022->client->addr)
                return -ENODEV;
 
        if (reg_write(icd, reg->reg, reg->val) < 0)
index 7f130284b5c730a0573bcc0c10c9cd925cb5dfec..e3cbe14c349a788288987200be077322e7ecf3d1 100644 (file)
@@ -489,7 +489,7 @@ static int mxb_detach(struct saa7146_dev *dev)
        return 0;
 }
 
-static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
+static long mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
 {
        struct saa7146_dev *dev = fh->dev;
        struct mxb *mxb = (struct mxb *)dev->ext_priv;
index 85c3c7c92af1902ccd7b51768882245950a66e9e..73eb656acfe356b0ca965fffee948fbd75436397 100644 (file)
@@ -1454,9 +1454,9 @@ static int omap24xxcam_mmap(struct file *file, struct vm_area_struct *vma)
        return rval;
 }
 
-static int omap24xxcam_open(struct inode *inode, struct file *file)
+static int omap24xxcam_open(struct file *file)
 {
-       int minor = iminor(inode);
+       int minor = video_devdata(file)->minor;
        struct omap24xxcam_device *cam = omap24xxcam.priv;
        struct omap24xxcam_fh *fh;
        struct v4l2_format format;
@@ -1511,7 +1511,7 @@ out_try_module_get:
        return -ENODEV;
 }
 
-static int omap24xxcam_release(struct inode *inode, struct file *file)
+static int omap24xxcam_release(struct file *file)
 {
        struct omap24xxcam_fh *fh = file->private_data;
        struct omap24xxcam_device *cam = fh->cam;
@@ -1559,8 +1559,7 @@ static int omap24xxcam_release(struct inode *inode, struct file *file)
        return 0;
 }
 
-static struct file_operations omap24xxcam_fops = {
-       .llseek  = no_llseek,
+static struct v4l2_file_operations omap24xxcam_fops = {
        .ioctl   = video_ioctl2,
        .poll    = omap24xxcam_poll,
        .mmap    = omap24xxcam_mmap,
index 6ee9b69cc4a90585c7daa10b27bcc0136f43bfa8..9af5532db1423eb1d7971e5a00396a49c03f1959 100644 (file)
@@ -3915,7 +3915,7 @@ ov51x_dealloc(struct usb_ov511 *ov)
  ***************************************************************************/
 
 static int
-ov51x_v4l1_open(struct inode *inode, struct file *file)
+ov51x_v4l1_open(struct file *file)
 {
        struct video_device *vdev = video_devdata(file);
        struct usb_ov511 *ov = video_get_drvdata(vdev);
@@ -3972,7 +3972,7 @@ out:
 }
 
 static int
-ov51x_v4l1_close(struct inode *inode, struct file *file)
+ov51x_v4l1_close(struct file *file)
 {
        struct video_device *vdev = file->private_data;
        struct usb_ov511 *ov = video_get_drvdata(vdev);
@@ -4010,7 +4010,7 @@ ov51x_v4l1_close(struct inode *inode, struct file *file)
 }
 
 /* Do not call this function directly! */
-static int
+static long
 ov51x_v4l1_ioctl_internal(struct file *file, unsigned int cmd, void *arg)
 {
        struct video_device *vdev = file->private_data;
@@ -4449,8 +4449,8 @@ redo:
        return 0;
 }
 
-static int
-ov51x_v4l1_ioctl(struct inode *inode, struct file *file,
+static long
+ov51x_v4l1_ioctl(struct file *file,
                 unsigned int cmd, unsigned long arg)
 {
        struct video_device *vdev = file->private_data;
@@ -4661,17 +4661,13 @@ ov51x_v4l1_mmap(struct file *file, struct vm_area_struct *vma)
        return 0;
 }
 
-static const struct file_operations ov511_fops = {
+static const struct v4l2_file_operations ov511_fops = {
        .owner =        THIS_MODULE,
        .open =         ov51x_v4l1_open,
        .release =      ov51x_v4l1_close,
        .read =         ov51x_v4l1_read,
        .mmap =         ov51x_v4l1_mmap,
        .ioctl =        ov51x_v4l1_ioctl,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl = v4l_compat_ioctl32,
-#endif
-       .llseek =       no_llseek,
 };
 
 static struct video_device vdev_template = {
index ea032f5f2f412ff2fae9eb6fa1535ad045e94ede..ca26b0c50cf2ab94095e0856f1183974fba3a918 100644 (file)
@@ -1310,7 +1310,7 @@ static int ov7670_command(struct i2c_client *client, unsigned int cmd,
                void *arg)
 {
        switch (cmd) {
-       case VIDIOC_G_CHIP_IDENT:
+       case VIDIOC_DBG_G_CHIP_IDENT:
                return v4l2_chip_ident_i2c_client(client, arg, V4L2_IDENT_OV7670, 0);
 
        case VIDIOC_INT_RESET:
index 54b736fcc07a4786bce26f89184f59a00ddf062d..3c9e0ba974e9ec57bb819b234f18cb05c53ecc4d 100644 (file)
@@ -724,7 +724,7 @@ static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd)
 }
 
 static int ov772x_get_chip_id(struct soc_camera_device *icd,
-                             struct v4l2_chip_ident   *id)
+                             struct v4l2_dbg_chip_ident   *id)
 {
        struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
 
@@ -736,11 +736,12 @@ static int ov772x_get_chip_id(struct soc_camera_device *icd,
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 static int ov772x_get_register(struct soc_camera_device *icd,
-                              struct v4l2_register *reg)
+                              struct v4l2_dbg_register *reg)
 {
        struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
        int                 ret;
 
+       reg->size = 1;
        if (reg->reg > 0xff)
                return -EINVAL;
 
@@ -754,7 +755,7 @@ static int ov772x_get_register(struct soc_camera_device *icd,
 }
 
 static int ov772x_set_register(struct soc_camera_device *icd,
-                              struct v4l2_register *reg)
+                              struct v4l2_dbg_register *reg)
 {
        struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
 
index 45730fac1570b0be08e3313700e525be3d710790..a1ad38fc49c18154f67b27dea1fba2b3888c97a1 100644 (file)
@@ -680,7 +680,7 @@ static int pms_capture(struct pms_device *dev, char __user *buf, int rgb555, int
  *     Video4linux interfacing
  */
 
-static int pms_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+static long pms_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 {
        struct video_device *dev = video_devdata(file);
        struct pms_device *pd=(struct pms_device *)dev;
@@ -862,7 +862,7 @@ static int pms_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        return 0;
 }
 
-static int pms_ioctl(struct inode *inode, struct file *file,
+static long pms_ioctl(struct file *file,
                     unsigned int cmd, unsigned long arg)
 {
        return video_usercopy(file, cmd, arg, pms_do_ioctl);
@@ -881,7 +881,7 @@ static ssize_t pms_read(struct file *file, char __user *buf,
        return len;
 }
 
-static int pms_exclusive_open(struct inode *inode, struct file *file)
+static int pms_exclusive_open(struct file *file)
 {
        struct video_device *v = video_devdata(file);
        struct pms_device *pd = (struct pms_device *)v;
@@ -889,7 +889,7 @@ static int pms_exclusive_open(struct inode *inode, struct file *file)
        return test_and_set_bit(0, &pd->in_use) ? -EBUSY : 0;
 }
 
-static int pms_exclusive_release(struct inode *inode, struct file *file)
+static int pms_exclusive_release(struct file *file)
 {
        struct video_device *v = video_devdata(file);
        struct pms_device *pd = (struct pms_device *)v;
@@ -898,16 +898,12 @@ static int pms_exclusive_release(struct inode *inode, struct file *file)
        return 0;
 }
 
-static const struct file_operations pms_fops = {
+static const struct v4l2_file_operations pms_fops = {
        .owner          = THIS_MODULE,
        .open           = pms_exclusive_open,
        .release        = pms_exclusive_release,
        .ioctl          = pms_ioctl,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = v4l_compat_ioctl32,
-#endif
        .read           = pms_read,
-       .llseek         = no_llseek,
 };
 
 static struct video_device pms_template=
index 4358079f1966f4efa4a60eaded89e9c75e1866fd..8fb92ac78c7b9ab4cd217a79efe6f60ca2c03085 100644 (file)
@@ -4732,26 +4732,25 @@ static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw)
 
 
 int pvr2_hdw_register_access(struct pvr2_hdw *hdw,
-                            u32 match_type, u32 match_chip, u64 reg_id,
-                            int setFl,u64 *val_ptr)
+                            struct v4l2_dbg_match *match, u64 reg_id,
+                            int setFl, u64 *val_ptr)
 {
 #ifdef CONFIG_VIDEO_ADV_DEBUG
        struct pvr2_i2c_client *cp;
-       struct v4l2_register req;
+       struct v4l2_dbg_register req;
        int stat = 0;
        int okFl = 0;
 
        if (!capable(CAP_SYS_ADMIN)) return -EPERM;
 
-       req.match_type = match_type;
-       req.match_chip = match_chip;
+       req.match = *match;
        req.reg = reg_id;
        if (setFl) req.val = *val_ptr;
        mutex_lock(&hdw->i2c_list_lock); do {
                list_for_each_entry(cp, &hdw->i2c_clients, list) {
                        if (!v4l2_chip_match_i2c_client(
                                    cp->client,
-                                   req.match_type, req.match_chip)) {
+                                   &req.match)) {
                                continue;
                        }
                        stat = pvr2_i2c_client_cmd(
index 49482d1f2b28d71b87ccd3318e3b0b45afeda2e1..1b4fec337c6b2f694b2aa6a53d8a7f7afb60fe3d 100644 (file)
@@ -242,8 +242,8 @@ void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *,
    setFl   - true to set the register, false to read it
    val_ptr - storage location for source / result. */
 int pvr2_hdw_register_access(struct pvr2_hdw *,
-                            u32 match_type, u32 match_chip,u64 reg_id,
-                            int setFl,u64 *val_ptr);
+                            struct v4l2_dbg_match *match, u64 reg_id,
+                            int setFl, u64 *val_ptr);
 
 /* The following entry points are all lower level things you normally don't
    want to worry about. */
index 52af1c4359655dbcd6159434e37ab02eb915b56b..878fd52a73b3a330df8cae9af1a0b5b9deae7bbc 100644 (file)
@@ -168,13 +168,13 @@ static const char *get_v4l_name(int v4l_type)
  * This is part of Video 4 Linux API. The procedure handles ioctl() calls.
  *
  */
-static int pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+static long pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 {
        struct pvr2_v4l2_fh *fh = file->private_data;
        struct pvr2_v4l2 *vp = fh->vhead;
        struct pvr2_v4l2_dev *dev_info = fh->dev_info;
        struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
-       int ret = -EINVAL;
+       long ret = -EINVAL;
 
        if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
                v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),cmd);
@@ -851,11 +851,11 @@ static int pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        case VIDIOC_DBG_G_REGISTER:
        {
                u64 val;
-               struct v4l2_register *req = (struct v4l2_register *)arg;
+               struct v4l2_dbg_register *req = (struct v4l2_dbg_register *)arg;
                if (cmd == VIDIOC_DBG_S_REGISTER) val = req->val;
                ret = pvr2_hdw_register_access(
-                       hdw,req->match_type,req->match_chip,req->reg,
-                       cmd == VIDIOC_DBG_S_REGISTER,&val);
+                       hdw, &req->match, req->reg,
+                       cmd == VIDIOC_DBG_S_REGISTER, &val);
                if (cmd == VIDIOC_DBG_G_REGISTER) req->val = val;
                break;
        }
@@ -871,20 +871,20 @@ static int pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        if (ret < 0) {
                if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
                        pvr2_trace(PVR2_TRACE_V4LIOCTL,
-                                  "pvr2_v4l2_do_ioctl failure, ret=%d",ret);
+                                  "pvr2_v4l2_do_ioctl failure, ret=%ld", ret);
                } else {
                        if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
                                pvr2_trace(PVR2_TRACE_V4LIOCTL,
-                                          "pvr2_v4l2_do_ioctl failure, ret=%d"
-                                          " command was:",ret);
+                                          "pvr2_v4l2_do_ioctl failure, ret=%ld"
+                                          " command was:", ret);
                                v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),
                                                cmd);
                        }
                }
        } else {
                pvr2_trace(PVR2_TRACE_V4LIOCTL,
-                          "pvr2_v4l2_do_ioctl complete, ret=%d (0x%x)",
-                          ret,ret);
+                          "pvr2_v4l2_do_ioctl complete, ret=%ld (0x%lx)",
+                          ret, ret);
        }
        return ret;
 }
@@ -948,7 +948,7 @@ static void pvr2_v4l2_internal_check(struct pvr2_channel *chp)
 }
 
 
-static int pvr2_v4l2_ioctl(struct inode *inode, struct file *file,
+static long pvr2_v4l2_ioctl(struct file *file,
                           unsigned int cmd, unsigned long arg)
 {
 
@@ -960,7 +960,7 @@ static int pvr2_v4l2_ioctl(struct inode *inode, struct file *file,
 }
 
 
-static int pvr2_v4l2_release(struct inode *inode, struct file *file)
+static int pvr2_v4l2_release(struct file *file)
 {
        struct pvr2_v4l2_fh *fhp = file->private_data;
        struct pvr2_v4l2 *vp = fhp->vhead;
@@ -1008,7 +1008,7 @@ static int pvr2_v4l2_release(struct inode *inode, struct file *file)
 }
 
 
-static int pvr2_v4l2_open(struct inode *inode, struct file *file)
+static int pvr2_v4l2_open(struct file *file)
 {
        struct pvr2_v4l2_dev *dip; /* Our own context pointer */
        struct pvr2_v4l2_fh *fhp;
@@ -1235,13 +1235,12 @@ static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait)
 }
 
 
-static const struct file_operations vdev_fops = {
+static const struct v4l2_file_operations vdev_fops = {
        .owner      = THIS_MODULE,
        .open       = pvr2_v4l2_open,
        .release    = pvr2_v4l2_release,
        .read       = pvr2_v4l2_read,
        .ioctl      = pvr2_v4l2_ioctl,
-       .llseek     = no_llseek,
        .poll       = pvr2_v4l2_poll,
 };
 
index c6653021019224c697053b869d62a656333a89d5..f9fbe02e0f6950d44d8f2cab2fa5bb549ca0445a 100644 (file)
@@ -1266,9 +1266,9 @@ int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
 /* copy local variable to arg */
 #define ARG_OUT(ARG_name) /* nothing */
 
-int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
+long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
 {
-       int ret = 0;
+       long ret = 0;
 
        switch(cmd) {
        case VIDIOCPWCRUSER:
index 1ce9da167b7e5e8de2b4f73064386eab3eda8f99..39fbc970f43de09da5d45fd6951b82af337a2775 100644 (file)
@@ -142,16 +142,16 @@ static struct {
 
 /***/
 
-static int pwc_video_open(struct inode *inode, struct file *file);
-static int pwc_video_close(struct inode *inode, struct file *file);
+static int pwc_video_open(struct file *file);
+static int pwc_video_close(struct file *file);
 static ssize_t pwc_video_read(struct file *file, char __user *buf,
                          size_t count, loff_t *ppos);
 static unsigned int pwc_video_poll(struct file *file, poll_table *wait);
-static int  pwc_video_ioctl(struct inode *inode, struct file *file,
+static long  pwc_video_ioctl(struct file *file,
                            unsigned int ioctlnr, unsigned long arg);
 static int  pwc_video_mmap(struct file *file, struct vm_area_struct *vma);
 
-static const struct file_operations pwc_fops = {
+static const struct v4l2_file_operations pwc_fops = {
        .owner =        THIS_MODULE,
        .open =         pwc_video_open,
        .release =      pwc_video_close,
@@ -159,10 +159,6 @@ static const struct file_operations pwc_fops = {
        .poll =         pwc_video_poll,
        .mmap =         pwc_video_mmap,
        .ioctl =        pwc_video_ioctl,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl = v4l_compat_ioctl32,
-#endif
-       .llseek =       no_llseek,
 };
 static struct video_device pwc_template = {
        .name =         "Philips Webcam",       /* Filled in later */
@@ -1104,7 +1100,7 @@ static const char *pwc_sensor_type_to_string(unsigned int sensor_type)
 /***************************************************************************/
 /* Video4Linux functions */
 
-static int pwc_video_open(struct inode *inode, struct file *file)
+static int pwc_video_open(struct file *file)
 {
        int i, ret;
        struct video_device *vdev = video_devdata(file);
@@ -1224,7 +1220,7 @@ static void pwc_cleanup(struct pwc_device *pdev)
 }
 
 /* Note that all cleanup is done in the reverse order as in _open */
-static int pwc_video_close(struct inode *inode, struct file *file)
+static int pwc_video_close(struct file *file)
 {
        struct video_device *vdev = file->private_data;
        struct pwc_device *pdev;
@@ -1399,12 +1395,12 @@ static unsigned int pwc_video_poll(struct file *file, poll_table *wait)
        return 0;
 }
 
-static int pwc_video_ioctl(struct inode *inode, struct file *file,
+static long pwc_video_ioctl(struct file *file,
                           unsigned int cmd, unsigned long arg)
 {
        struct video_device *vdev = file->private_data;
        struct pwc_device *pdev;
-       int r = -ENODEV;
+       long r = -ENODEV;
 
        if (!vdev)
                goto out;
index d7c147328e35268b6d68138cb499df52bdebe38c..bc0a464295c59d511128b8526c445419c808e7b3 100644 (file)
@@ -337,7 +337,7 @@ static int pwc_vidioc_set_fmt(struct pwc_device *pdev, struct v4l2_format *f)
 
 }
 
-int pwc_video_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+long pwc_video_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 {
        struct video_device *vdev = video_devdata(file);
        struct pwc_device *pdev;
index c046a253566880c115e437946ee2e38129aa89b8..01411fb2337ae9d0e392d2d0cd611889b1e8b2b7 100644 (file)
@@ -337,10 +337,10 @@ extern int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise);
 extern int pwc_camera_power(struct pwc_device *pdev, int power);
 
 /* Private ioctl()s; see pwc-ioctl.h */
-extern int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg);
+extern long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg);
 
 /** Functions in pwc-v4l.c */
-extern int pwc_video_do_ioctl(struct file *file, unsigned int cmd, void *arg);
+extern long pwc_video_do_ioctl(struct file *file, unsigned int cmd, void *arg);
 
 /** pwc-uncompress.c */
 /* Expand frame to image, possibly including decompression. Uses read_frame and fill_image */
index 3c3f8cf73108a55280fb27bd33118fbe8f4c98e6..13f85ad363cd3b7b81e5eae85675846b0452a966 100644 (file)
@@ -1502,9 +1502,9 @@ static int vidioc_s_jpegcomp(struct file *file, void *priv,
        dprintk(2, "setting jpeg quality %d\n", jc->quality);
        return 0;
 }
-static int s2255_open(struct inode *inode, struct file *file)
+static int s2255_open(struct file *file)
 {
-       int minor = iminor(inode);
+       int minor = video_devdata(file)->minor;
        struct s2255_dev *h, *dev = NULL;
        struct s2255_fh *fh;
        struct list_head *list;
@@ -1711,11 +1711,11 @@ static void s2255_destroy(struct kref *kref)
        mutex_unlock(&dev->open_lock);
 }
 
-static int s2255_close(struct inode *inode, struct file *file)
+static int s2255_close(struct file *file)
 {
        struct s2255_fh *fh = file->private_data;
        struct s2255_dev *dev = fh->dev;
-       int minor = iminor(inode);
+       int minor = video_devdata(file)->minor;
        if (!dev)
                return -ENODEV;
 
@@ -1759,15 +1759,13 @@ static int s2255_mmap_v4l(struct file *file, struct vm_area_struct *vma)
        return ret;
 }
 
-static const struct file_operations s2255_fops_v4l = {
+static const struct v4l2_file_operations s2255_fops_v4l = {
        .owner = THIS_MODULE,
        .open = s2255_open,
        .release = s2255_close,
        .poll = s2255_poll,
        .ioctl = video_ioctl2,  /* V4L2 ioctl handler */
-       .compat_ioctl = v4l_compat_ioctl32,
        .mmap = s2255_mmap_v4l,
-       .llseek = no_llseek,
 };
 
 static const struct v4l2_ioctl_ops s2255_ioctl_ops = {
index f159441e937527afbab13e49e824214613e3da6d..e637e440b6d589eaba402bebff53e4e05f756467 100644 (file)
@@ -804,7 +804,7 @@ static inline int saa5246a_stop_dau(struct saa5246a_device *t,
  *
  *  Returns 0 if successful
  */
-static int do_saa5246a_ioctl(struct file *file, unsigned int cmd, void *arg)
+static long do_saa5246a_ioctl(struct file *file, unsigned int cmd, void *arg)
 {
        struct saa5246a_device *t = video_drvdata(file);
 
@@ -944,11 +944,11 @@ static inline unsigned int vtx_fix_command(unsigned int cmd)
 /*
  *     Handle the locking
  */
-static int saa5246a_ioctl(struct inode *inode, struct file *file,
+static long saa5246a_ioctl(struct file *file,
                         unsigned int cmd, unsigned long arg)
 {
        struct saa5246a_device *t = video_drvdata(file);
-       int err;
+       long err;
 
        cmd = vtx_fix_command(cmd);
        mutex_lock(&t->lock);
@@ -957,7 +957,7 @@ static int saa5246a_ioctl(struct inode *inode, struct file *file,
        return err;
 }
 
-static int saa5246a_open(struct inode *inode, struct file *file)
+static int saa5246a_open(struct file *file)
 {
        struct saa5246a_device *t = video_drvdata(file);
 
@@ -999,7 +999,7 @@ static int saa5246a_open(struct inode *inode, struct file *file)
        return 0;
 }
 
-static int saa5246a_release(struct inode *inode, struct file *file)
+static int saa5246a_release(struct file *file)
 {
        struct saa5246a_device *t = video_drvdata(file);
 
@@ -1018,12 +1018,11 @@ static int saa5246a_release(struct inode *inode, struct file *file)
        return 0;
 }
 
-static const struct file_operations saa_fops = {
+static const struct v4l2_file_operations saa_fops = {
        .owner   = THIS_MODULE,
        .open    = saa5246a_open,
        .release = saa5246a_release,
        .ioctl   = saa5246a_ioctl,
-       .llseek  = no_llseek,
 };
 
 static struct video_device saa_template =
index 6ef3affb97f163d165c227a178c199ea5913d7bc..e297651924697ad8114977253ee509a5c3bfbefe 100644 (file)
@@ -190,7 +190,7 @@ static int i2c_getdata(struct saa5249_device *t, int count, u8 *buf)
  *     Standard character-device-driver functions
  */
 
-static int do_saa5249_ioctl(struct file *file, unsigned int cmd, void *arg)
+static long do_saa5249_ioctl(struct file *file, unsigned int cmd, void *arg)
 {
        static int virtual_mode = false;
        struct saa5249_device *t = video_drvdata(file);
@@ -479,11 +479,11 @@ static inline unsigned int vtx_fix_command(unsigned int cmd)
  *     Handle the locking
  */
 
-static int saa5249_ioctl(struct inode *inode, struct file *file,
+static long saa5249_ioctl(struct file *file,
                         unsigned int cmd, unsigned long arg)
 {
        struct saa5249_device *t = video_drvdata(file);
-       int err;
+       long err;
 
        cmd = vtx_fix_command(cmd);
        mutex_lock(&t->lock);
@@ -492,7 +492,7 @@ static int saa5249_ioctl(struct inode *inode, struct file *file,
        return err;
 }
 
-static int saa5249_open(struct inode *inode, struct file *file)
+static int saa5249_open(struct file *file)
 {
        struct saa5249_device *t = video_drvdata(file);
        int pgbuf;
@@ -529,7 +529,7 @@ static int saa5249_open(struct inode *inode, struct file *file)
 
 
 
-static int saa5249_release(struct inode *inode, struct file *file)
+static int saa5249_release(struct file *file)
 {
        struct saa5249_device *t = video_drvdata(file);
 
@@ -539,15 +539,11 @@ static int saa5249_release(struct inode *inode, struct file *file)
        return 0;
 }
 
-static const struct file_operations saa_fops = {
+static const struct v4l2_file_operations saa_fops = {
        .owner          = THIS_MODULE,
        .open           = saa5249_open,
        .release        = saa5249_release,
        .ioctl          = saa5249_ioctl,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = v4l_compat_ioctl32,
-#endif
-       .llseek         = no_llseek,
 };
 
 static struct video_device saa_template =
index 22708ecdf1bbaad27f1d8e81ef30054102d0977c..46c796c3fec887010d1da38810fdeac0d1ef2158 100644 (file)
@@ -1371,25 +1371,24 @@ static int saa711x_g_vbi_data(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_dat
 }
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-static int saa711x_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
+static int saa711x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
 
-       if (!v4l2_chip_match_i2c_client(client,
-                               reg->match_type, reg->match_chip))
+       if (!v4l2_chip_match_i2c_client(client, &reg->match))
                return -EINVAL;
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
        reg->val = saa711x_read(sd, reg->reg & 0xff);
+       reg->size = 1;
        return 0;
 }
 
-static int saa711x_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
+static int saa711x_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
 
-       if (!v4l2_chip_match_i2c_client(client,
-                               reg->match_type, reg->match_chip))
+       if (!v4l2_chip_match_i2c_client(client, &reg->match))
                return -EINVAL;
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
@@ -1398,7 +1397,7 @@ static int saa711x_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
 }
 #endif
 
-static int saa711x_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip)
+static int saa711x_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
 {
        struct saa711x_state *state = to_state(sd);
        struct i2c_client *client = v4l2_get_subdevdata(sd);
index bfc85654795e089189a1e676ac9d63b9651f0fcd..d6848f7a503b5874e58259696f69f8033f89b407 100644 (file)
@@ -623,25 +623,24 @@ static int saa7127_s_vbi_data(struct v4l2_subdev *sd, const struct v4l2_sliced_v
 }
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-static int saa7127_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
+static int saa7127_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
 
-       if (!v4l2_chip_match_i2c_client(client,
-                               reg->match_type, reg->match_chip))
+       if (!v4l2_chip_match_i2c_client(client, &reg->match))
                return -EINVAL;
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
        reg->val = saa7127_read(sd, reg->reg & 0xff);
+       reg->size = 1;
        return 0;
 }
 
-static int saa7127_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
+static int saa7127_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
 
-       if (!v4l2_chip_match_i2c_client(client,
-                               reg->match_type, reg->match_chip))
+       if (!v4l2_chip_match_i2c_client(client, &reg->match))
                return -EINVAL;
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
@@ -650,7 +649,7 @@ static int saa7127_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
 }
 #endif
 
-static int saa7127_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip)
+static int saa7127_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
 {
        struct saa7127_state *state = to_state(sd);
        struct i2c_client *client = v4l2_get_subdevdata(sd);
index 1fb6eccdade32ac5f22a1c6493914e6ce041bc8c..1fee6e84a512c77ac4e8dffaadca0d994a6fb9bf 100644 (file)
@@ -838,7 +838,7 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
                h->standard = *((v4l2_std_id *) arg);
                break;
 
-       case VIDIOC_G_CHIP_IDENT:
+       case VIDIOC_DBG_G_CHIP_IDENT:
                return v4l2_chip_ident_i2c_client(client,
                                arg, h->chip, h->revision);
 
index a2e3f6729c5b1ad709fc9749d17054a93c3188e4..e2febcd6e529f45245bbd02c6c7e684ca9e14fe5 100644 (file)
@@ -4462,6 +4462,7 @@ struct saa7134_board saa7134_boards[] = {
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
                .tda9887_conf   = TDA9887_PRESENT,
+               .mpeg           = SAA7134_MPEG_DVB,
                .inputs         = {{
                        .name = name_tv,
                        .vmux = 3,
@@ -4480,8 +4481,6 @@ struct saa7134_board saa7134_boards[] = {
                        .name = name_radio,
                        .amux = LINE2,
                },
-               /* no DVB support for now */
-               /* .mpeg           = SAA7134_MPEG_DVB, */
        },
        [SAA7134_BOARD_ASUSTeK_TIGER_3IN1] = {
                .name           = "Asus Tiger 3in1",
@@ -4643,6 +4642,38 @@ struct saa7134_board saa7134_boards[] = {
                        .amux = 2,
                },
        },
+       [SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS] = {
+               .name           = "Avermedia AVerTV GO 007 FM Plus",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .gpiomask       = 0x00300003,
+               /* .gpiomask       = 0x8c240003, */
+               .inputs         = { {
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+                       .gpio = 0x01,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 6,
+                       .amux = LINE1,
+                       .gpio = 0x02,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = TV,
+                       .gpio = 0x00300001,
+               },
+               .mute = {
+                       .name = name_mute,
+                       .amux = TV,
+                       .gpio = 0x01,
+               },
+       },
 };
 
 const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
@@ -5701,6 +5732,13 @@ struct pci_device_id saa7134_pci_tbl[] = {
                .subvendor    = 0x17de,
                .subdevice    = 0x7128,
                .driver_data  = SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
+               .subdevice    = 0xf31d,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS,
+
        }, {
                /* --- boards without eeprom + subsystem ID --- */
                .vendor       = PCI_VENDOR_ID_PHILIPS,
@@ -5930,6 +5968,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
        case SAA7134_BOARD_GENIUS_TVGO_A11MCE:
        case SAA7134_BOARD_REAL_ANGEL_220:
        case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG:
+       case SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS:
                dev->has_remote = SAA7134_REMOTE_GPIO;
                break;
        case SAA7134_BOARD_FLYDVBS_LR300:
@@ -6025,6 +6064,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
        case SAA7134_BOARD_BEHOLD_M6:
        case SAA7134_BOARD_BEHOLD_M63:
        case SAA7134_BOARD_BEHOLD_M6_EXTRA:
+       case SAA7134_BOARD_BEHOLD_H6:
                dev->has_remote = SAA7134_REMOTE_I2C;
                break;
        case SAA7134_BOARD_AVERMEDIA_A169_B:
index d9a5652595b525d16827da87af1bf9de56a88a57..0776ecf56d2702505dc227292fddb3113da9dc5e 100644 (file)
@@ -49,6 +49,8 @@
 #include "lnbp21.h"
 #include "tuner-simple.h"
 
+#include "zl10353.h"
+
 MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
 MODULE_LICENSE("GPL");
 
@@ -854,6 +856,12 @@ static struct tda1004x_config ads_tech_duo_config = {
        .request_firmware = philips_tda1004x_request_firmware
 };
 
+static struct zl10353_config behold_h6_config = {
+       .demod_address = 0x1e>>1,
+       .no_tuner      = 1,
+       .parallel_ts   = 1,
+};
+
 /* ==================================================================
  * tda10086 based DVB-S cards, helper functions
  */
@@ -1357,6 +1365,16 @@ static int dvb_init(struct saa7134_dev *dev)
                                         &tda827x_cfg_0) < 0)
                        goto dettach_frontend;
                break;
+       case SAA7134_BOARD_BEHOLD_H6:
+               fe0->dvb.frontend = dvb_attach(zl10353_attach,
+                                               &behold_h6_config,
+                                               &dev->i2c_adap);
+               if (fe0->dvb.frontend) {
+                       dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
+                                  &dev->i2c_adap, 0x61,
+                                  TUNER_PHILIPS_FMD1216ME_MK3);
+               }
+               break;
        default:
                wprintk("Huh? unknown DVB card?\n");
                break;
index 7f40511bcc04b9493423d2fc9826d57e2473af98..c9d8beb87a608114c30ce64577a440afb788847c 100644 (file)
@@ -83,9 +83,9 @@ static int ts_init_encoder(struct saa7134_dev* dev)
 
 /* ------------------------------------------------------------------ */
 
-static int ts_open(struct inode *inode, struct file *file)
+static int ts_open(struct file *file)
 {
-       int minor = iminor(inode);
+       int minor = video_devdata(file)->minor;
        struct saa7134_dev *dev;
        int err;
 
@@ -119,7 +119,7 @@ done:
        return err;
 }
 
-static int ts_release(struct inode *inode, struct file *file)
+static int ts_release(struct file *file)
 {
        struct saa7134_dev *dev = file->private_data;
 
@@ -405,7 +405,7 @@ static int empress_querymenu(struct file *file, void *priv,
 }
 
 static int empress_g_chip_ident(struct file *file, void *fh,
-              struct v4l2_chip_ident *chip)
+              struct v4l2_dbg_chip_ident *chip)
 {
        struct saa7134_dev *dev = file->private_data;
 
@@ -413,12 +413,12 @@ static int empress_g_chip_ident(struct file *file, void *fh,
        chip->revision = 0;
        if (dev->mpeg_i2c_client == NULL)
                return -EINVAL;
-       if (chip->match_type == V4L2_CHIP_MATCH_I2C_DRIVER &&
-           chip->match_chip == I2C_DRIVERID_SAA6752HS)
-               return saa7134_i2c_call_saa6752(dev, VIDIOC_G_CHIP_IDENT, chip);
-       if (chip->match_type == V4L2_CHIP_MATCH_I2C_ADDR &&
-           chip->match_chip == dev->mpeg_i2c_client->addr)
-               return saa7134_i2c_call_saa6752(dev, VIDIOC_G_CHIP_IDENT, chip);
+       if (chip->match.type == V4L2_CHIP_MATCH_I2C_DRIVER &&
+           !strcmp(chip->match.name, "saa6752hs"))
+               return saa7134_i2c_call_saa6752(dev, VIDIOC_DBG_G_CHIP_IDENT, chip);
+       if (chip->match.type == V4L2_CHIP_MATCH_I2C_ADDR &&
+           chip->match.addr == dev->mpeg_i2c_client->addr)
+               return saa7134_i2c_call_saa6752(dev, VIDIOC_DBG_G_CHIP_IDENT, chip);
        return -EINVAL;
 }
 
@@ -437,7 +437,7 @@ static int empress_g_std(struct file *file, void *priv, v4l2_std_id *id)
        return 0;
 }
 
-static const struct file_operations ts_fops =
+static const struct v4l2_file_operations ts_fops =
 {
        .owner    = THIS_MODULE,
        .open     = ts_open,
@@ -446,7 +446,6 @@ static const struct file_operations ts_fops =
        .poll     = ts_poll,
        .mmap     = ts_mmap,
        .ioctl    = video_ioctl2,
-       .llseek   = no_llseek,
 };
 
 static const struct v4l2_ioctl_ops ts_ioctl_ops = {
index d2124f64e4e2339a6d140e0bc83a72b011c0c766..8a106d36e7232c4bce0c38aef1071526cdf93ae1 100644 (file)
@@ -449,6 +449,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
        case SAA7134_BOARD_AVERMEDIA_STUDIO_507:
        case SAA7134_BOARD_AVERMEDIA_GO_007_FM:
        case SAA7134_BOARD_AVERMEDIA_M102:
+       case SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS:
                ir_codes     = ir_codes_avermedia;
                mask_keycode = 0x0007C8;
                mask_keydown = 0x000010;
index 02bb6747a39c846fa7c19c288e9703054c1c40d5..a1f7e351f57234480719c0b297c38ccbf7583cb1 100644 (file)
@@ -1326,9 +1326,9 @@ static int saa7134_resource(struct saa7134_fh *fh)
        return 0;
 }
 
-static int video_open(struct inode *inode, struct file *file)
+static int video_open(struct file *file)
 {
-       int minor = iminor(inode);
+       int minor = video_devdata(file)->minor;
        struct saa7134_dev *dev;
        struct saa7134_fh *fh;
        enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@@ -1462,7 +1462,7 @@ err:
        return POLLERR;
 }
 
-static int video_release(struct inode *inode, struct file *file)
+static int video_release(struct file *file)
 {
        struct saa7134_fh  *fh  = file->private_data;
        struct saa7134_dev *dev = fh->dev;
@@ -2247,24 +2247,25 @@ static int saa7134_g_parm(struct file *file, void *fh,
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 static int vidioc_g_register (struct file *file, void *priv,
-                             struct v4l2_register *reg)
+                             struct v4l2_dbg_register *reg)
 {
        struct saa7134_fh *fh = priv;
        struct saa7134_dev *dev = fh->dev;
 
-       if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
+       if (!v4l2_chip_match_host(&reg->match))
                return -EINVAL;
        reg->val = saa_readb(reg->reg);
+       reg->size = 1;
        return 0;
 }
 
 static int vidioc_s_register (struct file *file, void *priv,
-                               struct v4l2_register *reg)
+                               struct v4l2_dbg_register *reg)
 {
        struct saa7134_fh *fh = priv;
        struct saa7134_dev *dev = fh->dev;
 
-       if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
+       if (!v4l2_chip_match_host(&reg->match))
                return -EINVAL;
        saa_writeb(reg->reg&0xffffff, reg->val);
        return 0;
@@ -2377,7 +2378,7 @@ static int radio_queryctrl(struct file *file, void *priv,
        return 0;
 }
 
-static const struct file_operations video_fops =
+static const struct v4l2_file_operations video_fops =
 {
        .owner    = THIS_MODULE,
        .open     = video_open,
@@ -2386,8 +2387,6 @@ static const struct file_operations video_fops =
        .poll     = video_poll,
        .mmap     = video_mmap,
        .ioctl    = video_ioctl2,
-       .compat_ioctl   = v4l_compat_ioctl32,
-       .llseek   = no_llseek,
 };
 
 static const struct v4l2_ioctl_ops video_ioctl_ops = {
@@ -2441,13 +2440,11 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
 #endif
 };
 
-static const struct file_operations radio_fops = {
+static const struct v4l2_file_operations radio_fops = {
        .owner    = THIS_MODULE,
        .open     = video_open,
        .release  = video_release,
        .ioctl    = video_ioctl2,
-       .compat_ioctl   = v4l_compat_ioctl32,
-       .llseek   = no_llseek,
 };
 
 static const struct v4l2_ioctl_ops radio_ioctl_ops = {
index f6c1fcc720701cc04c74fe6029a0b0f3acfff942..14ee265f33747b3f9583f8e51d78b917189dfd97 100644 (file)
@@ -276,6 +276,7 @@ struct saa7134_format {
 #define SAA7134_BOARD_ADS_INSTANT_HDTV_PCI  151
 #define SAA7134_BOARD_ASUSTeK_TIGER         152
 #define SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG 153
+#define SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS 154
 
 #define SAA7134_MAXBOARDS 32
 #define SAA7134_INPUT_MAX 8
index 9befca65905e0e6dee10882f240fac2d361b1b99..454ad1dd7507a5f523b8513ef10988cd06d6b81f 100644 (file)
@@ -1171,25 +1171,26 @@ static int saa717x_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
 }
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-static int saa717x_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
+static int saa717x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
 
-       if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip))
+       if (!v4l2_chip_match_i2c_client(client, &reg->match))
                return -EINVAL;
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
        reg->val = saa717x_read(sd, reg->reg);
+       reg->size = 1;
        return 0;
 }
 
-static int saa717x_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
+static int saa717x_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        u16 addr = reg->reg & 0xffff;
        u8 val = reg->val & 0xff;
 
-       if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip))
+       if (!v4l2_chip_match_i2c_client(client, &reg->match))
                return -EINVAL;
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
index d652f25eef0edc9b5aef4a23c0928246588116b6..5990ab38a1249146a8ebdff9b2b1c8be02b58a8e 100644 (file)
@@ -932,7 +932,7 @@ static void usb_se401_remove_disconnected (struct usb_se401 *se401)
  ***************************************************************************/
 
 
-static int se401_open(struct inode *inode, struct file *file)
+static int se401_open(struct file *file)
 {
        struct video_device *dev = video_devdata(file);
        struct usb_se401 *se401 = (struct usb_se401 *)dev;
@@ -954,7 +954,7 @@ static int se401_open(struct inode *inode, struct file *file)
        return err;
 }
 
-static int se401_close(struct inode *inode, struct file *file)
+static int se401_close(struct file *file)
 {
        struct video_device *dev = file->private_data;
        struct usb_se401 *se401 = (struct usb_se401 *)dev;
@@ -975,7 +975,7 @@ static int se401_close(struct inode *inode, struct file *file)
        return 0;
 }
 
-static int se401_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+static long se401_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 {
        struct video_device *vdev = file->private_data;
        struct usb_se401 *se401 = (struct usb_se401 *)vdev;
@@ -1138,7 +1138,7 @@ static int se401_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        return 0;
 }
 
-static int se401_ioctl(struct inode *inode, struct file *file,
+static long se401_ioctl(struct file *file,
                       unsigned int cmd, unsigned long arg)
 {
        return video_usercopy(file, cmd, arg, se401_do_ioctl);
@@ -1222,17 +1222,13 @@ static int se401_mmap(struct file *file, struct vm_area_struct *vma)
        return 0;
 }
 
-static const struct file_operations se401_fops = {
+static const struct v4l2_file_operations se401_fops = {
        .owner =        THIS_MODULE,
        .open =         se401_open,
        .release =      se401_close,
        .read =         se401_read,
        .mmap =         se401_mmap,
        .ioctl =        se401_ioctl,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl = v4l_compat_ioctl32,
-#endif
-       .llseek =       no_llseek,
 };
 static struct video_device se401_template = {
        .name =         "se401 USB camera",
index 01a8efb8deb156f274ad54e514be0082783df6f2..23edfdc4d4bcafb8230e5924d0773381eea01dc3 100644 (file)
@@ -1746,7 +1746,7 @@ static void sn9c102_release_resources(struct kref *kref)
 }
 
 
-static int sn9c102_open(struct inode* inode, struct file* filp)
+static int sn9c102_open(struct file *filp)
 {
        struct sn9c102_device* cam;
        int err = 0;
@@ -1857,7 +1857,7 @@ out:
 }
 
 
-static int sn9c102_release(struct inode* inode, struct file* filp)
+static int sn9c102_release(struct file *filp)
 {
        struct sn9c102_device* cam;
 
@@ -3092,8 +3092,8 @@ sn9c102_vidioc_s_audio(struct sn9c102_device* cam, void __user * arg)
 }
 
 
-static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp,
-                             unsigned int cmd, void __user * arg)
+static long sn9c102_ioctl_v4l2(struct file *filp,
+                             unsigned int cmd, void __user *arg)
 {
        struct sn9c102_device *cam = video_drvdata(filp);
 
@@ -3196,7 +3196,7 @@ static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp,
 }
 
 
-static int sn9c102_ioctl(struct inode* inode, struct file* filp,
+static long sn9c102_ioctl(struct file *filp,
                         unsigned int cmd, unsigned long arg)
 {
        struct sn9c102_device *cam = video_drvdata(filp);
@@ -3220,7 +3220,7 @@ static int sn9c102_ioctl(struct inode* inode, struct file* filp,
 
        V4LDBG(3, "sn9c102", cmd);
 
-       err = sn9c102_ioctl_v4l2(inode, filp, cmd, (void __user *)arg);
+       err = sn9c102_ioctl_v4l2(filp, cmd, (void __user *)arg);
 
        mutex_unlock(&cam->fileop_mutex);
 
@@ -3229,18 +3229,14 @@ static int sn9c102_ioctl(struct inode* inode, struct file* filp,
 
 /*****************************************************************************/
 
-static const struct file_operations sn9c102_fops = {
+static const struct v4l2_file_operations sn9c102_fops = {
        .owner = THIS_MODULE,
        .open = sn9c102_open,
        .release = sn9c102_release,
        .ioctl = sn9c102_ioctl,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl = v4l_compat_ioctl32,
-#endif
        .read = sn9c102_read,
        .poll = sn9c102_poll,
        .mmap = sn9c102_mmap,
-       .llseek = no_llseek,
 };
 
 /*****************************************************************************/
index 90077cb4fe667fed105771fbb379ac3024dac480..fcb05f06de8ffb7d73e564820110ca78100a7a07 100644 (file)
@@ -256,7 +256,7 @@ static void soc_camera_free_user_formats(struct soc_camera_device *icd)
        vfree(icd->user_formats);
 }
 
-static int soc_camera_open(struct inode *inode, struct file *file)
+static int soc_camera_open(struct file *file)
 {
        struct video_device *vdev;
        struct soc_camera_device *icd;
@@ -330,7 +330,7 @@ emgd:
        return ret;
 }
 
-static int soc_camera_close(struct inode *inode, struct file *file)
+static int soc_camera_close(struct file *file)
 {
        struct soc_camera_file *icf = file->private_data;
        struct soc_camera_device *icd = icf->icd;
@@ -400,7 +400,7 @@ static unsigned int soc_camera_poll(struct file *file, poll_table *pt)
        return ici->ops->poll(file, pt);
 }
 
-static struct file_operations soc_camera_fops = {
+static struct v4l2_file_operations soc_camera_fops = {
        .owner          = THIS_MODULE,
        .open           = soc_camera_open,
        .release        = soc_camera_close,
@@ -408,7 +408,6 @@ static struct file_operations soc_camera_fops = {
        .read           = soc_camera_read,
        .mmap           = soc_camera_mmap,
        .poll           = soc_camera_poll,
-       .llseek         = no_llseek,
 };
 
 static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv,
@@ -700,7 +699,7 @@ static int soc_camera_s_crop(struct file *file, void *fh,
 }
 
 static int soc_camera_g_chip_ident(struct file *file, void *fh,
-                                  struct v4l2_chip_ident *id)
+                                  struct v4l2_dbg_chip_ident *id)
 {
        struct soc_camera_file *icf = file->private_data;
        struct soc_camera_device *icd = icf->icd;
@@ -713,7 +712,7 @@ static int soc_camera_g_chip_ident(struct file *file, void *fh,
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 static int soc_camera_g_register(struct file *file, void *fh,
-                                struct v4l2_register *reg)
+                                struct v4l2_dbg_register *reg)
 {
        struct soc_camera_file *icf = file->private_data;
        struct soc_camera_device *icd = icf->icd;
@@ -725,7 +724,7 @@ static int soc_camera_g_register(struct file *file, void *fh,
 }
 
 static int soc_camera_s_register(struct file *file, void *fh,
-                                struct v4l2_register *reg)
+                                struct v4l2_dbg_register *reg)
 {
        struct soc_camera_file *icf = file->private_data;
        struct soc_camera_device *icd = icf->icd;
index f9516d0f3c1121ee2122cb01ef51b9e6465434f3..26378cf390fc483542dce73a1e0ad5ccb6f3a698 100644 (file)
@@ -664,7 +664,7 @@ static void stk_free_buffers(struct stk_camera *dev)
 
 /* v4l file operations */
 
-static int v4l_stk_open(struct inode *inode, struct file *fp)
+static int v4l_stk_open(struct file *fp)
 {
        struct stk_camera *dev;
        struct video_device *vdev;
@@ -684,7 +684,7 @@ static int v4l_stk_open(struct inode *inode, struct file *fp)
        return 0;
 }
 
-static int v4l_stk_release(struct inode *inode, struct file *fp)
+static int v4l_stk_release(struct file *fp)
 {
        struct stk_camera *dev = fp->private_data;
 
@@ -1281,7 +1281,7 @@ static int stk_vidioc_enum_framesizes(struct file *filp,
        }
 }
 
-static struct file_operations v4l_stk_fops = {
+static struct v4l2_file_operations v4l_stk_fops = {
        .owner = THIS_MODULE,
        .open = v4l_stk_open,
        .release = v4l_stk_release,
@@ -1289,10 +1289,6 @@ static struct file_operations v4l_stk_fops = {
        .poll = v4l_stk_poll,
        .mmap = v4l_stk_mmap,
        .ioctl = video_ioctl2,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl = v4l_compat_ioctl32,
-#endif
-       .llseek = no_llseek
 };
 
 static const struct v4l2_ioctl_ops v4l_stk_ioctl_ops = {
index bbad54f85c83c83a92d8d4d41cdedf70af3b1803..0eb313082c973e78fcfe6e2e935ec1c5751ce5c6 100644 (file)
@@ -1275,7 +1275,7 @@ static void make_clip_tab(struct saa7146 *saa, struct video_clip *cr, int ncr)
                clip_draw_rectangle(clipmap, 0, 0, 1024, -saa->win.y);
 }
 
-static int saa_ioctl(struct inode *inode, struct file *file,
+static long saa_ioctl(struct file *file,
                     unsigned int cmd, unsigned long argl)
 {
        struct saa7146 *saa = file->private_data;
@@ -1877,7 +1877,7 @@ static ssize_t saa_write(struct file *file, const char __user * buf,
        return count;
 }
 
-static int saa_open(struct inode *inode, struct file *file)
+static int saa_open(struct file *file)
 {
        struct video_device *vdev = video_devdata(file);
        struct saa7146 *saa = container_of(vdev, struct saa7146, video_dev);
@@ -1895,7 +1895,7 @@ static int saa_open(struct inode *inode, struct file *file)
        return 0;
 }
 
-static int saa_release(struct inode *inode, struct file *file)
+static int saa_release(struct file *file)
 {
        struct saa7146 *saa = file->private_data;
        saa->user--;
@@ -1906,16 +1906,12 @@ static int saa_release(struct inode *inode, struct file *file)
        return 0;
 }
 
-static const struct file_operations saa_fops = {
+static const struct v4l2_file_operations saa_fops = {
        .owner = THIS_MODULE,
        .open = saa_open,
        .release = saa_release,
        .ioctl = saa_ioctl,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl = v4l_compat_ioctl32,
-#endif
        .read = saa_read,
-       .llseek = no_llseek,
        .write = saa_write,
        .mmap = saa_mmap,
 };
index 42acc92c182da708c3cdf0ed315996a11a74ea16..75f286f7a2e9939cfc9d24f25a06d6b50c8cab91 100644 (file)
@@ -1080,7 +1080,7 @@ static int stv680_newframe (struct usb_stv *stv680, int framenr)
  * Video4Linux
  *********************************************************************/
 
-static int stv_open (struct inode *inode, struct file *file)
+static int stv_open(struct file *file)
 {
        struct video_device *dev = video_devdata(file);
        struct usb_stv *stv680 = video_get_drvdata(dev);
@@ -1106,7 +1106,7 @@ static int stv_open (struct inode *inode, struct file *file)
        return err;
 }
 
-static int stv_close (struct inode *inode, struct file *file)
+static int stv_close(struct file *file)
 {
        struct video_device *dev = file->private_data;
        struct usb_stv *stv680 = video_get_drvdata(dev);
@@ -1132,7 +1132,7 @@ static int stv_close (struct inode *inode, struct file *file)
        return 0;
 }
 
-static int stv680_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+static long stv680_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 {
        struct video_device *vdev = file->private_data;
        struct usb_stv *stv680 = video_get_drvdata(vdev);
@@ -1299,7 +1299,7 @@ static int stv680_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        return 0;
 }
 
-static int stv680_ioctl(struct inode *inode, struct file *file,
+static long stv680_ioctl(struct file *file,
                        unsigned int cmd, unsigned long arg)
 {
        return video_usercopy(file, cmd, arg, stv680_do_ioctl);
@@ -1391,17 +1391,13 @@ static ssize_t stv680_read (struct file *file, char __user *buf,
        return realcount;
 }                              /* stv680_read */
 
-static const struct file_operations stv680_fops = {
+static const struct v4l2_file_operations stv680_fops = {
        .owner =        THIS_MODULE,
        .open =         stv_open,
        .release =      stv_close,
        .read =         stv680_read,
        .mmap =         stv680_mmap,
        .ioctl =        stv680_ioctl,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl = v4l_compat_ioctl32,
-#endif
-       .llseek =       no_llseek,
 };
 static struct video_device stv680_template = {
        .name =         "STV0680 USB camera",
index 2644e0dc925139dab0e8a7f4881257c3cf44ef05..6afb7059502d00df6aa75dbdd24568bb11a2d5f1 100644 (file)
@@ -137,7 +137,7 @@ static int tda9840_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *t)
        return 0;
 }
 
-static int tda9840_ioctl(struct v4l2_subdev *sd, unsigned cmd, void *arg)
+static long tda9840_ioctl(struct v4l2_subdev *sd, unsigned cmd, void *arg)
 {
        int byte;
 
index 31dde86f2df4f6f187fe97eea6c8358efef22f1a..7519fd1f57efbd14418b7c9993d34a0528e6ab34 100644 (file)
@@ -122,7 +122,7 @@ static int switch_matrix(struct i2c_client *client, int i, int o)
        return ret;
 }
 
-static int tea6415c_ioctl(struct v4l2_subdev *sd, unsigned cmd, void *arg)
+static long tea6415c_ioctl(struct v4l2_subdev *sd, unsigned cmd, void *arg)
 {
        if (cmd == TEA6415C_SWITCH) {
                struct i2c_client *client = v4l2_get_subdevdata(sd);
index 38e519f04bdeac9241ca12e7d70a3da598d7321d..081e74fa3b2eb2360dc68c1a0cdac0564548a0d2 100644 (file)
@@ -90,7 +90,7 @@ static int tea6420_switch(struct i2c_client *client, int i, int o, int g)
        return 0;
 }
 
-static int tea6420_ioctl(struct v4l2_subdev *sd, unsigned cmd, void *arg)
+static long tea6420_ioctl(struct v4l2_subdev *sd, unsigned cmd, void *arg)
 {
        if (cmd == TEA6420_SWITCH) {
                struct i2c_client *client = v4l2_get_subdevdata(sd);
index 97d7509d212f67602526b21a5656794be0656d90..30640fbfd0f921ad0734eb939a533bfea1e7fc0e 100644 (file)
@@ -800,7 +800,7 @@ static int tuner_s_standby(struct v4l2_subdev *sd, u32 standby)
 }
 
 #ifdef CONFIG_VIDEO_ALLOW_V4L1
-static int tuner_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
+static long tuner_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
 {
        struct tuner *t = to_tuner(sd);
        struct i2c_client *client = v4l2_get_subdevdata(sd);
index d0c794da735b413eb8b83006e732c4e89117adda..5aeccb301cea147370c89af12de35cc3306f4c9d 100644 (file)
@@ -1762,7 +1762,7 @@ static int tvaudio_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *fr
        return 0;
 }
 
-static int tvaudio_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip)
+static int tvaudio_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
 
index a388a9f0cb187d380f5286bef7838875b801beb9..2cd64ef27b95ee6b8f37a982cc233bb690d02017 100644 (file)
@@ -963,7 +963,7 @@ static int tvp5150_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
 
 
 static int tvp5150_g_chip_ident(struct v4l2_subdev *sd,
-                               struct v4l2_chip_ident *chip)
+                               struct v4l2_dbg_chip_ident *chip)
 {
        int rev;
        struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -977,25 +977,24 @@ static int tvp5150_g_chip_ident(struct v4l2_subdev *sd,
 
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-static int tvp5150_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
+static int tvp5150_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
 
-       if (!v4l2_chip_match_i2c_client(client,
-                               reg->match_type, reg->match_chip))
+       if (!v4l2_chip_match_i2c_client(client, &reg->match))
                return -EINVAL;
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
        reg->val = tvp5150_read(sd, reg->reg & 0xff);
+       reg->size = 1;
        return 0;
 }
 
-static int tvp5150_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
+static int tvp5150_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
 
-       if (!v4l2_chip_match_i2c_client(client,
-                               reg->match_type, reg->match_chip))
+       if (!v4l2_chip_match_i2c_client(client, &reg->match))
                return -EINVAL;
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
index d5cdc4be1a354e41d89e6c2de2b21648b0f0cfce..52c0357faa5d0fb2e270e41dc05fd44ec56bdd7a 100644 (file)
@@ -575,7 +575,7 @@ static unsigned long tw9910_query_bus_param(struct soc_camera_device *icd)
 }
 
 static int tw9910_get_chip_id(struct soc_camera_device *icd,
-                             struct v4l2_chip_ident *id)
+                             struct v4l2_dbg_chip_ident *id)
 {
        id->ident = V4L2_IDENT_TW9910;
        id->revision = 0;
@@ -606,7 +606,7 @@ static int tw9910_enum_input(struct soc_camera_device *icd,
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 static int tw9910_get_register(struct soc_camera_device *icd,
-                              struct v4l2_register *reg)
+                              struct v4l2_dbg_register *reg)
 {
        struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd);
        int ret;
@@ -627,7 +627,7 @@ static int tw9910_get_register(struct soc_camera_device *icd,
 }
 
 static int tw9910_set_register(struct soc_camera_device *icd,
-                              struct v4l2_register *reg)
+                              struct v4l2_dbg_register *reg)
 {
        struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd);
 
index 7a609a3a6dbe2e3be83b06afa6669c86c365e03a..4f16effb530fd61f33328e57028f67ec8c39faf4 100644 (file)
@@ -147,7 +147,7 @@ static int upd64031a_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing
        return upd64031a_s_frequency(sd, NULL);
 }
 
-static int upd64031a_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip)
+static int upd64031a_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
 
@@ -162,25 +162,24 @@ static int upd64031a_log_status(struct v4l2_subdev *sd)
 }
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-static int upd64031a_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
+static int upd64031a_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
 
-       if (!v4l2_chip_match_i2c_client(client,
-                               reg->match_type, reg->match_chip))
+       if (!v4l2_chip_match_i2c_client(client, &reg->match))
                return -EINVAL;
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
        reg->val = upd64031a_read(sd, reg->reg & 0xff);
+       reg->size = 1;
        return 0;
 }
 
-static int upd64031a_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
+static int upd64031a_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
 
-       if (!v4l2_chip_match_i2c_client(client,
-                               reg->match_type, reg->match_chip))
+       if (!v4l2_chip_match_i2c_client(client, &reg->match))
                return -EINVAL;
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
index 58412cb9c01a0d058ec01f3f5113b75e6b757e0b..4b712f69d1b715c1fddce33e9cadb7f531ccf62d 100644 (file)
@@ -120,25 +120,24 @@ static int upd64083_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing
 }
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-static int upd64083_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
+static int upd64083_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
 
-       if (!v4l2_chip_match_i2c_client(client,
-                               reg->match_type, reg->match_chip))
+       if (!v4l2_chip_match_i2c_client(client, &reg->match))
                return -EINVAL;
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
        reg->val = upd64083_read(sd, reg->reg & 0xff);
+       reg->size = 1;
        return 0;
 }
 
-static int upd64083_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
+static int upd64083_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
 
-       if (!v4l2_chip_match_i2c_client(client,
-                               reg->match_type, reg->match_chip))
+       if (!v4l2_chip_match_i2c_client(client, &reg->match))
                return -EINVAL;
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
@@ -147,7 +146,7 @@ static int upd64083_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg
 }
 #endif
 
-static int upd64083_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip)
+static int upd64083_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
 
index 148a1f98c70f714e46f0af650a49268f5d07ae59..dea8b321fb4a5b983f35da9f56fa6a83a22c1895 100644 (file)
@@ -41,13 +41,13 @@ module_param(video_nr, int, 0);
 static void usbvideo_Disconnect(struct usb_interface *intf);
 static void usbvideo_CameraRelease(struct uvd *uvd);
 
-static int usbvideo_v4l_ioctl(struct inode *inode, struct file *file,
+static long usbvideo_v4l_ioctl(struct file *file,
                              unsigned int cmd, unsigned long arg);
 static int usbvideo_v4l_mmap(struct file *file, struct vm_area_struct *vma);
-static int usbvideo_v4l_open(struct inode *inode, struct file *file);
+static int usbvideo_v4l_open(struct file *file);
 static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf,
                             size_t count, loff_t *ppos);
-static int usbvideo_v4l_close(struct inode *inode, struct file *file);
+static int usbvideo_v4l_close(struct file *file);
 
 static int usbvideo_StartDataPump(struct uvd *uvd);
 static void usbvideo_StopDataPump(struct uvd *uvd);
@@ -942,17 +942,13 @@ static int usbvideo_find_struct(struct usbvideo *cams)
        return rv;
 }
 
-static const struct file_operations usbvideo_fops = {
+static const struct v4l2_file_operations usbvideo_fops = {
        .owner =  THIS_MODULE,
        .open =   usbvideo_v4l_open,
        .release =usbvideo_v4l_close,
        .read =   usbvideo_v4l_read,
        .mmap =   usbvideo_v4l_mmap,
        .ioctl =  usbvideo_v4l_ioctl,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl = v4l_compat_ioctl32,
-#endif
-       .llseek = no_llseek,
 };
 static const struct video_device usbvideo_template = {
        .fops =       &usbvideo_fops,
@@ -1113,7 +1109,7 @@ static int usbvideo_v4l_mmap(struct file *file, struct vm_area_struct *vma)
  * 27-Jan-2000 Used USBVIDEO_NUMSBUF as number of URB buffers.
  * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT).
  */
-static int usbvideo_v4l_open(struct inode *inode, struct file *file)
+static int usbvideo_v4l_open(struct file *file)
 {
        struct video_device *dev = video_devdata(file);
        struct uvd *uvd = (struct uvd *) dev;
@@ -1233,7 +1229,7 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file)
  * 27-Jan-2000 Used USBVIDEO_NUMSBUF as number of URB buffers.
  * 24-May-2000 Moved MOD_DEC_USE_COUNT outside of code that can sleep.
  */
-static int usbvideo_v4l_close(struct inode *inode, struct file *file)
+static int usbvideo_v4l_close(struct file *file)
 {
        struct video_device *dev = file->private_data;
        struct uvd *uvd = (struct uvd *) dev;
@@ -1281,7 +1277,7 @@ static int usbvideo_v4l_close(struct inode *inode, struct file *file)
  * History:
  * 22-Jan-2000 Corrected VIDIOCSPICT to reject unsupported settings.
  */
-static int usbvideo_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+static long usbvideo_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 {
        struct uvd *uvd = file->private_data;
 
@@ -1501,7 +1497,7 @@ static int usbvideo_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        return 0;
 }
 
-static int usbvideo_v4l_ioctl(struct inode *inode, struct file *file,
+static long usbvideo_v4l_ioctl(struct file *file,
                       unsigned int cmd, unsigned long arg)
 {
        return video_usercopy(file, cmd, arg, usbvideo_v4l_do_ioctl);
index 4602597ed8d1af301b198dfb7dfe8f97994f5614..2f1106338c085d7881940e54951d10b8ac93c44b 100644 (file)
@@ -229,12 +229,12 @@ set_camera_power(struct vicam_camera *cam, int state)
        return 0;
 }
 
-static int
-vicam_ioctl(struct inode *inode, struct file *file, unsigned int ioctlnr, unsigned long arg)
+static long
+vicam_ioctl(struct file *file, unsigned int ioctlnr, unsigned long arg)
 {
        void __user *user_arg = (void __user *)arg;
        struct vicam_camera *cam = file->private_data;
-       int retval = 0;
+       long retval = 0;
 
        if (!cam)
                return -ENODEV;
@@ -470,7 +470,7 @@ vicam_ioctl(struct inode *inode, struct file *file, unsigned int ioctlnr, unsign
 }
 
 static int
-vicam_open(struct inode *inode, struct file *file)
+vicam_open(struct file *file)
 {
        struct vicam_camera *cam = video_drvdata(file);
 
@@ -536,7 +536,7 @@ vicam_open(struct inode *inode, struct file *file)
 }
 
 static int
-vicam_close(struct inode *inode, struct file *file)
+vicam_close(struct file *file)
 {
        struct vicam_camera *cam = file->private_data;
        int open_count;
@@ -783,17 +783,13 @@ vicam_mmap(struct file *file, struct vm_area_struct *vma)
        return 0;
 }
 
-static const struct file_operations vicam_fops = {
+static const struct v4l2_file_operations vicam_fops = {
        .owner          = THIS_MODULE,
        .open           = vicam_open,
        .release        = vicam_close,
        .read           = vicam_read,
        .mmap           = vicam_mmap,
        .ioctl          = vicam_ioctl,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = v4l_compat_ioctl32,
-#endif
-       .llseek         = no_llseek,
 };
 
 static struct video_device vicam_template = {
index 85661b1848fe5cb52111c50b65b56c93372070b8..2be5e47ed081949b8f50b2f6528d9929d47c45d8 100644 (file)
@@ -355,7 +355,7 @@ static void usbvision_remove_sysfs(struct video_device *vdev)
  * then allocates buffers needed for video processing.
  *
  */
-static int usbvision_v4l2_open(struct inode *inode, struct file *file)
+static int usbvision_v4l2_open(struct file *file)
 {
        struct usb_usbvision *usbvision = video_drvdata(file);
        int errCode = 0;
@@ -432,7 +432,7 @@ static int usbvision_v4l2_open(struct inode *inode, struct file *file)
  * allocated in usbvision_v4l2_open().
  *
  */
-static int usbvision_v4l2_close(struct inode *inode, struct file *file)
+static int usbvision_v4l2_close(struct file *file)
 {
        struct usb_usbvision *usbvision = video_drvdata(file);
 
@@ -477,12 +477,12 @@ static int usbvision_v4l2_close(struct inode *inode, struct file *file)
  */
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 static int vidioc_g_register (struct file *file, void *priv,
-                               struct v4l2_register *reg)
+                               struct v4l2_dbg_register *reg)
 {
        struct usb_usbvision *usbvision = video_drvdata(file);
        int errCode;
 
-       if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
+       if (!v4l2_chip_match_host(&reg->match))
                return -EINVAL;
        /* NT100x has a 8-bit register space */
        errCode = usbvision_read_reg(usbvision, reg->reg&0xff);
@@ -492,16 +492,17 @@ static int vidioc_g_register (struct file *file, void *priv,
                return errCode;
        }
        reg->val = errCode;
+       reg->size = 1;
        return 0;
 }
 
 static int vidioc_s_register (struct file *file, void *priv,
-                               struct v4l2_register *reg)
+                               struct v4l2_dbg_register *reg)
 {
        struct usb_usbvision *usbvision = video_drvdata(file);
        int errCode;
 
-       if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
+       if (!v4l2_chip_match_host(&reg->match))
                return -EINVAL;
        /* NT100x has a 8-bit register space */
        errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val);
@@ -1178,7 +1179,7 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
  * Here comes the stuff for radio on usbvision based devices
  *
  */
-static int usbvision_radio_open(struct inode *inode, struct file *file)
+static int usbvision_radio_open(struct file *file)
 {
        struct usb_usbvision *usbvision = video_drvdata(file);
        int errCode = 0;
@@ -1228,7 +1229,7 @@ out:
 }
 
 
-static int usbvision_radio_close(struct inode *inode, struct file *file)
+static int usbvision_radio_close(struct file *file)
 {
        struct usb_usbvision *usbvision = video_drvdata(file);
        int errCode = 0;
@@ -1266,26 +1267,26 @@ static int usbvision_radio_close(struct inode *inode, struct file *file)
  * Here comes the stuff for vbi on usbvision based devices
  *
  */
-static int usbvision_vbi_open(struct inode *inode, struct file *file)
+static int usbvision_vbi_open(struct file *file)
 {
        /* TODO */
        return -ENODEV;
 }
 
-static int usbvision_vbi_close(struct inode *inode, struct file *file)
+static int usbvision_vbi_close(struct file *file)
 {
        /* TODO */
        return -ENODEV;
 }
 
-static int usbvision_do_vbi_ioctl(struct file *file,
+static long usbvision_do_vbi_ioctl(struct file *file,
                                 unsigned int cmd, void *arg)
 {
        /* TODO */
        return -ENOIOCTLCMD;
 }
 
-static int usbvision_vbi_ioctl(struct inode *inode, struct file *file,
+static long usbvision_vbi_ioctl(struct file *file,
                       unsigned int cmd, unsigned long arg)
 {
        return video_usercopy(file, cmd, arg, usbvision_do_vbi_ioctl);
@@ -1297,16 +1298,14 @@ static int usbvision_vbi_ioctl(struct inode *inode, struct file *file,
 //
 
 // Video template
-static const struct file_operations usbvision_fops = {
+static const struct v4l2_file_operations usbvision_fops = {
        .owner             = THIS_MODULE,
        .open           = usbvision_v4l2_open,
        .release        = usbvision_v4l2_close,
        .read           = usbvision_v4l2_read,
        .mmap           = usbvision_v4l2_mmap,
        .ioctl          = video_ioctl2,
-       .llseek         = no_llseek,
 /*     .poll          = video_poll, */
-       .compat_ioctl  = v4l_compat_ioctl32,
 };
 
 static const struct v4l2_ioctl_ops usbvision_ioctl_ops = {
@@ -1355,13 +1354,11 @@ static struct video_device usbvision_video_template = {
 
 
 // Radio template
-static const struct file_operations usbvision_radio_fops = {
+static const struct v4l2_file_operations usbvision_radio_fops = {
        .owner             = THIS_MODULE,
        .open           = usbvision_radio_open,
        .release        = usbvision_radio_close,
        .ioctl          = video_ioctl2,
-       .llseek         = no_llseek,
-       .compat_ioctl  = v4l_compat_ioctl32,
 };
 
 static const struct v4l2_ioctl_ops usbvision_radio_ioctl_ops = {
@@ -1392,13 +1389,11 @@ static struct video_device usbvision_radio_template = {
 };
 
 // vbi template
-static const struct file_operations usbvision_vbi_fops = {
+static const struct v4l2_file_operations usbvision_vbi_fops = {
        .owner             = THIS_MODULE,
        .open           = usbvision_vbi_open,
        .release        = usbvision_vbi_close,
        .ioctl          = usbvision_vbi_ioctl,
-       .llseek         = no_llseek,
-       .compat_ioctl  = v4l_compat_ioctl32,
 };
 
 static struct video_device usbvision_vbi_template=
index afcc6934559e6f7c5f819fd74efb6b0f2c488e63..fa150fff2c10964e0ea8c2b9deb0ac22a98a96a3 100644 (file)
@@ -406,7 +406,7 @@ static int uvc_has_privileges(struct uvc_fh *handle)
  * V4L2 file operations
  */
 
-static int uvc_v4l2_open(struct inode *inode, struct file *file)
+static int uvc_v4l2_open(struct file *file)
 {
        struct uvc_video_device *video;
        struct uvc_fh *handle;
@@ -444,7 +444,7 @@ done:
        return ret;
 }
 
-static int uvc_v4l2_release(struct inode *inode, struct file *file)
+static int uvc_v4l2_release(struct file *file)
 {
        struct uvc_video_device *video = video_drvdata(file);
        struct uvc_fh *handle = (struct uvc_fh *)file->private_data;
@@ -472,12 +472,12 @@ static int uvc_v4l2_release(struct inode *inode, struct file *file)
        return 0;
 }
 
-static int uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 {
        struct video_device *vdev = video_devdata(file);
        struct uvc_video_device *video = video_get_drvdata(vdev);
        struct uvc_fh *handle = (struct uvc_fh *)file->private_data;
-       int ret = 0;
+       long ret = 0;
 
        switch (cmd) {
        /* Query capabilities */
@@ -996,7 +996,7 @@ static int uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        return ret;
 }
 
-static int uvc_v4l2_ioctl(struct inode *inode, struct file *file,
+static long uvc_v4l2_ioctl(struct file *file,
                     unsigned int cmd, unsigned long arg)
 {
        if (uvc_trace_param & UVC_TRACE_IOCTL) {
@@ -1097,13 +1097,11 @@ static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait)
        return uvc_queue_poll(&video->queue, file, wait);
 }
 
-struct file_operations uvc_fops = {
+const struct v4l2_file_operations uvc_fops = {
        .owner          = THIS_MODULE,
        .open           = uvc_v4l2_open,
        .release        = uvc_v4l2_release,
        .ioctl          = uvc_v4l2_ioctl,
-       .compat_ioctl   = v4l_compat_ioctl32,
-       .llseek         = no_llseek,
        .read           = uvc_v4l2_read,
        .mmap           = uvc_v4l2_mmap,
        .poll           = uvc_v4l2_poll,
index 896b791ece159565553804e8e2efb7db942820bc..bcf4361dc1bc8ffd543e5f1533d0b85d413da076 100644 (file)
@@ -753,7 +753,7 @@ static inline int uvc_queue_streaming(struct uvc_video_queue *queue)
 }
 
 /* V4L2 interface */
-extern struct file_operations uvc_fops;
+extern const struct v4l2_file_operations uvc_fops;
 
 /* Video */
 extern int uvc_video_init(struct uvc_video_device *video);
index f13c0a9d684fe997dcbe0ab593f04d1c49557c21..d450cab20be4d09f8e92e259ba424b235ba36139 100644 (file)
@@ -267,12 +267,12 @@ done:
 
 /* ----------------------------------------------------------------- */
 
-static noinline int v4l1_compat_get_capabilities(
+static noinline long v4l1_compat_get_capabilities(
                                        struct video_capability *cap,
                                        struct file *file,
                                        v4l2_kioctl drv)
 {
-       int err;
+       long err;
        struct v4l2_framebuffer fbuf;
        struct v4l2_capability *cap2;
 
@@ -286,13 +286,13 @@ static noinline int v4l1_compat_get_capabilities(
 
        err = drv(file, VIDIOC_QUERYCAP, cap2);
        if (err < 0) {
-               dprintk("VIDIOCGCAP / VIDIOC_QUERYCAP: %d\n", err);
+               dprintk("VIDIOCGCAP / VIDIOC_QUERYCAP: %ld\n", err);
                goto done;
        }
        if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY) {
                err = drv(file, VIDIOC_G_FBUF, &fbuf);
                if (err < 0) {
-                       dprintk("VIDIOCGCAP / VIDIOC_G_FBUF: %d\n", err);
+                       dprintk("VIDIOCGCAP / VIDIOC_G_FBUF: %ld\n", err);
                        memset(&fbuf, 0, sizeof(fbuf));
                }
                err = 0;
@@ -324,12 +324,12 @@ done:
        return err;
 }
 
-static noinline int v4l1_compat_get_frame_buffer(
+static noinline long v4l1_compat_get_frame_buffer(
                                        struct video_buffer *buffer,
                                        struct file *file,
                                        v4l2_kioctl drv)
 {
-       int err;
+       long err;
        struct v4l2_framebuffer fbuf;
 
        memset(buffer, 0, sizeof(*buffer));
@@ -337,7 +337,7 @@ static noinline int v4l1_compat_get_frame_buffer(
 
        err = drv(file, VIDIOC_G_FBUF, &fbuf);
        if (err < 0) {
-               dprintk("VIDIOCGFBUF / VIDIOC_G_FBUF: %d\n", err);
+               dprintk("VIDIOCGFBUF / VIDIOC_G_FBUF: %ld\n", err);
                goto done;
        }
        buffer->base   = fbuf.base;
@@ -378,12 +378,12 @@ done:
        return err;
 }
 
-static noinline int v4l1_compat_set_frame_buffer(
+static noinline long v4l1_compat_set_frame_buffer(
                                        struct video_buffer *buffer,
                                        struct file *file,
                                        v4l2_kioctl drv)
 {
-       int err;
+       long err;
        struct v4l2_framebuffer fbuf;
 
        memset(&fbuf, 0, sizeof(fbuf));
@@ -410,16 +410,16 @@ static noinline int v4l1_compat_set_frame_buffer(
        fbuf.fmt.bytesperline = buffer->bytesperline;
        err = drv(file, VIDIOC_S_FBUF, &fbuf);
        if (err < 0)
-               dprintk("VIDIOCSFBUF / VIDIOC_S_FBUF: %d\n", err);
+               dprintk("VIDIOCSFBUF / VIDIOC_S_FBUF: %ld\n", err);
        return err;
 }
 
-static noinline int v4l1_compat_get_win_cap_dimensions(
+static noinline long v4l1_compat_get_win_cap_dimensions(
                                        struct video_window *win,
                                        struct file *file,
                                        v4l2_kioctl drv)
 {
-       int err;
+       long err;
        struct v4l2_format *fmt;
 
        fmt = kzalloc(sizeof(*fmt), GFP_KERNEL);
@@ -432,7 +432,7 @@ static noinline int v4l1_compat_get_win_cap_dimensions(
        fmt->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
        err = drv(file, VIDIOC_G_FMT, fmt);
        if (err < 0)
-               dprintk("VIDIOCGWIN / VIDIOC_G_WIN: %d\n", err);
+               dprintk("VIDIOCGWIN / VIDIOC_G_WIN: %ld\n", err);
        if (err == 0) {
                win->x         = fmt->fmt.win.w.left;
                win->y         = fmt->fmt.win.w.top;
@@ -447,7 +447,7 @@ static noinline int v4l1_compat_get_win_cap_dimensions(
        fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        err = drv(file, VIDIOC_G_FMT, fmt);
        if (err < 0) {
-               dprintk("VIDIOCGWIN / VIDIOC_G_FMT: %d\n", err);
+               dprintk("VIDIOCGWIN / VIDIOC_G_FMT: %ld\n", err);
                goto done;
        }
        win->x         = 0;
@@ -462,12 +462,12 @@ done:
        return err;
 }
 
-static noinline int v4l1_compat_set_win_cap_dimensions(
+static noinline long v4l1_compat_set_win_cap_dimensions(
                                        struct video_window *win,
                                        struct file *file,
                                        v4l2_kioctl drv)
 {
-       int err, err1, err2;
+       long err, err1, err2;
        struct v4l2_format *fmt;
 
        fmt = kzalloc(sizeof(*fmt), GFP_KERNEL);
@@ -479,7 +479,7 @@ static noinline int v4l1_compat_set_win_cap_dimensions(
        drv(file, VIDIOC_STREAMOFF, &fmt->type);
        err1 = drv(file, VIDIOC_G_FMT, fmt);
        if (err1 < 0)
-               dprintk("VIDIOCSWIN / VIDIOC_G_FMT: %d\n", err1);
+               dprintk("VIDIOCSWIN / VIDIOC_G_FMT: %ld\n", err1);
        if (err1 == 0) {
                fmt->fmt.pix.width  = win->width;
                fmt->fmt.pix.height = win->height;
@@ -487,7 +487,7 @@ static noinline int v4l1_compat_set_win_cap_dimensions(
                fmt->fmt.pix.bytesperline = 0;
                err = drv(file, VIDIOC_S_FMT, fmt);
                if (err < 0)
-                       dprintk("VIDIOCSWIN / VIDIOC_S_FMT #1: %d\n",
+                       dprintk("VIDIOCSWIN / VIDIOC_S_FMT #1: %ld\n",
                                err);
                win->width  = fmt->fmt.pix.width;
                win->height = fmt->fmt.pix.height;
@@ -504,7 +504,7 @@ static noinline int v4l1_compat_set_win_cap_dimensions(
        fmt->fmt.win.clipcount = win->clipcount;
        err2 = drv(file, VIDIOC_S_FMT, fmt);
        if (err2 < 0)
-               dprintk("VIDIOCSWIN / VIDIOC_S_FMT #2: %d\n", err2);
+               dprintk("VIDIOCSWIN / VIDIOC_S_FMT #2: %ld\n", err2);
 
        if (err1 != 0 && err2 != 0)
                err = err1;
@@ -514,12 +514,12 @@ static noinline int v4l1_compat_set_win_cap_dimensions(
        return err;
 }
 
-static noinline int v4l1_compat_turn_preview_on_off(
+static noinline long v4l1_compat_turn_preview_on_off(
                                        int *on,
                                        struct file *file,
                                        v4l2_kioctl drv)
 {
-       int err;
+       long err;
        enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
        if (0 == *on) {
@@ -530,16 +530,16 @@ static noinline int v4l1_compat_turn_preview_on_off(
        }
        err = drv(file, VIDIOC_OVERLAY, on);
        if (err < 0)
-               dprintk("VIDIOCCAPTURE / VIDIOC_PREVIEW: %d\n", err);
+               dprintk("VIDIOCCAPTURE / VIDIOC_PREVIEW: %ld\n", err);
        return err;
 }
 
-static noinline int v4l1_compat_get_input_info(
+static noinline long v4l1_compat_get_input_info(
                                        struct video_channel *chan,
                                        struct file *file,
                                        v4l2_kioctl drv)
 {
-       int err;
+       long err;
        struct v4l2_input       input2;
        v4l2_std_id             sid;
 
@@ -548,7 +548,7 @@ static noinline int v4l1_compat_get_input_info(
        err = drv(file, VIDIOC_ENUMINPUT, &input2);
        if (err < 0) {
                dprintk("VIDIOCGCHAN / VIDIOC_ENUMINPUT: "
-                       "channel=%d err=%d\n", chan->channel, err);
+                       "channel=%d err=%ld\n", chan->channel, err);
                goto done;
        }
        chan->channel = input2.index;
@@ -569,7 +569,7 @@ static noinline int v4l1_compat_get_input_info(
        chan->norm = 0;
        err = drv(file, VIDIOC_G_STD, &sid);
        if (err < 0)
-               dprintk("VIDIOCGCHAN / VIDIOC_G_STD: %d\n", err);
+               dprintk("VIDIOCGCHAN / VIDIOC_G_STD: %ld\n", err);
        if (err == 0) {
                if (sid & V4L2_STD_PAL)
                        chan->norm = VIDEO_MODE_PAL;
@@ -582,17 +582,17 @@ done:
        return err;
 }
 
-static noinline int v4l1_compat_set_input(
+static noinline long v4l1_compat_set_input(
                                        struct video_channel *chan,
                                        struct file *file,
                                        v4l2_kioctl drv)
 {
-       int err;
+       long err;
        v4l2_std_id sid = 0;
 
        err = drv(file, VIDIOC_S_INPUT, &chan->channel);
        if (err < 0)
-               dprintk("VIDIOCSCHAN / VIDIOC_S_INPUT: %d\n", err);
+               dprintk("VIDIOCSCHAN / VIDIOC_S_INPUT: %ld\n", err);
        switch (chan->norm) {
        case VIDEO_MODE_PAL:
                sid = V4L2_STD_PAL;
@@ -607,17 +607,17 @@ static noinline int v4l1_compat_set_input(
        if (0 != sid) {
                err = drv(file, VIDIOC_S_STD, &sid);
                if (err < 0)
-                       dprintk("VIDIOCSCHAN / VIDIOC_S_STD: %d\n", err);
+                       dprintk("VIDIOCSCHAN / VIDIOC_S_STD: %ld\n", err);
        }
        return err;
 }
 
-static noinline int v4l1_compat_get_picture(
+static noinline long v4l1_compat_get_picture(
                                        struct video_picture *pict,
                                        struct file *file,
                                        v4l2_kioctl drv)
 {
-       int err;
+       long err;
        struct v4l2_format *fmt;
 
        fmt = kzalloc(sizeof(*fmt), GFP_KERNEL);
@@ -640,7 +640,7 @@ static noinline int v4l1_compat_get_picture(
        fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        err = drv(file, VIDIOC_G_FMT, fmt);
        if (err < 0) {
-               dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %d\n", err);
+               dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %ld\n", err);
                goto done;
        }
 
@@ -654,12 +654,12 @@ done:
        return err;
 }
 
-static noinline int v4l1_compat_set_picture(
+static noinline long v4l1_compat_set_picture(
                                        struct video_picture *pict,
                                        struct file *file,
                                        v4l2_kioctl drv)
 {
-       int err;
+       long err;
        struct v4l2_framebuffer fbuf;
        int mem_err = 0, ovl_err = 0;
        struct v4l2_format *fmt;
@@ -694,7 +694,7 @@ static noinline int v4l1_compat_set_picture(
           support memory capture.  Trying to set the memory capture
           parameters would be pointless.  */
        if (err < 0) {
-               dprintk("VIDIOCSPICT / VIDIOC_G_FMT: %d\n", err);
+               dprintk("VIDIOCSPICT / VIDIOC_G_FMT: %ld\n", err);
                mem_err = -1000;  /* didn't even try */
        } else if (fmt->fmt.pix.pixelformat !=
                 palette_to_pixelformat(pict->palette)) {
@@ -711,7 +711,7 @@ static noinline int v4l1_compat_set_picture(
           support overlay.  Trying to set the overlay parameters
           would be quite pointless.  */
        if (err < 0) {
-               dprintk("VIDIOCSPICT / VIDIOC_G_FBUF: %d\n", err);
+               dprintk("VIDIOCSPICT / VIDIOC_G_FBUF: %ld\n", err);
                ovl_err = -1000;  /* didn't even try */
        } else if (fbuf.fmt.pixelformat !=
                 palette_to_pixelformat(pict->palette)) {
@@ -736,12 +736,13 @@ static noinline int v4l1_compat_set_picture(
        return err;
 }
 
-static noinline int v4l1_compat_get_tuner(
+static noinline long v4l1_compat_get_tuner(
                                        struct video_tuner *tun,
                                        struct file *file,
                                        v4l2_kioctl drv)
 {
-       int err, i;
+       long err;
+       int i;
        struct v4l2_tuner       tun2;
        struct v4l2_standard    std2;
        v4l2_std_id             sid;
@@ -749,7 +750,7 @@ static noinline int v4l1_compat_get_tuner(
        memset(&tun2, 0, sizeof(tun2));
        err = drv(file, VIDIOC_G_TUNER, &tun2);
        if (err < 0) {
-               dprintk("VIDIOCGTUNER / VIDIOC_G_TUNER: %d\n", err);
+               dprintk("VIDIOCGTUNER / VIDIOC_G_TUNER: %ld\n", err);
                goto done;
        }
        memcpy(tun->name, tun2.name,
@@ -775,7 +776,7 @@ static noinline int v4l1_compat_get_tuner(
 
        err = drv(file, VIDIOC_G_STD, &sid);
        if (err < 0)
-               dprintk("VIDIOCGTUNER / VIDIOC_G_STD: %d\n", err);
+               dprintk("VIDIOCGTUNER / VIDIOC_G_STD: %ld\n", err);
        if (err == 0) {
                if (sid & V4L2_STD_PAL)
                        tun->mode = VIDEO_MODE_PAL;
@@ -794,12 +795,12 @@ done:
        return err;
 }
 
-static noinline int v4l1_compat_select_tuner(
+static noinline long v4l1_compat_select_tuner(
                                        struct video_tuner *tun,
                                        struct file *file,
                                        v4l2_kioctl drv)
 {
-       int err;
+       long err;
        struct v4l2_tuner       t;/*84 bytes on x86_64*/
        memset(&t, 0, sizeof(t));
 
@@ -807,34 +808,34 @@ static noinline int v4l1_compat_select_tuner(
 
        err = drv(file, VIDIOC_S_INPUT, &t);
        if (err < 0)
-               dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n", err);
+               dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %ld\n", err);
        return err;
 }
 
-static noinline int v4l1_compat_get_frequency(
+static noinline long v4l1_compat_get_frequency(
                                        unsigned long *freq,
                                        struct file *file,
                                        v4l2_kioctl drv)
 {
-       int err;
+       long err;
        struct v4l2_frequency   freq2;
        memset(&freq2, 0, sizeof(freq2));
 
        freq2.tuner = 0;
        err = drv(file, VIDIOC_G_FREQUENCY, &freq2);
        if (err < 0)
-               dprintk("VIDIOCGFREQ / VIDIOC_G_FREQUENCY: %d\n", err);
+               dprintk("VIDIOCGFREQ / VIDIOC_G_FREQUENCY: %ld\n", err);
        if (0 == err)
                *freq = freq2.frequency;
        return err;
 }
 
-static noinline int v4l1_compat_set_frequency(
+static noinline long v4l1_compat_set_frequency(
                                        unsigned long *freq,
                                        struct file *file,
                                        v4l2_kioctl drv)
 {
-       int err;
+       long err;
        struct v4l2_frequency   freq2;
        memset(&freq2, 0, sizeof(freq2));
 
@@ -842,16 +843,17 @@ static noinline int v4l1_compat_set_frequency(
        freq2.frequency = *freq;
        err = drv(file, VIDIOC_S_FREQUENCY, &freq2);
        if (err < 0)
-               dprintk("VIDIOCSFREQ / VIDIOC_S_FREQUENCY: %d\n", err);
+               dprintk("VIDIOCSFREQ / VIDIOC_S_FREQUENCY: %ld\n", err);
        return err;
 }
 
-static noinline int v4l1_compat_get_audio(
+static noinline long v4l1_compat_get_audio(
                                        struct video_audio *aud,
                                        struct file *file,
                                        v4l2_kioctl drv)
 {
-       int err, i;
+       long err;
+       int i;
        struct v4l2_queryctrl   qctrl2;
        struct v4l2_audio       aud2;
        struct v4l2_tuner       tun2;
@@ -859,7 +861,7 @@ static noinline int v4l1_compat_get_audio(
 
        err = drv(file, VIDIOC_G_AUDIO, &aud2);
        if (err < 0) {
-               dprintk("VIDIOCGAUDIO / VIDIOC_G_AUDIO: %d\n", err);
+               dprintk("VIDIOCGAUDIO / VIDIOC_G_AUDIO: %ld\n", err);
                goto done;
        }
        memcpy(aud->name, aud2.name,
@@ -903,7 +905,7 @@ static noinline int v4l1_compat_get_audio(
        memset(&tun2, 0, sizeof(tun2));
        err = drv(file, VIDIOC_G_TUNER, &tun2);
        if (err < 0) {
-               dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %d\n", err);
+               dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %ld\n", err);
                err = 0;
                goto done;
        }
@@ -918,12 +920,12 @@ done:
        return err;
 }
 
-static noinline int v4l1_compat_set_audio(
+static noinline long v4l1_compat_set_audio(
                                        struct video_audio *aud,
                                        struct file *file,
                                        v4l2_kioctl drv)
 {
-       int err;
+       long err;
        struct v4l2_audio       aud2;
        struct v4l2_tuner       tun2;
 
@@ -933,7 +935,7 @@ static noinline int v4l1_compat_set_audio(
        aud2.index = aud->audio;
        err = drv(file, VIDIOC_S_AUDIO, &aud2);
        if (err < 0) {
-               dprintk("VIDIOCSAUDIO / VIDIOC_S_AUDIO: %d\n", err);
+               dprintk("VIDIOCSAUDIO / VIDIOC_S_AUDIO: %ld\n", err);
                goto done;
        }
 
@@ -950,7 +952,7 @@ static noinline int v4l1_compat_set_audio(
 
        err = drv(file, VIDIOC_G_TUNER, &tun2);
        if (err < 0)
-               dprintk("VIDIOCSAUDIO / VIDIOC_G_TUNER: %d\n", err);
+               dprintk("VIDIOCSAUDIO / VIDIOC_G_TUNER: %ld\n", err);
        if (err == 0) {
                switch (aud->mode) {
                default:
@@ -967,19 +969,19 @@ static noinline int v4l1_compat_set_audio(
                }
                err = drv(file, VIDIOC_S_TUNER, &tun2);
                if (err < 0)
-                       dprintk("VIDIOCSAUDIO / VIDIOC_S_TUNER: %d\n", err);
+                       dprintk("VIDIOCSAUDIO / VIDIOC_S_TUNER: %ld\n", err);
        }
        err = 0;
 done:
        return err;
 }
 
-static noinline int v4l1_compat_capture_frame(
+static noinline long v4l1_compat_capture_frame(
                                        struct video_mmap *mm,
                                        struct file *file,
                                        v4l2_kioctl drv)
 {
-       int err;
+       long err;
        enum v4l2_buf_type      captype = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        struct v4l2_buffer      buf;
        struct v4l2_format      *fmt;
@@ -994,7 +996,7 @@ static noinline int v4l1_compat_capture_frame(
        fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        err = drv(file, VIDIOC_G_FMT, fmt);
        if (err < 0) {
-               dprintk("VIDIOCMCAPTURE / VIDIOC_G_FMT: %d\n", err);
+               dprintk("VIDIOCMCAPTURE / VIDIOC_G_FMT: %ld\n", err);
                goto done;
        }
        if (mm->width   != fmt->fmt.pix.width  ||
@@ -1010,7 +1012,7 @@ static noinline int v4l1_compat_capture_frame(
                fmt->fmt.pix.bytesperline = 0;
                err = drv(file, VIDIOC_S_FMT, fmt);
                if (err < 0) {
-                       dprintk("VIDIOCMCAPTURE / VIDIOC_S_FMT: %d\n", err);
+                       dprintk("VIDIOCMCAPTURE / VIDIOC_S_FMT: %ld\n", err);
                        goto done;
                }
        }
@@ -1018,28 +1020,28 @@ static noinline int v4l1_compat_capture_frame(
        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        err = drv(file, VIDIOC_QUERYBUF, &buf);
        if (err < 0) {
-               dprintk("VIDIOCMCAPTURE / VIDIOC_QUERYBUF: %d\n", err);
+               dprintk("VIDIOCMCAPTURE / VIDIOC_QUERYBUF: %ld\n", err);
                goto done;
        }
        err = drv(file, VIDIOC_QBUF, &buf);
        if (err < 0) {
-               dprintk("VIDIOCMCAPTURE / VIDIOC_QBUF: %d\n", err);
+               dprintk("VIDIOCMCAPTURE / VIDIOC_QBUF: %ld\n", err);
                goto done;
        }
        err = drv(file, VIDIOC_STREAMON, &captype);
        if (err < 0)
-               dprintk("VIDIOCMCAPTURE / VIDIOC_STREAMON: %d\n", err);
+               dprintk("VIDIOCMCAPTURE / VIDIOC_STREAMON: %ld\n", err);
 done:
        kfree(fmt);
        return err;
 }
 
-static noinline int v4l1_compat_sync(
+static noinline long v4l1_compat_sync(
                                int *i,
                                struct file *file,
                                v4l2_kioctl drv)
 {
-       int err;
+       long err;
        enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        struct v4l2_buffer buf;
        struct poll_wqueues *pwq;
@@ -1050,7 +1052,7 @@ static noinline int v4l1_compat_sync(
        err = drv(file, VIDIOC_QUERYBUF, &buf);
        if (err < 0) {
                /*  No such buffer */
-               dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n", err);
+               dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %ld\n", err);
                goto done;
        }
        if (!(buf.flags & V4L2_BUF_FLAG_MAPPED)) {
@@ -1062,7 +1064,7 @@ static noinline int v4l1_compat_sync(
        /* make sure capture actually runs so we don't block forever */
        err = drv(file, VIDIOC_STREAMON, &captype);
        if (err < 0) {
-               dprintk("VIDIOCSYNC / VIDIOC_STREAMON: %d\n", err);
+               dprintk("VIDIOCSYNC / VIDIOC_STREAMON: %ld\n", err);
                goto done;
        }
 
@@ -1076,7 +1078,7 @@ static noinline int v4l1_compat_sync(
                        break;
                err = drv(file, VIDIOC_QUERYBUF, &buf);
                if (err < 0)
-                       dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n", err);
+                       dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %ld\n", err);
        }
        kfree(pwq);
        if (!(buf.flags & V4L2_BUF_FLAG_DONE)) /* not done */
@@ -1084,18 +1086,18 @@ static noinline int v4l1_compat_sync(
        do {
                err = drv(file, VIDIOC_DQBUF, &buf);
                if (err < 0)
-                       dprintk("VIDIOCSYNC / VIDIOC_DQBUF: %d\n", err);
+                       dprintk("VIDIOCSYNC / VIDIOC_DQBUF: %ld\n", err);
        } while (err == 0 && buf.index != *i);
 done:
        return err;
 }
 
-static noinline int v4l1_compat_get_vbi_format(
+static noinline long v4l1_compat_get_vbi_format(
                                struct vbi_format *fmt,
                                struct file *file,
                                v4l2_kioctl drv)
 {
-       int err;
+       long err;
        struct v4l2_format *fmt2;
 
        fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
@@ -1107,7 +1109,7 @@ static noinline int v4l1_compat_get_vbi_format(
 
        err = drv(file, VIDIOC_G_FMT, fmt2);
        if (err < 0) {
-               dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %d\n", err);
+               dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %ld\n", err);
                goto done;
        }
        if (fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY) {
@@ -1128,12 +1130,12 @@ done:
        return err;
 }
 
-static noinline int v4l1_compat_set_vbi_format(
+static noinline long v4l1_compat_set_vbi_format(
                                struct vbi_format *fmt,
                                struct file *file,
                                v4l2_kioctl drv)
 {
-       int err;
+       long err;
        struct v4l2_format      *fmt2 = NULL;
 
        if (VIDEO_PALETTE_RAW != fmt->sample_format) {
@@ -1157,7 +1159,7 @@ static noinline int v4l1_compat_set_vbi_format(
        fmt2->fmt.vbi.flags            = fmt->flags;
        err = drv(file, VIDIOC_TRY_FMT, fmt2);
        if (err < 0) {
-               dprintk("VIDIOCSVBIFMT / VIDIOC_TRY_FMT: %d\n", err);
+               dprintk("VIDIOCSVBIFMT / VIDIOC_TRY_FMT: %ld\n", err);
                goto done;
        }
 
@@ -1174,7 +1176,7 @@ static noinline int v4l1_compat_set_vbi_format(
        }
        err = drv(file, VIDIOC_S_FMT, fmt2);
        if (err < 0)
-               dprintk("VIDIOCSVBIFMT / VIDIOC_S_FMT: %d\n", err);
+               dprintk("VIDIOCSVBIFMT / VIDIOC_S_FMT: %ld\n", err);
 done:
        kfree(fmt2);
        return err;
@@ -1183,13 +1185,13 @@ done:
 /*
  *     This function is exported.
  */
-int
+long
 v4l_compat_translate_ioctl(struct file         *file,
                           int                  cmd,
                           void                 *arg,
                           v4l2_kioctl          drv)
 {
-       int err;
+       long err;
 
        switch (cmd) {
        case VIDIOCGCAP:        /* capability */
index c676b0b0f708340f7644f69d3b6ceaab29fd8eea..b8f2be8d5c0ee3702bad5f880180797e711082f9 100644 (file)
@@ -797,11 +797,11 @@ u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id)
 }
 EXPORT_SYMBOL(v4l2_ctrl_next);
 
-int v4l2_chip_match_host(u32 match_type, u32 match_chip)
+int v4l2_chip_match_host(const struct v4l2_dbg_match *match)
 {
-       switch (match_type) {
+       switch (match->type) {
        case V4L2_CHIP_MATCH_HOST:
-               return match_chip == 0;
+               return match->addr == 0;
        default:
                return 0;
        }
@@ -809,23 +809,34 @@ int v4l2_chip_match_host(u32 match_type, u32 match_chip)
 EXPORT_SYMBOL(v4l2_chip_match_host);
 
 #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
-int v4l2_chip_match_i2c_client(struct i2c_client *c, u32 match_type, u32 match_chip)
+int v4l2_chip_match_i2c_client(struct i2c_client *c, const struct v4l2_dbg_match *match)
 {
-       switch (match_type) {
+       int len;
+
+       if (c == NULL || match == NULL)
+               return 0;
+
+       switch (match->type) {
        case V4L2_CHIP_MATCH_I2C_DRIVER:
-               return (c != NULL && c->driver != NULL && c->driver->id == match_chip);
+               if (c->driver == NULL || c->driver->driver.name == NULL)
+                       return 0;
+               len = strlen(c->driver->driver.name);
+               /* legacy drivers have a ' suffix, don't try to match that */
+               if (len && c->driver->driver.name[len - 1] == '\'')
+                       len--;
+               return len && !strncmp(c->driver->driver.name, match->name, len);
        case V4L2_CHIP_MATCH_I2C_ADDR:
-               return (c != NULL && c->addr == match_chip);
+               return c->addr == match->addr;
        default:
                return 0;
        }
 }
 EXPORT_SYMBOL(v4l2_chip_match_i2c_client);
 
-int v4l2_chip_ident_i2c_client(struct i2c_client *c, struct v4l2_chip_ident *chip,
+int v4l2_chip_ident_i2c_client(struct i2c_client *c, struct v4l2_dbg_chip_ident *chip,
                u32 ident, u32 revision)
 {
-       if (!v4l2_chip_match_i2c_client(c, chip->match_type, chip->match_chip))
+       if (!v4l2_chip_match_i2c_client(c, &chip->match))
                return 0;
        if (chip->ident == V4L2_IDENT_NONE) {
                chip->ident = ident;
index d0e1bd3ace6aec3a8f2aeab76a79509e783f762f..110376be5d2b247921d390f5ea1e503d3c82331d 100644 (file)
@@ -222,9 +222,9 @@ static int get_microcode32(struct video_code *kp, struct video_code32 __user *up
 
 #endif
 
-static int native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+static long native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-       int ret = -ENOIOCTLCMD;
+       long ret = -ENOIOCTLCMD;
 
        if (file->f_op->unlocked_ioctl)
                ret = file->f_op->unlocked_ioctl(file, cmd, arg);
@@ -705,7 +705,7 @@ static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext
 #define VIDIOC_G_OUTPUT32      _IOR ('V', 46, s32)
 #define VIDIOC_S_OUTPUT32      _IOWR('V', 47, s32)
 
-static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
        union {
 #ifdef CONFIG_VIDEO_V4L1_COMPAT
@@ -726,7 +726,7 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
        } karg;
        void __user *up = compat_ptr(arg);
        int compatible_arg = 1;
-       int err = 0;
+       long err = 0;
 
        /* First, convert the command. */
        switch (cmd) {
@@ -937,9 +937,9 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
        return err;
 }
 
-long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
+long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
 {
-       int ret = -ENOIOCTLCMD;
+       long ret = -ENOIOCTLCMD;
 
        if (!file->f_op->ioctl && !file->f_op->unlocked_ioctl)
                return ret;
@@ -1046,7 +1046,8 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
        case VIDIOC_TRY_ENCODER_CMD:
        case VIDIOC_DBG_S_REGISTER:
        case VIDIOC_DBG_G_REGISTER:
-       case VIDIOC_G_CHIP_IDENT:
+       case VIDIOC_DBG_G_CHIP_IDENT:
+       case VIDIOC_G_CHIP_IDENT_OLD:
        case VIDIOC_S_HW_FREQ_SEEK:
                ret = do_video_ioctl(file, cmd, arg);
                break;
@@ -1065,18 +1066,14 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
                break;
 #endif
        default:
-               v4l_print_ioctl("compat_ioctl32", cmd);
-               printk(KERN_CONT "\n");
+               printk(KERN_WARNING "compat_ioctl32: "
+                       "unknown ioctl '%c', dir=%d, #%d (0x%08x)\n",
+                       _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), cmd);
                break;
        }
        return ret;
 }
-#else
-long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
-{
-       return -ENOIOCTLCMD;
-}
+EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32);
 #endif
-EXPORT_SYMBOL_GPL(v4l_compat_ioctl32);
 
 MODULE_LICENSE("GPL");
index 7ad6711ee32776452f2493f022b9b4dc059de8a9..13f87c22e78dce1721bb10c464409786df685c2c 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <media/v4l2-common.h>
 #include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
 
 #define VIDEO_NUM_DEVICES      256
 #define VIDEO_NAME              "video4linux"
@@ -182,7 +183,7 @@ static int v4l2_ioctl(struct inode *inode, struct file *filp,
                return -ENOTTY;
        /* Allow ioctl to continue even if the device was unregistered.
           Things like dequeueing buffers might still be useful. */
-       return vdev->fops->ioctl(inode, filp, cmd, arg);
+       return vdev->fops->ioctl(filp, cmd, arg);
 }
 
 static long v4l2_unlocked_ioctl(struct file *filp,
@@ -197,20 +198,6 @@ static long v4l2_unlocked_ioctl(struct file *filp,
        return vdev->fops->unlocked_ioctl(filp, cmd, arg);
 }
 
-#ifdef CONFIG_COMPAT
-static long v4l2_compat_ioctl(struct file *filp,
-               unsigned int cmd, unsigned long arg)
-{
-       struct video_device *vdev = video_devdata(filp);
-
-       if (!vdev->fops->compat_ioctl)
-               return -ENOIOCTLCMD;
-       /* Allow ioctl to continue even if the device was unregistered.
-          Things like dequeueing buffers might still be useful. */
-       return vdev->fops->compat_ioctl(filp, cmd, arg);
-}
-#endif
-
 static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm)
 {
        struct video_device *vdev = video_devdata(filp);
@@ -239,7 +226,7 @@ static int v4l2_open(struct inode *inode, struct file *filp)
        /* and increase the device refcount */
        video_get(vdev);
        mutex_unlock(&videodev_lock);
-       ret = vdev->fops->open(inode, filp);
+       ret = vdev->fops->open(filp);
        /* decrease the refcount in case of an error */
        if (ret)
                video_put(vdev);
@@ -250,7 +237,7 @@ static int v4l2_open(struct inode *inode, struct file *filp)
 static int v4l2_release(struct inode *inode, struct file *filp)
 {
        struct video_device *vdev = video_devdata(filp);
-       int ret = vdev->fops->release(inode, filp);
+       int ret = vdev->fops->release(filp);
 
        /* decrease the refcount unconditionally since the release()
           return value is ignored. */
@@ -266,7 +253,7 @@ static const struct file_operations v4l2_unlocked_fops = {
        .mmap = v4l2_mmap,
        .unlocked_ioctl = v4l2_unlocked_ioctl,
 #ifdef CONFIG_COMPAT
-       .compat_ioctl = v4l2_compat_ioctl,
+       .compat_ioctl = v4l2_compat_ioctl32,
 #endif
        .release = v4l2_release,
        .poll = v4l2_poll,
@@ -281,7 +268,7 @@ static const struct file_operations v4l2_fops = {
        .mmap = v4l2_mmap,
        .ioctl = v4l2_ioctl,
 #ifdef CONFIG_COMPAT
-       .compat_ioctl = v4l2_compat_ioctl,
+       .compat_ioctl = v4l2_compat_ioctl32,
 #endif
        .release = v4l2_release,
        .poll = v4l2_poll,
index b063381f4b3b99af4e75ae4e96c7ebd26b38d9d7..52d687b165e0c6589cc3bab0e29f953b6625b295 100644 (file)
@@ -266,7 +266,7 @@ static const char *v4l2_ioctls[] = {
        [_IOC_NR(VIDIOC_DBG_S_REGISTER)]   = "VIDIOC_DBG_S_REGISTER",
        [_IOC_NR(VIDIOC_DBG_G_REGISTER)]   = "VIDIOC_DBG_G_REGISTER",
 
-       [_IOC_NR(VIDIOC_G_CHIP_IDENT)]     = "VIDIOC_G_CHIP_IDENT",
+       [_IOC_NR(VIDIOC_DBG_G_CHIP_IDENT)] = "VIDIOC_DBG_G_CHIP_IDENT",
        [_IOC_NR(VIDIOC_S_HW_FREQ_SEEK)]   = "VIDIOC_S_HW_FREQ_SEEK",
 #endif
 };
@@ -392,14 +392,14 @@ video_fix_command(unsigned int cmd)
 /*
  * Obsolete usercopy function - Should be removed soon
  */
-int
+long
 video_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
                v4l2_kioctl func)
 {
        char    sbuf[128];
        void    *mbuf = NULL;
        void    *parg = NULL;
-       int     err  = -EINVAL;
+       long    err  = -EINVAL;
        int     is_ext_ctrl;
        size_t  ctrls_size = 0;
        void __user *user_ptr = NULL;
@@ -623,13 +623,13 @@ static int check_fmt(const struct v4l2_ioctl_ops *ops, enum v4l2_buf_type type)
        return -EINVAL;
 }
 
-static int __video_do_ioctl(struct file *file,
+static long __video_do_ioctl(struct file *file,
                unsigned int cmd, void *arg)
 {
        struct video_device *vfd = video_devdata(file);
        const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
        void *fh = file->private_data;
-       int ret = -EINVAL;
+       long ret = -EINVAL;
 
        if ((vfd->debug & V4L2_DEBUG_IOCTL) &&
                                !(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) {
@@ -1720,7 +1720,7 @@ static int __video_do_ioctl(struct file *file,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
        case VIDIOC_DBG_G_REGISTER:
        {
-               struct v4l2_register *p = arg;
+               struct v4l2_dbg_register *p = arg;
 
                if (!capable(CAP_SYS_ADMIN))
                        ret = -EPERM;
@@ -1730,7 +1730,7 @@ static int __video_do_ioctl(struct file *file,
        }
        case VIDIOC_DBG_S_REGISTER:
        {
-               struct v4l2_register *p = arg;
+               struct v4l2_dbg_register *p = arg;
 
                if (!capable(CAP_SYS_ADMIN))
                        ret = -EPERM;
@@ -1739,9 +1739,9 @@ static int __video_do_ioctl(struct file *file,
                break;
        }
 #endif
-       case VIDIOC_G_CHIP_IDENT:
+       case VIDIOC_DBG_G_CHIP_IDENT:
        {
-               struct v4l2_chip_ident *p = arg;
+               struct v4l2_dbg_chip_ident *p = arg;
 
                if (!ops->vidioc_g_chip_ident)
                        break;
@@ -1750,6 +1750,11 @@ static int __video_do_ioctl(struct file *file,
                        dbgarg(cmd, "chip_ident=%u, revision=0x%x\n", p->ident, p->revision);
                break;
        }
+       case VIDIOC_G_CHIP_IDENT_OLD:
+               printk(KERN_ERR "VIDIOC_G_CHIP_IDENT has been deprecated and will disappear in 2.6.30.\n");
+               printk(KERN_ERR "It is a debugging ioctl and must not be used in applications!\n");
+               return -EINVAL;
+
        case VIDIOC_S_HW_FREQ_SEEK:
        {
                struct v4l2_hw_freq_seek *p = arg;
@@ -1845,20 +1850,20 @@ static int __video_do_ioctl(struct file *file,
        if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {
                if (ret < 0) {
                        v4l_print_ioctl(vfd->name, cmd);
-                       printk(KERN_CONT " error %d\n", ret);
+                       printk(KERN_CONT " error %ld\n", ret);
                }
        }
 
        return ret;
 }
 
-long __video_ioctl2(struct file *file,
+long video_ioctl2(struct file *file,
               unsigned int cmd, unsigned long arg)
 {
        char    sbuf[128];
        void    *mbuf = NULL;
        void    *parg = NULL;
-       int     err  = -EINVAL;
+       long    err  = -EINVAL;
        int     is_ext_ctrl;
        size_t  ctrls_size = 0;
        void __user *user_ptr = NULL;
@@ -1944,11 +1949,4 @@ out:
        kfree(mbuf);
        return err;
 }
-EXPORT_SYMBOL(__video_ioctl2);
-
-int video_ioctl2(struct inode *inode, struct file *file,
-              unsigned int cmd, unsigned long arg)
-{
-       return __video_ioctl2(file, cmd, arg);
-}
 EXPORT_SYMBOL(video_ioctl2);
index e3612f29d0df762f4f4805cef4ec3f7cd9f23ad8..fbe9cc0d433a29cf16a33d89a55a001596ad0c5e 100644 (file)
@@ -37,7 +37,7 @@ int v4l2_subdev_command(struct v4l2_subdev *sd, unsigned cmd, void *arg)
                return v4l2_subdev_call(sd, core, queryctrl, arg);
        case VIDIOC_LOG_STATUS:
                return v4l2_subdev_call(sd, core, log_status);
-       case VIDIOC_G_CHIP_IDENT:
+       case VIDIOC_DBG_G_CHIP_IDENT:
                return v4l2_subdev_call(sd, core, g_chip_ident, arg);
        case VIDIOC_INT_S_STANDBY:
                return v4l2_subdev_call(sd, core, s_standby, arg ? (*(u32 *)arg) : 0);
index a72a361daade1b33b92a5f6911d998e6bfe13685..88bf845a3d567cbe754dbd89dfe2fc3952ba0ecd 100644 (file)
@@ -4019,7 +4019,7 @@ out:
 
 /* File operations */
 
-static int vino_open(struct inode *inode, struct file *file)
+static int vino_open(struct file *file)
 {
        struct vino_channel_settings *vcs = video_drvdata(file);
        int ret = 0;
@@ -4050,7 +4050,7 @@ static int vino_open(struct inode *inode, struct file *file)
        return ret;
 }
 
-static int vino_close(struct inode *inode, struct file *file)
+static int vino_close(struct file *file)
 {
        struct vino_channel_settings *vcs = video_drvdata(file);
        dprintk("close():\n");
@@ -4237,7 +4237,7 @@ error:
        return ret;
 }
 
-static int vino_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+static long vino_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 {
        struct vino_channel_settings *vcs = video_drvdata(file);
 
@@ -4343,11 +4343,11 @@ static int vino_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        return 0;
 }
 
-static int vino_ioctl(struct inode *inode, struct file *file,
+static long vino_ioctl(struct file *file,
                      unsigned int cmd, unsigned long arg)
 {
        struct vino_channel_settings *vcs = video_drvdata(file);
-       int ret;
+       long ret;
 
        if (mutex_lock_interruptible(&vcs->mutex))
                return -EINTR;
@@ -4364,14 +4364,13 @@ static int vino_ioctl(struct inode *inode, struct file *file,
 /* __initdata */
 static int vino_init_stage;
 
-static const struct file_operations vino_fops = {
+static const struct v4l2_file_operations vino_fops = {
        .owner          = THIS_MODULE,
        .open           = vino_open,
        .release        = vino_close,
        .ioctl          = vino_ioctl,
        .mmap           = vino_mmap,
        .poll           = vino_poll,
-       .llseek         = no_llseek,
 };
 
 static struct video_device v4l_device_template = {
index e15e48f04be7511e788b5022f413952d10d93bc7..81d5aa5cf3317c336ecbaf7c666e75d793514dab 100644 (file)
@@ -1024,9 +1024,9 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
        File operations for the device
    ------------------------------------------------------------------*/
 
-static int vivi_open(struct inode *inode, struct file *file)
+static int vivi_open(struct file *file)
 {
-       int minor = iminor(inode);
+       int minor = video_devdata(file)->minor;
        struct vivi_dev *dev;
        struct vivi_fh *fh = NULL;
        int i;
@@ -1127,13 +1127,13 @@ vivi_poll(struct file *file, struct poll_table_struct *wait)
        return videobuf_poll_stream(file, q, wait);
 }
 
-static int vivi_close(struct inode *inode, struct file *file)
+static int vivi_close(struct file *file)
 {
        struct vivi_fh         *fh = file->private_data;
        struct vivi_dev *dev       = fh->dev;
        struct vivi_dmaqueue *vidq = &dev->vidq;
 
-       int minor = iminor(inode);
+       int minor = video_devdata(file)->minor;
 
        vivi_stop_thread(vidq);
        videobuf_stop(&fh->vb_vidq);
@@ -1195,16 +1195,14 @@ static int vivi_mmap(struct file *file, struct vm_area_struct *vma)
        return ret;
 }
 
-static const struct file_operations vivi_fops = {
+static const struct v4l2_file_operations vivi_fops = {
        .owner          = THIS_MODULE,
        .open           = vivi_open,
        .release        = vivi_close,
        .read           = vivi_read,
        .poll           = vivi_poll,
        .ioctl          = video_ioctl2, /* V4L2 ioctl handler */
-       .compat_ioctl   = v4l_compat_ioctl32,
        .mmap           = vivi_mmap,
-       .llseek         = no_llseek,
 };
 
 static const struct v4l2_ioctl_ops vivi_ioctl_ops = {
index f72b859486ada73f1725641f9a7cedcd4b272767..5d73f66d9f551efb65f541a2fab1c27970a7f667 100644 (file)
@@ -113,7 +113,7 @@ static int vp27smpx_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
        return 0;
 }
 
-static int vp27smpx_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip)
+static int vp27smpx_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
 
index 56c570c267ea1f6f110678867809d606642c3e7f..038ff32b01b85943fdc572fb6266becb9c4f4ada 100644 (file)
@@ -180,19 +180,19 @@ static int w9966_i2c_wbyte(struct w9966_dev* cam, int data);
 static int w9966_i2c_rbyte(struct w9966_dev* cam);
 #endif
 
-static int w9966_v4l_ioctl(struct inode *inode, struct file *file,
+static long w9966_v4l_ioctl(struct file *file,
                           unsigned int cmd, unsigned long arg);
 static ssize_t w9966_v4l_read(struct file *file, char __user *buf,
                              size_t count, loff_t *ppos);
 
-static int w9966_exclusive_open(struct inode *inode, struct file *file)
+static int w9966_exclusive_open(struct file *file)
 {
        struct w9966_dev *cam = video_drvdata(file);
 
        return test_and_set_bit(0, &cam->in_use) ? -EBUSY : 0;
 }
 
-static int w9966_exclusive_release(struct inode *inode, struct file *file)
+static int w9966_exclusive_release(struct file *file)
 {
        struct w9966_dev *cam = video_drvdata(file);
 
@@ -200,16 +200,12 @@ static int w9966_exclusive_release(struct inode *inode, struct file *file)
        return 0;
 }
 
-static const struct file_operations w9966_fops = {
+static const struct v4l2_file_operations w9966_fops = {
        .owner          = THIS_MODULE,
        .open           = w9966_exclusive_open,
        .release        = w9966_exclusive_release,
        .ioctl          = w9966_v4l_ioctl,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = v4l_compat_ioctl32,
-#endif
        .read           = w9966_v4l_read,
-       .llseek         = no_llseek,
 };
 static struct video_device w9966_template = {
        .name           = W9966_DRIVERNAME,
@@ -727,7 +723,7 @@ static int w9966_wReg_i2c(struct w9966_dev* cam, int reg, int data)
  *     Video4linux interfacing
  */
 
-static int w9966_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+static long w9966_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 {
        struct w9966_dev *cam = video_drvdata(file);
 
@@ -877,7 +873,7 @@ static int w9966_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        return 0;
 }
 
-static int w9966_v4l_ioctl(struct inode *inode, struct file *file,
+static long w9966_v4l_ioctl(struct file *file,
                           unsigned int cmd, unsigned long arg)
 {
        return video_usercopy(file, cmd, arg, w9966_v4l_do_ioctl);
index 4dfb43bd1846b977edfe277d6f8e2d06898bb837..a3997b7d4366049d9ce20e446e67fb47f0bececf 100644 (file)
@@ -399,13 +399,13 @@ MODULE_PARM_DESC(specific_debug,
  ****************************************************************************/
 
 /* Video4linux interface */
-static const struct file_operations w9968cf_fops;
-static int w9968cf_open(struct inode*, struct file*);
-static int w9968cf_release(struct inode*, struct file*);
-static int w9968cf_mmap(struct file*, struct vm_area_struct*);
-static int w9968cf_ioctl(struct inode*, struct file*, unsigned, unsigned long);
-static ssize_t w9968cf_read(struct file*, char __user *, size_t, loff_t*);
-static int w9968cf_v4l_ioctl(struct inode*, struct file*, unsigned int,
+static const struct v4l2_file_operations w9968cf_fops;
+static int w9968cf_open(struct file *);
+static int w9968cf_release(struct file *);
+static int w9968cf_mmap(struct file *, struct vm_area_struct *);
+static long w9968cf_ioctl(struct file *, unsigned, unsigned long);
+static ssize_t w9968cf_read(struct file *, char __user *, size_t, loff_t *);
+static long w9968cf_v4l_ioctl(struct file *, unsigned int,
                             void __user *);
 
 /* USB-specific */
@@ -2662,7 +2662,7 @@ static void w9968cf_release_resources(struct w9968cf_device* cam)
  * Video4Linux interface                                                    *
  ****************************************************************************/
 
-static int w9968cf_open(struct inode* inode, struct file* filp)
+static int w9968cf_open(struct file *filp)
 {
        struct w9968cf_device* cam;
        int err;
@@ -2748,7 +2748,7 @@ deallocate_memory:
 }
 
 
-static int w9968cf_release(struct inode* inode, struct file* filp)
+static int w9968cf_release(struct file *filp)
 {
        struct w9968cf_device* cam;
 
@@ -2885,12 +2885,12 @@ static int w9968cf_mmap(struct file* filp, struct vm_area_struct *vma)
 }
 
 
-static int
-w9968cf_ioctl(struct inode* inode, struct file* filp,
+static long
+w9968cf_ioctl(struct file *filp,
              unsigned int cmd, unsigned long arg)
 {
        struct w9968cf_device* cam;
-       int err;
+       long err;
 
        cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp));
 
@@ -2909,15 +2909,15 @@ w9968cf_ioctl(struct inode* inode, struct file* filp,
                return -EIO;
        }
 
-       err = w9968cf_v4l_ioctl(inode, filp, cmd, (void __user *)arg);
+       err = w9968cf_v4l_ioctl(filp, cmd, (void __user *)arg);
 
        mutex_unlock(&cam->fileop_mutex);
        return err;
 }
 
 
-static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp,
-                            unsigned int cmd, void __user * arg)
+static long w9968cf_v4l_ioctl(struct file *filp,
+                            unsigned int cmd, void __user *arg)
 {
        struct w9968cf_device* cam;
        const char* v4l1_ioctls[] = {
@@ -3456,17 +3456,13 @@ ioctl_fail:
 }
 
 
-static const struct file_operations w9968cf_fops = {
+static const struct v4l2_file_operations w9968cf_fops = {
        .owner =   THIS_MODULE,
        .open =    w9968cf_open,
        .release = w9968cf_release,
        .read =    w9968cf_read,
        .ioctl =   w9968cf_ioctl,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl = v4l_compat_ioctl32,
-#endif
        .mmap =    w9968cf_mmap,
-       .llseek =  no_llseek,
 };
 
 
index 12a31e7a5f6de31fbebce5fe93aa8ebfe0797f16..f2864d5cd1800c5662e6985bf5be2fdeafcb8c71 100644 (file)
@@ -233,7 +233,7 @@ static int wm8739_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
        return -EINVAL;
 }
 
-static int wm8739_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip)
+static int wm8739_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
 
index d0220b0ec0bcf331320ad89d67b398f617609773..53fcd42843e0eae0ef6c998002db002f8d37e355 100644 (file)
@@ -130,7 +130,7 @@ static int wm8775_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
        return 0;
 }
 
-static int wm8775_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip)
+static int wm8775_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
 
index 9d00e6056491b1a9baeb6fc305e48ee87bdd9f31..96971044fc78cb767815179b556fe30c4c20a4e8 100644 (file)
@@ -649,7 +649,7 @@ static void zc0301_release_resources(struct kref *kref)
 }
 
 
-static int zc0301_open(struct inode* inode, struct file* filp)
+static int zc0301_open(struct file *filp)
 {
        struct zc0301_device* cam;
        int err = 0;
@@ -733,7 +733,7 @@ out:
 }
 
 
-static int zc0301_release(struct inode* inode, struct file* filp)
+static int zc0301_release(struct file *filp)
 {
        struct zc0301_device* cam;
 
@@ -1793,8 +1793,8 @@ zc0301_vidioc_s_parm(struct zc0301_device* cam, void __user * arg)
 }
 
 
-static int zc0301_ioctl_v4l2(struct inode* inode, struct file* filp,
-                            unsigned int cmd, void __user * arg)
+static long zc0301_ioctl_v4l2(struct file *filp,
+                            unsigned int cmd, void __user *arg)
 {
        struct zc0301_device *cam = video_drvdata(filp);
 
@@ -1888,7 +1888,7 @@ static int zc0301_ioctl_v4l2(struct inode* inode, struct file* filp,
 }
 
 
-static int zc0301_ioctl(struct inode* inode, struct file* filp,
+static long zc0301_ioctl(struct file *filp,
                        unsigned int cmd, unsigned long arg)
 {
        struct zc0301_device *cam = video_drvdata(filp);
@@ -1912,7 +1912,7 @@ static int zc0301_ioctl(struct inode* inode, struct file* filp,
 
        V4LDBG(3, "zc0301", cmd);
 
-       err = zc0301_ioctl_v4l2(inode, filp, cmd, (void __user *)arg);
+       err = zc0301_ioctl_v4l2(filp, cmd, (void __user *)arg);
 
        mutex_unlock(&cam->fileop_mutex);
 
@@ -1920,18 +1920,14 @@ static int zc0301_ioctl(struct inode* inode, struct file* filp,
 }
 
 
-static const struct file_operations zc0301_fops = {
+static const struct v4l2_file_operations zc0301_fops = {
        .owner =   THIS_MODULE,
        .open =    zc0301_open,
        .release = zc0301_release,
        .ioctl =   zc0301_ioctl,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl = v4l_compat_ioctl32,
-#endif
        .read =    zc0301_read,
        .poll =    zc0301_poll,
        .mmap =    zc0301_mmap,
-       .llseek =  no_llseek,
 };
 
 /*****************************************************************************/
index 00b97d97aeaa612275e7cab190a7823fbcf1a1da..b58b9dda715ccedb80cb4c67a42d8c0b9816a903 100644 (file)
@@ -1197,10 +1197,9 @@ zoran_close_end_session (struct file *file)
  */
 
 static int
-zoran_open (struct inode *inode,
-           struct file  *file)
+zoran_open(struct file  *file)
 {
-       unsigned int minor = iminor(inode);
+       unsigned int minor = video_devdata(file)->minor;
        struct zoran *zr = NULL;
        struct zoran_fh *fh;
        int i, res, first_open = 0, have_module_locks = 0;
@@ -1340,8 +1339,7 @@ open_unlock_and_return:
 }
 
 static int
-zoran_close (struct inode *inode,
-            struct file  *file)
+zoran_close(struct file  *file)
 {
        struct zoran_fh *fh = file->private_data;
        struct zoran *zr = fh->zr;
@@ -1940,7 +1938,7 @@ zoran_set_input (struct zoran *zr,
  *   ioctl routine
  */
 
-static int zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 {
        struct zoran_fh *fh = file->private_data;
        struct zoran *zr = fh->zr;
@@ -4191,11 +4189,10 @@ static int zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 }
 
 
-static int
-zoran_ioctl (struct inode *inode,
-            struct file  *file,
-            unsigned int  cmd,
-            unsigned long arg)
+static long
+zoran_ioctl(struct file  *file,
+           unsigned int  cmd,
+           unsigned long arg)
 {
        return video_usercopy(file, cmd, arg, zoran_do_ioctl);
 }
@@ -4620,15 +4617,11 @@ zoran_mmap (struct file           *file,
        return 0;
 }
 
-static const struct file_operations zoran_fops = {
+static const struct v4l2_file_operations zoran_fops = {
        .owner = THIS_MODULE,
        .open = zoran_open,
        .release = zoran_close,
        .ioctl = zoran_ioctl,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = v4l_compat_ioctl32,
-#endif
-       .llseek = no_llseek,
        .read = zoran_read,
        .write = zoran_write,
        .mmap = zoran_mmap,
index a1d81ed44c7c965451ae5acb00727dc079305c5f..93023560f3242550f0ed2e026954cfcac9c0794c 100644 (file)
@@ -634,7 +634,7 @@ static int zr364xx_vidioc_streamoff(struct file *file, void *priv,
 
 
 /* open the camera */
-static int zr364xx_open(struct inode *inode, struct file *file)
+static int zr364xx_open(struct file *file)
 {
        struct video_device *vdev = video_devdata(file);
        struct zr364xx_camera *cam = video_get_drvdata(vdev);
@@ -688,7 +688,7 @@ out:
 
 
 /* release the camera */
-static int zr364xx_release(struct inode *inode, struct file *file)
+static int zr364xx_release(struct file *file)
 {
        struct video_device *vdev = video_devdata(file);
        struct zr364xx_camera *cam;
@@ -761,14 +761,13 @@ static int zr364xx_mmap(struct file *file, struct vm_area_struct *vma)
 }
 
 
-static const struct file_operations zr364xx_fops = {
+static const struct v4l2_file_operations zr364xx_fops = {
        .owner = THIS_MODULE,
        .open = zr364xx_open,
        .release = zr364xx_release,
        .read = zr364xx_read,
        .mmap = zr364xx_mmap,
        .ioctl = video_ioctl2,
-       .llseek = no_llseek,
 };
 
 static const struct v4l2_ioctl_ops zr364xx_ioctl_ops = {
@@ -894,7 +893,6 @@ static void zr364xx_disconnect(struct usb_interface *intf)
 {
        struct zr364xx_camera *cam = usb_get_intfdata(intf);
        usb_set_intfdata(intf, NULL);
-       dev_set_drvdata(&intf->dev, NULL);
        dev_info(&intf->dev, DRIVER_DESC " webcam unplugged\n");
        if (cam->vdev)
                video_unregister_device(cam->vdev);
index 56faef1a1d55a3412d852ab9b56a805d0651627a..06c655c5558718ec748ab496119fe320037d387d 100644 (file)
@@ -19,7 +19,7 @@
  *             Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI>
  *             Deepak Saxena <deepak@plexity.net>
  *             Boji T Kannanthanam <boji.t.kannanthanam@intel.com>
- *             Alan Cox <alan@redhat.com>:
+ *             Alan Cox <alan@lxorguk.ukuu.org.uk>:
  *                     Ported to Linux 2.5.
  *             Markus Lidel <Markus.Lidel@shadowconnect.com>:
  *                     Minor fixes for 2.6.
index f3384c32b9a1e3910e39f9331dd14a4ed382eb7f..efba7021948ab8f92c34c80e29c255a72e1fc70e 100644 (file)
@@ -19,7 +19,7 @@
  *             Changed ioctl_swdl(), implemented ioctl_swul() and ioctl_swdel()
  *     Deepak Saxena (11/18/1999):
  *             Added event managmenet support
- *     Alan Cox <alan@redhat.com>:
+ *     Alan Cox <alan@lxorguk.ukuu.org.uk>:
  *             2.4 rewrite ported to 2.5
  *     Markus Lidel <Markus.Lidel@shadowconnect.com>:
  *             Added pass-thru support for Adaptec's raidutils
index 6e53a30bfd38a7809f8bbcb2ce9b0f3966f35413..35c67d1f255e8c168f2ecc0dd11422be33fe2b73 100644 (file)
@@ -19,7 +19,7 @@
  *             Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI>
  *             Deepak Saxena <deepak@plexity.net>
  *             Boji T Kannanthanam <boji.t.kannanthanam@intel.com>
- *             Alan Cox <alan@redhat.com>:
+ *             Alan Cox <alan@lxorguk.ukuu.org.uk>:
  *                     Ported to Linux 2.5.
  *             Markus Lidel <Markus.Lidel@shadowconnect.com>:
  *                     Minor fixes for 2.6.
index 610ef1204e68f83ccfb2cd35f98ab5d3472c2229..25d6f234198367cd1f70895fc7ab7f030f7262e0 100644 (file)
@@ -19,7 +19,7 @@
  *             Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI>
  *             Deepak Saxena <deepak@plexity.net>
  *             Boji T Kannanthanam <boji.t.kannanthanam@intel.com>
- *             Alan Cox <alan@redhat.com>:
+ *             Alan Cox <alan@lxorguk.ukuu.org.uk>:
  *                     Ported to Linux 2.5.
  *             Markus Lidel <Markus.Lidel@shadowconnect.com>:
  *                     Minor fixes for 2.6.
index 22a7e8ba211d242dd0b25c477f2ea5b7c4bcd07c..de966a6fb7e634d50abce07bfa82a9c47f6f8ac9 100644 (file)
@@ -146,8 +146,6 @@ static struct inode *ibmasmfs_make_inode(struct super_block *sb, int mode)
 
        if (ret) {
                ret->i_mode = mode;
-               ret->i_uid = ret->i_gid = 0;
-               ret->i_blocks = 0;
                ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
        }
        return ret;
index 3d067c35185db9704157d8bc4bddbecc20bf22c7..45b1f430685fca915aa12c7f28913fa4ed6a0733 100644 (file)
@@ -145,7 +145,7 @@ struct mmc_blk_request {
 static u32 mmc_sd_num_wr_blocks(struct mmc_card *card)
 {
        int err;
-       u32 blocks;
+       __be32 blocks;
 
        struct mmc_request mrq;
        struct mmc_command cmd;
@@ -204,9 +204,24 @@ static u32 mmc_sd_num_wr_blocks(struct mmc_card *card)
        if (cmd.error || data.error)
                return (u32)-1;
 
-       blocks = ntohl(blocks);
+       return ntohl(blocks);
+}
+
+static u32 get_card_status(struct mmc_card *card, struct request *req)
+{
+       struct mmc_command cmd;
+       int err;
 
-       return blocks;
+       memset(&cmd, 0, sizeof(struct mmc_command));
+       cmd.opcode = MMC_SEND_STATUS;
+       if (!mmc_host_is_spi(card->host))
+               cmd.arg = card->rca << 16;
+       cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC;
+       err = mmc_wait_for_cmd(card->host, &cmd, 0);
+       if (err)
+               printk(KERN_ERR "%s: error %d sending status comand",
+                      req->rq_disk->disk_name, err);
+       return cmd.resp[0];
 }
 
 static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
@@ -214,13 +229,13 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
        struct mmc_blk_data *md = mq->data;
        struct mmc_card *card = md->queue.card;
        struct mmc_blk_request brq;
-       int ret = 1;
+       int ret = 1, disable_multi = 0;
 
        mmc_claim_host(card->host);
 
        do {
                struct mmc_command cmd;
-               u32 readcmd, writecmd;
+               u32 readcmd, writecmd, status = 0;
 
                memset(&brq, 0, sizeof(struct mmc_blk_request));
                brq.mrq.cmd = &brq.cmd;
@@ -236,6 +251,14 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
                brq.stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
                brq.data.blocks = req->nr_sectors;
 
+               /*
+                * After a read error, we redo the request one sector at a time
+                * in order to accurately determine which sectors can be read
+                * successfully.
+                */
+               if (disable_multi && brq.data.blocks > 1)
+                       brq.data.blocks = 1;
+
                if (brq.data.blocks > 1) {
                        /* SPI multiblock writes terminate using a special
                         * token, not a STOP_TRANSMISSION request.
@@ -264,6 +287,25 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
                brq.data.sg = mq->sg;
                brq.data.sg_len = mmc_queue_map_sg(mq);
 
+               /*
+                * Adjust the sg list so it is the same size as the
+                * request.
+                */
+               if (brq.data.blocks != req->nr_sectors) {
+                       int i, data_size = brq.data.blocks << 9;
+                       struct scatterlist *sg;
+
+                       for_each_sg(brq.data.sg, sg, brq.data.sg_len, i) {
+                               data_size -= sg->length;
+                               if (data_size <= 0) {
+                                       sg->length += data_size;
+                                       i++;
+                                       break;
+                               }
+                       }
+                       brq.data.sg_len = i;
+               }
+
                mmc_queue_bounce_pre(mq);
 
                mmc_wait_for_req(card->host, &brq.mrq);
@@ -275,19 +317,40 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
                 * until later as we need to wait for the card to leave
                 * programming mode even when things go wrong.
                 */
+               if (brq.cmd.error || brq.data.error || brq.stop.error) {
+                       if (brq.data.blocks > 1 && rq_data_dir(req) == READ) {
+                               /* Redo read one sector at a time */
+                               printk(KERN_WARNING "%s: retrying using single "
+                                      "block read\n", req->rq_disk->disk_name);
+                               disable_multi = 1;
+                               continue;
+                       }
+                       status = get_card_status(card, req);
+               }
+
                if (brq.cmd.error) {
-                       printk(KERN_ERR "%s: error %d sending read/write command\n",
-                              req->rq_disk->disk_name, brq.cmd.error);
+                       printk(KERN_ERR "%s: error %d sending read/write "
+                              "command, response %#x, card status %#x\n",
+                              req->rq_disk->disk_name, brq.cmd.error,
+                              brq.cmd.resp[0], status);
                }
 
                if (brq.data.error) {
-                       printk(KERN_ERR "%s: error %d transferring data\n",
-                              req->rq_disk->disk_name, brq.data.error);
+                       if (brq.data.error == -ETIMEDOUT && brq.mrq.stop)
+                               /* 'Stop' response contains card status */
+                               status = brq.mrq.stop->resp[0];
+                       printk(KERN_ERR "%s: error %d transferring data,"
+                              " sector %u, nr %u, card status %#x\n",
+                              req->rq_disk->disk_name, brq.data.error,
+                              (unsigned)req->sector,
+                              (unsigned)req->nr_sectors, status);
                }
 
                if (brq.stop.error) {
-                       printk(KERN_ERR "%s: error %d sending stop command\n",
-                              req->rq_disk->disk_name, brq.stop.error);
+                       printk(KERN_ERR "%s: error %d sending stop command, "
+                              "response %#x, card status %#x\n",
+                              req->rq_disk->disk_name, brq.stop.error,
+                              brq.stop.resp[0], status);
                }
 
                if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) {
@@ -320,8 +383,20 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
 #endif
                }
 
-               if (brq.cmd.error || brq.data.error || brq.stop.error)
+               if (brq.cmd.error || brq.stop.error || brq.data.error) {
+                       if (rq_data_dir(req) == READ) {
+                               /*
+                                * After an error, we redo I/O one sector at a
+                                * time, so we only reach here after trying to
+                                * read a single sector.
+                                */
+                               spin_lock_irq(&md->lock);
+                               ret = __blk_end_request(req, -EIO, brq.data.blksz);
+                               spin_unlock_irq(&md->lock);
+                               continue;
+                       }
                        goto cmd_err;
+               }
 
                /*
                 * A block was successfully transferred.
@@ -343,25 +418,20 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
         * If the card is not SD, we can still ok written sectors
         * as reported by the controller (which might be less than
         * the real number of written sectors, but never more).
-        *
-        * For reads we just fail the entire chunk as that should
-        * be safe in all cases.
         */
-       if (rq_data_dir(req) != READ) {
-               if (mmc_card_sd(card)) {
-                       u32 blocks;
+       if (mmc_card_sd(card)) {
+               u32 blocks;
 
-                       blocks = mmc_sd_num_wr_blocks(card);
-                       if (blocks != (u32)-1) {
-                               spin_lock_irq(&md->lock);
-                               ret = __blk_end_request(req, 0, blocks << 9);
-                               spin_unlock_irq(&md->lock);
-                       }
-               } else {
+               blocks = mmc_sd_num_wr_blocks(card);
+               if (blocks != (u32)-1) {
                        spin_lock_irq(&md->lock);
-                       ret = __blk_end_request(req, 0, brq.data.bytes_xfered);
+                       ret = __blk_end_request(req, 0, blocks << 9);
                        spin_unlock_irq(&md->lock);
                }
+       } else {
+               spin_lock_irq(&md->lock);
+               ret = __blk_end_request(req, 0, brq.data.bytes_xfered);
+               spin_unlock_irq(&md->lock);
        }
 
        mmc_release_host(card->host);
index f7284b905eb38c083882eaec993885aff5598b2c..df6ce4a06cf37f42c11935ce7f4e2f5d92409758 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/err.h>
 #include <linux/leds.h>
 #include <linux/scatterlist.h>
+#include <linux/log2.h>
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
@@ -448,6 +449,80 @@ void mmc_set_bus_width(struct mmc_host *host, unsigned int width)
        mmc_set_ios(host);
 }
 
+/**
+ * mmc_vdd_to_ocrbitnum - Convert a voltage to the OCR bit number
+ * @vdd:       voltage (mV)
+ * @low_bits:  prefer low bits in boundary cases
+ *
+ * This function returns the OCR bit number according to the provided @vdd
+ * value. If conversion is not possible a negative errno value returned.
+ *
+ * Depending on the @low_bits flag the function prefers low or high OCR bits
+ * on boundary voltages. For example,
+ * with @low_bits = true, 3300 mV translates to ilog2(MMC_VDD_32_33);
+ * with @low_bits = false, 3300 mV translates to ilog2(MMC_VDD_33_34);
+ *
+ * Any value in the [1951:1999] range translates to the ilog2(MMC_VDD_20_21).
+ */
+static int mmc_vdd_to_ocrbitnum(int vdd, bool low_bits)
+{
+       const int max_bit = ilog2(MMC_VDD_35_36);
+       int bit;
+
+       if (vdd < 1650 || vdd > 3600)
+               return -EINVAL;
+
+       if (vdd >= 1650 && vdd <= 1950)
+               return ilog2(MMC_VDD_165_195);
+
+       if (low_bits)
+               vdd -= 1;
+
+       /* Base 2000 mV, step 100 mV, bit's base 8. */
+       bit = (vdd - 2000) / 100 + 8;
+       if (bit > max_bit)
+               return max_bit;
+       return bit;
+}
+
+/**
+ * mmc_vddrange_to_ocrmask - Convert a voltage range to the OCR mask
+ * @vdd_min:   minimum voltage value (mV)
+ * @vdd_max:   maximum voltage value (mV)
+ *
+ * This function returns the OCR mask bits according to the provided @vdd_min
+ * and @vdd_max values. If conversion is not possible the function returns 0.
+ *
+ * Notes wrt boundary cases:
+ * This function sets the OCR bits for all boundary voltages, for example
+ * [3300:3400] range is translated to MMC_VDD_32_33 | MMC_VDD_33_34 |
+ * MMC_VDD_34_35 mask.
+ */
+u32 mmc_vddrange_to_ocrmask(int vdd_min, int vdd_max)
+{
+       u32 mask = 0;
+
+       if (vdd_max < vdd_min)
+               return 0;
+
+       /* Prefer high bits for the boundary vdd_max values. */
+       vdd_max = mmc_vdd_to_ocrbitnum(vdd_max, false);
+       if (vdd_max < 0)
+               return 0;
+
+       /* Prefer low bits for the boundary vdd_min values. */
+       vdd_min = mmc_vdd_to_ocrbitnum(vdd_min, true);
+       if (vdd_min < 0)
+               return 0;
+
+       /* Fill the mask, from max bit to min bit. */
+       while (vdd_max >= vdd_min)
+               mask |= 1 << vdd_max--;
+
+       return mask;
+}
+EXPORT_SYMBOL(mmc_vddrange_to_ocrmask);
+
 /*
  * Mask off any voltages we don't support and select
  * the lowest voltage
@@ -467,6 +542,8 @@ u32 mmc_select_voltage(struct mmc_host *host, u32 ocr)
                host->ios.vdd = bit;
                mmc_set_ios(host);
        } else {
+               pr_warning("%s: host doesn't support card's voltages\n",
+                               mmc_hostname(host));
                ocr = 0;
        }
 
index fdd7c760be8cff590d00310d620ab4b4fc7e02b3..c232d11a7ed4c16adf8de5502902889a1a7489ee 100644 (file)
@@ -434,13 +434,24 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
         * Activate wide bus (if supported).
         */
        if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
-               (host->caps & MMC_CAP_4_BIT_DATA)) {
+           (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) {
+               unsigned ext_csd_bit, bus_width;
+
+               if (host->caps & MMC_CAP_8_BIT_DATA) {
+                       ext_csd_bit = EXT_CSD_BUS_WIDTH_8;
+                       bus_width = MMC_BUS_WIDTH_8;
+               } else {
+                       ext_csd_bit = EXT_CSD_BUS_WIDTH_4;
+                       bus_width = MMC_BUS_WIDTH_4;
+               }
+
                err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-                       EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_4);
+                                EXT_CSD_BUS_WIDTH, ext_csd_bit);
+
                if (err)
                        goto free_card;
 
-               mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4);
+               mmc_set_bus_width(card->host, bus_width);
        }
 
        if (!oldcard)
@@ -624,4 +635,3 @@ err:
 
        return err;
 }
-
index c794cc5ce44220f94fc4d9351725bef5594b3711..f4853288bbb1ec158a9f712443fac20e19de4347 100644 (file)
@@ -19,6 +19,9 @@ obj-$(CONFIG_MMC_AT91)                += at91_mci.o
 obj-$(CONFIG_MMC_ATMELMCI)     += atmel-mci.o
 obj-$(CONFIG_MMC_TIFM_SD)      += tifm_sd.o
 obj-$(CONFIG_MMC_SPI)          += mmc_spi.o
+ifeq ($(CONFIG_OF),y)
+obj-$(CONFIG_MMC_SPI)          += of_mmc_spi.o
+endif
 obj-$(CONFIG_MMC_S3C)          += s3cmci.o
 obj-$(CONFIG_MMC_SDRICOH_CS)   += sdricoh_cs.o
 obj-$(CONFIG_MMC_TMIO)         += tmio_mmc.o
index 1f8b5b36222c26645576c3a338673839178ad267..e556d42cc45a755597e435e54e21235113611505 100644 (file)
@@ -1088,6 +1088,8 @@ static int __init at91_mci_probe(struct platform_device *pdev)
                goto fail0;
        }
 
+       setup_timer(&host->timer, at91_timeout_timer, (unsigned long)host);
+
        platform_set_drvdata(pdev, mmc);
 
        /*
@@ -1101,8 +1103,6 @@ static int __init at91_mci_probe(struct platform_device *pdev)
 
        mmc_add_host(mmc);
 
-       setup_timer(&host->timer, at91_timeout_timer, (unsigned long)host);
-
        /*
         * monitor card insertion/removal if we can
         */
index ad00e163231750177f39e4c6949e1d4cda3b916b..87e211df68ac0dcdaf75c6aab9f4cce9ebad97ab 100644 (file)
@@ -1285,7 +1285,7 @@ static int mmc_spi_probe(struct spi_device *spi)
        /* Platform data is used to hook up things like card sensing
         * and power switching gpios.
         */
-       host->pdata = spi->dev.platform_data;
+       host->pdata = mmc_spi_get_pdata(spi);
        if (host->pdata)
                mmc->ocr_avail = host->pdata->ocr_mask;
        if (!mmc->ocr_avail) {
@@ -1368,6 +1368,7 @@ fail_glue_init:
 
 fail_nobuf1:
        mmc_free_host(mmc);
+       mmc_spi_put_pdata(spi);
        dev_set_drvdata(&spi->dev, NULL);
 
 nomem:
@@ -1402,6 +1403,7 @@ static int __devexit mmc_spi_remove(struct spi_device *spi)
 
                spi->max_speed_hz = mmc->f_max;
                mmc_free_host(mmc);
+               mmc_spi_put_pdata(spi);
                dev_set_drvdata(&spi->dev, NULL);
        }
        return 0;
diff --git a/drivers/mmc/host/of_mmc_spi.c b/drivers/mmc/host/of_mmc_spi.c
new file mode 100644 (file)
index 0000000..fb2921f
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * OpenFirmware bindings for the MMC-over-SPI driver
+ *
+ * Copyright (c) MontaVista Software, Inc. 2008.
+ *
+ * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/mmc_spi.h>
+#include <linux/mmc/core.h>
+#include <linux/mmc/host.h>
+
+enum {
+       CD_GPIO = 0,
+       WP_GPIO,
+       NUM_GPIOS,
+};
+
+struct of_mmc_spi {
+       int gpios[NUM_GPIOS];
+       bool alow_gpios[NUM_GPIOS];
+       struct mmc_spi_platform_data pdata;
+};
+
+static struct of_mmc_spi *to_of_mmc_spi(struct device *dev)
+{
+       return container_of(dev->platform_data, struct of_mmc_spi, pdata);
+}
+
+static int of_mmc_spi_read_gpio(struct device *dev, int gpio_num)
+{
+       struct of_mmc_spi *oms = to_of_mmc_spi(dev);
+       bool active_low = oms->alow_gpios[gpio_num];
+       bool value = gpio_get_value(oms->gpios[gpio_num]);
+
+       return active_low ^ value;
+}
+
+static int of_mmc_spi_get_cd(struct device *dev)
+{
+       return of_mmc_spi_read_gpio(dev, CD_GPIO);
+}
+
+static int of_mmc_spi_get_ro(struct device *dev)
+{
+       return of_mmc_spi_read_gpio(dev, WP_GPIO);
+}
+
+struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi)
+{
+       struct device *dev = &spi->dev;
+       struct device_node *np = dev_archdata_get_node(&dev->archdata);
+       struct of_mmc_spi *oms;
+       const u32 *voltage_ranges;
+       int num_ranges;
+       int i;
+       int ret = -EINVAL;
+
+       if (dev->platform_data || !np)
+               return dev->platform_data;
+
+       oms = kzalloc(sizeof(*oms), GFP_KERNEL);
+       if (!oms)
+               return NULL;
+
+       voltage_ranges = of_get_property(np, "voltage-ranges", &num_ranges);
+       num_ranges = num_ranges / sizeof(*voltage_ranges) / 2;
+       if (!voltage_ranges || !num_ranges) {
+               dev_err(dev, "OF: voltage-ranges unspecified\n");
+               goto err_ocr;
+       }
+
+       for (i = 0; i < num_ranges; i++) {
+               const int j = i * 2;
+               u32 mask;
+
+               mask = mmc_vddrange_to_ocrmask(voltage_ranges[j],
+                                              voltage_ranges[j + 1]);
+               if (!mask) {
+                       ret = -EINVAL;
+                       dev_err(dev, "OF: voltage-range #%d is invalid\n", i);
+                       goto err_ocr;
+               }
+               oms->pdata.ocr_mask |= mask;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(oms->gpios); i++) {
+               enum of_gpio_flags gpio_flags;
+
+               oms->gpios[i] = of_get_gpio_flags(np, i, &gpio_flags);
+               if (!gpio_is_valid(oms->gpios[i]))
+                       continue;
+
+               ret = gpio_request(oms->gpios[i], dev->bus_id);
+               if (ret < 0) {
+                       oms->gpios[i] = -EINVAL;
+                       continue;
+               }
+
+               if (gpio_flags & OF_GPIO_ACTIVE_LOW)
+                       oms->alow_gpios[i] = true;
+       }
+
+       if (gpio_is_valid(oms->gpios[CD_GPIO]))
+               oms->pdata.get_cd = of_mmc_spi_get_cd;
+       if (gpio_is_valid(oms->gpios[WP_GPIO]))
+               oms->pdata.get_ro = of_mmc_spi_get_ro;
+
+       /* We don't support interrupts yet, let's poll. */
+       oms->pdata.caps |= MMC_CAP_NEEDS_POLL;
+
+       dev->platform_data = &oms->pdata;
+       return dev->platform_data;
+err_ocr:
+       kfree(oms);
+       return NULL;
+}
+EXPORT_SYMBOL(mmc_spi_get_pdata);
+
+void mmc_spi_put_pdata(struct spi_device *spi)
+{
+       struct device *dev = &spi->dev;
+       struct device_node *np = dev_archdata_get_node(&dev->archdata);
+       struct of_mmc_spi *oms = to_of_mmc_spi(dev);
+       int i;
+
+       if (!dev->platform_data || !np)
+               return;
+
+       for (i = 0; i < ARRAY_SIZE(oms->gpios); i++) {
+               if (gpio_is_valid(oms->gpios[i]))
+                       gpio_free(oms->gpios[i]);
+       }
+       kfree(oms);
+       dev->platform_data = NULL;
+}
+EXPORT_SYMBOL(mmc_spi_put_pdata);
index f88cc74063541a151107527772378fbb35535010..3c5483b75da47ac9e3b2ed4ef0428d1cbff970aa 100644 (file)
@@ -283,7 +283,7 @@ static int pxamci_data_done(struct pxamci_host *host, unsigned int stat)
                return 0;
 
        DCSR(host->dma) = 0;
-       dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len,
+       dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
                     host->dma_dir);
 
        if (stat & STAT_READ_TIME_OUT)
index a16d7609e4eede4fa88f4ecc6b3ac9dce699038a..be9e7b32b34e91fd790a9c196b37d7abc6976934 100644 (file)
 
 /*
  * This is a conceptually ridiculous driver, but it is required by the way
- * the Ricoh multi-function R5C832 works. This chip implements firewire
- * and four different memory card controllers. Two of those controllers are
- * an SDHCI controller and a proprietary MMC controller. The linux SDHCI
+ * the Ricoh multi-function chips (R5CXXX) work. These chips implement
+ * the four main memory card controllers (SD, MMC, MS, xD) and one or both
+ * of cardbus or firewire. It happens that they implement SD and MMC
+ * support as separate controllers (and PCI functions). The linux SDHCI
  * driver supports MMC cards but the chip detects MMC cards in hardware
  * and directs them to the MMC controller - so the SDHCI driver never sees
  * them. To get around this, we must disable the useless MMC controller.
  * a detection event occurs immediately, even if the MMC card is already
  * in the reader.
  *
- * The relevant registers live on the firewire function, so this is unavoidably
- * ugly. Such is life.
+ * It seems to be the case that the relevant PCI registers to deactivate the
+ * MMC controller live on PCI function 0, which might be the cardbus controller
+ * or the firewire controller, depending on the particular chip in question. As
+ * such, it makes what this driver has to do unavoidably ugly. Such is life.
  */
 
 #include <linux/pci.h>
@@ -143,6 +146,7 @@ static int __devinit ricoh_mmc_probe(struct pci_dev *pdev,
                pci_get_device(PCI_VENDOR_ID_RICOH,
                        PCI_DEVICE_ID_RICOH_RL5C476, fw_dev))) {
                if (PCI_SLOT(pdev->devfn) == PCI_SLOT(fw_dev->devfn) &&
+                   PCI_FUNC(fw_dev->devfn) == 0 &&
                    pdev->bus == fw_dev->bus) {
                        if (ricoh_mmc_disable(fw_dev) != 0)
                                return -ENODEV;
@@ -160,6 +164,7 @@ static int __devinit ricoh_mmc_probe(struct pci_dev *pdev,
            (fw_dev = pci_get_device(PCI_VENDOR_ID_RICOH,
                                        PCI_DEVICE_ID_RICOH_R5C832, fw_dev))) {
                if (PCI_SLOT(pdev->devfn) == PCI_SLOT(fw_dev->devfn) &&
+                   PCI_FUNC(fw_dev->devfn) == 0 &&
                    pdev->bus == fw_dev->bus) {
                        if (ricoh_mmc_disable(fw_dev) != 0)
                                return -ENODEV;
@@ -172,7 +177,7 @@ static int __devinit ricoh_mmc_probe(struct pci_dev *pdev,
 
        if (!ctrlfound) {
                printk(KERN_WARNING DRIVER_NAME
-                      ": Main firewire function not found. Cannot disable controller.\n");
+                      ": Main Ricoh function not found. Cannot disable controller.\n");
                return -ENODEV;
        }
 
index 9bd7026b0021bbc0aa15fadedd79ae0471844767..f07255cb17ee7a9d50dd3beacecd9157f523f1f0 100644 (file)
@@ -545,7 +545,7 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
        }
 
        addr = pci_resource_start(pdev, bar);
-       host->ioaddr = ioremap_nocache(addr, pci_resource_len(pdev, bar));
+       host->ioaddr = pci_ioremap_bar(pdev, bar);
        if (!host->ioaddr) {
                dev_err(&pdev->dev, "failed to remap registers\n");
                goto release;
index 4d010a984bed07e6bcbf17899118f3e022fc3200..6b2d1f99af6728d9cd12d42ebe2c71e0adaf08fe 100644 (file)
 #define DBG(f, x...) \
        pr_debug(DRIVER_NAME " [%s()]: " f, __func__,## x)
 
+#if defined(CONFIG_LEDS_CLASS) || (defined(CONFIG_LEDS_CLASS_MODULE) && \
+       defined(CONFIG_MMC_SDHCI_MODULE))
+#define SDHCI_USE_LEDS_CLASS
+#endif
+
 static unsigned int debug_quirks = 0;
 
 static void sdhci_prepare_data(struct sdhci_host *, struct mmc_data *);
@@ -149,7 +154,7 @@ static void sdhci_deactivate_led(struct sdhci_host *host)
        writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
 }
 
-#ifdef CONFIG_LEDS_CLASS
+#ifdef SDHCI_USE_LEDS_CLASS
 static void sdhci_led_control(struct led_classdev *led,
        enum led_brightness brightness)
 {
@@ -994,7 +999,7 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 
        WARN_ON(host->mrq != NULL);
 
-#ifndef CONFIG_LEDS_CLASS
+#ifndef SDHCI_USE_LEDS_CLASS
        sdhci_activate_led(host);
 #endif
 
@@ -1201,7 +1206,7 @@ static void sdhci_tasklet_finish(unsigned long param)
        host->cmd = NULL;
        host->data = NULL;
 
-#ifndef CONFIG_LEDS_CLASS
+#ifndef SDHCI_USE_LEDS_CLASS
        sdhci_deactivate_led(host);
 #endif
 
@@ -1717,7 +1722,7 @@ int sdhci_add_host(struct sdhci_host *host)
        sdhci_dumpregs(host);
 #endif
 
-#ifdef CONFIG_LEDS_CLASS
+#ifdef SDHCI_USE_LEDS_CLASS
        host->led.name = mmc_hostname(mmc);
        host->led.brightness = LED_OFF;
        host->led.default_trigger = mmc_hostname(mmc);
@@ -1739,7 +1744,7 @@ int sdhci_add_host(struct sdhci_host *host)
 
        return 0;
 
-#ifdef CONFIG_LEDS_CLASS
+#ifdef SDHCI_USE_LEDS_CLASS
 reset:
        sdhci_reset(host, SDHCI_RESET_ALL);
        free_irq(host->irq, host);
@@ -1775,7 +1780,7 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
 
        mmc_remove_host(host->mmc);
 
-#ifdef CONFIG_LEDS_CLASS
+#ifdef SDHCI_USE_LEDS_CLASS
        led_classdev_unregister(&host->led);
 #endif
 
index 31f4b1528e76137a43219c5b8d8ba7fb82d625c8..3efba236394164b195674905d4e978856494b477 100644 (file)
@@ -220,7 +220,7 @@ struct sdhci_host {
        struct mmc_host         *mmc;           /* MMC structure */
        u64                     dma_mask;       /* custom DMA mask */
 
-#ifdef CONFIG_LEDS_CLASS
+#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE)
        struct led_classdev     led;            /* LED control */
 #endif
 
index 1df44d966bdb927dc7bc7da7ff1ef5b1ee27a05e..cb41e9c3ac07cce58a2d96c00bff6cda57ec5c55 100644 (file)
@@ -82,6 +82,8 @@ static struct pcmcia_device_id pcmcia_ids[] = {
        /* vendor and device strings followed by their crc32 hashes */
        PCMCIA_DEVICE_PROD_ID12("RICOH", "Bay1Controller", 0xd9f522ed,
                                0xc3901202),
+       PCMCIA_DEVICE_PROD_ID12("RICOH", "Bay Controller", 0xd9f522ed,
+                               0xace80909),
        PCMCIA_DEVICE_NULL,
 };
 
@@ -463,7 +465,7 @@ static int sdricoh_init_mmc(struct pci_dev *pci_dev,
 
 err:
        if (iobase)
-               iounmap(iobase);
+               pci_iounmap(pci_dev, iobase);
        if (mmc)
                mmc_free_host(mmc);
 
index 95430b81ec11f9d000079a73bfa9cd13cb9b4ba1..6a7a619048339a556be68aa7a3640dbf4720e023 100644 (file)
@@ -224,7 +224,7 @@ static inline void tmio_mmc_data_irq(struct tmio_mmc_host *host)
 {
        void __iomem *ctl = host->ctl;
        struct mmc_data *data = host->data;
-       struct mmc_command *stop = data->stop;
+       struct mmc_command *stop;
 
        host->data = NULL;
 
@@ -232,6 +232,7 @@ static inline void tmio_mmc_data_irq(struct tmio_mmc_host *host)
                pr_debug("Spurious data end IRQ\n");
                return;
        }
+       stop = data->stop;
 
        /* FIXME - return correct transfer count on errors */
        if (!data->error)
index c7630a2283109a39d8289cf114f748bd9770cd8f..ba0bd3d5775be9933a0e3da5e15cf8caf366bf6d 100644 (file)
@@ -815,19 +815,20 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
        if (err)
                goto out_free;
 
+       err = -ENOMEM;
        ubi->peb_buf1 = vmalloc(ubi->peb_size);
        if (!ubi->peb_buf1)
                goto out_free;
 
        ubi->peb_buf2 = vmalloc(ubi->peb_size);
        if (!ubi->peb_buf2)
-                goto out_free;
+               goto out_free;
 
 #ifdef CONFIG_MTD_UBI_DEBUG
        mutex_init(&ubi->dbg_buf_mutex);
        ubi->dbg_peb_buf = vmalloc(ubi->peb_size);
        if (!ubi->dbg_peb_buf)
-                goto out_free;
+               goto out_free;
 #endif
 
        err = attach_by_scanning(ubi);
index b30a0b83d7f193ab5cf29ad20cbd7c7e44669f22..98cf31ed081438fc8ee05521cc7bc8c07f82a45d 100644 (file)
@@ -721,7 +721,8 @@ static int rename_volumes(struct ubi_device *ubi,
                 * It seems we need to remove volume with name @re->new_name,
                 * if it exists.
                 */
-               desc = ubi_open_volume_nm(ubi->ubi_num, re->new_name, UBI_EXCLUSIVE);
+               desc = ubi_open_volume_nm(ubi->ubi_num, re->new_name,
+                                         UBI_EXCLUSIVE);
                if (IS_ERR(desc)) {
                        err = PTR_ERR(desc);
                        if (err == -ENODEV)
index 78e914d23ece835d597e0c10c753965fed3d5e31..13777e5beac93344ae759aa2ea0176c796e97d1d 100644 (file)
 #define dbg_err(fmt, ...) ubi_err(fmt, ##__VA_ARGS__)
 
 #define ubi_assert(expr)  do {                                               \
-        if (unlikely(!(expr))) {                                             \
-                printk(KERN_CRIT "UBI assert failed in %s at %u (pid %d)\n", \
-                       __func__, __LINE__, current->pid);                    \
-                ubi_dbg_dump_stack();                                        \
-        }                                                                    \
+       if (unlikely(!(expr))) {                                             \
+               printk(KERN_CRIT "UBI assert failed in %s at %u (pid %d)\n", \
+                      __func__, __LINE__, current->pid);                    \
+               ubi_dbg_dump_stack();                                        \
+       }                                                                    \
 } while (0)
 
 #define dbg_msg(fmt, ...)                                    \
index d8966bae0e0b85ea2810dd094828ddedf1e7cf6a..048a606cebde26018893ab87863b8440f4da5367 100644 (file)
@@ -504,12 +504,9 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
        if (!vid_hdr)
                return -ENOMEM;
 
-       mutex_lock(&ubi->buf_mutex);
-
 retry:
        new_pnum = ubi_wl_get_peb(ubi, UBI_UNKNOWN);
        if (new_pnum < 0) {
-               mutex_unlock(&ubi->buf_mutex);
                ubi_free_vid_hdr(ubi, vid_hdr);
                return new_pnum;
        }
@@ -529,20 +526,23 @@ retry:
                goto write_error;
 
        data_size = offset + len;
+       mutex_lock(&ubi->buf_mutex);
        memset(ubi->peb_buf1 + offset, 0xFF, len);
 
        /* Read everything before the area where the write failure happened */
        if (offset > 0) {
                err = ubi_io_read_data(ubi, ubi->peb_buf1, pnum, 0, offset);
                if (err && err != UBI_IO_BITFLIPS)
-                       goto out_put;
+                       goto out_unlock;
        }
 
        memcpy(ubi->peb_buf1 + offset, buf, len);
 
        err = ubi_io_write_data(ubi, ubi->peb_buf1, new_pnum, 0, data_size);
-       if (err)
+       if (err) {
+               mutex_unlock(&ubi->buf_mutex);
                goto write_error;
+       }
 
        mutex_unlock(&ubi->buf_mutex);
        ubi_free_vid_hdr(ubi, vid_hdr);
@@ -553,8 +553,9 @@ retry:
        ubi_msg("data was successfully recovered");
        return 0;
 
-out_put:
+out_unlock:
        mutex_unlock(&ubi->buf_mutex);
+out_put:
        ubi_wl_put_peb(ubi, new_pnum, 1);
        ubi_free_vid_hdr(ubi, vid_hdr);
        return err;
@@ -567,7 +568,6 @@ write_error:
        ubi_warn("failed to write to PEB %d", new_pnum);
        ubi_wl_put_peb(ubi, new_pnum, 1);
        if (++tries > UBI_IO_RETRIES) {
-               mutex_unlock(&ubi->buf_mutex);
                ubi_free_vid_hdr(ubi, vid_hdr);
                return err;
        }
@@ -949,10 +949,14 @@ write_error:
  * This function copies logical eraseblock from physical eraseblock @from to
  * physical eraseblock @to. The @vid_hdr buffer may be changed by this
  * function. Returns:
- *   o %0  in case of success;
- *   o %1 if the operation was canceled and should be tried later (e.g.,
- *     because a bit-flip was detected at the target PEB);
- *   o %2 if the volume is being deleted and this LEB should not be moved.
+ *   o %0 in case of success;
+ *   o %1 if the operation was canceled because the volume is being deleted
+ *        or because the PEB was put meanwhile;
+ *   o %2 if the operation was canceled because there was a write error to the
+ *        target PEB;
+ *   o %-EAGAIN if the operation was canceled because a bit-flip was detected
+ *     in the target PEB;
+ *   o a negative error code in case of failure.
  */
 int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
                     struct ubi_vid_hdr *vid_hdr)
@@ -978,7 +982,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
        /*
         * Note, we may race with volume deletion, which means that the volume
         * this logical eraseblock belongs to might be being deleted. Since the
-        * volume deletion unmaps all the volume's logical eraseblocks, it will
+        * volume deletion un-maps all the volume's logical eraseblocks, it will
         * be locked in 'ubi_wl_put_peb()' and wait for the WL worker to finish.
         */
        vol = ubi->volumes[idx];
@@ -986,7 +990,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
                /* No need to do further work, cancel */
                dbg_eba("volume %d is being removed, cancel", vol_id);
                spin_unlock(&ubi->volumes_lock);
-               return 2;
+               return 1;
        }
        spin_unlock(&ubi->volumes_lock);
 
@@ -1023,7 +1027,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
 
        /*
         * OK, now the LEB is locked and we can safely start moving it. Since
-        * this function utilizes thie @ubi->peb1_buf buffer which is shared
+        * this function utilizes the @ubi->peb1_buf buffer which is shared
         * with some other functions, so lock the buffer by taking the
         * @ubi->buf_mutex.
         */
@@ -1068,8 +1072,11 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
        vid_hdr->sqnum = cpu_to_be64(next_sqnum(ubi));
 
        err = ubi_io_write_vid_hdr(ubi, to, vid_hdr);
-       if (err)
+       if (err) {
+               if (err == -EIO)
+                       err = 2;
                goto out_unlock_buf;
+       }
 
        cond_resched();
 
@@ -1079,14 +1086,17 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
                if (err != UBI_IO_BITFLIPS)
                        ubi_warn("cannot read VID header back from PEB %d", to);
                else
-                       err = 1;
+                       err = -EAGAIN;
                goto out_unlock_buf;
        }
 
        if (data_size > 0) {
                err = ubi_io_write_data(ubi, ubi->peb_buf1, to, 0, aldata_size);
-               if (err)
+               if (err) {
+                       if (err == -EIO)
+                               err = 2;
                        goto out_unlock_buf;
+               }
 
                cond_resched();
 
@@ -1101,15 +1111,16 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
                                ubi_warn("cannot read data back from PEB %d",
                                         to);
                        else
-                               err = 1;
+                               err = -EAGAIN;
                        goto out_unlock_buf;
                }
 
                cond_resched();
 
                if (memcmp(ubi->peb_buf1, ubi->peb_buf2, aldata_size)) {
-                       ubi_warn("read data back from PEB %d - it is different",
-                                to);
+                       ubi_warn("read data back from PEB %d and it is "
+                                "different", to);
+                       err = -EINVAL;
                        goto out_unlock_buf;
                }
        }
index 2fb64be44f1bab1efde6fd48988b8b22dabd5f39..a74118c05745f000fe317689a8b4824506a4f28d 100644 (file)
@@ -637,8 +637,6 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
 
        dbg_io("read EC header from PEB %d", pnum);
        ubi_assert(pnum >= 0 && pnum < ubi->peb_count);
-       if (UBI_IO_DEBUG)
-               verbose = 1;
 
        err = ubi_io_read(ubi, ec_hdr, pnum, 0, UBI_EC_HDR_SIZE);
        if (err) {
@@ -685,6 +683,9 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
                        if (verbose)
                                ubi_warn("no EC header found at PEB %d, "
                                         "only 0xFF bytes", pnum);
+                       else if (UBI_IO_DEBUG)
+                               dbg_msg("no EC header found at PEB %d, "
+                                       "only 0xFF bytes", pnum);
                        return UBI_IO_PEB_EMPTY;
                }
 
@@ -696,7 +697,9 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
                        ubi_warn("bad magic number at PEB %d: %08x instead of "
                                 "%08x", pnum, magic, UBI_EC_HDR_MAGIC);
                        ubi_dbg_dump_ec_hdr(ec_hdr);
-               }
+               } else if (UBI_IO_DEBUG)
+                       dbg_msg("bad magic number at PEB %d: %08x instead of "
+                               "%08x", pnum, magic, UBI_EC_HDR_MAGIC);
                return UBI_IO_BAD_EC_HDR;
        }
 
@@ -708,7 +711,9 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
                        ubi_warn("bad EC header CRC at PEB %d, calculated "
                                 "%#08x, read %#08x", pnum, crc, hdr_crc);
                        ubi_dbg_dump_ec_hdr(ec_hdr);
-               }
+               } else if (UBI_IO_DEBUG)
+                       dbg_msg("bad EC header CRC at PEB %d, calculated "
+                               "%#08x, read %#08x", pnum, crc, hdr_crc);
                return UBI_IO_BAD_EC_HDR;
        }
 
@@ -912,8 +917,6 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
 
        dbg_io("read VID header from PEB %d", pnum);
        ubi_assert(pnum >= 0 &&  pnum < ubi->peb_count);
-       if (UBI_IO_DEBUG)
-               verbose = 1;
 
        p = (char *)vid_hdr - ubi->vid_hdr_shift;
        err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset,
@@ -960,6 +963,9 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
                        if (verbose)
                                ubi_warn("no VID header found at PEB %d, "
                                         "only 0xFF bytes", pnum);
+                       else if (UBI_IO_DEBUG)
+                               dbg_msg("no VID header found at PEB %d, "
+                                       "only 0xFF bytes", pnum);
                        return UBI_IO_PEB_FREE;
                }
 
@@ -971,7 +977,9 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
                        ubi_warn("bad magic number at PEB %d: %08x instead of "
                                 "%08x", pnum, magic, UBI_VID_HDR_MAGIC);
                        ubi_dbg_dump_vid_hdr(vid_hdr);
-               }
+               } else if (UBI_IO_DEBUG)
+                       dbg_msg("bad magic number at PEB %d: %08x instead of "
+                               "%08x", pnum, magic, UBI_VID_HDR_MAGIC);
                return UBI_IO_BAD_VID_HDR;
        }
 
@@ -983,7 +991,9 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
                        ubi_warn("bad CRC at PEB %d, calculated %#08x, "
                                 "read %#08x", pnum, crc, hdr_crc);
                        ubi_dbg_dump_vid_hdr(vid_hdr);
-               }
+               } else if (UBI_IO_DEBUG)
+                       dbg_msg("bad CRC at PEB %d, calculated %#08x, "
+                               "read %#08x", pnum, crc, hdr_crc);
                return UBI_IO_BAD_VID_HDR;
        }
 
@@ -1024,7 +1034,7 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum,
 
        err = paranoid_check_peb_ec_hdr(ubi, pnum);
        if (err)
-               return err > 0 ? -EINVAL: err;
+               return err > 0 ? -EINVAL : err;
 
        vid_hdr->magic = cpu_to_be32(UBI_VID_HDR_MAGIC);
        vid_hdr->version = UBI_VERSION;
index 1c3fa18c26a7f9fdbf1b0b6a0d2443d82a65745e..4a8ec485c91d97c76b2abd8fe63e5f82603d0313 100644 (file)
  */
 #define UBI_IO_RETRIES 3
 
+/*
+ * Length of the protection queue. The length is effectively equivalent to the
+ * number of (global) erase cycles PEBs are protected from the wear-leveling
+ * worker.
+ */
+#define UBI_PROT_QUEUE_LEN 10
+
 /*
  * Error codes returned by the I/O sub-system.
  *
@@ -95,7 +102,8 @@ enum {
 
 /**
  * struct ubi_wl_entry - wear-leveling entry.
- * @rb: link in the corresponding RB-tree
+ * @u.rb: link in the corresponding (free/used) RB-tree
+ * @u.list: link in the protection queue
  * @ec: erase counter
  * @pnum: physical eraseblock number
  *
@@ -104,7 +112,10 @@ enum {
  * RB-trees. See WL sub-system for details.
  */
 struct ubi_wl_entry {
-       struct rb_node rb;
+       union {
+               struct rb_node rb;
+               struct list_head list;
+       } u;
        int ec;
        int pnum;
 };
@@ -288,7 +299,7 @@ struct ubi_wl_entry;
  * @beb_rsvd_level: normal level of PEBs reserved for bad PEB handling
  *
  * @autoresize_vol_id: ID of the volume which has to be auto-resized at the end
- *                     of UBI ititializetion
+ *                     of UBI initialization
  * @vtbl_slots: how many slots are available in the volume table
  * @vtbl_size: size of the volume table in bytes
  * @vtbl: in-RAM volume table copy
@@ -306,18 +317,17 @@ struct ubi_wl_entry;
  * @used: RB-tree of used physical eraseblocks
  * @free: RB-tree of free physical eraseblocks
  * @scrub: RB-tree of physical eraseblocks which need scrubbing
- * @prot: protection trees
- * @prot.pnum: protection tree indexed by physical eraseblock numbers
- * @prot.aec: protection tree indexed by absolute erase counter value
- * @wl_lock: protects the @used, @free, @prot, @lookuptbl, @abs_ec, @move_from,
- *           @move_to, @move_to_put @erase_pending, @wl_scheduled, and @works
- *           fields
+ * @pq: protection queue (contain physical eraseblocks which are temporarily
+ *      protected from the wear-leveling worker)
+ * @pq_head: protection queue head
+ * @wl_lock: protects the @used, @free, @pq, @pq_head, @lookuptbl, @move_from,
+ *          @move_to, @move_to_put @erase_pending, @wl_scheduled and @works
+ *          fields
  * @move_mutex: serializes eraseblock moves
- * @work_sem: sycnhronizes the WL worker with use tasks
+ * @work_sem: synchronizes the WL worker with use tasks
  * @wl_scheduled: non-zero if the wear-leveling was scheduled
  * @lookuptbl: a table to quickly find a &struct ubi_wl_entry object for any
  *             physical eraseblock
- * @abs_ec: absolute erase counter
  * @move_from: physical eraseblock from where the data is being moved
  * @move_to: physical eraseblock where the data is being moved to
  * @move_to_put: if the "to" PEB was put
@@ -351,11 +361,11 @@ struct ubi_wl_entry;
  *
  * @peb_buf1: a buffer of PEB size used for different purposes
  * @peb_buf2: another buffer of PEB size used for different purposes
- * @buf_mutex: proptects @peb_buf1 and @peb_buf2
+ * @buf_mutex: protects @peb_buf1 and @peb_buf2
  * @ckvol_mutex: serializes static volume checking when opening
- * @mult_mutex: serializes operations on multiple volumes, like re-nameing
+ * @mult_mutex: serializes operations on multiple volumes, like re-naming
  * @dbg_peb_buf: buffer of PEB size used for debugging
- * @dbg_buf_mutex: proptects @dbg_peb_buf
+ * @dbg_buf_mutex: protects @dbg_peb_buf
  */
 struct ubi_device {
        struct cdev cdev;
@@ -392,16 +402,13 @@ struct ubi_device {
        struct rb_root used;
        struct rb_root free;
        struct rb_root scrub;
-       struct {
-               struct rb_root pnum;
-               struct rb_root aec;
-       } prot;
+       struct list_head pq[UBI_PROT_QUEUE_LEN];
+       int pq_head;
        spinlock_t wl_lock;
        struct mutex move_mutex;
        struct rw_semaphore work_sem;
        int wl_scheduled;
        struct ubi_wl_entry **lookuptbl;
-       unsigned long long abs_ec;
        struct ubi_wl_entry *move_from;
        struct ubi_wl_entry *move_to;
        int move_to_put;
index dcb6dac1dc5446b4966d85ef8e6d8e1db5ed9dcb..14901cb82c184fb49d1c08e1713843df0171e7f5 100644 (file)
@@ -22,7 +22,7 @@
  * UBI wear-leveling sub-system.
  *
  * This sub-system is responsible for wear-leveling. It works in terms of
- * physical* eraseblocks and erase counters and knows nothing about logical
+ * physical eraseblocks and erase counters and knows nothing about logical
  * eraseblocks, volumes, etc. From this sub-system's perspective all physical
  * eraseblocks are of two types - used and free. Used physical eraseblocks are
  * those that were "get" by the 'ubi_wl_get_peb()' function, and free physical
  *
  * As it was said, for the UBI sub-system all physical eraseblocks are either
  * "free" or "used". Free eraseblock are kept in the @wl->free RB-tree, while
- * used eraseblocks are kept in a set of different RB-trees: @wl->used,
- * @wl->prot.pnum, @wl->prot.aec, and @wl->scrub.
+ * used eraseblocks are kept in @wl->used or @wl->scrub RB-trees, or
+ * (temporarily) in the @wl->pq queue.
+ *
+ * When the WL sub-system returns a physical eraseblock, the physical
+ * eraseblock is protected from being moved for some "time". For this reason,
+ * the physical eraseblock is not directly moved from the @wl->free tree to the
+ * @wl->used tree. There is a protection queue in between where this
+ * physical eraseblock is temporarily stored (@wl->pq).
+ *
+ * All this protection stuff is needed because:
+ *  o we don't want to move physical eraseblocks just after we have given them
+ *    to the user; instead, we first want to let users fill them up with data;
+ *
+ *  o there is a chance that the user will put the physical eraseblock very
+ *    soon, so it makes sense not to move it for some time, but wait; this is
+ *    especially important in case of "short term" physical eraseblocks.
+ *
+ * Physical eraseblocks stay protected only for limited time. But the "time" is
+ * measured in erase cycles in this case. This is implemented with help of the
+ * protection queue. Eraseblocks are put to the tail of this queue when they
+ * are returned by the 'ubi_wl_get_peb()', and eraseblocks are removed from the
+ * head of the queue on each erase operation (for any eraseblock). So the
+ * length of the queue defines how may (global) erase cycles PEBs are protected.
+ *
+ * To put it differently, each physical eraseblock has 2 main states: free and
+ * used. The former state corresponds to the @wl->free tree. The latter state
+ * is split up on several sub-states:
+ * o the WL movement is allowed (@wl->used tree);
+ * o the WL movement is temporarily prohibited (@wl->pq queue);
+ * o scrubbing is needed (@wl->scrub tree).
+ *
+ * Depending on the sub-state, wear-leveling entries of the used physical
+ * eraseblocks may be kept in one of those structures.
  *
  * Note, in this implementation, we keep a small in-RAM object for each physical
  * eraseblock. This is surely not a scalable solution. But it appears to be good
  * target PEB, we pick a PEB with the highest EC if our PEB is "old" and we
  * pick target PEB with an average EC if our PEB is not very "old". This is a
  * room for future re-works of the WL sub-system.
- *
- * Note: the stuff with protection trees looks too complex and is difficult to
- * understand. Should be fixed.
  */
 
 #include <linux/slab.h>
 /* Number of physical eraseblocks reserved for wear-leveling purposes */
 #define WL_RESERVED_PEBS 1
 
-/*
- * How many erase cycles are short term, unknown, and long term physical
- * eraseblocks protected.
- */
-#define ST_PROTECTION 16
-#define U_PROTECTION  10
-#define LT_PROTECTION 4
-
 /*
  * Maximum difference between two erase counters. If this threshold is
  * exceeded, the WL sub-system starts moving data from used physical
  */
 #define WL_MAX_FAILURES 32
 
-/**
- * struct ubi_wl_prot_entry - PEB protection entry.
- * @rb_pnum: link in the @wl->prot.pnum RB-tree
- * @rb_aec: link in the @wl->prot.aec RB-tree
- * @abs_ec: the absolute erase counter value when the protection ends
- * @e: the wear-leveling entry of the physical eraseblock under protection
- *
- * When the WL sub-system returns a physical eraseblock, the physical
- * eraseblock is protected from being moved for some "time". For this reason,
- * the physical eraseblock is not directly moved from the @wl->free tree to the
- * @wl->used tree. There is one more tree in between where this physical
- * eraseblock is temporarily stored (@wl->prot).
- *
- * All this protection stuff is needed because:
- *  o we don't want to move physical eraseblocks just after we have given them
- *    to the user; instead, we first want to let users fill them up with data;
- *
- *  o there is a chance that the user will put the physical eraseblock very
- *    soon, so it makes sense not to move it for some time, but wait; this is
- *    especially important in case of "short term" physical eraseblocks.
- *
- * Physical eraseblocks stay protected only for limited time. But the "time" is
- * measured in erase cycles in this case. This is implemented with help of the
- * absolute erase counter (@wl->abs_ec). When it reaches certain value, the
- * physical eraseblocks are moved from the protection trees (@wl->prot.*) to
- * the @wl->used tree.
- *
- * Protected physical eraseblocks are searched by physical eraseblock number
- * (when they are put) and by the absolute erase counter (to check if it is
- * time to move them to the @wl->used tree). So there are actually 2 RB-trees
- * storing the protected physical eraseblocks: @wl->prot.pnum and
- * @wl->prot.aec. They are referred to as the "protection" trees. The
- * first one is indexed by the physical eraseblock number. The second one is
- * indexed by the absolute erase counter. Both trees store
- * &struct ubi_wl_prot_entry objects.
- *
- * Each physical eraseblock has 2 main states: free and used. The former state
- * corresponds to the @wl->free tree. The latter state is split up on several
- * sub-states:
- * o the WL movement is allowed (@wl->used tree);
- * o the WL movement is temporarily prohibited (@wl->prot.pnum and
- * @wl->prot.aec trees);
- * o scrubbing is needed (@wl->scrub tree).
- *
- * Depending on the sub-state, wear-leveling entries of the used physical
- * eraseblocks may be kept in one of those trees.
- */
-struct ubi_wl_prot_entry {
-       struct rb_node rb_pnum;
-       struct rb_node rb_aec;
-       unsigned long long abs_ec;
-       struct ubi_wl_entry *e;
-};
-
 /**
  * struct ubi_work - UBI work description data structure.
  * @list: a link in the list of pending works
  * @func: worker function
- * @priv: private data of the worker function
  * @e: physical eraseblock to erase
  * @torture: if the physical eraseblock has to be tortured
  *
@@ -198,9 +163,11 @@ struct ubi_work {
 static int paranoid_check_ec(struct ubi_device *ubi, int pnum, int ec);
 static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e,
                                     struct rb_root *root);
+static int paranoid_check_in_pq(struct ubi_device *ubi, struct ubi_wl_entry *e);
 #else
 #define paranoid_check_ec(ubi, pnum, ec) 0
 #define paranoid_check_in_wl_tree(e, root)
+#define paranoid_check_in_pq(ubi, e) 0
 #endif
 
 /**
@@ -220,7 +187,7 @@ static void wl_tree_add(struct ubi_wl_entry *e, struct rb_root *root)
                struct ubi_wl_entry *e1;
 
                parent = *p;
-               e1 = rb_entry(parent, struct ubi_wl_entry, rb);
+               e1 = rb_entry(parent, struct ubi_wl_entry, u.rb);
 
                if (e->ec < e1->ec)
                        p = &(*p)->rb_left;
@@ -235,8 +202,8 @@ static void wl_tree_add(struct ubi_wl_entry *e, struct rb_root *root)
                }
        }
 
-       rb_link_node(&e->rb, parent, p);
-       rb_insert_color(&e->rb, root);
+       rb_link_node(&e->u.rb, parent, p);
+       rb_insert_color(&e->u.rb, root);
 }
 
 /**
@@ -331,7 +298,7 @@ static int in_wl_tree(struct ubi_wl_entry *e, struct rb_root *root)
        while (p) {
                struct ubi_wl_entry *e1;
 
-               e1 = rb_entry(p, struct ubi_wl_entry, rb);
+               e1 = rb_entry(p, struct ubi_wl_entry, u.rb);
 
                if (e->pnum == e1->pnum) {
                        ubi_assert(e == e1);
@@ -355,50 +322,24 @@ static int in_wl_tree(struct ubi_wl_entry *e, struct rb_root *root)
 }
 
 /**
- * prot_tree_add - add physical eraseblock to protection trees.
+ * prot_queue_add - add physical eraseblock to the protection queue.
  * @ubi: UBI device description object
  * @e: the physical eraseblock to add
- * @pe: protection entry object to use
- * @abs_ec: absolute erase counter value when this physical eraseblock has
- * to be removed from the protection trees.
  *
- * @wl->lock has to be locked.
+ * This function adds @e to the tail of the protection queue @ubi->pq, where
+ * @e will stay for %UBI_PROT_QUEUE_LEN erase operations and will be
+ * temporarily protected from the wear-leveling worker. Note, @wl->lock has to
+ * be locked.
  */
-static void prot_tree_add(struct ubi_device *ubi, struct ubi_wl_entry *e,
-                         struct ubi_wl_prot_entry *pe, int abs_ec)
+static void prot_queue_add(struct ubi_device *ubi, struct ubi_wl_entry *e)
 {
-       struct rb_node **p, *parent = NULL;
-       struct ubi_wl_prot_entry *pe1;
-
-       pe->e = e;
-       pe->abs_ec = ubi->abs_ec + abs_ec;
-
-       p = &ubi->prot.pnum.rb_node;
-       while (*p) {
-               parent = *p;
-               pe1 = rb_entry(parent, struct ubi_wl_prot_entry, rb_pnum);
-
-               if (e->pnum < pe1->e->pnum)
-                       p = &(*p)->rb_left;
-               else
-                       p = &(*p)->rb_right;
-       }
-       rb_link_node(&pe->rb_pnum, parent, p);
-       rb_insert_color(&pe->rb_pnum, &ubi->prot.pnum);
-
-       p = &ubi->prot.aec.rb_node;
-       parent = NULL;
-       while (*p) {
-               parent = *p;
-               pe1 = rb_entry(parent, struct ubi_wl_prot_entry, rb_aec);
+       int pq_tail = ubi->pq_head - 1;
 
-               if (pe->abs_ec < pe1->abs_ec)
-                       p = &(*p)->rb_left;
-               else
-                       p = &(*p)->rb_right;
-       }
-       rb_link_node(&pe->rb_aec, parent, p);
-       rb_insert_color(&pe->rb_aec, &ubi->prot.aec);
+       if (pq_tail < 0)
+               pq_tail = UBI_PROT_QUEUE_LEN - 1;
+       ubi_assert(pq_tail >= 0 && pq_tail < UBI_PROT_QUEUE_LEN);
+       list_add_tail(&e->u.list, &ubi->pq[pq_tail]);
+       dbg_wl("added PEB %d EC %d to the protection queue", e->pnum, e->ec);
 }
 
 /**
@@ -414,14 +355,14 @@ static struct ubi_wl_entry *find_wl_entry(struct rb_root *root, int max)
        struct rb_node *p;
        struct ubi_wl_entry *e;
 
-       e = rb_entry(rb_first(root), struct ubi_wl_entry, rb);
+       e = rb_entry(rb_first(root), struct ubi_wl_entry, u.rb);
        max += e->ec;
 
        p = root->rb_node;
        while (p) {
                struct ubi_wl_entry *e1;
 
-               e1 = rb_entry(p, struct ubi_wl_entry, rb);
+               e1 = rb_entry(p, struct ubi_wl_entry, u.rb);
                if (e1->ec >= max)
                        p = p->rb_left;
                else {
@@ -443,17 +384,12 @@ static struct ubi_wl_entry *find_wl_entry(struct rb_root *root, int max)
  */
 int ubi_wl_get_peb(struct ubi_device *ubi, int dtype)
 {
-       int err, protect, medium_ec;
+       int err, medium_ec;
        struct ubi_wl_entry *e, *first, *last;
-       struct ubi_wl_prot_entry *pe;
 
        ubi_assert(dtype == UBI_LONGTERM || dtype == UBI_SHORTTERM ||
                   dtype == UBI_UNKNOWN);
 
-       pe = kmalloc(sizeof(struct ubi_wl_prot_entry), GFP_NOFS);
-       if (!pe)
-               return -ENOMEM;
-
 retry:
        spin_lock(&ubi->wl_lock);
        if (!ubi->free.rb_node) {
@@ -461,16 +397,13 @@ retry:
                        ubi_assert(list_empty(&ubi->works));
                        ubi_err("no free eraseblocks");
                        spin_unlock(&ubi->wl_lock);
-                       kfree(pe);
                        return -ENOSPC;
                }
                spin_unlock(&ubi->wl_lock);
 
                err = produce_free_peb(ubi);
-               if (err < 0) {
-                       kfree(pe);
+               if (err < 0)
                        return err;
-               }
                goto retry;
        }
 
@@ -483,7 +416,6 @@ retry:
                 * %WL_FREE_MAX_DIFF.
                 */
                e = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF);
-               protect = LT_PROTECTION;
                break;
        case UBI_UNKNOWN:
                /*
@@ -492,81 +424,63 @@ retry:
                 * eraseblock with erase counter greater or equivalent than the
                 * lowest erase counter plus %WL_FREE_MAX_DIFF.
                 */
-               first = rb_entry(rb_first(&ubi->free), struct ubi_wl_entry, rb);
-               last = rb_entry(rb_last(&ubi->free), struct ubi_wl_entry, rb);
+               first = rb_entry(rb_first(&ubi->free), struct ubi_wl_entry,
+                                       u.rb);
+               last = rb_entry(rb_last(&ubi->free), struct ubi_wl_entry, u.rb);
 
                if (last->ec - first->ec < WL_FREE_MAX_DIFF)
                        e = rb_entry(ubi->free.rb_node,
-                                       struct ubi_wl_entry, rb);
+                                       struct ubi_wl_entry, u.rb);
                else {
                        medium_ec = (first->ec + WL_FREE_MAX_DIFF)/2;
                        e = find_wl_entry(&ubi->free, medium_ec);
                }
-               protect = U_PROTECTION;
                break;
        case UBI_SHORTTERM:
                /*
                 * For short term data we pick a physical eraseblock with the
                 * lowest erase counter as we expect it will be erased soon.
                 */
-               e = rb_entry(rb_first(&ubi->free), struct ubi_wl_entry, rb);
-               protect = ST_PROTECTION;
+               e = rb_entry(rb_first(&ubi->free), struct ubi_wl_entry, u.rb);
                break;
        default:
-               protect = 0;
-               e = NULL;
                BUG();
        }
 
+       paranoid_check_in_wl_tree(e, &ubi->free);
+
        /*
-        * Move the physical eraseblock to the protection trees where it will
+        * Move the physical eraseblock to the protection queue where it will
         * be protected from being moved for some time.
         */
-       paranoid_check_in_wl_tree(e, &ubi->free);
-       rb_erase(&e->rb, &ubi->free);
-       prot_tree_add(ubi, e, pe, protect);
-
-       dbg_wl("PEB %d EC %d, protection %d", e->pnum, e->ec, protect);
+       rb_erase(&e->u.rb, &ubi->free);
+       dbg_wl("PEB %d EC %d", e->pnum, e->ec);
+       prot_queue_add(ubi, e);
        spin_unlock(&ubi->wl_lock);
-
        return e->pnum;
 }
 
 /**
- * prot_tree_del - remove a physical eraseblock from the protection trees
+ * prot_queue_del - remove a physical eraseblock from the protection queue.
  * @ubi: UBI device description object
  * @pnum: the physical eraseblock to remove
  *
- * This function returns PEB @pnum from the protection trees and returns zero
- * in case of success and %-ENODEV if the PEB was not found in the protection
- * trees.
+ * This function deletes PEB @pnum from the protection queue and returns zero
+ * in case of success and %-ENODEV if the PEB was not found.
  */
-static int prot_tree_del(struct ubi_device *ubi, int pnum)
+static int prot_queue_del(struct ubi_device *ubi, int pnum)
 {
-       struct rb_node *p;
-       struct ubi_wl_prot_entry *pe = NULL;
-
-       p = ubi->prot.pnum.rb_node;
-       while (p) {
-
-               pe = rb_entry(p, struct ubi_wl_prot_entry, rb_pnum);
-
-               if (pnum == pe->e->pnum)
-                       goto found;
+       struct ubi_wl_entry *e;
 
-               if (pnum < pe->e->pnum)
-                       p = p->rb_left;
-               else
-                       p = p->rb_right;
-       }
+       e = ubi->lookuptbl[pnum];
+       if (!e)
+               return -ENODEV;
 
-       return -ENODEV;
+       if (paranoid_check_in_pq(ubi, e))
+               return -ENODEV;
 
-found:
-       ubi_assert(pe->e->pnum == pnum);
-       rb_erase(&pe->rb_aec, &ubi->prot.aec);
-       rb_erase(&pe->rb_pnum, &ubi->prot.pnum);
-       kfree(pe);
+       list_del(&e->u.list);
+       dbg_wl("deleted PEB %d from the protection queue", e->pnum);
        return 0;
 }
 
@@ -632,47 +546,47 @@ out_free:
 }
 
 /**
- * check_protection_over - check if it is time to stop protecting some PEBs.
+ * serve_prot_queue - check if it is time to stop protecting PEBs.
  * @ubi: UBI device description object
  *
- * This function is called after each erase operation, when the absolute erase
- * counter is incremented, to check if some physical eraseblock  have not to be
- * protected any longer. These physical eraseblocks are moved from the
- * protection trees to the used tree.
+ * This function is called after each erase operation and removes PEBs from the
+ * tail of the protection queue. These PEBs have been protected for long enough
+ * and should be moved to the used tree.
  */
-static void check_protection_over(struct ubi_device *ubi)
+static void serve_prot_queue(struct ubi_device *ubi)
 {
-       struct ubi_wl_prot_entry *pe;
+       struct ubi_wl_entry *e, *tmp;
+       int count;
 
        /*
         * There may be several protected physical eraseblock to remove,
         * process them all.
         */
-       while (1) {
-               spin_lock(&ubi->wl_lock);
-               if (!ubi->prot.aec.rb_node) {
-                       spin_unlock(&ubi->wl_lock);
-                       break;
-               }
-
-               pe = rb_entry(rb_first(&ubi->prot.aec),
-                             struct ubi_wl_prot_entry, rb_aec);
+repeat:
+       count = 0;
+       spin_lock(&ubi->wl_lock);
+       list_for_each_entry_safe(e, tmp, &ubi->pq[ubi->pq_head], u.list) {
+               dbg_wl("PEB %d EC %d protection over, move to used tree",
+                       e->pnum, e->ec);
 
-               if (pe->abs_ec > ubi->abs_ec) {
+               list_del(&e->u.list);
+               wl_tree_add(e, &ubi->used);
+               if (count++ > 32) {
+                       /*
+                        * Let's be nice and avoid holding the spinlock for
+                        * too long.
+                        */
                        spin_unlock(&ubi->wl_lock);
-                       break;
+                       cond_resched();
+                       goto repeat;
                }
-
-               dbg_wl("PEB %d protection over, abs_ec %llu, PEB abs_ec %llu",
-                      pe->e->pnum, ubi->abs_ec, pe->abs_ec);
-               rb_erase(&pe->rb_aec, &ubi->prot.aec);
-               rb_erase(&pe->rb_pnum, &ubi->prot.pnum);
-               wl_tree_add(pe->e, &ubi->used);
-               spin_unlock(&ubi->wl_lock);
-
-               kfree(pe);
-               cond_resched();
        }
+
+       ubi->pq_head += 1;
+       if (ubi->pq_head == UBI_PROT_QUEUE_LEN)
+               ubi->pq_head = 0;
+       ubi_assert(ubi->pq_head >= 0 && ubi->pq_head < UBI_PROT_QUEUE_LEN);
+       spin_unlock(&ubi->wl_lock);
 }
 
 /**
@@ -680,8 +594,8 @@ static void check_protection_over(struct ubi_device *ubi)
  * @ubi: UBI device description object
  * @wrk: the work to schedule
  *
- * This function enqueues a work defined by @wrk to the tail of the pending
- * works list.
+ * This function adds a work defined by @wrk to the tail of the pending works
+ * list.
  */
 static void schedule_ubi_work(struct ubi_device *ubi, struct ubi_work *wrk)
 {
@@ -739,13 +653,11 @@ static int schedule_erase(struct ubi_device *ubi, struct ubi_wl_entry *e,
 static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
                                int cancel)
 {
-       int err, put = 0, scrubbing = 0, protect = 0;
-       struct ubi_wl_prot_entry *uninitialized_var(pe);
+       int err, scrubbing = 0, torture = 0;
        struct ubi_wl_entry *e1, *e2;
        struct ubi_vid_hdr *vid_hdr;
 
        kfree(wrk);
-
        if (cancel)
                return 0;
 
@@ -781,7 +693,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
                 * highly worn-out free physical eraseblock. If the erase
                 * counters differ much enough, start wear-leveling.
                 */
-               e1 = rb_entry(rb_first(&ubi->used), struct ubi_wl_entry, rb);
+               e1 = rb_entry(rb_first(&ubi->used), struct ubi_wl_entry, u.rb);
                e2 = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF);
 
                if (!(e2->ec - e1->ec >= UBI_WL_THRESHOLD)) {
@@ -790,21 +702,21 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
                        goto out_cancel;
                }
                paranoid_check_in_wl_tree(e1, &ubi->used);
-               rb_erase(&e1->rb, &ubi->used);
+               rb_erase(&e1->u.rb, &ubi->used);
                dbg_wl("move PEB %d EC %d to PEB %d EC %d",
                       e1->pnum, e1->ec, e2->pnum, e2->ec);
        } else {
                /* Perform scrubbing */
                scrubbing = 1;
-               e1 = rb_entry(rb_first(&ubi->scrub), struct ubi_wl_entry, rb);
+               e1 = rb_entry(rb_first(&ubi->scrub), struct ubi_wl_entry, u.rb);
                e2 = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF);
                paranoid_check_in_wl_tree(e1, &ubi->scrub);
-               rb_erase(&e1->rb, &ubi->scrub);
+               rb_erase(&e1->u.rb, &ubi->scrub);
                dbg_wl("scrub PEB %d to PEB %d", e1->pnum, e2->pnum);
        }
 
        paranoid_check_in_wl_tree(e2, &ubi->free);
-       rb_erase(&e2->rb, &ubi->free);
+       rb_erase(&e2->u.rb, &ubi->free);
        ubi->move_from = e1;
        ubi->move_to = e2;
        spin_unlock(&ubi->wl_lock);
@@ -844,46 +756,67 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
 
        err = ubi_eba_copy_leb(ubi, e1->pnum, e2->pnum, vid_hdr);
        if (err) {
-
+               if (err == -EAGAIN)
+                       goto out_not_moved;
                if (err < 0)
                        goto out_error;
-               if (err == 1)
+               if (err == 2) {
+                       /* Target PEB write error, torture it */
+                       torture = 1;
                        goto out_not_moved;
+               }
 
                /*
-                * For some reason the LEB was not moved - it might be because
-                * the volume is being deleted. We should prevent this PEB from
-                * being selected for wear-levelling movement for some "time",
-                * so put it to the protection tree.
+                * The LEB has not been moved because the volume is being
+                * deleted or the PEB has been put meanwhile. We should prevent
+                * this PEB from being selected for wear-leveling movement
+                * again, so put it to the protection queue.
                 */
 
-               dbg_wl("cancelled moving PEB %d", e1->pnum);
-               pe = kmalloc(sizeof(struct ubi_wl_prot_entry), GFP_NOFS);
-               if (!pe) {
-                       err = -ENOMEM;
-                       goto out_error;
-               }
+               dbg_wl("canceled moving PEB %d", e1->pnum);
+               ubi_assert(err == 1);
+
+               ubi_free_vid_hdr(ubi, vid_hdr);
+               vid_hdr = NULL;
+
+               spin_lock(&ubi->wl_lock);
+               prot_queue_add(ubi, e1);
+               ubi_assert(!ubi->move_to_put);
+               ubi->move_from = ubi->move_to = NULL;
+               ubi->wl_scheduled = 0;
+               spin_unlock(&ubi->wl_lock);
 
-               protect = 1;
+               e1 = NULL;
+               err = schedule_erase(ubi, e2, 0);
+               if (err)
+                       goto out_error;
+               mutex_unlock(&ubi->move_mutex);
+               return 0;
        }
 
+       /* The PEB has been successfully moved */
        ubi_free_vid_hdr(ubi, vid_hdr);
-       if (scrubbing && !protect)
+       vid_hdr = NULL;
+       if (scrubbing)
                ubi_msg("scrubbed PEB %d, data moved to PEB %d",
                        e1->pnum, e2->pnum);
 
        spin_lock(&ubi->wl_lock);
-       if (protect)
-               prot_tree_add(ubi, e1, pe, protect);
-       if (!ubi->move_to_put)
+       if (!ubi->move_to_put) {
                wl_tree_add(e2, &ubi->used);
-       else
-               put = 1;
+               e2 = NULL;
+       }
        ubi->move_from = ubi->move_to = NULL;
        ubi->move_to_put = ubi->wl_scheduled = 0;
        spin_unlock(&ubi->wl_lock);
 
-       if (put) {
+       err = schedule_erase(ubi, e1, 0);
+       if (err) {
+               e1 = NULL;
+               goto out_error;
+       }
+
+       if (e2) {
                /*
                 * Well, the target PEB was put meanwhile, schedule it for
                 * erasure.
@@ -894,13 +827,6 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
                        goto out_error;
        }
 
-       if (!protect) {
-               err = schedule_erase(ubi, e1, 0);
-               if (err)
-                       goto out_error;
-       }
-
-
        dbg_wl("done");
        mutex_unlock(&ubi->move_mutex);
        return 0;
@@ -908,20 +834,24 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
        /*
         * For some reasons the LEB was not moved, might be an error, might be
         * something else. @e1 was not changed, so return it back. @e2 might
-        * be changed, schedule it for erasure.
+        * have been changed, schedule it for erasure.
         */
 out_not_moved:
+       dbg_wl("canceled moving PEB %d", e1->pnum);
        ubi_free_vid_hdr(ubi, vid_hdr);
+       vid_hdr = NULL;
        spin_lock(&ubi->wl_lock);
        if (scrubbing)
                wl_tree_add(e1, &ubi->scrub);
        else
                wl_tree_add(e1, &ubi->used);
+       ubi_assert(!ubi->move_to_put);
        ubi->move_from = ubi->move_to = NULL;
-       ubi->move_to_put = ubi->wl_scheduled = 0;
+       ubi->wl_scheduled = 0;
        spin_unlock(&ubi->wl_lock);
 
-       err = schedule_erase(ubi, e2, 0);
+       e1 = NULL;
+       err = schedule_erase(ubi, e2, torture);
        if (err)
                goto out_error;
 
@@ -938,8 +868,10 @@ out_error:
        ubi->move_to_put = ubi->wl_scheduled = 0;
        spin_unlock(&ubi->wl_lock);
 
-       kmem_cache_free(ubi_wl_entry_slab, e1);
-       kmem_cache_free(ubi_wl_entry_slab, e2);
+       if (e1)
+               kmem_cache_free(ubi_wl_entry_slab, e1);
+       if (e2)
+               kmem_cache_free(ubi_wl_entry_slab, e2);
        ubi_ro_mode(ubi);
 
        mutex_unlock(&ubi->move_mutex);
@@ -988,7 +920,7 @@ static int ensure_wear_leveling(struct ubi_device *ubi)
                 * erase counter of free physical eraseblocks is greater then
                 * %UBI_WL_THRESHOLD.
                 */
-               e1 = rb_entry(rb_first(&ubi->used), struct ubi_wl_entry, rb);
+               e1 = rb_entry(rb_first(&ubi->used), struct ubi_wl_entry, u.rb);
                e2 = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF);
 
                if (!(e2->ec - e1->ec >= UBI_WL_THRESHOLD))
@@ -1050,7 +982,6 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
                kfree(wl_wrk);
 
                spin_lock(&ubi->wl_lock);
-               ubi->abs_ec += 1;
                wl_tree_add(e, &ubi->free);
                spin_unlock(&ubi->wl_lock);
 
@@ -1058,7 +989,7 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
                 * One more erase operation has happened, take care about
                 * protected physical eraseblocks.
                 */
-               check_protection_over(ubi);
+               serve_prot_queue(ubi);
 
                /* And take care about wear-leveling */
                err = ensure_wear_leveling(ubi);
@@ -1190,12 +1121,12 @@ retry:
        } else {
                if (in_wl_tree(e, &ubi->used)) {
                        paranoid_check_in_wl_tree(e, &ubi->used);
-                       rb_erase(&e->rb, &ubi->used);
+                       rb_erase(&e->u.rb, &ubi->used);
                } else if (in_wl_tree(e, &ubi->scrub)) {
                        paranoid_check_in_wl_tree(e, &ubi->scrub);
-                       rb_erase(&e->rb, &ubi->scrub);
+                       rb_erase(&e->u.rb, &ubi->scrub);
                } else {
-                       err = prot_tree_del(ubi, e->pnum);
+                       err = prot_queue_del(ubi, e->pnum);
                        if (err) {
                                ubi_err("PEB %d not found", pnum);
                                ubi_ro_mode(ubi);
@@ -1255,11 +1186,11 @@ retry:
 
        if (in_wl_tree(e, &ubi->used)) {
                paranoid_check_in_wl_tree(e, &ubi->used);
-               rb_erase(&e->rb, &ubi->used);
+               rb_erase(&e->u.rb, &ubi->used);
        } else {
                int err;
 
-               err = prot_tree_del(ubi, e->pnum);
+               err = prot_queue_del(ubi, e->pnum);
                if (err) {
                        ubi_err("PEB %d not found", pnum);
                        ubi_ro_mode(ubi);
@@ -1290,7 +1221,7 @@ int ubi_wl_flush(struct ubi_device *ubi)
        int err;
 
        /*
-        * Erase while the pending works queue is not empty, but not more then
+        * Erase while the pending works queue is not empty, but not more than
         * the number of currently pending works.
         */
        dbg_wl("flush (%d pending works)", ubi->works_count);
@@ -1308,7 +1239,7 @@ int ubi_wl_flush(struct ubi_device *ubi)
        up_write(&ubi->work_sem);
 
        /*
-        * And in case last was the WL worker and it cancelled the LEB
+        * And in case last was the WL worker and it canceled the LEB
         * movement, flush again.
         */
        while (ubi->works_count) {
@@ -1337,11 +1268,11 @@ static void tree_destroy(struct rb_root *root)
                else if (rb->rb_right)
                        rb = rb->rb_right;
                else {
-                       e = rb_entry(rb, struct ubi_wl_entry, rb);
+                       e = rb_entry(rb, struct ubi_wl_entry, u.rb);
 
                        rb = rb_parent(rb);
                        if (rb) {
-                               if (rb->rb_left == &e->rb)
+                               if (rb->rb_left == &e->u.rb)
                                        rb->rb_left = NULL;
                                else
                                        rb->rb_right = NULL;
@@ -1436,15 +1367,13 @@ static void cancel_pending(struct ubi_device *ubi)
  */
 int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
 {
-       int err;
+       int err, i;
        struct rb_node *rb1, *rb2;
        struct ubi_scan_volume *sv;
        struct ubi_scan_leb *seb, *tmp;
        struct ubi_wl_entry *e;
 
-
        ubi->used = ubi->free = ubi->scrub = RB_ROOT;
-       ubi->prot.pnum = ubi->prot.aec = RB_ROOT;
        spin_lock_init(&ubi->wl_lock);
        mutex_init(&ubi->move_mutex);
        init_rwsem(&ubi->work_sem);
@@ -1458,6 +1387,10 @@ int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
        if (!ubi->lookuptbl)
                return err;
 
+       for (i = 0; i < UBI_PROT_QUEUE_LEN; i++)
+               INIT_LIST_HEAD(&ubi->pq[i]);
+       ubi->pq_head = 0;
+
        list_for_each_entry_safe(seb, tmp, &si->erase, u.list) {
                cond_resched();
 
@@ -1552,33 +1485,18 @@ out_free:
 }
 
 /**
- * protection_trees_destroy - destroy the protection RB-trees.
+ * protection_queue_destroy - destroy the protection queue.
  * @ubi: UBI device description object
  */
-static void protection_trees_destroy(struct ubi_device *ubi)
+static void protection_queue_destroy(struct ubi_device *ubi)
 {
-       struct rb_node *rb;
-       struct ubi_wl_prot_entry *pe;
-
-       rb = ubi->prot.aec.rb_node;
-       while (rb) {
-               if (rb->rb_left)
-                       rb = rb->rb_left;
-               else if (rb->rb_right)
-                       rb = rb->rb_right;
-               else {
-                       pe = rb_entry(rb, struct ubi_wl_prot_entry, rb_aec);
-
-                       rb = rb_parent(rb);
-                       if (rb) {
-                               if (rb->rb_left == &pe->rb_aec)
-                                       rb->rb_left = NULL;
-                               else
-                                       rb->rb_right = NULL;
-                       }
+       int i;
+       struct ubi_wl_entry *e, *tmp;
 
-                       kmem_cache_free(ubi_wl_entry_slab, pe->e);
-                       kfree(pe);
+       for (i = 0; i < UBI_PROT_QUEUE_LEN; ++i) {
+               list_for_each_entry_safe(e, tmp, &ubi->pq[i], u.list) {
+                       list_del(&e->u.list);
+                       kmem_cache_free(ubi_wl_entry_slab, e);
                }
        }
 }
@@ -1591,7 +1509,7 @@ void ubi_wl_close(struct ubi_device *ubi)
 {
        dbg_wl("close the WL sub-system");
        cancel_pending(ubi);
-       protection_trees_destroy(ubi);
+       protection_queue_destroy(ubi);
        tree_destroy(&ubi->used);
        tree_destroy(&ubi->free);
        tree_destroy(&ubi->scrub);
@@ -1661,4 +1579,27 @@ static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e,
        return 1;
 }
 
+/**
+ * paranoid_check_in_pq - check if wear-leveling entry is in the protection
+ *                        queue.
+ * @ubi: UBI device description object
+ * @e: the wear-leveling entry to check
+ *
+ * This function returns zero if @e is in @ubi->pq and %1 if it is not.
+ */
+static int paranoid_check_in_pq(struct ubi_device *ubi, struct ubi_wl_entry *e)
+{
+       struct ubi_wl_entry *p;
+       int i;
+
+       for (i = 0; i < UBI_PROT_QUEUE_LEN; ++i)
+               list_for_each_entry(p, &ubi->pq[i], u.list)
+                       if (p == e)
+                               return 0;
+
+       ubi_err("paranoid check failed for PEB %d, EC %d, Protect queue",
+               e->pnum, e->ec);
+       ubi_dbg_dump_stack();
+       return 1;
+}
 #endif /* CONFIG_MTD_UBI_DEBUG_PARANOID */
index 517fce48d94a0c2eac28ed49110e05ab322d0e97..5b396ff6c83f24d4749cd29f1b975d5cec8b42ad 100644 (file)
@@ -66,6 +66,7 @@
 #include <linux/mm.h>
 #include <linux/highmem.h>
 #include <linux/sockios.h>
+#include <linux/firmware.h>
 
 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
 #include <linux/if_vlan.h>
@@ -186,8 +187,6 @@ MODULE_DEVICE_TABLE(pci, acenic_pci_tbl);
 #define MAX_RODATA_LEN 8*1024
 #define MAX_DATA_LEN   2*1024
 
-#include "acenic_firmware.h"
-
 #ifndef tigon2FwReleaseLocal
 #define tigon2FwReleaseLocal 0
 #endif
@@ -417,6 +416,10 @@ static int dis_pci_mem_inval[ACE_MAX_MOD_PARMS] = {1, 1, 1, 1, 1, 1, 1, 1};
 MODULE_AUTHOR("Jes Sorensen <jes@trained-monkey.org>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("AceNIC/3C985/GA620 Gigabit Ethernet driver");
+#ifndef CONFIG_ACENIC_OMIT_TIGON_I
+MODULE_FIRMWARE("acenic/tg1.bin");
+#endif
+MODULE_FIRMWARE("acenic/tg2.bin");
 
 module_param_array_named(link, link_state, int, NULL, 0);
 module_param_array(trace, int, NULL, 0);
@@ -943,8 +946,8 @@ static int __devinit ace_init(struct net_device *dev)
        case 4:
        case 5:
                printk(KERN_INFO "  Tigon I  (Rev. %i), Firmware: %i.%i.%i, ",
-                      tig_ver, tigonFwReleaseMajor, tigonFwReleaseMinor,
-                      tigonFwReleaseFix);
+                      tig_ver, ap->firmware_major, ap->firmware_minor,
+                      ap->firmware_fix);
                writel(0, &regs->LocalCtrl);
                ap->version = 1;
                ap->tx_ring_entries = TIGON_I_TX_RING_ENTRIES;
@@ -952,8 +955,8 @@ static int __devinit ace_init(struct net_device *dev)
 #endif
        case 6:
                printk(KERN_INFO "  Tigon II (Rev. %i), Firmware: %i.%i.%i, ",
-                      tig_ver, tigon2FwReleaseMajor, tigon2FwReleaseMinor,
-                      tigon2FwReleaseFix);
+                      tig_ver, ap->firmware_major, ap->firmware_minor,
+                      ap->firmware_fix);
                writel(readl(&regs->CpuBCtrl) | CPU_HALT, &regs->CpuBCtrl);
                readl(&regs->CpuBCtrl);         /* PCI write posting */
                /*
@@ -1205,7 +1208,9 @@ static int __devinit ace_init(struct net_device *dev)
        memset(ap->info, 0, sizeof(struct ace_info));
        memset(ap->skb, 0, sizeof(struct ace_skb));
 
-       ace_load_firmware(dev);
+       if (ace_load_firmware(dev))
+               goto init_error;
+
        ap->fw_running = 0;
 
        tmp_ptr = ap->info_dma;
@@ -1441,10 +1446,7 @@ static int __devinit ace_init(struct net_device *dev)
        if (ap->version >= 2)
                writel(tmp, &regs->TuneFastLink);
 
-       if (ACE_IS_TIGON_I(ap))
-               writel(tigonFwStartAddr, &regs->Pc);
-       if (ap->version == 2)
-               writel(tigon2FwStartAddr, &regs->Pc);
+       writel(ap->firmware_start, &regs->Pc);
 
        writel(0, &regs->Mb0Lo);
 
@@ -2761,8 +2763,8 @@ static void ace_get_drvinfo(struct net_device *dev,
 
        strlcpy(info->driver, "acenic", sizeof(info->driver));
        snprintf(info->version, sizeof(info->version), "%i.%i.%i",
-               tigonFwReleaseMajor, tigonFwReleaseMinor,
-               tigonFwReleaseFix);
+                ap->firmware_major, ap->firmware_minor,
+                ap->firmware_fix);
 
        if (ap->pdev)
                strlcpy(info->bus_info, pci_name(ap->pdev),
@@ -2869,11 +2871,10 @@ static struct net_device_stats *ace_get_stats(struct net_device *dev)
 }
 
 
-static void __devinit ace_copy(struct ace_regs __iomem *regs, void *src,
-                           u32 dest, int size)
+static void __devinit ace_copy(struct ace_regs __iomem *regs, const __be32 *src,
+                              u32 dest, int size)
 {
        void __iomem *tdest;
-       u32 *wsrc;
        short tsize, i;
 
        if (size <= 0)
@@ -2885,20 +2886,15 @@ static void __devinit ace_copy(struct ace_regs __iomem *regs, void *src,
                tdest = (void __iomem *) &regs->Window +
                        (dest & (ACE_WINDOW_SIZE - 1));
                writel(dest & ~(ACE_WINDOW_SIZE - 1), &regs->WinBase);
-               /*
-                * This requires byte swapping on big endian, however
-                * writel does that for us
-                */
-               wsrc = src;
                for (i = 0; i < (tsize / 4); i++) {
-                       writel(wsrc[i], tdest + i*4);
+                       /* Firmware is big-endian */
+                       writel(be32_to_cpup(src), tdest);
+                       src++;
+                       tdest += 4;
+                       dest += 4;
+                       size -= 4;
                }
-               dest += tsize;
-               src += tsize;
-               size -= tsize;
        }
-
-       return;
 }
 
 
@@ -2937,8 +2933,13 @@ static void __devinit ace_clear(struct ace_regs __iomem *regs, u32 dest, int siz
  */
 static int __devinit ace_load_firmware(struct net_device *dev)
 {
+       const struct firmware *fw;
+       const char *fw_name = "acenic/tg2.bin";
        struct ace_private *ap = netdev_priv(dev);
        struct ace_regs __iomem *regs = ap->regs;
+       const __be32 *fw_data;
+       u32 load_addr;
+       int ret;
 
        if (!(readl(&regs->CpuCtrl) & CPU_HALTED)) {
                printk(KERN_ERR "%s: trying to download firmware while the "
@@ -2946,28 +2947,52 @@ static int __devinit ace_load_firmware(struct net_device *dev)
                return -EFAULT;
        }
 
+       if (ACE_IS_TIGON_I(ap))
+               fw_name = "acenic/tg1.bin";
+
+       ret = request_firmware(&fw, fw_name, &ap->pdev->dev);
+       if (ret) {
+               printk(KERN_ERR "%s: Failed to load firmware \"%s\"\n",
+                      ap->name, fw_name);
+               return ret;
+       }
+
+       fw_data = (void *)fw->data;
+
+       /* Firmware blob starts with version numbers, followed by
+          load and start address. Remainder is the blob to be loaded
+          contiguously from load address. We don't bother to represent
+          the BSS/SBSS sections any more, since we were clearing the
+          whole thing anyway. */
+       ap->firmware_major = fw->data[0];
+       ap->firmware_minor = fw->data[1];
+       ap->firmware_fix = fw->data[2];
+
+       ap->firmware_start = be32_to_cpu(fw_data[1]);
+       if (ap->firmware_start < 0x4000 || ap->firmware_start >= 0x80000) {
+               printk(KERN_ERR "%s: bogus load address %08x in \"%s\"\n",
+                      ap->name, ap->firmware_start, fw_name);
+               ret = -EINVAL;
+               goto out;
+       }
+
+       load_addr = be32_to_cpu(fw_data[2]);
+       if (load_addr < 0x4000 || load_addr >= 0x80000) {
+               printk(KERN_ERR "%s: bogus load address %08x in \"%s\"\n",
+                      ap->name, load_addr, fw_name);
+               ret = -EINVAL;
+               goto out;
+       }
+
        /*
-        * Do not try to clear more than 512KB or we end up seeing
-        * funny things on NICs with only 512KB SRAM
+        * Do not try to clear more than 512KiB or we end up seeing
+        * funny things on NICs with only 512KiB SRAM
         */
        ace_clear(regs, 0x2000, 0x80000-0x2000);
-       if (ACE_IS_TIGON_I(ap)) {
-               ace_copy(regs, tigonFwText, tigonFwTextAddr, tigonFwTextLen);
-               ace_copy(regs, tigonFwData, tigonFwDataAddr, tigonFwDataLen);
-               ace_copy(regs, tigonFwRodata, tigonFwRodataAddr,
-                        tigonFwRodataLen);
-               ace_clear(regs, tigonFwBssAddr, tigonFwBssLen);
-               ace_clear(regs, tigonFwSbssAddr, tigonFwSbssLen);
-       }else if (ap->version == 2) {
-               ace_clear(regs, tigon2FwBssAddr, tigon2FwBssLen);
-               ace_clear(regs, tigon2FwSbssAddr, tigon2FwSbssLen);
-               ace_copy(regs, tigon2FwText, tigon2FwTextAddr,tigon2FwTextLen);
-               ace_copy(regs, tigon2FwRodata, tigon2FwRodataAddr,
-                        tigon2FwRodataLen);
-               ace_copy(regs, tigon2FwData, tigon2FwDataAddr,tigon2FwDataLen);
-       }
-
-       return 0;
+       ace_copy(regs, &fw_data[3], load_addr, fw->size-12);
+ out:
+       release_firmware(fw);
+       return ret;
 }
 
 
index 4487f32759a4829d023225912bbe29abafc38fec..c987c9b5a137037cfed7a4e8326210104ecff091 100644 (file)
@@ -694,6 +694,10 @@ struct ace_private
        u32                     last_tx, last_std_rx, last_mini_rx;
 #endif
        int                     pci_using_dac;
+       u8                      firmware_major;
+       u8                      firmware_minor;
+       u8                      firmware_fix;
+       u32                     firmware_start;
 };
 
 
index 9f38b16ccbbd1b58f308225d15e59f94f1585a1c..134b2d60b479d435d73b75d769a783a81d259df4 100644 (file)
@@ -658,12 +658,12 @@ static int e100_self_test(struct nic *nic)
        e100_disable_irq(nic);
 
        /* Check results of self-test */
-       if(nic->mem->selftest.result != 0) {
+       if (nic->mem->selftest.result != 0) {
                DPRINTK(HW, ERR, "Self-test failed: result=0x%08X\n",
                        nic->mem->selftest.result);
                return -ETIMEDOUT;
        }
-       if(nic->mem->selftest.signature == 0) {
+       if (nic->mem->selftest.signature == 0) {
                DPRINTK(HW, ERR, "Self-test failed: timed out\n");
                return -ETIMEDOUT;
        }
@@ -684,13 +684,13 @@ static void e100_eeprom_write(struct nic *nic, u16 addr_len, u16 addr, __le16 da
        cmd_addr_data[2] = op_ewds << (addr_len - 2);
 
        /* Bit-bang cmds to write word to eeprom */
-       for(j = 0; j < 3; j++) {
+       for (j = 0; j < 3; j++) {
 
                /* Chip select */
                iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo);
                e100_write_flush(nic); udelay(4);
 
-               for(i = 31; i >= 0; i--) {
+               for (i = 31; i >= 0; i--) {
                        ctrl = (cmd_addr_data[j] & (1 << i)) ?
                                eecs | eedi : eecs;
                        iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo);
@@ -723,7 +723,7 @@ static __le16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr)
        e100_write_flush(nic); udelay(4);
 
        /* Bit-bang to read word from eeprom */
-       for(i = 31; i >= 0; i--) {
+       for (i = 31; i >= 0; i--) {
                ctrl = (cmd_addr_data & (1 << i)) ? eecs | eedi : eecs;
                iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo);
                e100_write_flush(nic); udelay(4);
@@ -734,7 +734,7 @@ static __le16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr)
                /* Eeprom drives a dummy zero to EEDO after receiving
                 * complete address.  Use this to adjust addr_len. */
                ctrl = ioread8(&nic->csr->eeprom_ctrl_lo);
-               if(!(ctrl & eedo) && i > 16) {
+               if (!(ctrl & eedo) && i > 16) {
                        *addr_len -= (i - 16);
                        i = 17;
                }
@@ -758,9 +758,9 @@ static int e100_eeprom_load(struct nic *nic)
        e100_eeprom_read(nic, &addr_len, 0);
        nic->eeprom_wc = 1 << addr_len;
 
-       for(addr = 0; addr < nic->eeprom_wc; addr++) {
+       for (addr = 0; addr < nic->eeprom_wc; addr++) {
                nic->eeprom[addr] = e100_eeprom_read(nic, &addr_len, addr);
-               if(addr < nic->eeprom_wc - 1)
+               if (addr < nic->eeprom_wc - 1)
                        checksum += le16_to_cpu(nic->eeprom[addr]);
        }
 
@@ -784,15 +784,15 @@ static int e100_eeprom_save(struct nic *nic, u16 start, u16 count)
        e100_eeprom_read(nic, &addr_len, 0);
        nic->eeprom_wc = 1 << addr_len;
 
-       if(start + count >= nic->eeprom_wc)
+       if (start + count >= nic->eeprom_wc)
                return -EINVAL;
 
-       for(addr = start; addr < start + count; addr++)
+       for (addr = start; addr < start + count; addr++)
                e100_eeprom_write(nic, addr_len, addr, nic->eeprom[addr]);
 
        /* The checksum, stored in the last word, is calculated such that
         * the sum of words should be 0xBABA */
-       for(addr = 0; addr < nic->eeprom_wc - 1; addr++)
+       for (addr = 0; addr < nic->eeprom_wc - 1; addr++)
                checksum += le16_to_cpu(nic->eeprom[addr]);
        nic->eeprom[nic->eeprom_wc - 1] = cpu_to_le16(0xBABA - checksum);
        e100_eeprom_write(nic, addr_len, nic->eeprom_wc - 1,
@@ -812,19 +812,19 @@ static int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr)
        spin_lock_irqsave(&nic->cmd_lock, flags);
 
        /* Previous command is accepted when SCB clears */
-       for(i = 0; i < E100_WAIT_SCB_TIMEOUT; i++) {
-               if(likely(!ioread8(&nic->csr->scb.cmd_lo)))
+       for (i = 0; i < E100_WAIT_SCB_TIMEOUT; i++) {
+               if (likely(!ioread8(&nic->csr->scb.cmd_lo)))
                        break;
                cpu_relax();
-               if(unlikely(i > E100_WAIT_SCB_FAST))
+               if (unlikely(i > E100_WAIT_SCB_FAST))
                        udelay(5);
        }
-       if(unlikely(i == E100_WAIT_SCB_TIMEOUT)) {
+       if (unlikely(i == E100_WAIT_SCB_TIMEOUT)) {
                err = -EAGAIN;
                goto err_unlock;
        }
 
-       if(unlikely(cmd != cuc_resume))
+       if (unlikely(cmd != cuc_resume))
                iowrite32(dma_addr, &nic->csr->scb.gen_ptr);
        iowrite8(cmd, &nic->csr->scb.cmd_lo);
 
@@ -843,7 +843,7 @@ static int e100_exec_cb(struct nic *nic, struct sk_buff *skb,
 
        spin_lock_irqsave(&nic->cb_lock, flags);
 
-       if(unlikely(!nic->cbs_avail)) {
+       if (unlikely(!nic->cbs_avail)) {
                err = -ENOMEM;
                goto err_unlock;
        }
@@ -853,7 +853,7 @@ static int e100_exec_cb(struct nic *nic, struct sk_buff *skb,
        nic->cbs_avail--;
        cb->skb = skb;
 
-       if(unlikely(!nic->cbs_avail))
+       if (unlikely(!nic->cbs_avail))
                err = -ENOSPC;
 
        cb_prepare(nic, cb, skb);
@@ -864,15 +864,15 @@ static int e100_exec_cb(struct nic *nic, struct sk_buff *skb,
        wmb();
        cb->prev->command &= cpu_to_le16(~cb_s);
 
-       while(nic->cb_to_send != nic->cb_to_use) {
-               if(unlikely(e100_exec_cmd(nic, nic->cuc_cmd,
+       while (nic->cb_to_send != nic->cb_to_use) {
+               if (unlikely(e100_exec_cmd(nic, nic->cuc_cmd,
                        nic->cb_to_send->dma_addr))) {
                        /* Ok, here's where things get sticky.  It's
                         * possible that we can't schedule the command
                         * because the controller is too busy, so
                         * let's just queue the command and try again
                         * when another command is scheduled. */
-                       if(err == -ENOSPC) {
+                       if (err == -ENOSPC) {
                                //request a reset
                                schedule_work(&nic->tx_timeout_task);
                        }
@@ -945,7 +945,7 @@ static void e100_get_defaults(struct nic *nic)
 
        /* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */
        nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->pdev->revision;
-       if(nic->mac == mac_unknown)
+       if (nic->mac == mac_unknown)
                nic->mac = mac_82557_D100_A;
 
        nic->params.rfds = rfds;
@@ -1008,23 +1008,23 @@ static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb)
        config->adaptive_ifs = nic->adaptive_ifs;
        config->loopback = nic->loopback;
 
-       if(nic->mii.force_media && nic->mii.full_duplex)
+       if (nic->mii.force_media && nic->mii.full_duplex)
                config->full_duplex_force = 0x1;        /* 1=force, 0=auto */
 
-       if(nic->flags & promiscuous || nic->loopback) {
+       if (nic->flags & promiscuous || nic->loopback) {
                config->rx_save_bad_frames = 0x1;       /* 1=save, 0=discard */
                config->rx_discard_short_frames = 0x0;  /* 1=discard, 0=save */
                config->promiscuous_mode = 0x1;         /* 1=on, 0=off */
        }
 
-       if(nic->flags & multicast_all)
+       if (nic->flags & multicast_all)
                config->multicast_all = 0x1;            /* 1=accept, 0=no */
 
        /* disable WoL when up */
-       if(netif_running(nic->netdev) || !(nic->flags & wol_magic))
+       if (netif_running(nic->netdev) || !(nic->flags & wol_magic))
                config->magic_packet_disable = 0x1;     /* 1=off, 0=on */
 
-       if(nic->mac >= mac_82558_D101_A4) {
+       if (nic->mac >= mac_82558_D101_A4) {
                config->fc_disable = 0x1;       /* 1=Tx fc off, 0=Tx fc on */
                config->mwi_enable = 0x1;       /* 1=enable, 0=disable */
                config->standard_tcb = 0x0;     /* 1=standard, 0=extended */
@@ -1369,21 +1369,21 @@ static int e100_phy_init(struct nic *nic)
        u16 bmcr, stat, id_lo, id_hi, cong;
 
        /* Discover phy addr by searching addrs in order {1,0,2,..., 31} */
-       for(addr = 0; addr < 32; addr++) {
+       for (addr = 0; addr < 32; addr++) {
                nic->mii.phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr;
                bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR);
                stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR);
                stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR);
-               if(!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0))))
+               if (!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0))))
                        break;
        }
        DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id);
-       if(addr == 32)
+       if (addr == 32)
                return -EAGAIN;
 
        /* Selected the phy and isolate the rest */
-       for(addr = 0; addr < 32; addr++) {
-               if(addr != nic->mii.phy_id) {
+       for (addr = 0; addr < 32; addr++) {
+               if (addr != nic->mii.phy_id) {
                        mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE);
                } else {
                        bmcr = mdio_read(netdev, addr, MII_BMCR);
@@ -1400,7 +1400,7 @@ static int e100_phy_init(struct nic *nic)
 
        /* Handle National tx phys */
 #define NCS_PHY_MODEL_MASK     0xFFF0FFFF
-       if((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) {
+       if ((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) {
                /* Disable congestion control */
                cong = mdio_read(netdev, nic->mii.phy_id, MII_NSC_CONG);
                cong |= NSC_CONG_TXREADY;
@@ -1408,7 +1408,7 @@ static int e100_phy_init(struct nic *nic)
                mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong);
        }
 
-       if((nic->mac >= mac_82550_D102) || ((nic->flags & ich) &&
+       if ((nic->mac >= mac_82550_D102) || ((nic->flags & ich) &&
           (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) &&
                !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) {
                /* enable/disable MDI/MDI-X auto-switching. */
@@ -1426,25 +1426,25 @@ static int e100_hw_init(struct nic *nic)
        e100_hw_reset(nic);
 
        DPRINTK(HW, ERR, "e100_hw_init\n");
-       if(!in_interrupt() && (err = e100_self_test(nic)))
+       if (!in_interrupt() && (err = e100_self_test(nic)))
                return err;
 
-       if((err = e100_phy_init(nic)))
+       if ((err = e100_phy_init(nic)))
                return err;
-       if((err = e100_exec_cmd(nic, cuc_load_base, 0)))
+       if ((err = e100_exec_cmd(nic, cuc_load_base, 0)))
                return err;
-       if((err = e100_exec_cmd(nic, ruc_load_base, 0)))
+       if ((err = e100_exec_cmd(nic, ruc_load_base, 0)))
                return err;
        if ((err = e100_exec_cb_wait(nic, NULL, e100_setup_ucode)))
                return err;
-       if((err = e100_exec_cb(nic, NULL, e100_configure)))
+       if ((err = e100_exec_cb(nic, NULL, e100_configure)))
                return err;
-       if((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr)))
+       if ((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr)))
                return err;
-       if((err = e100_exec_cmd(nic, cuc_dump_addr,
+       if ((err = e100_exec_cmd(nic, cuc_dump_addr,
                nic->dma_addr + offsetof(struct mem, stats))))
                return err;
-       if((err = e100_exec_cmd(nic, cuc_dump_reset, 0)))
+       if ((err = e100_exec_cmd(nic, cuc_dump_reset, 0)))
                return err;
 
        e100_disable_irq(nic);
@@ -1460,7 +1460,7 @@ static void e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb)
 
        cb->command = cpu_to_le16(cb_multi);
        cb->u.multi.count = cpu_to_le16(count * ETH_ALEN);
-       for(i = 0; list && i < count; i++, list = list->next)
+       for (i = 0; list && i < count; i++, list = list->next)
                memcpy(&cb->u.multi.addr[i*ETH_ALEN], &list->dmi_addr,
                        ETH_ALEN);
 }
@@ -1472,12 +1472,12 @@ static void e100_set_multicast_list(struct net_device *netdev)
        DPRINTK(HW, DEBUG, "mc_count=%d, flags=0x%04X\n",
                netdev->mc_count, netdev->flags);
 
-       if(netdev->flags & IFF_PROMISC)
+       if (netdev->flags & IFF_PROMISC)
                nic->flags |= promiscuous;
        else
                nic->flags &= ~promiscuous;
 
-       if(netdev->flags & IFF_ALLMULTI ||
+       if (netdev->flags & IFF_ALLMULTI ||
                netdev->mc_count > E100_MAX_MULTICAST_ADDRS)
                nic->flags |= multicast_all;
        else
@@ -1500,7 +1500,7 @@ static void e100_update_stats(struct nic *nic)
         * complete, so we're always waiting for results of the
         * previous command. */
 
-       if(*complete == cpu_to_le32(cuc_dump_reset_complete)) {
+       if (*complete == cpu_to_le32(cuc_dump_reset_complete)) {
                *complete = 0;
                nic->tx_frames = le32_to_cpu(s->tx_good_frames);
                nic->tx_collisions = le32_to_cpu(s->tx_total_collisions);
@@ -1527,12 +1527,12 @@ static void e100_update_stats(struct nic *nic)
                        le32_to_cpu(s->tx_single_collisions);
                nic->tx_multiple_collisions +=
                        le32_to_cpu(s->tx_multiple_collisions);
-               if(nic->mac >= mac_82558_D101_A4) {
+               if (nic->mac >= mac_82558_D101_A4) {
                        nic->tx_fc_pause += le32_to_cpu(s->fc_xmt_pause);
                        nic->rx_fc_pause += le32_to_cpu(s->fc_rcv_pause);
                        nic->rx_fc_unsupported +=
                                le32_to_cpu(s->fc_rcv_unsupported);
-                       if(nic->mac >= mac_82559_D101M) {
+                       if (nic->mac >= mac_82559_D101M) {
                                nic->tx_tco_frames +=
                                        le16_to_cpu(s->xmt_tco_frames);
                                nic->rx_tco_frames +=
@@ -1542,7 +1542,7 @@ static void e100_update_stats(struct nic *nic)
        }
 
 
-       if(e100_exec_cmd(nic, cuc_dump_reset, 0))
+       if (e100_exec_cmd(nic, cuc_dump_reset, 0))
                DPRINTK(TX_ERR, DEBUG, "exec cuc_dump_reset failed\n");
 }
 
@@ -1551,19 +1551,19 @@ static void e100_adjust_adaptive_ifs(struct nic *nic, int speed, int duplex)
        /* Adjust inter-frame-spacing (IFS) between two transmits if
         * we're getting collisions on a half-duplex connection. */
 
-       if(duplex == DUPLEX_HALF) {
+       if (duplex == DUPLEX_HALF) {
                u32 prev = nic->adaptive_ifs;
                u32 min_frames = (speed == SPEED_100) ? 1000 : 100;
 
-               if((nic->tx_frames / 32 < nic->tx_collisions) &&
+               if ((nic->tx_frames / 32 < nic->tx_collisions) &&
                   (nic->tx_frames > min_frames)) {
-                       if(nic->adaptive_ifs < 60)
+                       if (nic->adaptive_ifs < 60)
                                nic->adaptive_ifs += 5;
                } else if (nic->tx_frames < min_frames) {
-                       if(nic->adaptive_ifs >= 5)
+                       if (nic->adaptive_ifs >= 5)
                                nic->adaptive_ifs -= 5;
                }
-               if(nic->adaptive_ifs != prev)
+               if (nic->adaptive_ifs != prev)
                        e100_exec_cb(nic, NULL, e100_configure);
        }
 }
@@ -1579,12 +1579,12 @@ static void e100_watchdog(unsigned long data)
 
        mii_ethtool_gset(&nic->mii, &cmd);
 
-       if(mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) {
+       if (mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) {
                printk(KERN_INFO "e100: %s NIC Link is Up %s Mbps %s Duplex\n",
                       nic->netdev->name,
                       cmd.speed == SPEED_100 ? "100" : "10",
                       cmd.duplex == DUPLEX_FULL ? "Full" : "Half");
-       } else if(!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) {
+       } else if (!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) {
                printk(KERN_INFO "e100: %s NIC Link is Down\n",
                       nic->netdev->name);
        }
@@ -1604,11 +1604,11 @@ static void e100_watchdog(unsigned long data)
        e100_update_stats(nic);
        e100_adjust_adaptive_ifs(nic, cmd.speed, cmd.duplex);
 
-       if(nic->mac <= mac_82557_D100_C)
+       if (nic->mac <= mac_82557_D100_C)
                /* Issue a multicast command to workaround a 557 lock up */
                e100_set_multicast_list(nic->netdev);
 
-       if(nic->flags & ich && cmd.speed==SPEED_10 && cmd.duplex==DUPLEX_HALF)
+       if (nic->flags & ich && cmd.speed==SPEED_10 && cmd.duplex==DUPLEX_HALF)
                /* Need SW workaround for ICH[x] 10Mbps/half duplex Tx hang. */
                nic->flags |= ich_10h_workaround;
        else
@@ -1623,7 +1623,7 @@ static void e100_xmit_prepare(struct nic *nic, struct cb *cb,
 {
        cb->command = nic->tx_command;
        /* interrupt every 16 packets regardless of delay */
-       if((nic->cbs_avail & ~15) == nic->cbs_avail)
+       if ((nic->cbs_avail & ~15) == nic->cbs_avail)
                cb->command |= cpu_to_le16(cb_i);
        cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd);
        cb->u.tcb.tcb_byte_count = 0;
@@ -1640,18 +1640,18 @@ static int e100_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        struct nic *nic = netdev_priv(netdev);
        int err;
 
-       if(nic->flags & ich_10h_workaround) {
+       if (nic->flags & ich_10h_workaround) {
                /* SW workaround for ICH[x] 10Mbps/half duplex Tx hang.
                   Issue a NOP command followed by a 1us delay before
                   issuing the Tx command. */
-               if(e100_exec_cmd(nic, cuc_nop, 0))
+               if (e100_exec_cmd(nic, cuc_nop, 0))
                        DPRINTK(TX_ERR, DEBUG, "exec cuc_nop failed\n");
                udelay(1);
        }
 
        err = e100_exec_cb(nic, skb, e100_xmit_prepare);
 
-       switch(err) {
+       switch (err) {
        case -ENOSPC:
                /* We queued the skb, but now we're out of space. */
                DPRINTK(TX_ERR, DEBUG, "No space for CB\n");
@@ -1677,14 +1677,14 @@ static int e100_tx_clean(struct nic *nic)
        spin_lock(&nic->cb_lock);
 
        /* Clean CBs marked complete */
-       for(cb = nic->cb_to_clean;
+       for (cb = nic->cb_to_clean;
            cb->status & cpu_to_le16(cb_complete);
            cb = nic->cb_to_clean = cb->next) {
                DPRINTK(TX_DONE, DEBUG, "cb[%d]->status = 0x%04X\n",
                        (int)(((void*)cb - (void*)nic->cbs)/sizeof(struct cb)),
                        cb->status);
 
-               if(likely(cb->skb != NULL)) {
+               if (likely(cb->skb != NULL)) {
                        dev->stats.tx_packets++;
                        dev->stats.tx_bytes += cb->skb->len;
 
@@ -1703,7 +1703,7 @@ static int e100_tx_clean(struct nic *nic)
        spin_unlock(&nic->cb_lock);
 
        /* Recover from running out of Tx resources in xmit_frame */
-       if(unlikely(tx_cleaned && netif_queue_stopped(nic->netdev)))
+       if (unlikely(tx_cleaned && netif_queue_stopped(nic->netdev)))
                netif_wake_queue(nic->netdev);
 
        return tx_cleaned;
@@ -1711,10 +1711,10 @@ static int e100_tx_clean(struct nic *nic)
 
 static void e100_clean_cbs(struct nic *nic)
 {
-       if(nic->cbs) {
-               while(nic->cbs_avail != nic->params.cbs.count) {
+       if (nic->cbs) {
+               while (nic->cbs_avail != nic->params.cbs.count) {
                        struct cb *cb = nic->cb_to_clean;
-                       if(cb->skb) {
+                       if (cb->skb) {
                                pci_unmap_single(nic->pdev,
                                        le32_to_cpu(cb->u.tcb.tbd.buf_addr),
                                        le16_to_cpu(cb->u.tcb.tbd.size),
@@ -1746,10 +1746,10 @@ static int e100_alloc_cbs(struct nic *nic)
 
        nic->cbs = pci_alloc_consistent(nic->pdev,
                sizeof(struct cb) * count, &nic->cbs_dma_addr);
-       if(!nic->cbs)
+       if (!nic->cbs)
                return -ENOMEM;
 
-       for(cb = nic->cbs, i = 0; i < count; cb++, i++) {
+       for (cb = nic->cbs, i = 0; i < count; cb++, i++) {
                cb->next = (i + 1 < count) ? cb + 1 : nic->cbs;
                cb->prev = (i == 0) ? nic->cbs + count - 1 : cb - 1;
 
@@ -1767,14 +1767,14 @@ static int e100_alloc_cbs(struct nic *nic)
 
 static inline void e100_start_receiver(struct nic *nic, struct rx *rx)
 {
-       if(!nic->rxs) return;
-       if(RU_SUSPENDED != nic->ru_running) return;
+       if (!nic->rxs) return;
+       if (RU_SUSPENDED != nic->ru_running) return;
 
        /* handle init time starts */
-       if(!rx) rx = nic->rxs;
+       if (!rx) rx = nic->rxs;
 
        /* (Re)start RU if suspended or idle and RFA is non-NULL */
-       if(rx->skb) {
+       if (rx->skb) {
                e100_exec_cmd(nic, ruc_start, rx->dma_addr);
                nic->ru_running = RU_RUNNING;
        }
@@ -1783,7 +1783,7 @@ static inline void e100_start_receiver(struct nic *nic, struct rx *rx)
 #define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN)
 static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx)
 {
-       if(!(rx->skb = netdev_alloc_skb(nic->netdev, RFD_BUF_LEN + NET_IP_ALIGN)))
+       if (!(rx->skb = netdev_alloc_skb(nic->netdev, RFD_BUF_LEN + NET_IP_ALIGN)))
                return -ENOMEM;
 
        /* Align, init, and map the RFD. */
@@ -1820,7 +1820,7 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx,
        struct rfd *rfd = (struct rfd *)skb->data;
        u16 rfd_status, actual_size;
 
-       if(unlikely(work_done && *work_done >= work_to_do))
+       if (unlikely(work_done && *work_done >= work_to_do))
                return -EAGAIN;
 
        /* Need to sync before taking a peek at cb_complete bit */
@@ -1847,7 +1847,7 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx,
 
        /* Get actual data size */
        actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF;
-       if(unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd)))
+       if (unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd)))
                actual_size = RFD_BUF_LEN - sizeof(struct rfd);
 
        /* Get data */
@@ -1872,10 +1872,10 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx,
        skb_put(skb, actual_size);
        skb->protocol = eth_type_trans(skb, nic->netdev);
 
-       if(unlikely(!(rfd_status & cb_ok))) {
+       if (unlikely(!(rfd_status & cb_ok))) {
                /* Don't indicate if hardware indicates errors */
                dev_kfree_skb_any(skb);
-       } else if(actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) {
+       } else if (actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) {
                /* Don't indicate oversized frames */
                nic->rx_over_length_errors++;
                dev_kfree_skb_any(skb);
@@ -1883,7 +1883,7 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx,
                dev->stats.rx_packets++;
                dev->stats.rx_bytes += actual_size;
                netif_receive_skb(skb);
-               if(work_done)
+               if (work_done)
                        (*work_done)++;
        }
 
@@ -1901,7 +1901,7 @@ static void e100_rx_clean(struct nic *nic, unsigned int *work_done,
        struct rfd *old_before_last_rfd, *new_before_last_rfd;
 
        /* Indicate newly arrived packets */
-       for(rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) {
+       for (rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) {
                err = e100_rx_indicate(nic, rx, work_done, work_to_do);
                /* Hit quota or no more to clean */
                if (-EAGAIN == err || -ENODATA == err)
@@ -1922,8 +1922,8 @@ static void e100_rx_clean(struct nic *nic, unsigned int *work_done,
        old_before_last_rfd = (struct rfd *)old_before_last_rx->skb->data;
 
        /* Alloc new skbs to refill list */
-       for(rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) {
-               if(unlikely(e100_rx_alloc_skb(nic, rx)))
+       for (rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) {
+               if (unlikely(e100_rx_alloc_skb(nic, rx)))
                        break; /* Better luck next time (see watchdog) */
        }
 
@@ -1959,11 +1959,11 @@ static void e100_rx_clean(struct nic *nic, unsigned int *work_done,
                        PCI_DMA_BIDIRECTIONAL);
        }
 
-       if(restart_required) {
+       if (restart_required) {
                // ack the rnr?
                iowrite8(stat_ack_rnr, &nic->csr->scb.stat_ack);
                e100_start_receiver(nic, nic->rx_to_clean);
-               if(work_done)
+               if (work_done)
                        (*work_done)++;
        }
 }
@@ -1975,9 +1975,9 @@ static void e100_rx_clean_list(struct nic *nic)
 
        nic->ru_running = RU_UNINITIALIZED;
 
-       if(nic->rxs) {
-               for(rx = nic->rxs, i = 0; i < count; rx++, i++) {
-                       if(rx->skb) {
+       if (nic->rxs) {
+               for (rx = nic->rxs, i = 0; i < count; rx++, i++) {
+                       if (rx->skb) {
                                pci_unmap_single(nic->pdev, rx->dma_addr,
                                        RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL);
                                dev_kfree_skb(rx->skb);
@@ -1999,13 +1999,13 @@ static int e100_rx_alloc_list(struct nic *nic)
        nic->rx_to_use = nic->rx_to_clean = NULL;
        nic->ru_running = RU_UNINITIALIZED;
 
-       if(!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC)))
+       if (!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC)))
                return -ENOMEM;
 
-       for(rx = nic->rxs, i = 0; i < count; rx++, i++) {
+       for (rx = nic->rxs, i = 0; i < count; rx++, i++) {
                rx->next = (i + 1 < count) ? rx + 1 : nic->rxs;
                rx->prev = (i == 0) ? nic->rxs + count - 1 : rx - 1;
-               if(e100_rx_alloc_skb(nic, rx)) {
+               if (e100_rx_alloc_skb(nic, rx)) {
                        e100_rx_clean_list(nic);
                        return -ENOMEM;
                }
@@ -2038,7 +2038,7 @@ static irqreturn_t e100_intr(int irq, void *dev_id)
 
        DPRINTK(INTR, DEBUG, "stat_ack = 0x%02X\n", stat_ack);
 
-       if(stat_ack == stat_ack_not_ours ||     /* Not our interrupt */
+       if (stat_ack == stat_ack_not_ours ||    /* Not our interrupt */
           stat_ack == stat_ack_not_present)    /* Hardware is ejected */
                return IRQ_NONE;
 
@@ -2046,10 +2046,10 @@ static irqreturn_t e100_intr(int irq, void *dev_id)
        iowrite8(stat_ack, &nic->csr->scb.stat_ack);
 
        /* We hit Receive No Resource (RNR); restart RU after cleaning */
-       if(stat_ack & stat_ack_rnr)
+       if (stat_ack & stat_ack_rnr)
                nic->ru_running = RU_SUSPENDED;
 
-       if(likely(netif_rx_schedule_prep(&nic->napi))) {
+       if (likely(netif_rx_schedule_prep(&nic->napi))) {
                e100_disable_irq(nic);
                __netif_rx_schedule(&nic->napi);
        }
@@ -2102,7 +2102,7 @@ static int e100_set_mac_address(struct net_device *netdev, void *p)
 
 static int e100_change_mtu(struct net_device *netdev, int new_mtu)
 {
-       if(new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN)
+       if (new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN)
                return -EINVAL;
        netdev->mtu = new_mtu;
        return 0;
@@ -2121,16 +2121,16 @@ static int e100_up(struct nic *nic)
 {
        int err;
 
-       if((err = e100_rx_alloc_list(nic)))
+       if ((err = e100_rx_alloc_list(nic)))
                return err;
-       if((err = e100_alloc_cbs(nic)))
+       if ((err = e100_alloc_cbs(nic)))
                goto err_rx_clean_list;
-       if((err = e100_hw_init(nic)))
+       if ((err = e100_hw_init(nic)))
                goto err_clean_cbs;
        e100_set_multicast_list(nic->netdev);
        e100_start_receiver(nic, NULL);
        mod_timer(&nic->watchdog, jiffies);
-       if((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED,
+       if ((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED,
                nic->netdev->name, nic->netdev)))
                goto err_no_irq;
        netif_wake_queue(nic->netdev);
@@ -2192,26 +2192,26 @@ static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode)
         * in loopback mode, and the test passes if the received
         * packet compares byte-for-byte to the transmitted packet. */
 
-       if((err = e100_rx_alloc_list(nic)))
+       if ((err = e100_rx_alloc_list(nic)))
                return err;
-       if((err = e100_alloc_cbs(nic)))
+       if ((err = e100_alloc_cbs(nic)))
                goto err_clean_rx;
 
        /* ICH PHY loopback is broken so do MAC loopback instead */
-       if(nic->flags & ich && loopback_mode == lb_phy)
+       if (nic->flags & ich && loopback_mode == lb_phy)
                loopback_mode = lb_mac;
 
        nic->loopback = loopback_mode;
-       if((err = e100_hw_init(nic)))
+       if ((err = e100_hw_init(nic)))
                goto err_loopback_none;
 
-       if(loopback_mode == lb_phy)
+       if (loopback_mode == lb_phy)
                mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR,
                        BMCR_LOOPBACK);
 
        e100_start_receiver(nic, NULL);
 
-       if(!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) {
+       if (!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) {
                err = -ENOMEM;
                goto err_loopback_none;
        }
@@ -2224,7 +2224,7 @@ static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode)
        pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr,
                        RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL);
 
-       if(memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd),
+       if (memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd),
           skb->data, ETH_DATA_LEN))
                err = -EAGAIN;
 
@@ -2301,7 +2301,7 @@ static void e100_get_regs(struct net_device *netdev,
        buff[0] = ioread8(&nic->csr->scb.cmd_hi) << 24 |
                ioread8(&nic->csr->scb.cmd_lo) << 16 |
                ioread16(&nic->csr->scb.status);
-       for(i = E100_PHY_REGS; i >= 0; i--)
+       for (i = E100_PHY_REGS; i >= 0; i--)
                buff[1 + E100_PHY_REGS - i] =
                        mdio_read(netdev, nic->mii.phy_id, i);
        memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf));
@@ -2326,7 +2326,7 @@ static int e100_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
            !device_can_wakeup(&nic->pdev->dev))
                return -EOPNOTSUPP;
 
-       if(wol->wolopts)
+       if (wol->wolopts)
                nic->flags |= wol_magic;
        else
                nic->flags &= ~wol_magic;
@@ -2385,7 +2385,7 @@ static int e100_set_eeprom(struct net_device *netdev,
 {
        struct nic *nic = netdev_priv(netdev);
 
-       if(eeprom->magic != E100_EEPROM_MAGIC)
+       if (eeprom->magic != E100_EEPROM_MAGIC)
                return -EINVAL;
 
        memcpy(&((u8 *)nic->eeprom)[eeprom->offset], bytes, eeprom->len);
@@ -2421,7 +2421,7 @@ static int e100_set_ringparam(struct net_device *netdev,
        if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
                return -EINVAL;
 
-       if(netif_running(netdev))
+       if (netif_running(netdev))
                e100_down(nic);
        rfds->count = max(ring->rx_pending, rfds->min);
        rfds->count = min(rfds->count, rfds->max);
@@ -2429,7 +2429,7 @@ static int e100_set_ringparam(struct net_device *netdev,
        cbs->count = min(cbs->count, cbs->max);
        DPRINTK(DRV, INFO, "Ring Param settings: rx: %d, tx %d\n",
                rfds->count, cbs->count);
-       if(netif_running(netdev))
+       if (netif_running(netdev))
                e100_up(nic);
 
        return 0;
@@ -2454,12 +2454,12 @@ static void e100_diag_test(struct net_device *netdev,
        memset(data, 0, E100_TEST_LEN * sizeof(u64));
        data[0] = !mii_link_ok(&nic->mii);
        data[1] = e100_eeprom_load(nic);
-       if(test->flags & ETH_TEST_FL_OFFLINE) {
+       if (test->flags & ETH_TEST_FL_OFFLINE) {
 
                /* save speed, duplex & autoneg settings */
                err = mii_ethtool_gset(&nic->mii, &cmd);
 
-               if(netif_running(netdev))
+               if (netif_running(netdev))
                        e100_down(nic);
                data[2] = e100_self_test(nic);
                data[3] = e100_loopback_test(nic, lb_mac);
@@ -2468,10 +2468,10 @@ static void e100_diag_test(struct net_device *netdev,
                /* restore speed, duplex & autoneg settings */
                err = mii_ethtool_sset(&nic->mii, &cmd);
 
-               if(netif_running(netdev))
+               if (netif_running(netdev))
                        e100_up(nic);
        }
-       for(i = 0; i < E100_TEST_LEN; i++)
+       for (i = 0; i < E100_TEST_LEN; i++)
                test->flags |= data[i] ? ETH_TEST_FL_FAILED : 0;
 
        msleep_interruptible(4 * 1000);
@@ -2481,7 +2481,7 @@ static int e100_phys_id(struct net_device *netdev, u32 data)
 {
        struct nic *nic = netdev_priv(netdev);
 
-       if(!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))
+       if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))
                data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ);
        mod_timer(&nic->blink_timer, jiffies);
        msleep_interruptible(data * 1000);
@@ -2524,7 +2524,7 @@ static void e100_get_ethtool_stats(struct net_device *netdev,
        struct nic *nic = netdev_priv(netdev);
        int i;
 
-       for(i = 0; i < E100_NET_STATS_LEN; i++)
+       for (i = 0; i < E100_NET_STATS_LEN; i++)
                data[i] = ((unsigned long *)&netdev->stats)[i];
 
        data[i++] = nic->tx_deferred;
@@ -2539,7 +2539,7 @@ static void e100_get_ethtool_stats(struct net_device *netdev,
 
 static void e100_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
 {
-       switch(stringset) {
+       switch (stringset) {
        case ETH_SS_TEST:
                memcpy(data, *e100_gstrings_test, sizeof(e100_gstrings_test));
                break;
@@ -2589,7 +2589,7 @@ static int e100_alloc(struct nic *nic)
 
 static void e100_free(struct nic *nic)
 {
-       if(nic->mem) {
+       if (nic->mem) {
                pci_free_consistent(nic->pdev, sizeof(struct mem),
                        nic->mem, nic->dma_addr);
                nic->mem = NULL;
@@ -2602,7 +2602,7 @@ static int e100_open(struct net_device *netdev)
        int err = 0;
 
        netif_carrier_off(netdev);
-       if((err = e100_up(nic)))
+       if ((err = e100_up(nic)))
                DPRINTK(IFUP, ERR, "Cannot open interface, aborting.\n");
        return err;
 }
@@ -2635,8 +2635,8 @@ static int __devinit e100_probe(struct pci_dev *pdev,
        struct nic *nic;
        int err;
 
-       if(!(netdev = alloc_etherdev(sizeof(struct nic)))) {
-               if(((1 << debug) - 1) & NETIF_MSG_PROBE)
+       if (!(netdev = alloc_etherdev(sizeof(struct nic)))) {
+               if (((1 << debug) - 1) & NETIF_MSG_PROBE)
                        printk(KERN_ERR PFX "Etherdev alloc failed, abort.\n");
                return -ENOMEM;
        }
@@ -2653,24 +2653,24 @@ static int __devinit e100_probe(struct pci_dev *pdev,
        nic->msg_enable = (1 << debug) - 1;
        pci_set_drvdata(pdev, netdev);
 
-       if((err = pci_enable_device(pdev))) {
+       if ((err = pci_enable_device(pdev))) {
                DPRINTK(PROBE, ERR, "Cannot enable PCI device, aborting.\n");
                goto err_out_free_dev;
        }
 
-       if(!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
+       if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
                DPRINTK(PROBE, ERR, "Cannot find proper PCI device "
                        "base address, aborting.\n");
                err = -ENODEV;
                goto err_out_disable_pdev;
        }
 
-       if((err = pci_request_regions(pdev, DRV_NAME))) {
+       if ((err = pci_request_regions(pdev, DRV_NAME))) {
                DPRINTK(PROBE, ERR, "Cannot obtain PCI resources, aborting.\n");
                goto err_out_disable_pdev;
        }
 
-       if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) {
+       if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) {
                DPRINTK(PROBE, ERR, "No usable DMA configuration, aborting.\n");
                goto err_out_free_res;
        }
@@ -2681,13 +2681,13 @@ static int __devinit e100_probe(struct pci_dev *pdev,
                DPRINTK(PROBE, INFO, "using i/o access mode\n");
 
        nic->csr = pci_iomap(pdev, (use_io ? 1 : 0), sizeof(struct csr));
-       if(!nic->csr) {
+       if (!nic->csr) {
                DPRINTK(PROBE, ERR, "Cannot map device registers, aborting.\n");
                err = -ENOMEM;
                goto err_out_free_res;
        }
 
-       if(ent->driver_data)
+       if (ent->driver_data)
                nic->flags |= ich;
        else
                nic->flags &= ~ich;
@@ -2715,12 +2715,12 @@ static int __devinit e100_probe(struct pci_dev *pdev,
 
        INIT_WORK(&nic->tx_timeout_task, e100_tx_timeout_task);
 
-       if((err = e100_alloc(nic))) {
+       if ((err = e100_alloc(nic))) {
                DPRINTK(PROBE, ERR, "Cannot alloc driver memory, aborting.\n");
                goto err_out_iounmap;
        }
 
-       if((err = e100_eeprom_load(nic)))
+       if ((err = e100_eeprom_load(nic)))
                goto err_out_free;
 
        e100_phy_init(nic);
@@ -2740,7 +2740,7 @@ static int __devinit e100_probe(struct pci_dev *pdev,
        }
 
        /* Wol magic packet can be enabled from eeprom */
-       if((nic->mac >= mac_82558_D101_A4) &&
+       if ((nic->mac >= mac_82558_D101_A4) &&
           (nic->eeprom[eeprom_id] & eeprom_id_wol)) {
                nic->flags |= wol_magic;
                device_set_wakeup_enable(&pdev->dev, true);
@@ -2750,7 +2750,7 @@ static int __devinit e100_probe(struct pci_dev *pdev,
        pci_pme_active(pdev, false);
 
        strcpy(netdev->name, "eth%d");
-       if((err = register_netdev(netdev))) {
+       if ((err = register_netdev(netdev))) {
                DPRINTK(PROBE, ERR, "Cannot register net device, aborting.\n");
                goto err_out_free;
        }
@@ -2779,7 +2779,7 @@ static void __devexit e100_remove(struct pci_dev *pdev)
 {
        struct net_device *netdev = pci_get_drvdata(pdev);
 
-       if(netdev) {
+       if (netdev) {
                struct nic *nic = netdev_priv(netdev);
                unregister_netdev(netdev);
                e100_free(nic);
@@ -2932,7 +2932,7 @@ static struct pci_driver e100_driver = {
 
 static int __init e100_init_module(void)
 {
-       if(((1 << debug) - 1) & NETIF_MSG_DRV) {
+       if (((1 << debug) - 1) & NETIF_MSG_DRV) {
                printk(KERN_INFO PFX "%s, %s\n", DRV_DESCRIPTION, DRV_VERSION);
                printk(KERN_INFO PFX "%s\n", DRV_COPYRIGHT);
        }
index 9930d5f8b9e11b199459e69936c64a6900ffe4cb..6271b9411ccf08c079046059a00d4584746a9d83 100644 (file)
@@ -478,7 +478,7 @@ struct ehea_port {
        int num_add_tx_qps;
        int num_mcs;
        int resets;
-       u64 flags;
+       unsigned long flags;
        u64 mac_addr;
        u32 logical_port_id;
        u32 port_speed;
@@ -510,7 +510,6 @@ void ehea_set_ethtool_ops(struct net_device *netdev);
 int ehea_sense_port_attr(struct ehea_port *port);
 int ehea_set_portspeed(struct ehea_port *port, u32 port_speed);
 
-extern u64 ehea_driver_flags;
 extern struct work_struct ehea_rereg_mr_task;
 
 #endif /* __EHEA_H__ */
index a2f1905a23dfdc2d581b8751f631515bf326a448..e3131ea629cd14752c18b6511142c7b7966757bc 100644 (file)
@@ -99,7 +99,7 @@ MODULE_PARM_DESC(use_lro, " Large Receive Offload, 1: enable, 0: disable, "
 
 static int port_name_cnt;
 static LIST_HEAD(adapter_list);
-u64 ehea_driver_flags;
+static unsigned long ehea_driver_flags;
 struct work_struct ehea_rereg_mr_task;
 static DEFINE_MUTEX(dlpar_mem_lock);
 struct ehea_fw_handle_array ehea_fw_handles;
index b0ef46c51a9d556069c38ed97d0cdf3086555d6f..cefe1d98f93e91b4b92c0143db1da9b43513fd5a 100644 (file)
@@ -944,7 +944,7 @@ static void enc28j60_hw_rx(struct net_device *ndev)
        if (netif_msg_rx_status(priv))
                enc28j60_dump_rsv(priv, __func__, next_packet, len, rxstat);
 
-       if (!RSV_GETBIT(rxstat, RSV_RXOK)) {
+       if (!RSV_GETBIT(rxstat, RSV_RXOK) || len > MAX_FRAMELEN) {
                if (netif_msg_rx_err(priv))
                        dev_err(&ndev->dev, "Rx Error (%04x)\n", rxstat);
                ndev->stats.rx_errors++;
@@ -952,6 +952,8 @@ static void enc28j60_hw_rx(struct net_device *ndev)
                        ndev->stats.rx_crc_errors++;
                if (RSV_GETBIT(rxstat, RSV_LENCHECKERR))
                        ndev->stats.rx_frame_errors++;
+               if (len > MAX_FRAMELEN)
+                       ndev->stats.rx_over_errors++;
        } else {
                skb = dev_alloc_skb(len + NET_IP_ALIGN);
                if (!skb) {
index 5e70180bf5693bdf0096164c8bb26b9bf23d3634..6bb71b687f7b17ef396cdba018487be37b9cb47b 100644 (file)
@@ -75,7 +75,7 @@
 #include "myri10ge_mcp.h"
 #include "myri10ge_mcp_gen_header.h"
 
-#define MYRI10GE_VERSION_STR "1.4.4-1.395"
+#define MYRI10GE_VERSION_STR "1.4.4-1.398"
 
 MODULE_DESCRIPTION("Myricom 10G driver (10GbE)");
 MODULE_AUTHOR("Maintainer: help@myri.com");
@@ -3929,6 +3929,10 @@ abort_with_firmware:
        myri10ge_dummy_rdma(mgp, 0);
 
 abort_with_ioremap:
+       if (mgp->mac_addr_string != NULL)
+               dev_err(&pdev->dev,
+                       "myri10ge_probe() failed: MAC=%s, SN=%ld\n",
+                       mgp->mac_addr_string, mgp->serial_number);
        iounmap(mgp->sram);
 
 abort_with_mtrr:
index ba2e1c5b6bcf8c0cf5b37e49b993d3ae3f82bb44..459663a4023daaa24cbb5c30ff402d59e919890a 100644 (file)
@@ -818,15 +818,6 @@ struct tx_doorbell_context {
 };
 
 /* DATA STRUCTURES SHARED WITH HARDWARE. */
-
-struct bq_element {
-       u32 addr_lo;
-#define BQ_END 0x00000001
-#define BQ_CONT        0x00000002
-#define BQ_MASK        0x00000003
-       u32 addr_hi;
-} __attribute((packed));
-
 struct tx_buf_desc {
        __le64 addr;
        __le32 len;
@@ -860,8 +851,8 @@ struct ob_mac_iocb_req {
        __le16 frame_len;
 #define OB_MAC_IOCB_LEN_MASK 0x3ffff
        __le16 reserved2;
-       __le32 tid;
-       __le32 txq_idx;
+       u32 tid;
+       u32 txq_idx;
        __le32 reserved3;
        __le16 vlan_tci;
        __le16 reserved4;
@@ -880,8 +871,8 @@ struct ob_mac_iocb_rsp {
        u8 flags2;              /* */
        u8 flags3;              /* */
 #define OB_MAC_IOCB_RSP_B      0x80    /* */
-       __le32 tid;
-       __le32 txq_idx;
+       u32 tid;
+       u32 txq_idx;
        __le32 reserved[13];
 } __attribute((packed));
 
@@ -903,8 +894,8 @@ struct ob_mac_tso_iocb_req {
 #define OB_MAC_TSO_IOCB_V      0x04
        __le32 reserved1[2];
        __le32 frame_len;
-       __le32 tid;
-       __le32 txq_idx;
+       u32 tid;
+       u32 txq_idx;
        __le16 total_hdrs_len;
        __le16 net_trans_offset;
 #define OB_MAC_TRANSPORT_HDR_SHIFT 6
@@ -925,8 +916,8 @@ struct ob_mac_tso_iocb_rsp {
        u8 flags2;              /* */
        u8 flags3;              /* */
 #define OB_MAC_TSO_IOCB_RSP_B  0x8000
-       __le32 tid;
-       __le32 txq_idx;
+       u32 tid;
+       u32 txq_idx;
        __le32 reserved2[13];
 } __attribute((packed));
 
@@ -979,10 +970,11 @@ struct ib_mac_iocb_rsp {
 
        __le16 reserved1;
        __le32 reserved2[6];
-       __le32 flags4;
-#define IB_MAC_IOCB_RSP_HV     0x20000000      /* */
-#define IB_MAC_IOCB_RSP_HS     0x40000000      /* */
-#define IB_MAC_IOCB_RSP_HL     0x80000000      /* */
+       u8 reserved3[3];
+       u8 flags4;
+#define IB_MAC_IOCB_RSP_HV     0x20
+#define IB_MAC_IOCB_RSP_HS     0x40
+#define IB_MAC_IOCB_RSP_HL     0x80
        __le32 hdr_len;         /* */
        __le32 hdr_addr_lo;     /* */
        __le32 hdr_addr_hi;     /* */
@@ -1126,7 +1118,7 @@ struct map_list {
 struct tx_ring_desc {
        struct sk_buff *skb;
        struct ob_mac_iocb_req *queue_entry;
-       int index;
+       u32 index;
        struct oal oal;
        struct map_list map[MAX_SKB_FRAGS + 1];
        int map_cnt;
@@ -1138,8 +1130,8 @@ struct bq_desc {
                struct page *lbq_page;
                struct sk_buff *skb;
        } p;
-       struct bq_element *bq;
-       int index;
+       __le64 *addr;
+       u32 index;
         DECLARE_PCI_UNMAP_ADDR(mapaddr);
         DECLARE_PCI_UNMAP_LEN(maplen);
 };
@@ -1189,7 +1181,7 @@ struct rx_ring {
        u32 cq_size;
        u32 cq_len;
        u16 cq_id;
-       u32 *prod_idx_sh_reg;   /* Shadowed producer register. */
+       volatile __le32 *prod_idx_sh_reg;       /* Shadowed producer register. */
        dma_addr_t prod_idx_sh_reg_dma;
        void __iomem *cnsmr_idx_db_reg; /* PCI doorbell mem area + 0 */
        u32 cnsmr_idx;          /* current sw idx */
@@ -1467,21 +1459,6 @@ static inline void ql_write_db_reg(u32 val, void __iomem *addr)
        mmiowb();
 }
 
-/*
- * Shadow Registers:
- * Outbound queues have a consumer index that is maintained by the chip.
- * Inbound queues have a producer index that is maintained by the chip.
- * For lower overhead, these registers are "shadowed" to host memory
- * which allows the device driver to track the queue progress without
- * PCI reads. When an entry is placed on an inbound queue, the chip will
- * update the relevant index register and then copy the value to the
- * shadow register in host memory.
- */
-static inline unsigned int ql_read_sh_reg(const volatile void  *addr)
-{
-       return *(volatile unsigned int __force *)addr;
-}
-
 extern char qlge_driver_name[];
 extern const char qlge_driver_version[];
 extern const struct ethtool_ops qlge_ethtool_ops;
index 47df304a02c8fb710c8d1688d9babaa508cf5200..3f5e02d2e4a9ddb4605999953e7ca286b3a76f9c 100644 (file)
@@ -821,14 +821,11 @@ void ql_dump_ib_mac_rsp(struct ib_mac_iocb_rsp *ib_mac_rsp)
                       le16_to_cpu(ib_mac_rsp->vlan_id));
 
        printk(KERN_ERR PFX "flags4 = %s%s%s.\n",
-              le32_to_cpu(ib_mac_rsp->
-                          flags4) & IB_MAC_IOCB_RSP_HV ? "HV " : "",
-              le32_to_cpu(ib_mac_rsp->
-                          flags4) & IB_MAC_IOCB_RSP_HS ? "HS " : "",
-              le32_to_cpu(ib_mac_rsp->
-                          flags4) & IB_MAC_IOCB_RSP_HL ? "HL " : "");
-
-       if (le32_to_cpu(ib_mac_rsp->flags4) & IB_MAC_IOCB_RSP_HV) {
+               ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HV ? "HV " : "",
+               ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HS ? "HS " : "",
+               ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HL ? "HL " : "");
+
+       if (ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HV) {
                printk(KERN_ERR PFX "hdr length = %d.\n",
                       le32_to_cpu(ib_mac_rsp->hdr_len));
                printk(KERN_ERR PFX "hdr addr_hi    = 0x%x.\n",
index eefb81b137588d4b61ad94b568f811c4fb5f9382..9d922e2ff226d0753b545870fd9e0348f92fa445 100644 (file)
@@ -56,9 +56,9 @@ static int ql_update_ring_coalescing(struct ql_adapter *qdev)
                for (i = 1; i < qdev->rss_ring_first_cq_id; i++, rx_ring++) {
                        rx_ring = &qdev->rx_ring[i];
                        cqicb = (struct cqicb *)rx_ring;
-                       cqicb->irq_delay = le16_to_cpu(qdev->tx_coalesce_usecs);
+                       cqicb->irq_delay = cpu_to_le16(qdev->tx_coalesce_usecs);
                        cqicb->pkt_delay =
-                           le16_to_cpu(qdev->tx_max_coalesced_frames);
+                           cpu_to_le16(qdev->tx_max_coalesced_frames);
                        cqicb->flags = FLAGS_LI;
                        status = ql_write_cfg(qdev, cqicb, sizeof(cqicb),
                                                CFG_LCQ, rx_ring->cq_id);
@@ -79,9 +79,9 @@ static int ql_update_ring_coalescing(struct ql_adapter *qdev)
                     i++) {
                        rx_ring = &qdev->rx_ring[i];
                        cqicb = (struct cqicb *)rx_ring;
-                       cqicb->irq_delay = le16_to_cpu(qdev->rx_coalesce_usecs);
+                       cqicb->irq_delay = cpu_to_le16(qdev->rx_coalesce_usecs);
                        cqicb->pkt_delay =
-                           le16_to_cpu(qdev->rx_max_coalesced_frames);
+                           cpu_to_le16(qdev->rx_max_coalesced_frames);
                        cqicb->flags = FLAGS_LI;
                        status = ql_write_cfg(qdev, cqicb, sizeof(cqicb),
                                                CFG_LCQ, rx_ring->cq_id);
index 718a7bd0cd1a207f90a6aaf92ffe894fd5163d79..f4c016012f18bf8d767cefc40ee0f7eab638e5ec 100644 (file)
@@ -257,7 +257,7 @@ int ql_get_mac_addr_reg(struct ql_adapter *qdev, u32 type, u16 index,
                {
                        status =
                            ql_wait_reg_rdy(qdev,
-                               MAC_ADDR_IDX, MAC_ADDR_MW, MAC_ADDR_E);
+                               MAC_ADDR_IDX, MAC_ADDR_MW, 0);
                        if (status)
                                goto exit;
                        ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */
@@ -265,13 +265,13 @@ int ql_get_mac_addr_reg(struct ql_adapter *qdev, u32 type, u16 index,
                                   MAC_ADDR_ADR | MAC_ADDR_RS | type); /* type */
                        status =
                            ql_wait_reg_rdy(qdev,
-                               MAC_ADDR_IDX, MAC_ADDR_MR, MAC_ADDR_E);
+                               MAC_ADDR_IDX, MAC_ADDR_MR, 0);
                        if (status)
                                goto exit;
                        *value++ = ql_read32(qdev, MAC_ADDR_DATA);
                        status =
                            ql_wait_reg_rdy(qdev,
-                               MAC_ADDR_IDX, MAC_ADDR_MW, MAC_ADDR_E);
+                               MAC_ADDR_IDX, MAC_ADDR_MW, 0);
                        if (status)
                                goto exit;
                        ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */
@@ -279,14 +279,14 @@ int ql_get_mac_addr_reg(struct ql_adapter *qdev, u32 type, u16 index,
                                   MAC_ADDR_ADR | MAC_ADDR_RS | type); /* type */
                        status =
                            ql_wait_reg_rdy(qdev,
-                               MAC_ADDR_IDX, MAC_ADDR_MR, MAC_ADDR_E);
+                               MAC_ADDR_IDX, MAC_ADDR_MR, 0);
                        if (status)
                                goto exit;
                        *value++ = ql_read32(qdev, MAC_ADDR_DATA);
                        if (type == MAC_ADDR_TYPE_CAM_MAC) {
                                status =
                                    ql_wait_reg_rdy(qdev,
-                                       MAC_ADDR_IDX, MAC_ADDR_MW, MAC_ADDR_E);
+                                       MAC_ADDR_IDX, MAC_ADDR_MW, 0);
                                if (status)
                                        goto exit;
                                ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */
@@ -294,7 +294,7 @@ int ql_get_mac_addr_reg(struct ql_adapter *qdev, u32 type, u16 index,
                                           MAC_ADDR_ADR | MAC_ADDR_RS | type); /* type */
                                status =
                                    ql_wait_reg_rdy(qdev, MAC_ADDR_IDX,
-                                                   MAC_ADDR_MR, MAC_ADDR_E);
+                                                   MAC_ADDR_MR, 0);
                                if (status)
                                        goto exit;
                                *value++ = ql_read32(qdev, MAC_ADDR_DATA);
@@ -344,7 +344,7 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type,
 
                        status =
                            ql_wait_reg_rdy(qdev,
-                               MAC_ADDR_IDX, MAC_ADDR_MW, MAC_ADDR_E);
+                               MAC_ADDR_IDX, MAC_ADDR_MW, 0);
                        if (status)
                                goto exit;
                        ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */
@@ -353,7 +353,7 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type,
                        ql_write32(qdev, MAC_ADDR_DATA, lower);
                        status =
                            ql_wait_reg_rdy(qdev,
-                               MAC_ADDR_IDX, MAC_ADDR_MW, MAC_ADDR_E);
+                               MAC_ADDR_IDX, MAC_ADDR_MW, 0);
                        if (status)
                                goto exit;
                        ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */
@@ -362,7 +362,7 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type,
                        ql_write32(qdev, MAC_ADDR_DATA, upper);
                        status =
                            ql_wait_reg_rdy(qdev,
-                               MAC_ADDR_IDX, MAC_ADDR_MW, MAC_ADDR_E);
+                               MAC_ADDR_IDX, MAC_ADDR_MW, 0);
                        if (status)
                                goto exit;
                        ql_write32(qdev, MAC_ADDR_IDX, (offset) |       /* offset */
@@ -400,7 +400,7 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type,
 
                        status =
                            ql_wait_reg_rdy(qdev,
-                               MAC_ADDR_IDX, MAC_ADDR_MW, MAC_ADDR_E);
+                               MAC_ADDR_IDX, MAC_ADDR_MW, 0);
                        if (status)
                                goto exit;
                        ql_write32(qdev, MAC_ADDR_IDX, offset | /* offset */
@@ -431,13 +431,13 @@ int ql_get_routing_reg(struct ql_adapter *qdev, u32 index, u32 *value)
        if (status)
                goto exit;
 
-       status = ql_wait_reg_rdy(qdev, RT_IDX, RT_IDX_MW, RT_IDX_E);
+       status = ql_wait_reg_rdy(qdev, RT_IDX, RT_IDX_MW, 0);
        if (status)
                goto exit;
 
        ql_write32(qdev, RT_IDX,
                   RT_IDX_TYPE_NICQ | RT_IDX_RS | (index << RT_IDX_IDX_SHIFT));
-       status = ql_wait_reg_rdy(qdev, RT_IDX, RT_IDX_MR, RT_IDX_E);
+       status = ql_wait_reg_rdy(qdev, RT_IDX, RT_IDX_MR, 0);
        if (status)
                goto exit;
        *value = ql_read32(qdev, RT_DATA);
@@ -874,7 +874,6 @@ static void ql_update_lbq(struct ql_adapter *qdev, struct rx_ring *rx_ring)
 {
        int clean_idx = rx_ring->lbq_clean_idx;
        struct bq_desc *lbq_desc;
-       struct bq_element *bq;
        u64 map;
        int i;
 
@@ -884,7 +883,6 @@ static void ql_update_lbq(struct ql_adapter *qdev, struct rx_ring *rx_ring)
                                "lbq: try cleaning clean_idx = %d.\n",
                                clean_idx);
                        lbq_desc = &rx_ring->lbq[clean_idx];
-                       bq = lbq_desc->bq;
                        if (lbq_desc->p.lbq_page == NULL) {
                                QPRINTK(qdev, RX_STATUS, DEBUG,
                                        "lbq: getting new page for index %d.\n",
@@ -906,10 +904,7 @@ static void ql_update_lbq(struct ql_adapter *qdev, struct rx_ring *rx_ring)
                                }
                                pci_unmap_addr_set(lbq_desc, mapaddr, map);
                                pci_unmap_len_set(lbq_desc, maplen, PAGE_SIZE);
-                               bq->addr_lo =   /*lbq_desc->addr_lo = */
-                                   cpu_to_le32(map);
-                               bq->addr_hi =   /*lbq_desc->addr_hi = */
-                                   cpu_to_le32(map >> 32);
+                               *lbq_desc->addr = cpu_to_le64(map);
                        }
                        clean_idx++;
                        if (clean_idx == rx_ring->lbq_len)
@@ -934,7 +929,6 @@ static void ql_update_sbq(struct ql_adapter *qdev, struct rx_ring *rx_ring)
 {
        int clean_idx = rx_ring->sbq_clean_idx;
        struct bq_desc *sbq_desc;
-       struct bq_element *bq;
        u64 map;
        int i;
 
@@ -944,7 +938,6 @@ static void ql_update_sbq(struct ql_adapter *qdev, struct rx_ring *rx_ring)
                        QPRINTK(qdev, RX_STATUS, DEBUG,
                                "sbq: try cleaning clean_idx = %d.\n",
                                clean_idx);
-                       bq = sbq_desc->bq;
                        if (sbq_desc->p.skb == NULL) {
                                QPRINTK(qdev, RX_STATUS, DEBUG,
                                        "sbq: getting new skb for index %d.\n",
@@ -963,11 +956,15 @@ static void ql_update_sbq(struct ql_adapter *qdev, struct rx_ring *rx_ring)
                                                     sbq_desc->p.skb->data,
                                                     rx_ring->sbq_buf_size /
                                                     2, PCI_DMA_FROMDEVICE);
+                               if (pci_dma_mapping_error(qdev->pdev, map)) {
+                                       QPRINTK(qdev, IFUP, ERR, "PCI mapping failed.\n");
+                                       rx_ring->sbq_clean_idx = clean_idx;
+                                       return;
+                               }
                                pci_unmap_addr_set(sbq_desc, mapaddr, map);
                                pci_unmap_len_set(sbq_desc, maplen,
                                                  rx_ring->sbq_buf_size / 2);
-                               bq->addr_lo = cpu_to_le32(map);
-                               bq->addr_hi = cpu_to_le32(map >> 32);
+                               *sbq_desc->addr = cpu_to_le64(map);
                        }
 
                        clean_idx++;
@@ -1303,6 +1300,11 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev,
                                        "No skb available, drop the packet.\n");
                                return NULL;
                        }
+                       pci_unmap_page(qdev->pdev,
+                                      pci_unmap_addr(lbq_desc,
+                                                     mapaddr),
+                                      pci_unmap_len(lbq_desc, maplen),
+                                      PCI_DMA_FROMDEVICE);
                        skb_reserve(skb, NET_IP_ALIGN);
                        QPRINTK(qdev, RX_STATUS, DEBUG,
                                "%d bytes of headers and data in large. Chain page to new skb and pull tail.\n", length);
@@ -1330,7 +1332,7 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev,
                 *          eventually be in trouble.
                 */
                int size, offset, i = 0;
-               struct bq_element *bq, bq_array[8];
+               __le64 *bq, bq_array[8];
                sbq_desc = ql_get_curr_sbuf(rx_ring);
                pci_unmap_single(qdev->pdev,
                                 pci_unmap_addr(sbq_desc, mapaddr),
@@ -1356,16 +1358,10 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev,
                } else {
                        QPRINTK(qdev, RX_STATUS, DEBUG,
                                "Headers in small, %d bytes of data in chain of large.\n", length);
-                       bq = (struct bq_element *)sbq_desc->p.skb->data;
+                       bq = (__le64 *)sbq_desc->p.skb->data;
                }
                while (length > 0) {
                        lbq_desc = ql_get_curr_lbuf(rx_ring);
-                       if ((bq->addr_lo & ~BQ_MASK) != lbq_desc->bq->addr_lo) {
-                               QPRINTK(qdev, RX_STATUS, ERR,
-                                       "Panic!!! bad large buffer address, expected 0x%.08x, got 0x%.08x.\n",
-                                       lbq_desc->bq->addr_lo, bq->addr_lo);
-                               return NULL;
-                       }
                        pci_unmap_page(qdev->pdev,
                                       pci_unmap_addr(lbq_desc,
                                                      mapaddr),
@@ -1549,7 +1545,7 @@ static void ql_process_chip_ae_intr(struct ql_adapter *qdev,
 static int ql_clean_outbound_rx_ring(struct rx_ring *rx_ring)
 {
        struct ql_adapter *qdev = rx_ring->qdev;
-       u32 prod = ql_read_sh_reg(rx_ring->prod_idx_sh_reg);
+       u32 prod = le32_to_cpu(*rx_ring->prod_idx_sh_reg);
        struct ob_mac_iocb_rsp *net_rsp = NULL;
        int count = 0;
 
@@ -1575,7 +1571,7 @@ static int ql_clean_outbound_rx_ring(struct rx_ring *rx_ring)
                }
                count++;
                ql_update_cq(rx_ring);
-               prod = ql_read_sh_reg(rx_ring->prod_idx_sh_reg);
+               prod = le32_to_cpu(*rx_ring->prod_idx_sh_reg);
        }
        ql_write_cq_idx(rx_ring);
        if (netif_queue_stopped(qdev->ndev) && net_rsp != NULL) {
@@ -1595,7 +1591,7 @@ static int ql_clean_outbound_rx_ring(struct rx_ring *rx_ring)
 static int ql_clean_inbound_rx_ring(struct rx_ring *rx_ring, int budget)
 {
        struct ql_adapter *qdev = rx_ring->qdev;
-       u32 prod = ql_read_sh_reg(rx_ring->prod_idx_sh_reg);
+       u32 prod = le32_to_cpu(*rx_ring->prod_idx_sh_reg);
        struct ql_net_rsp_iocb *net_rsp;
        int count = 0;
 
@@ -1628,7 +1624,7 @@ static int ql_clean_inbound_rx_ring(struct rx_ring *rx_ring, int budget)
                }
                count++;
                ql_update_cq(rx_ring);
-               prod = ql_read_sh_reg(rx_ring->prod_idx_sh_reg);
+               prod = le32_to_cpu(*rx_ring->prod_idx_sh_reg);
                if (count == budget)
                        break;
        }
@@ -1791,7 +1787,7 @@ static irqreturn_t qlge_isr(int irq, void *dev_id)
         * Check the default queue and wake handler if active.
         */
        rx_ring = &qdev->rx_ring[0];
-       if (ql_read_sh_reg(rx_ring->prod_idx_sh_reg) != rx_ring->cnsmr_idx) {
+       if (le32_to_cpu(*rx_ring->prod_idx_sh_reg) != rx_ring->cnsmr_idx) {
                QPRINTK(qdev, INTR, INFO, "Waking handler for rx_ring[0].\n");
                ql_disable_completion_interrupt(qdev, intr_context->intr);
                queue_delayed_work_on(smp_processor_id(), qdev->q_workqueue,
@@ -1805,7 +1801,7 @@ static irqreturn_t qlge_isr(int irq, void *dev_id)
                 */
                for (i = 1; i < qdev->rx_ring_count; i++) {
                        rx_ring = &qdev->rx_ring[i];
-                       if (ql_read_sh_reg(rx_ring->prod_idx_sh_reg) !=
+                       if (le32_to_cpu(*rx_ring->prod_idx_sh_reg) !=
                            rx_ring->cnsmr_idx) {
                                QPRINTK(qdev, INTR, INFO,
                                        "Waking handler for rx_ring[%d].\n", i);
@@ -1874,7 +1870,7 @@ static void ql_hw_csum_setup(struct sk_buff *skb,
 {
        int len;
        struct iphdr *iph = ip_hdr(skb);
-       u16 *check;
+       __sum16 *check;
        mac_iocb_ptr->opcode = OPCODE_OB_MAC_TSO_IOCB;
        mac_iocb_ptr->frame_len = cpu_to_le32((u32) skb->len);
        mac_iocb_ptr->net_trans_offset =
@@ -2083,8 +2079,6 @@ static void ql_free_lbq_buffers(struct ql_adapter *qdev, struct rx_ring *rx_ring
                        put_page(lbq_desc->p.lbq_page);
                        lbq_desc->p.lbq_page = NULL;
                }
-               lbq_desc->bq->addr_lo = 0;
-               lbq_desc->bq->addr_hi = 0;
        }
 }
 
@@ -2097,12 +2091,12 @@ static int ql_alloc_lbq_buffers(struct ql_adapter *qdev,
        int i;
        struct bq_desc *lbq_desc;
        u64 map;
-       struct bq_element *bq = rx_ring->lbq_base;
+       __le64 *bq = rx_ring->lbq_base;
 
        for (i = 0; i < rx_ring->lbq_len; i++) {
                lbq_desc = &rx_ring->lbq[i];
                memset(lbq_desc, 0, sizeof(lbq_desc));
-               lbq_desc->bq = bq;
+               lbq_desc->addr = bq;
                lbq_desc->index = i;
                lbq_desc->p.lbq_page = alloc_page(GFP_ATOMIC);
                if (unlikely(!lbq_desc->p.lbq_page)) {
@@ -2119,8 +2113,7 @@ static int ql_alloc_lbq_buffers(struct ql_adapter *qdev,
                        }
                        pci_unmap_addr_set(lbq_desc, mapaddr, map);
                        pci_unmap_len_set(lbq_desc, maplen, PAGE_SIZE);
-                       bq->addr_lo = cpu_to_le32(map);
-                       bq->addr_hi = cpu_to_le32(map >> 32);
+                       *lbq_desc->addr = cpu_to_le64(map);
                }
                bq++;
        }
@@ -2149,13 +2142,6 @@ static void ql_free_sbq_buffers(struct ql_adapter *qdev, struct rx_ring *rx_ring
                        dev_kfree_skb(sbq_desc->p.skb);
                        sbq_desc->p.skb = NULL;
                }
-               if (sbq_desc->bq == NULL) {
-                       QPRINTK(qdev, IFUP, ERR, "sbq_desc->bq %d is NULL.\n",
-                               i);
-                       return;
-               }
-               sbq_desc->bq->addr_lo = 0;
-               sbq_desc->bq->addr_hi = 0;
        }
 }
 
@@ -2167,13 +2153,13 @@ static int ql_alloc_sbq_buffers(struct ql_adapter *qdev,
        struct bq_desc *sbq_desc;
        struct sk_buff *skb;
        u64 map;
-       struct bq_element *bq = rx_ring->sbq_base;
+       __le64 *bq = rx_ring->sbq_base;
 
        for (i = 0; i < rx_ring->sbq_len; i++) {
                sbq_desc = &rx_ring->sbq[i];
                memset(sbq_desc, 0, sizeof(sbq_desc));
                sbq_desc->index = i;
-               sbq_desc->bq = bq;
+               sbq_desc->addr = bq;
                skb = netdev_alloc_skb(qdev->ndev, rx_ring->sbq_buf_size);
                if (unlikely(!skb)) {
                        /* Better luck next round */
@@ -2199,10 +2185,7 @@ static int ql_alloc_sbq_buffers(struct ql_adapter *qdev,
                }
                pci_unmap_addr_set(sbq_desc, mapaddr, map);
                pci_unmap_len_set(sbq_desc, maplen, rx_ring->sbq_buf_size / 2);
-               bq->addr_lo =   /*sbq_desc->addr_lo = */
-                   cpu_to_le32(map);
-               bq->addr_hi =   /*sbq_desc->addr_hi = */
-                   cpu_to_le32(map >> 32);
+               *sbq_desc->addr = cpu_to_le64(map);
                bq++;
        }
        return 0;
@@ -2481,7 +2464,8 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring)
        memset((void *)cqicb, 0, sizeof(struct cqicb));
        cqicb->msix_vect = rx_ring->irq;
 
-       cqicb->len = cpu_to_le16(rx_ring->cq_len | LEN_V | LEN_CPP_CONT);
+       bq_len = (rx_ring->cq_len == 65536) ? 0 : (u16) rx_ring->cq_len;
+       cqicb->len = cpu_to_le16(bq_len | LEN_V | LEN_CPP_CONT);
 
        cqicb->addr_lo = cpu_to_le32(rx_ring->cq_base_dma);
        cqicb->addr_hi = cpu_to_le32((u64) rx_ring->cq_base_dma >> 32);
@@ -2503,8 +2487,11 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring)
                    cpu_to_le32(rx_ring->lbq_base_indirect_dma);
                cqicb->lbq_addr_hi =
                    cpu_to_le32((u64) rx_ring->lbq_base_indirect_dma >> 32);
-               cqicb->lbq_buf_size = cpu_to_le32(rx_ring->lbq_buf_size);
-               bq_len = (u16) rx_ring->lbq_len;
+               bq_len = (rx_ring->lbq_buf_size == 65536) ? 0 :
+                       (u16) rx_ring->lbq_buf_size;
+               cqicb->lbq_buf_size = cpu_to_le16(bq_len);
+               bq_len = (rx_ring->lbq_len == 65536) ? 0 :
+                       (u16) rx_ring->lbq_len;
                cqicb->lbq_len = cpu_to_le16(bq_len);
                rx_ring->lbq_prod_idx = rx_ring->lbq_len - 16;
                rx_ring->lbq_curr_idx = 0;
@@ -2520,7 +2507,8 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring)
                    cpu_to_le32((u64) rx_ring->sbq_base_indirect_dma >> 32);
                cqicb->sbq_buf_size =
                    cpu_to_le16(((rx_ring->sbq_buf_size / 2) + 8) & 0xfffffff8);
-               bq_len = (u16) rx_ring->sbq_len;
+               bq_len = (rx_ring->sbq_len == 65536) ? 0 :
+                       (u16) rx_ring->sbq_len;
                cqicb->sbq_len = cpu_to_le16(bq_len);
                rx_ring->sbq_prod_idx = rx_ring->sbq_len - 16;
                rx_ring->sbq_curr_idx = 0;
@@ -3341,11 +3329,11 @@ static int ql_configure_rings(struct ql_adapter *qdev)
                            rx_ring->cq_len * sizeof(struct ql_net_rsp_iocb);
                        rx_ring->lbq_len = NUM_LARGE_BUFFERS;
                        rx_ring->lbq_size =
-                           rx_ring->lbq_len * sizeof(struct bq_element);
+                           rx_ring->lbq_len * sizeof(__le64);
                        rx_ring->lbq_buf_size = LARGE_BUFFER_SIZE;
                        rx_ring->sbq_len = NUM_SMALL_BUFFERS;
                        rx_ring->sbq_size =
-                           rx_ring->sbq_len * sizeof(struct bq_element);
+                           rx_ring->sbq_len * sizeof(__le64);
                        rx_ring->sbq_buf_size = SMALL_BUFFER_SIZE * 2;
                        rx_ring->type = DEFAULT_Q;
                } else if (i < qdev->rss_ring_first_cq_id) {
@@ -3372,11 +3360,11 @@ static int ql_configure_rings(struct ql_adapter *qdev)
                            rx_ring->cq_len * sizeof(struct ql_net_rsp_iocb);
                        rx_ring->lbq_len = NUM_LARGE_BUFFERS;
                        rx_ring->lbq_size =
-                           rx_ring->lbq_len * sizeof(struct bq_element);
+                           rx_ring->lbq_len * sizeof(__le64);
                        rx_ring->lbq_buf_size = LARGE_BUFFER_SIZE;
                        rx_ring->sbq_len = NUM_SMALL_BUFFERS;
                        rx_ring->sbq_size =
-                           rx_ring->sbq_len * sizeof(struct bq_element);
+                           rx_ring->sbq_len * sizeof(__le64);
                        rx_ring->sbq_buf_size = SMALL_BUFFER_SIZE * 2;
                        rx_ring->type = RX_Q;
                }
index f54ac2389da29dd444395853582c5153a55309e9..57fb1f71c47becba464cbf9ba14bcb980e0d3a82 100644 (file)
 #include <linux/mii.h>
 #include <linux/if_vlan.h>
 #include <linux/mm.h>
+#include <linux/firmware.h>
 #include <asm/processor.h>             /* Processor type for cache alignment. */
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
-#include "starfire_firmware.h"
 /*
  * The current frame processor firmware fails to checksum a fragment
  * of length 1. If and when this is fixed, the #define below can be removed.
@@ -173,6 +173,10 @@ static int full_duplex[MAX_UNITS] = {0, };
 #define skb_first_frag_len(skb)        skb_headlen(skb)
 #define skb_num_frags(skb) (skb_shinfo(skb)->nr_frags + 1)
 
+/* Firmware names */
+#define FIRMWARE_RX    "adaptec/starfire_rx.bin"
+#define FIRMWARE_TX    "adaptec/starfire_tx.bin"
+
 /* These identify the driver base version and may not be removed. */
 static char version[] =
 KERN_INFO "starfire.c:v1.03 7/26/2000  Written by Donald Becker <becker@scyld.com>\n"
@@ -182,6 +186,8 @@ MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
 MODULE_DESCRIPTION("Adaptec Starfire Ethernet driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
+MODULE_FIRMWARE(FIRMWARE_RX);
+MODULE_FIRMWARE(FIRMWARE_TX);
 
 module_param(max_interrupt_work, int, 0);
 module_param(mtu, int, 0);
@@ -902,9 +908,12 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val
 
 static int netdev_open(struct net_device *dev)
 {
+       const struct firmware *fw_rx, *fw_tx;
+       const __be32 *fw_rx_data, *fw_tx_data;
        struct netdev_private *np = netdev_priv(dev);
        void __iomem *ioaddr = np->base;
        int i, retval;
+       size_t tx_size, rx_size;
        size_t tx_done_q_size, rx_done_q_size, tx_ring_size, rx_ring_size;
 
        /* Do we ever need to reset the chip??? */
@@ -1040,11 +1049,40 @@ static int netdev_open(struct net_device *dev)
        writel(ETH_P_8021Q, ioaddr + VlanType);
 #endif /* VLAN_SUPPORT */
 
+       retval = request_firmware(&fw_rx, FIRMWARE_RX, &np->pci_dev->dev);
+       if (retval) {
+               printk(KERN_ERR "starfire: Failed to load firmware \"%s\"\n",
+                      FIRMWARE_RX);
+               return retval;
+       }
+       if (fw_rx->size % 4) {
+               printk(KERN_ERR "starfire: bogus length %zu in \"%s\"\n",
+                      fw_rx->size, FIRMWARE_RX);
+               retval = -EINVAL;
+               goto out_rx;
+       }
+       retval = request_firmware(&fw_tx, FIRMWARE_TX, &np->pci_dev->dev);
+       if (retval) {
+               printk(KERN_ERR "starfire: Failed to load firmware \"%s\"\n",
+                      FIRMWARE_TX);
+               goto out_rx;
+       }
+       if (fw_tx->size % 4) {
+               printk(KERN_ERR "starfire: bogus length %zu in \"%s\"\n",
+                      fw_tx->size, FIRMWARE_TX);
+               retval = -EINVAL;
+               goto out_tx;
+       }
+       fw_rx_data = (const __be32 *)&fw_rx->data[0];
+       fw_tx_data = (const __be32 *)&fw_tx->data[0];
+       rx_size = fw_rx->size / 4;
+       tx_size = fw_tx->size / 4;
+
        /* Load Rx/Tx firmware into the frame processors */
-       for (i = 0; i < FIRMWARE_RX_SIZE * 2; i++)
-               writel(firmware_rx[i], ioaddr + RxGfpMem + i * 4);
-       for (i = 0; i < FIRMWARE_TX_SIZE * 2; i++)
-               writel(firmware_tx[i], ioaddr + TxGfpMem + i * 4);
+       for (i = 0; i < rx_size; i++)
+               writel(be32_to_cpup(&fw_rx_data[i]), ioaddr + RxGfpMem + i * 4);
+       for (i = 0; i < tx_size; i++)
+               writel(be32_to_cpup(&fw_tx_data[i]), ioaddr + TxGfpMem + i * 4);
        if (enable_hw_cksum)
                /* Enable the Rx and Tx units, and the Rx/Tx frame processors. */
                writel(TxEnable|TxGFPEnable|RxEnable|RxGFPEnable, ioaddr + GenCtrl);
@@ -1056,7 +1094,11 @@ static int netdev_open(struct net_device *dev)
                printk(KERN_DEBUG "%s: Done netdev_open().\n",
                       dev->name);
 
-       return 0;
+out_tx:
+       release_firmware(fw_tx);
+out_rx:
+       release_firmware(fw_rx);
+       return retval;
 }
 
 
diff --git a/drivers/net/starfire_firmware.h b/drivers/net/starfire_firmware.h
deleted file mode 100644 (file)
index 0a66852..0000000
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
- * Copyright 2003 Adaptec, Inc.
- *
- * Please read the following license before using the Adaptec Software
- * ("Program"). If you do not agree to the license terms, do not use the
- * Program:
- *
- * You agree to be bound by version 2 of the General Public License ("GPL")
- * dated June 1991, which can be found at http://www.fsf.org/licenses/gpl.html.
- * If the link is broken, write to Free Software Foundation, 59 Temple Place,
- * Boston, Massachusetts 02111-1307.
- *
- * BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE IT IS LICENSED "AS IS" AND
- * THERE IS NO WARRANTY FOR THE PROGRAM, INCLUDING BUT NOT LIMITED TO THE
- * IMPLIED WARRANTIES OF MERCHANTIBILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * (TO THE EXTENT PERMITTED BY APPLICABLE LAW). USE OF THE PROGRAM IS AT YOUR
- * OWN RISK. IN NO EVENT WILL ADAPTEC OR ITS LICENSORS BE LIABLE TO YOU FOR
- * DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM.
- *
- */
-
-static const u32 firmware_rx[] = {
-  0x010003dc, 0x00000000,
-  0x04000421, 0x00000086,
-  0x80000015, 0x0000180e,
-  0x81000015, 0x00006664,
-  0x1a0040ab, 0x00000b06,
-  0x14200011, 0x00000000,
-  0x14204022, 0x0000aaaa,
-  0x14204022, 0x00000300,
-  0x14204022, 0x00000000,
-  0x1a0040ab, 0x00000b14,
-  0x14200011, 0x00000000,
-  0x83000015, 0x00000002,
-  0x04000021, 0x00000000,
-  0x00000010, 0x00000000,
-  0x04000421, 0x00000087,
-  0x00000010, 0x00000000,
-  0x00000010, 0x00000000,
-  0x00008015, 0x00000000,
-  0x0000003e, 0x00000000,
-  0x00000010, 0x00000000,
-  0x82000015, 0x00004000,
-  0x009e8050, 0x00000000,
-  0x03008015, 0x00000000,
-  0x86008015, 0x00000000,
-  0x82000015, 0x00008000,
-  0x0100001c, 0x00000000,
-  0x000050a0, 0x0000010c,
-  0x4e20d011, 0x00006008,
-  0x1420d012, 0x00004008,
-  0x0000f090, 0x00007000,
-  0x0000c8b0, 0x00003000,
-  0x00004040, 0x00000000,
-  0x00108015, 0x00000000,
-  0x00a2c150, 0x00004000,
-  0x00a400b0, 0x00000014,
-  0x00000020, 0x00000000,
-  0x2500400d, 0x00002525,
-  0x00047220, 0x00003100,
-  0x00934070, 0x00000000,
-  0x00000020, 0x00000000,
-  0x00924460, 0x00000184,
-  0x2b20c011, 0x00000000,
-  0x0000c420, 0x00000540,
-  0x36014018, 0x0000422d,
-  0x14200011, 0x00000000,
-  0x00924460, 0x00000183,
-  0x3200001f, 0x00000034,
-  0x02ac0015, 0x00000002,
-  0x00a60110, 0x00000008,
-  0x42200011, 0x00000000,
-  0x00924060, 0x00000103,
-  0x0000001e, 0x00000000,
-  0x00000020, 0x00000100,
-  0x0000001e, 0x00000000,
-  0x00924460, 0x00000086,
-  0x00004080, 0x00000000,
-  0x0092c070, 0x00000000,
-  0x00924060, 0x00000100,
-  0x0000c890, 0x00005000,
-  0x00a6c110, 0x00000000,
-  0x00b0c090, 0x00000012,
-  0x021c0015, 0x00000000,
-  0x3200001f, 0x00000034,
-  0x00924460, 0x00000510,
-  0x44210011, 0x00000000,
-  0x42000011, 0x00000000,
-  0x83000015, 0x00000040,
-  0x00924460, 0x00000508,
-  0x45014018, 0x00004545,
-  0x00808050, 0x00000000,
-  0x62208012, 0x00000000,
-  0x82000015, 0x00000800,
-  0x15200011, 0x00000000,
-  0x00000010, 0x00000000,
-  0x00000010, 0x00000000,
-  0x00000010, 0x00000000,
-  0x00000010, 0x00000000,
-  0x00000010, 0x00000000,
-  0x80000015, 0x0000eea4,
-  0x81000015, 0x0000005f,
-  0x00000060, 0x00000000,
-  0x00004120, 0x00000000,
-  0x00004a00, 0x00004000,
-  0x00924460, 0x00000190,
-  0x5601401a, 0x00005956,
-  0x14000011, 0x00000000,
-  0x00934050, 0x00000018,
-  0x00930050, 0x00000018,
-  0x3601403a, 0x0000002d,
-  0x000643a9, 0x00000000,
-  0x0000c420, 0x00000140,
-  0x5601401a, 0x00005956,
-  0x14000011, 0x00000000,
-  0x00000010, 0x00000000,
-  0x00000010, 0x00000000,
-  0x000642a9, 0x00000000,
-  0x00024420, 0x00000183,
-  0x5601401a, 0x00005956,
-  0x82000015, 0x00002000,
-  0x15200011, 0x00000000,
-  0x82000015, 0x00000010,
-  0x15200011, 0x00000000,
-  0x82000015, 0x00000010,
-  0x15200011, 0x00000000,
-};     /* 104 Rx instructions */
-#define FIRMWARE_RX_SIZE 104
-
-static const u32 firmware_tx[] = {
-  0x010003dc, 0x00000000,
-  0x04000421, 0x00000086,
-  0x80000015, 0x0000180e,
-  0x81000015, 0x00006664,
-  0x1a0040ab, 0x00000b06,
-  0x14200011, 0x00000000,
-  0x14204022, 0x0000aaaa,
-  0x14204022, 0x00000300,
-  0x14204022, 0x00000000,
-  0x1a0040ab, 0x00000b14,
-  0x14200011, 0x00000000,
-  0x83000015, 0x00000002,
-  0x04000021, 0x00000000,
-  0x00000010, 0x00000000,
-  0x04000421, 0x00000087,
-  0x00000010, 0x00000000,
-  0x00000010, 0x00000000,
-  0x00008015, 0x00000000,
-  0x0000003e, 0x00000000,
-  0x00000010, 0x00000000,
-  0x82000015, 0x00004000,
-  0x009e8050, 0x00000000,
-  0x03008015, 0x00000000,
-  0x86008015, 0x00000000,
-  0x82000015, 0x00008000,
-  0x0100001c, 0x00000000,
-  0x000050a0, 0x0000010c,
-  0x4e20d011, 0x00006008,
-  0x1420d012, 0x00004008,
-  0x0000f090, 0x00007000,
-  0x0000c8b0, 0x00003000,
-  0x00004040, 0x00000000,
-  0x00108015, 0x00000000,
-  0x00a2c150, 0x00004000,
-  0x00a400b0, 0x00000014,
-  0x00000020, 0x00000000,
-  0x2500400d, 0x00002525,
-  0x00047220, 0x00003100,
-  0x00934070, 0x00000000,
-  0x00000020, 0x00000000,
-  0x00924460, 0x00000184,
-  0x2b20c011, 0x00000000,
-  0x0000c420, 0x00000540,
-  0x36014018, 0x0000422d,
-  0x14200011, 0x00000000,
-  0x00924460, 0x00000183,
-  0x3200001f, 0x00000034,
-  0x02ac0015, 0x00000002,
-  0x00a60110, 0x00000008,
-  0x42200011, 0x00000000,
-  0x00924060, 0x00000103,
-  0x0000001e, 0x00000000,
-  0x00000020, 0x00000100,
-  0x0000001e, 0x00000000,
-  0x00924460, 0x00000086,
-  0x00004080, 0x00000000,
-  0x0092c070, 0x00000000,
-  0x00924060, 0x00000100,
-  0x0000c890, 0x00005000,
-  0x00a6c110, 0x00000000,
-  0x00b0c090, 0x00000012,
-  0x021c0015, 0x00000000,
-  0x3200001f, 0x00000034,
-  0x00924460, 0x00000510,
-  0x44210011, 0x00000000,
-  0x42000011, 0x00000000,
-  0x83000015, 0x00000040,
-  0x00924460, 0x00000508,
-  0x45014018, 0x00004545,
-  0x00808050, 0x00000000,
-  0x62208012, 0x00000000,
-  0x82000015, 0x00000800,
-  0x15200011, 0x00000000,
-  0x00000010, 0x00000000,
-  0x00000010, 0x00000000,
-  0x00000010, 0x00000000,
-  0x00000010, 0x00000000,
-  0x00000010, 0x00000000,
-  0x80000015, 0x0000eea4,
-  0x81000015, 0x0000005f,
-  0x00000060, 0x00000000,
-  0x00004120, 0x00000000,
-  0x00004a00, 0x00004000,
-  0x00924460, 0x00000190,
-  0x5601401a, 0x00005956,
-  0x14000011, 0x00000000,
-  0x00934050, 0x00000018,
-  0x00930050, 0x00000018,
-  0x3601403a, 0x0000002d,
-  0x000643a9, 0x00000000,
-  0x0000c420, 0x00000140,
-  0x5601401a, 0x00005956,
-  0x14000011, 0x00000000,
-  0x00000010, 0x00000000,
-  0x00000010, 0x00000000,
-  0x000642a9, 0x00000000,
-  0x00024420, 0x00000183,
-  0x5601401a, 0x00005956,
-  0x82000015, 0x00002000,
-  0x15200011, 0x00000000,
-  0x82000015, 0x00000010,
-  0x15200011, 0x00000000,
-  0x82000015, 0x00000010,
-  0x15200011, 0x00000000,
-};     /* 104 Tx instructions */
-#define FIRMWARE_TX_SIZE 104
-#if 0
-static const u32 firmware_wol[] = {
-  0x010003dc, 0x00000000,
-  0x19000421, 0x00000087,
-  0x80000015, 0x00001a1a,
-  0x81000015, 0x00001a1a,
-  0x1a0040ab, 0x00000b06,
-  0x15200011, 0x00000000,
-  0x15204022, 0x0000aaaa,
-  0x15204022, 0x00000300,
-  0x15204022, 0x00000000,
-  0x1a0040ab, 0x00000b15,
-  0x15200011, 0x00000000,
-  0x83000015, 0x00000002,
-  0x04000021, 0x00000000,
-  0x00000010, 0x00000000,
-  0x04000421, 0x00000087,
-  0x00000010, 0x00000000,
-  0x00000010, 0x00000000,
-  0x00008015, 0x00000000,
-  0x0000003e, 0x00000000,
-  0x00000010, 0x00000000,
-  0x00000010, 0x00000000,
-  0x82000015, 0x00004000,
-  0x82000015, 0x00008000,
-  0x0000000c, 0x00000000,
-  0x00000010, 0x00000000,
-  0x00004080, 0x00000100,
-  0x1f20c011, 0x00001122,
-  0x2720f011, 0x00003011,
-  0x19200071, 0x00000000,
-  0x1a200051, 0x00000000,
-  0x00000010, 0x00000000,
-  0x00000010, 0x00000000,
-  0x1d2040a4, 0x00003344,
-  0x1d2040a2, 0x00005566,
-  0x000040a0, 0x00000100,
-  0x00108050, 0x00000001,
-  0x1a208012, 0x00000006,
-  0x82000015, 0x00008080,
-  0x010003dc, 0x00000000,
-  0x1d2040a4, 0x00002233,
-  0x1d2040a4, 0x00004455,
-  0x2d208011, 0x00000005,
-  0x1d2040a4, 0x00006611,
-  0x00108050, 0x00000001,
-  0x27200011, 0x00000000,
-  0x1d2050a4, 0x00006600,
-  0x82000015, 0x00008080,
-  0x010003dc, 0x00000000,
-  0x00000050, 0x00000000,
-  0x1b200031, 0x00000000,
-  0x0000001e, 0x00000000,
-  0x0000001e, 0x00000000,
-  0x0000001e, 0x00000000,
-  0x0000001e, 0x00000000,
-  0x00924460, 0x00000086,
-  0x00004080, 0x00000000,
-  0x0092c070, 0x00000000,
-  0x00924060, 0x00000100,
-  0x0000c890, 0x00005000,
-  0x00a6c110, 0x00000000,
-  0x00b0c090, 0x00000012,
-  0x021c0015, 0x00000000,
-  0x3200001f, 0x00000034,
-  0x00924460, 0x00000510,
-  0x44210011, 0x00000000,
-  0x42000011, 0x00000000,
-  0x83000015, 0x00000040,
-  0x00924460, 0x00000508,
-  0x476a0012, 0x00000100,
-  0x83000015, 0x00000008,
-  0x16200011, 0x00000000,
-  0x001e8050, 0x00000000,
-  0x001e8050, 0x00000000,
-  0x00808050, 0x00000000,
-  0x03008015, 0x00000000,
-  0x62208012, 0x00000000,
-  0x82000015, 0x00000800,
-  0x16200011, 0x00000000,
-  0x80000015, 0x0000eea4,
-  0x81000015, 0x0000005f,
-  0x00000020, 0x00000000,
-  0x00004120, 0x00000000,
-  0x00004a00, 0x00004000,
-  0x00924460, 0x00000190,
-  0x5c01401a, 0x0000595c,
-  0x15000011, 0x00000000,
-  0x00934050, 0x00000018,
-  0x00930050, 0x00000018,
-  0x3601403a, 0x0000002d,
-  0x00064029, 0x00000000,
-  0x0000c420, 0x00000140,
-  0x5c01401a, 0x0000595c,
-  0x15000011, 0x00000000,
-  0x00000010, 0x00000000,
-  0x00000010, 0x00000000,
-  0x00064029, 0x00000000,
-  0x00024420, 0x00000183,
-  0x5c01401a, 0x0000595c,
-  0x82000015, 0x00002000,
-  0x16200011, 0x00000000,
-  0x82000015, 0x00000010,
-  0x16200011, 0x00000000,
-  0x82000015, 0x00000010,
-  0x16200011, 0x00000000,
-};     /* 104 WoL instructions */
-#define FIRMWARE_WOL_SIZE 104
-#endif
diff --git a/drivers/net/starfire_firmware.pl b/drivers/net/starfire_firmware.pl
deleted file mode 100644 (file)
index 0c82b80..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/usr/bin/perl
-
-# This script can be used to generate a new starfire_firmware.h
-# from GFP_RX.DAT and GFP_TX.DAT, files included with the DDK
-# and also with the Novell drivers.
-
-open FW, "GFP_RX.DAT" || die;
-open FWH, ">starfire_firmware.h" || die;
-
-printf(FWH "static u32 firmware_rx[] = {\n");
-$counter = 0;
-while ($foo = <FW>) {
-  chomp;
-  printf(FWH "  0x%s, 0x0000%s,\n", substr($foo, 4, 8), substr($foo, 0, 4));
-  $counter++;
-}
-
-close FW;
-open FW, "GFP_TX.DAT" || die;
-
-printf(FWH "};\t/* %d Rx instructions */\n#define FIRMWARE_RX_SIZE %d\n\nstatic u32 firmware_tx[] = {\n", $counter, $counter);
-$counter = 0;
-while ($foo = <FW>) {
-  chomp;
-  printf(FWH "  0x%s, 0x0000%s,\n", substr($foo, 4, 8), substr($foo, 0, 4));
-  $counter++;
-}
-
-close FW;
-printf(FWH "};\t/* %d Tx instructions */\n#define FIRMWARE_TX_SIZE %d\n", $counter, $counter);
-close(FWH);
index 04ae1e86aeaa4c8b05ad6de192034f43e439420d..5e2dbaee125bcc1b520960dcbb6fe74623989a42 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/workqueue.h>
 #include <linux/prefetch.h>
 #include <linux/dma-mapping.h>
+#include <linux/firmware.h>
 
 #include <net/checksum.h>
 #include <net/ip.h>
 
 #define TG3_NUM_TEST           6
 
+#define FIRMWARE_TG3           "tigon/tg3.bin"
+#define FIRMWARE_TG3TSO                "tigon/tg3_tso.bin"
+#define FIRMWARE_TG3TSO5       "tigon/tg3_tso5.bin"
+
 static char version[] __devinitdata =
        DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 
@@ -144,6 +149,10 @@ MODULE_AUTHOR("David S. Miller (davem@redhat.com) and Jeff Garzik (jgarzik@pobox
 MODULE_DESCRIPTION("Broadcom Tigon3 ethernet driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_MODULE_VERSION);
+MODULE_FIRMWARE(FIRMWARE_TG3);
+MODULE_FIRMWARE(FIRMWARE_TG3TSO);
+MODULE_FIRMWARE(FIRMWARE_TG3TSO5);
+
 
 static int tg3_debug = -1;     /* -1 == use TG3_DEF_MSG_ENABLE as value */
 module_param(tg3_debug, int, 0);
@@ -6205,130 +6214,6 @@ static int tg3_halt(struct tg3 *tp, int kind, int silent)
        return 0;
 }
 
-#define TG3_FW_RELEASE_MAJOR   0x0
-#define TG3_FW_RELASE_MINOR    0x0
-#define TG3_FW_RELEASE_FIX     0x0
-#define TG3_FW_START_ADDR      0x08000000
-#define TG3_FW_TEXT_ADDR       0x08000000
-#define TG3_FW_TEXT_LEN                0x9c0
-#define TG3_FW_RODATA_ADDR     0x080009c0
-#define TG3_FW_RODATA_LEN      0x60
-#define TG3_FW_DATA_ADDR       0x08000a40
-#define TG3_FW_DATA_LEN                0x20
-#define TG3_FW_SBSS_ADDR       0x08000a60
-#define TG3_FW_SBSS_LEN                0xc
-#define TG3_FW_BSS_ADDR                0x08000a70
-#define TG3_FW_BSS_LEN         0x10
-
-static const u32 tg3FwText[(TG3_FW_TEXT_LEN / sizeof(u32)) + 1] = {
-       0x00000000, 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c1d0800,
-       0x37bd3ffc, 0x03a0f021, 0x3c100800, 0x26100000, 0x0e000018, 0x00000000,
-       0x0000000d, 0x3c1d0800, 0x37bd3ffc, 0x03a0f021, 0x3c100800, 0x26100034,
-       0x0e00021c, 0x00000000, 0x0000000d, 0x00000000, 0x00000000, 0x00000000,
-       0x27bdffe0, 0x3c1cc000, 0xafbf0018, 0xaf80680c, 0x0e00004c, 0x241b2105,
-       0x97850000, 0x97870002, 0x9782002c, 0x9783002e, 0x3c040800, 0x248409c0,
-       0xafa00014, 0x00021400, 0x00621825, 0x00052c00, 0xafa30010, 0x8f860010,
-       0x00e52825, 0x0e000060, 0x24070102, 0x3c02ac00, 0x34420100, 0x3c03ac01,
-       0x34630100, 0xaf820490, 0x3c02ffff, 0xaf820494, 0xaf830498, 0xaf82049c,
-       0x24020001, 0xaf825ce0, 0x0e00003f, 0xaf825d00, 0x0e000140, 0x00000000,
-       0x8fbf0018, 0x03e00008, 0x27bd0020, 0x2402ffff, 0xaf825404, 0x8f835400,
-       0x34630400, 0xaf835400, 0xaf825404, 0x3c020800, 0x24420034, 0xaf82541c,
-       0x03e00008, 0xaf805400, 0x00000000, 0x00000000, 0x3c020800, 0x34423000,
-       0x3c030800, 0x34633000, 0x3c040800, 0x348437ff, 0x3c010800, 0xac220a64,
-       0x24020040, 0x3c010800, 0xac220a68, 0x3c010800, 0xac200a60, 0xac600000,
-       0x24630004, 0x0083102b, 0x5040fffd, 0xac600000, 0x03e00008, 0x00000000,
-       0x00804821, 0x8faa0010, 0x3c020800, 0x8c420a60, 0x3c040800, 0x8c840a68,
-       0x8fab0014, 0x24430001, 0x0044102b, 0x3c010800, 0xac230a60, 0x14400003,
-       0x00004021, 0x3c010800, 0xac200a60, 0x3c020800, 0x8c420a60, 0x3c030800,
-       0x8c630a64, 0x91240000, 0x00021140, 0x00431021, 0x00481021, 0x25080001,
-       0xa0440000, 0x29020008, 0x1440fff4, 0x25290001, 0x3c020800, 0x8c420a60,
-       0x3c030800, 0x8c630a64, 0x8f84680c, 0x00021140, 0x00431021, 0xac440008,
-       0xac45000c, 0xac460010, 0xac470014, 0xac4a0018, 0x03e00008, 0xac4b001c,
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0,
-       0x02000008, 0x00000000, 0x0a0001e3, 0x3c0a0001, 0x0a0001e3, 0x3c0a0002,
-       0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000,
-       0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000,
-       0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000,
-       0x0a0001e3, 0x3c0a0007, 0x0a0001e3, 0x3c0a0008, 0x0a0001e3, 0x3c0a0009,
-       0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x3c0a000b,
-       0x0a0001e3, 0x3c0a000c, 0x0a0001e3, 0x3c0a000d, 0x0a0001e3, 0x00000000,
-       0x0a0001e3, 0x00000000, 0x0a0001e3, 0x3c0a000e, 0x0a0001e3, 0x00000000,
-       0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000,
-       0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000,
-       0x0a0001e3, 0x00000000, 0x0a0001e3, 0x3c0a0013, 0x0a0001e3, 0x3c0a0014,
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-       0x27bdffe0, 0x00001821, 0x00001021, 0xafbf0018, 0xafb10014, 0xafb00010,
-       0x3c010800, 0x00220821, 0xac200a70, 0x3c010800, 0x00220821, 0xac200a74,
-       0x3c010800, 0x00220821, 0xac200a78, 0x24630001, 0x1860fff5, 0x2442000c,
-       0x24110001, 0x8f906810, 0x32020004, 0x14400005, 0x24040001, 0x3c020800,
-       0x8c420a78, 0x18400003, 0x00002021, 0x0e000182, 0x00000000, 0x32020001,
-       0x10400003, 0x00000000, 0x0e000169, 0x00000000, 0x0a000153, 0xaf915028,
-       0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x3c050800,
-       0x8ca50a70, 0x3c060800, 0x8cc60a80, 0x3c070800, 0x8ce70a78, 0x27bdffe0,
-       0x3c040800, 0x248409d0, 0xafbf0018, 0xafa00010, 0x0e000060, 0xafa00014,
-       0x0e00017b, 0x00002021, 0x8fbf0018, 0x03e00008, 0x27bd0020, 0x24020001,
-       0x8f836810, 0x00821004, 0x00021027, 0x00621824, 0x03e00008, 0xaf836810,
-       0x27bdffd8, 0xafbf0024, 0x1080002e, 0xafb00020, 0x8f825cec, 0xafa20018,
-       0x8f825cec, 0x3c100800, 0x26100a78, 0xafa2001c, 0x34028000, 0xaf825cec,
-       0x8e020000, 0x18400016, 0x00000000, 0x3c020800, 0x94420a74, 0x8fa3001c,
-       0x000221c0, 0xac830004, 0x8fa2001c, 0x3c010800, 0x0e000201, 0xac220a74,
-       0x10400005, 0x00000000, 0x8e020000, 0x24420001, 0x0a0001df, 0xae020000,
-       0x3c020800, 0x8c420a70, 0x00021c02, 0x000321c0, 0x0a0001c5, 0xafa2001c,
-       0x0e000201, 0x00000000, 0x1040001f, 0x00000000, 0x8e020000, 0x8fa3001c,
-       0x24420001, 0x3c010800, 0xac230a70, 0x3c010800, 0xac230a74, 0x0a0001df,
-       0xae020000, 0x3c100800, 0x26100a78, 0x8e020000, 0x18400028, 0x00000000,
-       0x0e000201, 0x00000000, 0x14400024, 0x00000000, 0x8e020000, 0x3c030800,
-       0x8c630a70, 0x2442ffff, 0xafa3001c, 0x18400006, 0xae020000, 0x00031402,
-       0x000221c0, 0x8c820004, 0x3c010800, 0xac220a70, 0x97a2001e, 0x2442ff00,
-       0x2c420300, 0x1440000b, 0x24024000, 0x3c040800, 0x248409dc, 0xafa00010,
-       0xafa00014, 0x8fa6001c, 0x24050008, 0x0e000060, 0x00003821, 0x0a0001df,
-       0x00000000, 0xaf825cf8, 0x3c020800, 0x8c420a40, 0x8fa3001c, 0x24420001,
-       0xaf835cf8, 0x3c010800, 0xac220a40, 0x8fbf0024, 0x8fb00020, 0x03e00008,
-       0x27bd0028, 0x27bdffe0, 0x3c040800, 0x248409e8, 0x00002821, 0x00003021,
-       0x00003821, 0xafbf0018, 0xafa00010, 0x0e000060, 0xafa00014, 0x8fbf0018,
-       0x03e00008, 0x27bd0020, 0x8f82680c, 0x8f85680c, 0x00021827, 0x0003182b,
-       0x00031823, 0x00431024, 0x00441021, 0x00a2282b, 0x10a00006, 0x00000000,
-       0x00401821, 0x8f82680c, 0x0043102b, 0x1440fffd, 0x00000000, 0x03e00008,
-       0x00000000, 0x3c040800, 0x8c840000, 0x3c030800, 0x8c630a40, 0x0064102b,
-       0x54400002, 0x00831023, 0x00641023, 0x2c420008, 0x03e00008, 0x38420001,
-       0x27bdffe0, 0x00802821, 0x3c040800, 0x24840a00, 0x00003021, 0x00003821,
-       0xafbf0018, 0xafa00010, 0x0e000060, 0xafa00014, 0x0a000216, 0x00000000,
-       0x8fbf0018, 0x03e00008, 0x27bd0020, 0x00000000, 0x27bdffe0, 0x3c1cc000,
-       0xafbf0018, 0x0e00004c, 0xaf80680c, 0x3c040800, 0x24840a10, 0x03802821,
-       0x00003021, 0x00003821, 0xafa00010, 0x0e000060, 0xafa00014, 0x2402ffff,
-       0xaf825404, 0x3c0200aa, 0x0e000234, 0xaf825434, 0x8fbf0018, 0x03e00008,
-       0x27bd0020, 0x00000000, 0x00000000, 0x00000000, 0x27bdffe8, 0xafb00010,
-       0x24100001, 0xafbf0014, 0x3c01c003, 0xac200000, 0x8f826810, 0x30422000,
-       0x10400003, 0x00000000, 0x0e000246, 0x00000000, 0x0a00023a, 0xaf905428,
-       0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x27bdfff8, 0x8f845d0c,
-       0x3c0200ff, 0x3c030800, 0x8c630a50, 0x3442fff8, 0x00821024, 0x1043001e,
-       0x3c0500ff, 0x34a5fff8, 0x3c06c003, 0x3c074000, 0x00851824, 0x8c620010,
-       0x3c010800, 0xac230a50, 0x30420008, 0x10400005, 0x00871025, 0x8cc20000,
-       0x24420001, 0xacc20000, 0x00871025, 0xaf825d0c, 0x8fa20000, 0x24420001,
-       0xafa20000, 0x8fa20000, 0x8fa20000, 0x24420001, 0xafa20000, 0x8fa20000,
-       0x8f845d0c, 0x3c030800, 0x8c630a50, 0x00851024, 0x1443ffe8, 0x00851824,
-       0x27bd0008, 0x03e00008, 0x00000000, 0x00000000, 0x00000000
-};
-
-static const u32 tg3FwRodata[(TG3_FW_RODATA_LEN / sizeof(u32)) + 1] = {
-       0x35373031, 0x726c7341, 0x00000000, 0x00000000, 0x53774576, 0x656e7430,
-       0x00000000, 0x726c7045, 0x76656e74, 0x31000000, 0x556e6b6e, 0x45766e74,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x66617461, 0x6c457272,
-       0x00000000, 0x00000000, 0x4d61696e, 0x43707542, 0x00000000, 0x00000000,
-       0x00000000
-};
-
-#if 0 /* All zeros, don't eat up space with it. */
-u32 tg3FwData[(TG3_FW_DATA_LEN / sizeof(u32)) + 1] = {
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000
-};
-#endif
-
 #define RX_CPU_SCRATCH_BASE    0x30000
 #define RX_CPU_SCRATCH_SIZE    0x04000
 #define TX_CPU_SCRATCH_BASE    0x34000
@@ -6383,15 +6268,9 @@ static int tg3_halt_cpu(struct tg3 *tp, u32 offset)
 }
 
 struct fw_info {
-       unsigned int text_base;
-       unsigned int text_len;
-       const u32 *text_data;
-       unsigned int rodata_base;
-       unsigned int rodata_len;
-       const u32 *rodata_data;
-       unsigned int data_base;
-       unsigned int data_len;
-       const u32 *data_data;
+       unsigned int fw_base;
+       unsigned int fw_len;
+       const __be32 *fw_data;
 };
 
 /* tp->lock is held. */
@@ -6428,24 +6307,11 @@ static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_b
                write_op(tp, cpu_scratch_base + i, 0);
        tw32(cpu_base + CPU_STATE, 0xffffffff);
        tw32(cpu_base + CPU_MODE, tr32(cpu_base+CPU_MODE)|CPU_MODE_HALT);
-       for (i = 0; i < (info->text_len / sizeof(u32)); i++)
-               write_op(tp, (cpu_scratch_base +
-                             (info->text_base & 0xffff) +
-                             (i * sizeof(u32))),
-                        (info->text_data ?
-                         info->text_data[i] : 0));
-       for (i = 0; i < (info->rodata_len / sizeof(u32)); i++)
-               write_op(tp, (cpu_scratch_base +
-                             (info->rodata_base & 0xffff) +
-                             (i * sizeof(u32))),
-                        (info->rodata_data ?
-                         info->rodata_data[i] : 0));
-       for (i = 0; i < (info->data_len / sizeof(u32)); i++)
+       for (i = 0; i < (info->fw_len / sizeof(u32)); i++)
                write_op(tp, (cpu_scratch_base +
-                             (info->data_base & 0xffff) +
+                             (info->fw_base & 0xffff) +
                              (i * sizeof(u32))),
-                        (info->data_data ?
-                         info->data_data[i] : 0));
+                             be32_to_cpu(info->fw_data[i]));
 
        err = 0;
 
@@ -6457,17 +6323,20 @@ out:
 static int tg3_load_5701_a0_firmware_fix(struct tg3 *tp)
 {
        struct fw_info info;
+       const __be32 *fw_data;
        int err, i;
 
-       info.text_base = TG3_FW_TEXT_ADDR;
-       info.text_len = TG3_FW_TEXT_LEN;
-       info.text_data = &tg3FwText[0];
-       info.rodata_base = TG3_FW_RODATA_ADDR;
-       info.rodata_len = TG3_FW_RODATA_LEN;
-       info.rodata_data = &tg3FwRodata[0];
-       info.data_base = TG3_FW_DATA_ADDR;
-       info.data_len = TG3_FW_DATA_LEN;
-       info.data_data = NULL;
+       fw_data = (void *)tp->fw->data;
+
+       /* Firmware blob starts with version numbers, followed by
+          start address and length. We are setting complete length.
+          length = end_address_of_bss - start_address_of_text.
+          Remainder is the blob to be loaded contiguously
+          from start address. */
+
+       info.fw_base = be32_to_cpu(fw_data[1]);
+       info.fw_len = tp->fw->size - 12;
+       info.fw_data = &fw_data[3];
 
        err = tg3_load_firmware_cpu(tp, RX_CPU_BASE,
                                    RX_CPU_SCRATCH_BASE, RX_CPU_SCRATCH_SIZE,
@@ -6483,21 +6352,21 @@ static int tg3_load_5701_a0_firmware_fix(struct tg3 *tp)
 
        /* Now startup only the RX cpu. */
        tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
-       tw32_f(RX_CPU_BASE + CPU_PC,    TG3_FW_TEXT_ADDR);
+       tw32_f(RX_CPU_BASE + CPU_PC, info.fw_base);
 
        for (i = 0; i < 5; i++) {
-               if (tr32(RX_CPU_BASE + CPU_PC) == TG3_FW_TEXT_ADDR)
+               if (tr32(RX_CPU_BASE + CPU_PC) == info.fw_base)
                        break;
                tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
                tw32(RX_CPU_BASE + CPU_MODE,  CPU_MODE_HALT);
-               tw32_f(RX_CPU_BASE + CPU_PC,    TG3_FW_TEXT_ADDR);
+               tw32_f(RX_CPU_BASE + CPU_PC, info.fw_base);
                udelay(1000);
        }
        if (i >= 5) {
                printk(KERN_ERR PFX "tg3_load_firmware fails for %s "
                       "to set RX CPU PC, is %08x should be %08x\n",
                       tp->dev->name, tr32(RX_CPU_BASE + CPU_PC),
-                      TG3_FW_TEXT_ADDR);
+                      info.fw_base);
                return -ENODEV;
        }
        tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
@@ -6506,547 +6375,36 @@ static int tg3_load_5701_a0_firmware_fix(struct tg3 *tp)
        return 0;
 }
 
-
-#define TG3_TSO_FW_RELEASE_MAJOR       0x1
-#define TG3_TSO_FW_RELASE_MINOR                0x6
-#define TG3_TSO_FW_RELEASE_FIX         0x0
-#define TG3_TSO_FW_START_ADDR          0x08000000
-#define TG3_TSO_FW_TEXT_ADDR           0x08000000
-#define TG3_TSO_FW_TEXT_LEN            0x1aa0
-#define TG3_TSO_FW_RODATA_ADDR         0x08001aa0
-#define TG3_TSO_FW_RODATA_LEN          0x60
-#define TG3_TSO_FW_DATA_ADDR           0x08001b20
-#define TG3_TSO_FW_DATA_LEN            0x30
-#define TG3_TSO_FW_SBSS_ADDR           0x08001b50
-#define TG3_TSO_FW_SBSS_LEN            0x2c
-#define TG3_TSO_FW_BSS_ADDR            0x08001b80
-#define TG3_TSO_FW_BSS_LEN             0x894
-
-static const u32 tg3TsoFwText[(TG3_TSO_FW_TEXT_LEN / 4) + 1] = {
-       0x0e000003, 0x00000000, 0x08001b24, 0x00000000, 0x10000003, 0x00000000,
-       0x0000000d, 0x0000000d, 0x3c1d0800, 0x37bd4000, 0x03a0f021, 0x3c100800,
-       0x26100000, 0x0e000010, 0x00000000, 0x0000000d, 0x27bdffe0, 0x3c04fefe,
-       0xafbf0018, 0x0e0005d8, 0x34840002, 0x0e000668, 0x00000000, 0x3c030800,
-       0x90631b68, 0x24020002, 0x3c040800, 0x24841aac, 0x14620003, 0x24050001,
-       0x3c040800, 0x24841aa0, 0x24060006, 0x00003821, 0xafa00010, 0x0e00067c,
-       0xafa00014, 0x8f625c50, 0x34420001, 0xaf625c50, 0x8f625c90, 0x34420001,
-       0xaf625c90, 0x2402ffff, 0x0e000034, 0xaf625404, 0x8fbf0018, 0x03e00008,
-       0x27bd0020, 0x00000000, 0x00000000, 0x00000000, 0x27bdffe0, 0xafbf001c,
-       0xafb20018, 0xafb10014, 0x0e00005b, 0xafb00010, 0x24120002, 0x24110001,
-       0x8f706820, 0x32020100, 0x10400003, 0x00000000, 0x0e0000bb, 0x00000000,
-       0x8f706820, 0x32022000, 0x10400004, 0x32020001, 0x0e0001f0, 0x24040001,
-       0x32020001, 0x10400003, 0x00000000, 0x0e0000a3, 0x00000000, 0x3c020800,
-       0x90421b98, 0x14520003, 0x00000000, 0x0e0004c0, 0x00000000, 0x0a00003c,
-       0xaf715028, 0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x03e00008,
-       0x27bd0020, 0x27bdffe0, 0x3c040800, 0x24841ac0, 0x00002821, 0x00003021,
-       0x00003821, 0xafbf0018, 0xafa00010, 0x0e00067c, 0xafa00014, 0x3c040800,
-       0x248423d8, 0xa4800000, 0x3c010800, 0xa0201b98, 0x3c010800, 0xac201b9c,
-       0x3c010800, 0xac201ba0, 0x3c010800, 0xac201ba4, 0x3c010800, 0xac201bac,
-       0x3c010800, 0xac201bb8, 0x3c010800, 0xac201bbc, 0x8f624434, 0x3c010800,
-       0xac221b88, 0x8f624438, 0x3c010800, 0xac221b8c, 0x8f624410, 0xac80f7a8,
-       0x3c010800, 0xac201b84, 0x3c010800, 0xac2023e0, 0x3c010800, 0xac2023c8,
-       0x3c010800, 0xac2023cc, 0x3c010800, 0xac202400, 0x3c010800, 0xac221b90,
-       0x8f620068, 0x24030007, 0x00021702, 0x10430005, 0x00000000, 0x8f620068,
-       0x00021702, 0x14400004, 0x24020001, 0x3c010800, 0x0a000097, 0xac20240c,
-       0xac820034, 0x3c040800, 0x24841acc, 0x3c050800, 0x8ca5240c, 0x00003021,
-       0x00003821, 0xafa00010, 0x0e00067c, 0xafa00014, 0x8fbf0018, 0x03e00008,
-       0x27bd0020, 0x27bdffe0, 0x3c040800, 0x24841ad8, 0x00002821, 0x00003021,
-       0x00003821, 0xafbf0018, 0xafa00010, 0x0e00067c, 0xafa00014, 0x0e00005b,
-       0x00000000, 0x0e0000b4, 0x00002021, 0x8fbf0018, 0x03e00008, 0x27bd0020,
-       0x24020001, 0x8f636820, 0x00821004, 0x00021027, 0x00621824, 0x03e00008,
-       0xaf636820, 0x27bdffd0, 0xafbf002c, 0xafb60028, 0xafb50024, 0xafb40020,
-       0xafb3001c, 0xafb20018, 0xafb10014, 0xafb00010, 0x8f675c5c, 0x3c030800,
-       0x24631bbc, 0x8c620000, 0x14470005, 0x3c0200ff, 0x3c020800, 0x90421b98,
-       0x14400119, 0x3c0200ff, 0x3442fff8, 0x00e28824, 0xac670000, 0x00111902,
-       0x306300ff, 0x30e20003, 0x000211c0, 0x00622825, 0x00a04021, 0x00071602,
-       0x3c030800, 0x90631b98, 0x3044000f, 0x14600036, 0x00804821, 0x24020001,
-       0x3c010800, 0xa0221b98, 0x00051100, 0x00821025, 0x3c010800, 0xac201b9c,
-       0x3c010800, 0xac201ba0, 0x3c010800, 0xac201ba4, 0x3c010800, 0xac201bac,
-       0x3c010800, 0xac201bb8, 0x3c010800, 0xac201bb0, 0x3c010800, 0xac201bb4,
-       0x3c010800, 0xa42223d8, 0x9622000c, 0x30437fff, 0x3c010800, 0xa4222410,
-       0x30428000, 0x3c010800, 0xa4231bc6, 0x10400005, 0x24020001, 0x3c010800,
-       0xac2223f4, 0x0a000102, 0x2406003e, 0x24060036, 0x3c010800, 0xac2023f4,
-       0x9622000a, 0x3c030800, 0x94631bc6, 0x3c010800, 0xac2023f0, 0x3c010800,
-       0xac2023f8, 0x00021302, 0x00021080, 0x00c21021, 0x00621821, 0x3c010800,
-       0xa42223d0, 0x3c010800, 0x0a000115, 0xa4231b96, 0x9622000c, 0x3c010800,
-       0xa42223ec, 0x3c040800, 0x24841b9c, 0x8c820000, 0x00021100, 0x3c010800,
-       0x00220821, 0xac311bc8, 0x8c820000, 0x00021100, 0x3c010800, 0x00220821,
-       0xac271bcc, 0x8c820000, 0x25030001, 0x306601ff, 0x00021100, 0x3c010800,
-       0x00220821, 0xac261bd0, 0x8c820000, 0x00021100, 0x3c010800, 0x00220821,
-       0xac291bd4, 0x96230008, 0x3c020800, 0x8c421bac, 0x00432821, 0x3c010800,
-       0xac251bac, 0x9622000a, 0x30420004, 0x14400018, 0x00061100, 0x8f630c14,
-       0x3063000f, 0x2c620002, 0x1440000b, 0x3c02c000, 0x8f630c14, 0x3c020800,
-       0x8c421b40, 0x3063000f, 0x24420001, 0x3c010800, 0xac221b40, 0x2c620002,
-       0x1040fff7, 0x3c02c000, 0x00e21825, 0xaf635c5c, 0x8f625c50, 0x30420002,
-       0x10400014, 0x00000000, 0x0a000147, 0x00000000, 0x3c030800, 0x8c631b80,
-       0x3c040800, 0x94841b94, 0x01221025, 0x3c010800, 0xa42223da, 0x24020001,
-       0x3c010800, 0xac221bb8, 0x24630001, 0x0085202a, 0x3c010800, 0x10800003,
-       0xac231b80, 0x3c010800, 0xa4251b94, 0x3c060800, 0x24c61b9c, 0x8cc20000,
-       0x24420001, 0xacc20000, 0x28420080, 0x14400005, 0x00000000, 0x0e000656,
-       0x24040002, 0x0a0001e6, 0x00000000, 0x3c020800, 0x8c421bb8, 0x10400078,
-       0x24020001, 0x3c050800, 0x90a51b98, 0x14a20072, 0x00000000, 0x3c150800,
-       0x96b51b96, 0x3c040800, 0x8c841bac, 0x32a3ffff, 0x0083102a, 0x1440006c,
-       0x00000000, 0x14830003, 0x00000000, 0x3c010800, 0xac2523f0, 0x1060005c,
-       0x00009021, 0x24d60004, 0x0060a021, 0x24d30014, 0x8ec20000, 0x00028100,
-       0x3c110800, 0x02308821, 0x0e000625, 0x8e311bc8, 0x00402821, 0x10a00054,
-       0x00000000, 0x9628000a, 0x31020040, 0x10400005, 0x2407180c, 0x8e22000c,
-       0x2407188c, 0x00021400, 0xaca20018, 0x3c030800, 0x00701821, 0x8c631bd0,
-       0x3c020800, 0x00501021, 0x8c421bd4, 0x00031d00, 0x00021400, 0x00621825,
-       0xaca30014, 0x8ec30004, 0x96220008, 0x00432023, 0x3242ffff, 0x3083ffff,
-       0x00431021, 0x0282102a, 0x14400002, 0x02b23023, 0x00803021, 0x8e620000,
-       0x30c4ffff, 0x00441021, 0xae620000, 0x8e220000, 0xaca20000, 0x8e220004,
-       0x8e63fff4, 0x00431021, 0xaca20004, 0xa4a6000e, 0x8e62fff4, 0x00441021,
-       0xae62fff4, 0x96230008, 0x0043102a, 0x14400005, 0x02469021, 0x8e62fff0,
-       0xae60fff4, 0x24420001, 0xae62fff0, 0xaca00008, 0x3242ffff, 0x14540008,
-       0x24020305, 0x31020080, 0x54400001, 0x34e70010, 0x24020905, 0xa4a2000c,
-       0x0a0001cb, 0x34e70020, 0xa4a2000c, 0x3c020800, 0x8c4223f0, 0x10400003,
-       0x3c024b65, 0x0a0001d3, 0x34427654, 0x3c02b49a, 0x344289ab, 0xaca2001c,
-       0x30e2ffff, 0xaca20010, 0x0e0005a2, 0x00a02021, 0x3242ffff, 0x0054102b,
-       0x1440ffa9, 0x00000000, 0x24020002, 0x3c010800, 0x0a0001e6, 0xa0221b98,
-       0x8ec2083c, 0x24420001, 0x0a0001e6, 0xaec2083c, 0x0e0004c0, 0x00000000,
-       0x8fbf002c, 0x8fb60028, 0x8fb50024, 0x8fb40020, 0x8fb3001c, 0x8fb20018,
-       0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0030, 0x27bdffd0, 0xafbf0028,
-       0xafb30024, 0xafb20020, 0xafb1001c, 0xafb00018, 0x8f725c9c, 0x3c0200ff,
-       0x3442fff8, 0x3c070800, 0x24e71bb4, 0x02428824, 0x9623000e, 0x8ce20000,
-       0x00431021, 0xace20000, 0x8e220010, 0x30420020, 0x14400011, 0x00809821,
-       0x0e00063b, 0x02202021, 0x3c02c000, 0x02421825, 0xaf635c9c, 0x8f625c90,
-       0x30420002, 0x1040011e, 0x00000000, 0xaf635c9c, 0x8f625c90, 0x30420002,
-       0x10400119, 0x00000000, 0x0a00020d, 0x00000000, 0x8e240008, 0x8e230014,
-       0x00041402, 0x000231c0, 0x00031502, 0x304201ff, 0x2442ffff, 0x3042007f,
-       0x00031942, 0x30637800, 0x00021100, 0x24424000, 0x00624821, 0x9522000a,
-       0x3084ffff, 0x30420008, 0x104000b0, 0x000429c0, 0x3c020800, 0x8c422400,
-       0x14400024, 0x24c50008, 0x94c20014, 0x3c010800, 0xa42223d0, 0x8cc40010,
-       0x00041402, 0x3c010800, 0xa42223d2, 0x3c010800, 0xa42423d4, 0x94c2000e,
-       0x3083ffff, 0x00431023, 0x3c010800, 0xac222408, 0x94c2001a, 0x3c010800,
-       0xac262400, 0x3c010800, 0xac322404, 0x3c010800, 0xac2223fc, 0x3c02c000,
-       0x02421825, 0xaf635c9c, 0x8f625c90, 0x30420002, 0x104000e5, 0x00000000,
-       0xaf635c9c, 0x8f625c90, 0x30420002, 0x104000e0, 0x00000000, 0x0a000246,
-       0x00000000, 0x94c2000e, 0x3c030800, 0x946323d4, 0x00434023, 0x3103ffff,
-       0x2c620008, 0x1040001c, 0x00000000, 0x94c20014, 0x24420028, 0x00a22821,
-       0x00031042, 0x1840000b, 0x00002021, 0x24e60848, 0x00403821, 0x94a30000,
-       0x8cc20000, 0x24840001, 0x00431021, 0xacc20000, 0x0087102a, 0x1440fff9,
-       0x24a50002, 0x31020001, 0x1040001f, 0x3c024000, 0x3c040800, 0x248423fc,
-       0xa0a00001, 0x94a30000, 0x8c820000, 0x00431021, 0x0a000285, 0xac820000,
-       0x8f626800, 0x3c030010, 0x00431024, 0x10400009, 0x00000000, 0x94c2001a,
-       0x3c030800, 0x8c6323fc, 0x00431021, 0x3c010800, 0xac2223fc, 0x0a000286,
-       0x3c024000, 0x94c2001a, 0x94c4001c, 0x3c030800, 0x8c6323fc, 0x00441023,
-       0x00621821, 0x3c010800, 0xac2323fc, 0x3c024000, 0x02421825, 0xaf635c9c,
-       0x8f625c90, 0x30420002, 0x1440fffc, 0x00000000, 0x9522000a, 0x30420010,
-       0x1040009b, 0x00000000, 0x3c030800, 0x946323d4, 0x3c070800, 0x24e72400,
-       0x8ce40000, 0x8f626800, 0x24630030, 0x00832821, 0x3c030010, 0x00431024,
-       0x1440000a, 0x00000000, 0x94a20004, 0x3c040800, 0x8c842408, 0x3c030800,
-       0x8c6323fc, 0x00441023, 0x00621821, 0x3c010800, 0xac2323fc, 0x3c040800,
-       0x8c8423fc, 0x00041c02, 0x3082ffff, 0x00622021, 0x00041402, 0x00822021,
-       0x00041027, 0xa4a20006, 0x3c030800, 0x8c632404, 0x3c0200ff, 0x3442fff8,
-       0x00628824, 0x96220008, 0x24050001, 0x24034000, 0x000231c0, 0x00801021,
-       0xa4c2001a, 0xa4c0001c, 0xace00000, 0x3c010800, 0xac251b60, 0xaf635cb8,
-       0x8f625cb0, 0x30420002, 0x10400003, 0x00000000, 0x3c010800, 0xac201b60,
-       0x8e220008, 0xaf625cb8, 0x8f625cb0, 0x30420002, 0x10400003, 0x00000000,
-       0x3c010800, 0xac201b60, 0x3c020800, 0x8c421b60, 0x1040ffec, 0x00000000,
-       0x3c040800, 0x0e00063b, 0x8c842404, 0x0a00032a, 0x00000000, 0x3c030800,
-       0x90631b98, 0x24020002, 0x14620003, 0x3c034b65, 0x0a0002e1, 0x00008021,
-       0x8e22001c, 0x34637654, 0x10430002, 0x24100002, 0x24100001, 0x00c02021,
-       0x0e000350, 0x02003021, 0x24020003, 0x3c010800, 0xa0221b98, 0x24020002,
-       0x1202000a, 0x24020001, 0x3c030800, 0x8c6323f0, 0x10620006, 0x00000000,
-       0x3c020800, 0x944223d8, 0x00021400, 0x0a00031f, 0xae220014, 0x3c040800,
-       0x248423da, 0x94820000, 0x00021400, 0xae220014, 0x3c020800, 0x8c421bbc,
-       0x3c03c000, 0x3c010800, 0xa0201b98, 0x00431025, 0xaf625c5c, 0x8f625c50,
-       0x30420002, 0x10400009, 0x00000000, 0x2484f7e2, 0x8c820000, 0x00431025,
-       0xaf625c5c, 0x8f625c50, 0x30420002, 0x1440fffa, 0x00000000, 0x3c020800,
-       0x24421b84, 0x8c430000, 0x24630001, 0xac430000, 0x8f630c14, 0x3063000f,
-       0x2c620002, 0x1440000c, 0x3c024000, 0x8f630c14, 0x3c020800, 0x8c421b40,
-       0x3063000f, 0x24420001, 0x3c010800, 0xac221b40, 0x2c620002, 0x1040fff7,
-       0x00000000, 0x3c024000, 0x02421825, 0xaf635c9c, 0x8f625c90, 0x30420002,
-       0x1440fffc, 0x00000000, 0x12600003, 0x00000000, 0x0e0004c0, 0x00000000,
-       0x8fbf0028, 0x8fb30024, 0x8fb20020, 0x8fb1001c, 0x8fb00018, 0x03e00008,
-       0x27bd0030, 0x8f634450, 0x3c040800, 0x24841b88, 0x8c820000, 0x00031c02,
-       0x0043102b, 0x14400007, 0x3c038000, 0x8c840004, 0x8f624450, 0x00021c02,
-       0x0083102b, 0x1040fffc, 0x3c038000, 0xaf634444, 0x8f624444, 0x00431024,
-       0x1440fffd, 0x00000000, 0x8f624448, 0x03e00008, 0x3042ffff, 0x3c024000,
-       0x00822025, 0xaf645c38, 0x8f625c30, 0x30420002, 0x1440fffc, 0x00000000,
-       0x03e00008, 0x00000000, 0x27bdffe0, 0x00805821, 0x14c00011, 0x256e0008,
-       0x3c020800, 0x8c4223f4, 0x10400007, 0x24020016, 0x3c010800, 0xa42223d2,
-       0x2402002a, 0x3c010800, 0x0a000364, 0xa42223d4, 0x8d670010, 0x00071402,
-       0x3c010800, 0xa42223d2, 0x3c010800, 0xa42723d4, 0x3c040800, 0x948423d4,
-       0x3c030800, 0x946323d2, 0x95cf0006, 0x3c020800, 0x944223d0, 0x00832023,
-       0x01e2c023, 0x3065ffff, 0x24a20028, 0x01c24821, 0x3082ffff, 0x14c0001a,
-       0x01226021, 0x9582000c, 0x3042003f, 0x3c010800, 0xa42223d6, 0x95820004,
-       0x95830006, 0x3c010800, 0xac2023e4, 0x3c010800, 0xac2023e8, 0x00021400,
-       0x00431025, 0x3c010800, 0xac221bc0, 0x95220004, 0x3c010800, 0xa4221bc4,
-       0x95230002, 0x01e51023, 0x0043102a, 0x10400010, 0x24020001, 0x3c010800,
-       0x0a000398, 0xac2223f8, 0x3c030800, 0x8c6323e8, 0x3c020800, 0x94421bc4,
-       0x00431021, 0xa5220004, 0x3c020800, 0x94421bc0, 0xa5820004, 0x3c020800,
-       0x8c421bc0, 0xa5820006, 0x3c020800, 0x8c4223f0, 0x3c0d0800, 0x8dad23e4,
-       0x3c0a0800, 0x144000e5, 0x8d4a23e8, 0x3c020800, 0x94421bc4, 0x004a1821,
-       0x3063ffff, 0x0062182b, 0x24020002, 0x10c2000d, 0x01435023, 0x3c020800,
-       0x944223d6, 0x30420009, 0x10400008, 0x00000000, 0x9582000c, 0x3042fff6,
-       0xa582000c, 0x3c020800, 0x944223d6, 0x30420009, 0x01a26823, 0x3c020800,
-       0x8c4223f8, 0x1040004a, 0x01203821, 0x3c020800, 0x944223d2, 0x00004021,
-       0xa520000a, 0x01e21023, 0xa5220002, 0x3082ffff, 0x00021042, 0x18400008,
-       0x00003021, 0x00401821, 0x94e20000, 0x25080001, 0x00c23021, 0x0103102a,
-       0x1440fffb, 0x24e70002, 0x00061c02, 0x30c2ffff, 0x00623021, 0x00061402,
-       0x00c23021, 0x00c02821, 0x00061027, 0xa522000a, 0x00003021, 0x2527000c,
-       0x00004021, 0x94e20000, 0x25080001, 0x00c23021, 0x2d020004, 0x1440fffb,
-       0x24e70002, 0x95220002, 0x00004021, 0x91230009, 0x00442023, 0x01803821,
-       0x3082ffff, 0xa4e00010, 0x00621821, 0x00021042, 0x18400010, 0x00c33021,
-       0x00404821, 0x94e20000, 0x24e70002, 0x00c23021, 0x30e2007f, 0x14400006,
-       0x25080001, 0x8d630000, 0x3c02007f, 0x3442ff80, 0x00625824, 0x25670008,
-       0x0109102a, 0x1440fff3, 0x00000000, 0x30820001, 0x10400005, 0x00061c02,
-       0xa0e00001, 0x94e20000, 0x00c23021, 0x00061c02, 0x30c2ffff, 0x00623021,
-       0x00061402, 0x00c23021, 0x0a00047d, 0x30c6ffff, 0x24020002, 0x14c20081,
-       0x00000000, 0x3c020800, 0x8c42240c, 0x14400007, 0x00000000, 0x3c020800,
-       0x944223d2, 0x95230002, 0x01e21023, 0x10620077, 0x00000000, 0x3c020800,
-       0x944223d2, 0x01e21023, 0xa5220002, 0x3c020800, 0x8c42240c, 0x1040001a,
-       0x31e3ffff, 0x8dc70010, 0x3c020800, 0x94421b96, 0x00e04021, 0x00072c02,
-       0x00aa2021, 0x00431023, 0x00823823, 0x00072402, 0x30e2ffff, 0x00823821,
-       0x00071027, 0xa522000a, 0x3102ffff, 0x3c040800, 0x948423d4, 0x00453023,
-       0x00e02821, 0x00641823, 0x006d1821, 0x00c33021, 0x00061c02, 0x30c2ffff,
-       0x0a00047d, 0x00623021, 0x01203821, 0x00004021, 0x3082ffff, 0x00021042,
-       0x18400008, 0x00003021, 0x00401821, 0x94e20000, 0x25080001, 0x00c23021,
-       0x0103102a, 0x1440fffb, 0x24e70002, 0x00061c02, 0x30c2ffff, 0x00623021,
-       0x00061402, 0x00c23021, 0x00c02821, 0x00061027, 0xa522000a, 0x00003021,
-       0x2527000c, 0x00004021, 0x94e20000, 0x25080001, 0x00c23021, 0x2d020004,
-       0x1440fffb, 0x24e70002, 0x95220002, 0x00004021, 0x91230009, 0x00442023,
-       0x01803821, 0x3082ffff, 0xa4e00010, 0x3c040800, 0x948423d4, 0x00621821,
-       0x00c33021, 0x00061c02, 0x30c2ffff, 0x00623021, 0x00061c02, 0x3c020800,
-       0x944223d0, 0x00c34821, 0x00441023, 0x00021fc2, 0x00431021, 0x00021043,
-       0x18400010, 0x00003021, 0x00402021, 0x94e20000, 0x24e70002, 0x00c23021,
-       0x30e2007f, 0x14400006, 0x25080001, 0x8d630000, 0x3c02007f, 0x3442ff80,
-       0x00625824, 0x25670008, 0x0104102a, 0x1440fff3, 0x00000000, 0x3c020800,
-       0x944223ec, 0x00c23021, 0x3122ffff, 0x00c23021, 0x00061c02, 0x30c2ffff,
-       0x00623021, 0x00061402, 0x00c23021, 0x00c04021, 0x00061027, 0xa5820010,
-       0xadc00014, 0x0a00049d, 0xadc00000, 0x8dc70010, 0x00e04021, 0x11400007,
-       0x00072c02, 0x00aa3021, 0x00061402, 0x30c3ffff, 0x00433021, 0x00061402,
-       0x00c22821, 0x00051027, 0xa522000a, 0x3c030800, 0x946323d4, 0x3102ffff,
-       0x01e21021, 0x00433023, 0x00cd3021, 0x00061c02, 0x30c2ffff, 0x00623021,
-       0x00061402, 0x00c23021, 0x00c04021, 0x00061027, 0xa5820010, 0x3102ffff,
-       0x00051c00, 0x00431025, 0xadc20010, 0x3c020800, 0x8c4223f4, 0x10400005,
-       0x2de205eb, 0x14400002, 0x25e2fff2, 0x34028870, 0xa5c20034, 0x3c030800,
-       0x246323e8, 0x8c620000, 0x24420001, 0xac620000, 0x3c040800, 0x8c8423e4,
-       0x3c020800, 0x8c421bc0, 0x3303ffff, 0x00832021, 0x00431821, 0x0062102b,
-       0x3c010800, 0xac2423e4, 0x10400003, 0x2482ffff, 0x3c010800, 0xac2223e4,
-       0x3c010800, 0xac231bc0, 0x03e00008, 0x27bd0020, 0x27bdffb8, 0x3c050800,
-       0x24a51b96, 0xafbf0044, 0xafbe0040, 0xafb7003c, 0xafb60038, 0xafb50034,
-       0xafb40030, 0xafb3002c, 0xafb20028, 0xafb10024, 0xafb00020, 0x94a90000,
-       0x3c020800, 0x944223d0, 0x3c030800, 0x8c631bb0, 0x3c040800, 0x8c841bac,
-       0x01221023, 0x0064182a, 0xa7a9001e, 0x106000be, 0xa7a20016, 0x24be0022,
-       0x97b6001e, 0x24b3001a, 0x24b70016, 0x8fc20000, 0x14400008, 0x00000000,
-       0x8fc2fff8, 0x97a30016, 0x8fc4fff4, 0x00431021, 0x0082202a, 0x148000b0,
-       0x00000000, 0x97d50818, 0x32a2ffff, 0x104000a3, 0x00009021, 0x0040a021,
-       0x00008821, 0x0e000625, 0x00000000, 0x00403021, 0x14c00007, 0x00000000,
-       0x3c020800, 0x8c4223dc, 0x24420001, 0x3c010800, 0x0a000596, 0xac2223dc,
-       0x3c100800, 0x02118021, 0x8e101bc8, 0x9608000a, 0x31020040, 0x10400005,
-       0x2407180c, 0x8e02000c, 0x2407188c, 0x00021400, 0xacc20018, 0x31020080,
-       0x54400001, 0x34e70010, 0x3c020800, 0x00511021, 0x8c421bd0, 0x3c030800,
-       0x00711821, 0x8c631bd4, 0x00021500, 0x00031c00, 0x00431025, 0xacc20014,
-       0x96040008, 0x3242ffff, 0x00821021, 0x0282102a, 0x14400002, 0x02b22823,
-       0x00802821, 0x8e020000, 0x02459021, 0xacc20000, 0x8e020004, 0x00c02021,
-       0x26310010, 0xac820004, 0x30e2ffff, 0xac800008, 0xa485000e, 0xac820010,
-       0x24020305, 0x0e0005a2, 0xa482000c, 0x3242ffff, 0x0054102b, 0x1440ffc5,
-       0x3242ffff, 0x0a00058e, 0x00000000, 0x8e620000, 0x8e63fffc, 0x0043102a,
-       0x10400067, 0x00000000, 0x8e62fff0, 0x00028900, 0x3c100800, 0x02118021,
-       0x0e000625, 0x8e101bc8, 0x00403021, 0x14c00005, 0x00000000, 0x8e62082c,
-       0x24420001, 0x0a000596, 0xae62082c, 0x9608000a, 0x31020040, 0x10400005,
-       0x2407180c, 0x8e02000c, 0x2407188c, 0x00021400, 0xacc20018, 0x3c020800,
-       0x00511021, 0x8c421bd0, 0x3c030800, 0x00711821, 0x8c631bd4, 0x00021500,
-       0x00031c00, 0x00431025, 0xacc20014, 0x8e63fff4, 0x96020008, 0x00432023,
-       0x3242ffff, 0x3083ffff, 0x00431021, 0x02c2102a, 0x10400003, 0x00802821,
-       0x97a9001e, 0x01322823, 0x8e620000, 0x30a4ffff, 0x00441021, 0xae620000,
-       0xa4c5000e, 0x8e020000, 0xacc20000, 0x8e020004, 0x8e63fff4, 0x00431021,
-       0xacc20004, 0x8e63fff4, 0x96020008, 0x00641821, 0x0062102a, 0x14400006,
-       0x02459021, 0x8e62fff0, 0xae60fff4, 0x24420001, 0x0a000571, 0xae62fff0,
-       0xae63fff4, 0xacc00008, 0x3242ffff, 0x10560003, 0x31020004, 0x10400006,
-       0x24020305, 0x31020080, 0x54400001, 0x34e70010, 0x34e70020, 0x24020905,
-       0xa4c2000c, 0x8ee30000, 0x8ee20004, 0x14620007, 0x3c02b49a, 0x8ee20860,
-       0x54400001, 0x34e70400, 0x3c024b65, 0x0a000588, 0x34427654, 0x344289ab,
-       0xacc2001c, 0x30e2ffff, 0xacc20010, 0x0e0005a2, 0x00c02021, 0x3242ffff,
-       0x0056102b, 0x1440ff9b, 0x00000000, 0x8e620000, 0x8e63fffc, 0x0043102a,
-       0x1440ff48, 0x00000000, 0x8fbf0044, 0x8fbe0040, 0x8fb7003c, 0x8fb60038,
-       0x8fb50034, 0x8fb40030, 0x8fb3002c, 0x8fb20028, 0x8fb10024, 0x8fb00020,
-       0x03e00008, 0x27bd0048, 0x27bdffe8, 0xafbf0014, 0xafb00010, 0x8f624450,
-       0x8f634410, 0x0a0005b1, 0x00808021, 0x8f626820, 0x30422000, 0x10400003,
-       0x00000000, 0x0e0001f0, 0x00002021, 0x8f624450, 0x8f634410, 0x3042ffff,
-       0x0043102b, 0x1440fff5, 0x00000000, 0x8f630c14, 0x3063000f, 0x2c620002,
-       0x1440000b, 0x00000000, 0x8f630c14, 0x3c020800, 0x8c421b40, 0x3063000f,
-       0x24420001, 0x3c010800, 0xac221b40, 0x2c620002, 0x1040fff7, 0x00000000,
-       0xaf705c18, 0x8f625c10, 0x30420002, 0x10400009, 0x00000000, 0x8f626820,
-       0x30422000, 0x1040fff8, 0x00000000, 0x0e0001f0, 0x00002021, 0x0a0005c4,
-       0x00000000, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x00000000,
-       0x00000000, 0x00000000, 0x27bdffe8, 0x3c1bc000, 0xafbf0014, 0xafb00010,
-       0xaf60680c, 0x8f626804, 0x34420082, 0xaf626804, 0x8f634000, 0x24020b50,
-       0x3c010800, 0xac221b54, 0x24020b78, 0x3c010800, 0xac221b64, 0x34630002,
-       0xaf634000, 0x0e000605, 0x00808021, 0x3c010800, 0xa0221b68, 0x304200ff,
-       0x24030002, 0x14430005, 0x00000000, 0x3c020800, 0x8c421b54, 0x0a0005f8,
-       0xac5000c0, 0x3c020800, 0x8c421b54, 0xac5000bc, 0x8f624434, 0x8f634438,
-       0x8f644410, 0x3c010800, 0xac221b5c, 0x3c010800, 0xac231b6c, 0x3c010800,
-       0xac241b58, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x3c040800,
-       0x8c870000, 0x3c03aa55, 0x3463aa55, 0x3c06c003, 0xac830000, 0x8cc20000,
-       0x14430007, 0x24050002, 0x3c0355aa, 0x346355aa, 0xac830000, 0x8cc20000,
-       0x50430001, 0x24050001, 0x3c020800, 0xac470000, 0x03e00008, 0x00a01021,
-       0x27bdfff8, 0x18800009, 0x00002821, 0x8f63680c, 0x8f62680c, 0x1043fffe,
-       0x00000000, 0x24a50001, 0x00a4102a, 0x1440fff9, 0x00000000, 0x03e00008,
-       0x27bd0008, 0x8f634450, 0x3c020800, 0x8c421b5c, 0x00031c02, 0x0043102b,
-       0x14400008, 0x3c038000, 0x3c040800, 0x8c841b6c, 0x8f624450, 0x00021c02,
-       0x0083102b, 0x1040fffc, 0x3c038000, 0xaf634444, 0x8f624444, 0x00431024,
-       0x1440fffd, 0x00000000, 0x8f624448, 0x03e00008, 0x3042ffff, 0x3082ffff,
-       0x2442e000, 0x2c422001, 0x14400003, 0x3c024000, 0x0a000648, 0x2402ffff,
-       0x00822025, 0xaf645c38, 0x8f625c30, 0x30420002, 0x1440fffc, 0x00001021,
-       0x03e00008, 0x00000000, 0x8f624450, 0x3c030800, 0x8c631b58, 0x0a000651,
-       0x3042ffff, 0x8f624450, 0x3042ffff, 0x0043102b, 0x1440fffc, 0x00000000,
-       0x03e00008, 0x00000000, 0x27bdffe0, 0x00802821, 0x3c040800, 0x24841af0,
-       0x00003021, 0x00003821, 0xafbf0018, 0xafa00010, 0x0e00067c, 0xafa00014,
-       0x0a000660, 0x00000000, 0x8fbf0018, 0x03e00008, 0x27bd0020, 0x00000000,
-       0x00000000, 0x00000000, 0x3c020800, 0x34423000, 0x3c030800, 0x34633000,
-       0x3c040800, 0x348437ff, 0x3c010800, 0xac221b74, 0x24020040, 0x3c010800,
-       0xac221b78, 0x3c010800, 0xac201b70, 0xac600000, 0x24630004, 0x0083102b,
-       0x5040fffd, 0xac600000, 0x03e00008, 0x00000000, 0x00804821, 0x8faa0010,
-       0x3c020800, 0x8c421b70, 0x3c040800, 0x8c841b78, 0x8fab0014, 0x24430001,
-       0x0044102b, 0x3c010800, 0xac231b70, 0x14400003, 0x00004021, 0x3c010800,
-       0xac201b70, 0x3c020800, 0x8c421b70, 0x3c030800, 0x8c631b74, 0x91240000,
-       0x00021140, 0x00431021, 0x00481021, 0x25080001, 0xa0440000, 0x29020008,
-       0x1440fff4, 0x25290001, 0x3c020800, 0x8c421b70, 0x3c030800, 0x8c631b74,
-       0x8f64680c, 0x00021140, 0x00431021, 0xac440008, 0xac45000c, 0xac460010,
-       0xac470014, 0xac4a0018, 0x03e00008, 0xac4b001c, 0x00000000, 0x00000000,
-};
-
-static const u32 tg3TsoFwRodata[] = {
-       0x4d61696e, 0x43707542, 0x00000000, 0x4d61696e, 0x43707541, 0x00000000,
-       0x00000000, 0x00000000, 0x73746b6f, 0x66666c64, 0x496e0000, 0x73746b6f,
-       0x66662a2a, 0x00000000, 0x53774576, 0x656e7430, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x66617461, 0x6c457272, 0x00000000, 0x00000000,
-       0x00000000,
-};
-
-static const u32 tg3TsoFwData[] = {
-       0x00000000, 0x73746b6f, 0x66666c64, 0x5f76312e, 0x362e3000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000,
-};
-
 /* 5705 needs a special version of the TSO firmware.  */
-#define TG3_TSO5_FW_RELEASE_MAJOR      0x1
-#define TG3_TSO5_FW_RELASE_MINOR       0x2
-#define TG3_TSO5_FW_RELEASE_FIX                0x0
-#define TG3_TSO5_FW_START_ADDR         0x00010000
-#define TG3_TSO5_FW_TEXT_ADDR          0x00010000
-#define TG3_TSO5_FW_TEXT_LEN           0xe90
-#define TG3_TSO5_FW_RODATA_ADDR                0x00010e90
-#define TG3_TSO5_FW_RODATA_LEN         0x50
-#define TG3_TSO5_FW_DATA_ADDR          0x00010f00
-#define TG3_TSO5_FW_DATA_LEN           0x20
-#define TG3_TSO5_FW_SBSS_ADDR          0x00010f20
-#define TG3_TSO5_FW_SBSS_LEN           0x28
-#define TG3_TSO5_FW_BSS_ADDR           0x00010f50
-#define TG3_TSO5_FW_BSS_LEN            0x88
-
-static const u32 tg3Tso5FwText[(TG3_TSO5_FW_TEXT_LEN / 4) + 1] = {
-       0x0c004003, 0x00000000, 0x00010f04, 0x00000000, 0x10000003, 0x00000000,
-       0x0000000d, 0x0000000d, 0x3c1d0001, 0x37bde000, 0x03a0f021, 0x3c100001,
-       0x26100000, 0x0c004010, 0x00000000, 0x0000000d, 0x27bdffe0, 0x3c04fefe,
-       0xafbf0018, 0x0c0042e8, 0x34840002, 0x0c004364, 0x00000000, 0x3c030001,
-       0x90630f34, 0x24020002, 0x3c040001, 0x24840e9c, 0x14620003, 0x24050001,
-       0x3c040001, 0x24840e90, 0x24060002, 0x00003821, 0xafa00010, 0x0c004378,
-       0xafa00014, 0x0c00402c, 0x00000000, 0x8fbf0018, 0x03e00008, 0x27bd0020,
-       0x00000000, 0x00000000, 0x27bdffe0, 0xafbf001c, 0xafb20018, 0xafb10014,
-       0x0c0042d4, 0xafb00010, 0x3c128000, 0x24110001, 0x8f706810, 0x32020400,
-       0x10400007, 0x00000000, 0x8f641008, 0x00921024, 0x14400003, 0x00000000,
-       0x0c004064, 0x00000000, 0x3c020001, 0x90420f56, 0x10510003, 0x32020200,
-       0x1040fff1, 0x00000000, 0x0c0041b4, 0x00000000, 0x08004034, 0x00000000,
-       0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020,
-       0x27bdffe0, 0x3c040001, 0x24840eb0, 0x00002821, 0x00003021, 0x00003821,
-       0xafbf0018, 0xafa00010, 0x0c004378, 0xafa00014, 0x0000d021, 0x24020130,
-       0xaf625000, 0x3c010001, 0xa4200f50, 0x3c010001, 0xa0200f57, 0x8fbf0018,
-       0x03e00008, 0x27bd0020, 0x00000000, 0x00000000, 0x3c030001, 0x24630f60,
-       0x90620000, 0x27bdfff0, 0x14400003, 0x0080c021, 0x08004073, 0x00004821,
-       0x3c022000, 0x03021024, 0x10400003, 0x24090002, 0x08004073, 0xa0600000,
-       0x24090001, 0x00181040, 0x30431f80, 0x346f8008, 0x1520004b, 0x25eb0028,
-       0x3c040001, 0x00832021, 0x8c848010, 0x3c050001, 0x24a50f7a, 0x00041402,
-       0xa0a20000, 0x3c010001, 0xa0240f7b, 0x3c020001, 0x00431021, 0x94428014,
-       0x3c010001, 0xa0220f7c, 0x3c0c0001, 0x01836021, 0x8d8c8018, 0x304200ff,
-       0x24420008, 0x000220c3, 0x24020001, 0x3c010001, 0xa0220f60, 0x0124102b,
-       0x1040000c, 0x00003821, 0x24a6000e, 0x01602821, 0x8ca20000, 0x8ca30004,
-       0x24a50008, 0x24e70001, 0xacc20000, 0xacc30004, 0x00e4102b, 0x1440fff8,
-       0x24c60008, 0x00003821, 0x3c080001, 0x25080f7b, 0x91060000, 0x3c020001,
-       0x90420f7c, 0x2503000d, 0x00c32821, 0x00461023, 0x00021fc2, 0x00431021,
-       0x00021043, 0x1840000c, 0x00002021, 0x91020001, 0x00461023, 0x00021fc2,
-       0x00431021, 0x00021843, 0x94a20000, 0x24e70001, 0x00822021, 0x00e3102a,
-       0x1440fffb, 0x24a50002, 0x00041c02, 0x3082ffff, 0x00622021, 0x00041402,
-       0x00822021, 0x3c02ffff, 0x01821024, 0x3083ffff, 0x00431025, 0x3c010001,
-       0x080040fa, 0xac220f80, 0x3c050001, 0x24a50f7c, 0x90a20000, 0x3c0c0001,
-       0x01836021, 0x8d8c8018, 0x000220c2, 0x1080000e, 0x00003821, 0x01603021,
-       0x24a5000c, 0x8ca20000, 0x8ca30004, 0x24a50008, 0x24e70001, 0xacc20000,
-       0xacc30004, 0x00e4102b, 0x1440fff8, 0x24c60008, 0x3c050001, 0x24a50f7c,
-       0x90a20000, 0x30430007, 0x24020004, 0x10620011, 0x28620005, 0x10400005,
-       0x24020002, 0x10620008, 0x000710c0, 0x080040fa, 0x00000000, 0x24020006,
-       0x1062000e, 0x000710c0, 0x080040fa, 0x00000000, 0x00a21821, 0x9463000c,
-       0x004b1021, 0x080040fa, 0xa4430000, 0x000710c0, 0x00a21821, 0x8c63000c,
-       0x004b1021, 0x080040fa, 0xac430000, 0x00a21821, 0x8c63000c, 0x004b2021,
-       0x00a21021, 0xac830000, 0x94420010, 0xa4820004, 0x95e70006, 0x3c020001,
-       0x90420f7c, 0x3c030001, 0x90630f7a, 0x00e2c823, 0x3c020001, 0x90420f7b,
-       0x24630028, 0x01e34021, 0x24420028, 0x15200012, 0x01e23021, 0x94c2000c,
-       0x3c010001, 0xa4220f78, 0x94c20004, 0x94c30006, 0x3c010001, 0xa4200f76,
-       0x3c010001, 0xa4200f72, 0x00021400, 0x00431025, 0x3c010001, 0xac220f6c,
-       0x95020004, 0x3c010001, 0x08004124, 0xa4220f70, 0x3c020001, 0x94420f70,
-       0x3c030001, 0x94630f72, 0x00431021, 0xa5020004, 0x3c020001, 0x94420f6c,
-       0xa4c20004, 0x3c020001, 0x8c420f6c, 0xa4c20006, 0x3c040001, 0x94840f72,
-       0x3c020001, 0x94420f70, 0x3c0a0001, 0x954a0f76, 0x00441821, 0x3063ffff,
-       0x0062182a, 0x24020002, 0x1122000b, 0x00832023, 0x3c030001, 0x94630f78,
-       0x30620009, 0x10400006, 0x3062fff6, 0xa4c2000c, 0x3c020001, 0x94420f78,
-       0x30420009, 0x01425023, 0x24020001, 0x1122001b, 0x29220002, 0x50400005,
-       0x24020002, 0x11200007, 0x31a2ffff, 0x08004197, 0x00000000, 0x1122001d,
-       0x24020016, 0x08004197, 0x31a2ffff, 0x3c0e0001, 0x95ce0f80, 0x10800005,
-       0x01806821, 0x01c42021, 0x00041c02, 0x3082ffff, 0x00627021, 0x000e1027,
-       0xa502000a, 0x3c030001, 0x90630f7b, 0x31a2ffff, 0x00e21021, 0x0800418d,
-       0x00432023, 0x3c020001, 0x94420f80, 0x00442021, 0x00041c02, 0x3082ffff,
-       0x00622021, 0x00807021, 0x00041027, 0x08004185, 0xa502000a, 0x3c050001,
-       0x24a50f7a, 0x90a30000, 0x14620002, 0x24e2fff2, 0xa5e20034, 0x90a20000,
-       0x00e21023, 0xa5020002, 0x3c030001, 0x94630f80, 0x3c020001, 0x94420f5a,
-       0x30e5ffff, 0x00641821, 0x00451023, 0x00622023, 0x00041c02, 0x3082ffff,
-       0x00622021, 0x00041027, 0xa502000a, 0x3c030001, 0x90630f7c, 0x24620001,
-       0x14a20005, 0x00807021, 0x01631021, 0x90420000, 0x08004185, 0x00026200,
-       0x24620002, 0x14a20003, 0x306200fe, 0x004b1021, 0x944c0000, 0x3c020001,
-       0x94420f82, 0x3183ffff, 0x3c040001, 0x90840f7b, 0x00431021, 0x00e21021,
-       0x00442023, 0x008a2021, 0x00041c02, 0x3082ffff, 0x00622021, 0x00041402,
-       0x00822021, 0x00806821, 0x00041027, 0xa4c20010, 0x31a2ffff, 0x000e1c00,
-       0x00431025, 0x3c040001, 0x24840f72, 0xade20010, 0x94820000, 0x3c050001,
-       0x94a50f76, 0x3c030001, 0x8c630f6c, 0x24420001, 0x00b92821, 0xa4820000,
-       0x3322ffff, 0x00622021, 0x0083182b, 0x3c010001, 0xa4250f76, 0x10600003,
-       0x24a2ffff, 0x3c010001, 0xa4220f76, 0x3c024000, 0x03021025, 0x3c010001,
-       0xac240f6c, 0xaf621008, 0x03e00008, 0x27bd0010, 0x3c030001, 0x90630f56,
-       0x27bdffe8, 0x24020001, 0xafbf0014, 0x10620026, 0xafb00010, 0x8f620cf4,
-       0x2442ffff, 0x3042007f, 0x00021100, 0x8c434000, 0x3c010001, 0xac230f64,
-       0x8c434008, 0x24444000, 0x8c5c4004, 0x30620040, 0x14400002, 0x24020088,
-       0x24020008, 0x3c010001, 0xa4220f68, 0x30620004, 0x10400005, 0x24020001,
-       0x3c010001, 0xa0220f57, 0x080041d5, 0x00031402, 0x3c010001, 0xa0200f57,
-       0x00031402, 0x3c010001, 0xa4220f54, 0x9483000c, 0x24020001, 0x3c010001,
-       0xa4200f50, 0x3c010001, 0xa0220f56, 0x3c010001, 0xa4230f62, 0x24020001,
-       0x1342001e, 0x00000000, 0x13400005, 0x24020003, 0x13420067, 0x00000000,
-       0x080042cf, 0x00000000, 0x3c020001, 0x94420f62, 0x241a0001, 0x3c010001,
-       0xa4200f5e, 0x3c010001, 0xa4200f52, 0x304407ff, 0x00021bc2, 0x00031823,
-       0x3063003e, 0x34630036, 0x00021242, 0x3042003c, 0x00621821, 0x3c010001,
-       0xa4240f58, 0x00832021, 0x24630030, 0x3c010001, 0xa4240f5a, 0x3c010001,
-       0xa4230f5c, 0x3c060001, 0x24c60f52, 0x94c50000, 0x94c30002, 0x3c040001,
-       0x94840f5a, 0x00651021, 0x0044102a, 0x10400013, 0x3c108000, 0x00a31021,
-       0xa4c20000, 0x3c02a000, 0xaf620cf4, 0x3c010001, 0xa0200f56, 0x8f641008,
-       0x00901024, 0x14400003, 0x00000000, 0x0c004064, 0x00000000, 0x8f620cf4,
-       0x00501024, 0x104000b7, 0x00000000, 0x0800420f, 0x00000000, 0x3c030001,
-       0x94630f50, 0x00851023, 0xa4c40000, 0x00621821, 0x3042ffff, 0x3c010001,
-       0xa4230f50, 0xaf620ce8, 0x3c020001, 0x94420f68, 0x34420024, 0xaf620cec,
-       0x94c30002, 0x3c020001, 0x94420f50, 0x14620012, 0x3c028000, 0x3c108000,
-       0x3c02a000, 0xaf620cf4, 0x3c010001, 0xa0200f56, 0x8f641008, 0x00901024,
-       0x14400003, 0x00000000, 0x0c004064, 0x00000000, 0x8f620cf4, 0x00501024,
-       0x1440fff7, 0x00000000, 0x080042cf, 0x241a0003, 0xaf620cf4, 0x3c108000,
-       0x8f641008, 0x00901024, 0x14400003, 0x00000000, 0x0c004064, 0x00000000,
-       0x8f620cf4, 0x00501024, 0x1440fff7, 0x00000000, 0x080042cf, 0x241a0003,
-       0x3c070001, 0x24e70f50, 0x94e20000, 0x03821021, 0xaf620ce0, 0x3c020001,
-       0x8c420f64, 0xaf620ce4, 0x3c050001, 0x94a50f54, 0x94e30000, 0x3c040001,
-       0x94840f58, 0x3c020001, 0x94420f5e, 0x00a32823, 0x00822023, 0x30a6ffff,
-       0x3083ffff, 0x00c3102b, 0x14400043, 0x00000000, 0x3c020001, 0x94420f5c,
-       0x00021400, 0x00621025, 0xaf620ce8, 0x94e20000, 0x3c030001, 0x94630f54,
-       0x00441021, 0xa4e20000, 0x3042ffff, 0x14430021, 0x3c020008, 0x3c020001,
-       0x90420f57, 0x10400006, 0x3c03000c, 0x3c020001, 0x94420f68, 0x34630624,
-       0x0800427c, 0x0000d021, 0x3c020001, 0x94420f68, 0x3c030008, 0x34630624,
-       0x00431025, 0xaf620cec, 0x3c108000, 0x3c02a000, 0xaf620cf4, 0x3c010001,
-       0xa0200f56, 0x8f641008, 0x00901024, 0x14400003, 0x00000000, 0x0c004064,
-       0x00000000, 0x8f620cf4, 0x00501024, 0x10400015, 0x00000000, 0x08004283,
-       0x00000000, 0x3c030001, 0x94630f68, 0x34420624, 0x3c108000, 0x00621825,
-       0x3c028000, 0xaf630cec, 0xaf620cf4, 0x8f641008, 0x00901024, 0x14400003,
-       0x00000000, 0x0c004064, 0x00000000, 0x8f620cf4, 0x00501024, 0x1440fff7,
-       0x00000000, 0x3c010001, 0x080042cf, 0xa4200f5e, 0x3c020001, 0x94420f5c,
-       0x00021400, 0x00c21025, 0xaf620ce8, 0x3c020001, 0x90420f57, 0x10400009,
-       0x3c03000c, 0x3c020001, 0x94420f68, 0x34630624, 0x0000d021, 0x00431025,
-       0xaf620cec, 0x080042c1, 0x3c108000, 0x3c020001, 0x94420f68, 0x3c030008,
-       0x34630604, 0x00431025, 0xaf620cec, 0x3c020001, 0x94420f5e, 0x00451021,
-       0x3c010001, 0xa4220f5e, 0x3c108000, 0x3c02a000, 0xaf620cf4, 0x3c010001,
-       0xa0200f56, 0x8f641008, 0x00901024, 0x14400003, 0x00000000, 0x0c004064,
-       0x00000000, 0x8f620cf4, 0x00501024, 0x1440fff7, 0x00000000, 0x8fbf0014,
-       0x8fb00010, 0x03e00008, 0x27bd0018, 0x00000000, 0x27bdffe0, 0x3c040001,
-       0x24840ec0, 0x00002821, 0x00003021, 0x00003821, 0xafbf0018, 0xafa00010,
-       0x0c004378, 0xafa00014, 0x0000d021, 0x24020130, 0xaf625000, 0x3c010001,
-       0xa4200f50, 0x3c010001, 0xa0200f57, 0x8fbf0018, 0x03e00008, 0x27bd0020,
-       0x27bdffe8, 0x3c1bc000, 0xafbf0014, 0xafb00010, 0xaf60680c, 0x8f626804,
-       0x34420082, 0xaf626804, 0x8f634000, 0x24020b50, 0x3c010001, 0xac220f20,
-       0x24020b78, 0x3c010001, 0xac220f30, 0x34630002, 0xaf634000, 0x0c004315,
-       0x00808021, 0x3c010001, 0xa0220f34, 0x304200ff, 0x24030002, 0x14430005,
-       0x00000000, 0x3c020001, 0x8c420f20, 0x08004308, 0xac5000c0, 0x3c020001,
-       0x8c420f20, 0xac5000bc, 0x8f624434, 0x8f634438, 0x8f644410, 0x3c010001,
-       0xac220f28, 0x3c010001, 0xac230f38, 0x3c010001, 0xac240f24, 0x8fbf0014,
-       0x8fb00010, 0x03e00008, 0x27bd0018, 0x03e00008, 0x24020001, 0x27bdfff8,
-       0x18800009, 0x00002821, 0x8f63680c, 0x8f62680c, 0x1043fffe, 0x00000000,
-       0x24a50001, 0x00a4102a, 0x1440fff9, 0x00000000, 0x03e00008, 0x27bd0008,
-       0x8f634450, 0x3c020001, 0x8c420f28, 0x00031c02, 0x0043102b, 0x14400008,
-       0x3c038000, 0x3c040001, 0x8c840f38, 0x8f624450, 0x00021c02, 0x0083102b,
-       0x1040fffc, 0x3c038000, 0xaf634444, 0x8f624444, 0x00431024, 0x1440fffd,
-       0x00000000, 0x8f624448, 0x03e00008, 0x3042ffff, 0x3082ffff, 0x2442e000,
-       0x2c422001, 0x14400003, 0x3c024000, 0x08004347, 0x2402ffff, 0x00822025,
-       0xaf645c38, 0x8f625c30, 0x30420002, 0x1440fffc, 0x00001021, 0x03e00008,
-       0x00000000, 0x8f624450, 0x3c030001, 0x8c630f24, 0x08004350, 0x3042ffff,
-       0x8f624450, 0x3042ffff, 0x0043102b, 0x1440fffc, 0x00000000, 0x03e00008,
-       0x00000000, 0x27bdffe0, 0x00802821, 0x3c040001, 0x24840ed0, 0x00003021,
-       0x00003821, 0xafbf0018, 0xafa00010, 0x0c004378, 0xafa00014, 0x0800435f,
-       0x00000000, 0x8fbf0018, 0x03e00008, 0x27bd0020, 0x3c020001, 0x3442d600,
-       0x3c030001, 0x3463d600, 0x3c040001, 0x3484ddff, 0x3c010001, 0xac220f40,
-       0x24020040, 0x3c010001, 0xac220f44, 0x3c010001, 0xac200f3c, 0xac600000,
-       0x24630004, 0x0083102b, 0x5040fffd, 0xac600000, 0x03e00008, 0x00000000,
-       0x00804821, 0x8faa0010, 0x3c020001, 0x8c420f3c, 0x3c040001, 0x8c840f44,
-       0x8fab0014, 0x24430001, 0x0044102b, 0x3c010001, 0xac230f3c, 0x14400003,
-       0x00004021, 0x3c010001, 0xac200f3c, 0x3c020001, 0x8c420f3c, 0x3c030001,
-       0x8c630f40, 0x91240000, 0x00021140, 0x00431021, 0x00481021, 0x25080001,
-       0xa0440000, 0x29020008, 0x1440fff4, 0x25290001, 0x3c020001, 0x8c420f3c,
-       0x3c030001, 0x8c630f40, 0x8f64680c, 0x00021140, 0x00431021, 0xac440008,
-       0xac45000c, 0xac460010, 0xac470014, 0xac4a0018, 0x03e00008, 0xac4b001c,
-       0x00000000, 0x00000000, 0x00000000,
-};
-
-static const u32 tg3Tso5FwRodata[(TG3_TSO5_FW_RODATA_LEN / 4) + 1] = {
-       0x4d61696e, 0x43707542, 0x00000000, 0x4d61696e, 0x43707541, 0x00000000,
-       0x00000000, 0x00000000, 0x73746b6f, 0x66666c64, 0x00000000, 0x00000000,
-       0x73746b6f, 0x66666c64, 0x00000000, 0x00000000, 0x66617461, 0x6c457272,
-       0x00000000, 0x00000000, 0x00000000,
-};
-
-static const u32 tg3Tso5FwData[(TG3_TSO5_FW_DATA_LEN / 4) + 1] = {
-       0x00000000, 0x73746b6f, 0x66666c64, 0x5f76312e, 0x322e3000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000,
-};
 
 /* tp->lock is held. */
 static int tg3_load_tso_firmware(struct tg3 *tp)
 {
        struct fw_info info;
+       const __be32 *fw_data;
        unsigned long cpu_base, cpu_scratch_base, cpu_scratch_size;
        int err, i;
 
        if (tp->tg3_flags2 & TG3_FLG2_HW_TSO)
                return 0;
 
+       fw_data = (void *)tp->fw->data;
+
+       /* Firmware blob starts with version numbers, followed by
+          start address and length. We are setting complete length.
+          length = end_address_of_bss - start_address_of_text.
+          Remainder is the blob to be loaded contiguously
+          from start address. */
+
+       info.fw_base = be32_to_cpu(fw_data[1]);
+       cpu_scratch_size = tp->fw_len;
+       info.fw_len = tp->fw->size - 12;
+       info.fw_data = &fw_data[3];
+
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
-               info.text_base = TG3_TSO5_FW_TEXT_ADDR;
-               info.text_len = TG3_TSO5_FW_TEXT_LEN;
-               info.text_data = &tg3Tso5FwText[0];
-               info.rodata_base = TG3_TSO5_FW_RODATA_ADDR;
-               info.rodata_len = TG3_TSO5_FW_RODATA_LEN;
-               info.rodata_data = &tg3Tso5FwRodata[0];
-               info.data_base = TG3_TSO5_FW_DATA_ADDR;
-               info.data_len = TG3_TSO5_FW_DATA_LEN;
-               info.data_data = &tg3Tso5FwData[0];
                cpu_base = RX_CPU_BASE;
                cpu_scratch_base = NIC_SRAM_MBUF_POOL_BASE5705;
-               cpu_scratch_size = (info.text_len +
-                                   info.rodata_len +
-                                   info.data_len +
-                                   TG3_TSO5_FW_SBSS_LEN +
-                                   TG3_TSO5_FW_BSS_LEN);
        } else {
-               info.text_base = TG3_TSO_FW_TEXT_ADDR;
-               info.text_len = TG3_TSO_FW_TEXT_LEN;
-               info.text_data = &tg3TsoFwText[0];
-               info.rodata_base = TG3_TSO_FW_RODATA_ADDR;
-               info.rodata_len = TG3_TSO_FW_RODATA_LEN;
-               info.rodata_data = &tg3TsoFwRodata[0];
-               info.data_base = TG3_TSO_FW_DATA_ADDR;
-               info.data_len = TG3_TSO_FW_DATA_LEN;
-               info.data_data = &tg3TsoFwData[0];
                cpu_base = TX_CPU_BASE;
                cpu_scratch_base = TX_CPU_SCRATCH_BASE;
                cpu_scratch_size = TX_CPU_SCRATCH_SIZE;
@@ -7060,21 +6418,21 @@ static int tg3_load_tso_firmware(struct tg3 *tp)
 
        /* Now startup the cpu. */
        tw32(cpu_base + CPU_STATE, 0xffffffff);
-       tw32_f(cpu_base + CPU_PC,    info.text_base);
+       tw32_f(cpu_base + CPU_PC, info.fw_base);
 
        for (i = 0; i < 5; i++) {
-               if (tr32(cpu_base + CPU_PC) == info.text_base)
+               if (tr32(cpu_base + CPU_PC) == info.fw_base)
                        break;
                tw32(cpu_base + CPU_STATE, 0xffffffff);
                tw32(cpu_base + CPU_MODE,  CPU_MODE_HALT);
-               tw32_f(cpu_base + CPU_PC,    info.text_base);
+               tw32_f(cpu_base + CPU_PC, info.fw_base);
                udelay(1000);
        }
        if (i >= 5) {
                printk(KERN_ERR PFX "tg3_load_tso_firmware fails for %s "
                       "to set CPU PC, is %08x should be %08x\n",
                       tp->dev->name, tr32(cpu_base + CPU_PC),
-                      info.text_base);
+                      info.fw_base);
                return -ENODEV;
        }
        tw32(cpu_base + CPU_STATE, 0xffffffff);
@@ -7299,11 +6657,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
        else if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) {
                int fw_len;
 
-               fw_len = (TG3_TSO5_FW_TEXT_LEN +
-                         TG3_TSO5_FW_RODATA_LEN +
-                         TG3_TSO5_FW_DATA_LEN +
-                         TG3_TSO5_FW_SBSS_LEN +
-                         TG3_TSO5_FW_BSS_LEN);
+               fw_len = tp->fw_len;
                fw_len = (fw_len + (0x80 - 1)) & ~(0x80 - 1);
                tw32(BUFMGR_MB_POOL_ADDR,
                     NIC_SRAM_MBUF_POOL_BASE5705 + fw_len);
@@ -13580,6 +12934,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
        struct net_device *dev;
        struct tg3 *tp;
        int err, pm_cap;
+       const char *fw_name = NULL;
        char str[40];
        u64 dma_mask, persist_dma_mask;
 
@@ -13735,6 +13090,9 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 
        tg3_init_bufmgr_config(tp);
 
+       if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0)
+               fw_name = FIRMWARE_TG3;
+
        if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) {
                tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE;
        }
@@ -13747,6 +13105,37 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
        } else {
                tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE | TG3_FLG2_TSO_BUG;
        }
+       if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) {
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)
+                       fw_name = FIRMWARE_TG3TSO5;
+               else
+                       fw_name = FIRMWARE_TG3TSO;
+       }
+
+       if (fw_name) {
+               const __be32 *fw_data;
+
+               err = request_firmware(&tp->fw, fw_name, &tp->pdev->dev);
+               if (err) {
+                       printk(KERN_ERR "tg3: Failed to load firmware \"%s\"\n",
+                              fw_name);
+                       goto err_out_iounmap;
+               }
+
+               fw_data = (void *)tp->fw->data;
+
+               /* Firmware blob starts with version numbers, followed by
+                  start address and _full_ length including BSS sections
+                  (which must be longer than the actual data, of course */
+
+               tp->fw_len = be32_to_cpu(fw_data[2]);   /* includes bss */
+               if (tp->fw_len < (tp->fw->size - 12)) {
+                       printk(KERN_ERR "tg3: bogus length %d in \"%s\"\n",
+                              tp->fw_len, fw_name);
+                       err = -EINVAL;
+                       goto err_out_fw;
+               }
+       }
 
        /* TSO is on by default on chips that support hardware TSO.
         * Firmware TSO on older chips gives lower performance, so it
@@ -13778,7 +13167,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
        if (err) {
                printk(KERN_ERR PFX "Could not obtain valid ethernet address, "
                       "aborting.\n");
-               goto err_out_iounmap;
+               goto err_out_fw;
        }
 
        if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) {
@@ -13787,7 +13176,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
                        printk(KERN_ERR PFX "Cannot map APE registers, "
                               "aborting.\n");
                        err = -ENOMEM;
-                       goto err_out_iounmap;
+                       goto err_out_fw;
                }
 
                tg3_ape_lock_init(tp);
@@ -13867,6 +13256,10 @@ err_out_apeunmap:
                tp->aperegs = NULL;
        }
 
+err_out_fw:
+       if (tp->fw)
+               release_firmware(tp->fw);
+
 err_out_iounmap:
        if (tp->regs) {
                iounmap(tp->regs);
@@ -13892,6 +13285,9 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev)
        if (dev) {
                struct tg3 *tp = netdev_priv(dev);
 
+               if (tp->fw)
+                       release_firmware(tp->fw);
+
                flush_scheduled_work();
 
                if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) {
index 8936edfb0438c992c6cf7ceeb8d6880aa0fa98fe..ae5da603c6af0e8c0f24149766fa19f6a9119667 100644 (file)
@@ -2762,6 +2762,10 @@ struct tg3 {
 #define SST_25VF0X0_PAGE_SIZE          4098
 
        struct ethtool_coalesce         coal;
+
+       /* firmware info */
+       const struct firmware           *fw;
+       u32                             fw_len; /* includes BSS */
 };
 
 #endif /* !(_T3_H) */
index 69f9a0ec764d3e8503cb46c1d3d4fa380e5b87f3..d7b81e4fdd5631c0c537cd971cad3bebb72bb38d 100644 (file)
@@ -213,7 +213,7 @@ static int check_filter(struct tap_filter *filter, const struct sk_buff *skb)
 
 /* Network device part of the driver */
 
-static unsigned int tun_net_id;
+static int tun_net_id;
 struct tun_net {
        struct list_head dev_list;
 };
index ddc4c59f02dca27adc42d187429543dea4f4da63..b7e4cee24269a2e0a11b66833c6734dcf6f6a959 100644 (file)
@@ -29,9 +29,6 @@ static struct inode *oprofilefs_get_inode(struct super_block *sb, int mode)
 
        if (inode) {
                inode->i_mode = mode;
-               inode->i_uid = 0;
-               inode->i_gid = 0;
-               inode->i_blocks = 0;
                inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
        }
        return inode;
index 691b3adeb87057799841f112d8b77797e729e4ce..f5a662a50acb12edea158dc114002cf1be33a418 100644 (file)
@@ -191,26 +191,17 @@ dmar_parse_one_drhd(struct acpi_dmar_header *header)
 static int __init dmar_parse_dev(struct dmar_drhd_unit *dmaru)
 {
        struct acpi_dmar_hardware_unit *drhd;
-       static int include_all;
        int ret = 0;
 
        drhd = (struct acpi_dmar_hardware_unit *) dmaru->hdr;
 
-       if (!dmaru->include_all)
-               ret = dmar_parse_dev_scope((void *)(drhd + 1),
+       if (dmaru->include_all)
+               return 0;
+
+       ret = dmar_parse_dev_scope((void *)(drhd + 1),
                                ((void *)drhd) + drhd->header.length,
                                &dmaru->devices_cnt, &dmaru->devices,
                                drhd->segment);
-       else {
-               /* Only allow one INCLUDE_ALL */
-               if (include_all) {
-                       printk(KERN_WARNING PREFIX "Only one INCLUDE_ALL "
-                               "device scope is allowed\n");
-                       ret = -EINVAL;
-               }
-               include_all = 1;
-       }
-
        if (ret) {
                list_del(&dmaru->list);
                kfree(dmaru);
@@ -384,12 +375,21 @@ int dmar_pci_device_match(struct pci_dev *devices[], int cnt,
 struct dmar_drhd_unit *
 dmar_find_matched_drhd_unit(struct pci_dev *dev)
 {
-       struct dmar_drhd_unit *drhd = NULL;
+       struct dmar_drhd_unit *dmaru = NULL;
+       struct acpi_dmar_hardware_unit *drhd;
 
-       list_for_each_entry(drhd, &dmar_drhd_units, list) {
-               if (drhd->include_all || dmar_pci_device_match(drhd->devices,
-                                               drhd->devices_cnt, dev))
-                       return drhd;
+       list_for_each_entry(dmaru, &dmar_drhd_units, list) {
+               drhd = container_of(dmaru->hdr,
+                                   struct acpi_dmar_hardware_unit,
+                                   header);
+
+               if (dmaru->include_all &&
+                   drhd->segment == pci_domain_nr(dev->bus))
+                       return dmaru;
+
+               if (dmar_pci_device_match(dmaru->devices,
+                                         dmaru->devices_cnt, dev))
+                       return dmaru;
        }
 
        return NULL;
@@ -491,6 +491,7 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
        int map_size;
        u32 ver;
        static int iommu_allocated = 0;
+       int agaw;
 
        iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
        if (!iommu)
@@ -506,6 +507,15 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
        iommu->cap = dmar_readq(iommu->reg + DMAR_CAP_REG);
        iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG);
 
+       agaw = iommu_calculate_agaw(iommu);
+       if (agaw < 0) {
+               printk(KERN_ERR
+                       "Cannot get a valid agaw for iommu (seq_id = %d)\n",
+                       iommu->seq_id);
+               goto error;
+       }
+       iommu->agaw = agaw;
+
        /* the registers might be more than one page */
        map_size = max_t(int, ecap_max_iotlb_offset(iommu->ecap),
                cap_max_fault_reg_offset(iommu->cap));
index 8514c3a1746a6c15e4ff3db1dd43b7c1dcefdee2..c2e1bcbb28a79edf262926174d805e23b811015e 100644 (file)
@@ -45,7 +45,7 @@
 
 #include "cpqphp.h"
 #include "cpqphp_nvram.h"
-#include "../../../arch/x86/pci/pci.h" /* horrible hack showing how processor dependent we are... */
+#include <asm/pci_x86.h>
 
 
 /* Global variables */
index 09021930589fb477fc885b80a0dd7623c817e676..df146be9d2e9f33cb6c6c8eff1d72b8de5e86bc3 100644 (file)
@@ -37,7 +37,7 @@
 #include "../pci.h"
 #include "cpqphp.h"
 #include "cpqphp_nvram.h"
-#include "../../../arch/x86/pci/pci.h" /* horrible hack showing how processor dependent we are... */
+#include <asm/pci_x86.h>
 
 
 u8 cpqhp_nic_irq;
index 633e743442ac711d0b02d6b85a8252a1ee74dbb5..dd18f857dfb042d8d5802bfbbab57c617054b3f4 100644 (file)
@@ -35,7 +35,7 @@
 #include <linux/delay.h>
 #include <linux/wait.h>
 #include "../pci.h"
-#include "../../../arch/x86/pci/pci.h" /* for struct irq_routing_table */
+#include <asm/pci_x86.h>               /* for struct irq_routing_table */
 #include "ibmphp.h"
 
 #define attn_on(sl)  ibmphp_hpc_writeslot (sl, HPC_SLOT_ATTNON)
index 5c8baa43ac9c5ed86bde043702af795d37dcf2b8..235fb7a5a8a50455fcbf27a64ff8b84f6e418882 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/slab.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
-#include <linux/sysdev.h>
 #include <linux/spinlock.h>
 #include <linux/pci.h>
 #include <linux/dmar.h>
@@ -35,6 +34,7 @@
 #include <linux/mempool.h>
 #include <linux/timer.h>
 #include <linux/iova.h>
+#include <linux/iommu.h>
 #include <linux/intel-iommu.h>
 #include <asm/cacheflush.h>
 #include <asm/iommu.h>
 
 #define DOMAIN_MAX_ADDR(gaw) ((((u64)1) << gaw) - 1)
 
+#define IOVA_PFN(addr)         ((addr) >> PAGE_SHIFT)
+#define DMA_32BIT_PFN          IOVA_PFN(DMA_32BIT_MASK)
+#define DMA_64BIT_PFN          IOVA_PFN(DMA_64BIT_MASK)
+
+/* global iommu list, set NULL for ignored DMAR units */
+static struct intel_iommu **g_iommus;
+
+/*
+ * 0: Present
+ * 1-11: Reserved
+ * 12-63: Context Ptr (12 - (haw-1))
+ * 64-127: Reserved
+ */
+struct root_entry {
+       u64     val;
+       u64     rsvd1;
+};
+#define ROOT_ENTRY_NR (VTD_PAGE_SIZE/sizeof(struct root_entry))
+static inline bool root_present(struct root_entry *root)
+{
+       return (root->val & 1);
+}
+static inline void set_root_present(struct root_entry *root)
+{
+       root->val |= 1;
+}
+static inline void set_root_value(struct root_entry *root, unsigned long value)
+{
+       root->val |= value & VTD_PAGE_MASK;
+}
+
+static inline struct context_entry *
+get_context_addr_from_root(struct root_entry *root)
+{
+       return (struct context_entry *)
+               (root_present(root)?phys_to_virt(
+               root->val & VTD_PAGE_MASK) :
+               NULL);
+}
+
+/*
+ * low 64 bits:
+ * 0: present
+ * 1: fault processing disable
+ * 2-3: translation type
+ * 12-63: address space root
+ * high 64 bits:
+ * 0-2: address width
+ * 3-6: aval
+ * 8-23: domain id
+ */
+struct context_entry {
+       u64 lo;
+       u64 hi;
+};
+
+static inline bool context_present(struct context_entry *context)
+{
+       return (context->lo & 1);
+}
+static inline void context_set_present(struct context_entry *context)
+{
+       context->lo |= 1;
+}
+
+static inline void context_set_fault_enable(struct context_entry *context)
+{
+       context->lo &= (((u64)-1) << 2) | 1;
+}
+
+#define CONTEXT_TT_MULTI_LEVEL 0
+
+static inline void context_set_translation_type(struct context_entry *context,
+                                               unsigned long value)
+{
+       context->lo &= (((u64)-1) << 4) | 3;
+       context->lo |= (value & 3) << 2;
+}
+
+static inline void context_set_address_root(struct context_entry *context,
+                                           unsigned long value)
+{
+       context->lo |= value & VTD_PAGE_MASK;
+}
+
+static inline void context_set_address_width(struct context_entry *context,
+                                            unsigned long value)
+{
+       context->hi |= value & 7;
+}
+
+static inline void context_set_domain_id(struct context_entry *context,
+                                        unsigned long value)
+{
+       context->hi |= (value & ((1 << 16) - 1)) << 8;
+}
+
+static inline void context_clear_entry(struct context_entry *context)
+{
+       context->lo = 0;
+       context->hi = 0;
+}
+
+/*
+ * 0: readable
+ * 1: writable
+ * 2-6: reserved
+ * 7: super page
+ * 8-11: available
+ * 12-63: Host physcial address
+ */
+struct dma_pte {
+       u64 val;
+};
+
+static inline void dma_clear_pte(struct dma_pte *pte)
+{
+       pte->val = 0;
+}
+
+static inline void dma_set_pte_readable(struct dma_pte *pte)
+{
+       pte->val |= DMA_PTE_READ;
+}
+
+static inline void dma_set_pte_writable(struct dma_pte *pte)
+{
+       pte->val |= DMA_PTE_WRITE;
+}
+
+static inline void dma_set_pte_prot(struct dma_pte *pte, unsigned long prot)
+{
+       pte->val = (pte->val & ~3) | (prot & 3);
+}
+
+static inline u64 dma_pte_addr(struct dma_pte *pte)
+{
+       return (pte->val & VTD_PAGE_MASK);
+}
+
+static inline void dma_set_pte_addr(struct dma_pte *pte, u64 addr)
+{
+       pte->val |= (addr & VTD_PAGE_MASK);
+}
+
+static inline bool dma_pte_present(struct dma_pte *pte)
+{
+       return (pte->val & 3) != 0;
+}
+
+/* devices under the same p2p bridge are owned in one domain */
+#define DOMAIN_FLAG_P2P_MULTIPLE_DEVICES (1 << 0)
+
+/* domain represents a virtual machine, more than one devices
+ * across iommus may be owned in one domain, e.g. kvm guest.
+ */
+#define DOMAIN_FLAG_VIRTUAL_MACHINE    (1 << 1)
+
+struct dmar_domain {
+       int     id;                     /* domain id */
+       unsigned long iommu_bmp;        /* bitmap of iommus this domain uses*/
+
+       struct list_head devices;       /* all devices' list */
+       struct iova_domain iovad;       /* iova's that belong to this domain */
+
+       struct dma_pte  *pgd;           /* virtual address */
+       spinlock_t      mapping_lock;   /* page table lock */
+       int             gaw;            /* max guest address width */
+
+       /* adjusted guest address width, 0 is level 2 30-bit */
+       int             agaw;
+
+       int             flags;          /* flags to find out type of domain */
+
+       int             iommu_coherency;/* indicate coherency of iommu access */
+       int             iommu_count;    /* reference count of iommu */
+       spinlock_t      iommu_lock;     /* protect iommu set in domain */
+       u64             max_addr;       /* maximum mapped address */
+};
+
+/* PCI domain-device relationship */
+struct device_domain_info {
+       struct list_head link;  /* link to domain siblings */
+       struct list_head global; /* link to global list */
+       u8 bus;                 /* PCI bus numer */
+       u8 devfn;               /* PCI devfn number */
+       struct pci_dev *dev; /* it's NULL for PCIE-to-PCI bridge */
+       struct dmar_domain *domain; /* pointer to domain */
+};
 
 static void flush_unmaps_timeout(unsigned long data);
 
@@ -88,6 +277,8 @@ static int intel_iommu_strict;
 static DEFINE_SPINLOCK(device_domain_lock);
 static LIST_HEAD(device_domain_list);
 
+static struct iommu_ops intel_iommu_ops;
+
 static int __init intel_iommu_setup(char *str)
 {
        if (!str)
@@ -184,6 +375,87 @@ void free_iova_mem(struct iova *iova)
        kmem_cache_free(iommu_iova_cache, iova);
 }
 
+
+static inline int width_to_agaw(int width);
+
+/* calculate agaw for each iommu.
+ * "SAGAW" may be different across iommus, use a default agaw, and
+ * get a supported less agaw for iommus that don't support the default agaw.
+ */
+int iommu_calculate_agaw(struct intel_iommu *iommu)
+{
+       unsigned long sagaw;
+       int agaw = -1;
+
+       sagaw = cap_sagaw(iommu->cap);
+       for (agaw = width_to_agaw(DEFAULT_DOMAIN_ADDRESS_WIDTH);
+            agaw >= 0; agaw--) {
+               if (test_bit(agaw, &sagaw))
+                       break;
+       }
+
+       return agaw;
+}
+
+/* in native case, each domain is related to only one iommu */
+static struct intel_iommu *domain_get_iommu(struct dmar_domain *domain)
+{
+       int iommu_id;
+
+       BUG_ON(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE);
+
+       iommu_id = find_first_bit(&domain->iommu_bmp, g_num_of_iommus);
+       if (iommu_id < 0 || iommu_id >= g_num_of_iommus)
+               return NULL;
+
+       return g_iommus[iommu_id];
+}
+
+/* "Coherency" capability may be different across iommus */
+static void domain_update_iommu_coherency(struct dmar_domain *domain)
+{
+       int i;
+
+       domain->iommu_coherency = 1;
+
+       i = find_first_bit(&domain->iommu_bmp, g_num_of_iommus);
+       for (; i < g_num_of_iommus; ) {
+               if (!ecap_coherent(g_iommus[i]->ecap)) {
+                       domain->iommu_coherency = 0;
+                       break;
+               }
+               i = find_next_bit(&domain->iommu_bmp, g_num_of_iommus, i+1);
+       }
+}
+
+static struct intel_iommu *device_to_iommu(u8 bus, u8 devfn)
+{
+       struct dmar_drhd_unit *drhd = NULL;
+       int i;
+
+       for_each_drhd_unit(drhd) {
+               if (drhd->ignored)
+                       continue;
+
+               for (i = 0; i < drhd->devices_cnt; i++)
+                       if (drhd->devices[i]->bus->number == bus &&
+                           drhd->devices[i]->devfn == devfn)
+                               return drhd->iommu;
+
+               if (drhd->include_all)
+                       return drhd->iommu;
+       }
+
+       return NULL;
+}
+
+static void domain_flush_cache(struct dmar_domain *domain,
+                              void *addr, int size)
+{
+       if (!domain->iommu_coherency)
+               clflush_cache_range(addr, size);
+}
+
 /* Gets context entry for a given bus and devfn */
 static struct context_entry * device_to_context_entry(struct intel_iommu *iommu,
                u8 bus, u8 devfn)
@@ -226,7 +498,7 @@ static int device_context_mapped(struct intel_iommu *iommu, u8 bus, u8 devfn)
                ret = 0;
                goto out;
        }
-       ret = context_present(context[devfn]);
+       ret = context_present(&context[devfn]);
 out:
        spin_unlock_irqrestore(&iommu->lock, flags);
        return ret;
@@ -242,7 +514,7 @@ static void clear_context_table(struct intel_iommu *iommu, u8 bus, u8 devfn)
        root = &iommu->root_entry[bus];
        context = get_context_addr_from_root(root);
        if (context) {
-               context_clear_entry(context[devfn]);
+               context_clear_entry(&context[devfn]);
                __iommu_flush_cache(iommu, &context[devfn], \
                        sizeof(*context));
        }
@@ -339,7 +611,7 @@ static struct dma_pte * addr_to_dma_pte(struct dmar_domain *domain, u64 addr)
                if (level == 1)
                        break;
 
-               if (!dma_pte_present(*pte)) {
+               if (!dma_pte_present(pte)) {
                        tmp_page = alloc_pgtable_page();
 
                        if (!tmp_page) {
@@ -347,18 +619,17 @@ static struct dma_pte * addr_to_dma_pte(struct dmar_domain *domain, u64 addr)
                                        flags);
                                return NULL;
                        }
-                       __iommu_flush_cache(domain->iommu, tmp_page,
-                                       PAGE_SIZE);
-                       dma_set_pte_addr(*pte, virt_to_phys(tmp_page));
+                       domain_flush_cache(domain, tmp_page, PAGE_SIZE);
+                       dma_set_pte_addr(pte, virt_to_phys(tmp_page));
                        /*
                         * high level table always sets r/w, last level page
                         * table control read/write
                         */
-                       dma_set_pte_readable(*pte);
-                       dma_set_pte_writable(*pte);
-                       __iommu_flush_cache(domain->iommu, pte, sizeof(*pte));
+                       dma_set_pte_readable(pte);
+                       dma_set_pte_writable(pte);
+                       domain_flush_cache(domain, pte, sizeof(*pte));
                }
-               parent = phys_to_virt(dma_pte_addr(*pte));
+               parent = phys_to_virt(dma_pte_addr(pte));
                level--;
        }
 
@@ -381,9 +652,9 @@ static struct dma_pte *dma_addr_level_pte(struct dmar_domain *domain, u64 addr,
                if (level == total)
                        return pte;
 
-               if (!dma_pte_present(*pte))
+               if (!dma_pte_present(pte))
                        break;
-               parent = phys_to_virt(dma_pte_addr(*pte));
+               parent = phys_to_virt(dma_pte_addr(pte));
                total--;
        }
        return NULL;
@@ -398,8 +669,8 @@ static void dma_pte_clear_one(struct dmar_domain *domain, u64 addr)
        pte = dma_addr_level_pte(domain, addr, 1);
 
        if (pte) {
-               dma_clear_pte(*pte);
-               __iommu_flush_cache(domain->iommu, pte, sizeof(*pte));
+               dma_clear_pte(pte);
+               domain_flush_cache(domain, pte, sizeof(*pte));
        }
 }
 
@@ -445,10 +716,9 @@ static void dma_pte_free_pagetable(struct dmar_domain *domain,
                        pte = dma_addr_level_pte(domain, tmp, level);
                        if (pte) {
                                free_pgtable_page(
-                                       phys_to_virt(dma_pte_addr(*pte)));
-                               dma_clear_pte(*pte);
-                               __iommu_flush_cache(domain->iommu,
-                                               pte, sizeof(*pte));
+                                       phys_to_virt(dma_pte_addr(pte)));
+                               dma_clear_pte(pte);
+                               domain_flush_cache(domain, pte, sizeof(*pte));
                        }
                        tmp += level_size(level);
                }
@@ -950,17 +1220,28 @@ static int iommu_init_domains(struct intel_iommu *iommu)
 
 
 static void domain_exit(struct dmar_domain *domain);
+static void vm_domain_exit(struct dmar_domain *domain);
 
 void free_dmar_iommu(struct intel_iommu *iommu)
 {
        struct dmar_domain *domain;
        int i;
+       unsigned long flags;
 
        i = find_first_bit(iommu->domain_ids, cap_ndoms(iommu->cap));
        for (; i < cap_ndoms(iommu->cap); ) {
                domain = iommu->domains[i];
                clear_bit(i, iommu->domain_ids);
-               domain_exit(domain);
+
+               spin_lock_irqsave(&domain->iommu_lock, flags);
+               if (--domain->iommu_count == 0) {
+                       if (domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE)
+                               vm_domain_exit(domain);
+                       else
+                               domain_exit(domain);
+               }
+               spin_unlock_irqrestore(&domain->iommu_lock, flags);
+
                i = find_next_bit(iommu->domain_ids,
                        cap_ndoms(iommu->cap), i+1);
        }
@@ -978,6 +1259,17 @@ void free_dmar_iommu(struct intel_iommu *iommu)
        kfree(iommu->domains);
        kfree(iommu->domain_ids);
 
+       g_iommus[iommu->seq_id] = NULL;
+
+       /* if all iommus are freed, free g_iommus */
+       for (i = 0; i < g_num_of_iommus; i++) {
+               if (g_iommus[i])
+                       break;
+       }
+
+       if (i == g_num_of_iommus)
+               kfree(g_iommus);
+
        /* free context mapping */
        free_context_table(iommu);
 }
@@ -1006,7 +1298,9 @@ static struct dmar_domain * iommu_alloc_domain(struct intel_iommu *iommu)
 
        set_bit(num, iommu->domain_ids);
        domain->id = num;
-       domain->iommu = iommu;
+       memset(&domain->iommu_bmp, 0, sizeof(unsigned long));
+       set_bit(iommu->seq_id, &domain->iommu_bmp);
+       domain->flags = 0;
        iommu->domains[num] = domain;
        spin_unlock_irqrestore(&iommu->lock, flags);
 
@@ -1016,10 +1310,13 @@ static struct dmar_domain * iommu_alloc_domain(struct intel_iommu *iommu)
 static void iommu_free_domain(struct dmar_domain *domain)
 {
        unsigned long flags;
+       struct intel_iommu *iommu;
+
+       iommu = domain_get_iommu(domain);
 
-       spin_lock_irqsave(&domain->iommu->lock, flags);
-       clear_bit(domain->id, domain->iommu->domain_ids);
-       spin_unlock_irqrestore(&domain->iommu->lock, flags);
+       spin_lock_irqsave(&iommu->lock, flags);
+       clear_bit(domain->id, iommu->domain_ids);
+       spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
 static struct iova_domain reserved_iova_list;
@@ -1094,11 +1391,12 @@ static int domain_init(struct dmar_domain *domain, int guest_width)
 
        init_iova_domain(&domain->iovad, DMA_32BIT_PFN);
        spin_lock_init(&domain->mapping_lock);
+       spin_lock_init(&domain->iommu_lock);
 
        domain_reserve_special_ranges(domain);
 
        /* calculate AGAW */
-       iommu = domain->iommu;
+       iommu = domain_get_iommu(domain);
        if (guest_width > cap_mgaw(iommu->cap))
                guest_width = cap_mgaw(iommu->cap);
        domain->gaw = guest_width;
@@ -1115,6 +1413,13 @@ static int domain_init(struct dmar_domain *domain, int guest_width)
        domain->agaw = agaw;
        INIT_LIST_HEAD(&domain->devices);
 
+       if (ecap_coherent(iommu->ecap))
+               domain->iommu_coherency = 1;
+       else
+               domain->iommu_coherency = 0;
+
+       domain->iommu_count = 1;
+
        /* always allocate the top pgd */
        domain->pgd = (struct dma_pte *)alloc_pgtable_page();
        if (!domain->pgd)
@@ -1151,28 +1456,82 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
                u8 bus, u8 devfn)
 {
        struct context_entry *context;
-       struct intel_iommu *iommu = domain->iommu;
        unsigned long flags;
+       struct intel_iommu *iommu;
+       struct dma_pte *pgd;
+       unsigned long num;
+       unsigned long ndomains;
+       int id;
+       int agaw;
 
        pr_debug("Set context mapping for %02x:%02x.%d\n",
                bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
        BUG_ON(!domain->pgd);
+
+       iommu = device_to_iommu(bus, devfn);
+       if (!iommu)
+               return -ENODEV;
+
        context = device_to_context_entry(iommu, bus, devfn);
        if (!context)
                return -ENOMEM;
        spin_lock_irqsave(&iommu->lock, flags);
-       if (context_present(*context)) {
+       if (context_present(context)) {
                spin_unlock_irqrestore(&iommu->lock, flags);
                return 0;
        }
 
-       context_set_domain_id(*context, domain->id);
-       context_set_address_width(*context, domain->agaw);
-       context_set_address_root(*context, virt_to_phys(domain->pgd));
-       context_set_translation_type(*context, CONTEXT_TT_MULTI_LEVEL);
-       context_set_fault_enable(*context);
-       context_set_present(*context);
-       __iommu_flush_cache(iommu, context, sizeof(*context));
+       id = domain->id;
+       pgd = domain->pgd;
+
+       if (domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) {
+               int found = 0;
+
+               /* find an available domain id for this device in iommu */
+               ndomains = cap_ndoms(iommu->cap);
+               num = find_first_bit(iommu->domain_ids, ndomains);
+               for (; num < ndomains; ) {
+                       if (iommu->domains[num] == domain) {
+                               id = num;
+                               found = 1;
+                               break;
+                       }
+                       num = find_next_bit(iommu->domain_ids,
+                                           cap_ndoms(iommu->cap), num+1);
+               }
+
+               if (found == 0) {
+                       num = find_first_zero_bit(iommu->domain_ids, ndomains);
+                       if (num >= ndomains) {
+                               spin_unlock_irqrestore(&iommu->lock, flags);
+                               printk(KERN_ERR "IOMMU: no free domain ids\n");
+                               return -EFAULT;
+                       }
+
+                       set_bit(num, iommu->domain_ids);
+                       iommu->domains[num] = domain;
+                       id = num;
+               }
+
+               /* Skip top levels of page tables for
+                * iommu which has less agaw than default.
+                */
+               for (agaw = domain->agaw; agaw != iommu->agaw; agaw--) {
+                       pgd = phys_to_virt(dma_pte_addr(pgd));
+                       if (!dma_pte_present(pgd)) {
+                               spin_unlock_irqrestore(&iommu->lock, flags);
+                               return -ENOMEM;
+                       }
+               }
+       }
+
+       context_set_domain_id(context, id);
+       context_set_address_width(context, iommu->agaw);
+       context_set_address_root(context, virt_to_phys(pgd));
+       context_set_translation_type(context, CONTEXT_TT_MULTI_LEVEL);
+       context_set_fault_enable(context);
+       context_set_present(context);
+       domain_flush_cache(domain, context, sizeof(*context));
 
        /* it's a non-present to present mapping */
        if (iommu->flush.flush_context(iommu, domain->id,
@@ -1183,6 +1542,13 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
                iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_DSI_FLUSH, 0);
 
        spin_unlock_irqrestore(&iommu->lock, flags);
+
+       spin_lock_irqsave(&domain->iommu_lock, flags);
+       if (!test_and_set_bit(iommu->seq_id, &domain->iommu_bmp)) {
+               domain->iommu_count++;
+               domain_update_iommu_coherency(domain);
+       }
+       spin_unlock_irqrestore(&domain->iommu_lock, flags);
        return 0;
 }
 
@@ -1218,13 +1584,17 @@ domain_context_mapping(struct dmar_domain *domain, struct pci_dev *pdev)
                        tmp->bus->number, tmp->devfn);
 }
 
-static int domain_context_mapped(struct dmar_domain *domain,
-       struct pci_dev *pdev)
+static int domain_context_mapped(struct pci_dev *pdev)
 {
        int ret;
        struct pci_dev *tmp, *parent;
+       struct intel_iommu *iommu;
+
+       iommu = device_to_iommu(pdev->bus->number, pdev->devfn);
+       if (!iommu)
+               return -ENODEV;
 
-       ret = device_context_mapped(domain->iommu,
+       ret = device_context_mapped(iommu,
                pdev->bus->number, pdev->devfn);
        if (!ret)
                return ret;
@@ -1235,17 +1605,17 @@ static int domain_context_mapped(struct dmar_domain *domain,
        /* Secondary interface's bus number and devfn 0 */
        parent = pdev->bus->self;
        while (parent != tmp) {
-               ret = device_context_mapped(domain->iommu, parent->bus->number,
+               ret = device_context_mapped(iommu, parent->bus->number,
                        parent->devfn);
                if (!ret)
                        return ret;
                parent = parent->bus->self;
        }
        if (tmp->is_pcie)
-               return device_context_mapped(domain->iommu,
+               return device_context_mapped(iommu,
                        tmp->subordinate->number, 0);
        else
-               return device_context_mapped(domain->iommu,
+               return device_context_mapped(iommu,
                        tmp->bus->number, tmp->devfn);
 }
 
@@ -1273,22 +1643,25 @@ domain_page_mapping(struct dmar_domain *domain, dma_addr_t iova,
                /* We don't need lock here, nobody else
                 * touches the iova range
                 */
-               BUG_ON(dma_pte_addr(*pte));
-               dma_set_pte_addr(*pte, start_pfn << VTD_PAGE_SHIFT);
-               dma_set_pte_prot(*pte, prot);
-               __iommu_flush_cache(domain->iommu, pte, sizeof(*pte));
+               BUG_ON(dma_pte_addr(pte));
+               dma_set_pte_addr(pte, start_pfn << VTD_PAGE_SHIFT);
+               dma_set_pte_prot(pte, prot);
+               domain_flush_cache(domain, pte, sizeof(*pte));
                start_pfn++;
                index++;
        }
        return 0;
 }
 
-static void detach_domain_for_dev(struct dmar_domain *domain, u8 bus, u8 devfn)
+static void iommu_detach_dev(struct intel_iommu *iommu, u8 bus, u8 devfn)
 {
-       clear_context_table(domain->iommu, bus, devfn);
-       domain->iommu->flush.flush_context(domain->iommu, 0, 0, 0,
+       if (!iommu)
+               return;
+
+       clear_context_table(iommu, bus, devfn);
+       iommu->flush.flush_context(iommu, 0, 0, 0,
                                           DMA_CCMD_GLOBAL_INVL, 0);
-       domain->iommu->flush.flush_iotlb(domain->iommu, 0, 0, 0,
+       iommu->flush.flush_iotlb(iommu, 0, 0, 0,
                                         DMA_TLB_GLOBAL_FLUSH, 0);
 }
 
@@ -1296,6 +1669,7 @@ static void domain_remove_dev_info(struct dmar_domain *domain)
 {
        struct device_domain_info *info;
        unsigned long flags;
+       struct intel_iommu *iommu;
 
        spin_lock_irqsave(&device_domain_lock, flags);
        while (!list_empty(&domain->devices)) {
@@ -1307,7 +1681,8 @@ static void domain_remove_dev_info(struct dmar_domain *domain)
                        info->dev->dev.archdata.iommu = NULL;
                spin_unlock_irqrestore(&device_domain_lock, flags);
 
-               detach_domain_for_dev(info->domain, info->bus, info->devfn);
+               iommu = device_to_iommu(info->bus, info->devfn);
+               iommu_detach_dev(iommu, info->bus, info->devfn);
                free_devinfo_mem(info);
 
                spin_lock_irqsave(&device_domain_lock, flags);
@@ -1400,7 +1775,7 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)
                info->dev = NULL;
                info->domain = domain;
                /* This domain is shared by devices under p2p bridge */
-               domain->flags |= DOMAIN_FLAG_MULTIPLE_DEVICES;
+               domain->flags |= DOMAIN_FLAG_P2P_MULTIPLE_DEVICES;
 
                /* pcie-to-pci bridge already has a domain, uses it */
                found = NULL;
@@ -1563,6 +1938,11 @@ static void __init iommu_prepare_gfx_mapping(void)
                        printk(KERN_ERR "IOMMU: mapping reserved region failed\n");
        }
 }
+#else /* !CONFIG_DMAR_GFX_WA */
+static inline void iommu_prepare_gfx_mapping(void)
+{
+       return;
+}
 #endif
 
 #ifdef CONFIG_DMAR_FLOPPY_WA
@@ -1590,7 +1970,7 @@ static inline void iommu_prepare_isa(void)
 }
 #endif /* !CONFIG_DMAR_FLPY_WA */
 
-int __init init_dmars(void)
+static int __init init_dmars(void)
 {
        struct dmar_drhd_unit *drhd;
        struct dmar_rmrr_unit *rmrr;
@@ -1613,9 +1993,18 @@ int __init init_dmars(void)
                 */
        }
 
+       g_iommus = kcalloc(g_num_of_iommus, sizeof(struct intel_iommu *),
+                       GFP_KERNEL);
+       if (!g_iommus) {
+               printk(KERN_ERR "Allocating global iommu array failed\n");
+               ret = -ENOMEM;
+               goto error;
+       }
+
        deferred_flush = kzalloc(g_num_of_iommus *
                sizeof(struct deferred_flush_tables), GFP_KERNEL);
        if (!deferred_flush) {
+               kfree(g_iommus);
                ret = -ENOMEM;
                goto error;
        }
@@ -1625,6 +2014,7 @@ int __init init_dmars(void)
                        continue;
 
                iommu = drhd->iommu;
+               g_iommus[iommu->seq_id] = iommu;
 
                ret = iommu_init_domains(iommu);
                if (ret)
@@ -1737,6 +2127,7 @@ error:
                iommu = drhd->iommu;
                free_iommu(iommu);
        }
+       kfree(g_iommus);
        return ret;
 }
 
@@ -1805,7 +2196,7 @@ get_valid_domain_for_dev(struct pci_dev *pdev)
        }
 
        /* make sure context mapping is ok */
-       if (unlikely(!domain_context_mapped(domain, pdev))) {
+       if (unlikely(!domain_context_mapped(pdev))) {
                ret = domain_context_mapping(domain, pdev);
                if (ret) {
                        printk(KERN_ERR
@@ -1827,6 +2218,7 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr,
        struct iova *iova;
        int prot = 0;
        int ret;
+       struct intel_iommu *iommu;
 
        BUG_ON(dir == DMA_NONE);
        if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
@@ -1836,6 +2228,7 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr,
        if (!domain)
                return 0;
 
+       iommu = domain_get_iommu(domain);
        size = aligned_size((u64)paddr, size);
 
        iova = __intel_alloc_iova(hwdev, domain, size, pdev->dma_mask);
@@ -1849,7 +2242,7 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr,
         * mappings..
         */
        if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
-                       !cap_zlr(domain->iommu->cap))
+                       !cap_zlr(iommu->cap))
                prot |= DMA_PTE_READ;
        if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
                prot |= DMA_PTE_WRITE;
@@ -1865,10 +2258,10 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr,
                goto error;
 
        /* it's a non-present to present mapping */
-       ret = iommu_flush_iotlb_psi(domain->iommu, domain->id,
+       ret = iommu_flush_iotlb_psi(iommu, domain->id,
                        start_paddr, size >> VTD_PAGE_SHIFT, 1);
        if (ret)
-               iommu_flush_write_buffer(domain->iommu);
+               iommu_flush_write_buffer(iommu);
 
        return start_paddr + ((u64)paddr & (~PAGE_MASK));
 
@@ -1895,10 +2288,11 @@ static void flush_unmaps(void)
 
        /* just flush them all */
        for (i = 0; i < g_num_of_iommus; i++) {
-               if (deferred_flush[i].next) {
-                       struct intel_iommu *iommu =
-                               deferred_flush[i].domain[0]->iommu;
+               struct intel_iommu *iommu = g_iommus[i];
+               if (!iommu)
+                       continue;
 
+               if (deferred_flush[i].next) {
                        iommu->flush.flush_iotlb(iommu, 0, 0, 0,
                                                 DMA_TLB_GLOBAL_FLUSH, 0);
                        for (j = 0; j < deferred_flush[i].next; j++) {
@@ -1925,12 +2319,14 @@ static void add_unmap(struct dmar_domain *dom, struct iova *iova)
 {
        unsigned long flags;
        int next, iommu_id;
+       struct intel_iommu *iommu;
 
        spin_lock_irqsave(&async_umap_flush_lock, flags);
        if (list_size == HIGH_WATER_MARK)
                flush_unmaps();
 
-       iommu_id = dom->iommu->seq_id;
+       iommu = domain_get_iommu(dom);
+       iommu_id = iommu->seq_id;
 
        next = deferred_flush[iommu_id].next;
        deferred_flush[iommu_id].domain[next] = dom;
@@ -1952,12 +2348,15 @@ void intel_unmap_single(struct device *dev, dma_addr_t dev_addr, size_t size,
        struct dmar_domain *domain;
        unsigned long start_addr;
        struct iova *iova;
+       struct intel_iommu *iommu;
 
        if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
                return;
        domain = find_domain(pdev);
        BUG_ON(!domain);
 
+       iommu = domain_get_iommu(domain);
+
        iova = find_iova(&domain->iovad, IOVA_PFN(dev_addr));
        if (!iova)
                return;
@@ -1973,9 +2372,9 @@ void intel_unmap_single(struct device *dev, dma_addr_t dev_addr, size_t size,
        /* free page tables */
        dma_pte_free_pagetable(domain, start_addr, start_addr + size);
        if (intel_iommu_strict) {
-               if (iommu_flush_iotlb_psi(domain->iommu,
+               if (iommu_flush_iotlb_psi(iommu,
                        domain->id, start_addr, size >> VTD_PAGE_SHIFT, 0))
-                       iommu_flush_write_buffer(domain->iommu);
+                       iommu_flush_write_buffer(iommu);
                /* free iova */
                __free_iova(&domain->iovad, iova);
        } else {
@@ -2036,11 +2435,15 @@ void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist,
        size_t size = 0;
        void *addr;
        struct scatterlist *sg;
+       struct intel_iommu *iommu;
 
        if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
                return;
 
        domain = find_domain(pdev);
+       BUG_ON(!domain);
+
+       iommu = domain_get_iommu(domain);
 
        iova = find_iova(&domain->iovad, IOVA_PFN(sglist[0].dma_address));
        if (!iova)
@@ -2057,9 +2460,9 @@ void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist,
        /* free page tables */
        dma_pte_free_pagetable(domain, start_addr, start_addr + size);
 
-       if (iommu_flush_iotlb_psi(domain->iommu, domain->id, start_addr,
+       if (iommu_flush_iotlb_psi(iommu, domain->id, start_addr,
                        size >> VTD_PAGE_SHIFT, 0))
-               iommu_flush_write_buffer(domain->iommu);
+               iommu_flush_write_buffer(iommu);
 
        /* free iova */
        __free_iova(&domain->iovad, iova);
@@ -2093,6 +2496,7 @@ int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int nelems,
        int ret;
        struct scatterlist *sg;
        unsigned long start_addr;
+       struct intel_iommu *iommu;
 
        BUG_ON(dir == DMA_NONE);
        if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
@@ -2102,6 +2506,8 @@ int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int nelems,
        if (!domain)
                return 0;
 
+       iommu = domain_get_iommu(domain);
+
        for_each_sg(sglist, sg, nelems, i) {
                addr = SG_ENT_VIRT_ADDRESS(sg);
                addr = (void *)virt_to_phys(addr);
@@ -2119,7 +2525,7 @@ int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int nelems,
         * mappings..
         */
        if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
-                       !cap_zlr(domain->iommu->cap))
+                       !cap_zlr(iommu->cap))
                prot |= DMA_PTE_READ;
        if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
                prot |= DMA_PTE_WRITE;
@@ -2151,9 +2557,9 @@ int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int nelems,
        }
 
        /* it's a non-present to present mapping */
-       if (iommu_flush_iotlb_psi(domain->iommu, domain->id,
+       if (iommu_flush_iotlb_psi(iommu, domain->id,
                        start_addr, offset >> VTD_PAGE_SHIFT, 1))
-               iommu_flush_write_buffer(domain->iommu);
+               iommu_flush_write_buffer(iommu);
        return nelems;
 }
 
@@ -2325,10 +2731,220 @@ int __init intel_iommu_init(void)
        init_timer(&unmap_timer);
        force_iommu = 1;
        dma_ops = &intel_dma_ops;
+
+       register_iommu(&intel_iommu_ops);
+
+       return 0;
+}
+
+static int vm_domain_add_dev_info(struct dmar_domain *domain,
+                                 struct pci_dev *pdev)
+{
+       struct device_domain_info *info;
+       unsigned long flags;
+
+       info = alloc_devinfo_mem();
+       if (!info)
+               return -ENOMEM;
+
+       info->bus = pdev->bus->number;
+       info->devfn = pdev->devfn;
+       info->dev = pdev;
+       info->domain = domain;
+
+       spin_lock_irqsave(&device_domain_lock, flags);
+       list_add(&info->link, &domain->devices);
+       list_add(&info->global, &device_domain_list);
+       pdev->dev.archdata.iommu = info;
+       spin_unlock_irqrestore(&device_domain_lock, flags);
+
+       return 0;
+}
+
+static void vm_domain_remove_one_dev_info(struct dmar_domain *domain,
+                                         struct pci_dev *pdev)
+{
+       struct device_domain_info *info;
+       struct intel_iommu *iommu;
+       unsigned long flags;
+       int found = 0;
+       struct list_head *entry, *tmp;
+
+       iommu = device_to_iommu(pdev->bus->number, pdev->devfn);
+       if (!iommu)
+               return;
+
+       spin_lock_irqsave(&device_domain_lock, flags);
+       list_for_each_safe(entry, tmp, &domain->devices) {
+               info = list_entry(entry, struct device_domain_info, link);
+               if (info->bus == pdev->bus->number &&
+                   info->devfn == pdev->devfn) {
+                       list_del(&info->link);
+                       list_del(&info->global);
+                       if (info->dev)
+                               info->dev->dev.archdata.iommu = NULL;
+                       spin_unlock_irqrestore(&device_domain_lock, flags);
+
+                       iommu_detach_dev(iommu, info->bus, info->devfn);
+                       free_devinfo_mem(info);
+
+                       spin_lock_irqsave(&device_domain_lock, flags);
+
+                       if (found)
+                               break;
+                       else
+                               continue;
+               }
+
+               /* if there is no other devices under the same iommu
+                * owned by this domain, clear this iommu in iommu_bmp
+                * update iommu count and coherency
+                */
+               if (device_to_iommu(info->bus, info->devfn) == iommu)
+                       found = 1;
+       }
+
+       if (found == 0) {
+               unsigned long tmp_flags;
+               spin_lock_irqsave(&domain->iommu_lock, tmp_flags);
+               clear_bit(iommu->seq_id, &domain->iommu_bmp);
+               domain->iommu_count--;
+               domain_update_iommu_coherency(domain);
+               spin_unlock_irqrestore(&domain->iommu_lock, tmp_flags);
+       }
+
+       spin_unlock_irqrestore(&device_domain_lock, flags);
+}
+
+static void vm_domain_remove_all_dev_info(struct dmar_domain *domain)
+{
+       struct device_domain_info *info;
+       struct intel_iommu *iommu;
+       unsigned long flags1, flags2;
+
+       spin_lock_irqsave(&device_domain_lock, flags1);
+       while (!list_empty(&domain->devices)) {
+               info = list_entry(domain->devices.next,
+                       struct device_domain_info, link);
+               list_del(&info->link);
+               list_del(&info->global);
+               if (info->dev)
+                       info->dev->dev.archdata.iommu = NULL;
+
+               spin_unlock_irqrestore(&device_domain_lock, flags1);
+
+               iommu = device_to_iommu(info->bus, info->devfn);
+               iommu_detach_dev(iommu, info->bus, info->devfn);
+
+               /* clear this iommu in iommu_bmp, update iommu count
+                * and coherency
+                */
+               spin_lock_irqsave(&domain->iommu_lock, flags2);
+               if (test_and_clear_bit(iommu->seq_id,
+                                      &domain->iommu_bmp)) {
+                       domain->iommu_count--;
+                       domain_update_iommu_coherency(domain);
+               }
+               spin_unlock_irqrestore(&domain->iommu_lock, flags2);
+
+               free_devinfo_mem(info);
+               spin_lock_irqsave(&device_domain_lock, flags1);
+       }
+       spin_unlock_irqrestore(&device_domain_lock, flags1);
+}
+
+/* domain id for virtual machine, it won't be set in context */
+static unsigned long vm_domid;
+
+static int vm_domain_min_agaw(struct dmar_domain *domain)
+{
+       int i;
+       int min_agaw = domain->agaw;
+
+       i = find_first_bit(&domain->iommu_bmp, g_num_of_iommus);
+       for (; i < g_num_of_iommus; ) {
+               if (min_agaw > g_iommus[i]->agaw)
+                       min_agaw = g_iommus[i]->agaw;
+
+               i = find_next_bit(&domain->iommu_bmp, g_num_of_iommus, i+1);
+       }
+
+       return min_agaw;
+}
+
+static struct dmar_domain *iommu_alloc_vm_domain(void)
+{
+       struct dmar_domain *domain;
+
+       domain = alloc_domain_mem();
+       if (!domain)
+               return NULL;
+
+       domain->id = vm_domid++;
+       memset(&domain->iommu_bmp, 0, sizeof(unsigned long));
+       domain->flags = DOMAIN_FLAG_VIRTUAL_MACHINE;
+
+       return domain;
+}
+
+static int vm_domain_init(struct dmar_domain *domain, int guest_width)
+{
+       int adjust_width;
+
+       init_iova_domain(&domain->iovad, DMA_32BIT_PFN);
+       spin_lock_init(&domain->mapping_lock);
+       spin_lock_init(&domain->iommu_lock);
+
+       domain_reserve_special_ranges(domain);
+
+       /* calculate AGAW */
+       domain->gaw = guest_width;
+       adjust_width = guestwidth_to_adjustwidth(guest_width);
+       domain->agaw = width_to_agaw(adjust_width);
+
+       INIT_LIST_HEAD(&domain->devices);
+
+       domain->iommu_count = 0;
+       domain->iommu_coherency = 0;
+       domain->max_addr = 0;
+
+       /* always allocate the top pgd */
+       domain->pgd = (struct dma_pte *)alloc_pgtable_page();
+       if (!domain->pgd)
+               return -ENOMEM;
+       domain_flush_cache(domain, domain->pgd, PAGE_SIZE);
        return 0;
 }
 
-void intel_iommu_domain_exit(struct dmar_domain *domain)
+static void iommu_free_vm_domain(struct dmar_domain *domain)
+{
+       unsigned long flags;
+       struct dmar_drhd_unit *drhd;
+       struct intel_iommu *iommu;
+       unsigned long i;
+       unsigned long ndomains;
+
+       for_each_drhd_unit(drhd) {
+               if (drhd->ignored)
+                       continue;
+               iommu = drhd->iommu;
+
+               ndomains = cap_ndoms(iommu->cap);
+               i = find_first_bit(iommu->domain_ids, ndomains);
+               for (; i < ndomains; ) {
+                       if (iommu->domains[i] == domain) {
+                               spin_lock_irqsave(&iommu->lock, flags);
+                               clear_bit(i, iommu->domain_ids);
+                               iommu->domains[i] = NULL;
+                               spin_unlock_irqrestore(&iommu->lock, flags);
+                               break;
+                       }
+                       i = find_next_bit(iommu->domain_ids, ndomains, i+1);
+               }
+       }
+}
+
+static void vm_domain_exit(struct dmar_domain *domain)
 {
        u64 end;
 
@@ -2336,6 +2952,9 @@ void intel_iommu_domain_exit(struct dmar_domain *domain)
        if (!domain)
                return;
 
+       vm_domain_remove_all_dev_info(domain);
+       /* destroy iovas */
+       put_iova_domain(&domain->iovad);
        end = DOMAIN_MAX_ADDR(domain->gaw);
        end = end & (~VTD_PAGE_MASK);
 
@@ -2345,94 +2964,167 @@ void intel_iommu_domain_exit(struct dmar_domain *domain)
        /* free page tables */
        dma_pte_free_pagetable(domain, 0, end);
 
-       iommu_free_domain(domain);
+       iommu_free_vm_domain(domain);
        free_domain_mem(domain);
 }
-EXPORT_SYMBOL_GPL(intel_iommu_domain_exit);
 
-struct dmar_domain *intel_iommu_domain_alloc(struct pci_dev *pdev)
+static int intel_iommu_domain_init(struct iommu_domain *domain)
 {
-       struct dmar_drhd_unit *drhd;
-       struct dmar_domain *domain;
-       struct intel_iommu *iommu;
-
-       drhd = dmar_find_matched_drhd_unit(pdev);
-       if (!drhd) {
-               printk(KERN_ERR "intel_iommu_domain_alloc: drhd == NULL\n");
-               return NULL;
-       }
+       struct dmar_domain *dmar_domain;
 
-       iommu = drhd->iommu;
-       if (!iommu) {
-               printk(KERN_ERR
-                       "intel_iommu_domain_alloc: iommu == NULL\n");
-               return NULL;
-       }
-       domain = iommu_alloc_domain(iommu);
-       if (!domain) {
+       dmar_domain = iommu_alloc_vm_domain();
+       if (!dmar_domain) {
                printk(KERN_ERR
-                       "intel_iommu_domain_alloc: domain == NULL\n");
-               return NULL;
+                       "intel_iommu_domain_init: dmar_domain == NULL\n");
+               return -ENOMEM;
        }
-       if (domain_init(domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
+       if (vm_domain_init(dmar_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
                printk(KERN_ERR
-                       "intel_iommu_domain_alloc: domain_init() failed\n");
-               intel_iommu_domain_exit(domain);
-               return NULL;
+                       "intel_iommu_domain_init() failed\n");
+               vm_domain_exit(dmar_domain);
+               return -ENOMEM;
        }
-       return domain;
+       domain->priv = dmar_domain;
+
+       return 0;
 }
-EXPORT_SYMBOL_GPL(intel_iommu_domain_alloc);
 
-int intel_iommu_context_mapping(
-       struct dmar_domain *domain, struct pci_dev *pdev)
+static void intel_iommu_domain_destroy(struct iommu_domain *domain)
 {
-       int rc;
-       rc = domain_context_mapping(domain, pdev);
-       return rc;
+       struct dmar_domain *dmar_domain = domain->priv;
+
+       domain->priv = NULL;
+       vm_domain_exit(dmar_domain);
 }
-EXPORT_SYMBOL_GPL(intel_iommu_context_mapping);
 
-int intel_iommu_page_mapping(
-       struct dmar_domain *domain, dma_addr_t iova,
-       u64 hpa, size_t size, int prot)
+static int intel_iommu_attach_device(struct iommu_domain *domain,
+                                    struct device *dev)
 {
-       int rc;
-       rc = domain_page_mapping(domain, iova, hpa, size, prot);
-       return rc;
+       struct dmar_domain *dmar_domain = domain->priv;
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct intel_iommu *iommu;
+       int addr_width;
+       u64 end;
+       int ret;
+
+       /* normally pdev is not mapped */
+       if (unlikely(domain_context_mapped(pdev))) {
+               struct dmar_domain *old_domain;
+
+               old_domain = find_domain(pdev);
+               if (old_domain) {
+                       if (dmar_domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE)
+                               vm_domain_remove_one_dev_info(old_domain, pdev);
+                       else
+                               domain_remove_dev_info(old_domain);
+               }
+       }
+
+       iommu = device_to_iommu(pdev->bus->number, pdev->devfn);
+       if (!iommu)
+               return -ENODEV;
+
+       /* check if this iommu agaw is sufficient for max mapped address */
+       addr_width = agaw_to_width(iommu->agaw);
+       end = DOMAIN_MAX_ADDR(addr_width);
+       end = end & VTD_PAGE_MASK;
+       if (end < dmar_domain->max_addr) {
+               printk(KERN_ERR "%s: iommu agaw (%d) is not "
+                      "sufficient for the mapped address (%llx)\n",
+                      __func__, iommu->agaw, dmar_domain->max_addr);
+               return -EFAULT;
+       }
+
+       ret = domain_context_mapping(dmar_domain, pdev);
+       if (ret)
+               return ret;
+
+       ret = vm_domain_add_dev_info(dmar_domain, pdev);
+       return ret;
 }
-EXPORT_SYMBOL_GPL(intel_iommu_page_mapping);
 
-void intel_iommu_detach_dev(struct dmar_domain *domain, u8 bus, u8 devfn)
+static void intel_iommu_detach_device(struct iommu_domain *domain,
+                                     struct device *dev)
 {
-       detach_domain_for_dev(domain, bus, devfn);
+       struct dmar_domain *dmar_domain = domain->priv;
+       struct pci_dev *pdev = to_pci_dev(dev);
+
+       vm_domain_remove_one_dev_info(dmar_domain, pdev);
 }
-EXPORT_SYMBOL_GPL(intel_iommu_detach_dev);
 
-struct dmar_domain *
-intel_iommu_find_domain(struct pci_dev *pdev)
+static int intel_iommu_map_range(struct iommu_domain *domain,
+                                unsigned long iova, phys_addr_t hpa,
+                                size_t size, int iommu_prot)
 {
-       return find_domain(pdev);
+       struct dmar_domain *dmar_domain = domain->priv;
+       u64 max_addr;
+       int addr_width;
+       int prot = 0;
+       int ret;
+
+       if (iommu_prot & IOMMU_READ)
+               prot |= DMA_PTE_READ;
+       if (iommu_prot & IOMMU_WRITE)
+               prot |= DMA_PTE_WRITE;
+
+       max_addr = (iova & VTD_PAGE_MASK) + VTD_PAGE_ALIGN(size);
+       if (dmar_domain->max_addr < max_addr) {
+               int min_agaw;
+               u64 end;
+
+               /* check if minimum agaw is sufficient for mapped address */
+               min_agaw = vm_domain_min_agaw(dmar_domain);
+               addr_width = agaw_to_width(min_agaw);
+               end = DOMAIN_MAX_ADDR(addr_width);
+               end = end & VTD_PAGE_MASK;
+               if (end < max_addr) {
+                       printk(KERN_ERR "%s: iommu agaw (%d) is not "
+                              "sufficient for the mapped address (%llx)\n",
+                              __func__, min_agaw, max_addr);
+                       return -EFAULT;
+               }
+               dmar_domain->max_addr = max_addr;
+       }
+
+       ret = domain_page_mapping(dmar_domain, iova, hpa, size, prot);
+       return ret;
 }
-EXPORT_SYMBOL_GPL(intel_iommu_find_domain);
 
-int intel_iommu_found(void)
+static void intel_iommu_unmap_range(struct iommu_domain *domain,
+                                   unsigned long iova, size_t size)
 {
-       return g_num_of_iommus;
+       struct dmar_domain *dmar_domain = domain->priv;
+       dma_addr_t base;
+
+       /* The address might not be aligned */
+       base = iova & VTD_PAGE_MASK;
+       size = VTD_PAGE_ALIGN(size);
+       dma_pte_clear_range(dmar_domain, base, base + size);
+
+       if (dmar_domain->max_addr == base + size)
+               dmar_domain->max_addr = base;
 }
-EXPORT_SYMBOL_GPL(intel_iommu_found);
 
-u64 intel_iommu_iova_to_pfn(struct dmar_domain *domain, u64 iova)
+static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
+                                           unsigned long iova)
 {
+       struct dmar_domain *dmar_domain = domain->priv;
        struct dma_pte *pte;
-       u64 pfn;
-
-       pfn = 0;
-       pte = addr_to_dma_pte(domain, iova);
+       u64 phys = 0;
 
+       pte = addr_to_dma_pte(dmar_domain, iova);
        if (pte)
-               pfn = dma_pte_addr(*pte);
+               phys = dma_pte_addr(pte);
 
-       return pfn >> VTD_PAGE_SHIFT;
+       return phys;
 }
-EXPORT_SYMBOL_GPL(intel_iommu_iova_to_pfn);
+
+static struct iommu_ops intel_iommu_ops = {
+       .domain_init    = intel_iommu_domain_init,
+       .domain_destroy = intel_iommu_domain_destroy,
+       .attach_dev     = intel_iommu_attach_device,
+       .detach_dev     = intel_iommu_detach_device,
+       .map            = intel_iommu_map_range,
+       .unmap          = intel_iommu_unmap_range,
+       .iova_to_phys   = intel_iommu_iova_to_phys,
+};
index 7ff824496b397b236eda67c1a39b178b6ea22024..7e6b5a3b328177866ca2dbb15e7247510e95fd6e 100644 (file)
@@ -481,7 +481,7 @@ void pnpbios_calls_init(union pnp_bios_install_struct *header)
 
        set_base(bad_bios_desc, __va((unsigned long)0x40 << 4));
        _set_limit((char *)&bad_bios_desc, 4095 - (0x40 << 4));
-       for (i = 0; i < NR_CPUS; i++) {
+       for_each_possible_cpu(i) {
                struct desc_struct *gdt = get_cpu_gdt_table(i);
                if (!gdt)
                        continue;
index 123092d8a98484aebde61d7c60cc77639e95c351..165a81843357f230bb1c1ff0f47b9b0139277150 100644 (file)
@@ -102,9 +102,13 @@ config RTC_INTF_DEV_UIE_EMUL
        depends on RTC_INTF_DEV
        help
          Provides an emulation for RTC_UIE if the underlying rtc chip
-         driver does not expose RTC_UIE ioctls.  Those requests generate
+         driver does not expose RTC_UIE ioctls. Those requests generate
          once-per-second update interrupts, used for synchronization.
 
+         The emulation code will read the time from the hardware
+         clock several times per second, please enable this option
+         only if you know that you really need it.
+
 config RTC_DRV_TEST
        tristate "Test driver/device"
        help
index a04c1b6b1575ba28b94ccb8027007123731977d4..fd2c652504ff6bbac47545f9ca8f74604ea3e9b5 100644 (file)
@@ -307,6 +307,60 @@ int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
 }
 EXPORT_SYMBOL_GPL(rtc_set_alarm);
 
+int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled)
+{
+       int err = mutex_lock_interruptible(&rtc->ops_lock);
+       if (err)
+               return err;
+
+       if (!rtc->ops)
+               err = -ENODEV;
+       else if (!rtc->ops->alarm_irq_enable)
+               err = -EINVAL;
+       else
+               err = rtc->ops->alarm_irq_enable(rtc->dev.parent, enabled);
+
+       mutex_unlock(&rtc->ops_lock);
+       return err;
+}
+EXPORT_SYMBOL_GPL(rtc_alarm_irq_enable);
+
+int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled)
+{
+       int err = mutex_lock_interruptible(&rtc->ops_lock);
+       if (err)
+               return err;
+
+#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
+       if (enabled == 0 && rtc->uie_irq_active) {
+               mutex_unlock(&rtc->ops_lock);
+               return rtc_dev_update_irq_enable_emul(rtc, enabled);
+       }
+#endif
+
+       if (!rtc->ops)
+               err = -ENODEV;
+       else if (!rtc->ops->update_irq_enable)
+               err = -EINVAL;
+       else
+               err = rtc->ops->update_irq_enable(rtc->dev.parent, enabled);
+
+       mutex_unlock(&rtc->ops_lock);
+
+#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
+       /*
+        * Enable emulation if the driver did not provide
+        * the update_irq_enable function pointer or if returned
+        * -EINVAL to signal that it has been configured without
+        * interrupts or that are not available at the moment.
+        */
+       if (err == -EINVAL)
+               err = rtc_dev_update_irq_enable_emul(rtc, enabled);
+#endif
+       return err;
+}
+EXPORT_SYMBOL_GPL(rtc_update_irq_enable);
+
 /**
  * rtc_update_irq - report RTC periodic, alarm, and/or update irqs
  * @rtc: the rtc device
index ecdea44ae4e5465ddeb37e07361d74f020aa65da..45152f4952d66f5d28a99211f7e6e71d09649e12 100644 (file)
@@ -92,10 +92,10 @@ static void rtc_uie_timer(unsigned long data)
        spin_unlock_irqrestore(&rtc->irq_lock, flags);
 }
 
-static void clear_uie(struct rtc_device *rtc)
+static int clear_uie(struct rtc_device *rtc)
 {
        spin_lock_irq(&rtc->irq_lock);
-       if (rtc->irq_active) {
+       if (rtc->uie_irq_active) {
                rtc->stop_uie_polling = 1;
                if (rtc->uie_timer_active) {
                        spin_unlock_irq(&rtc->irq_lock);
@@ -108,9 +108,10 @@ static void clear_uie(struct rtc_device *rtc)
                        flush_scheduled_work();
                        spin_lock_irq(&rtc->irq_lock);
                }
-               rtc->irq_active = 0;
+               rtc->uie_irq_active = 0;
        }
        spin_unlock_irq(&rtc->irq_lock);
+       return 0;
 }
 
 static int set_uie(struct rtc_device *rtc)
@@ -122,8 +123,8 @@ static int set_uie(struct rtc_device *rtc)
        if (err)
                return err;
        spin_lock_irq(&rtc->irq_lock);
-       if (!rtc->irq_active) {
-               rtc->irq_active = 1;
+       if (!rtc->uie_irq_active) {
+               rtc->uie_irq_active = 1;
                rtc->stop_uie_polling = 0;
                rtc->oldsecs = tm.tm_sec;
                rtc->uie_task_active = 1;
@@ -134,6 +135,16 @@ static int set_uie(struct rtc_device *rtc)
        spin_unlock_irq(&rtc->irq_lock);
        return 0;
 }
+
+int rtc_dev_update_irq_enable_emul(struct rtc_device *rtc, unsigned int enabled)
+{
+       if (enabled)
+               return set_uie(rtc);
+       else
+               return clear_uie(rtc);
+}
+EXPORT_SYMBOL(rtc_dev_update_irq_enable_emul);
+
 #endif /* CONFIG_RTC_INTF_DEV_UIE_EMUL */
 
 static ssize_t
@@ -357,6 +368,22 @@ static long rtc_dev_ioctl(struct file *file,
                err = rtc_irq_set_state(rtc, NULL, 0);
                break;
 
+       case RTC_AIE_ON:
+               mutex_unlock(&rtc->ops_lock);
+               return rtc_alarm_irq_enable(rtc, 1);
+
+       case RTC_AIE_OFF:
+               mutex_unlock(&rtc->ops_lock);
+               return rtc_alarm_irq_enable(rtc, 0);
+
+       case RTC_UIE_ON:
+               mutex_unlock(&rtc->ops_lock);
+               return rtc_update_irq_enable(rtc, 1);
+
+       case RTC_UIE_OFF:
+               mutex_unlock(&rtc->ops_lock);
+               return rtc_update_irq_enable(rtc, 0);
+
        case RTC_IRQP_SET:
                err = rtc_irq_set_freq(rtc, NULL, arg);
                break;
@@ -401,17 +428,6 @@ static long rtc_dev_ioctl(struct file *file,
                        err = -EFAULT;
                return err;
 
-#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
-       case RTC_UIE_OFF:
-               mutex_unlock(&rtc->ops_lock);
-               clear_uie(rtc);
-               return 0;
-
-       case RTC_UIE_ON:
-               mutex_unlock(&rtc->ops_lock);
-               err = set_uie(rtc);
-               return err;
-#endif
        default:
                err = -ENOTTY;
                break;
@@ -440,7 +456,10 @@ static int rtc_dev_release(struct inode *inode, struct file *file)
         * Leave the alarm alone; it may be set to trigger a system wakeup
         * later, or be used by kernel code, and is a one-shot event anyway.
         */
+
+       /* Keep ioctl until all drivers are converted */
        rtc_dev_ioctl(file, RTC_UIE_OFF, 0);
+       rtc_update_irq_enable(rtc, 0);
        rtc_irq_set_state(rtc, NULL, 0);
 
        if (rtc->ops->release)
index 8a8df7552969d15ad0d2532b4cf94aef3bdf3f89..06b71823f3991b7e23d6810d13be0f6c0f5cee20 100644 (file)
@@ -632,8 +632,8 @@ do_IRQ (struct pt_regs *regs)
        struct pt_regs *old_regs;
 
        old_regs = set_irq_regs(regs);
-       irq_enter();
        s390_idle_check();
+       irq_enter();
        if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator)
                /* Serve timer interrupts first. */
                clock_comparator_work();
index d5ccce1643e43a9fc477ccda2ede4cbbf6ad2a73..e0c45574b0c8f0208594ebfe8087971c43b0c172 100644 (file)
@@ -643,7 +643,6 @@ struct qeth_card_options {
        int macaddr_mode;
        int fake_broadcast;
        int add_hhlen;
-       int fake_ll;
        int layer2;
        enum qeth_large_send_types large_send;
        int performance_stats;
index e783644a2105b41d7b45e2fda6318f72badae3da..6811dd529f48ca32029ca32f879869f365573951 100644 (file)
@@ -287,8 +287,15 @@ int qeth_set_large_send(struct qeth_card *card,
        card->options.large_send = type;
        switch (card->options.large_send) {
        case QETH_LARGE_SEND_EDDP:
-               card->dev->features |= NETIF_F_TSO | NETIF_F_SG |
+               if (card->info.type != QETH_CARD_TYPE_IQD) {
+                       card->dev->features |= NETIF_F_TSO | NETIF_F_SG |
                                        NETIF_F_HW_CSUM;
+               } else {
+                       card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG |
+                                               NETIF_F_HW_CSUM);
+                       card->options.large_send = QETH_LARGE_SEND_NO;
+                       rc = -EOPNOTSUPP;
+               }
                break;
        case QETH_LARGE_SEND_TSO:
                if (qeth_is_supported(card, IPA_OUTBOUND_TSO)) {
@@ -572,6 +579,10 @@ static void qeth_send_control_data_cb(struct qeth_channel *channel,
        card = CARD_FROM_CDEV(channel->ccwdev);
        if (qeth_check_idx_response(iob->data)) {
                qeth_clear_ipacmd_list(card);
+               if (((iob->data[2] & 0xc0) == 0xc0) && iob->data[4] == 0xf6)
+                       dev_err(&card->gdev->dev,
+                               "The qeth device is not configured "
+                               "for the OSI layer required by z/VM\n");
                qeth_schedule_recovery(card);
                goto out;
        }
@@ -1072,7 +1083,6 @@ static void qeth_set_intial_options(struct qeth_card *card)
        card->options.macaddr_mode = QETH_TR_MACADDR_NONCANONICAL;
        card->options.fake_broadcast = 0;
        card->options.add_hhlen = DEFAULT_ADD_HHLEN;
-       card->options.fake_ll = 0;
        card->options.performance_stats = 0;
        card->options.rx_sg_cb = QETH_RX_SG_CB;
 }
@@ -1682,6 +1692,7 @@ int qeth_send_control_data(struct qeth_card *card, int len,
        unsigned long flags;
        struct qeth_reply *reply = NULL;
        unsigned long timeout;
+       struct qeth_ipa_cmd *cmd;
 
        QETH_DBF_TEXT(TRACE, 2, "sendctl");
 
@@ -1728,17 +1739,34 @@ int qeth_send_control_data(struct qeth_card *card, int len,
                wake_up(&card->wait_q);
                return rc;
        }
-       while (!atomic_read(&reply->received)) {
-               if (time_after(jiffies, timeout)) {
-                       spin_lock_irqsave(&reply->card->lock, flags);
-                       list_del_init(&reply->list);
-                       spin_unlock_irqrestore(&reply->card->lock, flags);
-                       reply->rc = -ETIME;
-                       atomic_inc(&reply->received);
-                       wake_up(&reply->wait_q);
-               }
-               cpu_relax();
-       };
+
+       /* we have only one long running ipassist, since we can ensure
+          process context of this command we can sleep */
+       cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+       if ((cmd->hdr.command == IPA_CMD_SETIP) &&
+           (cmd->hdr.prot_version == QETH_PROT_IPV4)) {
+               if (!wait_event_timeout(reply->wait_q,
+                   atomic_read(&reply->received), timeout))
+                       goto time_err;
+       } else {
+               while (!atomic_read(&reply->received)) {
+                       if (time_after(jiffies, timeout))
+                               goto time_err;
+                       cpu_relax();
+               };
+       }
+
+       rc = reply->rc;
+       qeth_put_reply(reply);
+       return rc;
+
+time_err:
+       spin_lock_irqsave(&reply->card->lock, flags);
+       list_del_init(&reply->list);
+       spin_unlock_irqrestore(&reply->card->lock, flags);
+       reply->rc = -ETIME;
+       atomic_inc(&reply->received);
+       wake_up(&reply->wait_q);
        rc = reply->rc;
        qeth_put_reply(reply);
        return rc;
@@ -2250,7 +2278,8 @@ void qeth_print_status_message(struct qeth_card *card)
                }
                /* fallthrough */
        case QETH_CARD_TYPE_IQD:
-               if (card->info.guestlan) {
+               if ((card->info.guestlan) ||
+                   (card->info.mcl_level[0] & 0x80)) {
                        card->info.mcl_level[0] = (char) _ebcasc[(__u8)
                                card->info.mcl_level[0]];
                        card->info.mcl_level[1] = (char) _ebcasc[(__u8)
index 2c48591ced444530448b01c1881109da4acc34d5..21627ba3093be6aec8d4718afba2ca4e91248b62 100644 (file)
@@ -1126,9 +1126,11 @@ static int qeth_l2_recover(void *ptr)
                dev_info(&card->gdev->dev,
                        "Device successfully recovered!\n");
        else {
-               rtnl_lock();
-               dev_close(card->dev);
-               rtnl_unlock();
+               if (card->dev) {
+                       rtnl_lock();
+                       dev_close(card->dev);
+                       rtnl_unlock();
+               }
                dev_warn(&card->gdev->dev, "The qeth device driver "
                        "failed to recover an error on the device\n");
        }
index c0b30b25a5f19c6ec0d39f44ccc49c2007b731e8..cfda1ecffdf24db5e60122706f514c23c2ef2db0 100644 (file)
@@ -1047,7 +1047,7 @@ static int qeth_l3_setadapter_parms(struct qeth_card *card)
                rc = qeth_setadpparms_change_macaddr(card);
                if (rc)
                        dev_warn(&card->gdev->dev, "Reading the adapter MAC"
-                               " address failed\n", rc);
+                               " address failed\n");
        }
 
        if ((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
@@ -1207,12 +1207,9 @@ static int qeth_l3_start_ipa_source_mac(struct qeth_card *card)
 
        QETH_DBF_TEXT(TRACE, 3, "stsrcmac");
 
-       if (!card->options.fake_ll)
-               return -EOPNOTSUPP;
-
        if (!qeth_is_supported(card, IPA_SOURCE_MAC)) {
                dev_info(&card->gdev->dev,
-                       "Inbound source address not supported on %s\n",
+                       "Inbound source MAC-address not supported on %s\n",
                        QETH_CARD_IFNAME(card));
                return -EOPNOTSUPP;
        }
@@ -1221,7 +1218,7 @@ static int qeth_l3_start_ipa_source_mac(struct qeth_card *card)
                                          IPA_CMD_ASS_START, 0);
        if (rc)
                dev_warn(&card->gdev->dev,
-                       "Starting proxy ARP support for %s failed\n",
+                       "Starting source MAC-address support for %s failed\n",
                        QETH_CARD_IFNAME(card));
        return rc;
 }
@@ -1921,8 +1918,13 @@ static inline __u16 qeth_l3_rebuild_skb(struct qeth_card *card,
                        memcpy(tg_addr, card->dev->dev_addr,
                                card->dev->addr_len);
                }
-               card->dev->header_ops->create(skb, card->dev, prot, tg_addr,
-                                             "FAKELL", card->dev->addr_len);
+               if (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_SRC_MAC_ADDR)
+                       card->dev->header_ops->create(skb, card->dev, prot,
+                               tg_addr, &hdr->hdr.l3.dest_addr[2],
+                               card->dev->addr_len);
+               else
+                       card->dev->header_ops->create(skb, card->dev, prot,
+                               tg_addr, "FAKELL", card->dev->addr_len);
        }
 
 #ifdef CONFIG_TR
@@ -2080,9 +2082,11 @@ static int qeth_l3_stop_card(struct qeth_card *card, int recovery_mode)
                if (recovery_mode)
                        qeth_l3_stop(card->dev);
                else {
-                       rtnl_lock();
-                       dev_close(card->dev);
-                       rtnl_unlock();
+                       if (card->dev) {
+                               rtnl_lock();
+                               dev_close(card->dev);
+                               rtnl_unlock();
+                       }
                }
                if (!card->use_hard_stop) {
                        rc = qeth_send_stoplan(card);
index 834e9ee7e934f0e3222d17d0e7e929db565a615d..92b0417f8e12069403f1d50bbfb5653913b5a8f9 100644 (file)
@@ -18,6 +18,7 @@
 #include <asm/etr.h>
 #include <asm/lowcore.h>
 #include <asm/cio.h>
+#include <asm/cpu.h>
 #include "s390mach.h"
 
 static struct semaphore m_sem;
@@ -369,6 +370,8 @@ s390_do_machine_check(struct pt_regs *regs)
 
        lockdep_off();
 
+       s390_idle_check();
+
        mci = (struct mci *) &S390_lowcore.mcck_interruption_code;
        mcck = &__get_cpu_var(cpu_mcck);
        umode = user_mode(regs);
index 185be760833e8b05a2940f13d90af0f9bdcec946..2a129cb7bb568232e2c7869c26bd7061d62e3d9d 100644 (file)
@@ -279,7 +279,6 @@ static struct inode *usbfs_get_inode (struct super_block *sb, int mode, dev_t de
                inode->i_mode = mode;
                inode->i_uid = current_fsuid();
                inode->i_gid = current_fsgid();
-               inode->i_blocks = 0;
                inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
                switch (mode & S_IFMT) {
                default:
index c4e62a6297d7254b375c682e24e3c3d9c5d84e5d..2e71368f45b4c6d423f27c11ab11aa14bc4dd06c 100644 (file)
@@ -1863,26 +1863,10 @@ static int do_write(struct fsg_dev *fsg)
 static int fsync_sub(struct lun *curlun)
 {
        struct file     *filp = curlun->filp;
-       struct inode    *inode;
-       int             rc, err;
 
        if (curlun->ro || !filp)
                return 0;
-       if (!filp->f_op->fsync)
-               return -EINVAL;
-
-       inode = filp->f_path.dentry->d_inode;
-       mutex_lock(&inode->i_mutex);
-       rc = filemap_fdatawrite(inode->i_mapping);
-       err = filp->f_op->fsync(filp, filp->f_path.dentry, 1);
-       if (!rc)
-               rc = err;
-       err = filemap_fdatawait(inode->i_mapping);
-       if (!rc)
-               rc = err;
-       mutex_unlock(&inode->i_mutex);
-       VLDBG(curlun, "fdatasync -> %d\n", rc);
-       return rc;
+       return vfs_fsync(filp, filp->f_path.dentry, 1);
 }
 
 static void fsync_all(struct fsg_dev *fsg)
index eeb26c0f88e5846d4c0849e70ddf01eea90fa65d..317b48fdbf01b302bd9442d13b9bb923408a1c17 100644 (file)
@@ -2001,7 +2001,6 @@ gadgetfs_make_inode (struct super_block *sb,
                inode->i_mode = mode;
                inode->i_uid = default_uid;
                inode->i_gid = default_gid;
-               inode->i_blocks = 0;
                inode->i_atime = inode->i_mtime = inode->i_ctime
                                = CURRENT_TIME;
                inode->i_private = data;
index 73ac754ad801952bebb8741639df05a98ace7c4a..e21fe5b6f9ffcaa739a3a8faef9dc7db0842cfc1 100644 (file)
@@ -546,23 +546,25 @@ static int viafb_blank(int blank_mode, struct fb_info *info)
 
 static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
 {
-       struct viafb_ioctl_mode viamode;
-       struct viafb_ioctl_samm viasamm;
-       struct viafb_driver_version driver_version;
-       struct fb_var_screeninfo sec_var;
-       struct _panel_size_pos_info panel_pos_size_para;
+       union {
+               struct viafb_ioctl_mode viamode;
+               struct viafb_ioctl_samm viasamm;
+               struct viafb_driver_version driver_version;
+               struct fb_var_screeninfo sec_var;
+               struct _panel_size_pos_info panel_pos_size_para;
+               struct viafb_ioctl_setting viafb_setting;
+               struct device_t active_dev;
+       } u;
        u32 state_info = 0;
-       u32 viainfo_size = sizeof(struct viafb_ioctl_info);
        u32 *viafb_gamma_table;
        char driver_name[] = "viafb";
 
        u32 __user *argp = (u32 __user *) arg;
        u32 gpu32;
        u32 video_dev_info = 0;
-       struct viafb_ioctl_setting viafb_setting = {};
-       struct device_t active_dev = {};
 
        DEBUG_MSG(KERN_INFO "viafb_ioctl: 0x%X !!\n", cmd);
+       memset(&u, 0, sizeof(u));
 
        switch (cmd) {
        case VIAFB_GET_CHIP_INFO:
@@ -571,7 +573,7 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
                        return -EFAULT;
                break;
        case VIAFB_GET_INFO_SIZE:
-               return put_user(viainfo_size, argp);
+               return put_user((u32)sizeof(struct viafb_ioctl_info), argp);
        case VIAFB_GET_INFO:
                return viafb_ioctl_get_viafb_info(arg);
        case VIAFB_HOTPLUG:
@@ -584,60 +586,60 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
                viafb_hotplug = (gpu32) ? 1 : 0;
                break;
        case VIAFB_GET_RESOLUTION:
-               viamode.xres = (u32) viafb_hotplug_Xres;
-               viamode.yres = (u32) viafb_hotplug_Yres;
-               viamode.refresh = (u32) viafb_hotplug_refresh;
-               viamode.bpp = (u32) viafb_hotplug_bpp;
+               u.viamode.xres = (u32) viafb_hotplug_Xres;
+               u.viamode.yres = (u32) viafb_hotplug_Yres;
+               u.viamode.refresh = (u32) viafb_hotplug_refresh;
+               u.viamode.bpp = (u32) viafb_hotplug_bpp;
                if (viafb_SAMM_ON == 1) {
-                       viamode.xres_sec = viafb_second_xres;
-                       viamode.yres_sec = viafb_second_yres;
-                       viamode.virtual_xres_sec = viafb_second_virtual_xres;
-                       viamode.virtual_yres_sec = viafb_second_virtual_yres;
-                       viamode.refresh_sec = viafb_refresh1;
-                       viamode.bpp_sec = viafb_bpp1;
+                       u.viamode.xres_sec = viafb_second_xres;
+                       u.viamode.yres_sec = viafb_second_yres;
+                       u.viamode.virtual_xres_sec = viafb_second_virtual_xres;
+                       u.viamode.virtual_yres_sec = viafb_second_virtual_yres;
+                       u.viamode.refresh_sec = viafb_refresh1;
+                       u.viamode.bpp_sec = viafb_bpp1;
                } else {
-                       viamode.xres_sec = 0;
-                       viamode.yres_sec = 0;
-                       viamode.virtual_xres_sec = 0;
-                       viamode.virtual_yres_sec = 0;
-                       viamode.refresh_sec = 0;
-                       viamode.bpp_sec = 0;
+                       u.viamode.xres_sec = 0;
+                       u.viamode.yres_sec = 0;
+                       u.viamode.virtual_xres_sec = 0;
+                       u.viamode.virtual_yres_sec = 0;
+                       u.viamode.refresh_sec = 0;
+                       u.viamode.bpp_sec = 0;
                }
-               if (copy_to_user(argp, &viamode, sizeof(viamode)))
+               if (copy_to_user(argp, &u.viamode, sizeof(u.viamode)))
                        return -EFAULT;
                break;
        case VIAFB_GET_SAMM_INFO:
-               viasamm.samm_status = viafb_SAMM_ON;
+               u.viasamm.samm_status = viafb_SAMM_ON;
 
                if (viafb_SAMM_ON == 1) {
                        if (viafb_dual_fb) {
-                               viasamm.size_prim = viaparinfo->fbmem_free;
-                               viasamm.size_sec = viaparinfo1->fbmem_free;
+                               u.viasamm.size_prim = viaparinfo->fbmem_free;
+                               u.viasamm.size_sec = viaparinfo1->fbmem_free;
                        } else {
                                if (viafb_second_size) {
-                                       viasamm.size_prim =
+                                       u.viasamm.size_prim =
                                            viaparinfo->fbmem_free -
                                            viafb_second_size * 1024 * 1024;
-                                       viasamm.size_sec =
+                                       u.viasamm.size_sec =
                                            viafb_second_size * 1024 * 1024;
                                } else {
-                                       viasamm.size_prim =
+                                       u.viasamm.size_prim =
                                            viaparinfo->fbmem_free >> 1;
-                                       viasamm.size_sec =
+                                       u.viasamm.size_sec =
                                            (viaparinfo->fbmem_free >> 1);
                                }
                        }
-                       viasamm.mem_base = viaparinfo->fbmem;
-                       viasamm.offset_sec = viafb_second_offset;
+                       u.viasamm.mem_base = viaparinfo->fbmem;
+                       u.viasamm.offset_sec = viafb_second_offset;
                } else {
-                       viasamm.size_prim =
+                       u.viasamm.size_prim =
                            viaparinfo->memsize - viaparinfo->fbmem_used;
-                       viasamm.size_sec = 0;
-                       viasamm.mem_base = viaparinfo->fbmem;
-                       viasamm.offset_sec = 0;
+                       u.viasamm.size_sec = 0;
+                       u.viasamm.mem_base = viaparinfo->fbmem;
+                       u.viasamm.offset_sec = 0;
                }
 
-               if (copy_to_user(argp, &viasamm, sizeof(viasamm)))
+               if (copy_to_user(argp, &u.viasamm, sizeof(u.viasamm)))
                        return -EFAULT;
 
                break;
@@ -662,74 +664,75 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
                        viafb_lcd_disable();
                break;
        case VIAFB_SET_DEVICE:
-               if (copy_from_user(&active_dev, (void *)argp,
-                       sizeof(active_dev)))
+               if (copy_from_user(&u.active_dev, (void *)argp,
+                       sizeof(u.active_dev)))
                        return -EFAULT;
-               viafb_set_device(active_dev);
+               viafb_set_device(u.active_dev);
                viafb_set_par(info);
                break;
        case VIAFB_GET_DEVICE:
-               active_dev.crt = viafb_CRT_ON;
-               active_dev.dvi = viafb_DVI_ON;
-               active_dev.lcd = viafb_LCD_ON;
-               active_dev.samm = viafb_SAMM_ON;
-               active_dev.primary_dev = viafb_primary_dev;
+               u.active_dev.crt = viafb_CRT_ON;
+               u.active_dev.dvi = viafb_DVI_ON;
+               u.active_dev.lcd = viafb_LCD_ON;
+               u.active_dev.samm = viafb_SAMM_ON;
+               u.active_dev.primary_dev = viafb_primary_dev;
 
-               active_dev.lcd_dsp_cent = viafb_lcd_dsp_method;
-               active_dev.lcd_panel_id = viafb_lcd_panel_id;
-               active_dev.lcd_mode = viafb_lcd_mode;
+               u.active_dev.lcd_dsp_cent = viafb_lcd_dsp_method;
+               u.active_dev.lcd_panel_id = viafb_lcd_panel_id;
+               u.active_dev.lcd_mode = viafb_lcd_mode;
 
-               active_dev.xres = viafb_hotplug_Xres;
-               active_dev.yres = viafb_hotplug_Yres;
+               u.active_dev.xres = viafb_hotplug_Xres;
+               u.active_dev.yres = viafb_hotplug_Yres;
 
-               active_dev.xres1 = viafb_second_xres;
-               active_dev.yres1 = viafb_second_yres;
+               u.active_dev.xres1 = viafb_second_xres;
+               u.active_dev.yres1 = viafb_second_yres;
 
-               active_dev.bpp = viafb_bpp;
-               active_dev.bpp1 = viafb_bpp1;
-               active_dev.refresh = viafb_refresh;
-               active_dev.refresh1 = viafb_refresh1;
+               u.active_dev.bpp = viafb_bpp;
+               u.active_dev.bpp1 = viafb_bpp1;
+               u.active_dev.refresh = viafb_refresh;
+               u.active_dev.refresh1 = viafb_refresh1;
 
-               active_dev.epia_dvi = viafb_platform_epia_dvi;
-               active_dev.lcd_dual_edge = viafb_device_lcd_dualedge;
-               active_dev.bus_width = viafb_bus_width;
+               u.active_dev.epia_dvi = viafb_platform_epia_dvi;
+               u.active_dev.lcd_dual_edge = viafb_device_lcd_dualedge;
+               u.active_dev.bus_width = viafb_bus_width;
 
-               if (copy_to_user(argp, &active_dev, sizeof(active_dev)))
+               if (copy_to_user(argp, &u.active_dev, sizeof(u.active_dev)))
                        return -EFAULT;
                break;
 
        case VIAFB_GET_DRIVER_VERSION:
-               driver_version.iMajorNum = VERSION_MAJOR;
-               driver_version.iKernelNum = VERSION_KERNEL;
-               driver_version.iOSNum = VERSION_OS;
-               driver_version.iMinorNum = VERSION_MINOR;
+               u.driver_version.iMajorNum = VERSION_MAJOR;
+               u.driver_version.iKernelNum = VERSION_KERNEL;
+               u.driver_version.iOSNum = VERSION_OS;
+               u.driver_version.iMinorNum = VERSION_MINOR;
 
-               if (copy_to_user(argp, &driver_version,
-                       sizeof(driver_version)))
+               if (copy_to_user(argp, &u.driver_version,
+                       sizeof(u.driver_version)))
                        return -EFAULT;
 
                break;
 
        case VIAFB_SET_DEVICE_INFO:
-               if (copy_from_user(&viafb_setting,
-                       argp, sizeof(viafb_setting)))
+               if (copy_from_user(&u.viafb_setting,
+                       argp, sizeof(u.viafb_setting)))
                        return -EFAULT;
-               if (apply_device_setting(viafb_setting, info) < 0)
+               if (apply_device_setting(u.viafb_setting, info) < 0)
                        return -EINVAL;
 
                break;
 
        case VIAFB_SET_SECOND_MODE:
-               if (copy_from_user(&sec_var, argp, sizeof(sec_var)))
+               if (copy_from_user(&u.sec_var, argp, sizeof(u.sec_var)))
                        return -EFAULT;
-               apply_second_mode_setting(&sec_var);
+               apply_second_mode_setting(&u.sec_var);
                break;
 
        case VIAFB_GET_DEVICE_INFO:
 
-               retrieve_device_setting(&viafb_setting);
+               retrieve_device_setting(&u.viafb_setting);
 
-               if (copy_to_user(argp, &viafb_setting, sizeof(viafb_setting)))
+               if (copy_to_user(argp, &u.viafb_setting,
+                                sizeof(u.viafb_setting)))
                        return -EFAULT;
 
                break;
@@ -806,51 +809,51 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
                break;
 
        case VIAFB_GET_PANEL_MAX_SIZE:
-               if (copy_from_user
-                   (&panel_pos_size_para, argp, sizeof(panel_pos_size_para)))
+               if (copy_from_user(&u.panel_pos_size_para, argp,
+                                  sizeof(u.panel_pos_size_para)))
                        return -EFAULT;
-               panel_pos_size_para.x = panel_pos_size_para.y = 0;
-               if (copy_to_user(argp, &panel_pos_size_para,
-                    sizeof(panel_pos_size_para)))
+               u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0;
+               if (copy_to_user(argp, &u.panel_pos_size_para,
+                    sizeof(u.panel_pos_size_para)))
                        return -EFAULT;
                break;
        case VIAFB_GET_PANEL_MAX_POSITION:
-               if (copy_from_user
-                   (&panel_pos_size_para, argp, sizeof(panel_pos_size_para)))
+               if (copy_from_user(&u.panel_pos_size_para, argp,
+                                  sizeof(u.panel_pos_size_para)))
                        return -EFAULT;
-               panel_pos_size_para.x = panel_pos_size_para.y = 0;
-               if (copy_to_user(argp, &panel_pos_size_para,
-                    sizeof(panel_pos_size_para)))
+               u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0;
+               if (copy_to_user(argp, &u.panel_pos_size_para,
+                                sizeof(u.panel_pos_size_para)))
                        return -EFAULT;
                break;
 
        case VIAFB_GET_PANEL_POSITION:
-               if (copy_from_user
-                   (&panel_pos_size_para, argp, sizeof(panel_pos_size_para)))
+               if (copy_from_user(&u.panel_pos_size_para, argp,
+                                  sizeof(u.panel_pos_size_para)))
                        return -EFAULT;
-               panel_pos_size_para.x = panel_pos_size_para.y = 0;
-               if (copy_to_user(argp, &panel_pos_size_para,
-                    sizeof(panel_pos_size_para)))
+               u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0;
+               if (copy_to_user(argp, &u.panel_pos_size_para,
+                                sizeof(u.panel_pos_size_para)))
                        return -EFAULT;
                break;
        case VIAFB_GET_PANEL_SIZE:
-               if (copy_from_user
-                   (&panel_pos_size_para, argp, sizeof(panel_pos_size_para)))
+               if (copy_from_user(&u.panel_pos_size_para, argp,
+                                  sizeof(u.panel_pos_size_para)))
                        return -EFAULT;
-               panel_pos_size_para.x = panel_pos_size_para.y = 0;
-               if (copy_to_user(argp, &panel_pos_size_para,
-                    sizeof(panel_pos_size_para)))
+               u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0;
+               if (copy_to_user(argp, &u.panel_pos_size_para,
+                                sizeof(u.panel_pos_size_para)))
                        return -EFAULT;
                break;
 
        case VIAFB_SET_PANEL_POSITION:
-               if (copy_from_user
-                   (&panel_pos_size_para, argp, sizeof(panel_pos_size_para)))
+               if (copy_from_user(&u.panel_pos_size_para, argp,
+                                  sizeof(u.panel_pos_size_para)))
                        return -EFAULT;
                break;
        case VIAFB_SET_PANEL_SIZE:
-               if (copy_from_user
-                   (&panel_pos_size_para, argp, sizeof(panel_pos_size_para)))
+               if (copy_from_user(&u.panel_pos_size_para, argp,
+                                  sizeof(u.panel_pos_size_para)))
                        return -EFAULT;
                break;
 
@@ -1052,10 +1055,8 @@ static void viafb_imageblit(struct fb_info *info,
 
 static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 {
-       u8 data[CURSOR_SIZE / 8];
-       u32 data_bak[CURSOR_SIZE / 32];
        u32 temp, xx, yy, bg_col = 0, fg_col = 0;
-       int size, i, j = 0;
+       int i, j = 0;
        static int hw_cursor;
        struct viafb_par *p_viafb_par;
 
@@ -1178,22 +1179,29 @@ static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
        }
 
        if (cursor->set & FB_CUR_SETSHAPE) {
-               size =
+               struct {
+                       u8 data[CURSOR_SIZE / 8];
+                       u32 bak[CURSOR_SIZE / 32];
+               } *cr_data = kzalloc(sizeof(*cr_data), GFP_ATOMIC);
+               int size =
                    ((viacursor.image.width + 7) >> 3) *
                    viacursor.image.height;
 
+               if (cr_data == NULL)
+                       goto out;
+
                if (MAX_CURS == 32) {
                        for (i = 0; i < (CURSOR_SIZE / 32); i++) {
-                               data_bak[i] = 0x0;
-                               data_bak[i + 1] = 0xFFFFFFFF;
+                               cr_data->bak[i] = 0x0;
+                               cr_data->bak[i + 1] = 0xFFFFFFFF;
                                i += 1;
                        }
                } else if (MAX_CURS == 64) {
                        for (i = 0; i < (CURSOR_SIZE / 32); i++) {
-                               data_bak[i] = 0x0;
-                               data_bak[i + 1] = 0x0;
-                               data_bak[i + 2] = 0xFFFFFFFF;
-                               data_bak[i + 3] = 0xFFFFFFFF;
+                               cr_data->bak[i] = 0x0;
+                               cr_data->bak[i + 1] = 0x0;
+                               cr_data->bak[i + 2] = 0xFFFFFFFF;
+                               cr_data->bak[i + 3] = 0xFFFFFFFF;
                                i += 3;
                        }
                }
@@ -1201,12 +1209,12 @@ static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
                switch (viacursor.rop) {
                case ROP_XOR:
                        for (i = 0; i < size; i++)
-                               data[i] = viacursor.mask[i];
+                               cr_data->data[i] = viacursor.mask[i];
                        break;
                case ROP_COPY:
 
                        for (i = 0; i < size; i++)
-                               data[i] = viacursor.mask[i];
+                               cr_data->data[i] = viacursor.mask[i];
                        break;
                default:
                        break;
@@ -1214,23 +1222,25 @@ static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 
                if (MAX_CURS == 32) {
                        for (i = 0; i < size; i++) {
-                               data_bak[j] = (u32) data[i];
-                               data_bak[j + 1] = ~data_bak[j];
+                               cr_data->bak[j] = (u32) cr_data->data[i];
+                               cr_data->bak[j + 1] = ~cr_data->bak[j];
                                j += 2;
                        }
                } else if (MAX_CURS == 64) {
                        for (i = 0; i < size; i++) {
-                               data_bak[j] = (u32) data[i];
-                               data_bak[j + 1] = 0x0;
-                               data_bak[j + 2] = ~data_bak[j];
-                               data_bak[j + 3] = ~data_bak[j + 1];
+                               cr_data->bak[j] = (u32) cr_data->data[i];
+                               cr_data->bak[j + 1] = 0x0;
+                               cr_data->bak[j + 2] = ~cr_data->bak[j];
+                               cr_data->bak[j + 3] = ~cr_data->bak[j + 1];
                                j += 4;
                        }
                }
 
                memcpy(((struct viafb_par *)(info->par))->fbmem_virt +
                       ((struct viafb_par *)(info->par))->cursor_start,
-                      data_bak, CURSOR_SIZE);
+                      cr_data->bak, CURSOR_SIZE);
+out:
+               kfree(cr_data);
        }
 
        if (viacursor.enable)
index 4fd3fa5546b12282e5b25e521e5a7d5bb5bb829e..ec68c741b5645eddd206df2a02b492b3ee783650 100644 (file)
@@ -55,6 +55,13 @@ config SOFT_WATCHDOG
          To compile this driver as a module, choose M here: the
          module will be called softdog.
 
+config WM8350_WATCHDOG
+       tristate "WM8350 watchdog"
+       depends on MFD_WM8350
+       help
+         Support for the watchdog in the WM8350 AudioPlus PMIC.  When
+         the watchdog triggers the system will be reset.
+
 # ALPHA Architecture
 
 # ARM Architecture
@@ -551,6 +558,18 @@ config CPU5_WDT
          To compile this driver as a module, choose M here: the
          module will be called cpu5wdt.
 
+config SMSC_SCH311X_WDT
+       tristate "SMSC SCH311X Watchdog Timer"
+       depends on X86
+       ---help---
+         This is the driver for the hardware watchdog timer on the
+         SMSC SCH3112, SCH3114 and SCH3116 Super IO chipset
+         (LPC IO with 8042 KBC, Reset Generation, HWM and multiple
+         serial ports).
+
+         To compile this driver as a module, choose M here: the
+         module will be called sch311x_wdt.
+
 config SMSC37B787_WDT
        tristate "Winbond SMsC37B787 Watchdog Timer"
        depends on X86
index e352bbb7630b405a0ac3dc30a03c88b2eaa4c6b9..c19b866f5ed1d6a8e73cc627f494baadf0468af1 100644 (file)
@@ -83,6 +83,7 @@ obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o
 obj-$(CONFIG_SBC8360_WDT) += sbc8360.o
 obj-$(CONFIG_SBC7240_WDT) += sbc7240_wdt.o
 obj-$(CONFIG_CPU5_WDT) += cpu5wdt.o
+obj-$(CONFIG_SMSC_SCH311X_WDT) += sch311x_wdt.o
 obj-$(CONFIG_SMSC37B787_WDT) += smsc37b787_wdt.o
 obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o
 obj-$(CONFIG_W83697HF_WDT) += w83697hf_wdt.o
@@ -133,4 +134,5 @@ obj-$(CONFIG_WATCHDOG_CP1XXX)               += cpwd.o
 # XTENSA Architecture
 
 # Architecture Independant
+obj-$(CONFIG_WM8350_WATCHDOG) += wm8350_wdt.o
 obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
index 317ef2b16cffb27830813f273f5f0b6caead5d33..4bef3ddff4a5d8715ffeec1680376135a2c14a60 100644 (file)
@@ -91,32 +91,16 @@ static char expect_close;
  *
  */
 
-static int wd_times[] = {
-       30,     /* 0x0 */
-       28,     /* 0x1 */
-       26,     /* 0x2 */
-       24,     /* 0x3 */
-       22,     /* 0x4 */
-       20,     /* 0x5 */
-       18,     /* 0x6 */
-       16,     /* 0x7 */
-       14,     /* 0x8 */
-       12,     /* 0x9 */
-       10,     /* 0xA */
-       8,      /* 0xB */
-       6,      /* 0xC */
-       4,      /* 0xD */
-       2,      /* 0xE */
-       0,      /* 0xF */
-};
-
 #define WDT_STOP 0x441
 #define WDT_START 0x443
 
 /* Default timeout */
-#define WD_TIMO 0              /* 30 seconds +/- 20%, from table */
-
-static int wd_margin = WD_TIMO;
+#define WATCHDOG_TIMEOUT 30            /* 30 seconds +/- 20% */
+static int timeout = WATCHDOG_TIMEOUT; /* in seconds */
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout,
+       "Watchdog timeout in seconds. 0<= timeout <=30, default="
+               __MODULE_STRING(WATCHDOG_TIMEOUT) ".");
 
 static int nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, int, 0);
@@ -131,6 +115,8 @@ MODULE_PARM_DESC(nowayout,
 
 static void ibwdt_ping(void)
 {
+       int wd_margin = 15 - ((timeout + 1) / 2);
+
        spin_lock(&ibwdt_lock);
 
        /* Write a watchdog value */
@@ -148,15 +134,10 @@ static void ibwdt_disable(void)
 
 static int ibwdt_set_heartbeat(int t)
 {
-       int i;
-
-       if ((t < 0) || (t > 30))
+       if (t < 0 || t > 30)
                return -EINVAL;
 
-       for (i = 0x0F; i > -1; i--)
-               if (wd_times[i] >= t)
-                       break;
-       wd_margin = i;
+       timeout = t;
        return 0;
 }
 
@@ -240,7 +221,7 @@ static long ibwdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                /* Fall */
 
        case WDIOC_GETTIMEOUT:
-               return put_user(wd_times[wd_margin], p);
+               return put_user(timeout, p);
 
        default:
                return -ENOTTY;
@@ -317,6 +298,14 @@ static int __devinit ibwdt_probe(struct platform_device *dev)
                goto out_nostartreg;
        }
 
+       /* Check that the heartbeat value is within it's range ;
+        * if not reset to the default */
+       if (ibwdt_set_heartbeat(timeout)) {
+               ibwdt_set_heartbeat(WATCHDOG_TIMEOUT);
+               printk(KERN_INFO PFX
+                       "timeout value must be 0<=x<=30, using %d\n", timeout);
+       }
+
        res = misc_register(&ibwdt_miscdev);
        if (res) {
                printk(KERN_ERR PFX "failed to register misc device\n");
diff --git a/drivers/watchdog/sch311x_wdt.c b/drivers/watchdog/sch311x_wdt.c
new file mode 100644 (file)
index 0000000..569eb29
--- /dev/null
@@ -0,0 +1,578 @@
+/*
+ *     sch311x_wdt.c - Driver for the SCH311x Super-I/O chips
+ *                     integrated watchdog.
+ *
+ *     (c) Copyright 2008 Wim Van Sebroeck <wim@iguana.be>.
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     as published by the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ *
+ *     Neither Wim Van Sebroeck nor Iguana vzw. admit liability nor
+ *     provide warranty for any of this software. This material is
+ *     provided "AS-IS" and at no charge.
+ */
+
+/*
+ *     Includes, defines, variables, module parameters, ...
+ */
+
+/* Includes */
+#include <linux/module.h>              /* For module specific items */
+#include <linux/moduleparam.h>         /* For new moduleparam's */
+#include <linux/types.h>               /* For standard types (like size_t) */
+#include <linux/errno.h>               /* For the -ENODEV/... values */
+#include <linux/kernel.h>              /* For printk/... */
+#include <linux/miscdevice.h>          /* For MODULE_ALIAS_MISCDEV
+                                                       (WATCHDOG_MINOR) */
+#include <linux/watchdog.h>            /* For the watchdog specific items */
+#include <linux/init.h>                        /* For __init/__exit/... */
+#include <linux/fs.h>                  /* For file operations */
+#include <linux/platform_device.h>     /* For platform_driver framework */
+#include <linux/ioport.h>              /* For io-port access */
+#include <linux/spinlock.h>            /* For spin_lock/spin_unlock/... */
+#include <linux/uaccess.h>             /* For copy_to_user/put_user/... */
+#include <linux/io.h>                  /* For inb/outb/... */
+
+/* Module and version information */
+#define DRV_NAME       "sch311x_wdt"
+#define PFX            DRV_NAME ": "
+
+/* Runtime registers */
+#define RESGEN                 0x1d
+#define GP60                   0x47
+#define WDT_TIME_OUT           0x65
+#define WDT_VAL                        0x66
+#define WDT_CFG                        0x67
+#define WDT_CTRL               0x68
+
+/* internal variables */
+static unsigned long sch311x_wdt_is_open;
+static char sch311x_wdt_expect_close;
+static struct platform_device *sch311x_wdt_pdev;
+
+static int sch311x_ioports[] = { 0x2e, 0x4e, 0x162e, 0x164e, 0x00 };
+
+static struct {        /* The devices private data */
+       /* the Runtime Register base address */
+       unsigned short runtime_reg;
+       /* The card's boot status */
+       int boot_status;
+       /* the lock for io operations */
+       spinlock_t io_lock;
+} sch311x_wdt_data;
+
+/* Module load parameters */
+static unsigned short force_id;
+module_param(force_id, ushort, 0);
+MODULE_PARM_DESC(force_id, "Override the detected device ID");
+
+static unsigned short therm_trip;
+module_param(therm_trip, ushort, 0);
+MODULE_PARM_DESC(therm_trip, "Should a ThermTrip trigger the reset generator");
+
+#define WATCHDOG_TIMEOUT 60            /* 60 sec default timeout */
+static int timeout = WATCHDOG_TIMEOUT; /* in seconds */
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout,
+       "Watchdog timeout in seconds. 1<= timeout <=15300, default="
+               __MODULE_STRING(WATCHDOG_TIMEOUT) ".");
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout,
+       "Watchdog cannot be stopped once started (default="
+               __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+/*
+ *     Super-IO functions
+ */
+
+static inline void sch311x_sio_enter(int sio_config_port)
+{
+       outb(0x55, sio_config_port);
+}
+
+static inline void sch311x_sio_exit(int sio_config_port)
+{
+       outb(0xaa, sio_config_port);
+}
+
+static inline int sch311x_sio_inb(int sio_config_port, int reg)
+{
+       outb(reg, sio_config_port);
+       return inb(sio_config_port + 1);
+}
+
+static inline void sch311x_sio_outb(int sio_config_port, int reg, int val)
+{
+       outb(reg, sio_config_port);
+       outb(val, sio_config_port + 1);
+}
+
+/*
+ *     Watchdog Operations
+ */
+
+static void sch311x_wdt_set_timeout(int t)
+{
+       unsigned char timeout_unit = 0x80;
+
+       /* When new timeout is bigger then 255 seconds, we will use minutes */
+       if (t > 255) {
+               timeout_unit = 0;
+               t /= 60;
+       }
+
+       /* -- Watchdog Timeout --
+        * Bit 0-6 (Reserved)
+        * Bit 7   WDT Time-out Value Units Select
+        *         (0 = Minutes, 1 = Seconds)
+        */
+       outb(timeout_unit, sch311x_wdt_data.runtime_reg + WDT_TIME_OUT);
+
+       /* -- Watchdog Timer Time-out Value --
+        * Bit 0-7 Binary coded units (0=Disabled, 1..255)
+        */
+       outb(t, sch311x_wdt_data.runtime_reg + WDT_VAL);
+}
+
+static void sch311x_wdt_start(void)
+{
+       spin_lock(&sch311x_wdt_data.io_lock);
+
+       /* set watchdog's timeout */
+       sch311x_wdt_set_timeout(timeout);
+       /* enable the watchdog */
+       /* -- General Purpose I/O Bit 6.0 --
+        * Bit 0,   In/Out: 0 = Output, 1 = Input
+        * Bit 1,   Polarity: 0 = No Invert, 1 = Invert
+        * Bit 2-3, Function select: 00 = GPI/O, 01 = LED1, 11 = WDT,
+        *                           10 = Either Edge Triggered Intr.4
+        * Bit 4-6  (Reserved)
+        * Bit 7,   Output Type: 0 = Push Pull Bit, 1 = Open Drain
+        */
+       outb(0x0e, sch311x_wdt_data.runtime_reg + GP60);
+
+       spin_unlock(&sch311x_wdt_data.io_lock);
+
+}
+
+static void sch311x_wdt_stop(void)
+{
+       spin_lock(&sch311x_wdt_data.io_lock);
+
+       /* stop the watchdog */
+       outb(0x01, sch311x_wdt_data.runtime_reg + GP60);
+       /* disable timeout by setting it to 0 */
+       sch311x_wdt_set_timeout(0);
+
+       spin_unlock(&sch311x_wdt_data.io_lock);
+}
+
+static void sch311x_wdt_keepalive(void)
+{
+       spin_lock(&sch311x_wdt_data.io_lock);
+       sch311x_wdt_set_timeout(timeout);
+       spin_unlock(&sch311x_wdt_data.io_lock);
+}
+
+static int sch311x_wdt_set_heartbeat(int t)
+{
+       if (t < 1 || t > (255*60))
+               return -EINVAL;
+
+       /* When new timeout is bigger then 255 seconds,
+        * we will round up to minutes (with a max of 255) */
+       if (t > 255)
+               t = (((t - 1) / 60) + 1) * 60;
+
+       timeout = t;
+       return 0;
+}
+
+static void sch311x_wdt_get_status(int *status)
+{
+       unsigned char new_status;
+
+       *status = 0;
+
+       spin_lock(&sch311x_wdt_data.io_lock);
+
+       /* -- Watchdog timer control --
+        * Bit 0   Status Bit: 0 = Timer counting, 1 = Timeout occured
+        * Bit 1   Reserved
+        * Bit 2   Force Timeout: 1 = Forces WD timeout event (self-cleaning)
+        * Bit 3   P20 Force Timeout enabled:
+        *          0 = P20 activity does not generate the WD timeout event
+        *          1 = P20 Allows rising edge of P20, from the keyboard
+        *              controller, to force the WD timeout event.
+        * Bit 4-7 Reserved
+        */
+       new_status = inb(sch311x_wdt_data.runtime_reg + WDT_CTRL);
+       if (new_status & 0x01)
+               *status |= WDIOF_CARDRESET;
+
+       spin_unlock(&sch311x_wdt_data.io_lock);
+}
+
+/*
+ *     /dev/watchdog handling
+ */
+
+static ssize_t sch311x_wdt_write(struct file *file, const char __user *buf,
+                                               size_t count, loff_t *ppos)
+{
+       if (count) {
+               if (!nowayout) {
+                       size_t i;
+
+                       sch311x_wdt_expect_close = 0;
+
+                       for (i = 0; i != count; i++) {
+                               char c;
+                               if (get_user(c, buf + i))
+                                       return -EFAULT;
+                               if (c == 'V')
+                                       sch311x_wdt_expect_close = 42;
+                       }
+               }
+               sch311x_wdt_keepalive();
+       }
+       return count;
+}
+
+static long sch311x_wdt_ioctl(struct file *file, unsigned int cmd,
+                                                       unsigned long arg)
+{
+       int status;
+       int new_timeout;
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
+       static struct watchdog_info ident = {
+               .options                = WDIOF_KEEPALIVEPING |
+                                         WDIOF_SETTIMEOUT |
+                                         WDIOF_MAGICCLOSE,
+               .firmware_version       = 1,
+               .identity               = DRV_NAME,
+       };
+
+       switch (cmd) {
+       case WDIOC_GETSUPPORT:
+               if (copy_to_user(argp, &ident, sizeof(ident)))
+                       return -EFAULT;
+               break;
+
+       case WDIOC_GETSTATUS:
+       {
+               sch311x_wdt_get_status(&status);
+               return put_user(status, p);
+       }
+       case WDIOC_GETBOOTSTATUS:
+               return put_user(sch311x_wdt_data.boot_status, p);
+
+       case WDIOC_SETOPTIONS:
+       {
+               int options, retval = -EINVAL;
+
+               if (get_user(options, p))
+                       return -EFAULT;
+               if (options & WDIOS_DISABLECARD) {
+                       sch311x_wdt_stop();
+                       retval = 0;
+               }
+               if (options & WDIOS_ENABLECARD) {
+                       sch311x_wdt_start();
+                       retval = 0;
+               }
+               return retval;
+       }
+       case WDIOC_KEEPALIVE:
+               sch311x_wdt_keepalive();
+               break;
+
+       case WDIOC_SETTIMEOUT:
+               if (get_user(new_timeout, p))
+                       return -EFAULT;
+               if (sch311x_wdt_set_heartbeat(new_timeout))
+                       return -EINVAL;
+               sch311x_wdt_keepalive();
+               /* Fall */
+       case WDIOC_GETTIMEOUT:
+               return put_user(timeout, p);
+       default:
+               return -ENOTTY;
+       }
+       return 0;
+}
+
+static int sch311x_wdt_open(struct inode *inode, struct file *file)
+{
+       if (test_and_set_bit(0, &sch311x_wdt_is_open))
+               return -EBUSY;
+       /*
+        *      Activate
+        */
+       sch311x_wdt_start();
+       return nonseekable_open(inode, file);
+}
+
+static int sch311x_wdt_close(struct inode *inode, struct file *file)
+{
+       if (sch311x_wdt_expect_close == 42) {
+               sch311x_wdt_stop();
+       } else {
+               printk(KERN_CRIT PFX
+                               "Unexpected close, not stopping watchdog!\n");
+               sch311x_wdt_keepalive();
+       }
+       clear_bit(0, &sch311x_wdt_is_open);
+       sch311x_wdt_expect_close = 0;
+       return 0;
+}
+
+/*
+ *     Kernel Interfaces
+ */
+
+static const struct file_operations sch311x_wdt_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .write          = sch311x_wdt_write,
+       .unlocked_ioctl = sch311x_wdt_ioctl,
+       .open           = sch311x_wdt_open,
+       .release        = sch311x_wdt_close,
+};
+
+static struct miscdevice sch311x_wdt_miscdev = {
+       .minor  = WATCHDOG_MINOR,
+       .name   = "watchdog",
+       .fops   = &sch311x_wdt_fops,
+};
+
+/*
+ *     Init & exit routines
+ */
+
+static int __devinit sch311x_wdt_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       unsigned char val;
+       int err;
+
+       spin_lock_init(&sch311x_wdt_data.io_lock);
+
+       if (!request_region(sch311x_wdt_data.runtime_reg + RESGEN, 1,
+                                                               DRV_NAME)) {
+               dev_err(dev, "Failed to request region 0x%04x-0x%04x.\n",
+                       sch311x_wdt_data.runtime_reg + RESGEN,
+                       sch311x_wdt_data.runtime_reg + RESGEN);
+               err = -EBUSY;
+               goto exit;
+       }
+
+       if (!request_region(sch311x_wdt_data.runtime_reg + GP60, 1, DRV_NAME)) {
+               dev_err(dev, "Failed to request region 0x%04x-0x%04x.\n",
+                       sch311x_wdt_data.runtime_reg + GP60,
+                       sch311x_wdt_data.runtime_reg + GP60);
+               err = -EBUSY;
+               goto exit_release_region;
+       }
+
+       if (!request_region(sch311x_wdt_data.runtime_reg + WDT_TIME_OUT, 4,
+                                                               DRV_NAME)) {
+               dev_err(dev, "Failed to request region 0x%04x-0x%04x.\n",
+                       sch311x_wdt_data.runtime_reg + WDT_TIME_OUT,
+                       sch311x_wdt_data.runtime_reg + WDT_CTRL);
+               err = -EBUSY;
+               goto exit_release_region2;
+       }
+
+       /* Make sure that the watchdog is not running */
+       sch311x_wdt_stop();
+
+       /* Disable keyboard and mouse interaction and interrupt */
+       /* -- Watchdog timer configuration --
+        * Bit 0   Reserved
+        * Bit 1   Keyboard enable: 0* = No Reset, 1 = Reset WDT upon KBD Intr.
+        * Bit 2   Mouse enable: 0* = No Reset, 1 = Reset WDT upon Mouse Intr
+        * Bit 3   Reserved
+        * Bit 4-7 WDT Interrupt Mapping: (0000* = Disabled,
+        *            0001=IRQ1, 0010=(Invalid), 0011=IRQ3 to 1111=IRQ15)
+        */
+       outb(0, sch311x_wdt_data.runtime_reg + WDT_CFG);
+
+       /* Check that the heartbeat value is within it's range ;
+        * if not reset to the default */
+       if (sch311x_wdt_set_heartbeat(timeout)) {
+               sch311x_wdt_set_heartbeat(WATCHDOG_TIMEOUT);
+               dev_info(dev, "timeout value must be 1<=x<=15300, using %d\n",
+                       timeout);
+       }
+
+       /* Get status at boot */
+       sch311x_wdt_get_status(&sch311x_wdt_data.boot_status);
+
+       /* enable watchdog */
+       /* -- Reset Generator --
+        * Bit 0   Enable Watchdog Timer Generation: 0* = Enabled, 1 = Disabled
+        * Bit 1   Thermtrip Source Select: O* = No Source, 1 = Source
+        * Bit 2   WDT2_CTL: WDT input bit
+        * Bit 3-7 Reserved
+        */
+       outb(0, sch311x_wdt_data.runtime_reg + RESGEN);
+       val = therm_trip ? 0x06 : 0x04;
+       outb(val, sch311x_wdt_data.runtime_reg + RESGEN);
+
+       err = misc_register(&sch311x_wdt_miscdev);
+       if (err != 0) {
+               dev_err(dev, "cannot register miscdev on minor=%d (err=%d)\n",
+                                                       WATCHDOG_MINOR, err);
+               goto exit_release_region3;
+       }
+
+       sch311x_wdt_miscdev.parent = dev;
+
+       dev_info(dev,
+               "SMSC SCH311x WDT initialized. timeout=%d sec (nowayout=%d)\n",
+               timeout, nowayout);
+
+       return 0;
+
+exit_release_region3:
+       release_region(sch311x_wdt_data.runtime_reg + WDT_TIME_OUT, 4);
+exit_release_region2:
+       release_region(sch311x_wdt_data.runtime_reg + GP60, 1);
+exit_release_region:
+       release_region(sch311x_wdt_data.runtime_reg + RESGEN, 1);
+       sch311x_wdt_data.runtime_reg = 0;
+exit:
+       return err;
+}
+
+static int __devexit sch311x_wdt_remove(struct platform_device *pdev)
+{
+       /* Stop the timer before we leave */
+       if (!nowayout)
+               sch311x_wdt_stop();
+
+       /* Deregister */
+       misc_deregister(&sch311x_wdt_miscdev);
+       release_region(sch311x_wdt_data.runtime_reg + WDT_TIME_OUT, 4);
+       release_region(sch311x_wdt_data.runtime_reg + GP60, 1);
+       release_region(sch311x_wdt_data.runtime_reg + RESGEN, 1);
+       sch311x_wdt_data.runtime_reg = 0;
+       return 0;
+}
+
+static void sch311x_wdt_shutdown(struct platform_device *dev)
+{
+       /* Turn the WDT off if we have a soft shutdown */
+       sch311x_wdt_stop();
+}
+
+#define sch311x_wdt_suspend NULL
+#define sch311x_wdt_resume  NULL
+
+static struct platform_driver sch311x_wdt_driver = {
+       .probe          = sch311x_wdt_probe,
+       .remove         = __devexit_p(sch311x_wdt_remove),
+       .shutdown       = sch311x_wdt_shutdown,
+       .suspend        = sch311x_wdt_suspend,
+       .resume         = sch311x_wdt_resume,
+       .driver         = {
+               .owner = THIS_MODULE,
+               .name = DRV_NAME,
+       },
+};
+
+static int __init sch311x_detect(int sio_config_port, unsigned short *addr)
+{
+       int err = 0, reg;
+       unsigned short base_addr;
+       unsigned char dev_id;
+
+       sch311x_sio_enter(sio_config_port);
+
+       /* Check device ID. We currently know about:
+        * SCH3112 (0x7c), SCH3114 (0x7d), and SCH3116 (0x7f). */
+       reg = force_id ? force_id : sch311x_sio_inb(sio_config_port, 0x20);
+       if (!(reg == 0x7c || reg == 0x7d || reg == 0x7f)) {
+               err = -ENODEV;
+               goto exit;
+       }
+       dev_id = reg == 0x7c ? 2 : reg == 0x7d ? 4 : 6;
+
+       /* Select logical device A (runtime registers) */
+       sch311x_sio_outb(sio_config_port, 0x07, 0x0a);
+
+       /* Check if Logical Device Register is currently active */
+       if (sch311x_sio_inb(sio_config_port, 0x30) && 0x01 == 0)
+               printk(KERN_INFO PFX "Seems that LDN 0x0a is not active...\n");
+
+       /* Get the base address of the runtime registers */
+       base_addr = (sch311x_sio_inb(sio_config_port, 0x60) << 8) |
+                          sch311x_sio_inb(sio_config_port, 0x61);
+       if (!base_addr) {
+               printk(KERN_ERR PFX "Base address not set.\n");
+               err = -ENODEV;
+               goto exit;
+       }
+       *addr = base_addr;
+
+       printk(KERN_INFO PFX "Found an SMSC SCH311%d chip at 0x%04x\n",
+               dev_id, base_addr);
+
+exit:
+       sch311x_sio_exit(sio_config_port);
+       return err;
+}
+
+static int __init sch311x_wdt_init(void)
+{
+       int err, i, found = 0;
+       unsigned short addr = 0;
+
+       for (i = 0; !found && sch311x_ioports[i]; i++)
+               if (sch311x_detect(sch311x_ioports[i], &addr) == 0)
+                       found++;
+
+       if (!found)
+               return -ENODEV;
+
+       sch311x_wdt_data.runtime_reg = addr;
+
+       err = platform_driver_register(&sch311x_wdt_driver);
+       if (err)
+               return err;
+
+       sch311x_wdt_pdev = platform_device_register_simple(DRV_NAME, addr,
+                                                               NULL, 0);
+
+       if (IS_ERR(sch311x_wdt_pdev)) {
+               err = PTR_ERR(sch311x_wdt_pdev);
+               goto unreg_platform_driver;
+       }
+
+       return 0;
+
+unreg_platform_driver:
+       platform_driver_unregister(&sch311x_wdt_driver);
+       return err;
+}
+
+static void __exit sch311x_wdt_exit(void)
+{
+       platform_device_unregister(sch311x_wdt_pdev);
+       platform_driver_unregister(&sch311x_wdt_driver);
+}
+
+module_init(sch311x_wdt_init);
+module_exit(sch311x_wdt_exit);
+
+MODULE_AUTHOR("Wim Van Sebroeck <wim@iguana.be>");
+MODULE_DESCRIPTION("SMSC SCH311x WatchDog Timer Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+
diff --git a/drivers/watchdog/wm8350_wdt.c b/drivers/watchdog/wm8350_wdt.c
new file mode 100644 (file)
index 0000000..2bc0d4d
--- /dev/null
@@ -0,0 +1,329 @@
+/*
+ * Watchdog driver for the wm8350
+ *
+ * Copyright (C) 2007, 2008 Wolfson Microelectronics <linux@wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/platform_device.h>
+#include <linux/watchdog.h>
+#include <linux/uaccess.h>
+#include <linux/mfd/wm8350/core.h>
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout,
+                "Watchdog cannot be stopped once started (default="
+                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+static unsigned long wm8350_wdt_users;
+static struct miscdevice wm8350_wdt_miscdev;
+static int wm8350_wdt_expect_close;
+static DEFINE_MUTEX(wdt_mutex);
+
+static struct {
+       int time;  /* Seconds */
+       u16 val;   /* To be set in WM8350_SYSTEM_CONTROL_2 */
+} wm8350_wdt_cfgs[] = {
+       { 1, 0x02 },
+       { 2, 0x04 },
+       { 4, 0x05 },
+};
+
+static struct wm8350 *get_wm8350(void)
+{
+       return dev_get_drvdata(wm8350_wdt_miscdev.parent);
+}
+
+static int wm8350_wdt_set_timeout(struct wm8350 *wm8350, u16 value)
+{
+       int ret;
+       u16 reg;
+
+       mutex_lock(&wdt_mutex);
+       wm8350_reg_unlock(wm8350);
+
+       reg = wm8350_reg_read(wm8350, WM8350_SYSTEM_CONTROL_2);
+       reg &= ~WM8350_WDOG_TO_MASK;
+       reg |= value;
+       ret = wm8350_reg_write(wm8350, WM8350_SYSTEM_CONTROL_2, reg);
+
+       wm8350_reg_lock(wm8350);
+       mutex_unlock(&wdt_mutex);
+
+       return ret;
+}
+
+static int wm8350_wdt_start(struct wm8350 *wm8350)
+{
+       int ret;
+       u16 reg;
+
+       mutex_lock(&wdt_mutex);
+       wm8350_reg_unlock(wm8350);
+
+       reg = wm8350_reg_read(wm8350, WM8350_SYSTEM_CONTROL_2);
+       reg &= ~WM8350_WDOG_MODE_MASK;
+       reg |= 0x20;
+       ret = wm8350_reg_write(wm8350, WM8350_SYSTEM_CONTROL_2, reg);
+
+       wm8350_reg_lock(wm8350);
+       mutex_unlock(&wdt_mutex);
+
+       return ret;
+}
+
+static int wm8350_wdt_stop(struct wm8350 *wm8350)
+{
+       int ret;
+       u16 reg;
+
+       mutex_lock(&wdt_mutex);
+       wm8350_reg_unlock(wm8350);
+
+       reg = wm8350_reg_read(wm8350, WM8350_SYSTEM_CONTROL_2);
+       reg &= ~WM8350_WDOG_MODE_MASK;
+       ret = wm8350_reg_write(wm8350, WM8350_SYSTEM_CONTROL_2, reg);
+
+       wm8350_reg_lock(wm8350);
+       mutex_unlock(&wdt_mutex);
+
+       return ret;
+}
+
+static int wm8350_wdt_kick(struct wm8350 *wm8350)
+{
+       int ret;
+       u16 reg;
+
+       mutex_lock(&wdt_mutex);
+
+       reg = wm8350_reg_read(wm8350, WM8350_SYSTEM_CONTROL_2);
+       ret = wm8350_reg_write(wm8350, WM8350_SYSTEM_CONTROL_2, reg);
+
+       mutex_unlock(&wdt_mutex);
+
+       return ret;
+}
+
+static int wm8350_wdt_open(struct inode *inode, struct file *file)
+{
+       struct wm8350 *wm8350 = get_wm8350();
+       int ret;
+
+       if (!wm8350)
+               return -ENODEV;
+
+       if (test_and_set_bit(0, &wm8350_wdt_users))
+               return -EBUSY;
+
+       ret = wm8350_wdt_start(wm8350);
+       if (ret != 0)
+               return ret;
+
+       return nonseekable_open(inode, file);
+}
+
+static int wm8350_wdt_release(struct inode *inode, struct file *file)
+{
+       struct wm8350 *wm8350 = get_wm8350();
+
+       if (wm8350_wdt_expect_close)
+               wm8350_wdt_stop(wm8350);
+       else {
+               dev_warn(wm8350->dev, "Watchdog device closed uncleanly\n");
+               wm8350_wdt_kick(wm8350);
+       }
+
+       clear_bit(0, &wm8350_wdt_users);
+
+       return 0;
+}
+
+static ssize_t wm8350_wdt_write(struct file *file,
+                               const char __user *data, size_t count,
+                               loff_t *ppos)
+{
+       struct wm8350 *wm8350 = get_wm8350();
+       size_t i;
+
+       if (count) {
+               wm8350_wdt_kick(wm8350);
+
+               if (!nowayout) {
+                       /* In case it was set long ago */
+                       wm8350_wdt_expect_close = 0;
+
+                       /* scan to see whether or not we got the magic
+                          character */
+                       for (i = 0; i != count; i++) {
+                               char c;
+                               if (get_user(c, data + i))
+                                       return -EFAULT;
+                               if (c == 'V')
+                                       wm8350_wdt_expect_close = 42;
+                       }
+               }
+       }
+       return count;
+}
+
+static struct watchdog_info ident = {
+       .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+       .identity = "WM8350 Watchdog",
+};
+
+static long wm8350_wdt_ioctl(struct file *file, unsigned int cmd,
+                            unsigned long arg)
+{
+       struct wm8350 *wm8350 = get_wm8350();
+       int ret = -ENOTTY, time, i;
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
+       u16 reg;
+
+       switch (cmd) {
+       case WDIOC_GETSUPPORT:
+               ret = copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
+               break;
+
+       case WDIOC_GETSTATUS:
+       case WDIOC_GETBOOTSTATUS:
+               ret = put_user(0, p);
+               break;
+
+       case WDIOC_SETOPTIONS:
+       {
+               int options;
+
+               if (get_user(options, p))
+                       return -EFAULT;
+
+               ret = -EINVAL;
+
+               /* Setting both simultaneously means at least one must fail */
+               if (options == WDIOS_DISABLECARD)
+                       ret = wm8350_wdt_start(wm8350);
+
+               if (options == WDIOS_ENABLECARD)
+                       ret = wm8350_wdt_stop(wm8350);
+               break;
+       }
+
+       case WDIOC_KEEPALIVE:
+               ret = wm8350_wdt_kick(wm8350);
+               break;
+
+       case WDIOC_SETTIMEOUT:
+               ret = get_user(time, p);
+               if (ret)
+                       break;
+
+               if (time == 0) {
+                       if (nowayout)
+                               ret = -EINVAL;
+                       else
+                               wm8350_wdt_stop(wm8350);
+                       break;
+               }
+
+               for (i = 0; i < ARRAY_SIZE(wm8350_wdt_cfgs); i++)
+                       if (wm8350_wdt_cfgs[i].time == time)
+                               break;
+               if (i == ARRAY_SIZE(wm8350_wdt_cfgs))
+                       ret = -EINVAL;
+               else
+                       ret = wm8350_wdt_set_timeout(wm8350,
+                                                    wm8350_wdt_cfgs[i].val);
+               break;
+
+       case WDIOC_GETTIMEOUT:
+               reg = wm8350_reg_read(wm8350, WM8350_SYSTEM_CONTROL_2);
+               reg &= WM8350_WDOG_TO_MASK;
+               for (i = 0; i < ARRAY_SIZE(wm8350_wdt_cfgs); i++)
+                       if (wm8350_wdt_cfgs[i].val == reg)
+                               break;
+               if (i == ARRAY_SIZE(wm8350_wdt_cfgs)) {
+                       dev_warn(wm8350->dev,
+                                "Unknown watchdog configuration: %x\n", reg);
+                       ret = -EINVAL;
+               } else
+                       ret = put_user(wm8350_wdt_cfgs[i].time, p);
+
+       }
+
+       return ret;
+}
+
+static const struct file_operations wm8350_wdt_fops = {
+       .owner = THIS_MODULE,
+       .llseek = no_llseek,
+       .write = wm8350_wdt_write,
+       .unlocked_ioctl = wm8350_wdt_ioctl,
+       .open = wm8350_wdt_open,
+       .release = wm8350_wdt_release,
+};
+
+static struct miscdevice wm8350_wdt_miscdev = {
+       .minor = WATCHDOG_MINOR,
+       .name = "watchdog",
+       .fops = &wm8350_wdt_fops,
+};
+
+static int wm8350_wdt_probe(struct platform_device *pdev)
+{
+       struct wm8350 *wm8350 = platform_get_drvdata(pdev);
+
+       if (!wm8350) {
+               dev_err(wm8350->dev, "No driver data supplied\n");
+               return -ENODEV;
+       }
+
+       /* Default to 4s timeout */
+       wm8350_wdt_set_timeout(wm8350, 0x05);
+
+       wm8350_wdt_miscdev.parent = &pdev->dev;
+
+       return misc_register(&wm8350_wdt_miscdev);
+}
+
+static int __exit wm8350_wdt_remove(struct platform_device *pdev)
+{
+       misc_deregister(&wm8350_wdt_miscdev);
+
+       return 0;
+}
+
+static struct platform_driver wm8350_wdt_driver = {
+       .probe = wm8350_wdt_probe,
+       .remove = wm8350_wdt_remove,
+       .driver = {
+               .name = "wm8350-wdt",
+       },
+};
+
+static int __init wm8350_wdt_init(void)
+{
+       return platform_driver_register(&wm8350_wdt_driver);
+}
+module_init(wm8350_wdt_init);
+
+static void __exit wm8350_wdt_exit(void)
+{
+       platform_driver_unregister(&wm8350_wdt_driver);
+}
+module_exit(wm8350_wdt_exit);
+
+MODULE_AUTHOR("Mark Brown");
+MODULE_DESCRIPTION("WM8350 Watchdog");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:wm8350-wdt");
index 6968388818be797e34f4c49c5ce879fd5a262698..d872b7942a30384a64896eaaac17dea128effaa8 100644 (file)
@@ -20,6 +20,15 @@ fw-external-y := $(subst ",,$(CONFIG_EXTRA_FIRMWARE))
 # accurate. In the latter case it doesn't matter -- it'll use $(fw-shipped-all).
 # But be aware that the config file might not be included at all.
 
+ifdef CONFIG_ACENIC_OMIT_TIGON_I
+acenic-objs := acenic/tg2.bin
+fw-shipped- += acenic/tg1.bin
+else
+acenic-objs := acenic/tg1.bin acenic/tg2.bin
+endif
+fw-shipped-$(CONFIG_ACENIC) += $(acenic-objs)
+fw-shipped-$(CONFIG_ADAPTEC_STARFIRE) += adaptec/starfire_rx.bin \
+                                        adaptec/starfire_tx.bin
 fw-shipped-$(CONFIG_ATARI_DSP56K) += dsp56k/bootstrap.bin
 fw-shipped-$(CONFIG_ATM_AMBASSADOR) += atmsar11.fw
 fw-shipped-$(CONFIG_CASSINI) += sun/cassini.bin
@@ -38,6 +47,8 @@ fw-shipped-$(CONFIG_SND_SB16_CSP) += sb16/mulaw_main.csp sb16/alaw_main.csp \
                                     sb16/ima_adpcm_capture.csp
 fw-shipped-$(CONFIG_SND_YMFPCI) += yamaha/ds1_ctrl.fw yamaha/ds1_dsp.fw \
                                   yamaha/ds1e_ctrl.fw
+fw-shipped-$(CONFIG_TIGON3) += tigon/tg3.bin tigon/tg3_tso.bin \
+                              tigon/tg3_tso5.bin
 fw-shipped-$(CONFIG_USB_DABUSB) += dabusb/firmware.fw dabusb/bitstream.bin
 fw-shipped-$(CONFIG_USB_EMI26) += emi26/loader.fw emi26/firmware.fw \
                                  emi26/bitstream.fw
index 8f06639ba3e76923deae1255d65402016452ef31..1bb2cf4b17354f022c21a19160558c3ca2a57ca7 100644 (file)
@@ -360,3 +360,52 @@ License: GPLv2 or OpenIB.org BSD license, no source visible
 
 --------------------------------------------------------------------------
 
+Driver: acenic -- Alteon AceNIC Gigabit Ethernet card
+
+File: acenic/tg1.bin
+File: acenic/tg2.bin
+
+Licence: Unknown
+
+Found in hex form in kernel source, but source allegedly available at
+http://alteon.shareable.org/
+
+--------------------------------------------------------------------------
+
+Driver: tigon3 -- Broadcom Tigon3 based gigabit Ethernet cards
+
+File: tigon/tg3.bin
+File: tigon/tg3_tso.bin
+File: tigon/tg3_tso5.bin
+
+Licence:
+ * Firmware is:
+ *     Derived from proprietary unpublished source code,
+ *     Copyright (C) 2000-2003 Broadcom Corporation.
+ *
+ *     Permission is hereby granted for the distribution of this firmware
+ *     data in hexadecimal or equivalent format, provided this copyright
+ *     notice is accompanying it.
+
+Found in hex form in kernel source.
+
+--------------------------------------------------------------------------
+
+Driver: ADAPTEC_STARFIRE - Adaptec Starfire/DuraLAN support
+
+File: adaptec/starfire_rx.bin
+File: adaptec/starfire_tx.bin
+
+Licence: Allegedly GPLv2, but no source visible.
+
+Found in hex form in kernel source, with the following notice:
+
+ BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE IT IS LICENSED "AS IS" AND
+ THERE IS NO WARRANTY FOR THE PROGRAM, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTIBILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ (TO THE EXTENT PERMITTED BY APPLICABLE LAW). USE OF THE PROGRAM IS AT YOUR
+ OWN RISK. IN NO EVENT WILL ADAPTEC OR ITS LICENSORS BE LIABLE TO YOU FOR
+ DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
+ ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM.
+
+--------------------------------------------------------------------------
diff --git a/firmware/acenic/tg1.bin.ihex b/firmware/acenic/tg1.bin.ihex
new file mode 100644 (file)
index 0000000..bef2659
--- /dev/null
@@ -0,0 +1,4573 @@
+:100000000C040B0000004000000040001000000342
+:10001000000000000000000D0000000D3C1D00016C
+:100020008FBD5C5403A0F0213C100000261040005E
+:100030000C00100C000000000000000D27BDFFD8D0
+:100040003C1CC0003C1B0013377BD8000000D021B3
+:100050003C17001336F7541802E02021340583E8DA
+:10006000AFBF00240C002488AFB000200C0023E8B0
+:10007000000000003C040001248451A42405000178
+:1000800002E03021000038213C10000126107E5093
+:10009000AFB000100C002403AFBB00143C02000FF3
+:1000A0003442FFFF020210240362102B10400009AB
+:1000B000240500033C040001248451B002003021D7
+:1000C000036038213C020010AFA200100C00240392
+:1000D000AFA00014000020213405C0003C01000145
+:1000E00000370821A02083B03C010001003708211F
+:1000F000A02083B23C01000100370821A02083B377
+:100100003C01000100370821AC2083B4A2E004D8F0
+:10011000000418C02484000100771021AC40727CD8
+:1001200000771021AC40728002E31021A445727C5C
+:100130002C8200201440FFF7000418C0000020218A
+:100140003405C000000418C0248400010077102189
+:10015000AC40737C00771021AC40738002E3102127
+:10016000A445737C2C8200805440FFF7000418C023
+:10017000AF800054AF80011C8F82004434420040A5
+:10018000AF8200448F82004434420020AF8200449A
+:100190008F420218304200021040000900000000A7
+:1001A0008F4202203C030002346300040043102508
+:1001B000AEE204C48F42021C0800107434420004F2
+:1001C0008F4202203C0300023463000600431025E6
+:1001D000AEE204C48F42021C34420006AEE204CCFC
+:1001E0008F420218304200101040000A0000000048
+:1001F0008F42021C34420004AEE204C88F42022047
+:100200003C03000A34630004004310250800108AF0
+:10021000AEE204C08F4202203C03000A34630006B1
+:1002200000431025AEE204C08F42021C3442000697
+:10023000AEE204C88F4202183042020010400003B0
+:100240002402000108001091A2E27248A2E0724864
+:1002500024020001AF8200A0AF8200B08F8300545F
+:100260008F82005408001099246300648F82005428
+:10027000006210232C4200651440FFFC00000000C7
+:10028000AF8000448F4202088F43020CAEE20010A0
+:10029000AEE300148EE400108EE5001426E2003078
+:1002A000AEE2002824020490AEE20018AF84009071
+:1002B000AF8500948EE20028AF8200B496E2001A67
+:1002C000AF82009C8F8200B08EE304CC00431025E7
+:1002D000AF8200B08F8200B0304200041440FFFDB6
+:1002E000000000008EE204508EE30454AEE304FCF0
+:1002F0008EE204FC2442E0002C4220011440000D58
+:1003000026E400308EE204508EE304543C040001E5
+:10031000248451BC3C050001AFA00010AFA0001424
+:100320008EE704FC34A5F0000C00240300603021AB
+:1003300026E400300C0024882405040027440080B3
+:100340000C0024882405008026E4777C0C00248897
+:10035000240504008F42025C26E40094AEE20060B3
+:100360008F4202602745020024060008AEE20068C2
+:10037000240200060C00249AAEE200643C023B9A80
+:100380003442CA000000202124030002AEE30074BE
+:10039000AEE30070AEE2006C240203E8AEE20104BA
+:1003A00024020001AEE30100AEE2010C3C030001B7
+:1003B0000064182190635C2002E410212484000171
+:1003C000A043009C2C82000F1440FFF800000000A6
+:1003D0008F82004002E418212484000100021702E9
+:1003E00024420030A062009C02E41021A040009C46
+:1003F00096E2046A30420003144000090000000045
+:1004000096E2047A30420003504001313C03080078
+:1004100096E2046A304200031040002A3C020700C2
+:1004200096E2047A30420003104000263C020700A6
+:1004300096E3047A96E2046A146200223C02070002
+:100440008EE204C024030001A2E34E2034420E00D9
+:10045000AEE204C08F420218304201001040000595
+:10046000000000003C0200012442E1680800111D68
+:10047000000211003C0200012442D35C0002110082
+:10048000000211823C030800004310253C010001DA
+:10049000AC2212383C0200012442F6800002110016
+:1004A000000211823C030800004310253C010001BA
+:1004B000AC2212788EE2000034424000080012386C
+:1004C000AEE2000034423000AFA200188EE206080F
+:1004D0008F43022824420001304900FF512300E2EB
+:1004E000AFA000108EE20608000210C000571021D5
+:1004F0008FA300188FA4001CAC43060CAC4406105C
+:100500008F8701202762380024E800200102102B89
+:1005100050400001276830008F820128110200043A
+:10052000000000008F820124150200070000102146
+:100530008EE201A40000302124420001AEE201A4B9
+:10054000080011A08EE201A48EE40608000420C079
+:10055000008018218EE404308EE5043400A32821A5
+:1005600000A3302B0082202100862021ACE4000073
+:10057000ACE500048EE3060824020008A4E2000EA5
+:100580002402000DACE20018ACE9001C000318C006
+:100590002463060C02E31021ACE200088EE204C4DE
+:1005A000ACE20010AF88012092E24E2014400037E8
+:1005B000240600018EE24E30000210C02442503862
+:1005C00002E220218C830000240200071462001F35
+:1005D000000000008EE34E308EE24E341062001BAD
+:1005E000240300408C82000424420001AC820004F9
+:1005F0008EE24E348EE54E30244200011043000757
+:10060000000000008EE24E342442000110A20005DA
+:10061000000000000800118A0000000014A000057E
+:10062000000000008F82012824420020AF820128B0
+:100630008F8201288C8200042C420011504000134C
+:10064000AC800000080011A0000000008EE24E30D7
+:100650002403004024420001504300030000102105
+:100660008EE24E3024420001AEE24E308EE24E3039
+:10067000000210C02442503802E220212402000768
+:10068000AC82000024020001AC82000454C0000CC3
+:10069000AEE906083C040001248451C8AFA0001054
+:1006A000AFA000148EE606088F4702283C0500091B
+:1006B0000C00240334A5F000080012230000000001
+:1006C0008F830120276238002466002000C2102B8F
+:1006D00050400001276630008F82012810C20004BC
+:1006E000000000008F82012414C2000700000000F7
+:1006F0008EE201A40000302124420001AEE201A4F8
+:10070000080012078EE201A48EE20608AC62001C0B
+:100710008EE404A08EE504A42462001CAC620008F0
+:1007200024020008A462000E24020011AC6200182A
+:10073000AC640000AC6500048EE204C4AC6200103E
+:10074000AF86012092E24E201440003724060001BB
+:100750008EE24E30000210C02442503802E22021C6
+:100760008C830000240200121462001F00000000AD
+:100770008EE34E308EE24E341062001B24030040A4
+:100780008C82000424420001AC8200048EE24E34CC
+:100790008EE54E30244200011043000700000000A7
+:1007A0008EE24E342442000110A200050000000039
+:1007B000080011F10000000014A000050000000076
+:1007C0008F82012824420020AF8201288F820128D5
+:1007D0008C8200042C42001150400013AC800000B9
+:1007E00008001207000000008EE24E302403004093
+:1007F0002442000150430003000010218EE24E30DD
+:1008000024420001AEE24E308EE24E30000210C0B3
+:100810002442503802E2202124020012AC8200005F
+:1008200024020001AC82000414C0001B0000000080
+:100830003C040001248451D0AFA00010AFA00014EC
+:100840008EE606088F4702283C0500090C002403A9
+:1008500034A5F0018EE201B024420001AEE201B005
+:10086000080012238EE201B03C040001248451DC14
+:10087000AFA000148EE606088F4702283C05000949
+:100880000C00240334A5F0058EE201AC24420001E3
+:10089000AEE201AC8EE201AC8EE201603C040001EC
+:1008A000248451E83405F00124420001AEE20160E5
+:1008B0008EE201600000302100003821AFA000105E
+:1008C0000C002403AFA00014080012380000000040
+:1008D0003C0200012442F5A800021100000211822E
+:1008E000004310253C010001AC22127896E2045A24
+:1008F00030420003104000253C050FFF8EE204C883
+:1009000034A5FFFF34420A00AEE204C88EE304C8F7
+:100910003C040001248451F424020001A2E204EC0E
+:10092000A2E204ED3C020002006218253C02000134
+:100930002442A3900045102400021082AEE304C8B4
+:100940003C030800004310253C010001AC221220AA
+:100950003C0200012442ADD4004510240002108264
+:10096000004310253C010001AC22128096E6045A97
+:100970000000382124050011AFA000100C00240352
+:10098000AFA0001408001268000000003C02000143
+:100990002442A9D400021100000211823C03080085
+:1009A000004310253C010001AC22128096E2046A4B
+:1009B00030420010144000090000000096E2047A62
+:1009C00030420010104001120000000096E2046A5C
+:1009D00030420010104000053C02070096E2047A05
+:1009E00030420010144001023C0207003442300043
+:1009F000AFA200188EE206088F43022824420001AD
+:100A0000304900FF512300E2AFA000108EE206083B
+:100A1000000210C0005710218FA300188FA4001CE3
+:100A2000AC43060CAC4406108F87012027623800C7
+:100A300024E800200102102B5040000127683000FC
+:100A40008F82012811020004000000008F8201241F
+:100A500015020007000010218EE201A400003021E1
+:100A600024420001AEE201A4080012EA8EE201A4D1
+:100A70008EE40608000420C0008018218EE40430B3
+:100A80008EE5043400A3282100A3302B008220210E
+:100A900000862021ACE40000ACE500048EE30608EB
+:100AA00024020008A4E2000E2402000DACE20018AB
+:100AB000ACE9001C000318C02463060C02E31021FB
+:100AC000ACE200088EE204C4ACE20010AF88012062
+:100AD00092E24E2014400037240600018EE24E3090
+:100AE000000210C02442503802E220218C83000012
+:100AF000240200071462001F000000008EE34E3045
+:100B00008EE24E341062001B240300408C820004ED
+:100B100024420001AC8200048EE24E348EE54E3059
+:100B20002442000110430007000000008EE24E3412
+:100B30002442000110A2000500000000080012D4A9
+:100B40000000000014A00005000000008F820128B2
+:100B500024420020AF8201288F8201288C82000469
+:100B60002C42001150400013AC800000080012EA33
+:100B7000000000008EE24E302403004024420001B9
+:100B800050430003000010218EE24E302442000149
+:100B9000AEE24E308EE24E30000210C02442503899
+:100BA00002E2202124020007AC820000240200019E
+:100BB000AC82000454C0000CAEE906083C040001FD
+:100BC000248451C8AFA00010AFA000148EE6060820
+:100BD0008F4702283C0500090C00240334A5F000CF
+:100BE0000800136D000000008F8301202762380089
+:100BF0002466002000C2102B504000012766300000
+:100C00008F82012810C20004000000008F8201249E
+:100C100014C20007000000008EE201A40000302191
+:100C200024420001AEE201A4080013518EE201A4A7
+:100C30008EE20608AC62001C8EE404A08EE504A4DB
+:100C40002462001CAC62000824020008A462000EAA
+:100C500024020011AC620018AC640000AC65000412
+:100C60008EE204C4AC620010AF86012092E24E20F6
+:100C700014400037240600018EE24E30000210C0FE
+:100C80002442503802E220218C830000240200120A
+:100C90001462001F000000008EE34E308EE24E34DE
+:100CA0001062001B240300408C82000424420001D7
+:100CB000AC8200048EE24E348EE54E3024420001B8
+:100CC00010430007000000008EE24E342442000171
+:100CD00010A20005000000000800133B0000000007
+:100CE00014A00005000000008F820128244200208B
+:100CF000AF8201288F8201288C8200042C420011CF
+:100D000050400013AC8000000800135100000000A8
+:100D10008EE24E3024030040244200015043000381
+:100D2000000010218EE24E3024420001AEE24E302F
+:100D30008EE24E30000210C02442503802E22021E0
+:100D400024020012AC82000024020001AC820004E4
+:100D500014C0001B000000003C040001248451D09A
+:100D6000AFA00010AFA000148EE606088F4702283F
+:100D70003C0500090C00240334A5F0018EE201B00B
+:100D800024420001AEE201B00800136D8EE201B012
+:100D90003C040001248451DCAFA000148EE6060858
+:100DA0008F4702283C0500090C00240334A5F005F8
+:100DB0008EE201AC24420001AEE201AC8EE201AC55
+:100DC0008EE201603C040001248451E83405F00205
+:100DD00024420001AEE201608EE201600000302199
+:100DE00000003821AFA000100C002403AFA00014B5
+:100DF00096E6047A96E7046A3C04000124845200D3
+:100E000024050012AFA000100C002403AFA00014B2
+:100E10000C004500000000000C002318000000003A
+:100E20003C06000134C63800AEE00608AF40022898
+:100E3000AF40022C96E304588EE400003C0512D823
+:100E400034A5C35827623800AEE2725827623800D2
+:100E5000AEE2726027623800AEE27264036610216F
+:100E6000AEE272702402FFFFAEE004D4AEE004E014
+:100E7000AEE004E4AEE004F0A2E004F4AEE00E0C58
+:100E8000AEE00E18AEE00E10AEE00E14AEE00E1C9A
+:100E9000AEE0724CAEE05244AEE05240AEE0523CA6
+:100EA000AEE07250AEE07254AEE0725CAEE07268DA
+:100EB000AEE004D02463FFFF00852025AEE304F8F4
+:100EC000AEE40000AF800060AF8200643C0201002D
+:100ED000AFA200188EE206088F43022824420001C8
+:100EE000304900FF512300E2AFA000108EE2060857
+:100EF000000210C0005710218FA300188FA4001CFF
+:100F0000AC43060CAC4406108F87012027623800E2
+:100F100024E800200102102B504000012768300017
+:100F20008F82012811020004000000008F8201243A
+:100F300015020007000010218EE201A400003021FC
+:100F400024420001AEE201A4080014228EE201A4B2
+:100F50008EE40608000420C0008018218EE40430CE
+:100F60008EE5043400A3282100A3302B0082202129
+:100F700000862021ACE40000ACE500048EE3060806
+:100F800024020008A4E2000E2402000DACE20018C6
+:100F9000ACE9001C000318C02463060C02E3102116
+:100FA000ACE200088EE204C4ACE20010AF8801207D
+:100FB00092E24E2014400037240600018EE24E30AB
+:100FC000000210C02442503802E220218C8300002D
+:100FD000240200071462001F000000008EE34E3060
+:100FE0008EE24E341062001B240300408C82000409
+:100FF00024420001AC8200048EE24E348EE54E3075
+:101000002442000110430007000000008EE24E342D
+:101010002442000110A20005000000000800140C8A
+:101020000000000014A00005000000008F820128CD
+:1010300024420020AF8201288F8201288C82000484
+:101040002C42001150400013AC8000000800142214
+:10105000000000008EE24E302403004024420001D4
+:1010600050430003000010218EE24E302442000164
+:10107000AEE24E308EE24E30000210C024425038B4
+:1010800002E2202124020007AC82000024020001B9
+:10109000AC82000454C0000CAEE906083C04000118
+:1010A000248451C8AFA00010AFA000148EE606083B
+:1010B0008F4702283C0500090C00240334A5F000EA
+:1010C000080014A5000000008F830120276238006B
+:1010D0002466002000C2102B50400001276630001B
+:1010E0008F82012810C20004000000008F820124BA
+:1010F00014C20007000000008EE201A400003021AD
+:1011000024420001AEE201A4080014898EE201A489
+:101110008EE20608AC62001C8EE404A08EE504A4F6
+:101120002462001CAC62000824020008A462000EC5
+:1011300024020011AC620018AC640000AC6500042D
+:101140008EE204C4AC620010AF86012092E24E2011
+:1011500014400037240600018EE24E30000210C019
+:101160002442503802E220218C8300002402001225
+:101170001462001F000000008EE34E308EE24E34F9
+:101180001062001B240300408C82000424420001F2
+:10119000AC8200048EE24E348EE54E3024420001D3
+:1011A00010430007000000008EE24E34244200018C
+:1011B00010A20005000000000800147300000000E9
+:1011C00014A00005000000008F82012824420020A6
+:1011D000AF8201288F8201288C8200042C420011EA
+:1011E00050400013AC80000008001489000000008B
+:1011F0008EE24E302403004024420001504300039D
+:10120000000010218EE24E3024420001AEE24E304A
+:101210008EE24E30000210C02442503802E22021FB
+:1012200024020012AC82000024020001AC820004FF
+:1012300014C0001B000000003C040001248451D0B5
+:10124000AFA00010AFA000148EE606088F4702285A
+:101250003C0500090C00240334A5F0018EE201B026
+:1012600024420001AEE201B0080014A58EE201B0F4
+:101270003C040001248451DCAFA000148EE6060873
+:101280008F4702283C0500090C00240334A5F00513
+:101290008EE201AC24420001AEE201AC8EE201AC70
+:1012A0008EE2015424420001AEE201540C0014DC31
+:1012B0008EE201548F8200A0304200041440FFFDF2
+:1012C000000000008F8200403042000114400008FE
+:1012D000000000008F43010424020001106200049A
+:1012E000000000008F420264104000060000000071
+:1012F0008EE2017C24420001AEE2017C080014C5AC
+:101300008EE2017C8F82004434420004AF820044AC
+:101310008EE2017824420001AEE201788EE201788B
+:101320008F8200D88F8300D400431023AEE2726C0A
+:101330008EE2726C1C4000033C030001004310214C
+:10134000AEE2726C0C004064000000000C004440EF
+:10135000AF8002288FBF00248FB0002003E0000878
+:1013600027BD002803E000080000000003E000089B
+:101370000000000000000000000000002402002C1B
+:10138000AF820050AEE072748F420238AEE27278E3
+:101390008F82005424420067AF820058AEE07B8801
+:1013A000AEE07B8CAEE07B843C010001003708217D
+:1013B000AC2083BC3C0100010037082103E0000899
+:1013C000A02083B927BDFFD8AFBF0024AFB0002055
+:1013D0008F8200543C0300018C635CD82442006778
+:1013E0001060000DAF8200583C0200010057102130
+:1013F000904283B8104000053C0302003C0100010C
+:101400000037082108001503A02083B88EE20000F1
+:1014100000431025AEE200008F4202183042010066
+:10142000104000C6000000008F8200B0304200046F
+:10143000104000C2000000003C03000100771821AA
+:101440008C6383D08F820104146200B4000000001A
+:101450003C030001007718218C6383D48F8200B491
+:10146000146200AE000000008F8200B03C030080D8
+:10147000004310241040000D000000008F82011C6A
+:1014800034420002AF82011C8F8200B02403FFFBB4
+:1014900000431024AF8200B08F82011C2403FFFDA3
+:1014A00000431024080015CCAF82011C3C0300014E
+:1014B000007718218C6383D08F820104146200822C
+:1014C000000000003C030001007718218C6383D4E6
+:1014D0008F8200B41462007C000000003C07000111
+:1014E00000F738218CE783D08F8200B03C040001E4
+:1014F00024845270AFA00014AFA200108F8600B0F9
+:101500003C0500050C00240334A509008F82011C52
+:1015100034420002AF82011C8F8301048F8200B02D
+:1015200034420001AF8200B0AF8301048F830120F9
+:10153000276238002466002000C2102B50400001B2
+:10154000276630008F82012810C2000400000000CE
+:101550008F82012414C20006000000008EE201A464
+:1015600024420001AEE201A4080015A08EE201A40D
+:101570008F4402088F45020C26E20030AC6200085E
+:1015800024020400A462000E2402000FAC620018C2
+:10159000AC60001CAC640000AC6500048EE204C4C6
+:1015A000AC620010AF86012092E24E20144000375A
+:1015B000000000008EE24E30000210C0244250387D
+:1015C00002E220218C830000240200071462001F25
+:1015D000000000008EE34E308EE24E341062001B9D
+:1015E000240300408C82000424420001AC820004E9
+:1015F0008EE24E348EE54E30244200011043000747
+:10160000000000008EE24E342442000110A20005CA
+:10161000000000000800158A0000000014A000056A
+:10162000000000008F82012824420020AF820128A0
+:101630008F8201288C8200042C420011504000133C
+:10164000AC800000080015A0000000008EE24E30C3
+:1016500024030040244200015043000300001021F5
+:101660008EE24E3024420001AEE24E308EE24E3029
+:10167000000210C02442503802E220212402000758
+:10168000AC82000024020001AC8200048F82011CA5
+:101690002403FFFD00431024AF82011C8EE201E40D
+:1016A0003C07000100F738218CE783D02442000179
+:1016B000AEE201E48EE201E43C0400012484527CA9
+:1016C000080015BDAFA000108F8201043C0100018D
+:1016D00000370821AC2283D08F8200B43C07000180
+:1016E00000F738218CE783D03C0400012484528425
+:1016F0003C01000100370821AC2283D4AFA00010C8
+:10170000AFA000148F8600B03C0500050C00240338
+:1017100034A50900080015CC000000008F820104E8
+:101720003C01000100370821AC2283D08F8200B435
+:101730003C01000100370821AC2283D48EE2727490
+:1017400092E304F42442006714600006AEE272746F
+:101750008EE272748F4302340043102B1440007BDE
+:10176000000000008EE304E48EE204F8146200043A
+:101770000000000092E204F450400074A2E004F47F
+:101780008F830120276238002466002000C2102BBE
+:1017900050400001276630008F82012810C20004EB
+:1017A000000000008F82012414C200070000000026
+:1017B0008EE201A40000802124420001AEE201A4D7
+:1017C000080016378EE201A48EE204E4AC62001C2D
+:1017D0008EE404B08EE504B42462001CAC62000800
+:1017E00024020008A462000E24020011AC6200185A
+:1017F000AC640000AC6500048EE204C4AC6200106E
+:10180000AF86012092E24E201440003724100001E0
+:101810008EE24E30000210C02442503802E22021F5
+:101820008C830000240200121462001F00000000DC
+:101830008EE34E308EE24E341062001B24030040D3
+:101840008C82000424420001AC8200048EE24E34FB
+:101850008EE54E30244200011043000700000000D6
+:101860008EE24E342442000110A200050000000068
+:10187000080016210000000014A000050000000070
+:101880008F82012824420020AF8201288F82012804
+:101890008C8200042C42001150400013AC800000E8
+:1018A00008001637000000008EE24E30240300408E
+:1018B0002442000150430003000010218EE24E300C
+:1018C00024420001AEE24E308EE24E30000210C0E3
+:1018D0002442503802E2202124020012AC8200008F
+:1018E00024020001AC8200045600000B2410000109
+:1018F0008EE204E43C0400012484528CAFA0001466
+:10190000AFA200108EE606088F4702283C050009AA
+:101910000C00240334A5F006160000032402000185
+:1019200008001650A2E204F48EE201702442000185
+:10193000AEE201708EE201708EE204E4A2E004F4F3
+:10194000AEE004F0AEE07274AEE204F88EE20E1C7B
+:101950001040006D000000008F83012027623800D6
+:101960002466002000C2102B504000012766300082
+:101970008F82012810C20004000000008F82012421
+:1019800014C20007000000008EE201A400008021C4
+:1019900024420001AEE201A4080016AD8EE201A4CB
+:1019A0008EE2724CAC62001C8EE404A88EE504AC9E
+:1019B0002462001CAC62000824020008A462000E2D
+:1019C00024020011AC620018AC640000AC65000495
+:1019D0008EE204C4AC620010AF86012092E24E2079
+:1019E00014400037241000018EE24E30000210C077
+:1019F0002442503802E220218C830000240200128D
+:101A00001462001F000000008EE34E308EE24E3460
+:101A10001062001B240300408C8200042442000159
+:101A2000AC8200048EE24E348EE54E30244200013A
+:101A300010430007000000008EE24E3424420001F3
+:101A400010A200050000000008001697000000002A
+:101A500014A00005000000008F820128244200200D
+:101A6000AF8201288F8201288C8200042C42001151
+:101A700050400013AC800000080016AD00000000CC
+:101A80008EE24E3024030040244200015043000304
+:101A9000000010218EE24E3024420001AEE24E30B2
+:101AA0008EE24E30000210C02442503802E2202163
+:101AB00024020012AC82000024020001AC82000467
+:101AC0005600000B241000018EE2724C3C04000111
+:101AD00024845298AFA00014AFA200108EE6724C7E
+:101AE0008F4702803C0500090C00240334A5F00850
+:101AF00056000001AEE00E1C8EE20174244200018B
+:101B0000AEE201748EE201748EE24E2410400019A0
+:101B100000000000AEE04E248F8200403042000101
+:101B200014400008000000008F430104240200015B
+:101B300010620004000000008F42026410400006A2
+:101B4000000000008EE2017C24420001AEE2017C34
+:101B5000080016DA8EE2017C8F82004434420004D1
+:101B6000AF8200448EE2017824420001AEE20178A7
+:101B70008EE201788EE272782442FF99AEE27278AA
+:101B80008EE272781C4002AD000000008F420238E5
+:101B9000104002AA000000003C0200010057102182
+:101BA000904283E0144002A5000000008F420080B4
+:101BB000AEE2004C8F4200C0AEE200488F4200848B
+:101BC000AEE200388F420084AEE202448F420088C9
+:101BD000AEE202488F42008CAEE2024C8F4200908F
+:101BE000AEE202508F420094AEE202548F4200985F
+:101BF000AEE202588F42009CAEE2025C8F4200A02F
+:101C0000AEE202608F4200A4AEE202648F4200A8FE
+:101C1000AEE202688F4200ACAEE2026C8F4200B0CE
+:101C2000AEE202708F4200B4AEE202748F4200B89E
+:101C3000AEE202788F4200BC24040001AEE2027CD6
+:101C4000AEE0003C00041080005710218EE3003C01
+:101C50008C42024424840001006218212C82000F6F
+:101C6000AEE3003C1440FFF8000410808F4200CC2B
+:101C7000AEE200508F4200D0AEE200548F830120CC
+:101C8000276238002466002000C2102B504000015B
+:101C9000276630008F82012810C200040000000077
+:101CA0008F82012414C20007000000008EE201A40C
+:101CB0000000802124420001AEE201A40800177553
+:101CC0008EE201A48F4402088F45020C26E2003008
+:101CD000AC62000824020400A462000E2402000F7B
+:101CE000AC620018AC60001CAC640000AC65000481
+:101CF0008EE204C4AC620010AF86012092E24E2056
+:101D000014400037241000018EE24E30000210C053
+:101D10002442503802E220218C8300002402000774
+:101D20001462001F000000008EE34E308EE24E343D
+:101D30001062001B240300408C8200042442000136
+:101D4000AC8200048EE24E348EE54E302442000117
+:101D500010430007000000008EE24E3424420001D0
+:101D600010A20005000000000800175F000000003E
+:101D700014A00005000000008F82012824420020EA
+:101D8000AF8201288F8201288C8200042C4200112E
+:101D900050400013AC8000000800177500000000E0
+:101DA0008EE24E30240300402442000150430003E1
+:101DB000000010218EE24E3024420001AEE24E308F
+:101DC0008EE24E30000210C02442503802E2202140
+:101DD00024020007AC82000024020001AC8200044F
+:101DE000120002123C020400AFA200183C020001E3
+:101DF00000571021904283B01040010B00000000FA
+:101E00008EE206088F43022824420001304A00FF78
+:101E1000514300FDAFA000108EE20608000210C082
+:101E2000005710218FA300188FA4001CAC43060C90
+:101E3000AC4406108F8300548F8200542469003212
+:101E4000012210232C4200331040006A0000582168
+:101E500024180008240F000D240D0007240C004056
+:101E6000240E00018F8701202762380024E800201B
+:101E70000102102B50400001276830008F8201289A
+:101E800011020004000000008F82012415020007E7
+:101E9000000010218EE201A40000802124420001F4
+:101EA000AEE201A4080017F38EE201A48EE4060856
+:101EB000000420C0008018218EE404308EE5043434
+:101EC00000A3282100A3302B00822021008620219E
+:101ED000ACE40000ACE500048EE20608A4F8000EB5
+:101EE000ACEF0018ACEA001C000210C02442060C43
+:101EF00002E21021ACE200088EE204C4ACE2001061
+:101F0000AF88012092E24E201440003324100001DB
+:101F10008EE24E30000210C02442503802E22021EE
+:101F20008C820000144D001F000000008EE34E3034
+:101F30008EE24E341062001B000000008C82000410
+:101F400024420001AC8200048EE24E348EE34E3017
+:101F500024420001104C0007000000008EE24E34C5
+:101F6000244200011062000500000000080017E094
+:101F70000000000014600005000000008F820128AE
+:101F800024420020AF8201288F8201288C82000425
+:101F90002C42001150400010AC800000080017F3E4
+:101FA000000000008EE24E3024420001504C00033D
+:101FB000000010218EE24E3024420001AEE24E308D
+:101FC0008EE24E30000210C02442503802E220213E
+:101FD000AC8D0000AC8E000456000006240B0001FE
+:101FE0008F820054012210232C4200331440FF9DA5
+:101FF00000000000316300FF24020001146200773A
+:102000003C050009AEEA06088F8300548F82005415
+:1020100024690032012210232C4200331040006159
+:1020200000005821240D0008240C0011240800127F
+:1020300024070040240A00018F8301202762380012
+:102040002466002000C2102B50400001276630009B
+:102050008F82012810C20004000000008F8201243A
+:1020600014C20007000000008EE201A400008021DD
+:1020700024420001AEE201A40800185F8EE201A430
+:102080008EE20608AC62001C8EE404A08EE504A477
+:102090002462001CAC620008A46D000EAC6C001839
+:1020A000AC640000AC6500048EE204C4AC620010B5
+:1020B000AF86012092E24E2014400033241000012C
+:1020C0008EE24E30000210C02442503802E220213D
+:1020D0008C8200001448001F000000008EE34E3088
+:1020E0008EE24E341062001B000000008C8200045F
+:1020F00024420001AC8200048EE24E348EE34E3066
+:102100002442000110470007000000008EE24E3418
+:102110002442000110620005000000000800184C75
+:102120000000000014600005000000008F820128FC
+:1021300024420020AF8201288F8201288C82000473
+:102140002C42001150400010AC8000000800185FC5
+:10215000000000008EE24E30244200015047000390
+:10216000000010218EE24E3024420001AEE24E30DB
+:102170008EE24E30000210C02442503802E220218C
+:10218000AC880000AC8A000456000006240B000155
+:102190008F820054012210232C4200331440FFA6EA
+:1021A00000000000316300FF2402000114620003FC
+:1021B0003C0500090800197C241000013C040001C2
+:1021C000248452A4AFA00010AFA000148F86012079
+:1021D0008F8701240800187B34A5F0113C0400010E
+:1021E000248452B0AFA00010AFA000148F8601204D
+:1021F0008F87012434A5F0100C00240300008021F7
+:102200000800197C000000003C040001248452BC3A
+:10221000AFA000148EE606088F4702283C0500098F
+:102220000800197534A5F00F8EE206088F430228C6
+:1022300024420001304900FF512300E2AFA000100A
+:102240008EE20608000210C0005710218FA300186C
+:102250008FA4001CAC43060CAC4406108F870120F1
+:102260002762380024E800200102102B50400001B2
+:10227000276830008F82012811020004000000004E
+:102280008F82012415020007000010218EE201A4B4
+:102290000000802124420001AEE201A4080018F7EA
+:1022A0008EE201A48EE40608000420C000801821FC
+:1022B0008EE404308EE5043400A3282100A3302BE3
+:1022C0000082202100862021ACE40000ACE500045F
+:1022D0008EE3060824020008A4E2000E2402000D8A
+:1022E000ACE20018ACE9001C000318C02463060C23
+:1022F00002E31021ACE200088EE204C4ACE200105C
+:10230000AF88012092E24E201440003724100001D3
+:102310008EE24E30000210C02442503802E22021EA
+:102320008C830000240200071462001F00000000DC
+:102330008EE34E308EE24E341062001B24030040C8
+:102340008C82000424420001AC8200048EE24E34F0
+:102350008EE54E30244200011043000700000000CB
+:102360008EE24E342442000110A20005000000005D
+:10237000080018E10000000014A0000500000000A3
+:102380008F82012824420020AF8201288F820128F9
+:102390008C8200042C42001150400013AC800000DD
+:1023A000080018F7000000008EE24E3024030040C1
+:1023B0002442000150430003000010218EE24E3001
+:1023C00024420001AEE24E308EE24E30000210C0D8
+:1023D0002442503802E2202124020007AC8200008F
+:1023E00024020001AC8200045600000CAEE906088D
+:1023F0003C040001248452C8AFA00010AFA0001418
+:102400008EE606088F4702283C0500090C002403CD
+:1024100034A5F0000800197C000000008F83012023
+:10242000276238002466002000C2102B50400001B3
+:10243000276630008F82012810C2000400000000CF
+:102440008F82012414C20007000000008EE201A464
+:102450000000802124420001AEE201A40800195EC0
+:102460008EE201A48EE20608AC62001C8EE404A099
+:102470008EE504A42462001CAC620008240200085B
+:10248000A462000E24020011AC620018AC640000CB
+:10249000AC6500048EE204C4AC620010AF8601207B
+:1024A00092E24E2014400037241000018EE24E309C
+:1024B000000210C02442503802E220218C83000028
+:1024C000240200121462001F000000008EE34E3050
+:1024D0008EE24E341062001B240300408C82000404
+:1024E00024420001AC8200048EE24E348EE54E3070
+:1024F0002442000110430007000000008EE24E3429
+:102500002442000110A20005000000000800194844
+:102510000000000014A00005000000008F820128C8
+:1025200024420020AF8201288F8201288C8200047F
+:102530002C42001150400013AC8000000800195ECE
+:10254000000000008EE24E302403004024420001CF
+:1025500050430003000010218EE24E30244200015F
+:10256000AEE24E308EE24E30000210C024425038AF
+:1025700002E2202124020012AC82000024020001A9
+:10258000AC8200045600001D241000013C04000130
+:10259000248452D0AFA00010AFA000148EE606082D
+:1025A0008F4702283C0500090C00240334A5F001E4
+:1025B0008EE201B024420001AEE201B00800197CB5
+:1025C0008EE201B03C040001248452DCAFA0001470
+:1025D0008EE606088F4702283C05000934A5F00561
+:1025E0000C002403000000008EE201AC00008021FA
+:1025F00024420001AEE201AC8EE201AC1200000CFC
+:10260000240200013C01000100370821A02083B012
+:102610008F4202388EE3015824630001AEE3015873
+:102620008EE301580800198CAEE272782402000192
+:102630003C01000100370821A02283B03C020001C8
+:102640008C425CD810400187000000008EE27B8441
+:1026500024430001284200C9144001A4AEE37B8456
+:102660008EE204D43042000214400119AEE07B84B3
+:102670008EE204D43C0306003463100034420002AE
+:10268000AEE204D4AFA300188EE206088F430228FE
+:1026900024420001304A00FF514300FDAFA000106A
+:1026A0008EE20608000210C0005710218FA3001808
+:1026B0008FA4001CAC43060CAC4406108F8300545E
+:1026C0008F82005424690032012210232C420033EF
+:1026D0001040006A0000582124180008240F000D43
+:1026E000240D0007240C0040240E00018F870120D8
+:1026F0002762380024E800200102102B504000011E
+:10270000276830008F8201281102000400000000B9
+:102710008F82012415020007000010218EE201A41F
+:102720000000802124420001AEE201A408001A1535
+:102730008EE201A48EE40608000420C00080182167
+:102740008EE404308EE5043400A3282100A3302B4E
+:102750000082202100862021ACE40000ACE50004CA
+:102760008EE20608A4F8000EACEF0018ACEA001CDC
+:10277000000210C02442060C02E21021ACE2000864
+:102780008EE204C4ACE20010AF88012092E24E2039
+:1027900014400033241000018EE24E30000210C0BD
+:1027A0002442503802E220218C820000144D001F88
+:1027B000000000008EE34E308EE24E341062001BAB
+:1027C000000000008C82000424420001AC8200045E
+:1027D0008EE24E348EE34E3024420001104C00074E
+:1027E000000000008EE24E34244200011062000519
+:1027F0000000000008001A0200000000146000053C
+:10280000000000008F82012824420020AF820128AE
+:102810008F8201288C8200042C420011504000104D
+:10282000AC80000008001A15000000008EE24E3057
+:1028300024420001504C0003000010218EE24E3073
+:1028400024420001AEE24E308EE24E30000210C053
+:102850002442503802E22021AC8D0000AC8E0004EE
+:1028600056000006240B00018F8200540122102321
+:102870002C4200331440FF9D00000000316300FF34
+:102880002402000154620078AFA00010AEEA0608EE
+:102890008F8300548F820054246900320122102358
+:1028A0002C4200331040006100005821240D000824
+:1028B000240C00112408001224070040240A0001FF
+:1028C0008F830120276238002466002000C2102B6D
+:1028D00050400001276630008F82012810C200049A
+:1028E000000000008F82012414C2000700000000D5
+:1028F0008EE201A40000802124420001AEE201A486
+:1029000008001A818EE201A48EE20608AC62001C67
+:102910008EE404A08EE504A42462001CAC620008CE
+:10292000A46D000EAC6C0018AC640000AC65000433
+:102930008EE204C4AC620010AF86012092E24E2009
+:1029400014400033241000018EE24E30000210C00B
+:102950002442503802E220218C8200001448001FDB
+:10296000000000008EE34E308EE24E341062001BF9
+:10297000000000008C82000424420001AC820004AC
+:102980008EE24E348EE34E302442000110470007A1
+:10299000000000008EE24E34244200011062000567
+:1029A0000000000008001A6E00000000146000051E
+:1029B000000000008F82012824420020AF820128FD
+:1029C0008F8201288C8200042C420011504000109C
+:1029D000AC80000008001A81000000008EE24E303A
+:1029E0002442000150470003000010218EE24E30C7
+:1029F00024420001AEE24E308EE24E30000210C0A2
+:102A00002442503802E22021AC880000AC8A000445
+:102A100056000006240B00018F820054012210236F
+:102A20002C4200331440FFA600000000316300FF79
+:102A30002402000110620022000000003C0400019A
+:102A4000248452A4AFA00010AFA000148F860120F0
+:102A50008F8701243C0500090C00240334A5F011E4
+:102A600008001AAD000000003C040001248452B0AC
+:102A7000AFA000148F8601208F8701243C05000938
+:102A80000C00240334A5F01008001AAD000000006B
+:102A90003C040001248452BCAFA000148EE606085A
+:102AA0008F4702283C0500090C00240334A5F00FD1
+:102AB0008EE201AC24420001AEE201AC8EE201AC38
+:102AC0008EE2015C24420001AEE2015C8EE2015C18
+:102AD0008EE204D430420001104000550000000096
+:102AE0008F42021830420080104000290000000090
+:102AF0008F82004434420040AF8200448EE27B7CEF
+:102B0000004028218EE200C08EE300C424060000AD
+:102B10002407FFFF00002021004610241444000D6C
+:102B2000006718241465000B000000008EE27B8013
+:102B3000004028218EE200E08EE300E40000202126
+:102B40000046102414440003006718241065000B8D
+:102B5000000000008EE200C08EE300C48EE400E0BE
+:102B60008EE500E4AEE37B7CAEE57B808F820044A3
+:102B70003842002008001B38AF8200448F82004496
+:102B80002403FFDF0043102408001B38AF820044F9
+:102B90008F8200442403FFDF00431024AF820044EF
+:102BA0008EE27B7C004028218EE200C08EE300C4D0
+:102BB000240600002407FFFF000020210046102407
+:102BC0001444000D006718241465000B0000000079
+:102BD0008EE27B80004028218EE200E08EE300E45C
+:102BE000000020210046102414440003006718242C
+:102BF0001065000B000000008EE200C08EE300C4F0
+:102C00008EE400E08EE500E4AEE37B7CAEE57B8005
+:102C10008F8200443842004008001B38AF820044D5
+:102C20008F8200443442004008001B38AF820044C9
+:102C30008F82004434420040AF8200448EE27B8C9D
+:102C4000244300012842001514400028AEE37B8C89
+:102C50008F82004438420020AF82004408001B38B5
+:102C6000AEE07B8C8EE204D43042000110400011B3
+:102C7000000000008F42021830420080104000091E
+:102C8000000000008F82004434420020AF820044E4
+:102C90008F8200442403FFBF0043102408001B362A
+:102CA000AF8200448F8200443442006008001B362B
+:102CB000AF8200448F82004434420040AF8200441F
+:102CC0008EE27B88244300012842138914400005CA
+:102CD000AEE37B888F82004438420020AF820044FC
+:102CE000AEE07B880C004603000000008FBF00248C
+:102CF0008FB0002003E0000827BD002827BDFFB8E3
+:102D0000AFBF0044AFB60040AFB5003CAFB4003831
+:102D1000AFB30034AFB20030AFB1002CAFB0002879
+:102D20008F96006432C200041040000C240200049C
+:102D3000AF8200648F420114AEE204E08F82006033
+:102D400034420008AF8200608EE2016C2442000130
+:102D5000AEE2016C080022F48EE2016C32C2000186
+:102D60001040000424020001AF820064080022F435
+:102D70000000000032C200021440000C3C050003B9
+:102D80003C0400012484535434A5000102C03021C6
+:102D900000003821AFA000100C002403AFA00014E5
+:102DA0002402FFF8080022F4AF8200648F43022C53
+:102DB0008F42010C5062000CAFA000108F42022C19
+:102DC00000021080005A10218C420300AFA20020A4
+:102DD0008F42022C24070001244200013042003FB0
+:102DE00008001B80AF42022C3C0400012484536085
+:102DF000AFA000148F46022C8F47010C3C05000346
+:102E00000C00240334A5F01F0000382114E0000357
+:102E100000000000080022EDAF96006493A200209D
+:102E20002443FFFF2C62001110400658000310805D
+:102E30003C010001002208218C22541800400008A7
+:102E4000000000008FA2002030420FFFAEE20E0C07
+:102E50008F82006034420200AF8200608EE201186F
+:102E600024420001AEE20118080022E88EE20118B7
+:102E70008FA20020240300013C010001003708213B
+:102E8000A02383B130420FFFAEE252388F82006040
+:102E900034420100AF8200608EE20144244200010E
+:102EA000AEE20144080022E88EE201448FA2002035
+:102EB0000002120000022502240200011082000517
+:102EC00024020002108200092402FFFE08001BC930
+:102ED000AFA000108EE204D4AEE40070AEE4007443
+:102EE0003442000108001BBDAEE204D48EE304D4DA
+:102EF000AEE40070AEE4007400621824AEE304D4C3
+:102F00008F8400540004144200041C8200431021EA
+:102F100000041CC20043102300041D0200431021C2
+:102F200000041D420043102308001BD0AEE20078CD
+:102F30003C0400012484536CAFA000148FA6002031
+:102F40003C0500030C00240334A500048EE20110AC
+:102F500024420001AEE20110080022E88EE20110D6
+:102F6000274402120C0022FE240500063049001FEF
+:102F7000000920C002E410219442727C30424000DB
+:102F80001040000A0097102197430212A443727E5A
+:102F90008F43021400971021AC43728002E4182181
+:102FA0003402800008001C79A462727C9443727E13
+:102FB000974202121462000602E4102100971021C9
+:102FC0008C4372808F4202141062009F02E4102131
+:102FD0009442727C304280001040002A2406FFFF99
+:102FE00000002021000410C002E210219442737CF2
+:102FF000304240005440000500803021248400010C
+:103000002C8200801440FFF8000410C004C100109E
+:10301000000618C0000610C0005718218C63737C8E
+:1030200000571021AFA300108C4273803C040001B4
+:1030300024845378AFA200148F4702143C05000388
+:103040000C00240334A5001308001C903C02080067
+:103050009744021200771021A444737E8F44021417
+:103060000077102102E31821AC4473803402800001
+:10307000A462737C000910C002E2102108001C79D0
+:10308000A446727C02E410219445727C08001C2E38
+:10309000000510C09443737E97420212146200062A
+:1030A000000510C0009710218C4373808F420214DA
+:1030B00010620065000510C002E210219445737C87
+:1030C000000510C002E210219442737C304280005F
+:1030D0001040FFF000971021000520C0009710213C
+:1030E0009443737E97420212146200062406FFFF87
+:1030F000009710218C4373808F420214106200539A
+:103100003C02080000002021000410C002E210214F
+:103110009442737C304240005440000500803021CE
+:10312000248400012C8200801440FFF8000410C0A9
+:1031300004C10023000618C0000910C00057182160
+:103140008C63727C00571021AFA300108C427280F8
+:103150003C04000124845384AFA200148F4702145E
+:103160003C0500030C00240334A5F01708001C9054
+:103170003C0208008F43021000B71021AC43777C5B
+:103180008F43021400B71021AC4377803C0200014A
+:10319000005710218C4283B4244200013C010001FD
+:1031A00000370821AC2283B43C03000100771821CA
+:1031B0008C6383B402E5102108001C82A443777C51
+:1031C0009744021200771021A444737E8F440214A6
+:1031D0000077102102E31821AC4473803402800090
+:1031E000A462737C000510C002E21021A446737C27
+:1031F00000002021000428C002E510219442777CC1
+:103200001040FFDC248400012C8200805440FFFA2F
+:10321000000428C092E204D81040000624020001F5
+:103220008EE304DC012210040062182508001C8FC4
+:10323000AEE304DC8F830228240200010122100483
+:1032400000621825AF8302283C02080034421000B7
+:10325000AFA200188EE206088F4302282442000124
+:10326000304A00FF514300FDAFA000108EE2060877
+:10327000000210C0005710218FA300188FA4001C5B
+:10328000AC43060CAC4406108F8300548F8200546C
+:1032900024690032012210232C4200331040006ABE
+:1032A0000000582124100008240F000D240D0007F1
+:1032B000240C0040240E00018F8701202762380073
+:1032C00024E800200102102B504000012768300044
+:1032D0008F82012811020004000000008F82012467
+:1032E00015020007000010218EE201A40000382121
+:1032F00024420001AEE201A408001D088EE201A4F0
+:103300008EE40608000420C0008018218EE40430FA
+:103310008EE5043400A3282100A3302B0082202155
+:1033200000862021ACE40000ACE500048EE2060833
+:10333000A4F0000EACEF0018ACEA001C000210C0B4
+:103340002442060C02E21021ACE200088EE204C422
+:10335000ACE20010AF88012092E24E20144000330E
+:10336000240700018EE24E30000210C02442503883
+:1033700002E220218C820000144D001F000000009A
+:103380008EE34E308EE24E341062001B00000000CF
+:103390008C82000424420001AC8200048EE24E3490
+:1033A0008EE34E3024420001104C00070000000064
+:1033B0008EE24E342442000110620005000000003D
+:1033C00008001CF50000000014600005000000006B
+:1033D0008F82012824420020AF8201288F82012899
+:1033E0008C8200042C42001150400010AC80000080
+:1033F00008001D08000000008EE24E30244200014B
+:10340000504C0003000010218EE24E302442000197
+:10341000AEE24E308EE24E30000210C024425038F0
+:1034200002E22021AC8D0000AC8E000454E00006C6
+:10343000240B00018F820054012210232C42003300
+:103440001440FF9D00000000316300FF24020001D2
+:1034500054620078AFA00010AEEA06088F830054D3
+:103460008F82005424690032012210232C42003341
+:103470001040006100005821240E0008240D0011A6
+:10348000240A001224080040240C00018F8301202C
+:10349000276238002466002000C2102B5040000133
+:1034A000276630008F82012810C20004000000004F
+:1034B0008F82012414C20007000000008EE201A4E4
+:1034C0000000382124420001AEE201A408001D746E
+:1034D0008EE201A48EE20608AC62001C8EE404A019
+:1034E0008EE504A42462001CAC620008A46E000EE9
+:1034F000AC6D0018AC640000AC6500048EE204C43E
+:10350000AC620010AF86012092E24E2014400033DE
+:10351000240700018EE24E30000210C024425038D1
+:1035200002E220218C820000144A001F00000000EB
+:103530008EE34E308EE24E341062001B000000001D
+:103540008C82000424420001AC8200048EE24E34DE
+:103550008EE34E30244200011048000700000000B6
+:103560008EE24E342442000110620005000000008B
+:1035700008001D610000000014600005000000004C
+:103580008F82012824420020AF8201288F820128E7
+:103590008C8200042C42001150400010AC800000CE
+:1035A00008001D74000000008EE24E30244200012D
+:1035B00050480003000010218EE24E3024420001EA
+:1035C000AEE24E308EE24E30000210C0244250383F
+:1035D00002E22021AC8A0000AC8C000454E000061A
+:1035E000240B00018F820054012210232C4200334F
+:1035F0001440FFA600000000316300FF2402000118
+:1036000010620022000000003C040001248453905A
+:10361000AFA00010AFA000148F8601208F87012477
+:103620003C0500090C00240334A5F01108001DA07E
+:10363000000000003C0400012484539CAFA000144F
+:103640008F8601208F8701243C0500090C0024038C
+:1036500034A5F01008001DA0000000003C0400018B
+:10366000248453A8AFA000148EE606088F470228D2
+:103670003C0500090C00240334A5F00F8EE201ACD8
+:1036800024420001AEE201AC8EE201AC8EE20124E4
+:1036900024420001AEE2012408001F978EE20124BB
+:1036A000274402120C0022FE240500063049001FA8
+:1036B000000928C002E510219442727C304280004B
+:1036C0001040002F02E510219442727C30424000ED
+:1036D0001440001C00B710219443727E97420212DE
+:1036E0001462001800B710218C4372808F420214BC
+:1036F00054620016AFA2001092E204D810400007F6
+:10370000240200018EE304DC0122100400021027D1
+:103710000062182408001DC9AEE304DC8F83022870
+:10372000012210040002102700621824AF8302282F
+:10373000000910C002E218213402C00008001E4E29
+:10374000A462727C8F420214AFA20010000910C064
+:10375000005710218C42727C3C040001248453B435
+:103760003C050003AFA200148F47021034A5F01CE3
+:103770000C0024030120302108001E833C020800B5
+:1037800000B710219443727E97420212146200190E
+:10379000000918C000B710218C4372808F420214B8
+:1037A00014620014000918C002E510219447727CCD
+:1037B000000720C0009710219443737E00B71021AA
+:1037C000A443727E009710218C43738000B71021B0
+:1037D000AC43728002E410219443737C02E5102113
+:1037E000A443727C02E418213402C00008001E4E7B
+:1037F000A462737C02E310219447727C00003021A4
+:10380000000720C002E410219442737C0000402194
+:10381000304280001440002500E028210060502143
+:10382000340BC000009710219443737E974202121C
+:103830005462001500E02821009710218C4373800A
+:103840008F4202145462001000E02821110000068B
+:1038500002E410219443737C000510C002E21021A1
+:1038600008001E1AA443737C9443737C02EA10215F
+:10387000A443727C000710C002E21021A44B737CA9
+:1038800008001E2824060001000510C002E21021D5
+:103890009447737C000720C002E410219442737C9B
+:1038A000304280001040FFDF2508000130C200FFD9
+:1038B0001440002500002021000720C0009710219F
+:1038C0009443737E974202121462000F000910C0E5
+:1038D000009710218C4373808F4202141462000AF7
+:1038E000000910C002E418213402C00015000015C0
+:1038F000A462737C000910C002E218213402800027
+:1039000008001E4EA462727C005710218C42727C0B
+:103910003C040001248453C03C050003AFA2001006
+:10392000000710C0005710218C42737C34A5001E84
+:10393000012030210C002403AFA2001408001E83D4
+:103940003C02080000002021000428C000B710211C
+:103950009443777E974202125462002B2484000124
+:1039600000B710218C4377808F42021454620026E6
+:10397000248400013C020001005710218C4283B4D2
+:103980002442FFFF3C01000100370821AC2283B430
+:103990003C020001005710218C4283B4008090212A
+:1039A0000242102B1040000E24B1777C24B07784A3
+:1039B00002F0202102F128210C00249024060008A6
+:1039C000263100083C020001005710218C4283B4CC
+:1039D000265200010242102B1440FFF52610000869
+:1039E0003C040001009720218C8483B42405000846
+:1039F000000420C02484777C0C00248802E4202169
+:103A000008001E833C0208002C8200801440FFCF77
+:103A1000000428C03C02080034422000AFA2001875
+:103A20008EE206088F43022824420001304A00FF3C
+:103A3000514300FDAFA000108EE20608000210C046
+:103A4000005710218FA300188FA4001CAC43060C54
+:103A5000AC4406108F8300548F82005424690032D6
+:103A6000012210232C4200331040006A000058212C
+:103A700024100008240F000D240D0007240C004022
+:103A8000240E00018F8701202762380024E80020DF
+:103A90000102102B50400001276830008F8201285E
+:103AA00011020004000000008F82012415020007AB
+:103AB000000010218EE201A4000038212442000100
+:103AC000AEE201A408001EFB8EE201A48EE406080B
+:103AD000000420C0008018218EE404308EE50434F8
+:103AE00000A3282100A3302B008220210086202162
+:103AF000ACE40000ACE500048EE20608A4F0000E81
+:103B0000ACEF0018ACEA001C000210C02442060C06
+:103B100002E21021ACE200088EE204C4ACE2001024
+:103B2000AF88012092E24E201440003324070001A8
+:103B30008EE24E30000210C02442503802E22021B2
+:103B40008C820000144D001F000000008EE34E30F8
+:103B50008EE24E341062001B000000008C820004D4
+:103B600024420001AC8200048EE24E348EE34E30DB
+:103B700024420001104C0007000000008EE24E3489
+:103B800024420001106200050000000008001EE849
+:103B90000000000014600005000000008F82012872
+:103BA00024420020AF8201288F8201288C820004E9
+:103BB0002C42001150400010AC80000008001EFB99
+:103BC000000000008EE24E3024420001504C000301
+:103BD000000010218EE24E3024420001AEE24E3051
+:103BE0008EE24E30000210C02442503802E2202102
+:103BF000AC8D0000AC8E000454E00006240B0001E4
+:103C00008F820054012210232C4200331440FF9D68
+:103C100000000000316300FF2402000154620078BC
+:103C2000AFA00010AEEA06088F8300548F820054C4
+:103C300024690032012210232C420033104000611D
+:103C400000005821240E0008240D0011240A00123F
+:103C500024080040240C00018F83012027623800D3
+:103C60002466002000C2102B50400001276630005F
+:103C70008F82012810C20004000000008F820124FE
+:103C800014C20007000000008EE201A400003821E9
+:103C900024420001AEE201A408001F678EE201A4E5
+:103CA0008EE20608AC62001C8EE404A08EE504A43B
+:103CB0002462001CAC620008A46E000EAC6D0018FB
+:103CC000AC640000AC6500048EE204C4AC62001079
+:103CD000AF86012092E24E201440003324070001F9
+:103CE0008EE24E30000210C02442503802E2202101
+:103CF0008C820000144A001F000000008EE34E304A
+:103D00008EE24E341062001B000000008C82000422
+:103D100024420001AC8200048EE24E348EE34E3029
+:103D20002442000110480007000000008EE24E34DB
+:103D300024420001106200050000000008001F542A
+:103D40000000000014600005000000008F820128C0
+:103D500024420020AF8201288F8201288C82000437
+:103D60002C42001150400010AC80000008001F677A
+:103D7000000000008EE24E30244200015048000353
+:103D8000000010218EE24E3024420001AEE24E309F
+:103D90008EE24E30000210C02442503802E2202150
+:103DA000AC8A0000AC8C000454E00006240B000137
+:103DB0008F820054012210232C4200331440FFA6AE
+:103DC00000000000316300FF2402000110620022A5
+:103DD000000000003C04000124845390AFA00010B8
+:103DE000AFA000148F8601208F8701243C050009B5
+:103DF0000C00240334A5F01108001F9300000000FC
+:103E00003C0400012484539CAFA000148F86012041
+:103E10008F8701243C0500090C00240334A5F01011
+:103E200008001F93000000003C040001248453A8F4
+:103E3000AFA000148EE606088F4702283C05000953
+:103E40000C00240334A5F00F8EE201AC24420001E3
+:103E5000AEE201AC8EE201AC8EE201282442000108
+:103E6000AEE201288EE201288EE2016424420001C4
+:103E7000AEE20164080022E88EE201648FA2002015
+:103E80000002120000021D0224020001106200055F
+:103E9000240200021062000D0000000008001FB79D
+:103EA000AFA0001092E204D81440000624020001E2
+:103EB0008F820228AEE204DC2402FFFFAF820228D8
+:103EC0002402000108001FBEA2E204D892E204D836
+:103ED0005040000CA2E004D88EE204DCAF8202283D
+:103EE00008001FBEA2E004D83C040001248453C88B
+:103EF000AFA000148FA600203C0500030C00240393
+:103F000034A5F0098EE2013C24420001AEE2013CFE
+:103F1000080022E88EE2013C8FA20020000212007D
+:103F20000002250224020001108200052402000282
+:103F30001082000F0000000008001FE3AFA0001077
+:103F40008F8202203C0308FF3463FFFF00431024EC
+:103F500034420008AF820220240200013C0100012B
+:103F600000370821A02283B208001FEAAEE401084E
+:103F70008F8202203C0308FF3463FFF700431024C4
+:103F8000AF8202203C01000100370821A02083B24B
+:103F900008001FEAAEE401083C040001248453D465
+:103FA000AFA000148FA600203C0500030C002403E2
+:103FB00034A5F00A8EE2012C24420001AEE2012C6D
+:103FC000080022E88EE2012C8FA2002000021200DD
+:103FD00000021D02240200011062000524020002FA
+:103FE0001062000E0000000008002011AFA00010B9
+:103FF0008F8202203C0308FF3463FFFF004310243C
+:1040000034420008AF820220240200013C0100017A
+:104010000037082108002018A02283B33C020001C9
+:1040200000571021904283B23C0100010037082163
+:104030001440000EA02083B38F8202203C0308FFAF
+:104040003463FFF70043102408002018AF820220D9
+:104050003C040001248453E0AFA000148FA600208C
+:104060003C0500030C00240334A5F00B8EE2011480
+:1040700024420001AEE20114080022E88EE201149D
+:1040800027840208274502000C00249A2406000811
+:1040900026E40094274502000C00249A2406000818
+:1040A0008EE2013424420001AEE20134080022E82D
+:1040B0008EE201348F460248000020210C00510896
+:1040C000240500048EE2013024420001AEE20130FA
+:1040D000080022E88EE201308EF301CC8EF401D08C
+:1040E0008EF501D88EE2014026E400302442000122
+:1040F000AEE201408EF001408EF100748EF200704D
+:104100000C00248824050400AEF301CCAEF401D0E9
+:10411000AEF501D8AEF00140AEF10074AEF2007021
+:104120008F42025C26E40094AEE200608F4202609F
+:104130002745020024060008AEE2006824020006BB
+:104140000C00249AAEE200643C023B9A3442CA005E
+:10415000AEE2006C240203E8240400022403000100
+:10416000AEE20104AEE40100AEE3010C8F82022056
+:10417000304200081040000400000000AEE30108D7
+:104180000800206100002021AEE401080000202189
+:104190003C0300010064182190635C3002E41021AC
+:1041A00024840001A043009C2C82000F1440FFF8DF
+:1041B000000000008F82004002E4182124840001E6
+:1041C0000002170224420030A062009C02E4102189
+:1041D000080022E8A040009C240200013C010001EC
+:1041E00000370821A02283E0240B040024080014D7
+:1041F000240A0040240900018F8301002762300057
+:104200002466002000C2102B5040000127662800C1
+:104210008F82010810C20004000000008F82010498
+:1042200014C2000726E200308EE201A80000382107
+:1042300024420001AEE201A8080020A88EE201A8F5
+:104240008EE404B88EE504BCAC620008A46B000EDA
+:10425000AC680018AC60001CAC640000AC650004E5
+:104260008EE204CCAC620010AF86010092E204EC56
+:104270001440000E240700018EE24E282442000163
+:10428000504A0003000010218EE24E282442000113
+:10429000AEE24E288EE24E28000210C024424E3874
+:1042A00002E21021AC480000AC49000410E0FFD24B
+:1042B00000000000080022E8000000003C020900A5
+:1042C000AEE05238AEE0523CAEE05240AEE0524476
+:1042D000AEE001D03C01000100370821A02083B1ED
+:1042E000AFA200188EE206088F4302282442000184
+:1042F000304A00FF514300FDAFA000108EE20608D7
+:10430000000210C0005710218FA300188FA4001CBA
+:10431000AC43060CAC4406108F8300548F820054CB
+:1043200024690032012210232C4200331040006A1D
+:104330000000582124100008240F000D240D000750
+:10434000240C0040240E00018F87012027623800D2
+:1043500024E800200102102B5040000127683000A3
+:104360008F82012811020004000000008F820124C6
+:1043700015020007000010218EE201A40000382180
+:1043800024420001AEE201A40800212C8EE201A427
+:104390008EE40608000420C0008018218EE404305A
+:1043A0008EE5043400A3282100A3302B00822021B5
+:1043B00000862021ACE40000ACE500048EE2060893
+:1043C000A4F0000EACEF0018ACEA001C000210C014
+:1043D0002442060C02E21021ACE200088EE204C482
+:1043E000ACE20010AF88012092E24E20144000336E
+:1043F000240700018EE24E30000210C024425038E3
+:1044000002E220218C820000144D001F00000000F9
+:104410008EE34E308EE24E341062001B000000002E
+:104420008C82000424420001AC8200048EE24E34EF
+:104430008EE34E3024420001104C000700000000C3
+:104440008EE24E342442000110620005000000009C
+:1044500008002119000000001460000500000000A1
+:104460008F82012824420020AF8201288F820128F8
+:104470008C8200042C42001150400010AC800000DF
+:104480000800212C000000008EE24E302442000182
+:10449000504C0003000010218EE24E3024420001F7
+:1044A000AEE24E308EE24E30000210C02442503850
+:1044B00002E22021AC8D0000AC8E000454E0000626
+:1044C000240B00018F820054012210232C42003360
+:1044D0001440FF9D00000000316300FF2402000132
+:1044E00054620078AFA00010AEEA06088F83005433
+:1044F0008F82005424690032012210232C420033A1
+:104500001040006100005821240E0008240D001105
+:10451000240A001224080040240C00018F8301208B
+:10452000276238002466002000C2102B5040000192
+:10453000276630008F82012810C2000400000000AE
+:104540008F82012414C20007000000008EE201A443
+:104550000000382124420001AEE201A408002198A5
+:104560008EE201A48EE20608AC62001C8EE404A078
+:104570008EE504A42462001CAC620008A46E000E48
+:10458000AC6D0018AC640000AC6500048EE204C49D
+:10459000AC620010AF86012092E24E20144000333E
+:1045A000240700018EE24E30000210C02442503831
+:1045B00002E220218C820000144A001F000000004B
+:1045C0008EE34E308EE24E341062001B000000007D
+:1045D0008C82000424420001AC8200048EE24E343E
+:1045E0008EE34E3024420001104800070000000016
+:1045F0008EE24E34244200011062000500000000EB
+:104600000800218500000000146000050000000083
+:104610008F82012824420020AF8201288F82012846
+:104620008C8200042C42001150400010AC8000002D
+:1046300008002198000000008EE24E302442000164
+:1046400050480003000010218EE24E302442000149
+:10465000AEE24E308EE24E30000210C0244250389E
+:1046600002E22021AC8A0000AC8C000454E0000679
+:10467000240B00018F820054012210232C420033AE
+:104680001440FFA600000000316300FF2402000177
+:1046900010620022000000003C04000124845390BA
+:1046A000AFA00010AFA000148F8601208F870124D7
+:1046B0003C0500090C00240334A5F011080021C4B6
+:1046C000000000003C0400012484539CAFA00014AF
+:1046D0008F8601208F8701243C0500090C002403EC
+:1046E00034A5F010080021C4000000003C040001C3
+:1046F000248453A8AFA000148EE606088F47022832
+:104700003C0500090C00240334A5F00F8EE201AC37
+:1047100024420001AEE201AC8EE201AC8EE2012047
+:1047200024420001AEE201208EE201208EE2016807
+:1047300024420001AEE20168080022E88EE201682E
+:104740008F42025C26E40094AEE200608F42026079
+:1047500027450200240600080C00249AAEE20068F7
+:104760008F8202203042000814400002240200011F
+:1047700024020002AEE201088EE2011C2442000184
+:10478000AEE2011C080022E88EE2011C3C0400019C
+:10479000248453ECAFA00010AFA000148FA600201B
+:1047A0003C0500030C00240334A5F00F93A2002065
+:1047B0003C0307003463100000431025AFA200182B
+:1047C0008EE206088F43022824420001304900FF90
+:1047D000512300E2AFA000108EE20608000210C0D4
+:1047E000005710218FA300188FA4001CAC43060CA7
+:1047F000AC4406108F8701202762380024E800208F
+:104800000102102B50400001276830008F820128E0
+:1048100011020004000000008F820124150200072D
+:10482000000010218EE201A4000038212442000182
+:10483000AEE201A40800225D8EE201A48EE4060827
+:10484000000420C0008018218EE404308EE504347A
+:1048500000A3282100A3302B0082202100862021E4
+:10486000ACE40000ACE500048EE306082402000876
+:10487000A4E2000E2402000DACE20018ACE9001C1A
+:10488000000318C02463060C02E31021ACE2000808
+:104890008EE204C4ACE20010AF88012092E24E2008
+:1048A00014400037240700018EE24E30000210C091
+:1048B0002442503802E220218C83000024020007A9
+:1048C0001462001F000000008EE34E308EE24E3472
+:1048D0001062001B240300408C820004244200016B
+:1048E000AC8200048EE24E348EE54E30244200014C
+:1048F00010430007000000008EE24E342442000105
+:1049000010A200050000000008002247000000007F
+:1049100014A00005000000008F820128244200201E
+:10492000AF8201288F8201288C8200042C42001162
+:1049300050400013AC8000000800225D0000000021
+:104940008EE24E3024030040244200015043000315
+:10495000000010218EE24E3024420001AEE24E30C3
+:104960008EE24E30000210C02442503802E2202174
+:1049700024020007AC82000024020001AC82000483
+:1049800054E0000CAEE906083C040001248453F412
+:10499000AFA00010AFA000148EE606088F470228D3
+:1049A0003C0500090C00240334A5F000080022E0B7
+:1049B000000000008F830120276238002466002059
+:1049C00000C2102B50400001276630008F82012862
+:1049D00010C20004000000008F82012414C20007EE
+:1049E000000000008EE201A40000382124420001F2
+:1049F000AEE201A4080022C48EE201A48EE2060801
+:104A0000AC62001C8EE404A08EE504A42462001CA9
+:104A1000AC62000824020008A462000E2402001107
+:104A2000AC620018AC640000AC6500048EE204C403
+:104A3000AC620010AF86012092E24E201440003795
+:104A4000240700018EE24E30000210C0244250388C
+:104A500002E220218C830000240200121462001F55
+:104A6000000000008EE34E308EE24E341062001BD8
+:104A7000240300408C82000424420001AC82000424
+:104A80008EE24E348EE54E30244200011043000782
+:104A9000000000008EE24E342442000110A2000506
+:104AA00000000000080022AE0000000014A0000575
+:104AB000000000008F82012824420020AF820128DC
+:104AC0008F8201288C8200042C4200115040001378
+:104AD000AC800000080022C4000000008EE24E30CE
+:104AE0002403004024420001504300030000102131
+:104AF0008EE24E3024420001AEE24E308EE24E3065
+:104B0000000210C02442503802E220212402001288
+:104B1000AC82000024020001AC82000414E0001BFF
+:104B2000000000003C040001248453FCAFA00010EE
+:104B3000AFA000148EE606088F4702283C05000946
+:104B40000C00240334A5F0018EE201B024420001E0
+:104B5000AEE201B0080022E08EE201B03C040001A8
+:104B600024845408AFA000148EE606088F4702285C
+:104B70003C0500090C00240334A5F0058EE201ACCD
+:104B800024420001AEE201AC8EE201AC8EE20150A3
+:104B900024420001AEE201508EE201508EE201603B
+:104BA00024420001AEE201608EE201608F43022CDC
+:104BB0008F42010C1462000924020002AF820064DB
+:104BC0008F82006414400005000000008F43022C17
+:104BD0008F42010C1462F875000000008FBF004482
+:104BE0008FB600408FB5003C8FB400388FB30034CF
+:104BF0008FB200308FB1002C8FB0002803E0000886
+:104C000027BD004827BDFFF82408FFFF10A00014AF
+:104C1000000048213C0AEDB8354A83209087000007
+:104C200024840001000030210107102630420001D9
+:104C30001040000200081842006A18260060402157
+:104C400024C600012CC200081440FFF700073842B8
+:104C5000252900010125102B1440FFF00000000061
+:104C60000100102103E0000827BD000827BDFFE870
+:104C700027642800AFBF00100C0024882405100012
+:104C800024020021AF800100AF800104AF80010841
+:104C9000AF800110AF800114AF800118AF800120F8
+:104CA000AF800124AF800128AF800130AF80013494
+:104CB000AF800138AEE04E28AEE04E2CAEE04E3074
+:104CC000AEE04E34AF82011C8F42021830420040E9
+:104CD00010400004000000008F82011C34420004D8
+:104CE000AF82011C8FBF001003E0000827BD001831
+:104CF00027BDFFE0AFBF00188F820104AFA20010F4
+:104D00008F8201003C050002AFA200148F8600B024
+:104D10008F87011C3C040001248454C00C00240330
+:104D200034A5F0008F8300B03C027F00006218249D
+:104D30003C020400106200290043102B14400008BC
+:104D40003C0220003C020100106200243C020200F0
+:104D50001062001100000000080023740000000031
+:104D6000106200083C0240001462001C00000000B9
+:104D70008EE2019024420001AEE20190080023740B
+:104D80008EE201908EE2018C24420001AEE2018CA1
+:104D9000080023748EE2018C8F82011C34420002D1
+:104DA000AF82011C8F8301048F8200B03442000166
+:104DB000AF8200B0AF8301048F82011C2403FFFD8A
+:104DC00000431024AF82011C8EE201A024420001A6
+:104DD000AEE201A0080023778EE201A08F8200B02E
+:104DE00034420001AF8200B08FBF001803E000081A
+:104DF00027BD002027BDFFE0AFBF001CAFB00018EB
+:104E00008F820120AFA200108F8201243C05000197
+:104E1000AFA200148F8600A08F87011C3C04000104
+:104E2000248454CC0C00240334A5F0008F8300A00C
+:104E30003C027F00006218243C0204001062005310
+:104E4000000080210043102B144000083C04200087
+:104E50003C0201001062004D3C0202001062003A68
+:104E600000000000080023E00000000010640003C0
+:104E70003C02400014620045000000008F8200A048
+:104E80000044102410400006000000008EE201944F
+:104E900024420001AEE20194080023A98EE20194AD
+:104EA0008EE2019824420001AEE201988EE2019860
+:104EB0008F82011C34420002AF82011C8F82011CD0
+:104EC000304202001040001B000000008F8300A051
+:104ED0008F8401248F8200AC14400007240200015B
+:104EE0003C0200013442F0000062102450400001F6
+:104EF00024100001240200011200000DAF8200A066
+:104F00008F8201242442FFE0AF8201248F8201249A
+:104F10008F820124276330000043102B10400005CE
+:104F2000276237E0AF820124080023CA0000000096
+:104F3000AF8401248F82011C2403FFFD0043102451
+:104F4000080023E3AF82011C8F82011C344200025F
+:104F5000AF82011C8F8301248F8200A034420001A4
+:104F6000AF8200A0AF8301248F82011C2403FFFDC8
+:104F700000431024AF82011C8EE2019C24420001F8
+:104F8000AEE2019C080023E38EE2019C8F8200A028
+:104F900034420001AF8200A08FBF001C8FB0001808
+:104FA00003E0000827BD0020000000003C020001D3
+:104FB0008C425C5827BDFFE8AFBF001414400012BC
+:104FC000AFB000103C10000126105DD0020020217F
+:104FD0000C0024882405200026021FE03C0100016B
+:104FE000AC225D943C010001AC225D90AF420250C6
+:104FF00024022000AF500254AF42025824020001A4
+:105000003C010001AC225C588FBF00148FB000102F
+:1050100003E0000827BD00183C0300018C635D9489
+:105020008C8200008FA800108FA90014AC620000D1
+:105030003C0200018C425D948C830004AC4300046C
+:10504000AC4500088F8400542443FFE0AC460010B8
+:10505000AC470014AC480018AC49001C3C010001EE
+:10506000AC235D94AC44000C3C02000124425DD0B2
+:105070000062182B10600005000000003C020001D7
+:105080008C425D903C010001AC225D943C03000128
+:105090008C635D943C0200018C425C40AC62000079
+:1050A0003C0300018C635D943C0200018C425C4037
+:1050B000AC62000403E00008AF4302503C0300016F
+:1050C0008C635D943C0200018C425C4027BDFFD0A4
+:1050D000AFB400208FB40040AFB00010008080213A
+:1050E000AFB500248FB500448FA40048AFB10014C1
+:1050F00000A08821AFBF0028AFB3001CAFB20018DA
+:10510000AC6200003C0500018CA55D943C020001EE
+:105110008C425C4000C0902100E098211080000685
+:10512000ACA2000424A500080C002490240600185A
+:105130000800244E0000000024A400080C0024886D
+:10514000240500183C0200018C425D943C050001DE
+:1051500024A55DD02442FFE03C010001AC225D9417
+:105160000045102B10400005000000003C0200012B
+:105170008C425D903C010001AC225D943C03000137
+:105180008C635D948E020000AC6200003C03000161
+:105190008C635D948E020004AC620004AC71000864
+:1051A0008F8400542462FFE03C010001AC225D9436
+:1051B0000045102BAC720010AC730014AC740018D6
+:1051C000AC75001C10400005AC64000C3C020001F2
+:1051D0008C425D903C010001AC225D943C030001D7
+:1051E0008C635D943C0200018C425C40AC62000028
+:1051F0003C0300018C635D943C0200018C425C40E6
+:10520000AC620004AF4302508FBF00288FB500246A
+:105210008FB400208FB3001C8FB200188FB1001420
+:105220008FB0001003E0000827BD003010A000057B
+:1052300000000000AC80000024A5FFFC14A0FFFDCE
+:105240002484000403E000080000000010C00007F0
+:10525000000000008C8200002484000424C6FFFCAF
+:10526000ACA2000014C0FFFB24A5000403E000086A
+:105270000000000010C00007000000008CA2000029
+:1052800024A5000424C6FFFCAC82000014C0FFFB70
+:105290002484000403E000080000000003E000088C
+:1052A0000000000027BDFFD8AFBF00208EE304E45C
+:1052B0008EE204E010620436000000008EE204E496
+:1052C0008EE304FC00021100006260219587000853
+:1052D0008D8A00008D8B0004958D000A8EE2725C31
+:1052E0008EE3726C30E4FFFF004410210062182B43
+:1052F0001060001531A200048F8200D88EE372582E
+:1053000000431023AEE2726C8EE2726C1C4000030C
+:105310003C03000100431021AEE2726C8EE2725C2D
+:105320008EE3726C004410210062182B106000069E
+:1053300031A200048EE201B824420001AEE201B8BD
+:10534000080028E18EE201B81040024031A20200BC
+:105350001040014D0000482196E2045A30420010EE
+:1053600010400149000000008F84010027623000D6
+:105370002485002000A2102B504000012765280042
+:105380008F82010810A20004000000008F82010437
+:1053900014A200062402000C8EE201A8244200019F
+:1053A000AEE201A80800252C8EE201A8AC8A00001C
+:1053B000AC8B00048EE3726424060005A482000E08
+:1053C000AC860018AC8300088EE204E4AC82001CBA
+:1053D0008EE204C8AC820010AF85010092E204ECBA
+:1053E00014400036240900018EE24E28000210C04D
+:1053F00024424E3802E220218C8200001446001F15
+:10540000000000008EE34E288EE24E2C1062001B3E
+:10541000240300408C82000424420001AC8200047A
+:105420008EE24E2C8EE54E282442000110430007E8
+:10543000000000008EE24E2C2442000110A2000564
+:1054400000000000080025160000000014A0000560
+:10545000000000008F82010824420020AF82010872
+:105460008F8201088C8200042C42001150400013EE
+:10547000AC8000000800252C000000008EE24E28C1
+:105480002403004024420001504300030000102187
+:105490008EE24E2824420001AEE24E288EE24E28D3
+:1054A000000210C024424E3802E2202124020005EE
+:1054B000AC82000024020001AC8200041520000A26
+:1054C0003C040001AFAB00108EE272643C040001AA
+:1054D000248457303C050004AFA200148EE604E497
+:1054E000080028BE34A5F1148EE2726434843800BA
+:1054F00003641821244200100043102B1440007351
+:10550000000000008EE27264244800100364102141
+:105510000102102B144000023C02FFFF0102402157
+:105520008F8501002762300024A6002000C2102BC6
+:1055300050400001276628008F82010810C2000435
+:10554000000000008F82010414C200072563000CD4
+:105550008EE201A80000482124420001AEE201A829
+:10556000080025A08EE201A82C64000C0144102143
+:10557000ACA20000ACA3000424E2FFF4A4A2000E3D
+:1055800024020006ACA80008ACA200188EE204E4D5
+:10559000ACA2001C8EE204C83C03000200431025AC
+:1055A000ACA20010AF86010092E204EC1440003778
+:1055B000240900018EE24E28000210C024424E3819
+:1055C00002E220218C830000240200051462001FE7
+:1055D000000000008EE34E288EE24E2C1062001B6D
+:1055E000240300408C82000424420001AC820004A9
+:1055F0008EE24E2C8EE54E28244200011043000717
+:10560000000000008EE24E2C2442000110A2000592
+:10561000000000000800258A0000000014A000051A
+:10562000000000008F82010824420020AF820108A0
+:105630008F8201088C8200042C420011504000131C
+:10564000AC800000080025A0000000008EE24E287B
+:1056500024030040244200015043000300001021B5
+:105660008EE24E2824420001AEE24E288EE24E2801
+:10567000000210C024424E3802E22021240200051C
+:10568000AC82000024020001AC8200041520000A54
+:105690002508FFFCAFAB00108EE272643C040001F1
+:1056A000248457303C050004AFA200148EE604E4C5
+:1056B000080028BE34A5F12534028100A5020000AF
+:1056C0009582000E0800261DA50200028F850100AC
+:1056D0002762300024A6002000C2102B5040000199
+:1056E000276628008F82010810C200040000000015
+:1056F0008F82010414C200072563000C8EE201A80A
+:105700000000482124420001AEE201A80800260D55
+:105710008EE201A82C64000C01441021ACA2000010
+:10572000ACA300048EE3726424E2FFF4A4A2000E92
+:1057300024020006ACA2001824630010ACA30008E9
+:105740008EE204E4ACA2001C8EE204C83C0300021A
+:1057500000431025ACA20010AF86010092E204ECD9
+:1057600014400037240900018EE24E28000210C0C8
+:1057700024424E3802E220218C83000024020005DE
+:105780001462001F000000008EE34E288EE24E2CB3
+:105790001062001B240300408C820004244200019C
+:1057A000AC8200048EE24E2C8EE54E28244200018D
+:1057B00010430007000000008EE24E2C244200013E
+:1057C00010A2000500000000080025F700000000FE
+:1057D00014A00005000000008F8201082442002070
+:1057E000AF8201088F8201088C8200042C420011D4
+:1057F00050400013AC8000000800260D000000009F
+:105800008EE24E282403004024420001504300034E
+:10581000000010218EE24E2824420001AEE24E2804
+:105820008EE24E28000210C024424E3802E22021AF
+:1058300024020005AC82000024020001AC820004B6
+:105840001520000A34028100AFAB00108EE27264B2
+:105850003C040001248457303C050004AFA200142E
+:105860008EE604E4080028BE34A5F0158EE37264C9
+:10587000A462000C8EE372649582000EA462000E96
+:105880000800268124E700048F840100276230008D
+:105890002485002000A2102B50400001276528001D
+:1058A0008F82010810A20004000000008F82010412
+:1058B00014A20007240200068EE201A8000048217D
+:1058C00024420001AEE201A8080026778EE201A87A
+:1058D000AC8A0000AC8B00048EE37264A487000ED7
+:1058E000AC820018AC8300088EE204E4AC82001C99
+:1058F0008EE204C83C03000200431025AC82001075
+:10590000AF85010092E204EC144000372409000145
+:105910008EE24E28000210C024424E3802E22021BE
+:105920008C830000240200051462001F00000000A8
+:105930008EE34E288EE24E2C1062001B24030040A2
+:105940008C82000424420001AC8200048EE24E2CC2
+:105950008EE54E282442000110430007000000009D
+:105960008EE24E2C2442000110A20005000000002F
+:10597000080026610000000014A0000500000000DF
+:105980008F82010824420020AF8201088F82010823
+:105990008C8200042C42001150400013AC800000A7
+:1059A00008002677000000008EE24E282403004005
+:1059B0002442000150430003000010218EE24E28D3
+:1059C00024420001AEE24E288EE24E28000210C0B2
+:1059D00024424E3802E2202124020005AC8200005D
+:1059E00024020001AC820004152000093C050004DB
+:1059F000AFAB00108EE272643C0400012484573087
+:105A0000AFA200148EE604E4080028BE34A5F0041A
+:105A10008EE2725C30E7FFFF00471021AEE2725C5D
+:105A20008EE204E48EE304FC8EE47258000211005E
+:105A300000431021AC44000C8EE27258AFA2001853
+:105A40008EE3725CAFA3001C8EE2725C2C42003CC1
+:105A500010400004246200012403FFFE00431024D0
+:105A6000AFA2001C8EE272643C06000134C638000E
+:105A70008EE3725C2405FFF80047102124420007E2
+:105A80000045102424630007AEE272588EE2726C67
+:105A90008EE472580065182400431023AEE2726C45
+:105AA000036610210082202B148000043C03FFFFBA
+:105AB0008EE2725800431021AEE272588EE27258A4
+:105AC000AEE272648F8200F024470008276218005B
+:105AD00000E2102B50400001276710008F8200F475
+:105AE00014E20007000000008EE201B4000048212B
+:105AF00024420001AEE201B4080026C48EE201B4E3
+:105B00008F8200F0240900018FA300188FA4001CCD
+:105B1000AC430000AC440004AF8700F01520001235
+:105B2000000D11428F8200F0AFA200108F8200F4AE
+:105B30003C0400012484573CAFA200148FA6001837
+:105B40008FA7001C3C0500040C00240334A5F005BD
+:105B50008EE2008824420001AEE200888EE20088D6
+:105B6000080028D3AEE0725C304300032402000238
+:105B70001062001628620003104000052402000194
+:105B80001062000800000000080027030000000069
+:105B90002402000310620017000000000800270321
+:105BA000000000008EE200E88EE300EC24630001B8
+:105BB0002C64000100441021AEE200E8AEE300ECEA
+:105BC0008EE200E8080027038EE300EC8EE200F08E
+:105BD0008EE300F4246300012C64000100441021D2
+:105BE000AEE200F0AEE300F48EE200F0080027031E
+:105BF0008EE300F48EE200F88EE300FC24630001E3
+:105C00002C64000100441021AEE200F8AEE300FC79
+:105C10008EE200F88EE300FC8EE2725C8EE400E01F
+:105C20008EE500E4004018210000102100A3282187
+:105C300000A3302B0082202100862021AEE400E06A
+:105C4000AEE500E4080028D3AEE0725C30E2FFFF6E
+:105C5000104001C131A202001040014D0000482156
+:105C600096E2045A30420010104001490000000042
+:105C70008F840100276230002485002000A2102BB1
+:105C800050400001276528008F82010810A20004FF
+:105C9000000000008F82010414A200062402000C00
+:105CA0008EE201A824420001AEE201A80800276E9E
+:105CB0008EE201A8AC8A0000AC8B00048EE3726413
+:105CC00024060005A482000EAC860018AC830008F0
+:105CD0008EE204E4AC82001C8EE204C8AC820010A8
+:105CE000AF85010092E204EC144000362409000163
+:105CF0008EE24E28000210C024424E3802E22021DB
+:105D00008C8200001446001F000000008EE34E2825
+:105D10008EE24E2C1062001B240300408C82000493
+:105D200024420001AC8200048EE24E2C8EE54E2807
+:105D30002442000110430007000000008EE24E2CB8
+:105D40002442000110A200050000000008002758AE
+:105D50000000000014A00005000000008F82010870
+:105D600024420020AF8201088F8201088C82000447
+:105D70002C42001150400013AC8000000800276E38
+:105D8000000000008EE24E2824030040244200015F
+:105D900050430003000010218EE24E2824420001EF
+:105DA000AEE24E288EE24E28000210C024424E3849
+:105DB00002E2202124020005AC820000240200013E
+:105DC000AC8200041520000A3C040001AFAB0010B7
+:105DD0008EE272643C040001248457303C050004C8
+:105DE000AFA200148EE604E4080028BE34A5F01427
+:105DF0008EE2726434843800036418212442001057
+:105E00000043102B14400073000000008EE2726407
+:105E100024480010036410210102102B14400002DA
+:105E20003C02FFFF010240218F8501002762300004
+:105E300024A6002000C2102B504000012766280035
+:105E40008F82010810C20004000000008F8201044C
+:105E500014C200072563000C8EE201A8000048214F
+:105E600024420001AEE201A8080027E28EE201A868
+:105E70002C64000C01441021ACA20000ACA300046F
+:105E800024E2FFF4A4A2000E24020006ACA800083D
+:105E9000ACA200188EE204E4ACA2001C8EE204C89E
+:105EA0003C03000200431025ACA20010AF860100A5
+:105EB00092E204EC14400037240900018EE24E28DF
+:105EC000000210C024424E3802E220218C830000E0
+:105ED000240200051462001F000000008EE34E281B
+:105EE0008EE24E2C1062001B240300408C820004C2
+:105EF00024420001AC8200048EE24E2C8EE54E2836
+:105F00002442000110430007000000008EE24E2CE6
+:105F10002442000110A2000500000000080027CC68
+:105F20000000000014A00005000000008F8201089E
+:105F300024420020AF8201088F8201088C82000475
+:105F40002C42001150400013AC800000080027E2F2
+:105F5000000000008EE24E2824030040244200018D
+:105F600050430003000010218EE24E28244200011D
+:105F7000AEE24E288EE24E28000210C024424E3877
+:105F800002E2202124020005AC820000240200016C
+:105F9000AC8200041520000A2508FFFCAFAB0010FE
+:105FA0008EE272643C040001248457303C050004F6
+:105FB000AFA200148EE604E4080028BE34A5F01554
+:105FC00034028100A50200009582000E0800285FBF
+:105FD000A50200028F8501002762300024A6002060
+:105FE00000C2102B50400001276628008F82010854
+:105FF00010C20004000000008F82010414C20007D8
+:106000002563000C8EE201A8000048212442000113
+:10601000AEE201A80800284F8EE201A82C64000C13
+:1060200001441021ACA20000ACA300048EE3726412
+:1060300024E2FFF4A4A2000E24020006ACA2001881
+:1060400024630010ACA300088EE204E4ACA2001CA0
+:106050008EE204C83C03000200431025ACA20010ED
+:10606000AF86010092E204EC1440003724090001DD
+:106070008EE24E28000210C024424E3802E2202157
+:106080008C830000240200051462001F0000000041
+:106090008EE34E288EE24E2C1062001B240300403B
+:1060A0008C82000424420001AC8200048EE24E2C5B
+:1060B0008EE54E2824420001104300070000000036
+:1060C0008EE24E2C2442000110A2000500000000C8
+:1060D000080028390000000014A00005000000009E
+:1060E0008F82010824420020AF8201088F820108BC
+:1060F0008C8200042C42001150400013AC80000040
+:106100000800284F000000008EE24E2824030040C3
+:106110002442000150430003000010218EE24E286B
+:1061200024420001AEE24E288EE24E28000210C04A
+:1061300024424E3802E2202124020005AC820000F5
+:1061400024020001AC8200041520000A3402810000
+:10615000AFAB00108EE272643C040001248457301F
+:106160003C050004AFA200148EE604E4080028BE3B
+:1061700034A5F0168EE37264A462000C8EE37264A0
+:106180009582000EA462000E080028C224E70004D5
+:106190008F83010027623000246400200082102BCE
+:1061A00050400001276428008F82010810820004FB
+:1061B000000000008F8201041482000724050005FE
+:1061C0008EE201A80000482124420001AEE201A8AD
+:1061D000080028B68EE201A8AC6A0000AC6B00048F
+:1061E0008EE27264A467000EAC650018AC62000811
+:1061F0008EE204E4AC62001C8EE204C8AC620010C3
+:10620000AF84010092E204EC14400036240900013E
+:106210008EE24E28000210C024424E3802E22021B5
+:106220008C8200001445001F000000008EE34E2801
+:106230008EE24E2C1062001B240300408C8200046E
+:1062400024420001AC8200048EE24E2C8EE54E28E2
+:106250002442000110430007000000008EE24E2C93
+:106260002442000110A2000500000000080028A040
+:106270000000000014A00005000000008F8201084B
+:1062800024420020AF8201088F8201088C82000422
+:106290002C42001150400013AC800000080028B6CA
+:1062A000000000008EE24E2824030040244200013A
+:1062B00050430003000010218EE24E2824420001CA
+:1062C000AEE24E288EE24E28000210C024424E3824
+:1062D00002E2202124020005AC8200002402000119
+:1062E000AC8200041520000B3C0500043C040001B6
+:1062F00024845748AFAB0010AFA000148EE604E42E
+:1063000034A5F0170C00240330E7FFFF080028E154
+:10631000000000008EE272643C05000130E4FFFFE3
+:1063200000441021AEE272648EE2725C8EE372640D
+:1063300034A5380000441021AEE2725C03651021E0
+:106340000062182B146000043C03FFFF8EE27264AD
+:1063500000431021AEE272648EE304E496E2045836
+:10636000246300012442FFFF00621824AEE304E42A
+:106370008EE304E48EE204E01462000500000000F5
+:106380008F8200602403FFF700431024AF82006077
+:106390008FBF002003E0000827BD002827BDFFE0D5
+:1063A000AFBF00188EE304E88EE204E010620189BA
+:1063B000000000008EE204E88EE304FC00021100FD
+:1063C000006218219467000892E204ED8C680000D6
+:1063D0008C69000410400023946A000A8EE204C80D
+:1063E00034460400314202001040001F000000004B
+:1063F00096E2045A304200101040001B3C0280001C
+:106400003C01000100370821AC2283D88EE272647F
+:106410009464000E3C05000134A5380024420004B9
+:10642000AEE272648EE372640004240003651021FE
+:106430003C01000100370821AC2483DC0062182BEA
+:106440001460000524E700048EE272643C03FFFF41
+:1064500000431021AEE272648EE2726408002917D4
+:10646000AEE272588EE604C88EE2726C30E4FFFF32
+:106470000044102A10400015000000008F8200D850
+:106480008EE3725800431023AEE2726C8EE2726C9F
+:106490001C4000070044102A8EE2726C3C0300018D
+:1064A00000431021AEE2726C8EE2726C0044102A3E
+:1064B00010400006000000008EE201B824420001F6
+:1064C000AEE201B808002A728EE201B83C02000177
+:1064D000005710218C4283D85440000124E7FFFC70
+:1064E00031420004104000B930E2FFFF3C020001DD
+:1064F000005710218C4283D81040002F00005021FB
+:106500008F840100276230002485002000A2102B18
+:1065100050400001276528008F82010810A2003238
+:10652000000000008F82010410A2002F2402001539
+:10653000AC880000AC8900048EE37264A487000E6E
+:10654000AC820018AC8300088EE204E83C03000132
+:10655000007718218C6383DCAC8600100043102583
+:10656000AC82001CAF85010092E204EC144000668E
+:10657000240A00018EE24E28240300402442000138
+:1065800050430003000010218EE24E2824420001F7
+:10659000AEE24E288EE24E28000210C024424E3851
+:1065A00002E2182124020015AC620000240200015E
+:1065B000080029BFAC6200048F840100276230000C
+:1065C0002485002000A2102B5040000127652800E0
+:1065D0008F82010810A20004000000008F820104D5
+:1065E00014A20006240200068EE201A82442000143
+:1065F000AEE201A8080029BF8EE201A8AC88000025
+:10660000AC8900048EE37264A487000EAC8200188B
+:10661000AC8300088EE204E8AC860010AC82001C5B
+:10662000AF85010092E204EC14400037240A000117
+:106630008EE24E28000210C024424E3802E2202191
+:106640008C830000240200051462001F000000007B
+:106650008EE34E288EE24E2C1062001B2403004075
+:106660008C82000424420001AC8200048EE24E2C95
+:106670008EE54E2824420001104300070000000070
+:106680008EE24E2C2442000110A200050000000002
+:10669000080029A90000000014A000050000000067
+:1066A0008F82010824420020AF8201088F820108F6
+:1066B0008C8200042C42001150400013AC8000007A
+:1066C000080029BF000000008EE24E28240300408D
+:1066D0002442000150430003000010218EE24E28A6
+:1066E00024420001AEE24E288EE24E28000210C085
+:1066F00024424E3802E2202124020005AC82000030
+:1067000024020001AC8200041540000A24020001AA
+:10671000AFA900108EE272643C040001248457305B
+:106720003C050004AFA200148EE604E408002A4FE2
+:1067300034A5F204A2E204ED8EE204E88EE304FC48
+:106740008EE472583C06000134C638003C0100015A
+:1067500000370821AC2083D83C0100010037082114
+:10676000AC2083DC0002110000431021AC44000C7B
+:106770008EE272642405FFF830E3FFFF004310212E
+:10678000244200070045102424630007AEE272583B
+:106790008EE2726C8EE47258006518240043102358
+:1067A000AEE2726C036610210082202B148000047C
+:1067B0003C03FFFF8EE2725800431021AEE2725894
+:1067C0008EE2725808002A64AEE2726410400073D0
+:1067D000000000008F830100276230002464002045
+:1067E0000082102B14400002000050212764280072
+:1067F0008F82010810820004000000008F820104D3
+:1068000014820006240500058EE201A8244200013E
+:10681000AEE201A808002A468EE201A8AC6800009A
+:10682000AC6900048EE27264A467000EAC650018C7
+:10683000AC6200088EE204E8AC660010AC62001C9A
+:10684000AF84010092E204EC14400036240A0001F7
+:106850008EE24E28000210C024424E3802E220216F
+:106860008C8200001445001F000000008EE34E28BB
+:106870008EE24E2C1062001B240300408C82000428
+:1068800024420001AC8200048EE24E2C8EE54E289C
+:106890002442000110430007000000008EE24E2C4D
+:1068A0002442000110A200050000000008002A3068
+:1068B0000000000014A00005000000008F82010805
+:1068C00024420020AF8201088F8201088C820004DC
+:1068D0002C42001150400013AC80000008002A46F2
+:1068E000000000008EE24E282403004024420001F4
+:1068F00050430003000010218EE24E282442000184
+:10690000AEE24E288EE24E28000210C024424E38DD
+:1069100002E2202124020005AC82000024020001D2
+:10692000AC8200041540000C30E5FFFF3C04000180
+:10693000248457483C050004AFA90010AFA0001400
+:106940008EE604E434A5F2370C00240330E7FFFFA1
+:1069500008002A72000000008EE2726400451021D7
+:10696000AEE272648EE2726C8EE372643C040001EB
+:1069700034843800A2E004ED00451023AEE2726CCE
+:10698000036410210062182B146000043C03FFFF15
+:106990008EE2726400431021AEE272648EE304E87A
+:1069A00096E20458246300012442FFFF0062182489
+:1069B000AEE304E88EE304E88EE204E0146200052E
+:1069C000000000008F8200602403FFF700431024C2
+:1069D000AF8200608FBF001803E0000827BD0020D1
+:1069E00027BDFFE0AFBF001CAFB000188F820100D1
+:1069F0008EE34E2C8F8201048F8501082402004013
+:106A00002463000150620003000010218EE24E2C2E
+:106A100024420001AEE24E2C8EE24E2C8EE34E2C30
+:106A2000000210C024424E3802E220218EE24E289D
+:106A30008C8700041462000700A030218F820108B7
+:106A400024420020AF8201088F82010808002AA298
+:106A5000AC8000008EE24E2C240300402442000152
+:106A600050430003000010218EE24E2C244200010E
+:106A7000000210C024424E3802E220218C82000421
+:106A80008F8301080002114000621821AF830108C2
+:106A9000AC8000008CC200182443FFFE2C6200135F
+:106AA000104000C1000310803C01000100220821B9
+:106AB0008C22577000400008000000008EE204F0B5
+:106AC00000471021AEE204F08EE204F08F43023C56
+:106AD0000043102B144000BE000000008EE304E4CD
+:106AE0008EE204F8506200BAA2E004F48F83012021
+:106AF000276238002466002000C2102B504000019D
+:106B0000276630008F82012810C2000400000000B8
+:106B10008F82012414C20007000000008EE201A44D
+:106B20000000802124420001AEE201A408002B12E3
+:106B30008EE201A48EE204E4AC62001C8EE404B098
+:106B40008EE504B42462001CAC6200082402000834
+:106B5000A462000E24020011AC620018AC640000B4
+:106B6000AC6500048EE204C4AC620010AF86012064
+:106B700092E24E2014400037241000018EE24E3085
+:106B8000000210C02442503802E220218C83000011
+:106B9000240200121462001F000000008EE34E3039
+:106BA0008EE24E341062001B240300408C820004ED
+:106BB00024420001AC8200048EE24E348EE54E3059
+:106BC0002442000110430007000000008EE24E3412
+:106BD0002442000110A200050000000008002AFC69
+:106BE0000000000014A00005000000008F820128B2
+:106BF00024420020AF8201288F8201288C82000469
+:106C00002C42001150400013AC80000008002B12F1
+:106C1000000000008EE24E302403004024420001B8
+:106C200050430003000010218EE24E302442000148
+:106C3000AEE24E308EE24E30000210C02442503898
+:106C400002E2202124020012AC8200002402000192
+:106C5000AC8200045600000B241000018EE204E414
+:106C60003C04000124845754AFA00014AFA20010CC
+:106C70008EE606088F4702283C0500090C00240315
+:106C800034A5F006160000032402000108002B7151
+:106C9000A2E204F48EE2017024420001AEE201702F
+:106CA0008EE201708EE204E4A2E004F4AEE004F0AF
+:106CB000AEE204F88F42023C50400045AEE07274F0
+:106CC0008EE2018424420001AEE201848EE201845E
+:106CD00008002B71AEE072748EE2050424030040BC
+:106CE0002442000150430003000010218EE20504FD
+:106CF00024420001AEE205048EE205048CC30018B4
+:106D000000021080005710218C4405082402000363
+:106D10001462000F000000003C0200010057102127
+:106D2000904283B110400014000000008EE201D0B8
+:106D30008EE3524000441021AEE201D08EE201D831
+:106D400000641821306300FF08002B59AEE3524065
+:106D50008EE201CC8EE30E1000441021AEE201CC95
+:106D60008EE201D800641821306301FFAEE30E10FB
+:106D700000441021AEE201D88EE20000344200400F
+:106D800008002B71AEE200008EE2014C3C010001D4
+:106D900000370821A02083E024420001AEE2014C2C
+:106DA00008002B718EE2014C94C7000E8CC2001CAF
+:106DB0003C04000124845760AFA60014AFA2001069
+:106DC0008CC600183C0500080C00240334A50910EB
+:106DD0008FBF001C8FB0001803E0000827BD002003
+:106DE00027BDFF98AFBF0060AFBE005CAFB60058D4
+:106DF000AFB50054AFB40050AFB3004CAFB20048D1
+:106E0000AFB10044AFB000408F8301088F8201040E
+:106E1000AFA00024106203E7AFA0002C3C1E0001CD
+:106E200037DE38003C0BFFFF8F9301088E6200189D
+:106E30008F8301042443FFFE2C620014104003CF13
+:106E4000000310803C010001002208218C2257C061
+:106E500000400008000000009663000E8EE2725CA5
+:106E60008EE404F000431021AEE2725C8E63001CDD
+:106E700096E2045824840001AEE404F02463000187
+:106E80002442FFFF00621824AEE304E48F42023C78
+:106E90000082202B148003B9000000008F830120A2
+:106EA000276238002466002000C2102B50400001E9
+:106EB000276630008F82012810C200040000000005
+:106EC0008F82012414C20007000000008EE201A49A
+:106ED0000000802124420001AEE201A408002BFE44
+:106EE0008EE201A48EE204E4AC62001C8EE404B0E5
+:106EF0008EE504B42462001CAC6200082402000881
+:106F0000A462000E24020011AC620018AC64000000
+:106F1000AC6500048EE204C4AC620010AF860120B0
+:106F200092E24E2014400037241000018EE24E30D1
+:106F3000000210C02442503802E220218C8300005D
+:106F4000240200121462001F000000008EE34E3085
+:106F50008EE24E341062001B240C00408C82000430
+:106F600024420001AC8200048EE24E348EE34E30A7
+:106F700024420001104C0007000000008EE24E3455
+:106F800024420001106200050000000008002BE808
+:106F90000000000014600005000000008F8201283E
+:106FA00024420020AF8201288F8201288C820004B5
+:106FB0002C42001150400013AC80000008002BFE52
+:106FC000000000008EE24E30240C004024420001FC
+:106FD000504C0003000010218EE24E30244200018C
+:106FE000AEE24E308EE24E30000210C024425038E5
+:106FF00002E2202124020012240C0001AC820000D5
+:10700000AC8C00045600000D241000018EE204E454
+:107010003C04000124845754AFA00014AFA2001018
+:107020008EE606088F4702283C05000934A5F006C5
+:107030000C002403AFAB00388FAB00381200030AFA
+:10704000240C000108002F1900000000966C001CA1
+:10705000AFAC002C9662001E3C0C8000AFAC00244C
+:10706000AE62001C8E75001C8EE204FC8EE404FCF3
+:1070700000151900006210218C52000C92E27B98DE
+:10708000006418219476000A1440000332C2000202
+:10709000AEF27BA4AEF57B9C1040004B000080213B
+:1070A00096E2045A304200021040004700000000FF
+:1070B0008E63001C8EE204FC00032100008210217C
+:1070C0008C42000C037E1821244200220043102B26
+:1070D0001440000A240500148EE204FC00821021F2
+:1070E0008C44000CAFAB00380C002F752484000ECC
+:1070F0008FAB003808002C523050FFFF8EE204FCAA
+:10710000008210218C42000C9450000E9443001019
+:10711000944400129445001402038021020480214B
+:107120000205802194430016944400189445001AE7
+:107130000203802102048021020580219443001C67
+:107140009444001E94420020020380210204802106
+:107150000202802100101C023202FFFF0062802127
+:107160008E63001C8EE204FC001024020003290040
+:1071700000A210218C43000C3202FFFF008280210C
+:10718000037E1021246300180062182B146000098C
+:10719000000000008EE204FC00A210218C43000CD1
+:1071A000001010273C01FFFF0023082108002C6F6E
+:1071B000A42200188EE204FC00A210218C43000CD3
+:1071C00000101027A462001896E2045A00008821DB
+:1071D00030420008144000630000A0218E63001CB0
+:1071E0008EE204FC0003310000C210218C42000C2E
+:1071F000037E1821244200220043102B1440003546
+:10720000000000008EE204FC00C210218C42000C41
+:1072100024470010037E102100E2102B5040000193
+:1072200000EB38218EE204FC94F1000000C2102132
+:107230008C42000C24470016037E102100E2102B24
+:10724000144000022634FFEC00EB38218EE204FCEF
+:1072500090E3000100C210218C42000C2447001A68
+:10726000037E102100E2102B1440000202838821CB
+:1072700000EB382194E2000024E70002022288217A
+:10728000037E102100E2102B5040000100EB38215A
+:1072900094E2000024E7000202228821037E1021EC
+:1072A00000E2102B5040000100EB382194E2000076
+:1072B00024E7000202228821037E102100E2102B25
+:1072C0005040000100EB382194E2000008002CD06F
+:1072D000022288218EE204FC00C210218C43000CA3
+:1072E0008EE204FC947100108EE304FC00C21021B5
+:1072F0008C44000C00C318218C62000C2634FFEC77
+:10730000908400178EE304FC9442001A02848821C2
+:1073100000C318218C65000C8EE304FC0222882136
+:107320008EE204FC00C3182100C210218C44000C22
+:107330008C62000C94A3001C9484001E94420020D4
+:1073400002238821022488210222882100111C02A4
+:107350003222FFFF0062882100111C023222FFFF4F
+:107360000062882132C20001104000B2000000001B
+:1073700096E2045A30420001104000AE32C2008052
+:10738000104000080000000092E27B9814400005C5
+:1073900000000000240C0001A2EC7B98AEF57B9C61
+:1073A000AEF27BA48EE304FC001511000043102113
+:1073B0008C47000C037E182124E2000E0043102BA2
+:1073C0001440000800E020212405000E0C002F7559
+:1073D000AFAB00383042FFFF8FAB003808002D09FB
+:1073E0000202802194E6000024E7000294E50000F8
+:1073F00024E7000294E3000024E7000294E2000086
+:1074000024E7000294E4000024E700020206802141
+:1074100002058021020380210202802194E2000003
+:1074200094E30002020480210202802102038021F1
+:1074300000101C023202FFFF0062802100101C02BB
+:107440003202FFFF8EE47B9C0062802114950004D1
+:107450003205FFFF9662001608002D17005120210B
+:107460009662001600542021000414023083FFFFAE
+:1074700000432021008520230004140200822021E3
+:107480003084FFFF508000013404FFFF8EE27BA4B4
+:1074900024430017037E10210062102B504000018E
+:1074A000006B182190630000240200111462003167
+:1074B000240200068EE27BA4037E182124420028C9
+:1074C0000043102B14400018000000008EE27B9C4B
+:1074D00012A2000A32C201008EE27BA43C01FFFF2F
+:1074E00000220821942200280082202100041C028E
+:1074F0003082FFFF0062202132C2010014400004EC
+:107500000004102792E27B98144000020004102728
+:107510003044FFFF8EE27BA43C01FFFF00220821E4
+:1075200008002D8AA42400288EE27B9C12A2000869
+:1075300032C201008EE27BA4944200280082202106
+:1075400000041C023082FFFF0062202132C20100D1
+:10755000144000040004102792E27B9814400002BB
+:10756000000410273044FFFF8EE27BA408002D8A20
+:10757000A44400281462002F037E18218EE27BA40D
+:10758000244200320043102B144000180000000079
+:107590008EE27B9C12A2000A32C201008EE27BA422
+:1075A0003C01FFFF002208219422003200822021AA
+:1075B00000041C023082FFFF0062202132C2010061
+:1075C000144000040004102792E27B98144000024B
+:1075D000000410273044FFFF8EE27BA43C01FFFF34
+:1075E0000022082108002D8AA42400328EE27B9C10
+:1075F00012A2000832C201008EE27BA49442003243
+:107600000082202100041C023082FFFF0062202142
+:1076100032C20100144000040004102792E27B985B
+:1076200014400002000410273044FFFF8EE27BA4C8
+:10763000A44400328FAC00241180002C037E18215A
+:107640008E420000AE42FFFC2642000A0043102B8F
+:107650001440001B3403810026430004037E1021E4
+:107660000062102B1440000300602021006B1821E1
+:10767000006020218C62000024630004AE42000000
+:10768000037E10210062102B50400001006B182176
+:107690008C620000AC82000034028100A462000011
+:1076A00024630002037E10210062102B5040000171
+:1076B000006B182197AC002E08002DB4A46C0000BC
+:1076C0008E4200048E440008A643000897AC002EAA
+:1076D000A64C000AAE420000AE4400049662000EC2
+:1076E0002652FFFC24420004A662000E9662000EA1
+:1076F0008EE3725C00621821AEE3725CAFB20018D8
+:107700008EE3725CAFA3001C8EE2725C2C42003CE4
+:1077100010400004246200012403FFFE00431024F3
+:10772000AFA2001C32C200801040000C32C2010027
+:107730008EE27BA824430001000210C000571021F4
+:10774000AEE37BA88FA300188FA4001CAC437BACD6
+:10775000AC447BB008002EA0AEE0725C104000721A
+:10776000000000008EE27BA824430001000210C04C
+:1077700000571021AEE37BA88FA300188FA4001C34
+:10778000AC437BACAC447BB08EE27BA81040006382
+:1077900000004821000050218F8200F0244800089A
+:1077A000276218000102102B5040000127681000CA
+:1077B0008F8200F415020007000000008EE201B481
+:1077C0000000802124420001AEE201B408002DFA3D
+:1077D0008EE201B48F8300F02410000101571021C4
+:1077E0008C447BAC8C457BB0AC640000AC65000481
+:1077F000AF8800F01600000602EA10218EE2008831
+:1078000024420001AEE2008808002E3F8EE200888C
+:107810008C427BB08EE400E08EE500E48EE67B9C3B
+:10782000004018210000102100A3282100A3382BBC
+:1078300000822021008720218EE204FC00C9302133
+:1078400000063100AEE400E0AEE500E400C2302105
+:1078500094C2000A240C00020002114230430003CB
+:10786000106C00162862000310400005240C000173
+:10787000106C00080000000008002E3F000000000F
+:10788000240C0003106C00170000000008002E3FBD
+:10789000000000008EE200E88EE300EC24630001AB
+:1078A0002C64000100441021AEE200E8AEE300ECDD
+:1078B0008EE200E808002E3F8EE300EC8EE200F03E
+:1078C0008EE300F4246300012C64000100441021C5
+:1078D000AEE200F0AEE300F48EE200F008002E3FCE
+:1078E0008EE300F48EE200F88EE300FC24630001D6
+:1078F0002C64000100441021AEE200F8AEE300FC6D
+:107900008EE200F88EE300FC8EE27BA825290001C0
+:107910000122102B1440FFA0254A0008A2E07B980A
+:1079200008002E9FAEE07BA88F8200F0244700085D
+:107930002762180000E2102B50400001276710005A
+:107940008F8200F414E20007000000008EE201B410
+:107950000000802124420001AEE201B408002E5D47
+:107960008EE201B48F8200F0241000018FA3001872
+:107970008FA4001CAC430000AC440004AF8700F0AF
+:1079800016000007000000008EE20088244200017B
+:10799000AEE200888EE2008808002EA0AEE0725CA5
+:1079A0008EE2725C8EE400E08EE500E4240C0002BE
+:1079B000004018210000102100A3282100A3302B33
+:1079C000008220210086202100161142304300034E
+:1079D000AEE400E0AEE500E4106C00172C6200039A
+:1079E00010400005240C0001106C0008000000008D
+:1079F00008002EA0AEE0725C240C0003106C00198D
+:107A00000000000008002EA0AEE0725C8EE200E8EC
+:107A10008EE300EC246300012C640001004410217B
+:107A2000AEE200E8AEE300EC8EE200E88EE300ECAC
+:107A300008002EA0AEE0725C8EE200F08EE300F44F
+:107A4000246300012C64000100441021AEE200F028
+:107A5000AEE300F48EE200F08EE300F408002EA006
+:107A6000AEE0725C8EE200F88EE300FC246300015D
+:107A70002C64000100441021AEE200F8AEE300FCEB
+:107A80008EE200F88EE300FCAEE0725C8E62001CB9
+:107A900096E304588EE404F0244200012463FFFFBF
+:107AA0000043102424840001AEE204E4AEE404F0B8
+:107AB0008F42023C0082202B148000B000000000A6
+:107AC0008F830120276238002466002000C2102B1B
+:107AD00050400001276630008F82012810C2000448
+:107AE000000000008F82012414C200070000000083
+:107AF0008EE201A40000802124420001AEE201A434
+:107B000008002F078EE201A48EE204E4AC62001CA0
+:107B10008EE404B08EE504B42462001CAC6200085C
+:107B200024020008A462000E24020011AC620018B6
+:107B3000AC640000AC6500048EE204C4AC620010CA
+:107B4000AF86012092E24E2014400037241000013D
+:107B50008EE24E30000210C02442503802E2202152
+:107B60008C830000240200121462001F0000000039
+:107B70008EE34E308EE24E341062001B240C004027
+:107B80008C82000424420001AC8200048EE24E3458
+:107B90008EE34E3024420001104C0007000000002C
+:107BA0008EE24E3424420001106200050000000005
+:107BB00008002EF100000000146000050000000025
+:107BC0008F82012824420020AF8201288F82012861
+:107BD0008C8200042C42001150400013AC80000045
+:107BE00008002F07000000008EE24E30240C0040F9
+:107BF00024420001504C0003000010218EE24E3060
+:107C000024420001AEE24E308EE24E30000210C03F
+:107C10002442503802E2202124020012240C0001E8
+:107C2000AC820000AC8C00045600000D2410000152
+:107C30008EE204E43C04000124845754AFA00014F5
+:107C4000AFA200108EE606088F4702283C05000907
+:107C500034A5F0060C002403AFAB00388FAB00381E
+:107C600016000003240C000108002F5CA2EC04F4B1
+:107C70008EE2017024420001AEE201708EE20170DA
+:107C80008EE204E4A2E004F4AEE004F0AEE072742C
+:107C9000AEE204F88F42023C1040003800000000C1
+:107CA0008EE2018424420001AEE2018408002F5CD0
+:107CB0008EE201848EE20504240C0040244200017F
+:107CC000504C0003000010218EE205042442000104
+:107CD000AEE205048EE205048E630018240C000356
+:107CE0000002108000571021146C000F8C4405080E
+:107CF0003C02000100571021904283B11040001453
+:107D0000000000008EE201D08EE3524000441021BA
+:107D1000AEE201D08EE201D800641821306300FF8A
+:107D200008002F4FAEE352408EE201CC8EE30E10DE
+:107D300000441021AEE201CC8EE201D8006418218B
+:107D4000306301FFAEE30E1000441021AEE201D813
+:107D50008EE200003442004008002F5CAEE20000DA
+:107D60008EE2014C3C01000100370821A02083E095
+:107D700024420001AEE2014C8EE2014C8F820108E8
+:107D800024420020AF8201088F8201088F820108FF
+:107D9000276330000043102B1440000227622800A4
+:107DA000AF8201088F8301088F8201041462FC1ED8
+:107DB000000000008FBF00608FBE005C8FB60058CF
+:107DC0008FB500548FB400508FB3004C8FB2004871
+:107DD0008FB100448FB0004003E0000827BD006869
+:107DE0000005284310A0000D000030213C030001D5
+:107DF000346338003C07FFFF036310210082102B1F
+:107E00005040000100872021948200002484000259
+:107E100024A5FFFF14A0FFF800C2302100061C02B9
+:107E200030C2FFFF0062302100061C0230C2FFFF9B
+:107E30000062302103E0000830C2FFFF27BDFF8849
+:107E4000240F0001AFBF0070AFBE006CAFB600687A
+:107E5000AFB50064AFB40060AFB3005CAFB2005820
+:107E6000AFB10054AFB00050A3A00027AFAF002CBB
+:107E70008EE204D400008021304200011440002A28
+:107E8000A3A000378F8700E08F8800C48F8200E8AE
+:107E900000E220232C8210005040000124841000B6
+:107EA000000420C2008018218EE400C88EE500CCBA
+:107EB0000000102100A3282100A3302B00822021E4
+:107EC00000862021AEE400C8AEE500CC8F8300C858
+:107ED0003C02000A3442EFFF010320230044102B30
+:107EE000104000033C02000A3442F00000822021CE
+:107EF000008018218EE400C08EE500C4000010212F
+:107F000000A3282100A3302B0082202100862021FD
+:107F1000AEE400C0AEE500C4AF8800C8AF8700E49F
+:107F2000080034CCAF8700E83C0200010057102164
+:107F3000904283C01040000B000000003C14000180
+:107F40000297A0218E9483C43C13000102779821EC
+:107F50008E7383C83C1200010257902108003193B0
+:107F60008E5283CC8F8300E08F8200E410430007A1
+:107F7000000088218F8200E4241100018C4300005E
+:107F80008C440004AFA30018AFA4001C1620000E00
+:107F90003C02FFFF8F8200C4AFA200108F8200C896
+:107FA0003C04000124845870AFA200148F8600E0C6
+:107FB0008F8700E43C0500060C00240334A5F00084
+:107FC000080034CC000000008FA3001C8FB2001802
+:107FD0003074FFFF2694FFFC00621024104000580C
+:107FE000024098213C020080006210241040000AE8
+:107FF0003C0400408EE2007C24420001AEE2007CA2
+:108000008EE2007C8EE201FC24420001AEE201FC23
+:10801000080034C68EE201FC3C0600043C0B000163
+:108020003C0A00023C0500103C0900088EE200807A
+:108030003C0800203407800024420001AEE20080AA
+:108040008EE200808FA2001C0044182410660021DC
+:1080500000C3102B1440000700000000106B00113B
+:1080600000000000106A0015000000000800304900
+:10807000000420421065002300A3102B14400005CB
+:1080800000000000106900190000000008003049DD
+:108090000004204210680021000000000800304960
+:1080A000000420428EE2003424420001AEE200349B
+:1080B0008EE2003408003049000420428EE201ECD8
+:1080C00024420001AEE201EC8EE201EC08003049EE
+:1080D000000420428EE201F024420001AEE201F0F1
+:1080E0008EE201F008003049000420428EE201F4E3
+:1080F00024420001AEE201F48EE201F408003049AE
+:10810000000420428EE2003024420001AEE2003042
+:108110008EE2003008003049000420428EE201F86F
+:1081200024420001AEE201F88EE201F80004204290
+:108130001087047C000000000800300E00000000E2
+:108140003C02000100571021904283B21440008489
+:10815000240200013C03000100771821906383B3DF
+:108160001462007F3C0201008E4300000062102474
+:108170001040006F2402FFFF14620005241000016C
+:10818000964300043402FFFF1062007500000000F7
+:1081900092E204D814400072000000003C0200018A
+:1081A000005710218C4283B4284200051040002063
+:1081B000000038213C020001005710218C4283B49A
+:1081C000184000160000282196660000000520C017
+:1081D000009710219442777E1446000900971021E1
+:1081E0009443778096620002146200050097102184
+:1081F00094437782966200045062000824070001CD
+:108200003C020001005710218C4283B424A50001D8
+:1082100000A2102A5440FFEE000520C030E200FF0B
+:108220001040044000000000080030D500000000AD
+:10823000024020210C0022FE240500063044001FCD
+:10824000000428C002E510219442727C30424000B4
+:108250001440043400B710219443727E96620000EB
+:108260001462000B000418C000B710219443728000
+:108270009662000214620006000418C000B71021C4
+:10828000944372829662000410620035000418C0A4
+:1082900002E310219442727C304280001440042199
+:1082A00002E31021944B727C96670000000B28C0FB
+:1082B00000B710219442737E080030B700003021CF
+:1082C000000420C002E410219443737C02E41021D6
+:1082D000944B737C3063800014600010000B28C046
+:1082E00000B710219442737E1447FFF501602021EE
+:1082F00000B7102194437380966200025462FFF12C
+:10830000000420C000B710219443738296620004D9
+:108310005462FFEC000420C02406000130C200FFBC
+:108320001040040000000000080030D500000000EC
+:108330009743020296420000146203FA0000000014
+:108340009743020496420002146203F60000000004
+:108350009743020696420004146203F200000000F4
+:10836000924200003A030001304200010043102411
+:10837000104000742402FFFF8E63000014620004AA
+:108380003402FFFF966300041062006F240F0002A6
+:108390003C02000100571021904283B21440006A51
+:1083A000240F000392E204D854400068AFAF002CC1
+:1083B0003C020001005710218C4283B42842000582
+:1083C00010400020000038213C020001005710211D
+:1083D0008C4283B4184000160000282196660000E5
+:1083E000000520C0009710219442777E14460009B2
+:1083F0000097102194437780966200021462000572
+:10840000009710219443778296620004506200081E
+:10841000240700013C020001005710218C4283B464
+:1084200024A5000100A2102A5440FFEE000520C040
+:1084300030E200FF14400044240F0003080034C65B
+:1084400000000000024020210C0022FE240500064E
+:108450003044001F000428C002E510219442727CC1
+:1084600030424000144003AF00B710219443727EA5
+:10847000966200001462000B000418C000B71021BF
+:10848000944372809662000214620006000418C0D1
+:1084900000B7102194437282966200041062002794
+:1084A000000418C002E310219442727C3042800024
+:1084B0001440039C02E31021944B727C96670000E9
+:1084C000000B28C000B710219442737E0800313C95
+:1084D00000003021000420C002E410219443737C8A
+:1084E00002E41021944B737C306380001460001010
+:1084F000000B28C000B710219442737E1447FFF58B
+:108500000160202100B7102194437380966200021D
+:108510005462FFF1000420C000B71021944373821D
+:10852000966200045462FFEC000420C0240600019F
+:1085300030C200FF1040037B000000000800314FF4
+:10854000240F0003240F0001AFAF002C8F42026004
+:108550000054102B1040003A000000008F8300E40C
+:108560008F8200E01062000324630008AF8300E400
+:10857000AF8300E88EE400C08EE500C402801821BD
+:108580000000102100A3282100A3302B008220210D
+:1085900000862021AEE400C0AEE500C48EE20058A3
+:1085A00024420001AEE200588EE200588EE2007CC8
+:1085B00024420001AEE2007C8EE2007C8F8200E06B
+:1085C000AFA200108F8200E43C040001248458789C
+:1085D000AFA200148FA600188FA7001C3C05000650
+:1085E0000C00240334A5F003080034CC0000000084
+:1085F0008EE25240AFA200108EE252443C040001D1
+:1086000024845884AFA200148EE60E108EE70E1854
+:108610003C0500060C00240334A5F0028EE201C0E4
+:1086200024420001AEE201C08EE200008EE301C0F0
+:108630002403FFBF0043102408003470AEE20000A2
+:1086400096E204680054102B104000030000000064
+:10865000240F0001A3AF0027128003012416000796
+:1086600024150040241E0001240E00128EE2724CDC
+:108670008F43028024420001304207FF106202D380
+:108680000000000093A2002710400014000000002A
+:108690008EE352408EE252441062000926ED5244AD
+:1086A0008EE652448EE35244000211402442524866
+:1086B00002E2802124630001080031BF306B00FF1B
+:1086C00092E272481440FFCA000000008EE201E00E
+:1086D00024420001AEE201E08EE201E08EE30E10E2
+:1086E0008EE20E181062FFC226ED0E188EE60E18EE
+:1086F0008EE30E180002114024420E2002E2802177
+:1087000024630001306B01FF96E2046A30420010DE
+:1087100010400019000000009642000C340F810048
+:10872000144F0015000000003C020001005710210A
+:10873000904283C014400010000000009642000EDA
+:10874000A60200168E4200088E4300048E440000EC
+:108750002694FFFCAE42000CAE430008AE44000479
+:108760009602000E26730004240F0001A3AF003709
+:1087700034420200A602000E8E0200008E030004A6
+:108780003C04000134843800306A0007026A9823F0
+:10879000036410210262102B10400005028AA02100
+:1087A00002641023036218233C0200200043982334
+:1087B000268200072404FFF89603000A0044602480
+:1087C000006A1821006C102B104000020180382133
+:1087D00000603821AE1300188F88012024E20007C2
+:1087E0000044382427623800250900200122102B7C
+:1087F00050400001276930008F82012811220004B7
+:10880000000000008F82012415220007014018217A
+:108810008EE201A40000882124420001AEE201A4FE
+:108820000800324C8EE201A48E0400008E05000484
+:1088300000001021AD130008A507000EAD160018AA
+:10884000AD06001C00A3302B00A3282300822023A8
+:1088500000862023AD040000AD0500048EE204C0B4
+:10886000AD020010AF89012092E24E201440003387
+:10887000241100018EE24E30000210C02442503814
+:1088800002E220218C8200001456001F000000002C
+:108890008EE34E308EE24E341062001B000000006A
+:1088A0008C82000424420001AC8200048EE24E342B
+:1088B0008EE34E30244200011055000700000000F6
+:1088C0008EE24E34244200011062000500000000D8
+:1088D00008003239000000001460000500000000AC
+:1088E0008F82012824420020AF8201288F82012834
+:1088F0008C8200042C42001150400010AC8000001B
+:108900000800324C000000008EE24E30244200018C
+:1089100050550003000010218EE24E302442000129
+:10892000AEE24E308EE24E30000210C0244250388B
+:1089300002E22021AC960000AC9E00041620001834
+:108940003C0500068E0200183C0400012484589067
+:10895000AFA200108E0200008E03000434A5F009BF
+:10896000020030210C002403AFA3001493A20037AF
+:1089700010400216340F81008E4200048E4300081E
+:108980008E44000CA64F000CAE420000AE43000423
+:10899000AE4400089602001608003470A642000E8D
+:1089A00014EC0168028A1823960C000A9603000E44
+:1089B000028A1023A602000A34620004A602000EF6
+:1089C0008F88012027623800250900200122102B02
+:1089D00014400002306AFFFF276930008F820128AF
+:1089E00011220004000000008F82012415220007DC
+:1089F000240400208EE201A400008821244200010A
+:108A0000AEE201A4080032CA8EE201A48EE5724CE7
+:108A10008EE604908EE70494A504000E240400045E
+:108A2000AD100008AD0400180005294000A0182171
+:108A30000000102100E3382100E3202B00C2302188
+:108A400000C43021AD060000AD0700048EE2724C78
+:108A5000AD02001C8EE204C4AD020010AF890120FB
+:108A600092E24E2014400033241100018EE24E3079
+:108A7000000210C02442503802E220218C82000003
+:108A80001456001F000000008EE34E308EE24E347C
+:108A90001062001B000000008C82000424420001D0
+:108AA000AC8200048EE24E348EE34E30244200014C
+:108AB00010550007000000008EE24E3424420001F1
+:108AC0001062000500000000080032B7000000003E
+:108AD00014600005000000008F820128244200205D
+:108AE000AF8201288F8201288C8200042C42001161
+:108AF00050400010AC800000080032CA00000000A6
+:108B00008EE24E3024420001505500030000102137
+:108B10008EE24E3024420001AEE24E308EE24E3004
+:108B2000000210C02442503802E22021AC9600001E
+:108B3000AC9E00041620000D00000000A60C000AE8
+:108B4000A60A000E8F820100AFA200108F820104DE
+:108B50003C0400012484589C3C050006AFA200148C
+:108B60008EE6724C0800343B34A5F00B3C0100014A
+:108B700000370821A02083C0ADAB00008EE201D8F1
+:108B80008EE3724C2442FFFFAEE201D88EE201D8A0
+:108B900024630001306307FF26E2524415A2000659
+:108BA000AEE3724C8EE201D02442FFFFAEE201D070
+:108BB000080032EF8EE201D08EE201CC2442FFFFAA
+:108BC000AEE201CC8EE201CC8F4202401040007335
+:108BD000000000008EE20E1C24420001AEE20E1CDA
+:108BE0008F4302400043102B144001760000A02167
+:108BF0008F830120276238002466002000C2102BDA
+:108C000050400001276630008F82012810C2000406
+:108C1000000000008F82012414C200070000000041
+:108C20008EE201A40000882124420001AEE201A4EA
+:108C30000800334F8EE201A48EE2724CAC62001C3D
+:108C40008EE404A88EE504AC2462001CAC6200082B
+:108C500024020008A462000E24020011AC62001875
+:108C6000AC640000AC6500048EE204C4AC62001089
+:108C7000AF86012092E24E201440003324110001FF
+:108C80008EE24E30000210C02442503802E2202111
+:108C90008C820000144E001F000000008EE34E3056
+:108CA0008EE24E341062001B000000008C82000433
+:108CB00024420001AC8200048EE24E348EE34E303A
+:108CC0002442000110550007000000008EE24E34DF
+:108CD0002442000110620005000000000800333C3F
+:108CE0000000000014600005000000008F820128D1
+:108CF00024420020AF8201288F8201288C82000448
+:108D00002C42001150400010AC8000000800334F8E
+:108D1000000000008EE24E30244200015055000356
+:108D2000000010218EE24E3024420001AEE24E30AF
+:108D30008EE24E30000210C02442503802E2202160
+:108D4000AC8E0000AC9E00045620000D24110001E2
+:108D50008EE2724C3C040001248458A8AFA0001499
+:108D6000AFA200108EE6724C8F4702803C050009CE
+:108D700034A5F0080C002403AFAE00488FAE0048C5
+:108D800056200001AEE00E1C8EE201882442000154
+:108D9000AEE20188080033C88EE201888F8301208B
+:108DA000276238002466002000C2102B50400001CA
+:108DB000276630008F82012810C2000400000000E6
+:108DC0008F82012414C20007000000008EE201A47B
+:108DD0000000882124420001AEE201A4080033BA59
+:108DE0008EE201A48EE2724CAC62001C8EE404A8F8
+:108DF0008EE504AC2462001CAC620008240200086A
+:108E0000A462000E24020011AC620018AC640000E1
+:108E1000AC6500048EE204C4AC620010AF86012091
+:108E200092E24E2014400033241100018EE24E30B5
+:108E3000000210C02442503802E220218C8200003F
+:108E4000144E001F000000008EE34E308EE24E34C0
+:108E50001062001B000000008C820004244200010C
+:108E6000AC8200048EE24E348EE34E302442000188
+:108E700010550007000000008EE24E34244200012D
+:108E80001062000500000000080033A70000000089
+:108E900014600005000000008F8201282442002099
+:108EA000AF8201288F8201288C8200042C4200119D
+:108EB00050400010AC800000080033BA00000000F1
+:108EC0008EE24E3024420001505500030000102174
+:108ED0008EE24E3024420001AEE24E308EE24E3041
+:108EE000000210C02442503802E22021AC8E000063
+:108EF000AC9E00041620000D000000008EE2724CB3
+:108F00003C040001248458A8AFA00014AFA20010B4
+:108F10008EE6724C8F4702803C05000934A5F008AC
+:108F20000C002403AFAE00488FAE00488EE20174FF
+:108F300024420001AEE201748EE201740800346E36
+:108F40000000A021960C000A0183102B5440000160
+:108F500001801821A603000A8F88012027623800AB
+:108F6000250900200122102B504000012769300004
+:108F70008F82012811220004000000008F8201244A
+:108F800015220007240400208EE201A4000088219D
+:108F900024420001AEE201A40800342F8EE201A4B5
+:108FA0008EE5724C8EE604908EE70494A504000EC4
+:108FB00024040004AD100008AD0400180005294089
+:108FC00000A018210000102100E3382100E3202B2D
+:108FD00000C2302100C43021AD060000AD070004FE
+:108FE0008EE2724CAD02001C8EE204C4AD02001091
+:108FF000AF89012092E24E20144000332411000179
+:109000008EE24E30000210C02442503802E220218D
+:109010008C8200001456001F000000008EE34E30CA
+:109020008EE24E341062001B000000008C820004AF
+:1090300024420001AC8200048EE24E348EE34E30B6
+:109040002442000110550007000000008EE24E345B
+:109050002442000110620005000000000800341CDA
+:109060000000000014600005000000008F8201284D
+:1090700024420020AF8201288F8201288C820004C4
+:109080002C42001150400010AC8000000800342F2A
+:10909000000000008EE24E302442000150550003D3
+:1090A000000010218EE24E3024420001AEE24E302C
+:1090B0008EE24E30000210C02442503802E22021DD
+:1090C000AC960000AC9E00041620001D00000000BD
+:1090D000A60C000A8F820100AFA200108F8201044B
+:1090E0003C0400012484589C3C050006AFA20014F7
+:1090F0008EE6724C34A5F00D0C00240302003821DA
+:1091000093A2003710400031340F81008E420004DA
+:109110008E4300088E44000CA64F000CAE420000A7
+:10912000AE430004AE44000896020016A642000EAC
+:109130009602000E3042FDFF08003470A602000EB9
+:109140008EE201D82442FFFFAEE201D88EE201D8C0
+:109150008EE201CC3C04001F3C01000100370821D5
+:10916000A03E83C02442FFFFAEE201CC9603000A7A
+:109170003484FFFF8EE201CC006A1821026398213B
+:109180000093202B108000033C02FFF534421000B6
+:1091900002629821ADAB00008EE2724C24420001C5
+:1091A000304207FFAEE2724C8F4202401040000492
+:1091B0000283A0238EE20E1C24420001AEE20E1CAC
+:1091C000A3A000271680FD290000000012800024C3
+:1091D000000000003C01000100370821AC3483C4CA
+:1091E0003C01000100370821AC3383C83C01000179
+:1091F00000370821AC3283CC93A20037104000081E
+:10920000000000003C020001005710218C4283CC7A
+:10921000244200043C01000100370821AC2283CC29
+:109220008EE2724C8F43028024420001304207FFDD
+:1092300014620006000000008EE201C42442000116
+:10924000AEE201C4080034CC8EE201C48EE201BC5F
+:1092500024420001AEE201BC080034CC8EE201BC25
+:1092600097A4001E2484FFFC008018218EE400C017
+:109270008EE500C40000102100A3282100A3302B9C
+:109280000082202100862021AEE400C0AEE500C4AB
+:109290008FAF002C2402000211E2000F29E200032C
+:1092A000144000172402000315E20015000000001E
+:1092B0008EE200D08EE300D4246300012C64000110
+:1092C00000441021AEE200D0AEE300D48EE200D024
+:1092D000080034C68EE300D48EE200D88EE300DCB2
+:1092E000246300012C64000100441021AEE200D888
+:1092F000AEE300DC8EE200D8080034C68EE300DC6A
+:109300008EE200C88EE300CC246300012C640001CF
+:1093100000441021AEE200C8AEE300CC8EE200C8EB
+:109320008EE300CC8F8300E48F8200E010620003A4
+:1093300024630008AF8300E4AF8300E88FBF0070B0
+:109340008FBE006C8FB600688FB500648FB400606C
+:109350008FB3005C8FB200588FB100548FB00050B3
+:1093600003E0000827BD007827BDFFB0AFB500447B
+:109370000000A821AFB0003000008021AFBF004C3A
+:10938000AFB60048AFB40040AFB3003CAFB2003856
+:10939000AFB100348EE204D4241400013042000145
+:1093A0001440002A0000B0218F8700E08F8800C49D
+:1093B0008F8200E800E220232C8210005040000140
+:1093C00024841000000420C2008018218EE400C80C
+:1093D0008EE500CC0000102100A3282100A3302B33
+:1093E0000082202100862021AEE400C8AEE500CC3A
+:1093F0008F8300C83C02000A3442EFFF01032023A0
+:109400000044102B104000033C02000A3442F000DC
+:1094100000822021008018218EE400C08EE500C467
+:109420000000102100A3282100A3302B008220215E
+:1094300000862021AEE400C0AEE500C4AF8800C8BD
+:10944000AF8700E408003850AF8700E83C02000115
+:1094500000571021904283C01040000B0000000014
+:109460003C130001027798218E7383C43C110001E4
+:10947000023788218E3183C83C12000102579021A7
+:10948000080036E88E5283CC8F8300E08F8200E4A0
+:1094900010430007000048218F8200E424090001E6
+:1094A0008C4300008C440004AFA30018AFA4001C40
+:1094B0001520000E3C02FFFF8F8200C4AFA20010F7
+:1094C0008F8200C83C04000124845870AFA20014AD
+:1094D0008F8600E08F8700E43C0500060C00240323
+:1094E00034A5F00008003850000000008FA3001CD5
+:1094F0008FB200183073FFFF2673FFFC0062102448
+:1095000010400058024088213C0200800062102474
+:109510001040000A3C0400408EE2007C244200011E
+:10952000AEE2007C8EE2007C8EE201FC244200016F
+:10953000AEE201FC0800384A8EE201FC3C06000461
+:109540003C0B00013C0A00023C0500103C090008ED
+:109550008EE200803C080020340780002442000195
+:10956000AEE200808EE200808FA2001C004418242E
+:109570001066002100C3102B1440000700000000FB
+:10958000106B001100000000106A001500000000C0
+:1095900008003592000420421065002300A3102B20
+:1095A00014400005000000001069001900000000D0
+:1095B00008003592000420421068002100000000DD
+:1095C00008003592000420428EE20034244200015B
+:1095D000AEE200348EE200340800359200042042EE
+:1095E0008EE201EC24420001AEE201EC8EE201ECDD
+:1095F00008003592000420428EE201F0244200016E
+:10960000AEE201F08EE201F0080035920004204243
+:109610008EE201F424420001AEE201F48EE201F494
+:1096200008003592000420428EE2003024420001FE
+:10963000AEE200308EE20030080035920004204295
+:109640008EE201F824420001AEE201F88EE201F858
+:1096500000042042108702B70000000008003557C0
+:10966000000000003C02000100571021904283B22C
+:1096700014400084240200013C03000100771821FB
+:10968000906383B31462007F3C0201008E430000AC
+:10969000006210241040006F2402FFFF14620005D6
+:1096A00024100001964300043402FFFF106200758D
+:1096B0000000000092E204D8144000720000000094
+:1096C0003C020001005710218C4283B4284200055F
+:1096D00010400020000038213C02000100571021FA
+:1096E0008C4283B418400016000028219626000002
+:1096F000000520C0009710219442777E144600098F
+:10970000009710219443778096220002146200058E
+:10971000009710219443778296220004506200083B
+:10972000240700013C020001005710218C4283B441
+:1097300024A5000100A2102A5440FFEE000520C01D
+:1097400030E200FF1040027B000000000800361EDF
+:1097500000000000024020210C0022FE240500062B
+:109760003044001F000428C002E510219442727C9E
+:10977000304240001440026F00B710219443727EC3
+:10978000962200001462000B000418C000B71021DC
+:10979000944372809622000214620006000418C0EE
+:1097A00000B71021944372829622000410620035A3
+:1097B000000418C002E310219442727C3042800001
+:1097C0001440025C02E310219448727C962700004A
+:1097D000000828C000B710219442737E08003600AC
+:1097E00000003021000420C002E410219443737C67
+:1097F00002E410219448737C3063800014600010F0
+:10980000000828C000B710219442737E1447FFF56A
+:109810000100202100B7102194437380962200029A
+:109820005462FFF1000420C000B7102194437382FA
+:10983000962200045462FFEC000420C024060001BC
+:1098400030C200FF1040023B000000000800361E3E
+:1098500000000000974302029642000014620235A5
+:109860000000000097430204964200021462023195
+:109870000000000097430206964200041462022D85
+:1098800000000000924200003A0300013042000153
+:1098900000431024104000742402FFFF8E230000B8
+:1098A000146200043402FFFF962300041062006F6C
+:1098B000241400023C02000100571021904283B2A0
+:1098C0001440006A2414000392E204D81440006794
+:1098D000000000003C020001005710218C4283B4BC
+:1098E0002842000510400020000038213C02000101
+:1098F000005710218C4283B4184000160000282124
+:1099000096260000000520C0009710219442777E23
+:109910001446000900971021944377809622000294
+:109920001462000500971021944377829622000468
+:1099300050620008240700013C020001005710217A
+:109940008C4283B424A5000100A2102A5440FFEEEB
+:10995000000520C030E200FF14400044241400033E
+:109960000800384A00000000024020210C0022FEBE
+:10997000240500063044001F000428C002E5102121
+:109980009442727C30424000144001EA00B710213A
+:109990009443727E962200001462000B000418C0EB
+:1099A00000B71021944372809622000214620006D0
+:1099B000000418C000B7102194437282962200045C
+:1099C00010620027000418C002E310219442727C48
+:1099D00030428000144001D702E310219448727C89
+:1099E00096270000000828C000B710219442737E1B
+:1099F0000800368500003021000420C002E4102158
+:109A00009443737C02E410219448737C306380009B
+:109A100014600010000828C000B710219442737E23
+:109A20001447FFF50100202100B7102194437380F3
+:109A3000962200025462FFF1000420C000B71021FA
+:109A400094437382962200045462FFEC000420C009
+:109A50002406000130C200FF104001B600000000E3
+:109A60000800369824140003241400018F42026079
+:109A70000053102B10400049000000008F8300E4C9
+:109A80008F8200E01062000324630008AF8300E4CB
+:109A9000AF8300E88EE400C08EE500C402601821A8
+:109AA0000000102100A3282100A3302B00822021D8
+:109AB00000862021AEE400C0AEE500C48EE200586E
+:109AC00024420001AEE200588EE200588EE2007C93
+:109AD00024420001AEE2007C8EE2007C8F8200E036
+:109AE000AFA200108F8200E43C0400012484587867
+:109AF000AFA200148FA600188FA7001C3C0500061B
+:109B00000C00240334A5F0030800385000000000C6
+:109B10008EE25240AFA200108EE252443C0400019B
+:109B200024845884AFA200148EE60E108EE70E181F
+:109B30000C00240334A5F0028EE201C0244200018F
+:109B4000AEE201C08EE200008EE301C02403FFBF3D
+:109B500000431024080037F8AEE200008EE25240C5
+:109B6000AFA200108EE252443C04000124845884C9
+:109B7000AFA200148EE60E108EE70E183C0500060C
+:109B80000C00240334A5F0028EE201C0244200013F
+:109B9000AEE201C0080037F88EE201C096E2046828
+:109BA0000053102B544000013C158000126001311D
+:109BB0003C0C001F358CFFFF8EE2724C8F430280FD
+:109BC00024420001304207FF10620108000000003B
+:109BD00012A00014000000008EE352408EE25244B6
+:109BE0001062000926EE52448EEB52448EE352443A
+:109BF000000211402442524802E280212463000105
+:109C000008003712306800FF92E272481440FFC02B
+:109C10003C0500068EE201E024420001AEE201E0D4
+:109C20008EE201E08EE30E108EE20E181062FFCB82
+:109C300026EE0E188EEB0E180000A8218EE30E18EB
+:109C40000002114024420E2002E280212463000120
+:109C5000306801FF96E2046A30420010104000179D
+:109C6000340281009643000C1462001400000000CE
+:109C70003C02000100571021904283C01440000FA5
+:109C8000000000009642000EA60200168E42000858
+:109C90008E4300048E4400002673FFFCAE42000C8D
+:109CA000AE430008AE4400049602000E26310004C4
+:109CB0002416000134420200A602000E9603000A98
+:109CC000026050210073102B1040000202606821D6
+:109CD000006050212D42003D1040002A0000382134
+:109CE0009623000C2402080054620027AE110018CD
+:109CF0003C02000100571021904283C054400022D2
+:109D0000AE110018262200170182102B10400013FC
+:109D1000000000003C02FFF5005110219042101796
+:109D2000384300062C630001384200112C42000128
+:109D30000062182510600013262200100182102BEB
+:109D40001040000E000000003C07FFF500F1382134
+:109D500094E710100800375E24E7000E92220017E7
+:109D6000384300062C630001384200112C420001E8
+:109D70000062182550600004AE11001896270010EC
+:109D800024E7000EAE1100183C020001005710211C
+:109D9000904283C00002102B14E0000200024EC06B
+:109DA000014038218F83012027623800246600207B
+:109DB00000C2102B50400001276630008F8201281E
+:109DC00010C20004000000008F82012414C20007AA
+:109DD0002402000B8EE201A400004821244200016D
+:109DE000AEE201A4080037BF8EE201A48E04000099
+:109DF0008E050004AC62001801751025004910257D
+:109E0000AC710008A467000EAC62001CAC640000DA
+:109E1000AC6500048EE204C0AC620010AF86012085
+:109E200092E24E2014400038240900018EE24E30A8
+:109E3000000210C02442503802E220218C8300002E
+:109E40002402000714620020000000008EE34E3060
+:109E50008EE24E341062001C000000008C82000470
+:109E600024420001AC8200048EE34E348EE54E3075
+:109E7000240200402463000110620007000000007B
+:109E80008EE24E342442000110A2000500000000C2
+:109E9000080037A90000000014A000050000000021
+:109EA0008F82012824420020AF8201288F8201285E
+:109EB0008C8200042C42001150400013AC80000042
+:109EC000080037BF000000008EE24E30240300403F
+:109ED0002442000150430003000010218EE24E3066
+:109EE00024420001AEE24E308EE24E30000210C03D
+:109EF0002442503802E2202124020007AC820000F4
+:109F000024020001AC820004152000183C05000664
+:109F10008E0200183C04000124845890AFA2001067
+:109F20008E0200008E03000434A5F00902003021E7
+:109F30000C002403AFA3001432C200FF1040002B1A
+:109F4000340281008E4300048E4400088E45000CCC
+:109F5000A642000CAE430000AE440004AE4500082B
+:109F600096020016080037F8A642000E154D000AAA
+:109F7000000000009602000EA613000A34420004FE
+:109F8000A602000E3C01000100370821A02083C07A
+:109F9000080037F6000098219604000A0093102B61
+:109FA00010400002026018210080182124020001E4
+:109FB000A603000A3C01000100370821A02283C04B
+:109FC0009604000A022488210191102B10400003FE
+:109FD0003C02FFF5344210000222882102649823DB
+:109FE0000000A8211660FEF4ADC800001260002138
+:109FF00032C200FF3C01000100370821AC3383C4AA
+:10A000003C01000100370821AC3183C83C0100014C
+:10A010000037082110400008AC3283CC3C0200011C
+:10A02000005710218C4283CC244200043C010001E3
+:10A0300000370821AC2283CC8EE2724C8F43028021
+:10A040002442000114620006000000008EE201C4F8
+:10A0500024420001AEE201C4080038508EE201C47F
+:10A060008EE201BC24420001AEE201BC080038507F
+:10A070008EE201BC97A4001E2484FFFC00801821FE
+:10A080008EE400C08EE500C40000102100A328214A
+:10A0900000A3302B00822021008620212402000210
+:10A0A000AEE400C0AEE500C41282000F2A820003B5
+:10A0B000144000172402000316820015000000005F
+:10A0C0008EE200D08EE300D4246300012C640001F2
+:10A0D00000441021AEE200D0AEE300D48EE200D006
+:10A0E0000800384A8EE300D48EE200D88EE300DC0C
+:10A0F000246300012C64000100441021AEE200D86A
+:10A10000AEE300DC8EE200D80800384A8EE300DCC3
+:10A110008EE200C88EE300CC246300012C640001B1
+:10A1200000441021AEE200C8AEE300CC8EE200C8CD
+:10A130008EE300CC8F8300E48F8200E01062000386
+:10A1400024630008AF8300E4AF8300E88FBF004CB6
+:10A150008FB600488FB500448FB400408FB3003CE9
+:10A160008FB200388FB100348FB0003003E00008A8
+:10A1700027BD005027BDFF90AFB600600000B021A2
+:10A18000AFBF0068AFBE0064AFB5005CAFB40058AD
+:10A19000AFB30054AFB20050AFB1004CAFB0004805
+:10A1A0008EE204D400008821241500013042000111
+:10A1B0001440002AA3A0002F8F8700E08F8800C4DE
+:10A1C0008F8200E800E220232C8210005040000122
+:10A1D00024841000000420C2008018218EE400C8EE
+:10A1E0008EE500CC0000102100A3282100A3302B15
+:10A1F0000082202100862021AEE400C8AEE500CC1C
+:10A200008F8300C83C02000A3442EFFF0103202381
+:10A210000044102B104000033C02000A3442F000BE
+:10A2200000822021008018218EE400C08EE500C449
+:10A230000000102100A3282100A3302B0082202140
+:10A2400000862021AEE400C0AEE500C4AF8800C89F
+:10A25000AF8700E408003C5BAF8700E83C020001E8
+:10A2600000571021904283C01040000B00000000F6
+:10A270003C130001027798218E7383C43C100001C7
+:10A28000021780218E1083C83C12000102579021D2
+:10A2900008003A598E5283CC8F8300E08F8200E40D
+:10A2A00010430007000038218F8200E424070001DA
+:10A2B0008C4300008C440004AFA30018AFA4001C22
+:10A2C00014E0000E3C02FFFF8F8200C4AFA200101A
+:10A2D0008F8200C83C040001248458B4AFA200144B
+:10A2E0008F8600E08F8700E43C0500060C00240305
+:10A2F00034A5F20008003C5B000000008FA3001CA6
+:10A300008FB200183073FFFF2673FFFC0062102429
+:10A3100010400058024080213C020080006210245E
+:10A320001040000A3C0400408EE2007C2442000100
+:10A33000AEE2007C8EE2007C8EE201FC2442000151
+:10A34000AEE201FC08003C558EE201FC3C06000434
+:10A350003C0B00013C0A00023C0500103C090008CF
+:10A360008EE200803C080020340780002442000177
+:10A37000AEE200808EE200808FA2001C0044182410
+:10A380001066002100C3102B1440000700000000DD
+:10A39000106B001100000000106A001500000000A2
+:10A3A00008003916000420421065002300A3102B7A
+:10A3B00014400005000000001069001900000000B2
+:10A3C0000800391600042042106800210000000037
+:10A3D00008003916000420428EE2003424420001B5
+:10A3E000AEE200348EE20034080039160004204248
+:10A3F0008EE201EC24420001AEE201EC8EE201ECBF
+:10A4000008003916000420428EE201F024420001C7
+:10A41000AEE201F08EE201F008003916000420429D
+:10A420008EE201F424420001AEE201F48EE201F476
+:10A4300008003916000420428EE200302442000158
+:10A44000AEE200308EE200300800391600042042EF
+:10A450008EE201F824420001AEE201F88EE201F83A
+:10A46000000420421087033E00000000080038DB93
+:10A47000000000003C02000100571021904283B20E
+:10A4800014400084240200013C03000100771821DD
+:10A49000906383B31462007F3C0201008E4300008E
+:10A4A000006210241040006F2402FFFF14620005B8
+:10A4B00024110001964300043402FFFF106200756E
+:10A4C0000000000092E204D8144000720000000076
+:10A4D0003C020001005710218C4283B42842000541
+:10A4E00010400020000038213C02000100571021DC
+:10A4F0008C4283B418400016000028219606000004
+:10A50000000520C0009710219442777E1446000970
+:10A510000097102194437780960200021462000590
+:10A52000009710219443778296020004506200083D
+:10A53000240700013C020001005710218C4283B423
+:10A5400024A5000100A2102A5440FFEE000520C0FF
+:10A5500030E200FF1040030200000000080039A2B2
+:10A5600000000000024020210C0022FE240500060D
+:10A570003044001F000428C002E510219442727C80
+:10A5800030424000144002F600B710219443727E1E
+:10A59000960200001462000B000418C000B71021DE
+:10A5A000944372809602000214620006000418C0F0
+:10A5B00000B71021944372829602000410620035A5
+:10A5C000000418C002E310219442727C30428000E3
+:10A5D000144002E302E31021944D727C96070000C0
+:10A5E000000D28C000B710219442737E0800398402
+:10A5F00000003021000420C002E410219443737C49
+:10A6000002E41021944D737C3063800014600010CC
+:10A61000000D28C000B710219442737E1447FFF547
+:10A6200001A0202100B710219443738096020002FC
+:10A630005462FFF1000420C000B7102194437382DC
+:10A64000960200045462FFEC000420C024060001BE
+:10A6500030C200FF104002C200000000080039A212
+:10A66000000000009743020296420000146202BC00
+:10A67000000000009743020496420002146202B8F0
+:10A68000000000009743020696420004146202B4E0
+:10A6900000000000924200003A2300013042000115
+:10A6A00000431024104000742402FFFF8E030000BA
+:10A6B000146200043402FFFF960300041062006F6E
+:10A6C000241500023C02000100571021904283B281
+:10A6D0001440006A2415000392E204D81440006775
+:10A6E000000000003C020001005710218C4283B49E
+:10A6F0002842000510400020000038213C020001E3
+:10A70000005710218C4283B4184000160000282105
+:10A7100096060000000520C0009710219442777E25
+:10A720001446000900971021944377809602000296
+:10A73000146200050097102194437782960200046A
+:10A7400050620008240700013C020001005710215C
+:10A750008C4283B424A5000100A2102A5440FFEECD
+:10A76000000520C030E200FF14400044241500031F
+:10A7700008003C5500000000024020210C0022FE91
+:10A78000240500063044001F000428C002E5102103
+:10A790009442727C304240001440027100B7102194
+:10A7A0009443727E960200001462000B000418C0ED
+:10A7B00000B71021944372809602000214620006D2
+:10A7C000000418C000B7102194437282960200045E
+:10A7D00010620027000418C002E310219442727C2A
+:10A7E000304280001440025E02E31021944D727CDE
+:10A7F00096070000000D28C000B710219442737E18
+:10A8000008003A0900003021000420C002E41021B1
+:10A810009443737C02E41021944D737C3063800078
+:10A8200014600010000D28C000B710219442737E00
+:10A830001447FFF501A0202100B710219443738035
+:10A84000960200025462FFF1000420C000B71021FC
+:10A8500094437382960200045462FFEC000420C00B
+:10A860002406000130C200FF1040023D000000003D
+:10A8700008003A1C24150003241500018F420260D1
+:10A880000053102B10400036000000008F8300E4BE
+:10A890008F8200E01062000324630008AF8300E4AD
+:10A8A000AF8300E88EE400C08EE500C4026018218A
+:10A8B0000000102100A3282100A3302B00822021BA
+:10A8C00000862021AEE400C0AEE500C48EE2005850
+:10A8D00024420001AEE200588EE200588EE2007C75
+:10A8E00024420001AEE2007C8EE2007C8F8200E018
+:10A8F000AFA200108F8200E43C040001248458C001
+:10A90000AFA200148FA600188FA7001C3C050006FC
+:10A910000C00240334A5F20308003C5B0000000097
+:10A920008EE25240AFA200108EE252443C0400017D
+:10A93000248458CCAFA200148EE60E108EE70E18B9
+:10A940003C0500060C00240334A5F2028EE201C08F
+:10A9500024420001AEE201C008003C028EE201C0C8
+:10A9600096E204680053102B544000013C1680000E
+:10A97000126001CB3C0E001F35CEFFFF3C0FFFF5F0
+:10A9800035EF1000241E00408EE2724C8F4302808F
+:10A9900024420001304207FF1062019E00000000C7
+:10A9A00012C00012000000008EE352408EE25244BA
+:10A9B0001062000A26F852448EF45244AFB80024C4
+:10A9C0008EE35244000211402442524802E28821A0
+:10A9D0002463000108003A85306D00FF8EE201E03B
+:10A9E00024420001AEE201E08EE201E08EE30E10AF
+:10A9F0008EE20E181062FFCA26F80E188EF40E189A
+:10AA00000000B021AFB800248EE30E180002114000
+:10AA100024420E2002E2882124630001306D01FFF0
+:10AA200096E2046A3042001010400018340281009F
+:10AA30009643000C14620015000000003C02000167
+:10AA400000571021904283C0144000100000000005
+:10AA50009642000EA62200168E4200088E43000485
+:10AA60008E4400002673FFFCAE42000CAE4300088B
+:10AA7000AE4400049622000E2610000424180001A3
+:10AA8000A3B8002F34420200A622000E8E2200003E
+:10AA90008E2300043C04000134843800020030217D
+:10AAA000306A0007020A8023036410210202102B7F
+:10AAB00010400005026A9821020410230362182343
+:10AAC0003C02002000438023266200079623000AF0
+:10AAD0002418FFF80058C824006A18210079102BA8
+:10AAE00010400002032060210060602101801821D5
+:10AAF000246200072418FFF800586024026C102B11
+:10AB000014400004019328230183282308003AC33A
+:10AB100000C3102100D31021004A202301C4102BB0
+:10AB200054400001008F202125420040004C102B92
+:10AB3000144000350000582194C3000C2402080082
+:10AB400054620032AE2600183C020001005710216A
+:10AB5000904283C05440002DAE26001824C2001736
+:10AB600001C2102B10400013000000003C02FFF552
+:10AB70000046102190421017384300062C63000154
+:10AB8000384200112C4200010062182510600014A8
+:10AB900024C2001001C2102B1040000E0000000063
+:10ABA0003C0BFFF501665821956B101008003AF434
+:10ABB0002562000E90C20017384300062C63000186
+:10ABC000384200112C420001006218251060000577
+:10ABD0000160182194CB00102562000E004A582114
+:10ABE00001601821246200072418FFF80058582437
+:10ABF00000C31021004A202301C4102B1040000282
+:10AC000001632823008F2021AE2600183C0200019A
+:10AC100000571021904283C00002102B000216C082
+:10AC200015600002AFA2004401805821308200016B
+:10AC3000104000070000402190880000248400019B
+:10AC400001C4102B1040000224A5FFFF008F20211B
+:10AC500050A0001200081C022CA20002544000095F
+:10AC600024A5FFFF948200002484000201024021F9
+:10AC700001C4102B1040000624A5FFFE08003B2154
+:10AC8000008F20219082000000021200010240216A
+:10AC900014A0FFF22CA2000200081C023102FFFFE8
+:10ACA000006240213108FFFF0140282111400011BE
+:10ACB000020020212CA200025440000924A5FFFF1D
+:10ACC00094820000248400020102402101C4102B60
+:10ACD0001040000624A5FFFE08003B38008F20210D
+:10ACE00090820000000212000102402114A0FFF235
+:10ACF0002CA2000200081C023102FFFF006240216A
+:10AD000000081C023102FFFF8F89012000624021F0
+:10AD100027623800252300200062102B1440000217
+:10AD20003108FFFF276330008F8201281062000482
+:10AD3000000000008F8201241462000701402821D6
+:10AD40008EE201A40000382124420001AEE201A4F9
+:10AD500008003BC98EE201A48E2600008E27000465
+:10AD6000000814003448000BAD300008A52B000E7D
+:10AD7000AD2800188FB8004400002021029610254D
+:10AD800000581025AD22001C00E5102B00E53823EB
+:10AD900000C4302300C23023AD260000AD270004DC
+:10ADA0008EE204C0AD220010AF83012092E24E205B
+:10ADB0001440005F240700012502FFEE2C42000230
+:10ADC00014400003240200111502002400000000BA
+:10ADD0008EE24E30000210C02442503802E22021A0
+:10ADE0008C830000240200121462000F0000000097
+:10ADF0008EE34E308EE24E341062000B00000000F5
+:10AE00008C82000424420001AC8200048EE24E34A5
+:10AE10008EE34E3024420001105E002A0000000044
+:10AE200008003BA8000000008EE24E3024420001E2
+:10AE3000505E0003000010218EE24E3024420001DB
+:10AE4000AEE24E308EE24E30000210C02442503846
+:10AE500002E2202108003BC6240200128EE24E309E
+:10AE6000000210C02442503802E220218C830000EE
+:10AE7000240200071462001F000000008EE34E3021
+:10AE80008EE24E341062001B000000008C82000431
+:10AE900024420001AC8200048EE24E348EE34E3038
+:10AEA00024420001105E0007000000008EE24E34D4
+:10AEB00024420001106200050000000008003BB4BD
+:10AEC0000000000014600005000000008F820128CF
+:10AED00024420020AF8201288F8201288C82000446
+:10AEE0002C42001150400012AC80000008003BC909
+:10AEF000000000008EE24E3024420001505E00034C
+:10AF0000000010218EE24E3024420001AEE24E30AD
+:10AF10008EE24E30000210C02442503802E220215E
+:10AF200024020007AC82000024020001AC8200046D
+:10AF300014E000193C0500063C04000124845890EC
+:10AF40008E22001834A5F209AFA200108E22000054
+:10AF50008E23000402203021016038210C002403DC
+:10AF6000AFA3001493A2002F1040002A34028100E6
+:10AF70008E4300048E4400088E45000CA642000C4F
+:10AF8000AE430000AE440004AE4500089622001611
+:10AF900008003C02A642000E1599000A026A182316
+:10AFA0009622000EA623000A34420004A622000EB8
+:10AFB0003C01000100370821A02083C008003BFFAE
+:10AFC000000098219624000A0083102B54400001B1
+:10AFD0000080182124020001A623000A3C01000180
+:10AFE00000370821A02283C09622000A004A1821B7
+:10AFF0000203802101D0102B54400001020F802158
+:10B00000026398230000B0218FB800241660FE5E12
+:10B01000AF0D000012600022000000003C010001A2
+:10B0200000370821AC3383C43C01000100370821FC
+:10B03000AC3083C83C01000100370821AC3283CC1E
+:10B0400093A2002F10400008000000003C02000105
+:10B05000005710218C4283CC244200043C010001A3
+:10B0600000370821AC2283CC8F4302808EE2724CE1
+:10B0700014620006000000008EE201C424420001B8
+:10B08000AEE201C408003C5B8EE201C48EE201BC6A
+:10B0900024420001AEE201BC08003C5B8EE201BC30
+:10B0A00097A4001E2484FFFC008018218EE400C0B9
+:10B0B0008EE500C40000102100A3282100A3302B3E
+:10B0C000008220210086202124020002AEE400C07C
+:10B0D000AEE500C412A2000F2AA20003144000171C
+:10B0E0002402000316A20015000000008EE200D02A
+:10B0F0008EE300D4246300012C640001004410217D
+:10B10000AEE200D0AEE300D48EE200D008003C55A1
+:10B110008EE300D48EE200D88EE300DC24630001CD
+:10B120002C64000100441021AEE200D8AEE300DC44
+:10B130008EE200D808003C558EE300DC8EE200C8A9
+:10B140008EE300CC246300012C6400010044102134
+:10B15000AEE200C8AEE300CC8EE200C88EE300CCC5
+:10B160008F8300E48F8200E01062000324630008F4
+:10B17000AF8300E4AF8300E88FBF00688FBE006438
+:10B180008FB600608FB5005C8FB400588FB3005449
+:10B190008FB200508FB1004C8FB0004803E0000820
+:10B1A00027BD007027BDFFE0AFBF00188EE30E146F
+:10B1B0008EE20E0C10620074000000008EE30E0C94
+:10B1C0008EE20E1400622023048200012484020017
+:10B1D0008EE30E188EE20E140043102B1440000470
+:10B1E000240202008EE30E1408003C7D0043182365
+:10B1F0008EE20E188EE30E14004310232443FFFF4B
+:10B20000008048210069102A544000010060482154
+:10B210008F8701002762300024E800200102102BF4
+:10B2200050400001276828008F82010811020004A5
+:10B23000000000008F8201041502000700001021A9
+:10B240008EE201A80000202124420001AEE201A804
+:10B2500008003CBF8EE201A88EE40E1400042140D9
+:10B26000008018218EE404608EE5046400A3282188
+:10B2700000A3302B0082202100862021ACE40000B6
+:10B28000ACE500048EE30E1400091140A4E2000EA8
+:10B2900024020002ACE200180003194024630E20CF
+:10B2A00002E31021ACE200088EE20E14ACE2001CB6
+:10B2B0008EE204CCACE20010AF88010092E204EC14
+:10B2C00014400011240400018EE24E2824030040A3
+:10B2D0002442000150430003000010218EE24E285A
+:10B2E00024420001AEE24E288EE24E28000210C039
+:10B2F00024424E3802E2182124020002AC6200000F
+:10B3000024020001AC6200041480000E24030040FB
+:10B310008EE20E14AFA200108EE20E183C0500075C
+:10B32000AFA200148EE60E0C8EE70E103C04000156
+:10B33000248458D40C00240334A5F00108003CDD1B
+:10B34000000000008EE2050024420001504300038B
+:10B35000000010218EE2050024420001AEE205004B
+:10B360008EE205000002108000571021AC4905084C
+:10B370008EE20E1400491021304201FFAEE20E149D
+:10B380008EE30E148EE20E0C146200050000000025
+:10B390008F8200602403FDFF00431024AF82006011
+:10B3A0008FBF001803E0000827BD002027BDFFE085
+:10B3B000AFBF00188EE3523C8EE252381062007428
+:10B3C000000000008EE352388EE2523C00622023DF
+:10B3D00004820001248401008EE352448EE2523C38
+:10B3E0000043102B14400004240201008EE3523C61
+:10B3F00008003CFF004318238EE252448EE3523C87
+:10B40000004310232443FFFF008048210069102AD5
+:10B4100054400001006048218F87010027623000FE
+:10B4200024E800200102102B50400001276828006A
+:10B430008F82010811020004000000008F820104C5
+:10B4400015020007000010218EE201A80000202153
+:10B4500024420001AEE201A808003D418EE201A8AD
+:10B460008EE4523C00042140008018218EE40470D8
+:10B470008EE5047400A3282100A3302B0082202134
+:10B4800000862021ACE40000ACE500048EE3523CD1
+:10B4900000091140A4E2000E24020003ACE20018EF
+:10B4A000000319402463524802E31021ACE2000873
+:10B4B0008EE2523CACE2001C8EE204CCACE2001006
+:10B4C000AF88010092E204EC144000112404000152
+:10B4D0008EE24E2824030040244200015043000322
+:10B4E000000010218EE24E2824420001AEE24E28D8
+:10B4F0008EE24E28000210C024424E3802E218218B
+:10B5000024020003AC62000024020001AC620004CB
+:10B510001480000E240300408EE2523CAFA20010C3
+:10B520008EE252443C050007AFA200148EE652386A
+:10B530008EE752403C040001248458E00C002403B0
+:10B5400034A5F01008003D5F000000008EE2050009
+:10B550002442000150430003000010218EE2050048
+:10B5600024420001AEE205008EE2050000021080D8
+:10B5700000571021AC4905088EE2523C00491021C9
+:10B58000304200FFAEE2523C8EE3523C8EE2523833
+:10B5900014620005000000008F8200602403FEFF9B
+:10B5A00000431024AF8200608FBF001803E0000842
+:10B5B00027BD00208F8201208EE34E348F8201242C
+:10B5C0008F8601282402004024630001506200039A
+:10B5D000000010218EE24E3424420001AEE24E34CF
+:10B5E0008EE24E348EE44E348EE34E30000210C0B4
+:10B5F000244250381483000702E228218F82012858
+:10B6000024420020AF8201288F82012808003D9249
+:10B61000ACA000008EE24E3424030040244200011E
+:10B6200050430003000010218EE24E3424420001FA
+:10B63000000210C02442503802E228218CA20004EB
+:10B640008F8301280002114000621821AF83012876
+:10B65000ACA000008CC200182443FFFE2C62001234
+:10B6600010400008000310803C0100010022082166
+:10B670008C2258F000400008000000002402000165
+:10B68000AEE24E2403E000080000000027BDFFC822
+:10B69000AFBF0030AFB5002CAFB40028AFB300246B
+:10B6A000AFB20020AFB1001CAFB000188F830128EB
+:10B6B0008F820124106202B0000098213C11001F0B
+:10B6C0003631FFFF3C12FFF53652100024150012F0
+:10B6D000241400408F8C01288F82012824420020EE
+:10B6E000AF8201289182001B8F8301282443FFFE33
+:10B6F0002C6200121040029C000310803C010001EB
+:10B70000002208218C225948004000080000000057
+:10B710008F42021830420100104000070000000074
+:10B720009583001695820018006218230003140206
+:10B7300000431021A58200168D82001C3C0380006E
+:10B740003044FFFF004368243C03080000431824F2
+:10B7500011A00004AD84001C0004114008003DD875
+:10B76000244252480004114024420E2002E2582193
+:10B770009562000E3042FFFC10600004A562000ECE
+:10B780009584001608003EC0000000008D69001876
+:10B7900000004021952A000025290002952700007D
+:10B7A0002529000295260000252900029525000084
+:10B7B0002529000295240000252900029523000078
+:10B7C0002529000295220000252900020147502169
+:10B7D000014650210145502101445021014350218F
+:10B7E00001425021000A1C023142FFFF0062502139
+:10B7F000000A1C023142FFFF0062502196E2046AF7
+:10B80000314EFFFF30420002104000440000502142
+:10B81000252200140222102B1040001401201821B0
+:10B820002405000A000020210223102B54400001AF
+:10B8300000721821946200002463000224A5FFFF17
+:10B8400014A0FFF90082202100041C023082FFFFB7
+:10B8500000622021000414023083FFFF0043102106
+:10B860003042FFFF08003E3301425021952A00007C
+:10B8700025290002952800002529000295270000AF
+:10B8800025290002952600002529000295250000A3
+:10B890002529000295230000252900029522000099
+:10B8A0002529000295240000252900020148502185
+:10B8B00001475021014650210145502101435021AB
+:10B8C000014250219522000095230002014450219D
+:10B8D0000142502101435021000A1C023142FFFF66
+:10B8E00000625021000A1C023142FFFF0062502119
+:10B8F0003148FFFF510000013408FFFF8D6200183E
+:10B900009443000C2402080054620005A56800104E
+:10B910009562000E34420002A562000EA568001078
+:10B9200096E2046A000028213042000814400056C4
+:10B93000000030218D630018246200240222102BA5
+:10B9400010400034246900100229102B54400001DB
+:10B950000132482195250000246900140229102B8A
+:10B960001040000224A5FFEC01324821952200007E
+:10B9700030420FFF144000032529000208003E60FA
+:10B98000241300010000982100A030210229102B6F
+:10B990005440000101324821912200012529000272
+:10B9A00000A228210229102B544000010132482115
+:10B9B000252900020229102B5440000101324821A0
+:10B9C000952200002529000200A228210229102B1F
+:10B9D000544000010132482195220000252900022F
+:10B9E00000A228210229102B5440000101324821D5
+:10B9F000952200002529000200A228210229102BEF
+:10BA000054400001013248219522000008003E996F
+:10BA100000A2282194650010946200142469001685
+:10BA200030420FFF1440000324A5FFEC08003E8CB9
+:10BA3000241300010000982100A03021912300016F
+:10BA400025290004952200002529000295240000E4
+:10BA50002529000200A3282100A228219522000008
+:10BA60009523000200A4282100A2282100A3282158
+:10BA700000051C0230A2FFFF0062282100051C0205
+:10BA800030A2FFFF0062282196E2046A30420001E2
+:10BA90001040001E0000202195820016004E202339
+:10BAA0000004140200822021326200FF5040000294
+:10BAB000008620210085202100041402008220211C
+:10BAC0003084FFFF508000013404FFFF8D620018B6
+:10BAD000244300170223102B544000010072182148
+:10BAE00090620000384300112C63000138420006C8
+:10BAF0002C420001006218251060000400000000C4
+:10BB00009562000E34420001A562000E9562000E9F
+:10BB1000240A00023042000410400002A564001212
+:10BB2000240A00048F88012027623800250900209C
+:10BB30000122102B50400001276930008F8201281C
+:10BB400011220004000000008F820124152200074A
+:10BB5000240400208EE201A4000080212442000180
+:10BB6000AEE201A408003F4F8EE201A48EE5724CC4
+:10BB70008EE604908EE70494AD0B0008A504000E39
+:10BB8000AD0A00180005294000A01821000010216E
+:10BB900000E3382100E3202B00C2302100C4302113
+:10BBA000AD060000AD0700048EE2724C004D10257A
+:10BBB000AD02001C8EE204C4AD020010AF8901206A
+:10BBC00092E24E2014400060241000012543FFEE55
+:10BBD0002C630002394200112C420001006218253A
+:10BBE00010600024000000008EE24E30000210C001
+:10BBF0002442503802E220218C8200001455000FAC
+:10BC0000000000008EE34E308EE24E341062000BD6
+:10BC1000000000008C82000424420001AC82000479
+:10BC20008EE24E348EE34E30244200011054002B3D
+:10BC30000000000008003F2E000000008EE24E30A1
+:10BC40002442000150540003000010218EE24E30C7
+:10BC500024420001AEE24E308EE24E30000210C0AF
+:10BC60002442503802E220212402000108003F4E05
+:10BC7000AC9500008EE24E30000210C024425038D5
+:10BC800002E220218C830000240200071462001FBE
+:10BC9000000000008EE34E308EE24E341062001B36
+:10BCA000000000008C82000424420001AC820004E9
+:10BCB0008EE24E348EE34E302442000110540007D1
+:10BCC000000000008EE24E342442000110620005A4
+:10BCD0000000000008003F3A00000000146000056A
+:10BCE000000000008F82012824420020AF8201283A
+:10BCF0008F8201288C8200042C42001150400012D7
+:10BD0000AC80000008003F4F000000008EE24E3083
+:10BD10002442000150540003000010218EE24E30F6
+:10BD200024420001AEE24E308EE24E30000210C0DE
+:10BD30002442503802E2202124020007AC82000095
+:10BD400024020001AC8200041600000D0000000077
+:10BD50008F8201203C04000124845938AFA00014D4
+:10BD6000AFA200108D86001C8F8701243C050008BF
+:10BD70000C00240334A50001080040570000000017
+:10BD80008EE2724C24420001304207FF11A00006EF
+:10BD9000AEE2724C8EE201D02442FFFFAEE201D04F
+:10BDA00008003F6B8EE201D08EE201CC2442FFFFFF
+:10BDB000AEE201CC8EE201CC8EE201D82442FFFF3C
+:10BDC000AEE201D8080040578EE201D88F4202400F
+:10BDD000104000E5000000008EE20E1C244200012D
+:10BDE00008004057AEE20E1C9582001EAD82001C7A
+:10BDF0008F42024010400072000000008EE20E1CD4
+:10BE000024420001AEE20E1C8F4302400043102B7F
+:10BE1000144000D5000000008F8301202762380005
+:10BE20002466002000C2102B50400001276630001D
+:10BE30008F82012810C20004000000008F820124BC
+:10BE400014C20007000000008EE201A4000080215F
+:10BE500024420001AEE201A408003FDA8EE201A410
+:10BE60008EE2724CAC62001C8EE404A88EE504AC39
+:10BE70002462001CAC62000824020008A462000EC8
+:10BE800024020011AC620018AC640000AC65000430
+:10BE90008EE204C4AC620010AF86012092E24E2014
+:10BEA00014400034241000018EE24E30000210C015
+:10BEB0002442503802E220218C8200001455001FD9
+:10BEC000000000008EE34E308EE24E341062001B04
+:10BED000000000008C82000424420001AC820004B7
+:10BEE0008EE24E348EE34E3024420001105400079F
+:10BEF000000000008EE24E34244200011062000572
+:10BF00000000000008003FC60000000014600005AB
+:10BF1000000000008F82012824420020AF82012807
+:10BF20008F8201288C8200042C42001150400011A5
+:10BF3000AC80000008003FDA000000008EE24E30C6
+:10BF40002442000150540003000010218EE24E30C4
+:10BF500024420001AEE24E308EE24E30000210C0AC
+:10BF60002442503802E2202124020001AC95000056
+:10BF7000AC8200045600000B241000018EE2724CCB
+:10BF80003C040001248458A8AFA00014AFA2001004
+:10BF90008EE6724C8F4702803C0500090C0024039A
+:10BFA00034A5F00856000001AEE00E1C8EE20188B8
+:10BFB00024420001AEE20188080040508EE2018870
+:10BFC0008F830120276238002466002000C2102BD6
+:10BFD00050400001276630008F82012810C2000403
+:10BFE000000000008F82012414C20007000000003E
+:10BFF0008EE201A40000802124420001AEE201A4EF
+:10C00000080040448EE201A48EE2724CAC62001C37
+:10C010008EE404A88EE504AC2462001CAC62000827
+:10C0200024020008A462000E24020011AC62001871
+:10C03000AC640000AC6500048EE204C4AC62001085
+:10C04000AF86012092E24E201440003424100001FB
+:10C050008EE24E30000210C02442503802E220210D
+:10C060008C8200001455001F000000008EE34E304B
+:10C070008EE24E341062001B000000008C8200042F
+:10C0800024420001AC8200048EE24E348EE34E3036
+:10C090002442000110540007000000008EE24E34DC
+:10C0A000244200011062000500000000080040303A
+:10C0B0000000000014600005000000008F820128CD
+:10C0C00024420020AF8201288F8201288C82000444
+:10C0D0002C42001150400011AC8000000800404488
+:10C0E000000000008EE24E30244200015054000354
+:10C0F000000010218EE24E3024420001AEE24E30AC
+:10C100008EE24E30000210C02442503802E220215C
+:10C1100024020001AC950000AC8200041600000B64
+:10C12000000000008EE2724C3C040001248458A8F8
+:10C13000AFA00014AFA200108EE6724C8F470280B1
+:10C140003C0500090C00240334A5F0088EE20174BC
+:10C1500024420001AEE20174080040578EE20174EF
+:10C1600024020001AEE24E248F8301288F82012435
+:10C170001462FD58000000008FBF00308FB5002C06
+:10C180008FB400288FB300248FB200208FB1001C21
+:10C190008FB0001803E0000827BD003827BDFFE876
+:10C1A000278402082745020024060008AFBF0014B8
+:10C1B0000C00249AAFB000100000202124100001D0
+:10C1C0002402241FAF900210AF900200AF8002043F
+:10C1D000AF8202148F460248240300043C02004050
+:10C1E0003C010001AC235CC43C010001AC235CC8F1
+:10C1F0003C010001AC205D9C3C010001AC225CC014
+:10C200003C010001AC235CC80C005108240500046B
+:10C210000C004822000000008EE200003C03FEFFFC
+:10C220003463FFFD00431024AEE200003C023C00FA
+:10C23000AF82021C3C01000100370821AC3083AC06
+:10C240008FBF00148FB0001003E0000827BD001856
+:10C2500027BDFFE03C05000834A50400AFBF00186F
+:10C26000AFA00010AFA000148F8602003C040001B4
+:10C27000248459F00C002403000038218EE202804F
+:10C2800024420001AEE202808EE202808F8302002F
+:10C290003C023F00006218248FBF00183C020400DB
+:10C2A00003E0000827BD002027BDFFD8AFBF002056
+:10C2B000AFB1001CAFB000188F9002208EE20214C4
+:10C2C0000000382124420001AEE202148EE2021482
+:10C2D0003C02030002021024104000273C1104001D
+:10C2E0000C00429B000000003C02010002021024EE
+:10C2F00010400007000000008EE2021824420001F6
+:10C30000AEE202188EE20218080040C63C03FDFFB0
+:10C310008EE2021C24420001AEE2021C8EE2021CEC
+:10C320003C03FDFF3463FFFF3C0808FF3508FFFFB7
+:10C330008EE200003C040001248459FC3C05000806
+:10C340000200302100431024AEE200008F82022060
+:10C35000000038213C03030000481024004310254E
+:10C36000AF820220AFA000100C002403AFA0001485
+:10C370000800429600000000021110241040001F27
+:10C380003C0240008F830224240214021462000B3A
+:10C390003C03FDFF3C04000124845A083C050008CE
+:10C3A000AFA00010AFA000148F86022434A5FFFFB9
+:10C3B0000C002403000038213C03FDFF8EE2000046
+:10C3C0003463FFFF02002021004310240C004E5470
+:10C3D000AEE200008EE2022024420001AEE2022022
+:10C3E0008EE202208F8202203C0308FF3463FFFFAD
+:10C3F0000043102408004295005110250202102429
+:10C4000010400142000000008EE2022C2442000194
+:10C41000AEE2022C8EE2022C8F8202203C0308FF47
+:10C420003463FFFF0043102434420004AF82022033
+:10C430008F8300548F8200540800410E2463000251
+:10C440008F820054006210232C4200031440FFFC32
+:10C45000000000008F8600E08F8400E430C20007F7
+:10C4600010400012000000008F8300E42402FFF857
+:10C4700000C210241043000D000000008F82005401
+:10C480008F8300E014C30009244400508F820054BD
+:10C49000008210232C4200511040000400000000D4
+:10C4A0008F8200E010C2FFF9000000008F8202209E
+:10C4B0003C0308FF3463FFFD00431024AF820220D9
+:10C4C0008F8600E030C20007104000032402FFF80E
+:10C4D00000C23024AF8600E08F8300C43C02001FFE
+:10C4E0003442FFFF246800080048102B104000036E
+:10C4F0003C02FFF534421000010240218F8B00C83E
+:10C500008F8501208F8401240800414500006021AF
+:10C51000276238000082102B504000012764300051
+:10C5200010A40010318200FF8C82001838430007ED
+:10C530002C6300013842000B2C42000100621825D8
+:10C540005060FFF3248400208EE20240240C00019E
+:10C5500024420001AEE202408EE202408C8B0008D1
+:10C56000318200FF14400065000000003C02000121
+:10C5700000571021904283C014400060000000006A
+:10C580008F8400E400C41023000218C30462000179
+:10C59000246302008F8900C410600005240200019A
+:10C5A0001062000900000000080041870000000040
+:10C5B0008EE202300120582124420001AEE2023016
+:10C5C000080041BC8EE202308EE202343C05000AD3
+:10C5D00024420001AEE202348C8B000034A5F0004E
+:10C5E0008EE20234012B182300A3102B54400001CB
+:10C5F000006518212C62233F144000400000000019
+:10C600008F8200E824420008AF8200E88F8200E8B1
+:10C610008F8200E40120582124420008AF8200E408
+:10C62000080041BC8F8200E48EE202383C03000A1D
+:10C6300024420001AEE202388C8400003463F00032
+:10C640008EE20238008838230067102B5440000126
+:10C6500000E338213C02000334420D400047102B18
+:10C660001040000300000000080041BC0080582179
+:10C670008F8200E424440008AF8400E48F8400E447
+:10C68000108600183C05000A34A5F0003C0A00039F
+:10C69000354A0D408EE2007C24420001AEE2007C6F
+:10C6A0008C8300008EE2007C0068382300A7102BEA
+:10C6B0005440000100E538210147102B5440000789
+:10C6C000006058218F8200E424440008AF8400E415
+:10C6D0008F8400E41486FFEF00000000148600053C
+:10C6E0000000000001205821AF8600E4080041BC92
+:10C6F000AF8600E8AF8400E4AF8400E88F8200C812
+:10C700003C03000A3463F000004838230067102B14
+:10C710005440000100E338213C02000334420D3F45
+:10C720000047102B544000070000602101683823A7
+:10C730000067102B5440000300E33821080041CF6C
+:10C740003C0200033C02000334420D3F0047102B23
+:10C7500014400016318200FF144000060000000063
+:10C760003C02000100571021904283C01040000F8E
+:10C77000000000008EE2023C3C04FDFF8EE300005E
+:10C780003484FFFF24420001AEE2023C8EE2023C10
+:10C7900024020001006418243C0100010037082134
+:10C7A000A02283B80800422CAEE30000AF8B00C883
+:10C7B0008F8300C88F8200C43C04000A3484F000D8
+:10C7C000006238230087102B5440000100E4382118
+:10C7D0003C02000334420D400047102B2CE30001C3
+:10C7E0000043102510400008000000008F82022046
+:10C7F0003C0308FF3463FFFF004310243C03400068
+:10C8000000431025AF8202208F8600E08F8400E471
+:10C8100010C4002A000000008EE2007C24420001C7
+:10C82000AEE2007C8EE2007C24C2FFF8AF8200E022
+:10C830003C0200018C427E303C0300088F8600E001
+:10C84000004310241040001D0000000010C4001B15
+:10C85000240DFFF83C0A000A354AF0003C0C008029
+:10C86000248500082762280050A2000127651800CF
+:10C870008C8800048C8200008CA900003103FFFF2B
+:10C8800000431021004D102424430010006B102B96
+:10C8900054400001006A1821012B102B5440000164
+:10C8A000012A482110690002010C1025AC82000405
+:10C8B00000A0202114C4FFEB248500088F820220F1
+:10C8C0003C0308FF3463FFFF00431024344200029E
+:10C8D000AF8202208F8300548F82005408004237B9
+:10C8E000246300018F820054006210232C42000256
+:10C8F0001440FFFC000000008F8202203C0308FF70
+:10C900003463FFFB00431024AF8202200601005570
+:10C91000000000008EE2022824420001AEE202285C
+:10C920008EE202288F8202203C0308FF3463FFFF5F
+:10C930000043102434420004AF8202208F8300544D
+:10C940008F82005408004251246300028F820054F9
+:10C95000006210232C4200031440FFFC0000000082
+:10C960008F8600E030C20007104000120000000077
+:10C970008F8300E42402FFF800C210241043000D4E
+:10C98000000000008F8200548F8300E014C3000970
+:10C99000244400328F820054008210232C42003342
+:10C9A00010400004000000008F8200E010C2FFF978
+:10C9B000000000008F8202203C0308FF3463FFFD6B
+:10C9C00000431024AF8202208F8600E030C20007AF
+:10C9D000104000032402FFF800C23024AF8600E0BC
+:10C9E000240301F58F8200E800673823000718C090
+:10C9F00000431021AF8200E88F8200E8AF8200E49C
+:10CA00008EE2007C3C0408FF3484FFFF00471021C5
+:10CA1000AEE2007C8F8202203C038000346300027F
+:10CA20000044102400431025AF8202208F8300545D
+:10CA30008F8200540800428D246300018F820054CD
+:10CA4000006210232C4200021440FFFC0000000092
+:10CA50008F8202203C0308FF3463FFFB0043102455
+:10CA6000AF8202208FBF00208FB1001C8FB0001852
+:10CA700003E0000827BD00283C0200018C425CD87E
+:10CA800027BDFFD810400012AFBF00203C040001BA
+:10CA900024845A143C050008240200013C010001D2
+:10CAA00000370821AC2283ACAFA00010AFA0001467
+:10CAB0008F86022034A504983C010001AC205CD88C
+:10CAC0003C010001AC225CCC0C00240300003821A6
+:10CAD0008F4202683C037FFF3463FFFF0043102452
+:10CAE000AF4202688EE204D08EE404D42403FFFE39
+:10CAF00000431024308400021080011EAEE204D0F6
+:10CB00008EE204D42403FFFD00431024AEE204D4DB
+:10CB10008F8200443C03060034632000344200202E
+:10CB2000AF820044AFA300188EE206088F430228AC
+:10CB300024420001304A00FF514300FEAFA0001024
+:10CB40008EE20608000210C0005710218FA30018C3
+:10CB50008FA4001CAC43060CAC4406108F83005419
+:10CB60008F82005424690032012210232C420033AA
+:10CB70001040006A0000582124180008240F000DFE
+:10CB8000240D0007240C0040240E00018F87012093
+:10CB90002762380024E800200102102B50400001D9
+:10CBA000276830008F820128110200040000000075
+:10CBB0008F82012415020007000010218EE201A4DB
+:10CBC0000000282124420001AEE201A40800433DF8
+:10CBD0008EE201A48EE40608000420C00080182123
+:10CBE0008EE404308EE5043400A3282100A3302B0A
+:10CBF0000082202100862021ACE40000ACE5000486
+:10CC00008EE20608A4F8000EACEF0018ACEA001C97
+:10CC1000000210C02442060C02E21021ACE200081F
+:10CC20008EE204C4ACE20010AF88012092E24E20F4
+:10CC300014400033240500018EE24E30000210C083
+:10CC40002442503802E220218C820000144D001F43
+:10CC5000000000008EE34E308EE24E341062001B66
+:10CC6000000000008C82000424420001AC82000419
+:10CC70008EE24E348EE34E3024420001104C000709
+:10CC8000000000008EE24E342442000110620005D4
+:10CC9000000000000800432A0000000014600005A6
+:10CCA000000000008F82012824420020AF8201286A
+:10CCB0008F8201288C8200042C4200115040001009
+:10CCC000AC8000000800433D000000008EE24E30C2
+:10CCD00024420001504C0003000010218EE24E302F
+:10CCE00024420001AEE24E308EE24E30000210C00F
+:10CCF0002442503802E22021AC8D0000AC8E0004AA
+:10CD000054A00006240B00018F820054012210233E
+:10CD10002C4200331440FF9D00000000316300FFEF
+:10CD20002402000154620079AFA00010AEEA0608A8
+:10CD30008F8300548F820054246900320122102313
+:10CD40002C4200331040006100005821240D0008DF
+:10CD5000240C00112408001224070040240A0001BA
+:10CD60008F830120276238002466002000C2102B28
+:10CD700050400001276630008F82012810C2000455
+:10CD8000000000008F82012414C200070000000090
+:10CD90008EE201A40000282124420001AEE201A499
+:10CDA000080043A98EE201A48EE20608AC62001CD2
+:10CDB0008EE404A08EE504A42462001CAC6200088A
+:10CDC000A46D000EAC6C0018AC640000AC650004EF
+:10CDD0008EE204C4AC620010AF86012092E24E20C5
+:10CDE00014400033240500018EE24E30000210C0D2
+:10CDF0002442503802E220218C8200001448001F97
+:10CE0000000000008EE34E308EE24E341062001BB4
+:10CE1000000000008C82000424420001AC82000467
+:10CE20008EE24E348EE34E3024420001104700075C
+:10CE3000000000008EE24E34244200011062000522
+:10CE40000000000008004396000000001460000588
+:10CE5000000000008F82012824420020AF820128B8
+:10CE60008F8201288C8200042C4200115040001057
+:10CE7000AC800000080043A9000000008EE24E30A4
+:10CE80002442000150470003000010218EE24E3082
+:10CE900024420001AEE24E308EE24E30000210C05D
+:10CEA0002442503802E22021AC880000AC8A000401
+:10CEB00054A00006240B00018F820054012210238D
+:10CEC0002C4200331440FFA600000000316300FF35
+:10CED0002402000154620003AFA00010080043D6F2
+:10CEE000000000003C04000124845A20AFA000147C
+:10CEF0008F8601208F8701243C0500090C00240344
+:10CF000034A5F011080043D6000000003C040001E5
+:10CF100024845A2CAFA000148F8601208F8701240F
+:10CF20003C0500090C00240334A5F010080043D68A
+:10CF3000000000003C04000124845A38AFA0001413
+:10CF40008EE606088F4702283C0500090C002403E2
+:10CF500034A5F00F8EE201AC24420001AEE201AC38
+:10CF60008EE201AC8EE2015C24420001AEE2015C83
+:10CF70008EE2015C8FBF002003E0000827BD00287F
+:10CF80003C0200018C425CD827BDFFE01440000D3C
+:10CF9000AFBF00183C04000124845A443C0500083B
+:10CFA000AFA00010AFA000148F86022034A5049912
+:10CFB000240200013C010001AC225CD80C002403D7
+:10CFC000000038218EE204D03C03000100771821D4
+:10CFD000946383B23442000110600007AEE204D0D3
+:10CFE0008F8202203C0308FF3463FFFF00431024BC
+:10CFF00034420008AF820220000020210C0052A21F
+:10D0000024050004AF4202688FBF001803E0000847
+:10D0100027BD00200000000000000000000000000C
+:10D020000000000000000000000000000000000000
+:10D0300000000000000000000000000000000000F0
+:10D0400000000000000000000000000000000000E0
+:10D0500000000000000000000000000000000000D0
+:10D0600000000000000000000000000000000000C0
+:10D0700000000000000000000000000000000000B0
+:10D0800000000000000000000000000000000000A0
+:10D090000000000000000000000000000000000090
+:10D0A0000000000000000000000000000000000080
+:10D0B0000000000000000000000000000000000070
+:10D0C0000000000000000000000000000000000060
+:10D0D0000000000000000000000000000000000050
+:10D0E0000000000000000000000000000000000040
+:10D0F0000000000000000000000000000000000030
+:10D100000000000000000000000000003C120001D0
+:10D11000265212003C1400018E945C503C10000119
+:10D12000261011203C15C00036B500608E8A000024
+:10D130008EB30000026A400B0248000A0200F82188
+:10D14000000000000000000D0000000000000000D2
+:10D1500000000000000000000000000000000000CF
+:10D1600000000000000000000000000000000000BF
+:10D1700000000000000000000000000000000000AF
+:10D18000000000000000000000000000000000009F
+:10D19000000000000000000000000000000000008F
+:10D1A000000000000000000000000000000000007F
+:10D1B000000000000000000000000000000000006F
+:10D1C000000000000000000000000000000000005F
+:10D1D000000000000000000000000000000000004F
+:10D1E000000000000000000000000000000000003F
+:10D1F000000000000000000000000000000000002F
+:10D20000000000000000000000000000080014D62C
+:10D2100000000000080014D83C0A0001080014D8DF
+:10D220003C0A0002080014D800000000080024A6F0
+:10D2300000000000080014D83C0A0003080014D8BD
+:10D240003C0A000408002F8C00000000080014D8DD
+:10D250003C0A000508003CE80000000008003C66AD
+:10D2600000000000080014D83C0A0006080014D88A
+:10D270003C0A0007080014D800000000080014D879
+:10D2800000000000080014D80000000008002A7503
+:10D2900000000000080014D83C0A000B080014D855
+:10D2A0003C0A000C080014D83C0A000D0800237A40
+:10D2B000000000000800233900000000080014D816
+:10D2C0003C0A000E08001B3C00000000080024A4DB
+:10D2D00000000000080014D83C0A000F080040A716
+:10D2E000000000000800409100000000080014D871
+:10D2F0003C0A0010080014EE00000000080014D8DA
+:10D300003C0A0011080014D83C0A0012080014D886
+:10D310003C0A0013000000000000000000000000B4
+:10D3200000000000000000000000000000000000FD
+:10D3300000000000000000000000000000000000ED
+:10D3400000000000000000000000000000000000DD
+:10D3500000000000000000000000000000000000CD
+:10D3600000000000000000000000000000000000BD
+:10D3700000000000000000000000000000000000AD
+:10D38000000000000000000000000000000000009D
+:10D39000000000000000000000000000000000008D
+:10D3A000000000000000000000000000000000007D
+:10D3B000000000000000000000000000000000006D
+:10D3C000000000000000000000000000000000005D
+:10D3D000000000000000000000000000000000004D
+:10D3E000000000000000000000000000000000003D
+:10D3F000000000000000000000000000000000002D
+:10D400000000000000000000000000003C030001DC
+:10D4100034633800240500802404001F2406FFFF25
+:10D4200024020001AF80021CAF820200AF82022002
+:10D4300003631021AF8200C003631021AF8200C4D8
+:10D4400003631021AF8200C827623800AF8200D08A
+:10D4500027623800AF8200D427623800AF8200D83C
+:10D4600027621800AF8200E027621800AF8200E454
+:10D4700027621800AF8200E827621000AF8200F038
+:10D4800027621000AF8200F427621000AF8200F81C
+:10D49000ACA000002484FFFF1486FFFD24A5000437
+:10D4A0008F8300403C02F000006218243C025000D0
+:10D4B0001062000C0043102B144000063C02600078
+:10D4C0003C024000106200082402080008004539B0
+:10D4D0000000000010620004240208000800453922
+:10D4E00000000000240207003C010001AC225CDCCB
+:10D4F00003E000080000000027BDFFD8AFBF0024F4
+:10D50000AFB000208F8300548F8200543C01000193
+:10D51000AC205CC408004545246300648F8200543D
+:10D52000006210232C4200651440FFFC0000000044
+:10D530000C004D71000000002404000100002821AF
+:10D5400027A60018340280000C00498EA7A20018FC
+:10D550008F8300548F820054080045562463006472
+:10D560008F820054006210232C4200651440FFFC9F
+:10D5700024040001240500010C00494C27A60018D2
+:10D580008F8300548F820054080045622463006436
+:10D590008F820054006210232C4200651440FFFC6F
+:10D5A00024040001240500010C00494C27A60018A2
+:10D5B0008F8300548F8200540800456E24630064FA
+:10D5C0008F820054006210232C4200651440FFFC3F
+:10D5D000240400013C06000124C65DA00C00494C57
+:10D5E000240500028F8300548F8200540800457B7D
+:10D5F000246300648F820054006210232C42006573
+:10D600001440FFFC24040001240500033C10000129
+:10D6100026105DA20C00494C0200302197A600188C
+:10D620003C07000194E75DA03C04000124845AB04B
+:10D63000AFA00014960200003C05000D34A50100C7
+:10D640000C002403AFA2001097A200181040004C59
+:10D6500024036040960200003042FFF01443000AA9
+:10D66000240200203C03000194635DA05462000981
+:10D6700024027830240200033C010001AC225CC487
+:10D68000080045AC240200053C03000194635DA042
+:10D69000240278301462000F240300103C020001C1
+:10D6A00094425DA23042FFF01443000A24020003BA
+:10D6B0003C010001AC225CC4240200063C010001D4
+:10D6C000AC225DB03C010001AC225DBC080045E627
+:10D6D0003C09FFF03C0200018C425CC43C030001A9
+:10D6E00094635DA0344200013C010001AC225CC4A3
+:10D6F000240200151462000F000000003C0200012B
+:10D7000094425DA23042FFF03843F4202C630001C4
+:10D710003842F4302C4200010062182510600005E8
+:10D72000240200033C010001AC225DBC080045E678
+:10D730003C09FFF03C03000194635DA024027810D3
+:10D740001462000B240200023C02000194425DA21C
+:10D750003042FFF0144000062402000224020004BC
+:10D760003C010001AC225DBC080045E63C09FFF02D
+:10D770003C010001AC225DBC080045E63C09FFF01D
+:10D780003C0200018C425CC4240300013C01000106
+:10D79000AC235DBC344200043C010001AC225CC4FB
+:10D7A0003C09FFF03529BDC03C0600018CC65CC4B5
+:10D7B0003C04000124845AB0240200013C01000111
+:10D7C000AC225CCC8F8200543C0700018CE75DBC2E
+:10D7D0003C03000194635DA03C08000195085DA234
+:10D7E0003C05000D34A501003C010001AC205CC8E3
+:10D7F000004910213C010001AC225DACAFA3001038
+:10D800000C002403AFA800148FBF00248FB00020A9
+:10D8100003E0000827BD002827BDFFE83C05000104
+:10D820008CA55CC8240600042402000114A2001484
+:10D83000AFBF00103C0200018C427E3C30428000B1
+:10D84000104000053C04000F3C0300018C635DBCEC
+:10D8500008004617348442403C0400043C030001A5
+:10D860008C635DBC348493E02402000514620016CE
+:10D87000000000003C04003D0800462F34840900ED
+:10D880003C0200018C427E3830428000104000058E
+:10D890003C04001E3C0300018C635DBC0800462A6A
+:10D8A000348484803C04000F3C0300018C635DBC25
+:10D8B000348442402402000514620003000000008A
+:10D8C0003C04007A348412003C0200018C425DACBE
+:10D8D0008F83005400441021004310230044102B78
+:10D8E00014400037000000003C0200018C425CD074
+:10D8F00014400033000000003C01000110C000256E
+:10D90000AC205CE03C0900018D295CC424070001C7
+:10D910003C0440003C08000125087E3C250AFFFC31
+:10D920000005284214A0000224C6FFFF24050008B9
+:10D9300000A91024104000100000000014A70008E7
+:10D94000000000008D020000004410241040000A76
+:10D95000000000003C0100010800465BAC255CE0D3
+:10D960008D4200000044102410400003000000001D
+:10D970003C010001AC275CE03C0200018C425CE011
+:10D980000006182B2C420001004310245440FFE5F0
+:10D99000000528428F8200543C0300018C635CE048
+:10D9A0003C010001AC225DAC1060002A24020001A1
+:10D9B0003C010001AC255CC83C010001AC225CCC00
+:10D9C0003C0200018C425CE010400022000000009C
+:10D9D0003C0200018C425CCC1040000A2402000191
+:10D9E0003C010001AC205CCC3C0100010037082167
+:10D9F000AC2283AC3C010001AC205D4C3C01000139
+:10DA0000AC225D043C030001007718218C6383ACD9
+:10DA10002402000810620005240200010C00469553
+:10DA20000000000008004692000000003C030001D6
+:10DA30008C635CC8106200072402000E3C030001E6
+:10DA40008C637DD010620003000000000C004E5477
+:10DA50008F8402208FBF001003E0000827BD00184C
+:10DA600027BDFFE03C02FDFFAFBF00188EE30000C2
+:10DA70003C0500018CA55CC83C0400018C845CF072
+:10DA80003442FFFF0062182414A40008AEE3000033
+:10DA90003C030001007718218C6383AC3C02000139
+:10DAA0008C425CF410620008000000003C0200019F
+:10DAB000005710218C4283AC3C010001AC255CF086
+:10DAC0003C010001AC225CF43C0300018C635CC8A7
+:10DAD00024020002106201692C620003104000055C
+:10DAE0002402000110620008000000000800481C29
+:10DAF0000000000024020004106200B124020001B2
+:10DB00000800481D000000003C02000100571021E1
+:10DB10008C4283AC2443FFFF2C6200081040015A62
+:10DB2000000310803C010001002208218C225AC809
+:10DB300000400008000000003C0300018C635DBC55
+:10DB40002402000514620014000000003C020001E1
+:10DB50008C425CD41040000A240200030C004822CE
+:10DB600000000000240200023C01000100370821EF
+:10DB7000AC2283AC3C010001080046E0AC205CD440
+:10DB80003C01000100370821AC2283AC3C010001BC
+:10DB90000800481FAC205C600C0048220000000018
+:10DBA0003C0200018C425CD43C010001AC205C6072
+:10DBB000104000DD240200023C0100010037082172
+:10DBC000AC2283AC3C0100010800481FAC205CD4AF
+:10DBD0003C0300018C635DBC240200051462000359
+:10DBE000240200013C010001AC225D000C0049CF81
+:10DBF000000000003C0300018C635D000800478EBC
+:10DC0000240200113C0500018CA55CC83C06000103
+:10DC10008CC67E3C0C005108000020212402000527
+:10DC20003C010001AC205CD43C010001003708211C
+:10DC30000800481FAC2283AC3C04000124845ABC79
+:10DC40003C05000F34A50100000030210000382100
+:10DC5000AFA000100C002403AFA000140800481F60
+:10DC6000000000008F8202203C03F70000431025D3
+:10DC7000080047B7AF8202208F8202203C030004D5
+:10DC800000431024144000A9240200078F8300548D
+:10DC90003C0200018C425DA42463D8F000431023B1
+:10DCA0002C422710144000F8240200010800481DEF
+:10DCB000000000003C0500018CA55CC80C0052A2CD
+:10DCC000000020210C005386000020213C030001AD
+:10DCD0008C637E34046100EA240200013C020008E7
+:10DCE0000062102410400006000000008F82021421
+:10DCF0003C03FFFF00431024080047413442251F26
+:10DD00008F8202143C03FFFF004310243442241F7F
+:10DD1000AF8202148EE200003C0302000043102593
+:10DD2000AEE200008F8202202403FFFB0043102498
+:10DD3000AF8202208F82022034420002AF82022092
+:10DD4000240200083C01000100370821AC2283AC0A
+:10DD50008F8202203C03000400431024144000057D
+:10DD6000000000008F8202203C03F70000431025D2
+:10DD7000AF8202203C0300018C635DBC24020005DD
+:10DD80001462000A000000003C02000194425DA2FF
+:10DD900024429FBC2C4200041040000424040018BC
+:10DDA000240500020C004D93240600200C0043DDE6
+:10DDB000000000003C0100010800481FAC205D503D
+:10DDC0003C020001005710218C4283AC2443FFFF2A
+:10DDD0002C620008104000AC000310803C010001E0
+:10DDE000002208218C225AE80040000800000000B0
+:10DDF0000C00429B000000003C010001AC205CCC08
+:10DE0000AF8002043C0100010C004822AC207E20BF
+:10DE1000240200013C010001AC225CE42402000267
+:10DE20003C010001003708210800481FAC2283ACE8
+:10DE30000C00489F000000003C0300018C635CE480
+:10DE40002402000914620090240200033C01000136
+:10DE5000003708210800481FAC2283AC3C020001B7
+:10DE60008C427E3830424000104000050000000027
+:10DE70008F8200443C03FFFF0800479F34637FFF0D
+:10DE80008F8200442403FF7F00431024AF820044AC
+:10DE90008F830054080047B9240200048F83005484
+:10DEA0003C0200018C425DA42463D8F0004310239F
+:10DEB0002C42271014400074240200053C0100018C
+:10DEC000003708210800481FAC2283AC8F82022053
+:10DED0003C03F70000431025AF820220AF8002040C
+:10DEE0003C010001AC207E208F83005424020006F8
+:10DEF0003C01000100370821AC2283AC3C01000149
+:10DF00000800481FAC235DA48F8300543C0200012D
+:10DF10008C425DA42463FFF6004310232C42000AC8
+:10DF20001440005900000000240200073C010001D9
+:10DF3000003708210800481FAC2283AC8F820220E2
+:10DF40003C04F70000441025AF8202208F8202209B
+:10DF50003C03030000431024144000050000182176
+:10DF60008F8202202403000100441025AF8202208A
+:10DF700010600043240200018F8202143C03FFFF63
+:10DF80003C0400018C845D98004310243442251F1A
+:10DF9000AF820214240200083C010001003708216E
+:10DFA0001080000BAC2283AC3C0200018C425D74FB
+:10DFB00014400007240200013C010001AC227DD086
+:10DFC0000C004E548F8402200800480C0000000012
+:10DFD0008F8202203C0300080043102414400017E5
+:10DFE0002402000E3C010001AC227DD08EE2000034
+:10DFF000000020213C030200004310250C00538642
+:10E00000AEE200008F8202202403FFFB00431024B5
+:10E01000AF8202208F820220344200020C0043DDD6
+:10E02000AF8202203C0500018CA55CC80C0052A206
+:10E03000000020210800481F000000003C020001F1
+:10E040008C425D7410400010000000003C02000192
+:10E050008C425D702442FFFF3C010001AC225D70E8
+:10E0600014400009240200023C010001AC205D7450
+:10E070003C0100010800481FAC225D702402000131
+:10E080003C010001AC225CCC8FBF001803E000080B
+:10E0900027BD00208F8202008F8202208F82022003
+:10E0A00034420004AF8202208F8202003C0600014D
+:10E0B0008CC65CC834420004AF8202002402000215
+:10E0C00010C2003A2CC200031040000524020001D7
+:10E0D00010C20008000000000800486800000000AE
+:10E0E0002402000410C20013240200010800486842
+:10E0F000000000003C0300018C635CB83C0200019E
+:10E100008C425CC03C0400018C845CDC3C0500015A
+:10E110008CA55CBCAF860200AF860220346300226F
+:10E1200000441025004510253442000208004867CD
+:10E13000AF8302003C0300018C635D98AF82020054
+:10E1400010600009AF8202203C0200018C425D7425
+:10E15000144000053C033F003C0200018C425CB0CF
+:10E160000800485B346300E03C0200018C425CB074
+:10E170003C033F00346300E200431025AF820200FD
+:10E180003C0300018C635CB43C04F7003C020001DA
+:10E190008C425CC03C0500018CA55CDC0064182549
+:10E1A0000043102500451025AF82022003E000083F
+:10E1B000000000008F8202203C0300018C635CC8D9
+:10E1C00034420004AF820220240200011062000FDA
+:10E1D000000000008F8300548F82005424630002EB
+:10E1E000006210232C4200031040001100000000C8
+:10E1F0008F820054006210232C4200031040000C58
+:10E200000000000008004879000000008F830054DF
+:10E210008F82005408004885246300078F820054D1
+:10E22000006210232C4200081440FFFC0000000094
+:10E230008F8400E0308200071040000D00000000D5
+:10E240008F8200548F8300E014830009244500323C
+:10E250008F82005400A210232C420033104000048F
+:10E26000000000008F8200E01082FFF90000000033
+:10E270008F8202202403FFFD00431024AF8202207E
+:10E2800003E00008000000003C0300018C635CE434
+:10E290003C0200018C425CE8506200042463FFFFF2
+:10E2A0003C010001AC235CE82463FFFF2C62000901
+:10E2B0001040009D000310803C0100010022082155
+:10E2C0008C225B0800400008000000008F820044A0
+:10E2D00034428080AF8200448F8300540800493864
+:10E2E000240200028F8300543C0200018C425DA88E
+:10E2F0002463D8F0004310232C4227101440008AD6
+:10E300002402000308004945000000008F820044F9
+:10E310003C03FFFF34637FFF00431024AF820044BF
+:10E320008F83005408004938240200048F8300546E
+:10E330003C0200018C425DA82463FFF600431023D9
+:10E340002C42000A144000782402000508004945C8
+:10E35000000000008F8202203C03F70000431025DC
+:10E36000AF8202208F8202202403FFFB004310248F
+:10E37000AF8202208F82022034420002AF8202204C
+:10E380003C023F00344200E0AF8202008F82020074
+:10E390002403FFFD00431024AF8202002404000187
+:10E3A0003405FFFFAF8402048F8300548F82005432
+:10E3B000080048EC246300018F820054006210239F
+:10E3C0002C4200021440FFFC000000008F82022457
+:10E3D0000004204000A4102B1040FFF200000000B9
+:10E3E0008F8202203C03F70000431025AF820220F9
+:10E3F0008F8202143C03FFFF004310243442251F88
+:10E40000AF8202148F8202202403FFFB00431024FA
+:10E41000AF8202208F8202203C04F700348400087F
+:10E4200034420002AF8202208F8202203C033F0070
+:10E43000346300E200441025AF820220AF83020063
+:10E440008F8400F0276217F81482000224850008E8
+:10E45000276510008F8200F410A200073C038000A3
+:10E46000346300403C02000124425C70AC82000036
+:10E47000AC830004AF8500F08F8300540800493856
+:10E48000240200068F8300543C0200018C425DA8E8
+:10E490002463FFF6004310232C42000A144000229C
+:10E4A0002402000708004945000000008F8200E0B8
+:10E4B000AF8200E48F8200E0AF8200E88F8202200A
+:10E4C00034420004AF8202208F8202202403FFF72F
+:10E4D00000431024AF8202208F82004434428080A7
+:10E4E000AF8200448F830054240200083C010001E5
+:10E4F000AC225CE43C01000108004947AC235DA864
+:10E500008F8300543C0200018C425DA82463D8F044
+:10E51000004310232C42271014400003240200095A
+:10E520003C010001AC225CE403E0000800000000B4
+:10E5300000000000000000000000000027BDFFD820
+:10E54000AFB2001800809021AFB3001C00A098214A
+:10E55000AFB1001400C08821AFB0001000008021CE
+:10E56000AFBF0020A62000000C004D4B240400018A
+:10E57000261000012E0200201440FFFB00000000C6
+:10E580000C004D4B000020210C004D4B24040001D9
+:10E590000C004D4B240400010C004D4B00002021C9
+:10E5A000241000100250102410400002000020210E
+:10E5B000240400010C004D4B001080421600FFFAAD
+:10E5C0000250102424100010027010241040000289
+:10E5D00000002021240400010C004D4B001080425B
+:10E5E0001600FFFA027010240C004D7134108000E8
+:10E5F0000C004D71000000000C004D2B00000000CD
+:10E600005040000500108042962200000050102566
+:10E61000A6220000001080421600FFF70000000054
+:10E620000C004D71000000008FBF00208FB3001C54
+:10E630008FB200188FB100148FB0001003E00008F3
+:10E6400027BD002827BDFFD8AFB100140080882166
+:10E65000AFB2001800A09021AFB3001C00C09821F9
+:10E66000AFB0001000008021AFBF00200C004D4B68
+:10E6700024040001261000012E0200201440FFFB9C
+:10E68000000000000C004D4B000020210C004D4B01
+:10E69000240400010C004D4B000020210C004D4BC8
+:10E6A0002404000124100010023010241040000245
+:10E6B00000002021240400010C004D4B001080427A
+:10E6C0001600FFFA0230102424100010025010240B
+:10E6D0001040000200002021240400010C004D4BDA
+:10E6E000001080421600FFFA025010240C004D4B1F
+:10E6F000240400010C004D4B000020213410800048
+:10E7000096620000005010241040000200002021FA
+:10E71000240400010C004D4B001080421600FFF84D
+:10E72000000000000C004D71000000008FBF0020B1
+:10E730008FB3001C8FB200188FB100148FB000107F
+:10E7400003E0000827BD00283C0300018C635D0046
+:10E750003C0200018C425D4827BDFFD8AFBF0020BE
+:10E76000AFB1001C10620003AFB000183C01000103
+:10E77000AC235D482463FFFF2C6200131040034963
+:10E78000000310803C010001002208218C225B3034
+:10E7900000400008000000000C004D7100008021C6
+:10E7A00034028000A7A2001027B100100C004D4BCE
+:10E7B00024040001261000012E0200201440FFFB5B
+:10E7C000000000000C004D4B000020210C004D4BC0
+:10E7D000240400010C004D4B000020210C004D4B87
+:10E7E0002404000124100010320200011040000235
+:10E7F00000002021240400010C004D4B0010804239
+:10E800001600FFFA32020001241000100C004D4BDC
+:10E8100000002021001080421600FFFC00000000D4
+:10E820000C004D4B240400010C004D4B0000202136
+:10E830003410800096220000005010241040000286
+:10E8400000002021240400010C004D4B00108042E8
+:10E850001600FFF8000000000C004D7100000000E1
+:10E8600008004D242402000227B10010A7A00010C8
+:10E87000000080210C004D4B2404000126100001F3
+:10E880002E0200201440FFFB000000000C004D4B46
+:10E89000000020210C004D4B240400010C004D4BC6
+:10E8A000240400010C004D4B000020212410001016
+:10E8B0003202000110400002000020212404000167
+:10E8C0000C004D4B001080421600FFFA320200018E
+:10E8D000241000100C004D4B00002021001080423D
+:10E8E0001600FFFC000000000C004D713410800089
+:10E8F0000C004D71000000000C004D2B00000000CA
+:10E900005040000500108042962200000050102563
+:10E91000A6220000001080421600FFF70000000051
+:10E920000C004D710000000097A2001030428000E2
+:10E93000144002DC2402000308004D240000000003
+:10E9400024021200A7A2001027B1001000008021AD
+:10E950000C004D4B24040001261000012E02002063
+:10E960001440FFFB000000000C004D4B0000202174
+:10E970000C004D4B240400010C004D4B00002021E5
+:10E980000C004D4B24040001241000103202000141
+:10E990001040000200002021240400010C004D4B17
+:10E9A000001080421600FFFA32020001241000100D
+:10E9B0000C004D4B00002021001080421600FFFC8F
+:10E9C000000000000C004D4B240400010C004D4BD6
+:10E9D00000002021341080009622000000501024F6
+:10E9E0001040000200002021240400010C004D4BC7
+:10E9F000001080421600FFF8000000000C004D716E
+:10EA0000000000008F83005408004D16240200040B
+:10EA10008F8300543C0200018C425DB82463FF9C4C
+:10EA2000004310232C4200641440029E2402000282
+:10EA30003C0300018C635DBC106202972C620003F2
+:10EA40001440029624020011240200031062000503
+:10EA500024020004106202912402000F08004D24D9
+:10EA60002402001108004D24240200052402001491
+:10EA7000A7A2001027B10010000080210C004D4B10
+:10EA800024040001261000012E0200201440FFFB88
+:10EA9000000000000C004D4B000020210C004D4BED
+:10EAA000240400010C004D4B000020210C004D4BB4
+:10EAB0002404000124100010320200011040000262
+:10EAC00000002021240400010C004D4B0010804266
+:10EAD0001600FFFA32020001241000103202001268
+:10EAE0001040000200002021240400010C004D4BC6
+:10EAF000001080421600FFFA320200120C004D4B4B
+:10EB0000240400010C004D4B000020213410800033
+:10EB10009622000000501024104000020000202126
+:10EB2000240400010C004D4B001080421600FFF839
+:10EB3000000000000C004D71000000008F830054A5
+:10EB400008004D16240200068F8300543C02000189
+:10EB50008C425DB82463FF9C004310232C42006468
+:10EB6000144002502402000708004D240000000059
+:10EB700024020006A7A2001027B100100000802187
+:10EB80000C004D4B24040001261000012E02002031
+:10EB90001440FFFB000000000C004D4B0000202142
+:10EBA0000C004D4B240400010C004D4B00002021B3
+:10EBB0000C004D4B2404000124100010320200010F
+:10EBC0001040000200002021240400010C004D4BE5
+:10EBD000001080421600FFFA3202000124100010DB
+:10EBE0003202001310400002000020212404000122
+:10EBF0000C004D4B001080421600FFFA3202001349
+:10EC00000C004D4B240400010C004D4B0000202152
+:10EC100034108000962200000050102410400002A2
+:10EC200000002021240400010C004D4B0010804204
+:10EC30001600FFF8000000000C004D7100000000FD
+:10EC40008F83005408004D16240200088F8300545F
+:10EC50003C0200018C425DB82463FF9C00431023FA
+:10EC60002C4200641440020F2402000908004D24C5
+:10EC70000000000027B10010A7A0001000008021B4
+:10EC80000C004D4B24040001261000012E02002030
+:10EC90001440FFFB000000000C004D4B0000202141
+:10ECA0000C004D4B240400010C004D4B24040001CA
+:10ECB0000C004D4B000020212410001032020001F6
+:10ECC0001040000200002021240400010C004D4BE4
+:10ECD000001080421600FFFA3202000124100010DA
+:10ECE000320200181040000200002021240400011C
+:10ECF0000C004D4B001080421600FFFA3202001843
+:10ED00000C004D71341080000C004D7100000000AB
+:10ED10000C004D2B00000000504000050010804208
+:10ED20009622000000501025A6220000001080420C
+:10ED30001600FFF7000000000C004D71000080215C
+:10ED400097A2001027B1001034420001A7A20010C2
+:10ED50000C004D4B24040001261000012E0200205F
+:10ED60001440FFFB000000000C004D4B0000202170
+:10ED70000C004D4B240400010C004D4B00002021E1
+:10ED80000C004D4B2404000124100010320200013D
+:10ED90001040000200002021240400010C004D4B13
+:10EDA000001080421600FFFA320200012410001009
+:10EDB000320200181040000200002021240400014B
+:10EDC0000C004D4B001080421600FFFA3202001872
+:10EDD0000C004D4B240400010C004D4B0000202181
+:10EDE00034108000962200000050102410400002D1
+:10EDF00000002021240400010C004D4B0010804233
+:10EE00001600FFF8000000000C004D71000000002B
+:10EE10008F83005408004D162402000A8F8300548B
+:10EE20003C0200018C425DB82463FF9C0043102328
+:10EE30002C4200641440019B2402000B08004D2466
+:10EE40000000000027B10010A7A0001000008021E2
+:10EE50000C004D4B24040001261000012E0200205E
+:10EE60001440FFFB000000000C004D4B000020216F
+:10EE70000C004D4B240400010C004D4B24040001F8
+:10EE80000C004D4B00002021241000103202000124
+:10EE90001040000200002021240400010C004D4B12
+:10EEA000001080421600FFFA320200012410001008
+:10EEB000320200171040000200002021240400014B
+:10EEC0000C004D4B001080421600FFFA3202001772
+:10EED0000C004D71341080000C004D7100000000DA
+:10EEE0000C004D2B00000000504000050010804237
+:10EEF0009622000000501025A6220000001080423B
+:10EF00001600FFF7000000000C004D71000080218A
+:10EF100097A2001027B1001034420700A7A20010EA
+:10EF20000C004D4B24040001261000012E0200208D
+:10EF30001440FFFB000000000C004D4B000020219E
+:10EF40000C004D4B240400010C004D4B000020210F
+:10EF50000C004D4B2404000124100010320200016B
+:10EF60001040000200002021240400010C004D4B41
+:10EF7000001080421600FFFA320200012410001037
+:10EF8000320200171040000200002021240400017A
+:10EF90000C004D4B001080421600FFFA32020017A1
+:10EFA0000C004D4B240400010C004D4B00002021AF
+:10EFB00034108000962200000050102410400002FF
+:10EFC00000002021240400010C004D4B0010804261
+:10EFD0001600FFF8000000000C004D71000000005A
+:10EFE0008F83005408004D162402000C8F830054B8
+:10EFF0003C0200018C425DB82463FF9C0043102357
+:10F000002C420064144001272402001208004D2401
+:10F010000000000027B10010A7A000100000802110
+:10F020000C004D4B24040001261000012E0200208C
+:10F030001440FFFB000000000C004D4B000020219D
+:10F040000C004D4B240400010C004D4B2404000126
+:10F050000C004D4B00002021241000103202000152
+:10F060001040000200002021240400010C004D4B40
+:10F07000001080421600FFFA320200012410001036
+:10F08000320200141040000200002021240400017C
+:10F090000C004D4B001080421600FFFA32020014A3
+:10F0A0000C004D71341080000C004D710000000008
+:10F0B0000C004D2B00000000504000050010804265
+:10F0C0009622000000501025A62200000010804269
+:10F0D0001600FFF7000000000C004D7100008021B9
+:10F0E00097A2001027B1001034420010A7A2001010
+:10F0F0000C004D4B24040001261000012E020020BC
+:10F100001440FFFB000000000C004D4B00002021CC
+:10F110000C004D4B240400010C004D4B000020213D
+:10F120000C004D4B24040001241000103202000199
+:10F130001040000200002021240400010C004D4B6F
+:10F14000001080421600FFFA320200012410001065
+:10F1500032020014104000020000202124040001AB
+:10F160000C004D4B001080421600FFFA32020014D2
+:10F170000C004D4B240400010C004D4B00002021DD
+:10F18000341080009622000000501024104000022D
+:10F1900000002021240400010C004D4B001080428F
+:10F1A0001600FFF8000000000C004D710000000088
+:10F1B0008F83005408004D16240200138F830054DF
+:10F1C0003C0200018C425DB82463FF9C0043102385
+:10F1D0002C420064144000B32402000D08004D24AA
+:10F1E0000000000027B10010A7A00010000080213F
+:10F1F0000C004D4B24040001261000012E020020BB
+:10F200001440FFFB000000000C004D4B00002021CB
+:10F210000C004D4B240400010C004D4B2404000154
+:10F220000C004D4B00002021241000103202000180
+:10F230001040000200002021240400010C004D4B6E
+:10F24000001080421600FFFA320200012410001064
+:10F2500032020018104000020000202124040001A6
+:10F260000C004D4B001080421600FFFA32020018CD
+:10F270000C004D71341080000C004D710000000036
+:10F280000C004D2B00000000504000050010804293
+:10F290009622000000501025A62200000010804297
+:10F2A0001600FFF7000000000C004D7100008021E7
+:10F2B00097A2001027B100103042FFFEA7A2001055
+:10F2C0000C004D4B24040001261000012E020020EA
+:10F2D0001440FFFB000000000C004D4B00002021FB
+:10F2E0000C004D4B240400010C004D4B000020216C
+:10F2F0000C004D4B240400012410001032020001C8
+:10F300001040000200002021240400010C004D4B9D
+:10F31000001080421600FFFA320200012410001093
+:10F3200032020018104000020000202124040001D5
+:10F330000C004D4B001080421600FFFA32020018FC
+:10F340000C004D4B240400010C004D4B000020210B
+:10F35000341080009622000000501024104000025B
+:10F3600000002021240400010C004D4B00108042BD
+:10F370001600FFF8000000000C004D7100000000B6
+:10F380008F83005408004D162402000E240208400A
+:10F39000A7A2001027B10010000080210C004D4BE7
+:10F3A00024040001261000012E0200201440FFFB5F
+:10F3B000000000000C004D4B000020210C004D4BC4
+:10F3C000240400010C004D4B000020210C004D4B8B
+:10F3D0002404000124100010320200011040000239
+:10F3E00000002021240400010C004D4B001080423D
+:10F3F0001600FFFA3202000124100010320200133E
+:10F400001040000200002021240400010C004D4B9C
+:10F41000001080421600FFFA320200130C004D4B20
+:10F42000240400010C004D4B00002021341080000A
+:10F4300096220000005010241040000200002021FD
+:10F44000240400010C004D4B001080421600FFF810
+:10F45000000000000C004D71000000008F8300547C
+:10F46000240200103C010001AC225D003C010001BF
+:10F4700008004D26AC235DB88F8300543C02000188
+:10F480008C425DB82463FF9C004310232C4200642F
+:10F490001440000400000000240200113C0100019F
+:10F4A000AC225D008FBF00208FB1001C8FB0001810
+:10F4B00003E0000827BD00288F8500448F820044A8
+:10F4C0003C030001004310253C030008AF820044C8
+:10F4D0008F8400548F82005400A3282408004D37E5
+:10F4E000248400018F820054008210232C420002E9
+:10F4F0001440FFFC000000008F8200443C03FFFE2C
+:10F500003463FFFF00431024AF8200448F83005414
+:10F510008F82005408004D45246300018F820054FF
+:10F52000006210232C4200021440FFFC0000000087
+:10F5300003E0000800A010218F8300443C02FFF08C
+:10F540003442FFFF00042480006218243C020002C1
+:10F550000082202500641825AF8300448F82004478
+:10F560003C03FFFE3463FFFF00431024AF820044DE
+:10F570008F8300548F82005408004D5E2463000185
+:10F580008F820054006210232C4200021440FFFCC2
+:10F59000000000008F8200443C030001004310255E
+:10F5A000AF8200448F8300548F82005408004D6B5B
+:10F5B000246300018F820054006210232C42000259
+:10F5C0001440FFFC0000000003E000080000000001
+:10F5D0008F8200443C03FFF03463FFFF004310249C
+:10F5E000AF8200448F8200443C0300010043102599
+:10F5F000AF8200448F8300548F82005408004D7FF7
+:10F60000246300018F820054006210232C42000208
+:10F610001440FFFC000000008F8200443C03FFFE0A
+:10F620003463FFFF00431024AF8200448F830054F3
+:10F630008F82005408004D8D246300018F82005496
+:10F64000006210232C4200021440FFFC0000000066
+:10F6500003E000080000000027BDFFC8AFB300248E
+:10F6600000809821AFB5002C00A0A821AFB20020E7
+:10F6700000C0902132A2FFFFAFBF0030AFB400281E
+:10F68000AFB1001CAFB0001814400034A7B2001096
+:10F690003271FFFF27B20010000080210C004D4B9B
+:10F6A00024040001261000012E0200201440FFFB5C
+:10F6B000000000000C004D4B000020210C004D4BC1
+:10F6C000240400010C004D4B000020210C004D4B88
+:10F6D0002404000124100010320200011040000236
+:10F6E00000002021240400010C004D4B001080423A
+:10F6F0001600FFFA3202000124100010023010241C
+:10F700001040000200002021240400010C004D4B99
+:10F71000001080421600FFFA023010240C004D4BFE
+:10F72000240400010C004D4B000020213410800007
+:10F7300096420000005010241040000200002021DA
+:10F74000240400010C004D4B001080421200007593
+:10F750000000000008004DC9000000003274FFFFE7
+:10F7600027B10010A7A00010000080210C004D4B15
+:10F7700024040001261000012E0200201440FFFB8B
+:10F78000000000000C004D4B000020210C004D4BF0
+:10F79000240400010C004D4B240400010C004D4BCF
+:10F7A000000020212410001032020001104000024D
+:10F7B00000002021240400010C004D4B0010804269
+:10F7C0001600FFFA320200012410001002901024EB
+:10F7D0001040000200002021240400010C004D4BC9
+:10F7E000001080421600FFFA029010240C004D71A8
+:10F7F000341080000C004D71000000000C004D2BF7
+:10F8000000000000504000050010804296220000D9
+:10F8100000501025A6220000001080421600FFF7BD
+:10F82000000000000C004D710000000032A5FFFF39
+:10F830002402000154A200042402000297A2001036
+:10F8400008004E140052102514A200063271FFFF6A
+:10F8500097A200100012182700431024A7A200103E
+:10F860003271FFFF27B20010000080210C004D4BC9
+:10F8700024040001261000012E0200201440FFFB8A
+:10F88000000000000C004D4B000020210C004D4BEF
+:10F89000240400010C004D4B000020210C004D4BB6
+:10F8A0002404000124100010320200011040000264
+:10F8B00000002021240400010C004D4B0010804268
+:10F8C0001600FFFA3202000124100010023010244A
+:10F8D0001040000200002021240400010C004D4BC8
+:10F8E000001080421600FFFA023010240C004D4B2D
+:10F8F000240400010C004D4B000020213410800036
+:10F900009642000000501024104000020000202108
+:10F91000240400010C004D4B001080421600FFF83B
+:10F92000000000000C004D71000000008FBF00308F
+:10F930008FB5002C8FB400288FB300248FB2002025
+:10F940008FB1001C8FB0001803E0000827BD0038FD
+:10F9500000000000000000000000000027BDFFE8DC
+:10F96000AFBF00103C030001007718218C6383AC0B
+:10F97000240200081462022C008030213C020001A5
+:10F980008C425D9814400033000000008F850224F3
+:10F9900038A300202C63000138A200102C42000183
+:10F9A000006218251460000D38A300302C6300019C
+:10F9B00038A204002C4200010062182514600007E0
+:10F9C00038A304022C63000138A204042C42000175
+:10F9D0000062182510600005000000000C00429B2A
+:10F9E0000000000008004E8D2402000E0C0043DDD4
+:10F9F000000000003C0500018CA55CC80C0052A270
+:10FA0000000020213C0300018C635CC82402000438
+:10FA1000146200052403FFFB3C0200018C425CC41D
+:10FA200008004E892403FFF73C0200018C425CC4AD
+:10FA3000004310243C010001AC225CC42402000EEF
+:10FA40003C0100010C00429BAC227DD00800508795
+:10FA5000000000008F8202203C03040000431024B9
+:10FA6000104000272403FFBF8F8502243C020001C1
+:10FA70008C427DDC00A32024004310241482000C5F
+:10FA8000000000003C0200018C427DE024420001A5
+:10FA90003C010001AC227DE02C4200021440000831
+:10FAA000240200013C01000108004EADAC227E00A2
+:10FAB0003C010001AC207DE03C010001AC207E0057
+:10FAC0003C0200018C427E001040000630A2004043
+:10FAD00010400004240200013C01000108004EB85F
+:10FAE000AC227E043C010001AC207E043C010001FC
+:10FAF000AC257DDC3C01000108004EC8AC207E1026
+:10FB0000240200013C010001AC227E103C010001F6
+:10FB1000AC207E003C010001AC207DE03C010001F6
+:10FB2000AC207E043C010001AC207DDC3C030001E4
+:10FB30008C637DD03C0200018C427DD410620003B6
+:10FB40003C0202003C010001AC237DD400C2102421
+:10FB5000104000072463FFFF8F820220240300016E
+:10FB60003C010001AC235CCC080050853C03F7004D
+:10FB70002C62000E104001A8000310803C0100011F
+:10FB8000002208218C225B80004000080000000059
+:10FB90003C010001AC207E003C010001AC207DE076
+:10FBA0003C010001AC207DDC3C010001AC207E0466
+:10FBB0003C010001AC207DF83C010001AC207DF04F
+:10FBC0000C00486AAF800224240200023C010001BC
+:10FBD000AC227DD03C0200018C427E1014400056C5
+:10FBE0003C03FDFF8EE200003463FFFF004310245E
+:10FBF0000C00429BAEE20000AF8002048F82020044
+:10FC00002403FFFD00431024AF8202003C010001E9
+:10FC1000AC207E208F8300543C0200018C427DF892
+:10FC2000240400013C010001AC247E0C24420001AC
+:10FC30003C010001AC227DF82C4200043C01000193
+:10FC4000AC237DF414400006240200033C010001B3
+:10FC5000AC245CCC3C01000108005083AC207DF852
+:10FC60003C01000108005083AC227DD08F830054FA
+:10FC70003C0200018C427DF42463D8F00043102341
+:10FC80002C42271014400003240200043C01000110
+:10FC9000AC227DD03C0200018C427E101440002634
+:10FCA0003C03FDFF8EE200003463FFFF004310249D
+:10FCB00008005083AEE200003C0400018C845D9C8F
+:10FCC0003C0100010C00508AAC207DE83C020001A0
+:10FCD0008C427E1CAF8202043C0200018C427E10EA
+:10FCE000144000153C03FDFF8EE200003463FFFF6B
+:10FCF00000431024AEE200008F8202043042003044
+:10FD00001440013C240200023C0300018C637E1C71
+:10FD1000240200053C010001AC227DD03C01000121
+:10FD200008005083AC237E203C0200018C427E10F0
+:10FD3000104000103C03FDFF3C0200018C425D6C52
+:10FD4000244200013C010001AC225D6C2C42000207
+:10FD500014400131240200013C010001AC225D7419
+:10FD60003C010001AC205D6C3C01000108005083A7
+:10FD7000AC225CCC8EE200003463FFFF0043102411
+:10FD8000AEE200003C0200018C427E0010400122E5
+:10FD9000000000003C0200018C427DDC1040011E8E
+:10FDA000000000003C010001AC227E082402000398
+:10FDB0003C010001AC227DE0080050242402000632
+:10FDC0003C010001AC207DE88F82020434420040F7
+:10FDD000AF8202043C0200018C427E202403000713
+:10FDE0003C010001AC237DD0344200403C010001C5
+:10FDF000AC227E203C0200018C427E0010400005B7
+:10FE0000000000003C0200018C427DDC104000F943
+:10FE1000240200023C05000124A57DE08CA2000024
+:10FE20002C424E21104000F3240200023C0200014B
+:10FE30008C427E04104000F82404FFBF3C02000105
+:10FE40008C427DDC3C0300018C637E08004410245E
+:10FE50000064182410430004240200013C01000146
+:10FE600008005083AC227DD024020003ACA2000025
+:10FE7000240200083C010001AC227DD03C020001BC
+:10FE80008C427E0C1040000C240200013C04000156
+:10FE90000C0050978C847DDC3C0200018C427E2853
+:10FEA00014400005240200013C0200018C427E2423
+:10FEB00010400006240200013C010001AC225CCC91
+:10FEC0003C01000108005083AC207DF83C02000199
+:10FED0008C427DF03C0300018C637DDC2C420001F0
+:10FEE000000210C0306300083C010001AC227DF02C
+:10FEF0003C010001AC237DEC8F83005424020009F7
+:10FF00003C010001AC227DD03C010001080050837F
+:10FF1000AC237DF48F8300543C0200018C427DF4BD
+:10FF20002463D8F0004310232C422710144000A86B
+:10FF3000000000003C0200018C427E0010400005E1
+:10FF4000000000003C0200018C427DDC104000A952
+:10FF5000240200023C03000124637DE08C62000067
+:10FF60002C424E21104000A3240200023C0200015A
+:10FF70008C427E0C1040000E000000003C0200018C
+:10FF80008C427DDC3C010001AC207E0C30420080C4
+:10FF90001040002F2402000C8F82020430420080A7
+:10FFA0001440000C24020003080050112402000C2D
+:10FFB0003C0200018C427DDC304200801440000590
+:10FFC000240200038F820204304200801040001F90
+:10FFD00024020003AC6200002402000A3C0100017C
+:10FFE000AC227DD03C04000124847E188C82000069
+:10FFF0003C0300018C637DF000431025AF820204B6
+:020000021000EC
+:100000008C8300003C0400018C847DF02402000BF2
+:100010003C010001AC227DD0006418253C010001A8
+:10002000AC237E203C05000124A57DE08CA20000CD
+:100030002C424E211040006F240200023C020001BD
+:100040008C427E1010400005000000002402000CCD
+:100050003C01000108005083AC227DD03C0200012D
+:100060008C427E001040006C000000003C04000147
+:100070008C847DDC1080005E308200083C0300012F
+:100080008C637DEC10620064240200033C010001DB
+:10009000AC247E08ACA20000240200063C01000152
+:1000A00008005083AC227DD08F82020034420002CF
+:1000B000AF8202008F8300542402000D3C01000136
+:1000C000AC227DD03C010001AC237DF48F83005431
+:1000D0003C0200018C427DF42463D8F000431023DD
+:1000E0002C4227101440003A000000003C0200019E
+:1000F0008C427E10104000292402000E3C030001B7
+:100100008C637E243C01000114600015AC227DD07C
+:100110000C0043DD000000003C0500018CA55CC81C
+:100120000C0052A2000020213C0300018C635CC83B
+:1001300024020004146200052403FFFB3C020001BA
+:100140008C425CC4080050522403FFF73C020001BB
+:100150008C425CC4004310243C010001AC225CC40E
+:100160008EE200003C03020000431025AEE20000D6
+:100170008F8202243C010001AC227E2C8F8202205F
+:100180002403FFFB00431024AF8202208F82022051
+:100190003442000208005083AF8202203C0200017A
+:1001A0008C427E0010400005000000003C0200016F
+:1001B0008C427DDC1040000F240200023C02000152
+:1001C0008C427DE02C424E211040000A24020002A5
+:1001D0003C0200018C427E001040000F0000000035
+:1001E0003C0200018C427DDC1440000B000000004A
+:1001F000240200023C01000108005083AC227DD0A3
+:100200003C0200018C427E00104000030000000010
+:100210000C00429B000000008F8202203C03F7008C
+:1002200000431025AF8202208FBF001003E00008BA
+:1002300027BD00183C03000124637E288C62000067
+:1002400010400005344220003C010001AC227E1C1D
+:1002500008005095AC6000003C010001AC247E1CFD
+:1002600003E000080000000027BDFFE030820030FE
+:10027000AFBF00183C010001AC227E24144000678F
+:100280003C02FFFF34421F0E008210241440006124
+:1002900024020030308220001040005D3083800056
+:1002A00000031A0230820001000212003C04000127
+:1002B0008C845D9C00621825000331C23C03000160
+:1002C00024635D78308280000002120230840001D5
+:1002D0000004220000441025000239C200061080EC
+:1002E0000043102100471021904300002402000128
+:1002F00010620025000000001060000724020002C8
+:1003000010620013240200031062002C3C05000F51
+:10031000080050F9000000008F8202002403FEFF55
+:1003200000431024AF8202008F8202203C03FFFEB4
+:100330003463FFFF00431024AF8202203C01000120
+:10034000AC207E443C01000108005104AC207E4CEE
+:100350008F82020034420100AF8202008F820220AD
+:100360003C03FFFE3463FFFF00431024AF820220F2
+:10037000240201003C010001AC227E443C0100014A
+:1003800008005104AC207E4C8F8202002403FEFF43
+:1003900000431024AF8202008F8202203C03000140
+:1003A00000431025AF8202203C010001AC207E44B6
+:1003B0003C01000108005104AC237E4C8F820200F6
+:1003C00034420100AF8202008F8202203C03000110
+:1003D00000431025AF820220240201003C010001ED
+:1003E000AC227E443C01000108005104AC237E4C49
+:1003F00034A5FFFF3C04000124845BB8AFA30010C8
+:100400000C002403AFA000140800510400000000F9
+:10041000240200303C010001AC227E288FBF00186E
+:1004200003E0000827BD00200000000027BDFFC832
+:10043000AFB2002800809021AFB3002C00A098211B
+:10044000AFB0002000C080213C04000124845BD0B8
+:100450003C0500093C0200018C425CC834A59001B7
+:100460000240302102603821AFBF0030AFB100241C
+:10047000A7A0001AAFB000140C002403AFA2001014
+:1004800024020002126200832E6200031040000565
+:10049000240200011262000A000000000800529BC2
+:1004A0000000000024020004126200FA2402000886
+:1004B000126200F93C02FFEC0800529B00000000B1
+:1004C0003C0200018C425CC4304200021440000433
+:1004D000001289403C02FFFB3442FFFF02028024ED
+:1004E0003C01000100310821AC307E3C3C02400060
+:1004F000020210241040004E001023C2308400304D
+:10050000001013823042001C3C03000124635D088C
+:1005100000431021008238213C02002002021024F6
+:1005200010400006240201003C01000100310821B6
+:10053000AC227E40080051503C0200803C0100018A
+:1005400000310821AC207E403C02008002021024D1
+:1005500010400006001219403C0200013C0100015D
+:10056000002308210800515CAC227E480012114093
+:100570003C01000100220821AC207E4894E40000E8
+:100580003C0300018C635DBC240200051062001076
+:10059000A7A400183202400010400002348240003C
+:1005A000A7A200182404000194E20002240500041C
+:1005B00024E60002344200010C00498EA4E200024D
+:1005C00024040001000028210C00498E27A60018F1
+:1005D0003C0200018C425CC8241100013C01000176
+:1005E000AC315CD414530004320280000C00429BF6
+:1005F00000000000320280001040011F00000000D7
+:100600000C00429B000000003C0300018C635DBCB9
+:100610002402000510620118240200023C010001BE
+:10062000AC315CCC3C0100010800529BAC225CC8A0
+:10063000240400012405000427B0001A0C00498E90
+:100640000200302124040001000028210C00498E02
+:10065000020030213C020001005110218C427E3406
+:100660003C0400018C845CC83C03BFFF3463FFFF83
+:100670003C010001AC335CD4004310243C01000178
+:1006800000310821109300FAAC227E340800529BFE
+:10069000000000003C02200002021024104000056F
+:1006A000240200013C010001AC225D98080051AD1C
+:1006B000001289403C010001AC205D980012894085
+:1006C0003C01000100310821AC307E383C02400082
+:1006D0000202102414400016000000003C02000139
+:1006E0008C425D9810400008240400042405000199
+:1006F0000C004D9324062000240200013C0100015F
+:1007000000370821AC2283AC3C02000100511021CB
+:100710008C427E303C03BFFF3463FFFF0043102454
+:100720003C0100010031082108005299AC227E30C2
+:100730003C0200018C425D98104000283C0300A060
+:10074000020310245443000D3C0200203C0200012F
+:100750008C425D9C240301003C0100010031082112
+:10076000AC237E443C0300013C0100010031082120
+:10077000AC237E4C080051F03442040002021024E5
+:1007800010400008240301003C0200018C425D9CE3
+:100790003C01000100310821AC237E44080051F0E7
+:1007A000344208003C020080020210241040002E57
+:1007B0003C0300013C0200018C425D9C3C010001B5
+:1007C00000310821AC237E4C34420C003C01000176
+:1007D000AC225D9C08005218240400013C02002059
+:1007E0000202102410400006240201003C01000116
+:1007F00000310821AC227E44080052013C020080F6
+:100800003C01000100310821AC207E443C02008004
+:100810000202102410400007001219403C0200019F
+:100820003C01000100230821AC227E4C0800520F3D
+:1008300024040001001211403C01000100220821A3
+:10084000AC207E4C240400010000282127B0001EAB
+:100850000C00494C02003021240400010000282132
+:100860000C00494C02003021240400012405000141
+:1008700027B0001C0C00494C020030212404000168
+:10088000240500010C00494C020030210800529957
+:10089000000000003C02FFEC3442FFFF0202802413
+:1008A0003C02000802028025001211403C010001B8
+:1008B00000220821AC307E383C02200002021024C5
+:1008C00010400009000000003C0200018C425D74F1
+:1008D00014400005240200013C010001AC225D9897
+:1008E0000800523A3C0240003C010001AC205D98F7
+:1008F0003C024000020210241440001E00000000D0
+:100900003C0200018C425D983C010001AC205CE09F
+:1009100010400007240220203C010001AC225D9C15
+:10092000240200013C01000100370821AC2283AC05
+:100930003C04BFFF001219403C020001004310219B
+:100940008C427E303C0500018CA55CC83484FFFFDE
+:10095000004410243C01000100230821AC227E3019
+:100960002402000110A20044000000000800529977
+:10097000000000003C0200018C425D981040001C09
+:10098000240220003C010001AC225D9C3C0300A03D
+:100990000203102414430005001211403402A00089
+:1009A0003C01000108005294AC225D9C3C03000114
+:1009B000006218218C637E383C0200200062102403
+:1009C00010400004240220013C0100010800529460
+:1009D000AC225D9C3C020080006210241040001F8D
+:1009E0003402A0013C01000108005294AC225D9C3D
+:1009F0003C0200200202102410400007001219409F
+:100A0000240201003C01000100230821AC227E44A5
+:100A1000080052883C020080001211403C01000195
+:100A200000220821AC207E443C02008002021024F7
+:100A300010400006001219403C0200013C01000178
+:100A40000023082108005294AC227E4C0012114071
+:100A50003C01000100220821AC207E4C3C03000137
+:100A60008C635CC8240200011062000300000000D7
+:100A70000C00429B000000008FBF00308FB3002CA1
+:100A80008FB200288FB100248FB0002003E000084F
+:100A900027BD003827BDFFD8AFB2002000809021CD
+:100AA000AFB1001C0000882124020002AFBF002467
+:100AB000AFB00018A7A0001210A200D3A7A000108A
+:100AC0002CA20003104000052402000110A2000A1D
+:100AD00000128140080053800220102124020004EB
+:100AE00010A2007D2402000810A2007C0012294000
+:100AF00008005380022010213C03000100701821DF
+:100B00008C637E3C3C0240000062102414400009CB
+:100B1000240400013C027FFF3442FFFF006288246E
+:100B20003C01000100300821AC317E3408005380C4
+:100B300002201021240500010C00494C27A60010BA
+:100B400024040001240500010C00494C27A60010D4
+:100B500097A2001030420004104000343C114000C5
+:100B60003C0200018C425DBC2443FFFF2C62000666
+:100B700010400034000310803C01000100220821D5
+:100B80008C225BE00040000800000000240400010B
+:100B90002405001127B000120C00494C020030213E
+:100BA00024040001240500110C00494C02003021EE
+:100BB00097A5001230A24000104000023C04001033
+:100BC0003C0400083C0300010800530130A28000EF
+:100BD000240400012405001427B000120C00494C25
+:100BE0000200302124040001240500140C00494CAB
+:100BF0000200302197A5001230A210001040000220
+:100C00003C0400103C0400083C03000130A2080032
+:100C1000544000013C0300023C02800002221025E7
+:100C2000006418250800530E004388253C1100017C
+:100C3000023088218E317E3C3C027FFF3442FFFF30
+:100C4000022288243C0200018C425CD81040001D26
+:100C5000001211403C0200018C425D9810400002DD
+:100C60003C02200002228825001211403C010001B4
+:100C7000002208218C227E40104000033C0200200C
+:100C800008005322022288253C02FFDF3442FFFF86
+:100C900002228824001211403C0100010022082198
+:100CA0008C227E48104000033C0200800800532D37
+:100CB000022288253C02FF7F3442FFFF0222882463
+:100CC000001211403C01000100220821AC317E34A9
+:100CD0000800538002201021001229403C0300012B
+:100CE000006518218C637E383C02400000621024AD
+:100CF000144000083C027FFF3442FFFF006288245A
+:100D00003C01000100250821AC317E3008005380F1
+:100D1000022010213C0200018C425CD810400033BC
+:100D20003C11C00C3C0200018C425D743C04C00CC0
+:100D3000348420003C0300018C635D980002102B7A
+:100D40000002102300441024106000030051882585
+:100D50003C022000022288253C02000100451021AF
+:100D60008C427E44104000033C0200200800535D8A
+:100D7000022288253C02FFDF3442FFFF0222882442
+:100D8000001211403C010001002208218C227E4CFF
+:100D9000104000033C0200800800536802228825AE
+:100DA0003C02FF7F3442FFFF022288243C02000104
+:100DB0008C425D60104000023C020800022288253F
+:100DC0003C0200018C425D64104000023C020400C1
+:100DD000022288253C0200018C425D68104000061A
+:100DE0003C0201000800537B022288253C027FFF61
+:100DF0003442FFFF00628824001211403C010001D0
+:100E000000220821AC317E30022010218FBF002447
+:100E10008FB200208FB1001C8FB0001803E00008D3
+:100E200027BD002827BDFFD8AFB400200080A02137
+:100E3000AFBF0024AFB3001CAFB20018AFB10014B5
+:100E4000AFB000108F9002003C0300018C635CC8BF
+:100E50008F93022024020002106200632C620003C0
+:100E600010400005240200011062000A001419401D
+:100E70000800544800000000240200041062005AD8
+:100E800024020008106200590014914008005448E0
+:100E9000000000003C040001008320218C847E3C83
+:100EA0003C110001022388218E317E343C02400037
+:100EB000008210241040003E3C0200080222102450
+:100EC00010400020361000023C02000100431021B7
+:100ED0008C427E4010400005361000203610010084
+:100EE0003C020020080053BD022288252402FEFF98
+:100EF000020280243C02FFDF3442FFFF02228824EA
+:100F0000001411403C010001002208218C227E487F
+:100F1000104000053C020001026298253C0200805E
+:100F2000080053DC022288253C02FFFE3442FFFF0A
+:100F3000026298243C02FF7F3442FFFF080053DC2A
+:100F4000022288242402FEDF020280243C02FFFEEB
+:100F50003442FFFF026298243C02FF5F3442FFFFED
+:100F6000022288243C01000100230821AC207E409D
+:100F70003C01000100230821AC207E480C00486A97
+:100F800000000000AF900200AF9302208F82022089
+:100F90002403FFFB00431024AF8202208F82022033
+:100FA00034420002AF820220080053F300141140C3
+:100FB0008F8202002403FFFD004310240C00486AC6
+:100FC000AF8202003C02BFFF3442FFFF0C00429B95
+:100FD00002228824001411403C0100010022082153
+:100FE00008005448AC317E34001491403C040001A8
+:100FF000009220218C847E383C110001023288212D
+:101000008E317E303C0240000082102414400011DA
+:10101000000000003C0200018C425D981440000674
+:101020003C02BFFF8F820200344200020C00486A7B
+:10103000AF8202003C02BFFF3442FFFF0C00429B24
+:10104000022288243C010001003208210800544893
+:10105000AC317E303C0200018C425D9810400005AE
+:101060003C0200203C0200018C425D741040002BC9
+:101070003C0200200082102410400007361000209F
+:10108000240201003C01000100320821AC227E4410
+:1010900008005428361001003C01000100320821EC
+:1010A000AC207E442402FEFF020280243C02008029
+:1010B0000082102410400007001419403C02000177
+:1010C0003C01000100230821AC227E4C0800543969
+:1010D00002629825001411403C0100010022082101
+:1010E000AC207E4C3C02FFFE3442FFFF026298249B
+:1010F0000C00486A00000000AF900200AF9302208D
+:101100008F8202202403FFFB00431024AF820220C1
+:101110008F82022034420002AF820220001411406C
+:101120003C01000100220821AC317E308FBF002439
+:101130008FB400208FB3001C8FB200188FB1001441
+:101140008FB0001003E0000827BD00282448656127
+:101150006465723A202F70726F6A656374732F72C0
+:1011600063732F73772F67652F2E2F6E69632F663A
+:10117000772F636F6D6D6F6E2F66776D61696E2E61
+:10118000632C7620312E312E322E313120313939F7
+:10119000382F30342F32372032323A31333A34322A
+:1011A00020736875616E6720457870202400000008
+:1011B0007468655F4441574E00000000535441433A
+:1011C0004B5F312000000000426164536E64526E38
+:1011D000670000003F456E71457674003F6E6F51A9
+:1011E00064457650000000006576526E6746756C67
+:1011F0006C000000496C6C436F6E66527800000012
+:1012000053656E64436B53756D00000052656376E1
+:10121000566C616E0000000000000000244865610B
+:101220006465723A202F70726F6A656374732F72EF
+:1012300063732F73772F67652F2E2F6E69632F6669
+:10124000772F636F6D6D6F6E2F74696D65722E638E
+:101250002C7620312E312E322E3820313939382F4C
+:1012600030372F33312031373A35383A343520731F
+:101270006875616E6720457870202400542D446D98
+:101280006152643100000000542D446D61424200FF
+:10129000542D446D613200003F6E6F5164547845A7
+:1012A000000000003F6E6F5164527845000000005E
+:1012B000656E714D4576504661696C00656E714D85
+:1012C00045764661696C00006661696C456E454D06
+:1012D000000000003F456E71457674003F6E6F510F
+:1012E00064457650000000006576526E6746756C66
+:1012F0006C00000000000000000000002448656150
+:101300006465723A202F70726F6A656374732F720E
+:1013100063732F73772F67652F2E2F6E69632F6688
+:10132000772F636F6D6D6F6E2F636F6D6D616E6480
+:101330002E632C7620312E312E322E313020313951
+:1013400039382F31312F31382031373A31313A3174
+:101350003820736875616E6720457870202400001E
+:101360003F4D626F78457674000000004E4F636F0A
+:101370006D616E6400000000687374655F455252D1
+:1013800000000000412D45727242756300000000AC
+:101390004552524F522D416464000000656E714DFC
+:1013A0004576504661696C00656E714D45764661C3
+:1013B000696C00006661696C456E454D0000000077
+:1013C000442D4572724C617374000000442D4572C7
+:1013D000723200006D4373744D6445525200000038
+:1013E00070726F6D4D6445525200000046696C7416
+:1013F0004D64455252000000636D645F45525200D7
+:101400003F456E71457674003F6E6F51644576506E
+:10141000000000006576526E6746756C6C00000037
+:101420000000000000006EA000007FBC00006E38CD
+:1014300000008734000082B00000878000008780B1
+:1014400000006F540000769400007F0C000080A81C
+:10145000000080740000878000007E70000080CC57
+:1014600000006E64000081CC00000000244865612B
+:101470006465723A202F70726F6A656374732F729D
+:1014800063732F73772F67652F2E2F6E69632F6617
+:10149000772F636F6D6D6F6E2F646D612E632C7689
+:1014A00020312E312E322E3320313939382F30343D
+:1014B0002F32372032323A31333A34312073687563
+:1014C000616E67204578702024000000646D6172B1
+:1014D0006441544E00000000646D61777241544EC7
+:1014E00000000000000000000000000024486561CA
+:1014F0006465723A202F70726F6A656374732F721D
+:1015000063732F73772F67652F2E2F6E69632F6696
+:10151000772F636F6D6D6F6E2F74726163652E63CD
+:101520002C7620312E312E322E3220313939382F7F
+:1015300030342F32372032323A31333A353020735B
+:101540006875616E672045787020240024486561C5
+:101550006465723A202F70726F6A656374732F72BC
+:1015600063732F73772F67652F2E2F6E69632F6636
+:10157000772F636F6D6D6F6E2F646174612E632CB6
+:101580007620312E312E322E3220313939382F301B
+:10159000342F32372032323A31333A3430207368C4
+:1015A00075616E67204578702024000046575F56AD
+:1015B000455253494F4E3A2023312046726920410B
+:1015C000707220372031373A35353A34382050445C
+:1015D000542032303030000046575F434F4D504961
+:1015E0004C455F54494D453A2031373A35353A3408
+:1015F0003800000046575F434F4D50494C455F420D
+:10160000593A2064657672637300000046575F4361
+:101610004F4D50494C455F484F53543A20636F6DCE
+:10162000707574650000000046575F434F4D504988
+:101630004C455F444F4D41494E3A20656E672E61DF
+:101640006374656F6E2E636F6D00000046575F43D5
+:101650004F4D50494C45523A20676363207665727E
+:1016600073696F6E20322E372E32000000000000AA
+:101670000000000000000000000000002448656138
+:101680006465723A202F70726F6A656374732F728B
+:1016900063732F73772F67652F2E2F6E69632F6605
+:1016A000772F636F6D6D6F6E2F6D656D2E632C766A
+:1016B00020312E312E322E3220313939382F30342C
+:1016C0002F32372032323A31333A3434207368754E
+:1016D000616E672045787020240000002448656111
+:1016E0006465723A202F70726F6A656374732F722B
+:1016F00063732F73772F67652F2E2F6E69632F66A5
+:10170000772F636F6D6D6F6E2F73656E642E632C14
+:101710007620312E312E322E313120313939382F89
+:1017200031322F32322031373A31373A3535207362
+:101730006875616E6720457870202400736E64645C
+:10174000654E6F51200000006E6F454E515F54583A
+:1017500000000000736E6464744E6F51200000003E
+:101760003F6E6F516454784500000000756E6B72D7
+:101770006474797065000000000000000000ACCCCB
+:101780000000ACCC0000AD9C0000AAB00000AAB0E4
+:101790000000AD9C0000AD9C0000AD9C0000AD9C25
+:1017A0000000AD9C0000AD9C0000AD9C0000AD9C15
+:1017B0000000AD9C0000AD9C0000AD9C0000AD9C05
+:1017C0000000AD9C0000AD7C000000000000BCA843
+:1017D0000000BCA80000BD700000AE4C0000B05876
+:1017E0000000BD700000BD700000BD700000BD7045
+:1017F0000000BD700000BD700000BD700000BD7035
+:101800000000BD700000BD700000BD700000BD7024
+:101810000000BD700000BD540000B0402448656168
+:101820006465723A202F70726F6A656374732F72E9
+:1018300063732F73772F67652F2E2F6E69632F6663
+:10184000772F636F6D6D6F6E2F726563762E632CCD
+:101850007620312E312E322E313920313939382F40
+:1018600030372F32342032313A33303A303520732A
+:101870006875616E6720457870202400706B52781F
+:101880004552520066726D324C617267650000000D
+:1018900072784E6F527842640000000072785144B2
+:1018A0006D61444600000000727851446D6142460B
+:1018B000000000003F6E6F51645278450000000048
+:1018C000706B5278455252730000000066726D32A0
+:1018D0004C7267530000000072784E6F42645300F0
+:1018E0003F724264446D6146000000003F724A420C
+:1018F00064446D4600000000000000000000F6781F
+:101900000000F6780000F6780000F6780000F6781F
+:101910000000F6780000F6780000F6780000F6780F
+:101920000000F6780000F6780000F6780000F678FF
+:101930000000F6780000F6780000F6700000F670FF
+:101940000000F670572D444D41456E4600000000E2
+:10195000000000000000FDC00001015C0000FDDC93
+:101960000001015C0001015C0001015C0001015CFF
+:101970000001015C0001015C0000F7040001015C52
+:101980000001015C0001015C0001015C0001015CDF
+:101990000001015400010154000101542448656113
+:1019A0006465723A202F70726F6A656374732F7268
+:1019B00063732F73772F67652F2E2F6E69632F66E2
+:1019C000772F636F6D6D6F6E2F6D61632E632C7655
+:1019D00020312E312E322E313220313939382F300C
+:1019E000342F32372032323A31333A34322073686E
+:1019F00075616E6720457870202400006D61637406
+:101A00007841544E000000004E7453796E264C6BA2
+:101A10000000000072656D61737372740000000055
+:101A20006C696E6B444F574E00000000656E714D3F
+:101A30004576504661696C00656E714D457646612C
+:101A4000696C00006661696C456E454D00000000E0
+:101A50006C696E6B55500000000000002448656101
+:101A60006465723A202F70726F6A656374732F72A7
+:101A700063732F73772F67652F2E2F6E69632F6621
+:101A8000772F636F6D6D6F6E2F636B73756D2E6344
+:101A90002C7620312E312E322E3220313939382F0A
+:101AA00030342F32372032323A31333A33392073DF
+:101AB0006875616E672045787020240050726F62EF
+:101AC00065506879000000006C6E6B4153535254AE
+:101AD0000000000000011B2C00011BC400011BF8CA
+:101AE00000011C2C00011C5800011C6C00011CA8EA
+:101AF0000001207C00011DE400011E2400011E5095
+:101B000000011E9000011EC000011EFC00011F30DC
+:101B10000001207C000122C0000122D80001230026
+:101B2000000123200001234800012478000124A0A3
+:101B3000000124F40001251C000000000001278C96
+:101B40000001285C0001293400012A0400012A60F8
+:101B500000012B3C00012B6400012C4000012C688B
+:101B600000012E1000012E3800012FE0000131D8B5
+:101B70000001346C000133800001346C00013498A2
+:101B800000013008000131B00000000000013B847A
+:101B900000013BC800013C6000013CAC00013D1C61
+:101BA00000013DB400013DE800013E7000013F0826
+:101BB00000013FD8000140180001409C000140C0D6
+:101BC000000141F4646F42617365506700000000DA
+:101BD00000000000000000000000000073746D6150
+:101BE000634C4E4B000000000000000000014C3828
+:101BF00000014C3800014B8000014BC400014C38FF
+:101C000000014C380000000000000000000000004F
+:101C100000000000000000000000000000000000C4
+:101C2000000000000000000000000000416C74652E
+:101C30006F6E204163654E4943205600416C7465C8
+:101C40006F6E204163654E49432056004242424236
+:101C50000000000000000000000000000013541805
+:101C60000013E7FC0000000000000000000000007E
+:101C70000000000000000000000000000060CF0035
+:101C800000000060CF000000000000000000000025
+:101C90000000000000000000000000000000000044
+:101CA0000000000000000000000000000000000034
+:101CB0000000000000000000000000000000000024
+:101CC0000000000000000000000000000000000014
+:101CD0000000000000000000000000030000000001
+:101CE00000000001000000000000000000000000F3
+:101CF00000000001000000000000000100000000E2
+:101D000000000000000000000000000000000001D2
+:101D100000000001000000000000000000000000C2
+:101D20000000000000000000010000002100000091
+:101D30001200014000000000000000002000000030
+:101D4000120000A0000000001200006012000180DC
+:101D5000120001E000000000000000000000000090
+:101D60000000000100000000000000000000000072
+:101D70000000000000000000000000000000000261
+:101D8000000000000000000000030001000000014E
+:0C1D900000030201000000000000000041
+:00000001FF
+/* tg1 firmware v12.4.11 */
diff --git a/firmware/acenic/tg2.bin.ihex b/firmware/acenic/tg2.bin.ihex
new file mode 100644 (file)
index 0000000..a9ff4f4
--- /dev/null
@@ -0,0 +1,4844 @@
+:100000000C040B0000004000000040000000000055
+:1000100010000003000000000000000D0000000DB3
+:100020003C1D00018FBD6D2003A0F0213C1000009D
+:10003000261040000C0010C0000000000000000D61
+:100040003C1D00018FBD6D2403A0F0213C10000079
+:10005000261040000C0017E0000000000000000D1A
+:100060000000000000000000000000000000000090
+:100070000000000000000000000000000000000080
+:100080000000000000000000000000000000000070
+:100090000000000000000000000000000000000060
+:1000A0000000000000000000000000000000000050
+:1000B0000000000000000000000000000000000040
+:1000C0000000000000000000000000000000000030
+:1000D0000000000000000000000000000000000020
+:1000E0000000000000000000000000000000000010
+:1000F0000000000000000000000000000000000000
+:1001000000000000000000000000000002000008E5
+:10011000000000000800172F3C0A00010800172FFC
+:100120003C0A00020800172F0000000008002CAC59
+:100130000000000008002C4F000000000800172FEE
+:100140003C0A00040800328A0000000008001A522D
+:10015000000000000800394D00000000080038F4DD
+:10016000000000000800172F3C0A0006080039BBF9
+:100170003C0A00070800172F3C0A00080800172F48
+:100180003C0A000908003A130000000008002EA6EF
+:10019000000000000800172F3C0A000B0800172F72
+:1001A0003C0A000C0800172F3C0A000D080028FB31
+:1001B0000000000008002890000000000800172F31
+:1001C0003C0A000E0800208C0000000008001964A2
+:1001D0000000000008001A040000000008003CA60F
+:1001E0000000000008003C94000000000800172FE9
+:1001F000000000000800191A000000000800172F76
+:10020000000000000800172F3C0A00130800172FF9
+:100210003C0A001400000000000000000000000084
+:1002200000000000000000000000000000000000CE
+:1002300000000000000000000000000000000000BE
+:1002400000000000000000000000000000000000AE
+:10025000000000000000000000000000000000009E
+:10026000000000000000000000000000000000008E
+:10027000000000000000000000000000000000007E
+:10028000000000000000000000000000000000006E
+:10029000000000000000000000000000000000005E
+:1002A000000000000000000000000000000000004E
+:1002B000000000000000000000000000000000003E
+:1002C000000000000000000000000000000000002E
+:1002D000000000000000000000000000000000001E
+:1002E000000000000000000000000000000000000E
+:1002F00000000000000000000000000000000000FE
+:1003000000000000000000000000000027BDFFE02A
+:100310003C1CC000AFBF001CAFB000188F82014072
+:1003200024030003AF8300EC344200040C002B20B4
+:10033000AF8201403C0100C00C001763AC203FFCC1
+:10034000004018213C0200103C010001AC236E9CCF
+:10035000106200110043102B144000023C020020E8
+:100360003C0200081062000C240501003C0600015C
+:100370008CC66E9C3C04000124845C74000038210F
+:10038000AFA000100C002B3BAFA000143C020020DB
+:100390003C010001AC226E9C240200083C010001DB
+:1003A000AC226EB42402001F3C010001AC226EC4DA
+:1003B000240200163C010001AC226E983C05FFFEB1
+:1003C00034A56F083C0200018C426E9C3C03000285
+:1003D000246390103C0400018C846CC400431023FF
+:1003E00014800002004580212610FA382402F00013
+:1003F000020280240C00178502002021020228231B
+:100400003C0400200082182300651823247BB000E0
+:100410003C03FFFE3463BF080363B8213C0600BF02
+:1004200034C6F0003C0700018CE76CC03C0300BF01
+:100430003463E000008520233C010001AC246EA859
+:10044000008220233C010001AC256E90000528426B
+:100450003C010001AC226E8427620FFC3C010001CC
+:10046000AC226D2027621FFC00DB3023007B1823A9
+:100470003C010001AC246E883C010001AC256EAC4F
+:100480003C010001AC226D24AF86015010E0001148
+:10049000AF8302503C1D00018FBD6CCC03A0F02146
+:1004A0000C001749000000003C0200018C426CD097
+:1004B0003C0300018C636CD42442FE0024630200E0
+:1004C0003C010001AC226CD03C0100011000000492
+:1004D000AC236CD43C1D00018FBD6D2003A0F02126
+:1004E0003C0200018C426CC41040000D26FAFA3820
+:1004F0003C0200018C426CD03C0300018C636CD444
+:100500003C1A00018F5A6CD42442FA38246305C87F
+:100510003C010001AC226CD03C010001AC236CD446
+:100520003C0200018C426CC8144000030000000033
+:100530003C010001AC206CD00C0011510000000007
+:100540008FBF001C8FB0001803E0000827BD0020FB
+:100550003C0200018C426CD03C0300018C636CD4E3
+:1005600027BDFF98AFB000483C1000018E1066B860
+:10057000AFB200503C12000026524100AFBF0060F5
+:10058000AFBE005CAFB50058AFB30054AFB1004C84
+:10059000AFA20034AFA30030AFA00010AFA0001492
+:1005A0008F8600403C04000124845C802405020006
+:1005B0003C010001AC326E800C002B3B0200382164
+:1005C0008F8300403C02F000006218243C0260006F
+:1005D0001062000BA3A0003F240E00013C040001A8
+:1005E00024845C88A3AE003FAFA00010AFA000142D
+:1005F0008F860040240503000C002B3B02003821AD
+:100600008F8202403C03000100431025AF8202406C
+:10061000AF8000488F8200481440000500000000B1
+:10062000AF8000488F8200481040000400000000A6
+:10063000AF8000481000000302E02021AF80004C92
+:1006400002E020213C0500010C002BA834A540F855
+:10065000034020210C002BA8240505C83C02000102
+:100660008C426EA83C0D00018DAD6E883C030001EC
+:100670008C636E843C0800018D086E903C0900017B
+:100680008D296EAC3C0A00018D4A6EB43C0B000112
+:100690008D6B6EC43C0C00018D8C6E983C04000187
+:1006A00024845C9424050400AF42013C8F42013C49
+:1006B0002406000124070001AF400000AF4D0138BF
+:1006C000AF430144AF480148AF49014CAF4A015024
+:1006D000AF4B0154AF4C01582442FF80AF42014060
+:1006E00024020001AFA200100C002B3BAFA00014AD
+:1006F0008F420138AFA200108F42013CAFA200141C
+:100700008F4601448F4701483C04000124845CA0CB
+:100710000C002B3B24050500AFB70010AFBA001446
+:100720008F46014C8F4701503C04000124845CAC8F
+:100730000C002B3B240506003C0200018C426E9C01
+:10074000036038213C06000224C690102448FFFFB5
+:100750000106182400E810240043102B1040000666
+:10076000240509003C04000124845CB8AFA80010F3
+:100770000C002B3BAFA000148F82000CAFA2001026
+:100780008F82003CAFA200148F8600008F87000488
+:100790003C04000124845CC40C002B3B24051000A5
+:1007A0008C0202208C0302248C0602188C07021C87
+:1007B0003C04000124845CCC24051100AFA200108D
+:1007C0000C002B3BAFA30014AF800054AF80011C82
+:1007D0008C020218304200021040000900000000A4
+:1007E0008C0202203C030002346300040043102505
+:1007F000AF42000C8C02021C1000000834420004BE
+:100800008C0202203C0300023463000600431025E2
+:10081000AF42000C8C02021C34420006AF420014AE
+:100820008C020218304200101040000A0000000044
+:100830008C02021C34420004AF4200108C020220E1
+:100840003C03000A34630004004310251000000933
+:10085000AF4200088C0202203C03000A3463000609
+:1008600000431025AF4200088C02021C34420006EF
+:10087000AF42001024020001AF8200A0AF8200B09E
+:100880008F8300548F820054AF8000D0AF8000C0AF
+:1008900010000002246300648F8200540062102361
+:1008A0002C4200651440FFFC000000008C0402088C
+:1008B0008C05020C26E20028AEE2002024020490FF
+:1008C000AEE20010AEE40008AEE5000C26E400083D
+:1008D0008C8200008C830004AF820090AF83009470
+:1008E0008C820018AF8200B49482000AAF82009C10
+:1008F0008F420014AF8200B08F8200B030420004FB
+:100900001440FFFD000000008F8200B03C03EF00A8
+:100910000043102410400021000000008F8200B42A
+:10092000AFA200108F8200908F8300943C040001DE
+:1009300024845CD4AFA300148F8600B08F87009C02
+:100940003C0500010C002B3B34A5200D3C040001AC
+:1009500024845CE0240203C0AFA20010AFA0001406
+:100960008F8601443C07000124E75CE80C002B3B28
+:100970003405DEAD8F82011C34420002AF82011CBF
+:100980008F82022034420004AF8202208F82014015
+:100990003C03000100431025AF82014096E204723F
+:1009A00096E6045296E70462AFA2001096E2048233
+:1009B0003C04000124845D14240512000C002B3B30
+:1009C000AFA2001496F0045232020001104000025F
+:1009D0000000B02124160001320200025440000140
+:1009E00036D60002320200085440000136D6000418
+:1009F000320200105440000136D6000832020020B6
+:100A00005440000136D6001032020040544000012C
+:100A100036D60020320200805440000136D6004015
+:100A200096E6048230C202005440000136D64000EF
+:100A300096E304723062020010400003306201004D
+:100A40001000000336D620005440000136D61000B6
+:100A500096F0046232C24000144000043207009B4A
+:100A600030C2009B14E20007240E000132C22000B5
+:100A70001440000D320200013062009B10E20009B8
+:100A8000240E00013C04000124845D202405130091
+:100A900002003821A3AE003FAFA300100C002B3B97
+:100AA000AFA00014320200015440000136D600808D
+:100AB000320200025440000136D601003202000822
+:100AC0005440000136D602003202001054400001AA
+:100AD00036D60400320200805440000136D60800A9
+:100AE0008C02021830420200104000023C02000852
+:100AF00002C2B0258C0202183042080010400002E9
+:100B00003C02008002C2B0258C0202183042040070
+:100B1000104000023C02010002C2B0258C02021803
+:100B200030420100104000023C02020002C2B02527
+:100B30008C02021830420080104000023C02040087
+:100B400002C2B0258C020218304220001040000280
+:100B50003C02001002C2B0258C0202183042400054
+:100B6000104000023C02002002C2B0258C02021894
+:100B700030421000104000023C02004002C2B0258A
+:100B80008EE204988EE3049CAF420160AF4301649F
+:100B90008EE204A08EE304A4AF420168AF43016C6F
+:100BA0008EE204A88EE304ACAF420170AF4301743F
+:100BB0008EE204288EE3042CAF420178AF43017C1F
+:100BC0008EE204488EE3044CAF420180AF430184BF
+:100BD0008EE204588EE3045CAF420188AF43018C7F
+:100BE0008EE204688EE3046CAF420190AF4301943F
+:100BF0008EE204788EE3047CAF420198AF43019CFF
+:100C00008EE204888EE3048CAF4201A0AF4301A4BE
+:100C10008EE204B08EE304B424040080AF4201A845
+:100C2000AF4301AC0C002BA8240500808C02025CB1
+:100C300027440224AF4201F08C0202602405020026
+:100C4000240600080C002BBFAF4201F83C043B9A7D
+:100C50003484CA0000003821240200062403000264
+:100C6000AF4201F4240203E8AF430204AF430200A1
+:100C7000AF4401FCAF42029424020001AF43029052
+:100C8000AF42029C3C0300010067182190636CD8BE
+:100C90000347102124E70001A043022C2CE2000F9F
+:100CA0001440FFF80347182124E700013C08000125
+:100CB000350840F88F8200403C04000124845D2CFC
+:100CC000240514000002170224420030A062022C06
+:100CD00003471021A040022C8C07021802C03021CB
+:100CE000240205C8AFA200100C002B3BAFA80014D3
+:100CF0003C04000124845D383C05000024A55C8090
+:100D00002406001027B100300220382127B3003418
+:100D10000C0017A3AFB300103C0300018C636CC838
+:100D20001060000A004080218FA300302405FF00DE
+:100D30008FA20034246400FF008520240083182340
+:100D400000431023AFA20034AFA400303C040001E4
+:100D500024845D443C05000024A5410024060108CC
+:100D6000022038210C0017A3AFB3001000409021DF
+:100D700032C200033C010001AC326E8010400045DD
+:100D8000022038218F8200503C03001000431024C1
+:100D900010400016000000008C0202183042004093
+:100DA0001040000F240200018F8200508C030218B3
+:100DB000240E00013C04000124845D50A3AE003FDA
+:100DC000AFA20010AFA300148F87004024051500C8
+:100DD0000C002B3B02C0302110000004000000007A
+:100DE0003C01000100370821A02240F43C0400012E
+:100DF00024845D5C3C05000124A55B403C060001A9
+:100E000024C65BAC00C530238F42001027B30030EE
+:100E10000260382127B1003434420A00AF4200108A
+:100E20000C0017A3AFB100103C04000124845D70D6
+:100E30003C05000124A5B7143C06000124C6BA9065
+:100E400000C5302302603821AF4201080C0017A30F
+:100E5000AFB100103C04000124845D8C3C0500010E
+:100E600024A5BE583C06000124C6C90000C5302395
+:100E7000026038213C010001AC226EF40C0017A383
+:100E8000AFB100103C04000124845DA410000024D4
+:100E9000240516003C04000124845DAC3C050001DF
+:100EA00024A5A10C3C06000124C6A23800C53023AD
+:100EB0000C0017A3AFB300103C04000124845DBCF8
+:100EC0003C05000124A5B2B03C06000124C6B70CC5
+:100ED00000C5302302203821AF4201080C0017A3BF
+:100EE000AFB300103C04000124845DD03C05000138
+:100EF00024A5BA983C06000124C6BE5000C5302384
+:100F0000022038213C010001AC226EF40C0017A332
+:100F1000AFB300103C04000124845DE424051650A6
+:100F200002C03021000038213C010001AC226EF8E3
+:100F3000AFA000100C002B3BAFA0001432C2002069
+:100F40001040002127A700303C04000124845DF0FC
+:100F50003C05000124A5B13C3C06000124C6B2A812
+:100F600000C5302324022000AF42001C27A2003419
+:100F70000C0017A3AFA20010000219000003198291
+:100F80003C04080000641825AE4300282403001028
+:100F9000AF43003C96E30450AF4300408F43004012
+:100FA0003C04000124845E04AFA00014AFA3001031
+:100FB0008F47001C240516603C010001AC226EF036
+:100FC0001000002532C600208EE204488EE3044C57
+:100FD000AF43001C8F42001C2442E0002C42200141
+:100FE0001440000A240E00013C04000124845E1019
+:100FF000A3AE003FAFA00010AFA000148F46001CAE
+:10100000240517000C002B3B000038213C02000097
+:1010100024425CBC00021100000211823C03080063
+:1010200000431025AE42002824020008AF42003CD5
+:1010300096E20450AF4200408F4200403C04000161
+:1010400024845E1CAFA00014AFA200108F47001CC8
+:101050002405180032C600200C002B3B00000000C5
+:101060003C050FFF3C0300018C636EF434A5FFFFC9
+:10107000024030213C0200018C426EF83C04080022
+:101080000065182400031882006418250045102408
+:101090000002108200441025ACC2008032C20180E0
+:1010A00010400056ACC300208F82005C3C030080DF
+:1010B000004310241040000D000000008F820050FB
+:1010C000AFA200108F82005C240E00013C040001DE
+:1010D00024845E28A3AE003FAFA200148F87004097
+:1010E000240519000C002B3B02C030218F820050D8
+:1010F0003C030010004310241040001600000000C4
+:101100008C020218304200401040000F24020001FF
+:101110008F8200508C030218240E00013C04000151
+:1011200024845D50A3AE003FAFA20010AFA3001413
+:101130008F870040240520000C002B3B02C030218B
+:1011400010000004000000003C01000100370821ED
+:10115000A02240F43C04000124845E343C050001DC
+:1011600024A55AC03C06000124C65B3800C53023C4
+:101170008F42000827B300300260382127B10034C5
+:1011800034420E00AF4200080C0017A3AFB10010AC
+:101190003C04000124845E4C3C05000124A5D8B425
+:1011A0003C06000124C6E3C800C530230260382194
+:1011B000AF42010C0C0017A3AFB100103C040001BA
+:1011C00024845E643C05000124A5E9AC3C060001D2
+:1011D00024C6F0F000C53023026038213C01000134
+:1011E000AC226F040C0017A3AFB100103C04000147
+:1011F00024845E7C10000027240521003C040001AB
+:1012000024845E843C05000124A59FC83C0600019F
+:1012100024C6A10400C5302327B1003002203821A4
+:1012200027B300340C0017A3AFB300103C04000137
+:1012300024845E943C05000124A5CAD43C06000128
+:1012400024C6D8AC00C5302302203821AF42010C9F
+:101250000C0017A3AFB300103C04000124845EA46B
+:101260003C05000124A5E84C3C06000124C6E9A485
+:1012700000C53023022038213C010001AC226F045C
+:101280000C0017A3AFB300103C04000124845EB827
+:101290002405215002C03021000038213C0100010A
+:1012A000AC226F10AFA000100C002B3BAFA00014BD
+:1012B0003C110FFF3C0300018C636F043631FFFFCC
+:1012C000024098213C0200018C426F103C0E080045
+:1012D0000071182400031882006E18250051102494
+:1012E00000021082004E1025AE630038AE62007816
+:1012F0008C02021830420040144000042402000115
+:101300003C01000100370821A02240F43C04000108
+:1013100024845EC43C05000124A5E3D03C06000102
+:1013200024C6E52C00C5302327BE003003C0382179
+:1013300027B500340C0017A3AFB500103C01000125
+:10134000AC226EFC00511024000210823C0E0800FA
+:10135000004E1025AE62005032C220001040000640
+:1013600003C038213C02000024425CBC022210244D
+:101370001000000F000210823C04000124845ED89B
+:101380003C05000124A5E5343C06000124C6E6E442
+:1013900000C530230C0017A3AFB500103C010001BD
+:1013A000AC226F1400511024000210823C0E080081
+:1013B000004E1025AE62004832C2400010400005C9
+:1013C00027A700303C02000024425CBC1000000E45
+:1013D000000211003C04000124845EF03C05000181
+:1013E00024A5E6EC3C06000124C6E84400C53023F1
+:1013F00027A200340C0017A3AFA200103C0100018B
+:10140000AC226F0800021100000211823C030800A8
+:1014100000431025AE4200603C04000124845F08B4
+:101420003C05000124A582303C06000124C68650FC
+:1014300000C5302327B100300220382127B3003403
+:101440000C0017A3AFB300103C0E0FFF35CEFFFF0B
+:101450003C04000124845F143C05000024A564685A
+:101460003C06000024C6658800C5302302203821D0
+:101470000240F0213C010001AC226EDC004E102441
+:10148000000210823C15080000551025AFAE004444
+:10149000AFC200B80C0017A3AFB300103C040001AA
+:1014A00024845F203C05000024A565903C060000D4
+:1014B00024C668088FAE004400C5302302203821BE
+:1014C0003C010001AC226ED0004E102400021082BC
+:1014D00000551025AFC200E80C0017A3AFB30010F1
+:1014E0003C04000124845F383C05000024A56810FA
+:1014F0003C06000024C669408FAE004400C530237E
+:10150000022038213C010001AC226EC8004E10249C
+:101510000002108200551025AFC200C00C0017A3B6
+:10152000AFB300103C04000124845F503C0500016F
+:1015300024A5FAD03C06000124C6FBA88FAE0044C7
+:1015400000C53023022038213C010001AC226ED4BA
+:10155000004E10240002108200551025AFC200C8B2
+:101560000C0017A3AFB300103C04000124845F5C9F
+:101570003C05000124A5C93C3C06000124C6CA2044
+:1015800000C5302302203821AF4201100C0017A300
+:10159000AFB300103C04000124845F6C3C050001E3
+:1015A00024A5C9103C06000124C6C93400C5302357
+:1015B00002203821AF4201240C0017A3AFB3001062
+:1015C0003C04000124845F7C3C05000124A55A8072
+:1015D0003C06000124C65AAC00C530230220382145
+:1015E000AF420120AF4201140C0017A3AFB30010AB
+:1015F0003C04000124845F883C05000124A5F29886
+:101600003C06000124C6F6B400C530230220382170
+:10161000AF4201180C0017A3AFB300108FAE004407
+:101620003C010001AC226F18004E10240002108211
+:10163000005510250C003FC3AFC200D00C003C4049
+:10164000000000000C0027A800000000AC000228E9
+:10165000AC00022C96E204502442FFFFAF42003857
+:1016600096E20460AF42008032C2400014400003A2
+:101670000000000096E20480AF42008496E70490E8
+:1016800050E000012407080024E2FFFFAF42008879
+:10169000AF42007C2402080010E2000F32C240007A
+:1016A000104000032402040010E2000B00000000C0
+:1016B000240E00013C04000124845F98A3AE003F87
+:1016C00096E604902405217002C03821AFA00010D6
+:1016D0000C002B3BAFA000148F4301388F4401381E
+:1016E00024020001A34205C2AF430094AF44009816
+:1016F000AFA00010AFA000148F4600808F47008479
+:101700003C04000124845FA40C002B3B2405220030
+:101710000C0024A43C1108003C1433D83694CB5858
+:101720003C020800344200803C04000124845FB085
+:101730003C05000024A55D003C06000024C65D1C9D
+:1017400000C5302327A70030AF8200602402FFFFCE
+:10175000AF82006427A200340C0017A3AFA20010D0
+:101760003C010001AC226EB800021100000211829F
+:10177000005110250C0018FCAE4200008F82024080
+:101780003C03000100431025AF8202403C020000F0
+:1017900024424034AF820244AF8002408F82006016
+:1017A00000511024144000053C0308008F820060A3
+:1017B000004310241040FFFD000000000C003C4DD1
+:1017C000000088213C020100AFA200208F530018C6
+:1017D000240200FF56620001267100018C020228DB
+:1017E0001622000E001330C08F42033C2442000139
+:1017F000AF42033C8F42033C8C0202283C040001B0
+:1018000024845C243C050009AFA00014AFA20010A2
+:101810008FA600201000003F34A5010000D7102142
+:101820008FA300208FA40024AC4304C0AC4404C4A4
+:1018300000C018218F4401788F45017C00001021E1
+:1018400024070004AFA70010AFB100148F48000CAC
+:1018500024C604C002E63021AFA800188F48010C4E
+:101860002407000800A3282100A3482B0082202180
+:101870000100F809008920211440000B240700080A
+:101880008F820120AFA200108F8201243C0400014E
+:1018900024845C2C3C050009AFA200148FA6002014
+:1018A0001000001C34A502008F4401608F450164C4
+:1018B0008F43000CAF5100188F86012024020010C6
+:1018C000AFA20010AFB10014AFA300188F42010CFB
+:1018D0000040F80924C6001C14400010000000005D
+:1018E0008F42034024420001AF4203408F42034035
+:1018F0008F820120AFA200108F8201243C040001DE
+:1019000024845C343C050009AFA200148FA600209B
+:1019100034A503000C002B3B026038218F4202E407
+:1019200024420001AF4202E48F4202E493A2003F4E
+:10193000104000693C02070034423000AFA200288A
+:101940008F530018240200FF126200020000882159
+:10195000267100018C0202281622000E001330C0EE
+:101960008F42033C24420001AF42033C8F42033CC0
+:101970008C0202283C04000124845C243C050009FC
+:10198000AFA00014AFA200108FA600281000003FE7
+:1019900034A5010000D710218FA300288FA4002CAC
+:1019A000AC4304C0AC4404C400C018218F44017887
+:1019B0008F45017C0000102124070004AFA7001010
+:1019C000AFB100148F48000C24C604C002E63021D9
+:1019D000AFA800188F48010C2407000800A3282195
+:1019E00000A3482B008220210100F8090089202152
+:1019F0001440000B240700088F820120AFA20010C2
+:101A00008F8201243C04000124845C2C3C050009E5
+:101A1000AFA200148FA600281000001C34A50200FD
+:101A20008F4401608F4501648F43000CAF51001853
+:101A30008F86012024020010AFA20010AFB1001465
+:101A4000AFA300188F42010C0040F80924C6001C07
+:101A500014400010000000008F42034024420001A7
+:101A6000AF4203408F4203408F820120AFA200109B
+:101A70008F8201243C04000124845C343C0500096D
+:101A8000AFA200148FA6002834A503000C002B3B46
+:101A9000026038218F4202F024420001AF4202F07E
+:101AA0008F4202F03C04000124845FC0AFA000100C
+:101AB000AFA000148FA60028240523000C002B3BA8
+:101AC0000000382110000004000000008C020264B5
+:101AD00010400005000000008F8200A0304200048A
+:101AE0001440FFFA000000008F82004434420004DA
+:101AF000AF8200448F42030824420001AF42030832
+:101B00008F4203088F8200D88F8300D400431023B4
+:101B10002442FF80AF4200908F4200902842FF8114
+:101B200010400006240200018F4200908F430144C0
+:101B300000431021AF42009024020001AF42008C0C
+:101B400032C2000810400006000000008F8202141C
+:101B50003C0381003042FFFF00431025AF82021496
+:101B60003C0300018C636D94306200021040000958
+:101B7000306200013C04000124845FCC3C0500007D
+:101B800024A56D503C06000024C671C81000001248
+:101B900000C5302310400009000000003C04000193
+:101BA00024845FDC3C05000024A571D03C060000C5
+:101BB00024C676781000000800C530233C040001DC
+:101BC00024845FEC3C05000024A569483C06000025
+:101BD00024C66D4800C5302327A7003027A2003453
+:101BE0000C0017A3AFA200103C010001AC226ECC88
+:101BF0003C0200018C426ECC3C0308000002110044
+:101C00000002118200431025AE4200408F8200A0E6
+:101C1000AFA200108F8200B0AFA200148F86005CCC
+:101C20008F87011C3C04000124845FFC3C010001FF
+:101C3000AC366EA43C010001AC206E943C01000166
+:101C4000AC3C6E8C3C010001AC3B6EBC3C01000125
+:101C5000AC376EC03C010001AC3A6EA00C002B3BCF
+:101C6000240524008F820200AFA200108F82022080
+:101C7000AFA200148F8600448F8700503C040001FF
+:101C8000248460080C002B3B240525008F83006012
+:101C90000074100B0242000A0200F821000000004C
+:101CA0000000000D8FBF00608FBE005C8FB5005834
+:101CB0008FB300548FB200508FB1004C8FB00048EA
+:101CC00003E0000827BD006827BDFFE03C040001D9
+:101CD00024846014240526000000302100003821EF
+:101CE000AFBF0018AFA000100C002B3BAFA000143A
+:101CF0008FBF001803E0000827BD002003E00008A4
+:101D00000000000003E000080000000000000000E8
+:101D100000000000000000000000000000000000C3
+:101D200003E000080000000003E0000800000000DD
+:101D300027BDFDE027A500183C04DEAD3484BEEFCE
+:101D4000AFBF02188F8201503C03001F3463FFFFB6
+:101D5000AFA4001800A2282300A328248CA200000E
+:101D60001044000A00000000AFA500108CA2000083
+:101D7000AFA200148F8601508F8702503C040001EF
+:101D80002484601C0C002B3B240527008FBF021805
+:101D900003E0000827BD022027BDFFE03C06ABBAE8
+:101DA00034C6BABEAFB000183C1000043C07007F38
+:101DB00034E7FFFFAFBF001C001028408E04000076
+:101DC0008CA30000ACA00000AE0600008CA20000B6
+:101DD000ACA3000010460005AE04000000A0802166
+:101DE00000F0102B1040FFF5001028403C040001CB
+:101DF00024846028240528000200302100003821B6
+:101E0000AFA000100C002B3BAFA00014020010216B
+:101E10008FBF001C8FB0001803E0000827BD002012
+:101E20008C0202243047003F10E000100080302177
+:101E3000000028212403002000E3102410400002A9
+:101E40000006304200A62821000318421460FFFB60
+:101E500000E310242402F00000A228243402FFFF33
+:101E60000045102B144000033C0200011000000844
+:101E70003C0200013442FFFF008518230043102B71
+:101E80001440000300A010213C02FFFE008210213C
+:101E900003E000080000000027BDFFD0AFB5002818
+:101EA0008FB50040AFB2002000A09021AFB1001C60
+:101EB00024C60003AFBF002CAFB30024AFB000189E
+:101EC0008EA200002403FFFC00C380240050102BCE
+:101ED0001440001B00E088218E330000AFB00010DA
+:101EE0008EA20000AFA200148E270000240530004F
+:101EF0000C002B3B024030218E230000007020217B
+:101F00000064102B10400007024028218CA2000022
+:101F1000AC620000246300040064102B1440FFFB3B
+:101F200024A500048EA2000000501023AEA20000E1
+:101F30008E220000005010211000000BAE22000085
+:101F40002402002DA0820000AFB000108EA200007D
+:101F500002409821AFA200148E2700002405310012
+:101F60000C002B3B02603021026010218FBF002C3F
+:101F70008FB500288FB300248FB200208FB1001CD2
+:101F80008FB0001803E0000827BD003027BDFFE830
+:101F90003C1CC0003C05FFFE3C0300018C636E84CA
+:101FA0003C0400018C846E9034A5BF0824021FFC01
+:101FB0003C010001AC226CD03C0200C03C0100019D
+:101FC000AC226CD43C020020AFBF00103C0100C02A
+:101FD000AC201FFC0043102300441023245BB000FE
+:101FE0000365B8213C1D00018FBD6CCC03A0F0211E
+:101FF0003C0400C0348402003C1A00C03C0300C012
+:10200000346307C824021DFC3C010001AC226CD0E3
+:10201000240218343C010001AC246CD43C010001C2
+:10202000AC226CD03C010001AC236CD40C00180D28
+:10203000375A02008FBF001003E0000827BD0018C8
+:1020400027BDFFC83C04000124846034240532000D
+:102050003C0200018C426CD03C0300018C636CD4C8
+:102060000000302103603821AFBF0030AFB3002C37
+:10207000AFB20028AFB10024AFB00020AFA2001C67
+:10208000AFA30018AFB700100C002B3BAFBA001481
+:102090000C001916000000008F8202403442000438
+:1020A000AF82024024020001AF4200003C02000166
+:1020B00000571021904240F4104000922403FFFC8E
+:1020C0003C1000012610AC733C1200012652A84CB3
+:1020D00002121023004380248FA3001C3C04000143
+:1020E000248460400070102B1440001A27B300189D
+:1020F0008FB100182405300002403021AFB000102D
+:10210000AFA300140C002B3B022038218FA3001832
+:10211000007020210064102B104000070240302185
+:102120008CC20000AC620000246300040064102B29
+:102130001440FFFB24C600048FA2001C0050102393
+:10214000AFA2001C8E620000005010211000000A97
+:10215000AE6200000240882124053100AFB00010BB
+:10216000AFA300148FA70018022030212402002DF5
+:102170000C002B3BA0820000240700208FA3001C32
+:102180003C0400012484605C241200203C01000116
+:10219000AC316EB02C6200201440001D27B1001835
+:1021A0008FB00018240530003C06000124C66F5093
+:1021B000AFA70010AFA300140C002B3B0200382186
+:1021C0008FA300183C04000124846F502465002074
+:1021D0000065102B10400007000000008C820000FA
+:1021E000AC620000246300040065102B1440FFFB68
+:1021F000248400048FA2001C00521023AFA2001CF4
+:102200008E220000005210211000000BAE220000B0
+:102210003C10000126106F5024053100AFA70010BC
+:10222000AFA300148FA70018020030212402002D54
+:102230000C002B3BA0820000240700203C0400017E
+:10224000248460708FA3001C241200203C01000134
+:10225000AC306EE42C6200201440001D27B1001841
+:102260008FB00018240530003C06000124C66F70B2
+:10227000AFA70010AFA300140C002B3B02003821C5
+:102280008FA300183C04000124846F702465002093
+:102290000065102B10400007000000008C82000039
+:1022A000AC620000246300040065102B1440FFFBA7
+:1022B000248400048FA2001C00521023AFA2001C33
+:1022C0008E220000005210211000000BAE220000F0
+:1022D0003C10000126106F7024053100AFA70010DC
+:1022E000AFA300148FA70018020030212402002D94
+:1022F0000C002B3BA08200003C01000110000031CB
+:10230000AC306EE03C1000012610821F3C12000130
+:102310002652809C02121023004380248FA3001CAD
+:102320003C040001248460840070102B1440001AC7
+:1023300027B300188FB10018240530000240302167
+:10234000AFB00010AFA300140C002B3B02203821CB
+:102350008FA30018007020210064102B104000078C
+:10236000024030218CC20000AC62000024630004F3
+:102370000064102B1440FFFB24C600048FA2001C35
+:1023800000501023AFA2001C8E62000000501021EC
+:102390001000000AAE6200000240882124053100CE
+:1023A000AFB00010AFA300148FA700180220302197
+:1023B0002402002D0C002B3BA08200003C010001F8
+:1023C000AC316EB03C0300018C636EB0240204009B
+:1023D0000060F809AF8200708FBF00308FB3002C0F
+:1023E0008FB200288FB100248FB0002003E00008D6
+:1023F00027BD003800000000000000008F82004070
+:102400003C03F000004310243C036000144300062A
+:10241000000000008F8200502403FF80004310243E
+:1024200034420055AF8200508F820054244203E8AA
+:10243000AF820058240201F4AF4200E024020004FD
+:10244000AF4200E824020002AF4001B0AF4000E418
+:10245000AF4200DCAF4000D8AF4000D403E000083A
+:10246000AF4000D08F8200542442000503E00008F2
+:10247000AF82007827BDFFE8AFBF00108F82005405
+:10248000244203E8AF8200583C02080002C2102434
+:10249000104000043C02F7FF3442FFFF02C2B024A8
+:1024A000369400403C0200018C426DA81040001799
+:1024B0003C0202003C0300018C636F1C106000169C
+:1024C0000282A0253C0200018C426E44144000129E
+:1024D0003C0202003C0200018C426D943042000339
+:1024E0001440000D3C0202008F8302243C020002D3
+:1024F0008C428FEC106200083C0202000C003DAFE1
+:1025000000000000100000043C0202000C00419694
+:10251000000000003C02020002C210241040000330
+:10252000000000000C001F4B000000008F4200D88C
+:102530008F4300DC24420001AF4200D80043102B3F
+:102540001440000300000000AF4000D83694008023
+:102550008C0302381060000C000000008F4201B0B4
+:10256000244203E8AF4201B00043102B14400006A0
+:1025700000000000934205C5144000030000000065
+:102580000C001DA0000000008FBF001003E0000839
+:1025900027BD001803E000080000000027BDFFD899
+:1025A000AFBF00208F43002C8F42003810620059CB
+:1025B000000000003C02000100571021904240F052
+:1025C00010400026240700088F4401708F450174D5
+:1025D0008F48000C8F86012024020020AFA200103B
+:1025E000AFA30014AFA800188F42010C0040F809F7
+:1025F00024C6001C14400011240200013C0100010B
+:1026000000370821A02240F08F820124AFA20010E1
+:102610008F8201283C04000124846128AFA20014A9
+:102620008F46002C8F8701203C0500090C002B3BB6
+:1026300034A509001000005C000000008F42030078
+:1026400024420001AF4203008F4203008F42002C5E
+:10265000A34005C110000027AF4200388F4401702D
+:102660008F4501748F43002C8F48000C8F8601200A
+:1026700024020080AFA20010AFA30014AFA800187E
+:102680008F42010C0040F80924C6001C14400011C0
+:10269000240200013C01000100370821A02240F182
+:1026A0008F820124AFA200108F8201283C04000118
+:1026B00024846134AFA200148F46002C8F87012040
+:1026C0003C0500090C002B3B34A51100100000361E
+:1026D000000000008F4203008F43002C24420001C1
+:1026E000AF4203008F42030024020001A34205C150
+:1026F000AF4300383C01000100370821A02040F121
+:102700003C01000100370821A02040F01000002605
+:10271000AF400034934205C11040001D000000008E
+:10272000A34005C18F8200403042000114400008E0
+:10273000000020218C0301042402000150620005E6
+:10274000240400018C020264104000030080102168
+:102750002404000100801021104000060000000049
+:102760008F42030C24420001AF42030C100000080A
+:102770008F42030C8F82004434420004AF82004435
+:102780008F42030824420001AF4203088F4203082E
+:102790003C01000100370821A02040F03C0100016D
+:1027A00000370821A02040F18F42000010400007B0
+:1027B00000000000AF80004C8F82004C1040FFFDF5
+:1027C000000000001000000500000000AF8000487D
+:1027D0008F8200481040FFFD000000008F820060E3
+:1027E0003C03FF7F3463FFFF00431024AF8200608F
+:1027F0008F420000104000030000000010000002A3
+:10280000AF80004CAF8000488FBF002003E000087D
+:1028100027BD002803E000080000000027BDFFD806
+:10282000AFBF00208F4300448F42007C106200291C
+:10283000240700088F4401688F45016C8F48000C05
+:102840008F86012024020040AFA20010AFA3001425
+:10285000AFA800188F42010C0040F80924C6001CE4
+:1028600014400011240200013C010001003708213E
+:10287000A02240F28F820124AFA200108F82012893
+:102880003C0400012484613CAFA200148F46004444
+:102890008F8701203C0500090C002B3B34A5130059
+:1028A0001000000F000000008F42030424420001CA
+:1028B000AF4203048F4203048F420044AF42007CC6
+:1028C0003C01000100370821A02040F21000000464
+:1028D000AF4000783C01000100370821A02040F201
+:1028E0008F4200001040000700000000AF80004C45
+:1028F0008F82004C1040FFFD00000000100000051A
+:1029000000000000AF8000488F8200481040FFFDAB
+:10291000000000008F8200603C03FEFF3463FFFF75
+:1029200000431024AF8200608F420000104000037B
+:102930000000000010000002AF80004CAF80004893
+:102940008FBF002003E0000827BD002803E0000837
+:10295000000000003C0200018C426DA827BDFFA8CA
+:10296000AFBF0050AFBE004CAFB50048AFB300449E
+:10297000AFB20040AFB1003CAFB00038104000D55E
+:102980008F9000448F4200D0244300012842000B66
+:10299000144000E4AF4300D08F42000430420002F4
+:1029A0001440009CAF4000D08F4200043C03000163
+:1029B0008C636D9834420002AF420004240200018F
+:1029C000146200033C020600100000023442300092
+:1029D00034421000AFA200208F4A0018AFAA003482
+:1029E00027AA0020AFAA002C8FAA0034240200FFDF
+:1029F0001142000200001821254300018C02022828
+:102A0000006098211662000E3C0500098F42033CCD
+:102A100024420001AF42033C8F42033C8C02022857
+:102A20008FA700343C0400012484610CAFA0001483
+:102A3000AFA200108FA600201000007034A5050082
+:102A40008FAA0034000A38C000F710218FA300209D
+:102A50008FA40024AC4304C0AC4404C48F8300544E
+:102A60008F820054247103E8022210232C4203E9D0
+:102A70001040001B0000A82100E09021265E04C049
+:102A80008F4401788F45017C02401821240A0004FC
+:102A9000AFAA0010AFB300148F48000C0000102143
+:102AA00002FE3021AFA800188F48010C240700084F
+:102AB00000A3282100A3482B008220210100F8094F
+:102AC0000089202154400006241500018F82005403
+:102AD000022210232C4203E91440FFE90000000009
+:102AE00032A200FF54400018AF5300188F42037801
+:102AF00024420001AF4203788F4203788F82012085
+:102B00008FAA002C8FA70034AFA200108F8201245F
+:102B10003C04000124846118AFA200148D4600001B
+:102B20003C0500091000003534A506008F4203085B
+:102B30002415000124420001AF4203088F4203081C
+:102B40001000001E32A200FF8F8300548F820054B9
+:102B5000247103E8022210232C4203E910400016DE
+:102B60000000A8213C1E0020241200108F42000CFF
+:102B70008F4401608F4501648F860120AFB2001041
+:102B8000AFB30014005E1025AFA200188F42010CF5
+:102B9000240700080040F80924C6001C1440FFE385
+:102BA000000000008F820054022210232C4203E90F
+:102BB0001440FFEE0000000032A200FF144000119C
+:102BC0003C0500098F42037824420001AF4203789C
+:102BD0008F4203788F8201208FAA002C8FA70034A8
+:102BE000AFA200108F8201243C04000124846120E4
+:102BF000AFA200148D46000034A507000C002B3B4B
+:102C0000000000008F4202EC24420001AF4202ECBF
+:102C10008F4202EC8F4200043042000150400029F4
+:102C2000361000403C02040002C210241040001381
+:102C30002404FFDF8F4202508F4302548F4401B4BB
+:102C400014640006361000408F4202708F430274F5
+:102C50008F4401B8106400072402FFDF8F42025046
+:102C60008F4302548F4402708F450274100000128B
+:102C70003A1000201000002B020280248F420250E4
+:102C80008F4302548F4501B414650006020480246A
+:102C90008F4202708F4302748F4401B85064002148
+:102CA000361000408F4202508F4302548F4402700E
+:102CB0008F4502743A100040AF4301B41000001970
+:102CC000AF4501B88F4200D4244300011000001129
+:102CD000284200338F4200043042000110400009B6
+:102CE0003C02040002C21024104000042402FFDF52
+:102CF000020280241000000B361000401000000972
+:102D0000361000608F4200D436100040244300018A
+:102D1000284201F514400003AF4300D4AF4000D473
+:102D20003A100020AF9000442402FF7F0282A024CA
+:102D30008FBF00508FBE004C8FB500488FB300444A
+:102D40008FB200408FB1003C8FB0003803E0000824
+:102D500027BD005803E00008000000003C0200010D
+:102D60008C426DA827BDFFB0AFBF0048AFBE004486
+:102D7000AFB50040AFB3003CAFB20038AFB10034E4
+:102D8000104000C7AFB000308F4200D02443000194
+:102D90002842000B144000DAAF4300D08F420004F9
+:102DA0003042000214400097AF4000D08F42000430
+:102DB0003C0300018C636D9834420002AF42000472
+:102DC00024020001146200033C020600100000020D
+:102DD0003442300034421000AFA20020000018211D
+:102DE0008F5E001827AA0020240200FF13C20002F1
+:102DF000AFAA002C27C300018C020228006090219A
+:102E00001642000E001E38C08F42033C24420001CF
+:102E1000AF42033C8F42033C8C0202283C04000179
+:102E20002484610C3C050009AFA00014AFA200107F
+:102E30008FA600201000006D34A5050000F71021BA
+:102E40008FA300208FA40024AC4304C0AC4404C46E
+:102E50008F8300548F820054247003E802021023F1
+:102E60002C4203E91040001B0000982100E088215B
+:102E7000263504C08F4401788F45017C022018213B
+:102E8000240A0004AFAA0010AFB200148F48000C4F
+:102E90000000102102F53021AFA800188F48010C66
+:102EA0002407000800A3282100A3482B008220212A
+:102EB0000100F80900892021544000062413000174
+:102EC0008F820054020210232C4203E91440FFE9D0
+:102ED00000000000326200FF54400017AF5200189B
+:102EE0008F42037824420001AF4203788F42037877
+:102EF0008F8201208FAA002CAFA200108F820124A4
+:102F00003C040001248461183C050009AFA20014B0
+:102F10008D4600001000003534A506008F420308DE
+:102F20002413000124420001AF4203088F4203082A
+:102F30001000001E326200FF8F8300548F82005405
+:102F4000247003E8020210232C4203E9104000160B
+:102F5000000098213C150020241100108F42000C25
+:102F60008F4401608F4501648F860120AFB100104E
+:102F7000AFB2001400551025AFA200188F42010C0B
+:102F8000240700080040F80924C6001C1440FFE391
+:102F9000000000008F820054020210232C4203E93B
+:102FA0001440FFEE00000000326200FF14400011E8
+:102FB000000000008F42037824420001AF420378F2
+:102FC0008F4203788F8201208FAA002CAFA20010BD
+:102FD0008F8201243C040001248461203C05000907
+:102FE000AFA200148D46000034A507000C002B3B57
+:102FF00003C038218F4202EC24420001AF4202ECB0
+:103000008F4202EC8F420004304200011040001851
+:10301000240400018F4202508F4302548F4501B4B3
+:103020003C01000114650006A0246CF18F4202707F
+:103030008F4302748F4401B8106400210000000027
+:103040008F4202508F4302543C04000190846CF084
+:103050008F4602708F47027438840001AF4301B479
+:10306000AF4701B83C01000110000025A0246CF01E
+:103070008F4200D43C010001A0206CF024430001E9
+:10308000284200331440001EAF4300D43C0200012C
+:1030900090426CF1AF4000D410000017384200019C
+:1030A0008F42000430420001104000080000000080
+:1030B0000C00565A000020213C010001A0206CF1B8
+:1030C0003C0100011000000EA0206CF08F4200D4E3
+:1030D0003C010001A0206CF024430001284201F5CE
+:1030E00014400007AF4300D43C02000190426CF151
+:1030F000AF4000D4004210263C010001A0226CF138
+:103100003C0300018C636D98240200021462000CE1
+:103110003C0300023C03000190636CF124020001B7
+:103120005462001F000020213C02000190426CF01C
+:103130001443001B24040005100000192404000699
+:103140003C0200028C428FF4004310241040000B1C
+:10315000240200013C03000190636CF154620010F2
+:10316000000020213C02000190426CF01443000C4E
+:10317000240400031000000A240400043C0300019E
+:1031800090636CF114620006000020213C020001F3
+:1031900090426CF024040001504400012404000219
+:1031A0000C00565A000000002402FF7F0282A02477
+:1031B0008FBF00488FBE00448FB500408FB3003CE6
+:1031C0008FB200388FB100348FB0003003E00008B8
+:1031D00027BD005003E00008000000003C02000191
+:1031E0008C426DA827BDFFB0AFBF0048AFBE004402
+:1031F000AFB50040AFB3003CAFB20038AFB1003460
+:10320000104000DEAFB000308F4200D03C0400011F
+:103210008C846D98244300012842000BAF4400E8E1
+:10322000144000FEAF4300D08F4200043042000241
+:1032300014400095AF4000D08F4200043442000299
+:10324000AF42000424020001148200033C02060085
+:10325000100000023442300034421000AFA20020BF
+:10326000000018218F5E001827AA0020240200FF0A
+:1032700013C20002AFAA002C27C300018C0202284F
+:10328000006090211642000E001E38C08F42033CA1
+:1032900024420001AF42033C8F42033C8C020228CF
+:1032A0003C0400012484610C3C050009AFA000141B
+:1032B000AFA200108FA600201000006D34A50500FD
+:1032C00000F710218FA300208FA40024AC4304C07A
+:1032D000AC4404C48F8300548F820054247003E8EC
+:1032E000020210232C4203E91040001B0000982129
+:1032F00000E08821263504C08F4401788F45017C89
+:1033000002201821240A0004AFAA0010AFB2001452
+:103310008F48000C0000102102F53021AFA80018E2
+:103320008F48010C2407000800A3282100A3482B84
+:10333000008220210100F809008920215440000664
+:10334000241300018F820054020210232C4203E94F
+:103350001440FFE900000000326200FF54400017F3
+:10336000AF5200188F42037824420001AF42037825
+:103370008F4203788F8201208FAA002CAFA2001009
+:103380008F8201243C040001248461183C0500095B
+:10339000AFA200148D4600001000003534A50600D1
+:1033A0008F4203082413000124420001AF420308A6
+:1033B0008F4203081000001E326200FF8F8300540A
+:1033C0008F820054247003E8020210232C4203E988
+:1033D00010400016000098213C1500202411001018
+:1033E0008F42000C8F4401608F4501648F8601205D
+:1033F000AFB10010AFB2001400551025AFA20018F5
+:103400008F42010C240700080040F80924C6001C64
+:103410001440FFE3000000008F82005402021023DA
+:103420002C4203E91440FFEE00000000326200FF6E
+:1034300014400011000000008F4203782442000174
+:10344000AF4203788F4203788F8201208FAA002C2D
+:10345000AFA200108F8201243C040001248461206B
+:103460003C050009AFA200148D46000034A50700FA
+:103470000C002B3B03C038218F4202EC2442000198
+:10348000AF4202EC8F4202EC8F4200043042000156
+:10349000104000333C02040002C210241040001708
+:1034A00000000000934205C08F4402508F45025433
+:1034B0008F4301B43442002014A30006A34205C088
+:1034C0008F4202708F4302748F4401B81064000869
+:1034D000000000008F4202508F430254934405C005
+:1034E0008F4602708F470274100000163884004027
+:1034F000934205C010000048304200BF934205C00F
+:103500008F4402508F4502548F4301B4304200BFB4
+:1035100014A30006A34205C08F4202708F430274B9
+:103520008F4401B81064000B000000008F4202506D
+:103530008F430254934405C08F4602708F47027434
+:1035400038840020AF4301B4AF4701B81000003306
+:10355000A34405C0934205C01000002F3442002050
+:10356000934205C08F4300D434420020A34205C0DB
+:103570002462000110000023286300338F4200E41E
+:103580008F4300E024420001AF4200E40043102AD0
+:1035900014400006240300018F4200E81443000297
+:1035A000AF4000E424030004AF4300E88F4200046E
+:1035B000304200011040000D3C02040002C2102401
+:1035C0001040000700000000934205C03442004054
+:1035D000A34205C0934205C01000000F304200DF37
+:1035E000934205C01000000C34420060934205C0B5
+:1035F0008F4300D434420020A34205C0246200015E
+:10360000286300FB14600005AF4200D4934205C05C
+:10361000AF4000D438420040A34205C0934205C0E9
+:103620008F4300E83042007FA34205C0240200011E
+:103630001462000500000000934405C0000421024C
+:1036400010000003348400F0934405C03484000F5C
+:103650000C005640000000002402FF7F0282A024DC
+:103660008FBF00488FBE00448FB500408FB3003C31
+:103670008FB200388FB100348FB0003003E0000803
+:1036800027BD005003E000080000000027BDFFB088
+:10369000274401C026E30028246504000065102BA0
+:1036A000AFBF0048AFBE0044AFB50040AFB3003C71
+:1036B000AFB20038AFB1003410400007AFB00030F7
+:1036C0008C820000AC620000246300040065102BB3
+:1036D0001440FFFB248400048C020080AEE200440E
+:1036E0008C0200C0AEE200408C020084AEE20030EA
+:1036F0008C020084AEE2023C8C020088AEE2024002
+:103700008C02008CAEE202448C020090AEE20248D1
+:103710008C020094AEE2024C8C020098AEE20250A1
+:103720008C02009CAEE202548C0200A0AEE2025871
+:103730008C0200A4AEE2025C8C0200A8AEE2026041
+:103740008C0200ACAEE202648C0200B0AEE2026811
+:103750008C0200B4AEE2026C8C0200B8AEE20270E1
+:103760008C0200BC24040001AEE20274AEE000341E
+:1037700000041080005710218EE300348C42023C7C
+:1037800024840001006218212C82000FAEE3003473
+:103790001440FFF8000410808C0200CCAEE2004818
+:1037A0008C0200D0AEE2004C8C0200E0AEE201F8E8
+:1037B0008C0200E4AEE201FC8C0200E8AEE2020002
+:1037C0008C0200ECAEE202048C0200F0AEE20208D1
+:1037D0008EE400C08EE500C48C0200FC0045102B76
+:1037E0001040000B000000008EE200C08EE300C419
+:1037F0002404000124050000006518210065302B19
+:103800000044102100461021AEE200C0AEE300C427
+:103810008C0200FC8EE400C08EE500C42408FFFF8B
+:1038200024090000004018210000102100882024F5
+:1038300000A928240082202500A32825AEE400C08A
+:10384000AEE500C48EE400D08EE500D48C0200F416
+:103850000045102B1040000B000000008EE200D04D
+:103860008EE300D424040001240500000065182123
+:103870000065302B0044102100461021AEE200D03C
+:10388000AEE300D48C0200F48EE400D08EE500D4C8
+:1038900000401821000010210088202400A92824BD
+:1038A0000082202500A32825AEE400D0AEE500D498
+:1038B0008EE400C88EE500CC8C0200F80045102B89
+:1038C0001040000B000000008EE200C88EE300CC28
+:1038D0002404000124050000006518210065302B38
+:1038E0000044102100461021AEE200C8AEE300CC37
+:1038F0008C0200F88EE400C88EE500CC0040182150
+:10390000000010210088202400A9282400822025FE
+:1039100000A3282524020008AEE400C8AEE500CCD0
+:10392000AFA20010AFA000148F42000C8C0402085C
+:103930008C05020CAFA200188F42010C26E600286D
+:103940000040F80924070400104000F03C02040085
+:10395000AFA20020934205C6104000890000182144
+:103960008F5E001827AA0020240200FF13C2000265
+:10397000AFAA002C27C300018C020228006090210E
+:103980001642000E001E38C08F42033C2442000144
+:10399000AF42033C8F42033C8C0202283C040001EE
+:1039A0002484610C3C050009AFA00014AFA20010F4
+:1039B0008FA600201000006B34A5050000F7102131
+:1039C0008FA300208FA40024AC4304C0AC4404C4E3
+:1039D0008F8300548F820054247003E80202102366
+:1039E0002C4203E91040001B0000982100E08821D0
+:1039F000263504C08F4401788F45017C02201821B0
+:103A0000240A0004AFAA0010AFB200148F48000CC3
+:103A10000000102102F53021AFA800188F48010CDA
+:103A20002407000800A3282100A3482B008220219E
+:103A30000100F809008920215440000624130001E8
+:103A40008F820054020210232C4203E91440FFE944
+:103A500000000000326200FF54400017AF5200180F
+:103A60008F42037824420001AF4203788F420378EB
+:103A70008F8201208FAA002CAFA200108F82012418
+:103A80003C040001248461183C050009AFA2001425
+:103A90008D4600001000003334A506008F42030855
+:103AA0002413000124420001AF4203088F4203089F
+:103AB0001000001C326200FF8F8300548F8200547C
+:103AC000247003E8020210232C4203E91040001482
+:103AD00000009821241100108F42000C8F440160D7
+:103AE0008F4501648F860120AFB10010AFB2001482
+:103AF000AFA200188F42010C240700080040F8090B
+:103B000024C6001C1440FFE5000000008F82005412
+:103B1000020210232C4203E91440FFEF00000000D2
+:103B2000326200FF54400012240200018F420378E9
+:103B300024420001AF4203788F4203788F82012034
+:103B40008FAA002CAFA200108F8201243C04000138
+:103B5000248461203C050009AFA200148D460000BA
+:103B600034A507000C002B3B03C0382100001021B6
+:103B70001440005B240200011000006500000000FA
+:103B80008F510018240200FF122200020000802141
+:103B9000263000018C0202281602000E001130C0EF
+:103BA0008F42033C24420001AF42033C8F42033C5E
+:103BB0008C0202283C040001248460F43C050009C6
+:103BC000AFA00014AFA200108FA600201000003F8D
+:103BD00034A5010000D710218FA300208FA400245A
+:103BE000AC4304C0AC4404C400C018218F44017825
+:103BF0008F45017C0000102124070004AFA70010AE
+:103C0000AFB000148F48000C24C604C002E6302177
+:103C1000AFA800188F48010C2407000800A3282132
+:103C200000A3482B008220210100F80900892021EF
+:103C30001440000B240700088F820120AFA200105F
+:103C40008F8201243C040001248460FC3C050009AF
+:103C5000AFA200148FA600201000001C34A50200A3
+:103C60008F4401608F4501648F43000CAF500018F2
+:103C70008F86012024020010AFA20010AFB0001404
+:103C8000AFA300188F42010C0040F80924C6001CA5
+:103C900054400011240200018F42034024420001DD
+:103CA000AF4203408F4203408F820120AFA2001039
+:103CB0008F8201243C040001248461043C05000936
+:103CC000AFA200148FA6002034A503000C002B3BEC
+:103CD00002203821000010211040000D24020001B4
+:103CE0008F4202E8A34005C6AF4001B02442000164
+:103CF000AF4202E88F4202E88EE201502442000106
+:103D0000AEE20150100000038EE2015024020001D7
+:103D1000A34205C68FBF00488FBE00448FB5004048
+:103D20008FB3003C8FB200388FB100348FB00030B9
+:103D300003E0000827BD005027BDFFD8AFBF00201B
+:103D40008F8200B030420004104000680000000084
+:103D50008F4301288F8201041462000500000000D7
+:103D60008F4301308F8200B4106200060000000013
+:103D70008F820104AF4201288F8200B41000005BE3
+:103D8000AF4201308F8200B03C030080004310241A
+:103D90001040000D000000008F82011C3442000220
+:103DA000AF82011C8F8200B02403FFFB004310246C
+:103DB000AF8200B08F82011C2403FFFD004310245A
+:103DC0001000004AAF82011C8F4301288F8201043A
+:103DD00014620005000000008F4301308F8200B4A0
+:103DE00010620010000000008F820104AF42012821
+:103DF0008F8200B48F430128AF420130AFA300107F
+:103E00008F4201303C04000124846144AFA20014BD
+:103E10008F86011C8F8700B03C0500051000003123
+:103E200034A509008F420128AFA200108F42013053
+:103E30003C04000124846150AFA200148F86011C51
+:103E40008F8700B03C0500050C002B3B34A510000B
+:103E50008F82011C34420002AF82011C8F83010457
+:103E60008F8200B034420001AF8200B0240200080B
+:103E7000AF830104AFA20010AFA000148F42000C6A
+:103E80008C0402088C05020CAFA200188F42010CB2
+:103E900026E600280040F809240704008F82011C50
+:103EA0002403FFFD00431024AF82011C8EE201DCDD
+:103EB00024420001AEE201DC8EE201DC8F420128E7
+:103EC000AFA200108F4201303C0400012484615CE9
+:103ED000AFA200148F86011C8F8700B03C0500053F
+:103EE00034A511000C002B3B000000008F8200A0C5
+:103EF0003042000410400069000000008F43012C94
+:103F00008F82012414620005000000008F430134F9
+:103F10008F8200A410620006000000008F8201243E
+:103F2000AF42012C8F8200A41000005CAF4201342C
+:103F30008F8200A03C030080004310241040000D3D
+:103F4000000000008F82011C34420002AF82011C7D
+:103F50008F8200A02403FFFB00431024AF8200A047
+:103F60008F82011C2403FFFD004310241000004B2E
+:103F7000AF82011C8F43012C8F8201241462000543
+:103F8000000000008F4301348F8200A410620010F3
+:103F9000000000008F820124AF42012C8F8200A418
+:103FA0008F43012CAF420134AFA300108F42013484
+:103FB0003C04000124846168AFA200148F86011CB8
+:103FC0008F8700A03C0500051000003234A51200C8
+:103FD0008F42012CAFA200108F4201343C0400013B
+:103FE00024846174AFA200148F86011C8F8700A007
+:103FF0003C0500050C002B3B34A513008F82011CEF
+:1040000034420002AF82011C8F8301248F8200A002
+:1040100034420001AF8200A024020080AF8301245B
+:10402000AFA20010AFA000148F4200148C0402084D
+:104030008C05020CAFA200188F4201083C0600015B
+:1040400024C66ED80040F809240700048F82011CA2
+:104050002403FFFD00431024AF82011C8EE201DC2B
+:1040600024420001AEE201DC8EE201DC8F42012C31
+:10407000AFA200108F4201343C040001248461800F
+:10408000AFA200148F86011C8F8700A03C0500059D
+:1040900034A514000C002B3B000000008FBF002053
+:1040A00003E0000827BD00283C0810002407000199
+:1040B0003C0600803C0501008F82007000481024FF
+:1040C0001040FFFD000000008F82005424420005D4
+:1040D000AF8200788C040234108000160000182192
+:1040E0003C020001005710218C4240E824420005A8
+:1040F0003C01000100370821AC2240E83C020001ED
+:10410000005710218C4240E80044102B1440000955
+:10411000000000003C0300803C0100010037082142
+:10412000AC2040E83C010001003708211000000BE2
+:10413000A02740F03C02000100571021904240F0BF
+:1041400054400006006618253C020001005710216B
+:10415000904240F154400001006618258C04023062
+:1041600010800013000000003C02000100571021E5
+:104170008C4240EC244200053C010001003708213C
+:10418000AC2240EC3C020001005710218C4240EC74
+:104190000044102B14400006000000003C01000108
+:1041A00000370821AC2040EC1000000600651825FF
+:1041B0003C02000100571021904240F2544000019F
+:1041C000006518251060FFBC000000008F42000051
+:1041D0001040000700000000AF80004C8F82004CB0
+:1041E0001040FFFD0000000010000005000000006E
+:1041F000AF8000488F8200481040FFFD00000000A3
+:104200008F82006000431025AF8200608F42000063
+:1042100010400003000000001000FFA7AF80004C1A
+:104220001000FFA5AF80004803E000080000000078
+:1042300000000000000000000000000027BDFFE0BB
+:10424000AFBF00188F86006430C200041040002504
+:10425000240400048C020114AF420020AF840064E7
+:104260008F4202FC24420001AF4202FC8F4202FC5A
+:104270008F820064304200041440000500000000FA
+:104280008C0301148F4200201462FFF20000000032
+:104290008F420000104000078F43003CAF80004C6D
+:1042A0008F82004C1040FFFD000000001000000550
+:1042B00000000000AF8000488F8200481040FFFDE2
+:1042C000000000008F82006000431025AF82006074
+:1042D0008F42000010400073000000001000006FCB
+:1042E0000000000030C20008104000202404000834
+:1042F0008C02011CAF420048AF8400648F4202A8C8
+:1043000024420001AF4202A88F4202A88F820064BB
+:104310003042000814400005000000008C03011C1E
+:104320008F4200481462FFF2000000008F4200003C
+:104330001040000700000000AF80004C8F82004C4E
+:104340001040FFFD0000000010000005000000000C
+:10435000AF8000488F8200481040FFFD0000000041
+:104360008F8200601000FFD93442020030C200206A
+:1043700010400023240400208C02012CAF4200686E
+:10438000AF8400648F4202D824420001AF4202D8B9
+:104390008F4202D88F820064304200201440000512
+:1043A00032C240008C03012C8F4200681462FFF27D
+:1043B00032C24000144000023C02000102C2B0259B
+:1043C0008F4200001040000700000000AF80004C4A
+:1043D0008F82004C1040FFFD00000000100000051F
+:1043E00000000000AF8000488F8200481040FFFDB1
+:1043F000000000008F8200601000FFB4344208000B
+:1044000030C2001010400029240400108C02012446
+:10441000AF420058AF8400648F4202D424420001AE
+:10442000AF4202D48F4202D48F8200643042001027
+:104430001440000532C220008C0301248F42005832
+:104440001462FFF232C220005040000136D68000D4
+:104450008F4200001040000700000000AF80004CB9
+:104460008F82004C1040FFFD00000000100000058E
+:1044700000000000AF8000488F8200481040FFFD20
+:10448000000000008F82006034420100AF820060B3
+:104490008F42000010400003000000001000006C7C
+:1044A000AF80004C1000006AAF80004830C20001AD
+:1044B0001040000424020001AF8200641000006478
+:1044C0000000000030C200021440000B3C05000355
+:1044D0003C0400012484624434A505000000382116
+:1044E000AFA000100C002B3BAFA000142402FFC0B3
+:1044F00010000057AF8200648C05022C8C02010C66
+:1045000010A20048000510808C46030024A2000180
+:104510003045003F24020003AC05022C00061E02B9
+:1045200010620005240200101062001D30C20FFF4F
+:1045300010000039000000008F4302A88F440000E3
+:1045400030C20FFFAF42004824630001AF4302A80E
+:10455000108000078F4202A8AF80004C8F82004C71
+:104560001040FFFD000000001000000500000000EA
+:10457000AF8000488F8200481040FFFD000000001F
+:104580008F82006034420200AF8200608F420000E0
+:104590001040001F000000001000001B0000000081
+:1045A000AF42005832C220005040000136D6800091
+:1045B0008F4202D48F43000024420001AF4202D454
+:1045C000106000078F4202D4AF80004C8F82004CF5
+:1045D0001040FFFD0000000010000005000000007A
+:1045E000AF8000488F8200481040FFFD00000000AF
+:1045F0008F82006034420100AF8200608F42000071
+:10460000104000030000000010000006AF80004CC6
+:1046100010000004AF8000480C00219600C020214B
+:10462000004028218C02010C14A200022402000286
+:10463000AF8200648F8200643042000214400004A4
+:10464000000000008C02010C14A2FFAC000000006E
+:104650008FBF001803E0000827BD002003E000081A
+:104660000000000027BDFFA0AFB000400080802107
+:10467000001016022442FFFF304300FF2C6200139B
+:10468000AFBF0058AFBE0054AFB50050AFB3004C41
+:10469000AFB20048AFB10044104001F3AFA5003401
+:1046A000000310803C010001002208218C22628856
+:1046B00000400008000000000010130230440FFF0B
+:1046C0002402000110820005240200021082000C66
+:1046D0002402FFFE100000243C0500038F43000469
+:1046E0003C0200018C426F04AF440200AF4402045C
+:1046F0003C0400018C846E801000000934630001CA
+:104700008F430004AF440200AF4402043C040001A4
+:104710008C846E80006218243C0200012442CA2866
+:104720000002110000021182AF4300043C030800A4
+:1047300000431025AC8200388F84005400041442DA
+:1047400000041C820043102100041CC200431023FB
+:1047500000041D020043102100041D4200431023E9
+:1047600010000009AF4202083C040001248462509A
+:1047700034A510000200302100003821AFA0001045
+:104780000C002B3BAFA000148F4202A0244200017A
+:10479000AF4202A01000021F8F4202A027B00028E3
+:1047A00002002021240502100C002BBF2406000863
+:1047B0000C00251802002021100002160000000045
+:1047C0008FAA003427A40028000A1880254200017F
+:1047D0003042003FAFA200348C6503008FAA003442
+:1047E000000210808C430300254200013042003F4C
+:1047F000AFA20034AC02022CAFA500280C00251893
+:10480000AFA3002C100002030000000027B0002816
+:1048100002002021240502100C002BBF24060008F2
+:104820000C00265702002021100001FA00000000B1
+:104830008FAA003427A40028000A1880254200010E
+:104840003042003FAFA200348C6503008FAA0034D1
+:10485000000210808C430300254200013042003FDB
+:10486000AFA20034AC02022CAFA500280C002657E2
+:10487000AFA3002C100001E700000000001013029D
+:1048800030430FFF240200011062000524020002E1
+:104890001062001E3C020002100000333C050003C1
+:1048A0003C03000202C310245440003702C3B02569
+:1048B0008F8202283C01000100370821AC2238D841
+:1048C0008F82022C3C01000100370821AC2238DC29
+:1048D0008F8202303C01000100370821AC2238E011
+:1048E0008F8202343C01000100370821AC2238E4F9
+:1048F0002402FFFFAF820228AF82022CAF82023077
+:10490000AF8202341000002002C3B02502C210247E
+:10491000104000123C02FFFD3C0200010057102134
+:104920008C4238D8AF8202283C0200010057102187
+:104930008C4238DCAF82022C3C020001005710216F
+:104940008C4238E0AF8202303C0200010057102157
+:104950008C4238E4AF8202343C02FFFD3442FFFF58
+:104960001000000902C2B0243C0400012484625CEF
+:1049700034A511000200302100003821AFA0001042
+:104980000C002B3BAFA000148F4202CC244200014C
+:10499000AF4202CC1000019F8F4202CC00101302E4
+:1049A00030450FFF2402000110A20005240200027E
+:1049B00010A2000D3C0408FF100000143C05000389
+:1049C0003C0208FF3442FFFF8F8302203C040004B6
+:1049D00002C4B0250062182434630008AF830220AB
+:1049E00010000012AF4502983484FFF73C03FFFB30
+:1049F0008F8202203463FFFF02C3B02400441024DE
+:104A0000AF82022010000009AF4502983C0400016B
+:104A10002484626834A5120002003021000038218D
+:104A2000AFA000100C002B3BAFA000148F4202BCC3
+:104A300024420001AF4202BC100001768F4202BC4A
+:104A400027840208240502000C002BBF240600085E
+:104A500027440224240502000C002BBF2406000872
+:104A60008F4202C424420001AF4202C41000016917
+:104A70008F4202C40010130230430FFF24020001D2
+:104A8000106200112862000250400005240200025A
+:104A90001060000700000000100000170000000078
+:104AA0001062000F00000000100000130000000062
+:104AB0008C060248000020210C005104240500044B
+:104AC00010000007000000008C06024800002021B2
+:104AD0000C00510424050004100000100000000028
+:104AE0008C06024C000020210C005104240500011A
+:104AF0001000000A000000003C04000124846274DD
+:104B00003C05000334A513000200302100003821C9
+:104B1000AFA000100C002B3BAFA000148F4202C0CE
+:104B200024420001AF4202C01000013A8F4202C08D
+:104B30000C002426000000001000013600000000D8
+:104B400024020001A34205C5241001008F4401A8DE
+:104B50008F4501ACAFB00010AFA000148F4200141D
+:104B6000AFA200188F42010826E600280040F8098D
+:104B7000240704001040FFF500000000100001258C
+:104B8000000000003C03FFFF34637FFF8F42036897
+:104B90008F44036002C3B02400001821AF400058C6
+:104BA000AF40005CAF400060AF40006400441023A1
+:104BB000AF4203683C020900AF400360AFA200208F
+:104BC0008F5E001827AA0020240200FF13C20002F3
+:104BD000AFAA003C27C300018C020228006090218C
+:104BE0001642000E001E38C08F42033C24420001D2
+:104BF000AF42033C8F42033C8C0202283C0400017C
+:104C00002484620C3C050009AFA00014AFA2001080
+:104C10008FA600201000006B34A5050000F71021BE
+:104C20008FA300208FA40024AC4304C0AC4404C470
+:104C30008F8300548F820054247003E802021023F3
+:104C40002C4203E91040001B0000982100E088215D
+:104C5000263504C08F4401788F45017C022018213D
+:104C6000240A0004AFAA0010AFB200148F48000C51
+:104C70000000102102F53021AFA800188F48010C68
+:104C80002407000800A3282100A3482B008220212C
+:104C90000100F80900892021544000062413000176
+:104CA0008F820054020210232C4203E91440FFE9D2
+:104CB00000000000326200FF54400017AF5200189D
+:104CC0008F42037824420001AF4203788F42037879
+:104CD0008F8201208FAA003CAFA200108F82012496
+:104CE0003C040001248462183C050009AFA20014B2
+:104CF0008D4600001000003334A506008F420308E3
+:104D00002413000124420001AF4203088F4203082C
+:104D10001000001C326200FF8F8300548F82005409
+:104D2000247003E8020210232C4203E9104000140F
+:104D300000009821241100108F42000C8F44016064
+:104D40008F4501648F860120AFB10010AFB200140F
+:104D5000AFA200188F42010C240700080040F80998
+:104D600024C6001C1440FFE5000000008F820054A0
+:104D7000020210232C4203E91440FFEF0000000060
+:104D8000326200FF14400011000000008F420378DF
+:104D900024420001AF4203788F4203788F820120C2
+:104DA0008FAA003CAFA200108F8201243C040001B6
+:104DB000248462203C050009AFA200148D46000047
+:104DC00034A507000C002B3B03C038218F4202B0F2
+:104DD00024420001AF4202B08F4202B08F4202F87B
+:104DE00024420001AF4202F81000008A8F4202F80C
+:104DF0008C02025C27440224AF4201F08C02026064
+:104E000024050200240600080C002BBFAF4201F865
+:104E10008F82022030420008144000022402000168
+:104E200024020002AF4202988F4202AC24420001E9
+:104E3000AF4202AC100000778F4202AC3C0200FF90
+:104E40003442FFFF0202182432C2018014400006DF
+:104E50003402FFFB0043102B14400003000000004D
+:104E60001000006CAF4300BC3C040001248462804D
+:104E70003C05000334A51500020030210000382154
+:104E8000AFA000100C002B3BAFA000143C020700A9
+:104E90003442100000101E0200621825AFA300204B
+:104EA0008F510018240200FF12220002000080210E
+:104EB000263000018C0202281602000E001130C0BC
+:104EC0008F42033C24420001AF42033C8F42033C2B
+:104ED0008C0202283C040001248461F43C05000992
+:104EE000AFA00014AFA200108FA600201000003F5A
+:104EF00034A5010000D710218FA300208FA4002427
+:104F0000AC4304C0AC4404C400C018218F440178F1
+:104F10008F45017C0000102124070004AFA700107A
+:104F2000AFB000148F48000C24C604C002E6302144
+:104F3000AFA800188F48010C2407000800A32821FF
+:104F400000A3482B008220210100F80900892021BC
+:104F50001440000B240700088F820120AFA200102C
+:104F60008F8201243C040001248461FC3C0500097B
+:104F7000AFA200148FA600201000001C34A5020070
+:104F80008F4401608F4501648F43000CAF500018BF
+:104F90008F86012024020010AFA20010AFB00014D1
+:104FA000AFA300188F42010C0040F80924C6001C72
+:104FB00014400010000000008F4203402442000112
+:104FC000AF4203408F4203408F820120AFA2001006
+:104FD0008F8201243C040001248462043C05000902
+:104FE000AFA200148FA6002034A503000C002B3BB9
+:104FF000022038218F4202E024420001AF4202E049
+:105000008F4202E08F4202F024420001AF4202F0E0
+:105010008F4202F08FA200348FBF00588FBE005421
+:105020008FB500508FB3004C8FB200488FB1004451
+:105030008FB0004003E0000827BD006027BDFFF8E7
+:105040002408FFFF10A00014000048213C0AEDB81E
+:10505000354A83209087000024840001000030211D
+:1050600001071026304200011040000200081842DB
+:10507000006A18260060402124C600012CC20008E6
+:105080001440FFF700073842252900010125102BA5
+:105090001440FFF0000000000100102103E00008B0
+:1050A00027BD000827BDFFB0AFBF0048AFBE00441A
+:1050B000AFB50040AFB3003CAFB20038AFB1003481
+:1050C000AFB000308F870220AFA700248F87020087
+:1050D000AFA7002C8F8202203C0308FF3463FFFF40
+:1050E0000043102434420004AF8202208F82020069
+:1050F0003C03C0FF3463FFFF00431024344200042C
+:10510000AF8202008F5303588F55035C8F5E03609C
+:105110008F470364AFA700148F470368AFA7001C35
+:105120008F4202D0274401C024420001AF4202D086
+:105130008F5002D08F5102048F5202000C002BA816
+:1051400024050400AF530358AF55035CAF5E036002
+:105150008FA70014AF4703648FA7001CAF470368F5
+:10516000AF5002D0AF510204AF5202008C02025C79
+:1051700027440224AF4201F08C02026024050200A1
+:1051800024060008AF4201F8240200060C002BBFE1
+:10519000AF4201F43C023B9A3442CA00AF4201FCE8
+:1051A000240203E82404000224030001AF42029415
+:1051B000AF440290AF43029C8F820220304200082D
+:1051C0001040000400000000AF43029810000003EC
+:1051D00000003021AF440298000030213C03000160
+:1051E0000066182190636D000346102124C600015B
+:1051F000A043022C2CC2000F1440FFF803461821D4
+:1052000024C600018F820040240400802405008011
+:105210000002170224420030A062022C0346102133
+:105220000C002BA8A040022C8FA7002430E2000421
+:1052300014400006000000008F8202203C0308FF9B
+:105240003463FFFB00431024AF8202208FA7002CA1
+:1052500030E2000414400006000000008F820200CB
+:105260003C03C0FF3463FFFB00431024AF82020005
+:105270008FBF00488FBE00448FB500408FB3003C05
+:105280008FB200388FB100348FB0003003E00008D7
+:1052900027BD00500000000000000000AF400104E6
+:1052A00024040001000410C002E21821248200013D
+:1052B0003C01000100230821A42234D00040202119
+:1052C0002C8200801440FFF8000410C0240200016A
+:1052D0003C01000100370821A42038D0AF42010072
+:1052E000AF800228AF80022CAF800230AF80023442
+:1052F00003E000080000000027BDFFE8AFBF001476
+:10530000AFB000108F420104284200051040002673
+:10531000008080213C0200018F430104344230D0E0
+:1053200002E22021000318C00062182102E31821C4
+:105330000083102B1040001500001021960700007C
+:1053400024840006246600069482FFFC14470009AA
+:10535000000028219483FFFE9602000214620006DA
+:1053600000A0102194820000960300040043102640
+:105370002C45000100A010211440000924840008DD
+:105380000086102B1440FFF000001021304200FF77
+:1053900014400030240200011000002E00001021F3
+:1053A0001000FFFA24020001020020210C00240C4E
+:1053B000240500063042007F000218C002E31021DD
+:1053C0003C01000100220821942230D01040FFF25D
+:1053D00002E310213C06000100C2302194C630D007
+:1053E00010C0FFED3C080001350834D296070000DC
+:1053F000000610C000572021008820219482000060
+:10540000144700090000282194830002960200023C
+:105410001462000600A01021948200049603000488
+:10542000004310262C45000100A010211440000765
+:10543000000610C002E210213C06000100C230212B
+:1054400094C634D014C0FFEB000610C010C0FFD2C9
+:10545000240200018FBF00148FB0001003E0000889
+:1054600027BD001803E000080000000027BDFFB0C2
+:1054700000801021AFB00030245000020200202133
+:1054800024050006AFB1003400408821AFBF0048BA
+:10549000AFBE0044AFB50040AFB3003C0C00240CDD
+:1054A000AFB200383047007F000710C002E2102181
+:1054B0003C05000100A2282194A530D050A0001C7A
+:1054C00000A030213C090001352934D29628000281
+:1054D000000510C00057202100892021948200007F
+:1054E0001448000900003021948300029602000253
+:1054F0001462000600C01021948200049603000488
+:10550000004310262C46000100C010211440000763
+:10551000000510C002E210213C05000100A2282174
+:1055200094A534D014A0FFEB000510C000A03021DA
+:1055300010C00014000610C0005718213C010001E3
+:10554000002308218C2334D000571021AFA3001072
+:105550003C010001002208218C2234D43C040001CB
+:1055600024846394AFA200148E2600008E270004CA
+:105570003C0500040C002B3B34A504001000006324
+:105580003C0208008F45010010A00006000510C075
+:1055900002E210213C01000100220821942234D0B3
+:1055A000AF42010000A0302114C00011000628C045
+:1055B000000710C002E21021AFA700103C0100015B
+:1055C00000220821942230D03C040001248463A0EE
+:1055D000AFA200148E2600008E2700043C050004B4
+:1055E0000C002B3B34A50500100000483C020800CD
+:1055F00000B718213C02000196040000344234D266
+:1056000000621821A46400008E020002000720C07E
+:10561000AC62000202E410213C0300010062182188
+:10562000946330D002E510213C01000100220821E2
+:10563000A42334D002E410213C01000100220821FF
+:10564000A42630D08F420104244200012842008069
+:105650001040000F3C0200028F4201043C04000194
+:10566000348430D296030000000210C0005710218D
+:1056700000441021A44300008E030002AC4300024A
+:105680008F42010424420001AF4201043C020002A7
+:1056900002C2102410400011000721423C03000107
+:1056A000346338D824020003004410230002108021
+:1056B0000057202100832021005710210043102192
+:1056C00030E5001F8C4300002402000100A21004FA
+:1056D000006218251000000CAC83000024020003B7
+:1056E0000044102300021080005C2821005C10217F
+:1056F00030E4001F8C4302282402000100821004C1
+:1057000000621825ACA302283C02080034421000B5
+:1057100000001821AFA200208F5E001827AA0020E9
+:10572000240200FF13C20002AFAA002C27C300010D
+:105730008C020228006090211642000E001E38C024
+:105740008F42033C24420001AF42033C8F42033CA2
+:105750008C0202283C0400012484635C3C0500099F
+:10576000AFA00014AFA200108FA600201000006BA5
+:1057700034A5050000F710218FA300208FA400247A
+:10578000AC4304C0AC4404C48F8300548F820054E3
+:10579000247003E8020210232C4203E91040001B8E
+:1057A0000000982100E08821263504C08F4401784C
+:1057B0008F45017C02201821240A0004AFAA0010A2
+:1057C000AFB200148F48000C0000102102F5302108
+:1057D000AFA800188F48010C2407000800A3282157
+:1057E00000A3482B008220210100F8090089202114
+:1057F00054400006241300018F820054020210233B
+:105800002C4203E91440FFE900000000326200FF6F
+:1058100054400017AF5200188F4203782442000111
+:10582000AF4203788F4203788F8201208FAA002C29
+:10583000AFA200108F8201243C040001248463681D
+:105840003C050009AFA200148D4600001000003393
+:1058500034A506008F4203082413000124420001EE
+:10586000AF4203088F4203081000001C326200FFA1
+:105870008F8300548F820054247003E802021023A7
+:105880002C4203E91040001400009821241100105C
+:105890008F42000C8F4401608F4501648F86012088
+:1058A000AFB10010AFB20014AFA200188F42010CCC
+:1058B000240700080040F80924C6001C1440FFE536
+:1058C000000000008F820054020210232C4203E9E2
+:1058D0001440FFEF00000000326200FF144000118E
+:1058E000000000008F42037824420001AF42037899
+:1058F0008F4203788F8201208FAA002CAFA2001064
+:105900008F8201243C040001248463703C0500095B
+:10591000AFA200148D46000034A507000C002B3BFD
+:1059200003C038218F4202B424420001AF4202B4C6
+:105930008F4202B48F4202F424420001AF4202F4CB
+:105940008F4202F48FBF00488FBE00448FB50040E5
+:105950008FB3003C8FB200388FB100348FB000306D
+:1059600003E0000827BD005027BDFFA000801021E4
+:10597000AFB00040245000020200202124050006A0
+:10598000AFB1004400408821AFBF0058AFBE005403
+:10599000AFB50050AFB3004C0C00240CAFB20048C0
+:1059A0003048007F000810C002E210213C060001D0
+:1059B00000C2302194C630D010C0001C0000382135
+:1059C0003C0A0001354A34D296290002000610C074
+:1059D00000572021008A20219482000014490009E8
+:1059E000000028219483000296020002146200063F
+:1059F00000A01021948200049603000400431026A6
+:105A00002C45000100A0102114400008000610C021
+:105A100000C0382102E210213C06000100C2302102
+:105A200094C634D014C0FFEA000610C014C00011A0
+:105A3000AFA70028000810C002E21021AFA8001094
+:105A40003C01000100220821942230D03C040001D6
+:105A5000248463ACAFA200148E2600008E270004BD
+:105A60003C0500040C002B3B34A509001000007518
+:105A70003C02080010E0000C000610C002E21021F9
+:105A80003C03000100621821946334D0000710C069
+:105A900002E210213C01000100220821A42334D09D
+:105AA0001000000B3C04000102E210213C03000145
+:105AB00000621821946334D0000810C002E2102163
+:105AC0003C01000100220821A42330D03C04000145
+:105AD000348430D08F430100000610C002E2102150
+:105AE0003C01000100220821A42334D08F4201048C
+:105AF00002E438210000282118400029AF460100A7
+:105B000024E6000694C3FFFC96020000146200091C
+:105B10000000202194C3FFFE9602000214620006DA
+:105B20000080102194C20000960300040043102658
+:105B30002C440001008010215040001424A50001D5
+:105B40008F4201042442FFFF00A2102A1040000BE4
+:105B500024E40004948200068C830008A482FFFEE3
+:105B6000AC8300008F42010424A500012442FFFF02
+:105B700000A2102A1440FFF7248400088F42010479
+:105B80002442FFFF10000006AF4201048F420104CF
+:105B900024C6000800A2102A1440FFDA24E70008F7
+:105BA000000810C002E210213C010001002208217F
+:105BB000942230D0144000233C0208003C02000232
+:105BC00002C2102410400012000821423C030001D0
+:105BD000346338D8240200030044102300021080EC
+:105BE000005720210083202100571021004310215D
+:105BF0003105001F240300018C42000000A318049B
+:105C000000031827004310241000000DAC82000090
+:105C1000240200030044102300021080005C2821AD
+:105C2000005C10213104001F240300018C42022873
+:105C3000008318040003182700431024ACA2022894
+:105C40003C0208003442200000001821AFA20020CE
+:105C50008F5E001827AB0020240200FF13C2000251
+:105C6000AFAB003427C300018C02022800609021F2
+:105C70001642000E001E38C08F42033C2442000131
+:105C8000AF42033C8F42033C8C0202283C040001DB
+:105C90002484635C3C050009AFA00014AFA200108F
+:105CA0008FA600201000006B34A5050000F710211E
+:105CB0008FA300208FA40024AC4304C0AC4404C4D0
+:105CC0008F8300548F820054247003E80202102353
+:105CD0002C4203E91040001B0000982100E08821BD
+:105CE000263504C08F4401788F45017C022018219D
+:105CF000240B0004AFAB0010AFB200148F48000CAF
+:105D00000000102102F53021AFA800188F48010CC7
+:105D10002407000800A3282100A3482B008220218B
+:105D20000100F809008920215440000624130001D5
+:105D30008F820054020210232C4203E91440FFE931
+:105D400000000000326200FF54400017AF520018FC
+:105D50008F42037824420001AF4203788F420378D8
+:105D60008F8201208FAB0034AFA200108F820124FC
+:105D70003C040001248463683C050009AFA20014C0
+:105D80008D6600001000003334A506008F42030822
+:105D90002413000124420001AF4203088F4203088C
+:105DA0001000001C326200FF8F8300548F82005469
+:105DB000247003E8020210232C4203E9104000146F
+:105DC00000009821241100108F42000C8F440160C4
+:105DD0008F4501648F860120AFB10010AFB200146F
+:105DE000AFA200188F42010C240700080040F809F8
+:105DF00024C6001C1440FFE5000000008F82005400
+:105E0000020210232C4203E91440FFEF00000000BF
+:105E1000326200FF14400011000000008F4203783E
+:105E200024420001AF4203788F4203788F82012021
+:105E30008FAB0034AFA200108F8201243C0400011C
+:105E4000248463703C050009AFA200148D66000035
+:105E500034A507000C002B3B03C038218F4202B849
+:105E600024420001AF4202B88F4202B88F4202F4CE
+:105E700024420001AF4202F48F4202F48FBF005867
+:105E80008FBE00548FB500508FB3004C8FB20048C6
+:105E90008FB100448FB0004003E0000827BD0060D0
+:105EA00000000000000000000000000027BDFFE02F
+:105EB00027644000AFBF00180C002BA82405100079
+:105EC0003C03000134632CC03C04000134842EC820
+:105ED00024020020AF82011C02E31021AF800100E8
+:105EE000AF800104AF800108AF800110AF800114C2
+:105EF000AF800118AF800120AF800124AF8001285E
+:105F0000AF800130AF800134AF800138AF4200EC88
+:105F100002E31021AF4200F002E41021AF4200F48E
+:105F200002E41021AF4200F83C02000100571021AA
+:105F3000904240F41440001C3C0500018F82011C7B
+:105F40003C040001248464703C05000134420001DB
+:105F5000AF82011CAFA00010AFA000148F86011CFF
+:105F600034A501000C002B3B000038218C020218E4
+:105F70003042004010400014000000008F82011CDD
+:105F80003C0400012484647C3C050001344200048C
+:105F9000AF82011CAFA00010AFA000148F86011CBF
+:105FA0001000000734A502003C040001248464842E
+:105FB000AFA00010AFA000148F86011C34A5030011
+:105FC0000C002B3B000038218FBF001803E00008B5
+:105FD00027BD00208FA900108F83012C8FAA0014E9
+:105FE0008FAB00181060000A27624FE014620002B5
+:105FF00024680020276848008F82012811020004CD
+:10600000000000008F82012415020007000000003C
+:106010008F4303340000102124630001AF43033495
+:10602000100000398F430334AC640000AC650004F9
+:10603000AC660008A467000EAC690018AC6A001CCE
+:10604000AC6B0010AC620014AF8801208F4200FCE2
+:106050008F4400F42442FFFFAF4200FC8C8200001A
+:10606000104900053042FF8F104000193122FF8F88
+:10607000104000183C0200018C8300042C620010C8
+:10608000104000133C02000124630001AC830004B3
+:106090008F4300F8344230C802E2102154620004F9
+:1060A000246200083C02000134422EC802E21021A2
+:1060B00014440015240200018F820128244200208C
+:1060C000AF8201288F8201281000000F24020001F6
+:1060D0003C020001344230C802E210215482000424
+:1060E000248200083C02000134422EC802E2102142
+:1060F0000040202124020001AF4400F4AC890000DC
+:10610000AC8200042402000103E00008000000004B
+:1061100003E00008000000008FA900108F83010C2D
+:106120008FAA00148FAB00181060000A276247E0A6
+:106130001462000224680020276840008F82010852
+:1061400011020004000000008F8201041502000704
+:10615000000000008F430338000010212463000179
+:10616000AF430338100000358F430338AC640000A0
+:10617000AC650004AC660008A467000EAC690018AA
+:10618000AC6A001CAC6B0010AC620014AF8801005C
+:106190008F4400EC8C820000304200061040001951
+:1061A00031220006104000183C0200018C830004DC
+:1061B0002C620010104000133C0200012463000117
+:1061C000AC8300048F4300F034422EC002E2102161
+:1061D00054620004246200083C02000134422CC0D6
+:1061E00002E2102114440015240200018F820108EC
+:1061F00024420020AF8201088F8201081000000FA6
+:10620000240200013C02000134422EC002E21021AF
+:1062100054820004248200083C02000134422CC055
+:1062200002E210210040202124020001AF4400ECD2
+:10623000AC890000AC8200042402000103E00008E5
+:106240000000000003E000080000000027BDFFD8A8
+:106250003C0400012484648C3C050001AFBF002491
+:10626000AFB20020AFB1001CAFB000188F90010496
+:106270008F9100B08F92011C34A525008F82010000
+:106280000240302102203821AFA200100C002B3B2D
+:10629000AFB000148E020008AFA200108E02000CF6
+:1062A0003C04000124846498AFA200148E06000010
+:1062B0008E0700043C0500010C002B3B34A5251083
+:1062C0008E020018AFA200108E02001C3C040001D8
+:1062D000248464A4AFA200148E0600108E0700145C
+:1062E0003C0500010C002B3B34A525203C027F001F
+:1062F000022210243C030800544300163C03020011
+:106300008F82009C3042FFFF144000123C030200C9
+:106310003C040001248464B03C05000234A5F03044
+:10632000000030210000382136420002AF82011CFB
+:1063300036220001AF8200B0AF900104AF92011C81
+:10634000AFA000100C002B3BAFA0001410000024E5
+:106350000000000002C310241040000D022310248E
+:106360001040000B36420002AF82011C36220001B1
+:10637000AF8200B0AF900104AF92011C8F42033096
+:1063800024420001AF420330100000158F42033059
+:106390003C040001248464B8240202A9AFA20010C6
+:1063A000AFA000148F8601443C07000124E764C0BD
+:1063B0000C002B3B3405DEAD8F82011C3442000201
+:1063C000AF82011C8F82022034420004AF8202207F
+:1063D0008F8201403C03000100431025AF82014041
+:1063E0008FBF00248FB200208FB1001C8FB0001827
+:1063F00003E0000827BD002827BDFFD83C040001AA
+:10640000248464E83C050001AFBF0024AFB2002043
+:10641000AFB1001CAFB000188F9001248F9100A085
+:106420008F92011C34A526008F820120024030216A
+:1064300002203821AFA200100C002B3BAFB000149B
+:106440008E020008AFA200108E02000C3C04000176
+:10645000248464F4AFA200148E0600008E070004AA
+:106460003C0500010C002B3B34A526108E020018C1
+:10647000AFA200108E02001C3C04000124846500C1
+:10648000AFA200148E0600108E0700143C05000118
+:106490000C002B3B34A526203C027F000222102456
+:1064A0003C030800544300163C0302008F8200ACFA
+:1064B0003042FFFF144000123C0302003C04000184
+:1064C0002484650C3C05000134A5F0300000302127
+:1064D0000000382136420002AF82011C3622000142
+:1064E000AF8200A0AF900124AF92011CAFA00010BA
+:1064F0000C002B3BAFA00014100000240000000093
+:1065000002C310241040000D022310241040000B81
+:1065100036420002AF82011C36220001AF8200A089
+:10652000AF900124AF92011C8F42032C2442000142
+:10653000AF42032C100000158F42032C3C040001D5
+:10654000248464B8240202E2AFA20010AFA00014B9
+:106550008F8601443C07000124E764C00C002B3BFC
+:106560003405DEAD8F82011C34420002AF82011C73
+:106570008F82022034420004AF8202208F820140C9
+:106580003C03000100431025AF8201408FBF00246F
+:106590008FB200208FB1001C8FB0001803E00008FC
+:1065A00027BD00280000602100005021000030219C
+:1065B0000000282100006821000048210000782107
+:1065C000000070218F8801248F8701041580002E20
+:1065D0008F8B011C11A00014316208008F820120F2
+:1065E00010460029000000003C0400018C846EE489
+:1065F0008CC200008CC30004AC820000AC83000499
+:106600008CC20008AC82000894C2000EA482000E66
+:106610008CC20010240C0001AC8200108CC200144B
+:106620001000001224C600201040001700000000D7
+:106630003C0400018C846EE48D0200008D03000494
+:10664000AC820000AC8300048D020008AC8200081C
+:106650009502000EA482000E8D0200102506002077
+:10666000AC8200108D020014240C000100C018211F
+:10667000AC82001427624FE00043102B544000010D
+:1066800027634800006030211540002F316201006F
+:1066900011200014316280008F8201001045002A11
+:1066A000316201003C0400018C846EE08CA2000089
+:1066B0008CA30004AC820000AC8300048CA2000810
+:1066C000AC82000894A2000EA482000E8CA20010DE
+:1066D000240A0001AC8200108CA2001410000012E9
+:1066E00024A5002010400018316201003C04000184
+:1066F0008C846EE08CE200008CE30004AC8200002D
+:10670000AC8300048CE20008AC82000894E2000E26
+:10671000A482000E8CE2001024E50020AC82001060
+:106720008CE20014240A000100A01821AC8200149D
+:10673000276247E00043102B5440000127634000CC
+:1067400000602821316201005440001D31621000B8
+:1067500011A0000931A20800104000042502002009
+:106760008F8200A8A5E2000025020020AF8201244C
+:106770008F8801240000682111800011316210000F
+:106780003C0400018C846EE48C8200008C83000445
+:10679000AF820080AF8300848C820008AF8200A4A7
+:1067A0009482000EAF8200AC8C8200100000602149
+:1067B000AF8200A08C8D00108C8F0014316210000D
+:1067C0001440FF82000000001120000F3122080059
+:1067D000104000043C0200028F8200B8A5C20000F5
+:1067E0003C020002012210241040000424E2002098
+:1067F0008F8200B4AF8200D424E20020AF82010473
+:106800008F870104000048211140FF700000000044
+:106810003C0400018C846EE08C8200008C830004B8
+:10682000AF820090AF8300948C820008AF8200B4E6
+:106830009482000EAF82009C8C82001000005021D8
+:10684000AF8200B08C8900101000FF608C8E0014A5
+:1068500003E0000800000000000060210000582153
+:106860000000302100002821000068210000502194
+:1068700000007821000070218F8801248F87010497
+:106880003C1801001580002E8F89011C11A00014F6
+:10689000312208008F8201201046002900000000EC
+:1068A0003C0400018C846EE48CC200008CC30004A4
+:1068B000AC820000AC8300048CC20008AC820008EB
+:1068C00094C2000EA482000E8CC20010240C0001A1
+:1068D000AC8200108CC200141000001224C60020EC
+:1068E00010400017000000003C0400018C846EE49E
+:1068F0008D0200008D030004AC820000AC83000414
+:106900008D020008AC8200089502000EA482000EE1
+:106910008D02001025060020AC8200108D020014AC
+:10692000240C000100C01821AC82001427624FE043
+:106930000043102B544000012763480000603021C1
+:106940001560002F31220100114000143122800017
+:106950008F8201001045002A312201003C04000111
+:106960008C846EE08CA200008CA30004AC8200003A
+:10697000AC8300048CA20008AC82000894A2000E34
+:10698000A482000E8CA20010240B0001AC82001027
+:106990008CA200141000001224A500201040001842
+:1069A000312201003C0400018C846EE08CE2000086
+:1069B0008CE30004AC820000AC8300048CE200088D
+:1069C000AC82000894E2000EA482000E8CE200105B
+:1069D00024E50020AC8200108CE20014240B00019E
+:1069E00000A01821AC820014276247E00043102B5E
+:1069F000544000012763400000602821312201003B
+:106A00005440001D3122100011A0000931A20800DD
+:106A100010400004250200208F8200A8A5E200009B
+:106A200025020020AF8201248F8801240000682104
+:106A300011800011312210003C0400018C846EE4AE
+:106A40008C8200008C830004AF820080AF830084BE
+:106A50008C820008AF8200A49482000EAF8200AC4A
+:106A60008C82001000006021AF8200A08C8D00108D
+:106A70008C8F00143122100014400022000000000E
+:106A80001140000F31420800104000043C02000297
+:106A90008F8200B8A5C200003C020002014210240F
+:106AA0001040000424E200208F8200B4AF8200D4A2
+:106AB00024E20020AF8201048F87010400005021EE
+:106AC00011600010000000003C0400018C846EE0A6
+:106AD0008C8200008C830004AF820090AF8300940E
+:106AE0008C820008AF8200B49482000EAF82009CBA
+:106AF0008C82001000005821AF8200B08C8A0010F8
+:106B00008C8E00148F8200703C0310000043102410
+:106B10001040FF5C000000008F82005424420005FA
+:106B2000AF8200788C040234108000160000182117
+:106B30003C020001005710218C4240E8244200052D
+:106B40003C01000100370821AC2240E83C02000172
+:106B5000005710218C4240E80044102B14400009DB
+:106B6000240200013C0300803C01000100370821A1
+:106B7000AC2040E83C010001003708211000000C67
+:106B8000A02240F03C02000100571021904240F04A
+:106B9000144000063C0200803C0200010057102116
+:106BA000904240F1104000023C0200800062182533
+:106BB0008C04023010800013000000003C02000131
+:106BC000005710218C4240EC244200053C0100019A
+:106BD00000370821AC2240EC3C0200010057102194
+:106BE0008C4240EC0044102B1440000600000000D2
+:106BF0003C01000100370821AC2040EC10000006E9
+:106C0000007818253C02000100571021904240F204
+:106C100054400001007818251060FF1A00000000A1
+:106C20008F4200001040000700000000AF80004CC1
+:106C30008F82004C1040FFFD000000001000000596
+:106C400000000000AF8000488F8200481040FFFD28
+:106C5000000000008F82006000431025AF820060BA
+:106C60008F42000010400003000000001000FF05EC
+:106C7000AF80004C1000FF03AF80004803E0000825
+:106C80000000000000000000000000003C020001C5
+:106C90008C426D2827BDFFE8AFBF001414400012DE
+:106CA000AFB000103C10000126106F9002002021B0
+:106CB0000C002BA82405200026021FE03C01000147
+:106CC000AC226EEC3C010001AC226EE8AC0202503A
+:106CD00024022000AC100254AC020258240200012D
+:106CE0003C010001AC226D288FBF00148FB0001052
+:106CF00003E0000827BD00183C0900018D296EEC57
+:106D00008C8200008FA300108FA80014AD22000019
+:106D10008C820004AD250008AD2200048F8200544F
+:106D2000AD260010AD270014AD230018AD28001CBF
+:106D3000AD22000C2529FFE03C02000124426F90A7
+:106D40000122102B10400003000000003C0900014C
+:106D50008D296EE83C0200018C426D10AD220000CE
+:106D60003C0200018C426D103C010001AC296EEC2C
+:106D7000AD220004AC09025003E00008000000004E
+:106D800027BDFFD0AFB000103C1000018E106EEC9C
+:106D90003C0200018C426D10AFB1001400808821CC
+:106DA000AFBE00248FBE00408FA40048AFB20018D1
+:106DB00000A09021AFBF0028AFB50020AFB3001CEA
+:106DC000AE0200003C0200018C426D1000C0982110
+:106DD00000E0A82110800006AE020004260500088D
+:106DE0000C002BB324060018100000052610FFE04D
+:106DF000260400080C002BA8240500182610FFE02C
+:106E00003C03000124636F900203102B1040000329
+:106E1000000000003C1000018E106EE88E22000081
+:106E2000AE0200008E220004AE120008AE02000482
+:106E30008F820054AE130010AE150014AE1E001861
+:106E40008FA80044AE08001CAE02000C2610FFE024
+:106E50000203102B10400003000000003C10000152
+:106E60008E106EE83C0200018C426D10AE020000F4
+:106E70003C0200018C426D103C010001AC306EEC14
+:106E8000AE020004AC1002508FBF00288FBE002459
+:106E90008FB500208FB3001C8FB200188FB1001483
+:106EA0008FB0001003E0000827BD003000851821D6
+:106EB0000083102B1040000600000000AC80000092
+:106EC000248400040083102B5440FFFDAC8000009C
+:106ED00003E000080000000000A6182100A3102B0A
+:106EE00010400007000000008C820000ACA20000EF
+:106EF00024A5000400A3102B1440FFFB24840004ED
+:106F000003E0000800000000008618210083102B19
+:106F100010400007000000008CA20000AC820000BE
+:106F2000248400040083102B1440FFFB24A50004DC
+:106F300003E00008000000000006308000861821F1
+:106F40000083102B1040000600000000AC850000FC
+:106F5000248400040083102B5440FFFDAC85000006
+:106F600003E00008000000000000000026E5002803
+:106F700000A03021274301C08F4D03588F47035C89
+:106F80008F4803608F4903648F4A03688F4B020464
+:106F90008F4C0200246404000064102B1040000891
+:106FA0003C0208FF8CC20000AC62000024630004B5
+:106FB0000064102B1440FFFB24C600043C0208FFB1
+:106FC0003442FFFF3C03C0FFAF4D0358AF47035CA3
+:106FD000AF480360AF490364AF4A0368AF4B020494
+:106FE000AF4C02008F8402203463FFFF8F860200C3
+:106FF000008210243442000400C3182434630004C7
+:10700000AF820220AF8302008CA20214AC02008483
+:107010008CA20218AC0200888CA2021CAC02008C6C
+:107020008CA20220AC0200908CA20224AC0200943C
+:107030008CA20228AC0200988CA2022CAC02009C0C
+:107040008CA20230AC0200A08CA20234AC0200A4DC
+:107050008CA20238AC0200A88CA2023CAC0200ACAC
+:107060008CA20240AC0200B08CA20244AC0200B47C
+:107070008CA20248AC0200B88CA2024CAC0200BC4C
+:107080008CA2001CAC0200808CA20018AC0200C0D4
+:107090008CA20020AC0200CC8CA20024AC0200D058
+:1070A0008CA201D0AC0200E08CA201D4AC0200E4BE
+:1070B0008CA201D8AC0200E88CA201DCAC0200EC8E
+:1070C0008CA201E0AC0200F08CA200988CA3009C82
+:1070D000AC0300FC8CA200A88CA300ACAC0300F4B1
+:1070E0008CA200A08CA300A430840004AC0300F8A0
+:1070F0001480000730C200048F8202203C0308FF86
+:107100003463FFFB00431024AF82022030C200042E
+:1071100014400006000000008F8202003C03C0FF04
+:107120003463FFFB00431024AF8202008F4202DC75
+:10713000A34005C524420001AF4202DC8F4202DCBD
+:1071400003E000080000000027BDFFD8AFBF002407
+:10715000AFB000208F4300248F420020106200381F
+:10716000000000008F4300208F4200240062202393
+:1071700004810003000000008F42004000822021B3
+:107180008F4300308F4200240043102B1440000531
+:10719000000000008F4300408F42002410000005D3
+:1071A000006210238F4200308F43002400431023DD
+:1071B0002442FFFF00406021008C102A544000014F
+:1071C000008060218F4A00248F4900408F480024AE
+:1071D0008F4401808F4501848F4600248F4B001C13
+:1071E00024070001AFA7001000084100010018218A
+:1071F000014C50212529FFFF01498024AFB0001424
+:107200008F4700140000102100063100AFA70018BE
+:1072100000A3282100A3382B0082202100872021F1
+:107220008F420108016630210040F809000C390046
+:1072300054400001AF5000248F4300248F420020AF
+:1072400014620018000000008F4200001040000788
+:1072500000000000AF80004C8F82004C1040FFFD0A
+:10726000000000001000000500000000AF80004892
+:107270008F8200481040FFFD000000008F820060F8
+:107280002403FFEF00431024AF8200608F42000010
+:10729000104000030000000010000002AF80004C0E
+:1072A000AF8000488FBF00248FB0002003E00008AB
+:1072B00027BD002803E000080000000027BDFFC034
+:1072C00032C20020AFBF0038AFB30034AFB20030DD
+:1072D000AFB1002C10400004AFB000288F5300283D
+:1072E00010000002000000008F5300208F42003089
+:1072F000105300EB000211008F43001C006280213C
+:107300008E0400008E050004961200088F42009043
+:107310009611000A3246FFFF0046102A104000175F
+:10732000000000008F8200D88F4300980043102394
+:107330002442DCBEAF4200908F4200902842DCBF66
+:1073400010400005000000008F4200908F43014470
+:1073500000431021AF4200908F4200900046102A57
+:1073600010400006000000008F4203482442000144
+:10737000AF420348100000E18F4203488F8200FCB7
+:1073800014400006000000008F4203442442000124
+:10739000AF420344100000D98F420344934205C218
+:1073A0001040000B32C200081040000832220200D8
+:1073B000104000063C0340009602000EAF4300ACB4
+:1073C0000002140010000002AF4200B0AF4000AC59
+:1073D000322200041040007F3222080010400003D7
+:1073E0003247FFFF100000022402002024020004A4
+:1073F000AFA200108F420030AFA200148F420010E5
+:107400003C03000200431025AFA200188F460098ED
+:107410008F4201080040F80900000000104000B74A
+:10742000000000008F42009C8F4300940242102114
+:10743000AF42009CAE03000C8F4200AC104000082D
+:107440003C0340008F42009400431025AFA200206F
+:107450008F42009C8F4300B01000000400431025B1
+:107460008F420094AFA200208F42009CAFA2002464
+:107470008F8200FC8FA300208FA40024AC43000067
+:10748000AC44000424420008AF8200F08F42009C0C
+:107490008F4402708F4502740040182100001021B3
+:1074A00000A3282100A3302B008220210086202168
+:1074B0003223006024020040AF440270AF450274E2
+:1074C000106200172C6200411040000524020020C9
+:1074D00010620008240200011000002600000000D5
+:1074E0002402006010620019240200011000002133
+:1074F000000000008F4202788F43027C2463000169
+:107500002C64000100441021AF420278AF43027C9A
+:107510008F4202788F43027C100000162402000183
+:107520008F4202808F430284246300012C64000197
+:1075300000441021AF420280AF4302848F42028098
+:107540008F4302841000000B240200018F42028846
+:107550008F43028C246300012C640001004410213D
+:10756000AF420288AF43028C8F4202888F43028C65
+:1075700024020001A34205C28F4200983244FFFF5B
+:107580002406FFF88F45013C0044102124420007E7
+:107590000046102424840007AF4200948F420090DC
+:1075A0008F43009400862024004410230065182B8C
+:1075B00014600005AF4200908F4200948F43014455
+:1075C00000431023AF4200948F4200941000002328
+:1075D000AF40009C3247FFFF50E0002232C2002043
+:1075E000144000022402001024020002AFA2001086
+:1075F0008F420030AFA200148F420010AFA20018DB
+:107600008F4600988F4201080040F80900000000F2
+:107610001040003A3245FFFF8F4200988F430090A0
+:107620008F46013C00451021AF4200988F42009CDC
+:107630008F440098A34005C200651823AF43009013
+:10764000004510210086202B14800005AF42009CCD
+:107650008F4200988F43014400431023AF420098AB
+:1076600032C2002010400005000000008F42035885
+:107670002442FFFFAF4203588F4203588F4200302D
+:107680008F430040244200012463FFFF0043102485
+:10769000AF4200308F420030145300180000000049
+:1076A0008F4200001040000700000000AF80004C37
+:1076B0008F82004C1040FFFD00000000100000050C
+:1076C00000000000AF8000488F8200481040FFFD9E
+:1076D000000000008F8200602403FFF700431024A5
+:1076E000AF8200608F4200001040000300000000E5
+:1076F00010000002AF80004CAF8000488FBF003800
+:107700008FB300348FB200308FB1002C8FB00028BF
+:1077100003E0000827BD004003E00008000000006F
+:1077200027BDFFD032C20020AFBF002CAFB200286F
+:10773000AFB1002410400004AFB000208F520028E9
+:1077400010000002000000008F5200208F42003025
+:10775000105200B5000211008F43001C006280210E
+:107760008E0400008E050004961100088F420090E0
+:107770009607000A3226FFFF0046102A1040001725
+:10778000000000008F8200D88F4300980043102330
+:107790002442DC46AF4200908F4200902842DC47F2
+:1077A00010400005000000008F4200908F4301440C
+:1077B00000431021AF4200908F4200900046102AF3
+:1077C00010400006000000008F42034824420001E0
+:1077D000AF420348100000AB8F4203488F8600FC85
+:1077E00010C0000C000000008F8200F42403FFF89A
+:1077F0000043102400461023000218C35860000103
+:10780000246301008F42008C0043102B14400006BB
+:10781000000712C28F42034424420001AF420344D6
+:10782000100000988F420344934305C21060000F7C
+:10783000304600018F4200103448040032C2000874
+:107840001040000830E20200104000063C034000F7
+:107850009602000EAF4300AC0002140010000004BA
+:10786000AF4200B010000002AF4000AC8F480010E3
+:1078700030E20004104000453227FFFF8F4900AC82
+:107880001120000530C200FF144000062402004011
+:10789000100000042402000814400002240200200A
+:1078A00024020004AFA200108F4300301120000416
+:1078B000AFA300148F4200B000621025AFA20014E5
+:1078C0003C02000201021025AFA200188F4600986A
+:1078D0008F4201080040F8090000000010400069D4
+:1078E0003224FFFF8F42008C8F430094244200011A
+:1078F000AF42008C24020001AE03000CA34205C27B
+:107900008F4200982406FFF88F45013C0044102167
+:10791000244200070046102424840007AF4200944C
+:107920008F4200908F43009400862024004410234F
+:107930000065182B14600005AF4200908F42009440
+:107940008F43014400431023AF4200948F430094BF
+:107950008F4201400043102B10400009000000003E
+:107960008F43013C8F4400948F4200908F45013833
+:107970000064182300431023AF420090AF450094E9
+:107980008F4200941000001FAF42009810E0001DCD
+:1079900030C200FF14400002240200102402000242
+:1079A000AFA200108F420030AFA80018AFA20014A1
+:1079B0008F4600988F4201080040F809000000003F
+:1079C000104000303225FFFF8F4200988F44013C69
+:1079D00000451021AF4200988F4200908F430098DD
+:1079E000A34005C2004510230064182B1460000555
+:1079F000AF4200908F4200988F4301440043102310
+:107A0000AF4200988F4200308F4300402442000173
+:107A10002463FFFF00431024AF4200308F42003048
+:107A200014520018000000008F42000010400007B0
+:107A300000000000AF80004C8F82004C1040FFFD22
+:107A4000000000001000000500000000AF800048AA
+:107A50008F8200481040FFFD000000008F82006010
+:107A60002403FFF700431024AF8200608F42000020
+:107A7000104000030000000010000002AF80004C26
+:107A8000AF8000488FBF002C8FB200288FB1002438
+:107A90008FB0002003E0000827BD003003E000089D
+:107AA0000000000027BDFFD83C02000134422EC078
+:107AB000AFBF00208F4300F08F84010802E2102145
+:107AC00054620004246200083C02000134422CC0CD
+:107AD00002E2102100401821AF4300F0AC6000002A
+:107AE0008F4200EC8C660004146200043C0200012A
+:107AF000248200201000000FAF8201088F4300F0A5
+:107B000034422EC002E210215462000424620008B4
+:107B10003C02000134422CC002E210210040182136
+:107B20008C6200040002114000821021AF82010823
+:107B3000AC6000008C85001830A200361040006C4C
+:107B400030A200018C82001C8F4300408F4400341F
+:107B5000244200012463FFFF0043102400862021FB
+:107B6000AF42002C30A2003014400006AF44003475
+:107B70008F4200348C03023C0043102B144000B4AD
+:107B80000000000032C20010104000282407000846
+:107B90008F4401708F4501748F43002C8F48000C77
+:107BA0008F86012024020080AFA20010AFA3001432
+:107BB000AFA800188F42010C0040F80924C6001C31
+:107BC00014400011240200013C010001003708218B
+:107BD000A02240F18F820124AFA200108F820128E1
+:107BE0003C040001248467C4AFA200148F46002C1B
+:107BF0008F8701203C0500090C002B3B34A51100A8
+:107C000010000036000000008F4203008F43002C5C
+:107C100024420001AF4203008F420300240200010E
+:107C2000A34205C110000026AF4300388F44017005
+:107C30008F4501748F43002C8F48000C8F860120E4
+:107C400024020020AFA20010AFA30014AFA80018B8
+:107C50008F42010C0040F80924C6001C144000119A
+:107C6000240200013C01000100370821A02240F05D
+:107C70008F820124AFA200108F8201283C040001F2
+:107C8000248467B8AFA200148F46002C8F87012090
+:107C90003C0500090C002B3B34A509001000000F27
+:107CA000000000008F42030024420001AF420300A5
+:107CB0008F4203008F42002CA34005C1AF42003821
+:107CC0003C01000100370821A02040F13C010001E7
+:107CD00000370821A02040F0AF4000348F42031449
+:107CE00024420001AF420314100000598F420314D4
+:107CF0001040002230A270008C85001C8F420028AA
+:107D000000A2202304810003000000008F420040F5
+:107D1000008220218F4203588F430000AF45002886
+:107D20000044102110600007AF420358AF80004CA0
+:107D30008F82004C1040FFFD000000001000000585
+:107D400000000000AF8000488F8200481040FFFD17
+:107D5000000000008F82006034420008AF820060A3
+:107D60008F420000104000030000000010000038A7
+:107D7000AF80004C10000036AF8000481040002F4C
+:107D800030A210001040000C30A240008C83001C78
+:107D90008F420050006220230482000124840200EC
+:107DA0008F42035C00441021AF42035C8F420368A2
+:107DB0001000001AAF4300501040000C32C2800087
+:107DC0008C83001C8F42007000622023048200011B
+:107DD000248404008F42036400441021AF420364F2
+:107DE0008F4203681000000DAF4300701040000E7A
+:107DF0003C0208008C83001C8F420060006220233C
+:107E000004820001248401008F4203600044102199
+:107E1000AF4203608F420368AF430060004410210B
+:107E2000AF4203683C02080002C210245040000820
+:107E300036940040100000060000000030A201004F
+:107E400010400003000000000C002BD800000000D0
+:107E50008FBF002003E0000827BD002803E00008D2
+:107E60000000000027BDFFA8AFBF0050AFBE004C10
+:107E7000AFB50048AFB30044AFB20040AFB1003C73
+:107E8000AFB000388F91010826220020AF82010890
+:107E90008E3200180000A82132420024104001BA9E
+:107EA0000000F0218E26001C8F43001C00061100EC
+:107EB000006218218C70000C9604000C962D0016A0
+:107EC0009473000A2C8305DD388288702C420001EF
+:107ED00000621825106000150000282132C2004001
+:107EE00010400015240208009603001414620012CA
+:107EF0003402AAAA9603000E146200070000202193
+:107F00009603001024020300146200040080102174
+:107F1000960200122C4400010080102154400006FB
+:107F200024050016100000040000000024020800D0
+:107F3000508200012405000E934205C3144000083E
+:107F400000005821240B000132620180AF4500A8D7
+:107F5000AF5000A010400002AF4600A4A34B05C3E1
+:107F600010A0008502054021910200000000382188
+:107F70003042000F0002508032C200021040001256
+:107F8000010A1821326200021040001032C20001C2
+:107F900001002021948200002484000200E23821A4
+:107FA0000083102B1440FFFB30E2FFFF00071C0290
+:107FB0000062382100071C0230E2FFFF0062382116
+:107FC00000071027A502000A32C200011040006A13
+:107FD0003262000110400068000000008F4200A8DB
+:107FE00010400065000000008F4200A08F4300A8F1
+:107FF00000431021904C0009318900FF392300060D
+:108000000003182B392200110002102B00621824E3
+:108010001060000C3C0500068F4200A43C040001E7
+:10802000248467D4AFA200108F4200A034A546007C
+:10803000012038210C002B3BAFA200141000004E91
+:108040000000000032C20004144000130000282188
+:10805000316200FF1440000400000000950200029D
+:108060001000000D004A28239505000C9502000E13
+:108070009503001000A2282100A3282195030012D7
+:10808000910400099502000200A3282100A42821E0
+:10809000004A102300A2282102002021948200001F
+:1080A0002484000200E238210088102B1440FFFBDA
+:1080B00000071C0230E2FFFF0062382100071C02AB
+:1080C00030E2FFFF0062382101A5282100051C02D3
+:1080D00030A2FFFF0062282100051C0230A2FFFF32
+:1080E0000062282100A728230005140200A22821ED
+:1080F00030A5FFFF50A000013405FFFF316200FFF3
+:1081000014400008318300FF8F4300A08F4200A875
+:1081100000624021910200003042000F00025080B6
+:10812000318300FF2402000614620003010A1021BB
+:10813000100000022444001024440006316200FFB5
+:1081400014400006000000009482000000A22821D4
+:1081500000051C0230A2FFFF00622821934205C3E4
+:10816000104000033262010050400003A48500006B
+:1081700000052827A48500009622000E8F43009C4E
+:108180000062182132A200FF10400007AF43009C9C
+:108190003C02400002021025AFA200208F42009C4A
+:1081A00010000003005E1025AFB000208F42009C3D
+:1081B000AFA2002432620080104000103262010041
+:1081C0008F4200B424430001000210C00057102168
+:1081D000AF4300B48FA300208FA400243C01000112
+:1081E00000220821AC2338E83C01000100220821CC
+:1081F000AC2438EC100000A532C20020104000640E
+:10820000000000008F4200B424430001000210C0AF
+:1082100000571021AF4300B48FA300208FA4002487
+:108220003C01000100220821AC2338E83C01000198
+:1082300000220821AC2438EC8F4200B410400051D9
+:10824000000038213C090001352938E83C08001FAE
+:108250003508FFFF240BFFFF340AFFFF000710C0A3
+:1082600000571021004910218C4300008C44000469
+:10827000AFA30028AFA4002C8F8200FC8FA300289E
+:108280008FA4002CAC430000AC440004244200083E
+:10829000AF8200F08F42008C2442FFFFAF42008C7F
+:1082A00097A2002E8F4402708F450274004018215F
+:1082B0000000102100A3282100A3302B00822021E0
+:1082C00000862021AF440270AF4502748FA20028BF
+:1082D0000048102490430000306300011460000B3C
+:1082E000004020218F4202788F43027C24630001EA
+:1082F0002C64000100441021AF420278AF43027C9D
+:108300008F4202781000001A8F43027C8C8200009A
+:10831000144B000E0000000094820004144A000B6D
+:10832000000000008F4202888F43028C246300010A
+:108330002C64000100441021AF420288AF43028C3C
+:108340008F4202881000000A8F43028C8F42028005
+:108350008F430284246300012C6400010044102137
+:10836000AF420280AF4302848F4202808F43028477
+:108370008F4200B424E7000100E2102B1440FFB844
+:10838000000710C0A34005C31000003FAF4000B479
+:108390008F8200FC8FA300208FA40024AC43000038
+:1083A000AC44000424420008AF8200F08F42009CDD
+:1083B0008F46008C8F4402708F4502740040182154
+:1083C0000000102124C6FFFFAF46008C00A3282127
+:1083D00000A3302B0082202100862021AF440270B0
+:1083E000AF45027492020000304200011440000CBC
+:1083F0002402FFFF8F4202788F43027C2463000136
+:108400002C64000100441021AF420278AF43027C8B
+:108410008F4202788F43027C1000001C32C2002081
+:108420008E0300001462000F3402FFFF9603000465
+:108430001462000C000000008F4202888F43028CFF
+:10844000246300012C64000100441021AF42028823
+:10845000AF43028C8F4202888F43028C1000000BC6
+:1084600032C200208F4202808F43028424630001C5
+:108470002C64000100441021AF420280AF4302840B
+:108480008F4202808F43028432C2002010400005D8
+:10849000AF40009C8F4203582442FFFFAF42035875
+:1084A0008F4203588E22001C8F430040244200015B
+:1084B0002463FFFF00431024AF42002C32420060CF
+:1084C0001440000832C200108F42003424420001E0
+:1084D000AF4200348C03023C0043102B14400102D5
+:1084E00032C2001010400018240700088F440170A9
+:1084F0008F4501748F43002C8F48000C8F8601201C
+:1085000024020080AFA20010AFA30014AFA800188F
+:108510008F42010C0040F80924C6001C104000479F
+:10852000240200018F4203008F43002C24420001EB
+:10853000AF4203008F42030024020001A34205C1A1
+:108540001000007CAF4300388F4401708F450174E8
+:108550008F43002C8F48000C8F86012024020020BE
+:10856000AFA20010AFA30014AFA800188F42010CF7
+:108570000040F80924C6001C1040005724020001E6
+:10858000100000650000000032420012104000752B
+:10859000324200019622000E8F43009C0062182197
+:1085A00032C2002010400005AF43009C8F420358A8
+:1085B0002442FFFFAF4203588F4203588E22001C13
+:1085C0008F430040244200012463FFFF0043102436
+:1085D000AF42002C324200101440000832C200109A
+:1085E0008F42003424420001AF4200348C03023C2D
+:1085F0000043102B144000BC32C200101040002871
+:10860000240700088F4401708F4501748F43002CAC
+:108610008F48000C8F86012024020080AFA200103A
+:10862000AFA30014AFA800188F42010C0040F80956
+:1086300024C6001C14400011240200013C0100016A
+:1086400000370821A02240F18F820124AFA2001040
+:108650008F8201283C040001248467C4AFA2001467
+:108660008F46002C8F8701203C0500090C002B3B16
+:1086700034A5110010000036000000008F420300F6
+:108680008F43002C24420001AF4203008F420300BD
+:1086900024020001A34205C110000026AF430038A8
+:1086A0008F4401708F4501748F43002C8F48000C5C
+:1086B0008F86012024020020AFA20010AFA3001477
+:1086C000AFA800188F42010C0040F80924C6001C16
+:1086D00014400011240200013C0100010037082170
+:1086E000A02240F08F820124AFA200108F820128C7
+:1086F0003C040001248467B8AFA200148F46002C0C
+:108700008F8701203C0500090C002B3B34A5090094
+:108710001000000F000000008F42030024420001FF
+:10872000AF4203008F4203008F42002CA34005C1DB
+:10873000AF4200383C01000100370821A02040F181
+:108740003C01000100370821A02040F0AF40003478
+:108750008F42031424420001AF4203141000006250
+:108760008F42031410400022324270008E25001CFC
+:108770008F42002800A22023048100030000000093
+:108780008F420040008220218F4203588F43000017
+:10879000AF4500280044102110600007AF42035885
+:1087A000AF80004C8F82004C1040FFFD00000000A5
+:1087B0001000000500000000AF8000488F820048D4
+:1087C0001040FFFD000000008F820060344200086E
+:1087D000AF8200608F4200001040000300000000E4
+:1087E00010000041AF80004C1000003FAF800048F7
+:1087F0001040002F324210001040000C3242400066
+:108800008E23001C8F42005000622023048200014E
+:10881000248402008F42035C00441021AF42035CB9
+:108820008F4203681000001AAF4300501040000C44
+:1088300032C280008E23001C8F4200700062202311
+:1088400004820001248404008F4203640044102148
+:10885000AF4203648F4203681000000DAF43007005
+:108860001040000E3C0208008E23001C8F42006066
+:108870000062202304820001248401008F420360EF
+:1088800000441021AF4203608F420368AF43006091
+:1088900000441021AF4203683C02080002C21024C9
+:1088A00050400011369400401000000F00000000FE
+:1088B0003242004810400007241500018E22001C9F
+:1088C0003C03FFFF0043F0243042FFFF1000FD7522
+:1088D000AE22001C324201001040000300000000E4
+:1088E0000C002BD8000000008FBF00508FBE004C42
+:1088F0008FB500488FB300448FB200408FB1003C69
+:108900008FB0003803E0000827BD005803E00008DE
+:108910000000000000000000000000008F8300E461
+:108920008F8200E02404FFF8004410240062102627
+:108930000002102B0002102303E000080062102444
+:1089400003E000080000000027BDFFE0AFBF001CEF
+:10895000AFB000188F8600C48F8400E08F8500E4DC
+:108960002402FFF80082182410A3000927623FF8B0
+:1089700014A2000224A200082762300000408021D7
+:1089800016030005308200041040000400C02021BE
+:1089900010000022000010218E0400008F42011CF4
+:1089A00014A20003000000008F420120AF42011416
+:1089B0008CA300008F420148008318230043102B32
+:1089C00010400003000000008F420148006218219F
+:1089D00094A20006244200500062102B1440000FA5
+:1089E00000A01021AFA40010AFA300148CA60000BB
+:1089F0008CA700043C0400010C002B3B24846894E9
+:108A00008F42020C24420001AF42020C8F42020C42
+:108A100000001021AF9000E8AF9000E48FBF001C71
+:108A20008FB0001803E0000827BD002003E0000815
+:108A3000000000008F8400E08F8800C48F8300E86E
+:108A40002402FFF80082382400E320232C82100047
+:108A50005040000124841000000420C2008018212E
+:108A60008F4402588F45025C0000102100A328218A
+:108A700000A3302B0082202100862021AF44025821
+:108A8000AF45025C8F8300C88F4201480103202359
+:108A90000082102B14400004008018218F420148EE
+:108AA00000822021008018218F4402508F450254FB
+:108AB0000000102100A3282100A3302B00822021D8
+:108AC00000862021AF440250AF450254AF8800C851
+:108AD000AF8700E4AF8700E803E000080000000073
+:108AE00027BDFF30240A0001AFBF00C8AFBE00C4DD
+:108AF000AFB500C0AFB300BCAFB200B8AFB100B407
+:108B0000AFB000B0A3A00097AFA00044AFAA005C34
+:108B1000934205C4A7A0008E1040000AA7A00086BB
+:108B20008F4B00C4AFAB00648F4A00C0AFAA006C8B
+:108B30008F4B00CCAFAB00748F4A00C810000129E6
+:108B4000AFAA007C8F4201140040F8090000000029
+:108B50000040302110C0034F000000008CC2000014
+:108B60008CC30004AFA20020AFA300248FAB00246D
+:108B70008FAA00203162FFFF2442FFFCAFA2006CED
+:108B80003C02000602C21024AFAB007C144000156A
+:108B9000AFAA006491420000304200011040001171
+:108BA0002402FFFF8D430000146200043402FFFF23
+:108BB000954300041062000B000000000C0024BB71
+:108BC0008FA40064304200FF144000060000000043
+:108BD0008F4201180040F809000000001000032D2A
+:108BE000000000008FA200243C03FFBF3463FFFF9E
+:108BF000004310243C03FFFF0043182414600003CB
+:108C0000AFA2002410000040000018213C020080A8
+:108C10000062102410400007000000008F42038C07
+:108C200024420001AF42038C8F42038C10000036B7
+:108C3000240300018F42021024420001AF420210BF
+:108C40008F4202103C020001006210241040000616
+:108C50003C0200028F4201C424420001AF4201C421
+:108C60008F4201C43C020002006210241040000642
+:108C70003C0200048F42037C24420001AF42037C8B
+:108C80008F42037C3C020004006210241040000666
+:108C90003C0200088F42038024420001AF4203805F
+:108CA0008F4203803C02000800621024104000063E
+:108CB0003C0200108F42038424420001AF4203842F
+:108CC0008F4203843C020010006210241040000612
+:108CD0003C0200208F4201C024420001AF4201C08B
+:108CE0008F4201C03C0200200062102410400006A8
+:108CF000240300018F42038824420001AF4203880D
+:108D00008F420388240300018C0202608FAB006C49
+:108D1000004B102B10400014307000FF8F4201E810
+:108D200024420001AF4201E88F4201E88FAA007C93
+:108D30008F8200E0354A0100AFAA007CAFA200108C
+:108D40008F8200E4241000013C040001248468A008
+:108D5000AFA200148FA600208FA700243C050007B7
+:108D60000C002B3B34A50800120000103C020080D0
+:108D700002C210241440000E32C204008FAB007CEB
+:108D80003C020080344201000162102410400005C2
+:108D9000000000008F42020C24420001AF42020C8E
+:108DA0008F42020C100002B08FA3006C32C204008C
+:108DB00010400015340281008FAA00649543000C16
+:108DC000146200123C020100240B0200A7AB008ECB
+:108DD0009542000E8D4300088D4400048D4500002F
+:108DE0008FAA006C8FAB0064254AFFFCAFAA006C11
+:108DF000A7A20086AD63000CAD640008AD65000459
+:108E0000256B0004AFAB00643C02010002C21024D9
+:108E100010400004000000008FAA006C254A0004E6
+:108E2000AFAA006C8F4200BC5040000AAFA0007493
+:108E30008FAB006C004B102B50400006AFA00074AD
+:108E40008F4200BC01621023AFA200748F4A00BCA5
+:108E5000AFAA006C8F4200808FAB006C004B102BD0
+:108E60001040005632C280001040005E240A000309
+:108E700032C210001040005BAFAA005C1000005826
+:108E8000240B00048F4203502403FFBF0283A0245D
+:108E900024420001AF4203501000024F8F420350A2
+:108EA00002C2B0252402FFBF0282A0248F830128C2
+:108EB0003C040001248468D026620001AFA20014A3
+:108EC000AFA300108F8601208F8701243C05000787
+:108ED0000C002B3B34A522501000023F0000000084
+:108EE00002C2B0252402FFBF0282A0248F83012882
+:108EF0003C040001248468D024020002AFA20014C4
+:108F0000AFA300108F8601208F8701243C05000746
+:108F10000C002B3B34A524501000022F0000000051
+:108F20008EA200008EA300043C040001248468E8A3
+:108F3000AFB00010AFBE00148EA7001834A52800F3
+:108F40000C002B3B006030211000022300000000C9
+:108F5000A6B1000A8F8201243C040001248468F039
+:108F6000AFBE0014AFA200108F4600448F870120CF
+:108F70003C0500070C002B3B34A530001000021606
+:108F800000000000A6B1000AA6B2000E8F820124E4
+:108F90003C040001248468FCAFBE0014AFA20010A2
+:108FA0008F4600448F8701203C0500070C002B3BB7
+:108FB00034A5320010000208000000008F42008437
+:108FC0008FAA006C004A102B144000073C020001DD
+:108FD00002C210241040000400000000240B000214
+:108FE000AFAB005C8FAA006C1140021B27AB0020C6
+:108FF000AFAB00A43C0A001F354AFFFFAFAA009C9C
+:109000008FAB005C240A0001556A0021240A00028B
+:109010008F4300548F4200501062000B274B0054C6
+:109020008F5E00543403ECC0AFAB004C27C200018C
+:10903000304201FFAFA20054001E11400043102136
+:109040001000006B02E2A8218F4200448FAA006C3E
+:109050003C040001248468ACAFAA0014AFA2001045
+:109060008F4600548F4700503C0500070C002B3BF7
+:1090700034A513008F4303502402FFBF0282A024B3
+:1090800024630001AF430350100001D38F4203500B
+:10909000156A001D000000008F4300748F420070AD
+:1090A0001062000A274B00748F5E0074AFAB004C57
+:1090B00027C20001304203FFAFA20054001E11403E
+:1090C00024426CC01000004A02E2A8218F420044F2
+:1090D0008FAA006C3C040001248468B83C0500079A
+:1090E000AFAA0014AFA200108F4600748F47007023
+:1090F00034A51500240B00010C002B3BAFAB005C2A
+:109100001000FFC3000000008F4300648F42006026
+:109110001062001A274A00648F5E00648FAB005C07
+:10912000AFAA004C27C20001304200FFAFA200549A
+:10913000240200041562000E001E1140001E118062
+:1091400024420CC002E21021AFA200449442002A43
+:109150008FAA00448FAB006C004B102B10400024F2
+:1091600025550020240A000110000021A3AA009721
+:1091700024424CC01000001E02E2A8218F4200448D
+:109180008FAB006C3C040001248468C4AFAB0014B6
+:10919000AFA200108F4600648F4700603C050007B7
+:1091A0000C002B3B34A518003C02000802C210241E
+:1091B0001440FF34000000008F420370240A0001B5
+:1091C000AFAA005C24420001AF4203701000FF9080
+:1091D0008F42037027A3003600131040006218214D
+:1091E000946200000044102110000020A4620000DE
+:1091F0008FAB0064AEAB001893A2009710400072D2
+:10920000000098218FAA00448FA4006C8FA300A4B3
+:1092100025420020AFA2002825420008AFA200305E
+:1092200025420010AFAA002CAFA200349542002ABC
+:10923000A7A2003895420018A7A2003A9542001A4A
+:10924000A7A2003C9542001CA7A2003E9462001811
+:1092500024630002008220231880FFDE26730001B1
+:109260002E6200041440FFF9000000008F4200FC51
+:109270002665000100A2102A1440002B24030001DF
+:109280008F83012C10600023000000008F820124D6
+:109290000043102300022143588000012484004031
+:1092A0008F820128004310230002194358600001F7
+:1092B000246300400064102A544000010060202113
+:1092C000AF4400FC8F4200FC00A2102A10400011A5
+:1092D0002403000110000015306200FF8FAB006412
+:1092E00096070018AFAB00108E2200083C04000166
+:1092F000248468DC8C4300048C42000034A52400E4
+:10930000024030210C002B3BAFA300141000002BB7
+:10931000000000008F4203340000182124420001A5
+:10932000AF4203348F420334306200FF5040FEDC12
+:109330003C02080012600021000090218FB100A4BF
+:10934000022080218E220008960700188FA6006454
+:109350008C4400008C450004240A0001AFAA0010D0
+:10936000AFBE00148F420008AFA200188F42010C5C
+:109370000040F809000000001040FFD83C0500073D
+:10938000960200188FAB00648FAA009C01625821DE
+:10939000014B102B10400004AFAB00648F4201481A
+:1093A00001625823AFAB0064261000022652000170
+:1093B0000253102B1440FFE3263100048FB0006CE1
+:1093C0001000003697B100388F4200FC24050002DF
+:1093D00000A2102A1440001B240300018F83012CDB
+:1093E00010600013000000008F820124004310234E
+:1093F0000002214358800001248400408F8201280C
+:109400000043102300021943586000012463004008
+:109410000064102A5440000100602021AF4400FC89
+:109420008F4200FC00A2102A144000062403000111
+:109430008F4203340000182124420001AF4203345C
+:109440008F420334306200FF1040FEA53C0208004A
+:1094500096B1000A8FB0006C3223FFFF0070102B12
+:1094600054400001006080218EA400008EA50004FD
+:10947000240B0001AFAB0010AFBE00148F420008F8
+:109480008FA60064AFA200188F42010C0040F809BB
+:10949000020038211040FEA23C05000796A3000EF2
+:1094A00097AA008E1140000700609021934205C4E6
+:1094B000144000040000000097AB0086006A1825E5
+:1094C000A6AB00168FAA007C3C02FFFF01421024CD
+:1094D00010400003000A140234630400A6A2001422
+:1094E0008FAB006C560B0072A6A3000E3462000412
+:1094F000A6A2000E8FAA0074016A1021A6A2000A7B
+:109500008F4300448F4401A08F4501A434028000A2
+:10951000AFA200108F42004402A030212407002097
+:10952000AFA200148F42000C0003194000604821D4
+:10953000AFA200188F42010C0000402100A9282191
+:1095400000A9182B008820210040F8090083202161
+:109550005040FE7FA6B2000E8F420368AFA0006CA1
+:10956000A34005C42442FFFFAF4203688FAB005CF9
+:10957000240A00018F420368156A0006240A0002CB
+:109580008F42035C2442FFFFAF42035C1000000CDB
+:109590008F42035C156A0006000000008F420364DE
+:1095A0002442FFFFAF420364100000058F420364B2
+:1095B0008F4203602442FFFFAF4203608F4203608B
+:1095C0008FAA00548FAB004CAD6A00008F4200445C
+:1095D0008F4400888F430078244200010044102407
+:1095E00024630001AF420044AF4300788C02024084
+:1095F0000062182B14600075240700088F4401686E
+:109600008F45016C8F4300448F48000C8F860120EA
+:1096100024020040AFA20010AFA30014AFA80018AE
+:109620008F42010C0040F80924C6001C14400011B0
+:10963000240B00013C01000100370821A02B40F25F
+:109640008F820124AFA200108F8201283C04000108
+:109650002484688CAFA200148F4600448F870120B9
+:109660003C0500090C002B3B34A513001000000B37
+:10967000000000008F42030424420001AF420304B3
+:109680008F4203048F420044AF42007C3C01000142
+:1096900000370821A02040F2AF4000788F42031825
+:1096A00024420001AF420318100000488F42031803
+:1096B000A6B0000A8F4300448F4401A08F4501A447
+:1096C00034028000AFA200108F42004402A030217B
+:1096D00024070020AFA200148F42000C00031940A1
+:1096E00000604821AFA200188F42010C0000402109
+:1096F00000A9282100A9182B008820210040F80982
+:10970000008320211040FE1F240A0001A34A05C443
+:109710008FAB006C8FAA006401705823AFAB006C54
+:109720008FAB009C01505021016A102B10400004A7
+:10973000AFAA00648F42014801425023AFAA0064DF
+:109740008F4203682442FFFFAF4203688FAA005C88
+:10975000240B00018F420368154B0006240B000206
+:109760008F42035C2442FFFFAF42035C1000000CF9
+:109770008F42035C114B0006000000008F42036023
+:109780002442FFFFAF420360100000058F420360D8
+:109790008F4203642442FFFFAF4203648F4203649D
+:1097A0008FAB00548FAA004CAD4B00008F42004499
+:1097B0008F4400888F430078244200010044102425
+:1097C00024630001AF420044AF4300788FAA006CCD
+:1097D0001540FE0B000000008FAB006C1160001EF6
+:1097E00000000000934205C4104000090000000082
+:1097F0008FAA0064AF4A00C4AF4B00C08FAB007C9F
+:10980000AF4B00C88FAA00741000000EAF4A00CC06
+:1098100097AB008E1160000B340381008FA20020F3
+:109820008C46000CA443000C97AA00868C440004CC
+:109830008C450008A44A000EAC440000AC4500046E
+:10984000AC4600088F42034C24420001AF42034C57
+:10985000100000108F42034C8FAB007C3164FFFF7F
+:109860002484FFFC008018218F4402508F4502544D
+:109870008F4601180000102100A3282100A3382BD7
+:109880000082202100872021AF44025000C0F80947
+:10989000AF4502548FBF00C88FBE00C48FB500C053
+:1098A0008FB300BC8FB200B88FB100B48FB000B0DE
+:1098B00003E0000827BD00D003E00008000000001E
+:1098C00027BDFF38240B0001AFBF00C0AFBE00BCF6
+:1098D000AFB500B8AFB300B4AFB200B0AFB100AC39
+:1098E000AFB000A8A3A00087AFA00044AFAB005C5E
+:1098F000934205C4A7A0007610400007A7A0007EF1
+:109900008F4C00C0AFAC00648F4B00C88F5E00C4AA
+:1099100010000130AFAB006C8F4201140040F80919
+:10992000000000000040302110C002A10000000033
+:109930008CC200008CC30004AFA20020AFA300249F
+:109940008FAC00248FBE00203182FFFF2442FFFC39
+:10995000AFA200643C02000602C2102414400015AD
+:10996000AFAC006C93C20000304200011040001107
+:109970002402FFFF8FC30000146200043402FFFFC3
+:1099800097C300041062000B000000000C0024BB11
+:1099900003C02021304200FF1440000600000000F8
+:1099A0008F4201180040F8090000000010000280FA
+:1099B000000000008FA200243C03FFBF3463FFFFC0
+:1099C000004310243C03FFFF0043182414600003ED
+:1099D000AFA2002410000040000080213C02008063
+:1099E0000062102410400007000000008F42038C2A
+:1099F00024420001AF42038C8F42038C10000036DA
+:109A0000241000018F42021024420001AF420210D4
+:109A10008F4202103C020001006210241040000638
+:109A20003C0200028F4201C424420001AF4201C443
+:109A30008F4201C43C020002006210241040000664
+:109A40003C0200048F42037C24420001AF42037CAD
+:109A50008F42037C3C020004006210241040000688
+:109A60003C0200088F42038024420001AF42038081
+:109A70008F4203803C020008006210241040000660
+:109A80003C0200108F42038424420001AF42038451
+:109A90008F4203843C020010006210241040000634
+:109AA0003C0200208F4201C024420001AF4201C0AD
+:109AB0008F4201C03C0200200062102410400006CA
+:109AC000241000018F42038824420001AF42038822
+:109AD0008F420388241000018C0202608FAB006467
+:109AE000004B102B10400015320200FF8F4201E89E
+:109AF00024420001AF4201E88F4201E88FAC006CC4
+:109B00008F8200E0358C0100AFAC006CAFA200107A
+:109B10008F8200E4241000013C040001248468A02A
+:109B2000AFA200148FA600208FA700243C050007D9
+:109B30000C002B3B34A53600320200FF1040001011
+:109B40003C02008002C210241440000E32C2040005
+:109B50008FAB006C3C020080344201000162102493
+:109B600010400005000000008F42020C244200015A
+:109B7000AF42020C8F42020C100002028FA300645D
+:109B800032C20400104000123402810097C3000C5E
+:109B90001462000F00000000240C0200A7AC007645
+:109BA00097C2000E8FC300088FC400048FAB0064FF
+:109BB0008FC50000256BFFFCAFAB0064A7A2007E41
+:109BC000AFC3000CAFC40008AFC5000427DE00041B
+:109BD0008FA70064320200FF144000343C020100F1
+:109BE00097C4000C2C8305DD388288702C4200015C
+:109BF00000621825106000150000282132C20800FC
+:109C0000104000152402080097C3001414620012CB
+:109C10003402AAAA97C3000E146200070000202194
+:109C200097C3001024020300146200040080102176
+:109C300097C200122C4400010080102154400006FD
+:109C40002405001610000004000000002402080093
+:109C5000508200012405000E10A0001303C520212E
+:109C6000248300093C02001F3442FFFF0043102BF5
+:109C700010400003000000008F42014800621823DA
+:109C800090620000384300062C6300013842001146
+:109C90002C42000100621825106000043C02010003
+:109CA00094820002004538213C02010002C21024C7
+:109CB0005040000EAFA700648FAC006410EC0008A9
+:109CC0003C0500073C040001248469088FA6006459
+:109CD00034A54000AFA000100C002B3BAFA0001437
+:109CE0008FAB0064256B0004AFAB00648F42008033
+:109CF0008FAC0064004C102B1040002C32C280004E
+:109D000010400034240B000332C210001040003118
+:109D1000AFAB005C1000002E240C00048F420350F7
+:109D20002403FFBF0283A02424420001AF4203505A
+:109D3000100001738F4203503C02080002C2B0259C
+:109D40002402FFBF0282A0248F8301283C0400016B
+:109D5000248468D026620001AFA20014AFA30010D3
+:109D60008F8601208F8701243C0500070C002B3BC8
+:109D700034A5530010000162000000008EA2000014
+:109D80008EA300043C040001248468E8AFB00010F6
+:109D9000AFB100148EA7001834A559000C002B3B5E
+:109DA0000060302110000156000000008F42008446
+:109DB0008FAB0064004B102B144000073C020001E5
+:109DC00002C210241040000400000000240C000215
+:109DD000AFAC005C8FAB00641160016627AC002063
+:109DE000AFAC008C8FAB005C240C0001556C0021E3
+:109DF000240C00028F4300548F4200501062000B6D
+:109E0000274B00548F5100543403ECC0AFAB004CCF
+:109E100026220001304201FFAFA200540011114080
+:109E2000004310211000006B02E2A8218F42004481
+:109E30008FAC00643C040001248468ACAFAC001417
+:109E4000AFA200108F4600548F4700503C0500071A
+:109E50000C002B3B34A543008F4303502402FFBF6B
+:109E60000282A02424630001AF43035010000124A8
+:109E70008F420350156C001D000000008F430074DA
+:109E80008F4200701062000A274B00748F510074DB
+:109E9000AFAB004C26220001304203FFAFA20054BA
+:109EA0000011114024426CC01000004A02E2A821B7
+:109EB0008F4200448FAC00643C040001248468B8E5
+:109EC0003C050007AFAC0014AFA200108F46007431
+:109ED0008F47007034A54500240B00010C002B3B7C
+:109EE000AFAB005C1000FFC3000000008F430064B4
+:109EF0008F4200601062001A274C00648F5100648A
+:109F00008FAB005CAFAC004C26220001304200FF5A
+:109F1000AFA20054240200041562000E001111408B
+:109F20000011118024420CC002E21021AFA20044B3
+:109F30009442002A8FAC00448FAB0064004B102B7E
+:109F40001040002425950020240C00011000002161
+:109F5000A3AC008724424CC01000001E02E2A821DE
+:109F60008F4200448FAB00643C040001248468C429
+:109F7000AFAB0014AFA200108F4600648F470060A3
+:109F80003C0500070C002B3B34A548003C020008B0
+:109F900002C210241440FF61000000008F420370D1
+:109FA000240C0001AFAC005C24420001AF420370FE
+:109FB0001000FF908F42037027A30036001310405B
+:109FC0000062182194620000004410211000001F5C
+:109FD000A4620000AEBE001893A200871040008467
+:109FE000000098218FAB00448FA400648FA3008CE5
+:109FF00025620020AFA2002825620008AFA2003031
+:10A0000025620010AFAB002CAFA200349562002A8D
+:10A01000A7A2003895620018A7A2003A9562001A1C
+:10A02000A7A2003C9562001CA7A2003E9462001803
+:10A0300024630002008220231880FFDF26730001C2
+:10A040002E6200041440FFF9000000008F4200FC63
+:10A050000262102A14400030240300018F83012C77
+:10A0600010600028000000008F82012400431023AC
+:10A070000002214358800001248400408F8201287F
+:10A08000004310230002194358600001246300407C
+:10A090000064102A5440000100602021AF4400FCFD
+:10A0A0008F4200FC0262102A1040001624030001B7
+:10A0B0001000001A306200FF8FAC008C00101040BE
+:10A0C000004C10219447001800101080004C102103
+:10A0D000AFBE00108C4200083C040001248468DC00
+:10A0E0003C0500078C4300048C42000034A5550059
+:10A0F000020030210C002B3BAFA3001410000039EC
+:10A10000000000008F4203340000182124420001A7
+:10A11000AF4203348F420334306200FF1040FF0629
+:10A12000000080218F4300082402FBFF1260002DF5
+:10A13000006250243C0B4000022B40258FB1008C64
+:10A140002669FFFF022090218E4200089627001802
+:10A150008C4400008C45000456090004240B0001C7
+:10A16000240C000210000002AFAC0010AFAB0010D6
+:10A1700016000004AFA800148F420008100000026F
+:10A18000AFA20018AFAA00188F42010C03C0302103
+:10A19000AFA80098AFA9009C0040F809AFAA00A0A2
+:10A1A0008FA800988FA9009C8FAA00A01040FFC222
+:10A1B0003C02001F962300183442FFFF03C3F02126
+:10A1C000005E102B10400003263100028F42014830
+:10A1D00003C2F023261000010213102B1440FFDAF3
+:10A1E000265200048FB000641000001A0000000026
+:10A1F00096A3000A8FB000640070102B5440000139
+:10A20000006080218EA400008EA500048FAB005C4E
+:10A21000240C0002AFAC0010934305C4000B1700E0
+:10A2200010600003022230253C02080000C23025E5
+:10A23000AFA600148F420008AFA200188F42010C95
+:10A2400003C030210040F809020038211040FECB45
+:10A250003C05000797AC00761180000796A3000E1E
+:10A26000934205C4144000040000000097AB007E38
+:10A27000006C1825A6AB00168FAC006C3C02FFFFEB
+:10A280000182102410400003000C14023463040007
+:10A29000A6A20014A6B0000A8FAB0064560B0006FD
+:10A2A00003D0F02134620004AFA00064A6A2000E27
+:10A2B0001000000DA34005C48FAC00643C02001FD9
+:10A2C0003442FFFF005E102B01906023AFAC0064AE
+:10A2D000A6A3000E240B000110400003A34B05C4ED
+:10A2E0008F42014803C2F0238FAB00548FAC004C67
+:10A2F000AD8B00008FAC00641580FEBA000000003A
+:10A300008FAB00641160001B00000000934205C485
+:10A310001040000600000000AF5E00C4AF4B00C05C
+:10A320008FAC006C1000000EAF4C00C897AB0076ED
+:10A330001160000B340381008FA200208C46000CBA
+:10A34000A443000C97AC007E8C4400048C450008AC
+:10A35000A44C000EAC440000AC450004AC46000820
+:10A360008F42034C24420001AF42034C1000001006
+:10A370008F42034C8FAB006C3164FFFF2484FFFCE1
+:10A38000008018218F4402508F4502548F460118D7
+:10A390000000102100A3282100A3382B00822021D7
+:10A3A00000872021AF44025000C0F809AF45025495
+:10A3B0008FBF00C08FBE00BC8FB500B88FB300B494
+:10A3C0008FB200B08FB100AC8FB000A803E00008DE
+:10A3D00027BD00C803E000080000000027BDFFD82B
+:10A3E000AFBF0024AFB000208F43004C8F42004825
+:10A3F00010620034000000008F4300488F42004C80
+:10A400000062202304820001248402008F43005450
+:10A410008F42004C0043102B144000042402020021
+:10A420008F43004C10000005004310238F4200545E
+:10A430008F43004C004310232442FFFF0040502173
+:10A44000008A102A54400001008050218F49004C9E
+:10A450008F48004C8F4401888F45018C8F46004CFB
+:10A4600024071000AFA70010000841400100182188
+:10A47000012A4821313001FFAFB000148F4700148A
+:10A480000000102100063140AFA7001800A32821CA
+:10A4900000A3382B00822021008720213402ECC049
+:10A4A00000C230218F42010802E630210040F80945
+:10A4B000000A394054400001AF50004C8F43004C1B
+:10A4C0008F42004814620018000000008F42000014
+:10A4D0001040000700000000AF80004C8F82004C4D
+:10A4E0001040FFFD0000000010000005000000000B
+:10A4F000AF8000488F8200481040FFFD0000000040
+:10A500008F8200602403FDFF00431024AF820060AF
+:10A510008F42000010400003000000001000000205
+:10A52000AF80004CAF8000488FBF00248FB0002068
+:10A5300003E0000827BD002803E000080000000039
+:10A5400027BDFFD8AFBF0024AFB000208F43005C11
+:10A550008F42005810620049000000008F430058ED
+:10A560008F42005C006220230482000124840100E9
+:10A570008F4300648F42005C0043102B14400004A2
+:10A58000240201008F43005C1000000500431023EB
+:10A590008F4200648F43005C004310232442FFFF7E
+:10A5A000004038210087102A5440000100803821E3
+:10A5B0008F42005C00471021305000FF32C2100073
+:10A5C00010400015240820008F49005C8F44019042
+:10A5D0008F4501948F46005C00073980AFA80010BA
+:10A5E000AFB000148F4800140009498001201821E1
+:10A5F0000000102100A3282100A3482B0082202165
+:10A600000089202100063180AFA800188F42010880
+:10A610001000001424C60CC08F49005C8F440190C8
+:10A620008F4501948F46005C00073940AFA80010A9
+:10A63000AFB000148F4800140009494001201821D0
+:10A640000000102100A3282100A3482B0082202114
+:10A650000089202100063140AFA800188F42010870
+:10A6600024C64CC00040F80902E6302154400001E5
+:10A67000AF50005C8F43005C8F420058146200189A
+:10A68000000000008F4200001040000700000000A2
+:10A69000AF80004C8F82004C1040FFFD0000000096
+:10A6A0001000000500000000AF8000488F820048C5
+:10A6B0001040FFFD000000008F8200602403FEFFB9
+:10A6C00000431024AF8200608F420000104000035E
+:10A6D0000000000010000002AF80004CAF80004876
+:10A6E0008FBF00248FB0002003E0000827BD0028A2
+:10A6F00003E000080000000027BDFFD8AFBF002422
+:10A70000AFB000208F43006C8F42006810620033AE
+:10A71000000000008F4300688F42006C006220231D
+:10A7200004820001248404008F4300748F42006C73
+:10A730000043102B14400004240204008F43006CDB
+:10A7400010000005004310238F4200748F43006CFB
+:10A75000004310232442FFFF00405021008A102AAA
+:10A7600054400001008050218F49006C8F48006CDC
+:10A770008F4401988F45019C8F46006C2407400050
+:10A78000AFA700100008414001001821012A48210C
+:10A79000313003FFAFB000148F47001400001021C8
+:10A7A0000006314024C66CC0AFA7001800A32821C2
+:10A7B00000A3382B00822021008720218F4201082E
+:10A7C00002E630210040F809000A394054400001F7
+:10A7D000AF50006C8F43006C8F4200681462001809
+:10A7E000000000008F420000104000070000000041
+:10A7F000AF80004C8F82004C1040FFFD0000000035
+:10A800001000000500000000AF8000488F82004863
+:10A810001040FFFD000000008F8200602403F7FF5E
+:10A8200000431024AF8200608F42000010400003FC
+:10A830000000000010000002AF80004CAF80004814
+:10A840008FBF00248FB0002003E0000827BD002840
+:10A8500003E00008000000008F4200FC3C03000100
+:10A860008F4400F8346330C824420001AF4200FC3A
+:10A870008F85012802E310215482000424820008FD
+:10A880003C02000134422EC802E21021004018218F
+:10A89000AF4300F8AC6000008F4200F41462000483
+:10A8A0003C02000124A200201000000FAF8201280A
+:10A8B0008F4300F8344230C802E210215462000491
+:10A8C000246200083C02000134422EC802E210213A
+:10A8D000004018218C6200040002114000A21021E7
+:10A8E000AF820128AC6000008CA3001830620070B9
+:10A8F0001040002D30620020104000043C02001087
+:10A9000002C210241040000D000000003062004020
+:10A91000104000043C02002002C210241040000736
+:10A9200000000000306200101040001F3C02004098
+:10A9300002C210241440001C000000008F8200405E
+:10A940003042000114400008000020218C03010463
+:10A950002402000150620005240400018C020264FC
+:10A960001040000300801021240400010080102109
+:10A9700010400006000000008F42030C244200013A
+:10A98000AF42030C100000088F42030C8F8200447A
+:10A9900034420004AF8200448F4203082442000185
+:10A9A000AF4203088F42030803E0000800000000E4
+:10A9B00003E000080000000027BDFF98AFBF006063
+:10A9C000AFBE005CAFB50058AFB30054AFB200509B
+:10A9D000AFB1004CAFB000488F4200FC24420001F0
+:10A9E000AF4200FC8F88012825020020AF82012899
+:10A9F0008D030018306200701040002E306200207D
+:10AA0000104000043C02001002C210241040000D4F
+:10AA10000000000030620040104000043C020020B2
+:10AA200002C2102410400007000000003062001035
+:10AA3000104001A93C02004002C21024144001A6AB
+:10AA4000000000008F8200403042000114400008E6
+:10AA5000000020218C030104240200015062000543
+:10AA6000240400018C0202641040000300801021C5
+:10AA700024040001008010211040000600000000A6
+:10AA80008F42030C24420001AF42030C10000192DC
+:10AA90008F42030C8F82004434420004AF82004492
+:10AAA0008F42030824420001AF4203081000018ACC
+:10AAB0008F420308306200021040014B3C02080044
+:10AAC0008D1E001C001E5702AFAA0034950A001606
+:10AAD00003C22024AFAA00248FAA0034240200015C
+:10AAE0001542000633DEFFFF001E11403403ECC0A8
+:10AAF000004310211000001002E2A82124020002ED
+:10AB00001542000524020003001E114024426CC0BF
+:10AB10001000000902E2A82115420005001E118064
+:10AB2000001E114024424CC01000000302E2A82184
+:10AB30000057102124550CE096A2000E304AFFFC6D
+:10AB40003042040010400003AFAA002C100000E1C6
+:10AB500000008821108000040000882197B10026A1
+:10AB6000100000DDA6B100128EB30018966A000C2A
+:10AB7000A7AA003E97A5003E2CA305DD38A2887049
+:10AB80002C420001006218251060001500002021F1
+:10AB900032C2080010400015240208009663001419
+:10ABA000146200123402AAAA9663000E146200070F
+:10ABB00000002821966300102402030014620004A0
+:10ABC00000A01021966200122C45000100A0102167
+:10ABD0005440000624040016100000040000000089
+:10ABE0002402080050A200012404000E108000B9C5
+:10ABF00002649021924200003042000F00028080E7
+:10AC000032C2010010400020025018213C020020F6
+:10AC10000043102B1440000E024020210000282188
+:10AC2000948200002484000200A228210083102BBB
+:10AC30001440FFFB30A2FFFF00051C020062282128
+:10AC400000051C0230A2FFFF10000009006228214D
+:10AC50008F4701488F420110001028423C06002017
+:10AC60000040F809AFA800403045FFFF8FA8004022
+:10AC700050A000013405FFFF8FAA002C354A0002C6
+:10AC800010000002AFAA002C0000282132C2008070
+:10AC900010400090A6A50010264300093C02001FAA
+:10ACA0003442FFFF0043102B10400003000000005F
+:10ACB0008F420148006218239066000030C200FFF6
+:10ACC000384300062C630001384200112C42000179
+:10ACD000006218251060007F24020800000088210F
+:10ACE00097A3003E1462000F0260202196710000BD
+:10ACF0009662000296630004966400060222882190
+:10AD00000223882102248821966200089663000AA3
+:10AD10009664000C0222882102238821100000077B
+:10AD200002248821948200002484000202228821C7
+:10AD30000092102B1440FFFB0000000000111C02C9
+:10AD40003222FFFF0062882100111C023222FFFF25
+:10AD50000062882132C2020010400003264400062F
+:10AD60001000003E000080213C05001F34A5FFFFBD
+:10AD700000A4102B10400003000000008F42014887
+:10AD8000008220239482000030421FFF1040000404
+:10AD90002644000C96420002100000300050802330
+:10ADA0009642000226430014005080233C020020FB
+:10ADB0000043102B1440000A00D080219642000C62
+:10ADC000020280219642000E964300109644001223
+:10ADD0000202802102038021100000200204802151
+:10ADE00000A4102B10400003000000008F42014817
+:10ADF0000082202394820000248400020202802129
+:10AE000000A4102B10400003000000008F420148F6
+:10AE10000082202394820000248400020202802108
+:10AE200000A4102B10400003000000008F420148D6
+:10AE300000822023948200002484000202028021E8
+:10AE400000A4102B10400003000000008F420148B6
+:10AE50000082202394820000020280213C02010033
+:10AE600002C210241040000E000000008FAA002C27
+:10AE7000314200041040000A000000009504000E5A
+:10AE8000026420210C003EEC2484FFFC3042FFFFD2
+:10AE90000222882100111C023222FFFF0062882159
+:10AEA0008FAA002401518823001114020222882154
+:10AEB0000230882100111402022288213231FFFF62
+:10AEC000522000013411FFFF8FAA002C354A0001E7
+:10AED000AFAA002CA6B1001297AA002EA6AA000EB7
+:10AEE0008FAA002C314200041040000224091000F7
+:10AEF000340980008F4800448F4401A08F4501A48D
+:10AF0000AFA900108F4900440008414001001821FA
+:10AF1000AFA900148F48000C02A0302124070020A4
+:10AF2000AFA800188F48010C0000102100A32821B1
+:10AF300000A3482B008220210100F809008920216C
+:10AF40001440000B000000008F8201283C04000127
+:10AF500024846914AFBE0014AFA200108F860124B0
+:10AF60008F8701203C0500070C002B3B34A599205E
+:10AF70008F4203682442FFFFAF4203688F420044C0
+:10AF80008F4300882442000100431024AF42004454
+:10AF90008FAA00348F440368240200011542000682
+:10AFA000240200028F42035C2442FFFFAF42035C95
+:10AFB000100000498F42035C1542000600000000AB
+:10AFC0008F4203642442FFFFAF420364100000423B
+:10AFD0008F4203648F4203602442FFFFAF4203604D
+:10AFE0001000003D8F4203603062100010400005E9
+:10AFF000306280008F420078244200011000003649
+:10B00000AF42007810400034000000008F4200780A
+:10B0100024420001AF4200788C0302400043102B11
+:10B020001440002D240700088F4401688F45016CEF
+:10B030008F4300448F48000C8F860120240200407B
+:10B04000AFA20010AFA30014AFA800188F42010CEC
+:10B050000040F80924C6001C14400011240200011D
+:10B060003C01000100370821A02240F28F82012418
+:10B07000AFA200108F8201283C0400012484688C58
+:10B08000AFA200148F4600448F8701203C050009C1
+:10B090000C002B3B34A513001000000B0000000037
+:10B0A0008F42030424420001AF4203048F42030491
+:10B0B0008F420044AF42007C3C0100010037082170
+:10B0C000A02040F2AF4000788F42031824420001D4
+:10B0D000AF4203188F4203188FBF00608FBE005C21
+:10B0E0008FB500588FB300548FB200508FB1004C11
+:10B0F0008FB0004803E0000827BD006803E00008A7
+:10B100000000000000000000000000008F42013C31
+:10B11000AF8200C08F42013CAF8200C48F42013C2D
+:10B12000AF8200C88F420138AF8200D08F42013811
+:10B13000AF8200D48F42013803E00008AF8200D80C
+:10B1400027BDFFE02784020824050200AFBF0018D6
+:10B150000C002BBF240600088C0202040C004012D5
+:10B16000AF8202103C0200018C426D94304200021A
+:10B170001040000E000020218C060248240200022C
+:10B180003C010001AC226D980C0051042405000222
+:10B19000000020218C060248240200013C0100012D
+:10B1A000AC226D9810000011240500018C060248A5
+:10B1B000240200043C010001AC226D980C005104F3
+:10B1C000240500043C0200018C426D9430420001D1
+:10B1D00010400008240200013C010001AC226D98DF
+:10B1E00000002021240500013C06601B0C005104D6
+:10B1F000000000003C040001248469D08F4201500B
+:10B200008F4301543C0500088F4601580002164048
+:10B21000000319403463040300431025000633C0C3
+:10B2200000461025AF82021CAFA00010AFA0001492
+:10B230008F86021C34A502000C002B3B0000382135
+:10B240003C010001AC206D903C010001AC206DA8D8
+:10B250008FBF001803E0000827BD002027BDFFE0D6
+:10B260003C05000834A50300AFBF0018AFA00010D4
+:10B27000AFA000148F8602003C040001248469DC26
+:10B280000C002B3B000038218F42041024420001A7
+:10B29000AF4204108F4204108FBF001803E0000873
+:10B2A00027BD002027BDFFD8AFBF0020AFB1001CD5
+:10B2B000AFB000188F4203A424420001AF4203A4A0
+:10B2C0008F4203A48F9002208F8200E0AFA2001073
+:10B2D0008F8200E4AFA200148F8600C48F8700C85D
+:10B2E0003C040001248469E80C002B3B0200282167
+:10B2F0003C04400002041024504000B43C0401000F
+:10B300008F4203BC24420001AF4203BC8F4203BC06
+:10B310008F8700C48F8300C88F42014800671823BD
+:10B320000043102B10400003000000008F42014832
+:10B330000062182110600005000000008F42014CDF
+:10B340000043102B1040000B000000008F8200E033
+:10B350008F430124AF42011CAF4301148F820220AE
+:10B360003C0308FF3463FFFB00431024100000CEB1
+:10B37000004410258F8202203C0308FF3463FFFF46
+:10B380000043102434420004AF8202208F8200E088
+:10B390008F430124AF42011CAF4301148F8600C8C4
+:10B3A0008F8401208F8301241000000500002821D4
+:10B3B0001462000224620020276248000040182125
+:10B3C0001064000C30A200FF8C62001830420003B1
+:10B3D0001040FFF727624FE08F4203D024050001A1
+:10B3E00024420001AF4203D08F4203D08C66000894
+:10B3F00030A200FF1440005800000000934205C432
+:10B4000014400055000000008F8700C48F8800E0C2
+:10B410008F8400E42402FFF8010240240104102379
+:10B42000000218C3046200012463020010600005DA
+:10B430002402000110620009000000001000001F3B
+:10B44000000000008F4203C000E0302124420001D0
+:10B45000AF4203C0100000408F4203C08F4203C4BC
+:10B4600024420001AF4203C48C8600008F42014891
+:10B470008F4303C400E618230043102B1040000440
+:10B480002C62233F8F420148006218212C62233F27
+:10B4900014400031000000008F42020C24420001E1
+:10B4A000AF42020C8F42020C00E0302124820008DF
+:10B4B000AF8200E410000028AF8200E88F4203C88A
+:10B4C00024420001AF4203C88F4203C88C850000AC
+:10B4D0008F42014800A718230043102B104000039F
+:10B4E000000000008F420148006218218F42014C89
+:10B4F0000043102B5440000A00A030218F42020C60
+:10B5000024420001AF42020C8F42020C2482000848
+:10B51000AF8200E48F8400E41488FFECAF8400E87D
+:10B520001488000D27623000148200022482FFF884
+:10B5300027623FF8944300063C02001F3442FFFF9D
+:10B5400000C330210046102B104000030000000013
+:10B550008F42014800C23023AF8600C88F8300C4E9
+:10B560008F42014800C318230043102B10400003F2
+:10B57000000000008F4201480062182110600005A1
+:10B58000000000008F42014C0043102B5040000887
+:10B590003C02FDFF8F8202203C0308FF3463FFFB67
+:10B5A000004310243C0340001000003F00431025DE
+:10B5B0008F4303CC3442FFFF0282A02424630001A6
+:10B5C000AF4303CC100000398F4203CC0204102497
+:10B5D0001040000E3C1102008F4203A824420001DB
+:10B5E000AF4203A88F4203A88F8202203C0308FFCA
+:10B5F0003463FFFF00431024004410250C003DAFCE
+:10B60000AF82022010000029000000000211102467
+:10B61000504000083C1104008F4203AC244200015A
+:10B62000AF4203AC0C003DAF8F4203AC10000019D9
+:10B6300000000000021110241040001C0000000057
+:10B640008F83022424021402146200093C050008BE
+:10B650003C040001248469F4AFA00010AFA00014E2
+:10B660008F86022434A505000C002B3B00003821F6
+:10B670008F4203B024420001AF4203B08F4203B0B7
+:10B680008F82022002002021344200020C004E9CD6
+:10B69000AF8202208F8202203C0308FF3463FFFF49
+:10B6A0000043102400511025AF8202208FBF0020DC
+:10B6B0008FB1001C8FB0001803E0000827BD0028E0
+:10B6C00003E00008000000003C0200018C426DA86D
+:10B6D00027BDFFB0AFBF0048AFBE0044AFB50040CC
+:10B6E000AFB3003CAFB20038AFB100341040000F30
+:10B6F000AFB000303C04000124846A003C0500081F
+:10B70000AFA00010AFA000148F86022034A5060061
+:10B71000240200013C010001AC206DA83C010001A5
+:10B72000AC226D9C0C002B3B000038213C037FFFBA
+:10B730008C0202683463FFFF3C04FDFF00431024C9
+:10B74000AC0202688F4200043484FFFF30420002E2
+:10B75000104000920284A0243C040600348420009F
+:10B760008F420004000028212403FFFD0043102421
+:10B77000AF420004AFA400208F5E001827AA00206B
+:10B78000240200FF13C20002AFAA002C27C500014B
+:10B790008C02022800A090211642000E001E38C024
+:10B7A0008F42033C24420001AF42033C8F42033CE2
+:10B7B0008C0202283C040001248469983C0500099D
+:10B7C000AFA00014AFA200108FA600201000006DE3
+:10B7D00034A5050000F710218FA300208FA40024BA
+:10B7E000AC4304C0AC4404C48F8300548F82005423
+:10B7F000247003E8020210232C4203E91040001BCE
+:10B800000000982100E08821263504C08F4401788B
+:10B810008F45017C02201821240A0004AFAA0010E1
+:10B82000AFB200148F48000C0000102102F5302147
+:10B83000AFA800188F48010C2407000800A3282196
+:10B8400000A3482B008220210100F8090089202153
+:10B8500054400006241300018F820054020210237A
+:10B860002C4203E91440FFE900000000326200FFAF
+:10B8700054400017AF5200188F4203782442000151
+:10B88000AF4203788F4203788F8201208FAA002C69
+:10B89000AFA200108F8201243C040001248469A41B
+:10B8A0003C050009AFA200148D46000010000035D1
+:10B8B00034A506008F42030824130001244200012E
+:10B8C000AF4203088F4203081000001E326200FFDF
+:10B8D0008F8300548F820054247003E802021023E7
+:10B8E0002C4203E910400016000098213C1500206E
+:10B8F000241100108F42000C8F4401608F450164B9
+:10B900008F860120AFB10010AFB200140055102592
+:10B91000AFA200188F42010C240700080040F8096C
+:10B9200024C6001C1440FFE3000000008F82005476
+:10B93000020210232C4203E91440FFEE0000000035
+:10B94000326200FF14400011000000008F420378B3
+:10B9500024420001AF4203788F4203788F82012096
+:10B960008FAA002CAFA200108F8201243C0400019A
+:10B97000248469AC3C050009AFA200148D46000088
+:10B9800034A507000C002B3B03C038218F4202EC8A
+:10B9900024420001AF4202EC8F4202EC8FBF00480C
+:10B9A0008FBE00448FB500408FB3003C8FB200388B
+:10B9B0008FB100348FB0003003E0000827BD005085
+:10B9C0003C0200018C426DA827BDFFE01440000D31
+:10B9D000AFBF00183C04000124846A0C3C05000839
+:10B9E000AFA00010AFA000148F86022034A507007E
+:10B9F000240200013C010001AC226DA80C002B3B8D
+:10BA0000000038213C02000402C21024104000074C
+:10BA1000000000008F8202203C0308FF3463FFFF18
+:10BA20000043102434420008AF8202203C0500018C
+:10BA30008CA56D982402000114A2000700002021AB
+:10BA40000C00529B24050001AC02026C8C03026CBA
+:10BA5000100000063C0200070C00529B0000202151
+:10BA6000AC0202688C0302683C02000700621824E2
+:10BA70003C0200025062000D3C0205F50043102B11
+:10BA8000144000063C0200043C0200011062000960
+:10BA90003C0200981000000B000000001462000936
+:10BAA0003C023B9A100000043442CA00100000021D
+:10BAB0003442E10034429680AF4201FC8F4201FCE7
+:10BAC000AEE200648FBF001803E0000827BD00202D
+:10BAD0000000000000000000000000000086102BA5
+:10BAE000504000010087202300C410230002484377
+:10BAF0000125102B1040001B00091040008240213E
+:10BB00000088102B104000070000182194820000CC
+:10BB100024840002006218210088102B1440FFFBCF
+:10BB2000000000000060202100C7302300A910237E
+:10BB30000002104000C2282100C5102B1040000751
+:10BB40000000182194C2000024C6000200621821DF
+:10BB500000C5102B1440FFFB000000001000000D7A
+:10BB60000083202100051040008228210085102B31
+:10BB70001040000700001821948200002484000275
+:10BB8000006218210085102B1440FFFB000000000C
+:10BB90000060202100041C023082FFFF006220218F
+:10BBA00000041C023082FFFF0062202103E0000835
+:10BBB0003082FFFF03E00008000000000080282121
+:10BBC00030A200011040002B3C03001F3463FFFF34
+:10BBD00024A200040062102B544000070065102BC3
+:10BBE00090A2000190A4000390A3000090A5000281
+:10BBF0001000002A00441021104000030000000043
+:10BC00008F42014800A2282390A4000024A500012F
+:10BC10000065102B10400003000000008F42014817
+:10BC200000A2282390A2000024A500010002120017
+:10BC3000008220210065102B10400003000000004E
+:10BC40008F42014800A2282390A2000024A50001F1
+:10BC5000008220210065102B10400003000000002E
+:10BC60008F42014800A2282390A200001000002D5E
+:10BC7000000212003463FFFF24A200040062102BB4
+:10BC80005440000A0065102B90A2000090A400020E
+:10BC900090A3000190A500030044102100021200AF
+:10BCA00000651821100000200043202110400003EF
+:10BCB000000000008F42014800A2282390A200004B
+:10BCC00024A50001000222000065102B1040000393
+:10BCD000000000008F42014800A2282390A200002B
+:10BCE00024A50001008220210065102B10400003D4
+:10BCF000000000008F42014800A2282390A200000B
+:10BD000024A5000100021200008220210065102BF2
+:10BD100010400003000000008F42014800A22823C9
+:10BD200090A200000082202100041C023082FFFF4C
+:10BD30000062202100041C023082FFFF00622021EB
+:10BD400003E000083082FFFF000000008F82022025
+:10BD500034420002AF8202203C0200028C428FF883
+:10BD60003042400010400054240400018F82020041
+:10BD700024067FFF8F830200304500022402FFFD6E
+:10BD800000621824AF830200AF8402048F83005442
+:10BD90008F82005410000002246300018F8200543F
+:10BDA000006210232C4200021440FFFC000000003F
+:10BDB0008F8202241444004D0004204000C4102B44
+:10BDC0001040FFF1000000008F82020000451025A6
+:10BDD000AF8202008F82022034428000AF820220B4
+:10BDE0008F8300548F8200541000000224630001EE
+:10BDF0008F820054006210232C4200021440FFFC8A
+:10BE0000000000008F8202203C0300040043102445
+:10BE10001440000F000000008F8202203C03FFFF4F
+:10BE200034637FFF00431024AF8202208F830054CD
+:10BE30008F82005410000002246300018F8200549E
+:10BE4000006210232C4200021440FFFC000000009E
+:10BE50008F8202203C030004004310241440000D94
+:10BE6000000000008F82022034428000AF82022056
+:10BE70008F8300548F82005410000002246300015D
+:10BE80008F820054006210232C4200021440FFFCF9
+:10BE9000000000008F8202203C03000400431024B5
+:10BEA0001040001B000010218F830220240200019B
+:10BEB000100000153C04F7008F8202203C04F700BC
+:10BEC00000441025AF8202208F8202202403FFFD50
+:10BED00000431024AF8202208F8202203C03030023
+:10BEE000004310241440000300000000100000086C
+:10BEF000000010218F82022034420002AF82022013
+:10BF00008F8302202402000100641825AF830220E1
+:10BF100003E0000800000000000020213C050100B3
+:10BF200024020001AF80021CAF820200AF82022017
+:10BF300027625000AF8200C027625000AF8200C469
+:10BF400027625000AF8200C827625000AF8200D045
+:10BF500027625000AF8200D427625000AF8200D821
+:10BF600027623000AF8200E027623000AF8200E439
+:10BF700027623000AF8200E827622800AF8200F01D
+:10BF800027622800AF8200F427622800AF8200F801
+:10BF9000000418C02484000103631021AC45300460
+:10BFA00003631021AC403000288202001440FFF9E6
+:10BFB000000418C000002021000418C024840001DF
+:10BFC00003631021AC40280403631021AC40280017
+:10BFD000288201001440FFF9000418C0AF80023C21
+:10BFE0002403008024040100AC60000024630004EA
+:10BFF0000064102B5440FFFDAC6000008F830040B4
+:10C000003C02F000006218243C0250001062000C58
+:10C010000043102B144000063C0260003C0240002C
+:10C020001062000824020800100000080000000050
+:10C030001062000424020800100000040000000048
+:10C04000240207003C010001AC226DAC03E00008B3
+:10C05000000000003C0200018C426DBC27BDFFD0F7
+:10C06000AFBF002CAFB20028AFB10024AFB00020AA
+:10C070003C01000110400005AC206D940C004D9E69
+:10C08000000000003C010001AC206DBC8F83005417
+:10C090008F82005410000002246300648F820054D9
+:10C0A000006210232C4200651440FFFC00000000D9
+:10C0B0000C004DB9000000002404000100002821FC
+:10C0C00027A60018340280000C0045BEA7A2001865
+:10C0D0008F8300548F820054100000022463006498
+:10C0E0008F820054006210232C4200651440FFFC34
+:10C0F00024040001240500010C00457C27A600183B
+:10C100008F8300548F820054100000022463006467
+:10C110008F820054006210232C4200651440FFFC03
+:10C1200024040001240500010C00457C27A600180A
+:10C130008F8300548F820054100000022463006437
+:10C140008F820054006210232C4200651440FFFCD3
+:10C15000240400013C06000124C66F240C00457C29
+:10C16000240500028F8300548F82005410000002C7
+:10C17000246300648F820054006210232C42006507
+:10C180001440FFFC24040001240500033C100001BE
+:10C1900026106F260C00457C0200302197A600185F
+:10C1A0003C07000194E76F243C04000124846AE00A
+:10C1B000AFA00014960200003C05000D34A501005C
+:10C1C0000C002B3BAFA2001097A200181040004DAE
+:10C1D00024036040960200003042FFF01443000C3C
+:10C1E000240200203C03000194636F241462000BBE
+:10C1F00024027830240200033C010001AC226D943B
+:10C20000240200053C0100011000003FAC226F3405
+:10C210003C03000194636F24240278301462000C04
+:10C22000240300103C02000194426F263042FFF0CC
+:10C2300014430007240200033C010001AC226D946A
+:10C24000240200063C0100011000002FAC226F34D4
+:10C250003C0200018C426D943C03000194636F2406
+:10C26000344200013C010001AC226D94240200150F
+:10C270001462000B000000003C02000194426F2693
+:10C280003042FFF03843F4202C6300013842F43090
+:10C290002C420001006218251460001B24020003D8
+:10C2A0003C03000194636F2424027810146200168A
+:10C2B000240200023C02000194426F263042FFF04B
+:10C2C00014400011240200021000000F2402000498
+:10C2D0003C0200018C426D94344200083C01000194
+:10C2E000AC226D941000005E240200043C020001A8
+:10C2F0008C426D94344200043C010001100000AFF8
+:10C30000AC226D94240200013C010001AC226F407C
+:10C310003C0200018C426D9430420002144000B295
+:10C320003C09FFF024020E00AF8202388F840054D3
+:10C330008F820054240300083C010001AC236D9857
+:10C3400010000002248401F48F8200540082102324
+:10C350002C4201F51440FFFC3C0200C8344201FBB2
+:10C36000AF8202388F8300548F8200541000000285
+:10C37000246301F48F820054006210232C4201F5E3
+:10C380001440FFFC00008021241200012411000948
+:10C390000C004482000000003C010001AC326DB48E
+:10C3A0000C004547000000003C0200018C426DB4C7
+:10C3B0001451FFFB3C0200C8344201F6AF82023840
+:10C3C0008F8300548F820054100000022463000AFF
+:10C3D0008F820054006210232C42000B1440FFFC9B
+:10C3E000000000008F820220240400013442000279
+:10C3F000AF8202208F83020024057FFF2402FFFD0D
+:10C4000000621824AF830200AF8402048F830054BB
+:10C410008F82005410000002246300018F820054B8
+:10C42000006210232C4200021440FFFC00000000B8
+:10C430008F8202241444000534028000000420404E
+:10C4400000A4102B1040FFF0340280001082FFA0E7
+:10C45000261000012E0200141440FFCD2402000417
+:10C460003C010001AC226D980000802124120009DB
+:10C470003C11FFFF36313F7F0C004482000000007A
+:10C48000240200013C010001AC226DB40C004547C0
+:10C49000000000003C0200018C426DB41452FFFB0E
+:10C4A000000000008F82004400511024344250806C
+:10C4B000AF8200448F8300548F820054100000022A
+:10C4C0002463000A8F820054006210232C42000B68
+:10C4D0001440FFFC000000008F8200440051102433
+:10C4E0003442F080AF8200448F8300548F82005426
+:10C4F000100000022463000A8F820054006210239F
+:10C500002C42000B1440FFFC000000008F82022030
+:10C510003C03F70000431025AF8202208F830054B4
+:10C520008F82005410000002246300648F82005444
+:10C53000006210232C4200651440FFFC0000000044
+:10C540008F8202202404000134420002AF820220C4
+:10C550008F83020024057FFF2402FFFD0062182460
+:10C56000AF830200AF8402048F8300548F82005493
+:10C5700010000002246300018F8200540062102327
+:10C580002C4200021440FFFC000000008F820224B5
+:10C5900014440005340280000004204000A4102B45
+:10C5A0001040FFF0340280001082FF50261000017E
+:10C5B0002E0200641440FFB0000000003C020001A5
+:10C5C0008C426D9430420004144000073C09FFF097
+:10C5D0008F8200443C03FFFF34633F7F00431024FD
+:10C5E000AF8200443C09FFF03529BDC03C06000184
+:10C5F0008CC66D943C04000124846AE0240200018E
+:10C600003C010001AC226D9C8F8200543C0700016C
+:10C610008CE76F403C03000194636F243C080001E9
+:10C6200095086F263C05000D34A501003C01000172
+:10C63000AC206D98004910213C010001AC226F3004
+:10C64000AFA300100C002B3BAFA800148FBF002C31
+:10C650008FB200288FB100248FB0002003E00008C3
+:10C6600027BD003027BDFFE83C0500018CA56D9873
+:10C67000240600042402000114A20014AFBF00101D
+:10C680003C0200028C428FFC3042800010400005CA
+:10C690003C04000F3C0300018C636F401000000558
+:10C6A000348442403C0400043C0300018C636F402E
+:10C6B000348493E024020005146200160000000098
+:10C6C0003C04003D10000013348409003C020002C9
+:10C6D0008C428FF830428000104000053C04001E60
+:10C6E0003C0300018C636F4010000005348484809B
+:10C6F0003C04000F3C0300018C636F4034844240D3
+:10C700002402000514620003000000003C04007ACB
+:10C71000348412003C0200018C426F308F8300543D
+:10C7200000441021004310230044102B1440004CFF
+:10C73000000000003C0200018C426DA01440004843
+:10C74000000000003C01000110C00025AC206DB0CD
+:10C750003C0900018D296D94240700013C04400030
+:10C760003C08000225088FFC250AFFFC0005284232
+:10C7700014A0000224C6FFFF2405000800A910240D
+:10C78000104000100000000014A700080000000086
+:10C790008D020000004410241040000A0000000038
+:10C7A0003C01000110000007AC256DB08D42000077
+:10C7B0000044102410400003000000003C01000170
+:10C7C000AC276DB03C0200018C426DB00006182B06
+:10C7D0002C420001004310245440FFE5000528428C
+:10C7E0008F8200543C0300018C636DB03C0100015A
+:10C7F000AC226F301060003B240200053C030001B6
+:10C800008C636F403C010001AC256D9814620012EE
+:10C81000240200013C0200028C428FF83C032000FD
+:10C820003463500000431024144000062402000129
+:10C830003C010001AC206F1C3C010001AC226D9852
+:10C84000240200013C010001AC226E243C010001E5
+:10C85000AC226DA4240200013C010001AC226D9CBD
+:10C860003C0200018C426DB01040001E0000000030
+:10C870003C0200018C426D9C104000082402000123
+:10C880003C010001AC206D9CAEE204B83C0100010B
+:10C89000AC206E1C3C010001AC226DD48EE304B8C8
+:10C8A0002402000810620005240200010C00423935
+:10C8B000000000001000000B000000003C0300011D
+:10C8C0008C636D98106200072402000E3C03000286
+:10C8D0008C638F9010620003000000000C004E9CDF
+:10C8E0008F8402208FBF001003E0000827BD0018CE
+:10C8F00027BDFFE03C03FDFF3C0400018C846D98E4
+:10C900003C0200018C426DC03463FFFF0283A0240F
+:10C9100014820006AFBF00188EE304B83C02000189
+:10C920008C426DC410620006000000008EE204B864
+:10C930003C010001AC246DC03C010001AC226DC47F
+:10C940003C0300018C636D98240200021062019C7C
+:10C950002C62000310400005240200011062000A4E
+:10C960000000000010000226000000002402000465
+:10C97000106200B6240200081062010A24020001BD
+:10C980001000021F000000008EE204B82443FFFFE5
+:10C990002C6200081040021C000310803C010001C2
+:10C9A000002208218C226AF80040000800000000E4
+:10C9B0003C0300018C636F402402000514620010E8
+:10C9C000000000003C0200018C426DA410400008F1
+:10C9D000240200030C004482000000002402000234
+:10C9E000AEE204B83C01000110000002AC206DA4CE
+:10C9F000AEE204B83C01000110000203AC206D302F
+:10CA00000C004482000000003C0200018C426DA436
+:10CA10003C010001AC206D301440017A2402000278
+:10CA20001000019D240200073C0300018C636F404D
+:10CA30002402000514620003240200013C010001ED
+:10CA4000AC226DD00C0045FF000000003C0300014B
+:10CA50008C636DD010000174240200113C050001AC
+:10CA60008CA56D983C0600028CC68FFC0C0051040E
+:10CA700000002021240200053C010001AC206DA42F
+:10CA8000100001E1AEE204B83C04000124846AEC29
+:10CA90003C05000F34A501000000302100003821C2
+:10CAA000AFA000100C002B3BAFA00014100001D66B
+:10CAB000000000008F8202203C0300040043102489
+:10CAC00014400175240200078F8300543C020001CA
+:10CAD0008C426F282463D8F0004310232C42271087
+:10CAE00014400003240200013C010001AC226D9CB3
+:10CAF0003C0200028C428FFC30425000104001C2C8
+:10CB0000000000008F820220304280001040017D32
+:10CB10000000000010000175000000003C0500014D
+:10CB20008CA56D980C00529B000020210C00551B19
+:10CB3000000020213C0300028C638FF4046101B0EB
+:10CB4000240200013C02000800621024104000068C
+:10CB5000000000008F8202143C03FFFF00431024FA
+:10CB6000100000053442251F8F8202143C03FFFF92
+:10CB7000004310243442241FAF8202148F8202200B
+:10CB80003C03020034420002AF820220240200086B
+:10CB9000AEE204B88F8202200283A0253C03000489
+:10CBA0000043102414400016000000003C02000264
+:10CBB0008C428FFC304250001040000D00000000FD
+:10CBC0008F820220304280001040000600000000EA
+:10CBD0008F8202203C03FFFF34637FFF10000003BD
+:10CBE000004310248F82022034428000AF82022052
+:10CBF0008F8202203C03F70000431025AF82022001
+:10CC00003C0300018C636F40240200051462000A9B
+:10CC1000000000003C02000194426F2624429FBCA9
+:10CC20002C420004104000042404001824050002D3
+:10CC30000C004DDB240600200C003E6D00000000BF
+:10CC40003C01000110000170AC206E208EE204B89F
+:10CC50002443FFFF2C6200081040016B000310808A
+:10CC60003C010001002208218C226B1800400008C2
+:10CC7000000000000C004547000000003C030001DC
+:10CC80008C636DB4100000E8240200093C0200022D
+:10CC90008C428FF830424000104000040000000039
+:10CCA0008F820044100000063442F0808F820044DE
+:10CCB0003C03FFFF34633F7F004310243442A080D5
+:10CCC000AF8200448F830054100000EA2402000465
+:10CCD0008F8300543C0200018C426F282463D8F0FB
+:10CCE000004310232C422710144001472402000562
+:10CCF000100000D8000000008F8202203C03F700E3
+:10CD000000431025AF820220AF8002043C010002E4
+:10CD1000100000D6AC208FE08F8300543C0200014D
+:10CD20008C426F282463FFF6004310232C42000A34
+:10CD30001440013524020007100000D70000000055
+:10CD40000C003F50000000001040012D24020001A3
+:10CD50008F8202143C03FFFF3C0400018C846F1C93
+:10CD6000004310243442251FAF820214240200081D
+:10CD700010800005AEE204B83C0200018C426E4413
+:10CD800010400064240200018F8202203C0300084E
+:10CD9000004310241040006A3C020200100000789A
+:10CDA000000000008EE204B82443FFFF2C6200075D
+:10CDB00010400115000310803C01000100220821F1
+:10CDC0008C226B3800400008000000000C003DAFD2
+:10CDD000000000003C010001AC206D9CAF8002040B
+:10CDE0003C0100020C004482AC208FE024020001D0
+:10CDF0003C010001AC226DB42402000210000102CB
+:10CE0000AEE204B80C004547000000003C030001FE
+:10CE10008C636DB410000084240200093C020002FF
+:10CE20008C428FF830424000104000033C0200C8A2
+:10CE300010000002344201F6344201FEAF82023893
+:10CE40008F8300541000008B240200048F83005451
+:10CE50003C0200018C426F282463D8F00043102369
+:10CE60002C422710144000E824020005100000792D
+:10CE7000000000008F8202203C03F70000431025D1
+:10CE8000AF820220AF8002043C0100021000007754
+:10CE9000AC208FE08F8300543C0200018C426F284D
+:10CEA0002463FFF6004310232C42000A144000D6EE
+:10CEB0002402000710000078000000000C003F5022
+:10CEC00000000000104000CE240200018F820214F6
+:10CED0003C03FFFF3C0400018C846F1C00431024C2
+:10CEE0003442251FAF820214240200081080000F74
+:10CEF000AEE204B83C0200018C426E441440000BC8
+:10CF0000000000008F82022034420002AF82022023
+:10CF1000240200013C010002AC228F900C004E9CC8
+:10CF20008F84022010000016000000008F82022073
+:10CF30003C03000800431024144000113C0202008E
+:10CF40000282A0252402000E3C010002AC228F9038
+:10CF50000C00551B000020218F8202203442000269
+:10CF60000C003E6DAF8202203C0500018CA56D983F
+:10CF70000C00529B00002021100000A300000000C4
+:10CF80003C0200018C426E441040009F00000000F3
+:10CF90003C0200018C426E402442FFFF3C01000134
+:10CFA000AC226E4014400098240200023C010001B3
+:10CFB000AC206E443C01000110000093AC226E4096
+:10CFC0008EE204B82443FFFF2C6200071040008E5D
+:10CFD000000310803C010001002208218C226B58C4
+:10CFE00000400008000000003C0200018C426DA4DB
+:10CFF00010400018240200050C00448200000000CC
+:10D0000024020002AEE204B83C0100011000007EE0
+:10D01000AC206DA40C004963000000003C0300013B
+:10D020008C636DD42402000614620077240200038E
+:10D0300010000075AEE204B83C0500018CA56D98A7
+:10D040003C0600028CC68FF80C0051040000202121
+:10D05000240200051000006CAEE204B88F820220AA
+:10D060003C03F70000431025AF8202208F83005459
+:10D0700024020006AEE204B83C0100011000006288
+:10D08000AC236F288F8202203C030004004310244D
+:10D0900010400003240200071000005BAEE204B859
+:10D0A0008F8300543C0200018C426F282463D8F027
+:10D0B000004310232C4227101440000324020001D7
+:10D0C0003C010001AC226D9C3C0200028C428FF8B6
+:10D0D000304250001040004C000000008F820220BF
+:10D0E0003042800010400007000000008F820220C4
+:10D0F0003C03FFFF34637FFF004310241000004215
+:10D10000AF8202208F820220344280001000003E55
+:10D11000AF8202203C0500018CA56D980C00529B4B
+:10D12000000020210C00551B000020213C020002C1
+:10D130008C428FF004410032240200018F820214DD
+:10D140003C03FFFF004310243442251FAF8202142A
+:10D1500024020008AEE204B88F82022034420002AA
+:10D16000AF8202208F8202203C030004004310247F
+:10D1700014400016000000003C0200028C428FF8B0
+:10D18000304250001040000D000000008F8202204D
+:10D190003042800010400006000000008F82022014
+:10D1A0003C03FFFF34637FFF1000000300431024A3
+:10D1B0008F82022034428000AF8202208F820220C0
+:10D1C0003C03F70000431025AF8202203C0200011F
+:10D1D00094426F2624429FBC2C420004104000045D
+:10D1E00024040018240500020C004DDB2406002056
+:10D1F0000C003E6D00000000100000030000000065
+:10D200003C010001AC226D9C8FBF001803E00008B8
+:10D2100027BD00208F8202008F8202208F82022091
+:10D2200034420004AF8202208F8202003C050001DC
+:10D230008CA56D9834420004AF82020024020002E3
+:10D2400010A2004B2CA20003104000052402000194
+:10D2500010A2000A00000000100000B10000000051
+:10D260002402000410A200722402000810A200850B
+:10D270003C02F0FF100000AA000000008F83005065
+:10D280003C02F0FF3442FFFF3C0400018C846F40FD
+:10D29000006218243C0207000062182524020E00D8
+:10D2A0002484FFFB2C840002AF830050AF85020072
+:10D2B000AF85022014800006AF8202388F820044BE
+:10D2C0003C03FFFF34633F7F00431024AF820044E0
+:10D2D0003C0300018C636F402402000514620004CB
+:10D2E000000000008F82004434425000AF820044AE
+:10D2F0003C0200018C426D883C0300018C636F404E
+:10D30000344200222463FFFC2C6300021460000CF2
+:10D31000AF8202003C0200018C426DAC3C03000174
+:10D320008C636D903C0400018C846D8C34428000D1
+:10D3300000621825006418251000000A34620002FB
+:10D340003C0200018C426D903C0300018C636DAC8B
+:10D350003C0400018C846D8C004310250044102592
+:10D3600034420002AF8202201000002F240200018C
+:10D3700024020E01AF8202388F8300503C02F0FF7E
+:10D380003442FFFF3C0400018C846F1C00621824AF
+:10D390003C020D000062182524020001AF830050FA
+:10D3A000AF820200AF820220108000053C033F00E4
+:10D3B0003C0200018C426D80100000043463007058
+:10D3C0003C0200018C426D803463007200431025E2
+:10D3D000AF8202003C0300018C636D843C02F700C5
+:10D3E000006218253C0200018C426D903C04000153
+:10D3F0008C846DAC3C0500018CA56F40004310256A
+:10D4000000441025AF8202202402000514A2000669
+:10D41000240200018F8200442403AFFF0043102444
+:10D42000AF820044240200011000003DAF820238A8
+:10D430008F8300503C02F0FF3442FFFF3C040001A8
+:10D440008C846F1C006218243C020A0000621825BC
+:10D4500024020001AF830050AF8202001080001E42
+:10D46000AF8202203C0200018C426E441440001A3C
+:10D470003C033F003C0200018C426D801000001A0A
+:10D48000346300E08F8300503C0400018C846F1CE7
+:10D490003442FFFF006218241080000FAF83005059
+:10D4A0003C0200018C426E441440000B3C043F00DF
+:10D4B0003C0300018C636D80348400E02402000191
+:10D4C000AF820200AF82022000641825AF83020001
+:10D4D000100000083C05F7003C0200018C426D8002
+:10D4E0003C033F00346300E200431025AF8202009A
+:10D4F0003C05F70034A580003C0300018C636D847B
+:10D500003C0200018C426D903C0400018C846DACA7
+:10D51000006518250043102500441025AF82022025
+:10D5200003E00008000000003C0300018C636DB4C0
+:10D530003C0200018C426DB810620003240200021C
+:10D540003C010001AC236DB81062001D2C62000389
+:10D55000104000252402000114620023240200046C
+:10D560003C0300018C636D981062000624020008E1
+:10D570001462000C3C0200C8344201FB1000000998
+:10D58000AF82023824020E01AF8202388F8200443B
+:10D590003C03FFFF34633F7F00431024344200808C
+:10D5A000AF8200448F830054240200023C0100013A
+:10D5B000AC226DB43C0100011000000BAC236F2CB9
+:10D5C0008F8300543C0200018C426F2C2463D8F0FE
+:10D5D000004310232C4227101440000324020009AA
+:10D5E0003C010001AC226DB403E000080000000023
+:10D5F00000000000000000000000000027BDFFD870
+:10D60000AFB2001800809021AFB3001C00A0982199
+:10D61000AFB1001400C08821AFB00010000080211D
+:10D62000AFBF0020A62000000C004D7824040001AC
+:10D63000261000012E0200201440FFFB0000000015
+:10D640000C004D78000020210C004D7824040001CE
+:10D650000C004D78240400010C004D7800002021BE
+:10D66000241000100250102410400002000020215D
+:10D67000240400010C004D78001080421600FFFACF
+:10D6800002501024241000100270102410400002D8
+:10D6900000002021240400010C004D78001080427D
+:10D6A0001600FFFA027010240C004DB934108000EF
+:10D6B0000C004DB9000000000C004D5800000000A7
+:10D6C00050400005001080429622000000501025B6
+:10D6D000A6220000001080421600FFF700000000A4
+:10D6E0000C004DB9000000008FBF00208FB3001C5C
+:10D6F0008FB200188FB100148FB0001003E0000843
+:10D7000027BD002827BDFFD8AFB1001400808821B5
+:10D71000AFB2001800A09021AFB3001C00C0982148
+:10D72000AFB0001000008021AFBF00200C004D788A
+:10D7300024040001261000012E0200201440FFFBEB
+:10D74000000000000C004D78000020210C004D78F6
+:10D75000240400010C004D78000020210C004D78BD
+:10D760002404000124100010023010241040000294
+:10D7700000002021240400010C004D78001080429C
+:10D780001600FFFA0230102424100010025010245A
+:10D790001040000200002021240400010C004D78FC
+:10D7A000001080421600FFFA025010240C004D7841
+:10D7B000240400010C004D7800002021341080006A
+:10D7C000966200000050102410400002000020214A
+:10D7D000240400010C004D78001080421600FFF870
+:10D7E000000000000C004DB9000000008FBF0020B9
+:10D7F0008FB3001C8FB200188FB100148FB00010CF
+:10D8000003E0000827BD00283C0400018C846DD093
+:10D810003C0200018C426E1827BDFFD8AFBF00202C
+:10D82000AFB1001C10820003AFB000183C01000132
+:10D83000AC246E183C0300018C636F402402000589
+:10D84000146200052483FFFF0C0049630000000000
+:10D850001000034C000000002C620013104003492C
+:10D86000000310803C010001002208218C226B8003
+:10D8700000400008000000000C004DB900008021AD
+:10D8800034028000A7A2001027B100100C004D78D0
+:10D8900024040001261000012E0200201440FFFB8A
+:10D8A000000000000C004D78000020210C004D7895
+:10D8B000240400010C004D78000020210C004D785C
+:10D8C0002404000124100010320200011040000264
+:10D8D00000002021240400010C004D78001080423B
+:10D8E0001600FFFA32020001241000100C004D78DF
+:10D8F00000002021001080421600FFFC0000000004
+:10D900000C004D78240400010C004D78000020210B
+:10D9100034108000962200000050102410400002B5
+:10D9200000002021240400010C004D7800108042EA
+:10D930001600FFF8000000000C004DB900000000C8
+:10D940001000030E2402000227B10010A7A000104F
+:10D95000000080210C004D782404000126100001F5
+:10D960002E0200201440FFFB000000000C004D7848
+:10D97000000020210C004D78240400010C004D789B
+:10D98000240400010C004D78000020212410001018
+:10D990003202000110400002000020212404000196
+:10D9A0000C004D78001080421600FFFA3202000190
+:10D9B000241000100C004D7800002021001080423F
+:10D9C0001600FFFC000000000C004DB93410800070
+:10D9D0000C004DB9000000000C004D580000000084
+:10D9E0005040000500108042962200000050102593
+:10D9F000A6220000001080421600FFF70000000081
+:10DA00000C004DB90000000097A2001030428000C9
+:10DA1000144002DC24020003100002D800000000C1
+:10DA200024021200A7A2001027B1001000008021DC
+:10DA30000C004D7824040001261000012E02002065
+:10DA40001440FFFB000000000C004D780000202176
+:10DA50000C004D78240400010C004D7800002021BA
+:10DA60000C004D7824040001241000103202000143
+:10DA70001040000200002021240400010C004D7819
+:10DA8000001080421600FFFA32020001241000103C
+:10DA90000C004D7800002021001080421600FFFC91
+:10DAA000000000000C004D78240400010C004D78AB
+:10DAB0000000202134108000962200000050102425
+:10DAC0001040000200002021240400010C004D78C9
+:10DAD000001080421600FFF8000000000C004DB955
+:10DAE000000000008F8300541000029624020004FE
+:10DAF0008F8300543C0200018C426F3C2463FF9CE6
+:10DB0000004310232C4200641440029E24020002B1
+:10DB10003C0300018C636F40106202972C6200038B
+:10DB20001440029624020011240200031062000532
+:10DB300024020004106202912402000F1000028FE0
+:10DB4000240200111000028D24020005240200149A
+:10DB5000A7A2001027B10010000080210C004D7812
+:10DB600024040001261000012E0200201440FFFBB7
+:10DB7000000000000C004D78000020210C004D78C2
+:10DB8000240400010C004D78000020210C004D7889
+:10DB90002404000124100010320200011040000291
+:10DBA00000002021240400010C004D780010804268
+:10DBB0001600FFFA32020001241000103202001297
+:10DBC0001040000200002021240400010C004D78C8
+:10DBD000001080421600FFFA320200120C004D784D
+:10DBE000240400010C004D78000020213410800036
+:10DBF0009622000000501024104000020000202156
+:10DC0000240400010C004D78001080421600FFF83B
+:10DC1000000000000C004DB9000000008F8300548C
+:10DC200010000248240200068F8300543C020001C9
+:10DC30008C426F3C2463FF9C004310232C42006401
+:10DC400014400250240200071000024C00000000A3
+:10DC500024020006A7A2001027B1001000008021B6
+:10DC60000C004D7824040001261000012E02002033
+:10DC70001440FFFB000000000C004D780000202144
+:10DC80000C004D78240400010C004D780000202188
+:10DC90000C004D7824040001241000103202000111
+:10DCA0001040000200002021240400010C004D78E7
+:10DCB000001080421600FFFA32020001241000100A
+:10DCC0003202001310400002000020212404000151
+:10DCD0000C004D78001080421600FFFA320200134B
+:10DCE0000C004D78240400010C004D780000202128
+:10DCF00034108000962200000050102410400002D2
+:10DD000000002021240400010C004D780010804206
+:10DD10001600FFF8000000000C004DB900000000E4
+:10DD20008F83005410000207240200088F830054E0
+:10DD30003C0200018C426F3C2463FF9C0043102393
+:10DD40002C4200641440020F240200091000020B50
+:10DD50000000000027B10010A7A0001000008021E3
+:10DD60000C004D7824040001261000012E02002032
+:10DD70001440FFFB000000000C004D780000202143
+:10DD80000C004D78240400010C004D78240400019F
+:10DD90000C004D78000020212410001032020001F8
+:10DDA0001040000200002021240400010C004D78E6
+:10DDB000001080421600FFFA320200012410001009
+:10DDC000320200181040000200002021240400014B
+:10DDD0000C004D78001080421600FFFA3202001845
+:10DDE0000C004DB9341080000C004DB9000000004B
+:10DDF0000C004D580000000050400005001080420B
+:10DE00009622000000501025A6220000001080423B
+:10DE10001600FFF7000000000C004DB90000802143
+:10DE200097A2001027B1001034420001A7A20010F1
+:10DE30000C004D7824040001261000012E02002061
+:10DE40001440FFFB000000000C004D780000202172
+:10DE50000C004D78240400010C004D7800002021B6
+:10DE60000C004D782404000124100010320200013F
+:10DE70001040000200002021240400010C004D7815
+:10DE8000001080421600FFFA320200012410001038
+:10DE9000320200181040000200002021240400017A
+:10DEA0000C004D78001080421600FFFA3202001874
+:10DEB0000C004D78240400010C004D780000202156
+:10DEC0003410800096220000005010241040000200
+:10DED00000002021240400010C004D780010804235
+:10DEE0001600FFF8000000000C004DB90000000013
+:10DEF0008F830054100001932402000A8F83005482
+:10DF00003C0200018C426F3C2463FF9C00431023C1
+:10DF10002C4200641440019B2402000B1000019766
+:10DF20000000000027B10010A7A000100000802111
+:10DF30000C004D7824040001261000012E02002060
+:10DF40001440FFFB000000000C004D780000202171
+:10DF50000C004D78240400010C004D7824040001CD
+:10DF60000C004D7800002021241000103202000126
+:10DF70001040000200002021240400010C004D7814
+:10DF8000001080421600FFFA320200012410001037
+:10DF9000320200171040000200002021240400017A
+:10DFA0000C004D78001080421600FFFA3202001774
+:10DFB0000C004DB9341080000C004DB90000000079
+:10DFC0000C004D5800000000504000050010804239
+:10DFD0009622000000501025A6220000001080426A
+:10DFE0001600FFF7000000000C004DB90000802172
+:10DFF00097A2001027B1001034420700A7A200101A
+:10E000000C004D7824040001261000012E0200208F
+:10E010001440FFFB000000000C004D7800002021A0
+:10E020000C004D78240400010C004D7800002021E4
+:10E030000C004D782404000124100010320200016D
+:10E040001040000200002021240400010C004D7843
+:10E05000001080421600FFFA320200012410001066
+:10E0600032020017104000020000202124040001A9
+:10E070000C004D78001080421600FFFA32020017A3
+:10E080000C004D78240400010C004D780000202184
+:10E09000341080009622000000501024104000022E
+:10E0A00000002021240400010C004D780010804263
+:10E0B0001600FFF8000000000C004DB90000000041
+:10E0C0008F8300541000011F2402000C8F83005422
+:10E0D0003C0200018C426F3C2463FF9C00431023F0
+:10E0E0002C42006414400127240200121000012376
+:10E0F0000000000027B10010A7A000100000802140
+:10E100000C004D7824040001261000012E0200208E
+:10E110001440FFFB000000000C004D78000020219F
+:10E120000C004D78240400010C004D7824040001FB
+:10E130000C004D7800002021241000103202000154
+:10E140001040000200002021240400010C004D7842
+:10E15000001080421600FFFA320200012410001065
+:10E1600032020014104000020000202124040001AB
+:10E170000C004D78001080421600FFFA32020014A5
+:10E180000C004DB9341080000C004DB900000000A7
+:10E190000C004D5800000000504000050010804267
+:10E1A0009622000000501025A62200000010804298
+:10E1B0001600FFF7000000000C004DB900008021A0
+:10E1C00097A2001027B1001034420010A7A200103F
+:10E1D0000C004D7824040001261000012E020020BE
+:10E1E0001440FFFB000000000C004D7800002021CF
+:10E1F0000C004D78240400010C004D780000202113
+:10E200000C004D782404000124100010320200019B
+:10E210001040000200002021240400010C004D7871
+:10E22000001080421600FFFA320200012410001094
+:10E2300032020014104000020000202124040001DA
+:10E240000C004D78001080421600FFFA32020014D4
+:10E250000C004D78240400010C004D7800002021B2
+:10E26000341080009622000000501024104000025C
+:10E2700000002021240400010C004D780010804291
+:10E280001600FFF8000000000C004DB9000000006F
+:10E290008F830054100000AB240200138F830054BE
+:10E2A0003C0200018C426F3C2463FF9C004310231E
+:10E2B0002C420064144000B32402000D100000AF93
+:10E2C0000000000027B10010A7A00010000080216E
+:10E2D0000C004D7824040001261000012E020020BD
+:10E2E0001440FFFB000000000C004D7800002021CE
+:10E2F0000C004D78240400010C004D78240400012A
+:10E300000C004D7800002021241000103202000182
+:10E310001040000200002021240400010C004D7870
+:10E32000001080421600FFFA320200012410001093
+:10E3300032020018104000020000202124040001D5
+:10E340000C004D78001080421600FFFA32020018CF
+:10E350000C004DB9341080000C004DB900000000D5
+:10E360000C004D5800000000504000050010804295
+:10E370009622000000501025A622000000108042C6
+:10E380001600FFF7000000000C004DB900008021CE
+:10E3900097A2001027B100103042FFFEA7A2001084
+:10E3A0000C004D7824040001261000012E020020EC
+:10E3B0001440FFFB000000000C004D7800002021FD
+:10E3C0000C004D78240400010C004D780000202141
+:10E3D0000C004D78240400012410001032020001CA
+:10E3E0001040000200002021240400010C004D78A0
+:10E3F000001080421600FFFA3202000124100010C3
+:10E400003202001810400002000020212404000104
+:10E410000C004D78001080421600FFFA32020018FE
+:10E420000C004D78240400010C004D7800002021E0
+:10E43000341080009622000000501024104000028A
+:10E4400000002021240400010C004D7800108042BF
+:10E450001600FFF8000000000C004DB9000000009D
+:10E460008F830054100000372402000E240208405D
+:10E47000A7A2001027B10010000080210C004D78E9
+:10E4800024040001261000012E0200201440FFFB8E
+:10E49000000000000C004D78000020210C004D7899
+:10E4A000240400010C004D78000020210C004D7860
+:10E4B0002404000124100010320200011040000268
+:10E4C00000002021240400010C004D78001080423F
+:10E4D0001600FFFA3202000124100010320200136D
+:10E4E0001040000200002021240400010C004D789F
+:10E4F000001080421600FFFA320200130C004D7823
+:10E50000240400010C004D7800002021341080000C
+:10E51000962200000050102410400002000020212C
+:10E52000240400010C004D78001080421600FFF812
+:10E53000000000000C004DB9000000008F83005463
+:10E54000240200103C010001AC226DD03C0100010E
+:10E550001000000CAC236F3C8F8300543C02000180
+:10E560008C426F3C2463FF9C004310232C420064C8
+:10E570001440000400000000240200113C010001CE
+:10E58000AC226DD08FBF00208FB1001C8FB000185F
+:10E5900003E0000827BD00283C0300018C636D9850
+:10E5A00027BDFFC824020002AFBF0034AFB2003065
+:10E5B000AFB1002C14620004AFB000283C1200027E
+:10E5C000100000038E528FF83C1200028E528FFC16
+:10E5D0003C0300018C636DD43C0200018C426E1C34
+:10E5E000506200042463FFFF3C010001AC236E1C59
+:10E5F0002463FFFF2C6200061040037700031080A5
+:10E600003C010001002208218C226BD80040000848
+:10E610000000000000002021000028210C004DDB3C
+:10E6200034068000240400102405000224060002A1
+:10E63000240200020C004DDBA7A2001824020002F5
+:10E640003C01000110000364AC226DD427B1001816
+:10E65000A7A00018000080210C004D7824040001C0
+:10E66000261000012E0200201440FFFB00000000D5
+:10E670000C004D78000020210C004D78240400018E
+:10E680000C004D78240400010C004D78000020217E
+:10E69000241000103202000110400002000020216E
+:10E6A000240400010C004D78001080421600FFFA8F
+:10E6B00032020001241000100C004D7800002021CF
+:10E6C000001080421600FFFC000000000C004DB955
+:10E6D000341080000C004DB9000000000C004D58B3
+:10E6E000000000005040000500108042962200000B
+:10E6F00000501025A6220000001080421600FFF7EF
+:10E70000000000000C004DB90000000097A20018A6
+:10E710003042800014400004240200033C01000148
+:10E72000AC226DD4240200033C0100011000032A36
+:10E73000AC226DD42404001024050002240600023B
+:10E74000240200020C004DDBA7A200183C030001CC
+:10E750008C636E2024020001146201E1000080211C
+:10E7600027B10018A7A000180C004D782404000160
+:10E77000261000012E0200201440FFFB00000000C4
+:10E780000C004D78000020210C004D78240400017D
+:10E790000C004D78240400010C004D78000020216D
+:10E7A000241000103202000110400002000020215D
+:10E7B000240400010C004D78001080421600FFFA7E
+:10E7C0003202000124100010320200181040000232
+:10E7D00000002021240400010C004D78001080422C
+:10E7E0001600FFFA320200180C004DB934108000F8
+:10E7F0000C004DB9000000000C004D580000000056
+:10E800005040000500108042962200000050102564
+:10E81000A6220000001080421600FFF70000000052
+:10E820000C004DB90000802127B10018A7A00018E6
+:10E830000C004D7824040001261000012E02002057
+:10E840001440FFFB000000000C004D780000202168
+:10E850000C004D78240400010C004D7824040001C4
+:10E860000C004D780000202124100010320200011D
+:10E870001040000200002021240400010C004D780B
+:10E88000001080421600FFFA32020001241000102E
+:10E890003202001810400002000020212404000170
+:10E8A0000C004D78001080421600FFFA320200186A
+:10E8B0000C004DB9341080000C004DB90000000070
+:10E8C0000C004D5800000000504000050010804230
+:10E8D0009622000000501025A62200000010804261
+:10E8E0001600FFF7000000000C004DB90000802169
+:10E8F00024040018000028210C004DDB2406040429
+:10E90000A7A0001A0C004D78240400012610000175
+:10E910002E0200201440FFFB000000000C004D7888
+:10E92000000020210C004D78240400010C004D78DB
+:10E93000240400010C004D78000020212410001058
+:10E9400032020001104000020000202124040001D6
+:10E950000C004D78001080421600FFFA32020001D0
+:10E960002410001032020018104000020000202184
+:10E97000240400010C004D78001080421600FFFABC
+:10E98000320200180C004DB9341080000C004DB953
+:10E99000000000000C004D58000000005040000531
+:10E9A0000010804297A2001A00501025A7A2001A5A
+:10E9B000001080421600FFF7000000000C004DB967
+:10E9C00000008021A7A0001A0C004D78240400014B
+:10E9D000261000012E0200201440FFFB0000000062
+:10E9E0000C004D78000020210C004D78240400011B
+:10E9F0000C004D78240400010C004D78000020210B
+:10EA000024100010320200011040000200002021FA
+:10EA1000240400010C004D78001080421600FFFA1B
+:10EA200032020001241000103202001810400002CF
+:10EA300000002021240400010C004D7800108042C9
+:10EA40001600FFFA320200180C004DB93410800095
+:10EA50000C004DB9000000000C004D5800000000F3
+:10EA6000504000050010804297A2001A0050102567
+:10EA7000A7A2001A001080421600FFF70000000055
+:10EA80000C004DB900008021A7A0001C0C004D789F
+:10EA900024040001261000012E0200201440FFFB78
+:10EAA000000000000C004D78000020210C004D7883
+:10EAB000240400010C004D78240400010C004D7862
+:10EAC00000002021241000100C004D7800002021AF
+:10EAD000001080421600FFFC00000000241000100F
+:10EAE0003202001E10400002000020212404000118
+:10EAF0000C004D78001080421600FFFA3202001E12
+:10EB00000C004DB9341080000C004DB9000000001D
+:10EB10000C004D58000000005040000500108042DD
+:10EB200097A2001C00501025A7A2001C00108042D4
+:10EB30001600FFF7000000000C004DB90000802116
+:10EB4000A7A0001C0C004D78240400012610000131
+:10EB50002E0200201440FFFB000000000C004D7846
+:10EB6000000020210C004D78240400010C004D7899
+:10EB7000240400010C004D78000020212410001016
+:10EB80000C004D7800002021001080421600FFFC90
+:10EB900000000000241000103202001E104000028D
+:10EBA00000002021240400010C004D780010804258
+:10EBB0001600FFFA3202001E0C004DB9341080001E
+:10EBC0000C004DB9000000000C004D580000000082
+:10EBD000504000050010804297A2001C00501025F4
+:10EBE000A7A2001C001080421600FFF700000000E2
+:10EBF0000C004DB90000802124020002A7A2001ED3
+:10EC00000C004D7824040001261000012E02002083
+:10EC10001440FFFB000000000C004D780000202194
+:10EC20000C004D78240400010C004D7800002021D8
+:10EC30000C004D7824040001241000100C004D78C5
+:10EC400000002021001080421600FFFC00000000A0
+:10EC5000241000103202001E10400002000020218B
+:10EC6000240400010C004D78001080421600FFFAC9
+:10EC70003202001E0C004D78240400010C004D7877
+:10EC8000000020213410800097A2001E00501024A4
+:10EC90001040000200002021240400010C004D78E7
+:10ECA000001080421600FFF8000000000C004DB973
+:10ECB00000008021A7A000200C004D782404000152
+:10ECC000261000012E0200201440FFFB000000006F
+:10ECD0000C004D78000020210C004D782404000128
+:10ECE0000C004D78240400010C004D780000202118
+:10ECF000241000100C004D780000202100108042EC
+:10ED00001600FFFC00000000241000103202001E5C
+:10ED10001040000200002021240400010C004D7866
+:10ED2000001080421600FFFA3202001E0C004DB99E
+:10ED3000341080000C004DB9000000000C004D584C
+:10ED400000000000504000050010804297A2002003
+:10ED500000501025A7A20020001080421600FFF7E7
+:10ED6000000000000C004DB900008021A7A0002089
+:10ED70000C004D7824040001261000012E02002012
+:10ED80001440FFFB000000000C004D780000202123
+:10ED90000C004D78240400010C004D78240400017F
+:10EDA0000C004D7800002021241000100C004D783C
+:10EDB00000002021001080421600FFFC000000002F
+:10EDC000241000103202001E10400002000020211A
+:10EDD000240400010C004D78001080421600FFFA58
+:10EDE0003202001E0C004DB9341080000C004DB9E9
+:10EDF000000000000C004D580000000050400005CD
+:10EE00000010804297A2002000501025A7A20020E9
+:10EE1000001080421600FFF7000000000C004DB902
+:10EE200000008021A7A000220C004D7824040001DE
+:10EE3000261000012E0200201440FFFB00000000FD
+:10EE40000C004D78000020210C004D7824040001B6
+:10EE50000C004D78000020210C004D7824040001A6
+:10EE6000241000100C004D7800002021001080427A
+:10EE70001600FFFC00000000241000100C004D786C
+:10EE800000002021001080421600FFFC000000005E
+:10EE90000C004D78240400010C004D780000202166
+:10EEA0003410800097A2002200501024104000026D
+:10EEB00000002021240400010C004D780010804245
+:10EEC0001600FFF8000000000C004DB90000000023
+:10EED00024040018240500020C004DDB2406000465
+:10EEE0003C1000018E106E24240200011602011D48
+:10EEF000000000003C02000194426F263C0100012A
+:10EF0000AC206E2424429FBC2C4200041040000C14
+:10EF100024040009240500010C004DDB2406040034
+:10EF200024040018240500010C004DDB24060020F9
+:10EF300024040018240500010C004DDB24062000E9
+:10EF40003C02400002421024104001233C022000F9
+:10EF50000242102410400004000000003C010001A7
+:10EF600010000003AC306F1C3C010001AC206F1C92
+:10EF70003C0300018C636F3424020005146200F925
+:10EF8000000000003C0200018C426F1C1040006732
+:10EF90003C0200040242102410400011A7A00018F7
+:10EFA0003C02000802421024104000022402020029
+:10EFB000A7A200183C0200100242102410400004D6
+:10EFC0000000000097A2001834420100A7A2001818
+:10EFD00097A600182404000910000004000028214E
+:10EFE0002404000900002821000030210C004DDB22
+:10EFF0000000000024020001A7A2001A3C02000841
+:10F00000024210241040000C3C0200020242102474
+:10F010001040000224020101A7A2001A3C020001D4
+:10F0200002421024104000053C02001097A2001A72
+:10F0300034420040A7A2001A3C02001002421024F1
+:10F040001040000E3C020002024210241040000555
+:10F050003C02000197A2001A34420080A7A2001AC5
+:10F060003C02000102421024104000053C0300A0B5
+:10F0700097A2001A34420020A7A2001A3C0300A065
+:10F0800002431024544300043C02002097A2001ABB
+:10F090001000000C344204000242102450400004CE
+:10F0A0003C02008097A2001A1000000634420800BB
+:10F0B00002421024104000040000000097A2001A31
+:10F0C00034420C00A7A2001A97A6001A24040004D8
+:10F0D0000C004DDB000028213C02000402421024F9
+:10F0E00010400004A7A0001C32425000144000044D
+:10F0F00000000000324240001040000500002021C6
+:10F100000C004CF902402021100000960000000085
+:10F1100097A6001C0000282134C612000C004DDB0D
+:10F12000A7A6001C1000008F00000000024210245F
+:10F1300010400004A7A00018324250001440000400
+:10F140000000000032424000104000053C02001068
+:10F150000C004CF90240202110000019A7A0001A51
+:10F1600002421024104000040000000097A2001882
+:10F1700010000004A7A2001897A200183442010052
+:10F18000A7A200183C020001024210241040000413
+:10F190000000000097A2001810000004A7A20018A9
+:10F1A00097A2001834422000A7A2001897A60018C2
+:10F1B000000020210C004DDB00002821A7A0001A30
+:10F1C000000080210C004D7824040001261000016D
+:10F1D0002E0200201440FFFB000000000C004D78C0
+:10F1E000000020210C004D78240400010C004D7813
+:10F1F000240400010C004D78000020212410001090
+:10F20000320200011040000200002021240400010D
+:10F210000C004D78001080421600FFFA3202000107
+:10F22000241000100C004D780000202100108042B6
+:10F230001600FFFC000000000C004DB934108000E7
+:10F240000C004DB9000000000C004D5800000000FB
+:10F25000504000050010804297A2001A005010256F
+:10F26000A7A2001A001080421600FFF7000000005D
+:10F270000C004DB900008021A7A0001A0C004D78A9
+:10F2800024040001261000012E0200201440FFFB80
+:10F29000000000000C004D78000020210C004D788B
+:10F2A000240400010C004D78240400010C004D786A
+:10F2B0000000202124100010320200011040000242
+:10F2C00000002021240400010C004D780010804231
+:10F2D0001600FFFA32020001241000100C004D78D5
+:10F2E00000002021001080421600FFFC00000000FA
+:10F2F0000C004DB9341080000C004DB90000000026
+:10F300000C004D58000000005040000500108042E5
+:10F3100097A2001A00501025A7A2001A00108042E0
+:10F320001600FFF7000000000C004DB900000000BF
+:10F330003C04000124846BCC97A6001897A7001A00
+:10F340003C0200018C426D983C0300018C636F1CF1
+:10F350003C05000D34A50205AFA200100C002B3BAC
+:10F36000AFA300148F830054240200043C01000169
+:10F37000AC226DD43C01000110000017AC236F38A3
+:10F380008F8300543C0200018C426F382463FF9C41
+:10F39000004310232C4200641440000F00000000C2
+:10F3A0008F820220240300053C010001AC236DD4B0
+:10F3B0003C03F7000043102510000007AF82022035
+:10F3C000240200063C010001AC226DD4240200118D
+:10F3D0003C010001AC226DD08FBF00348FB20030F1
+:10F3E0008FB1002C8FB0002803E0000827BD003843
+:10F3F00027BDFFD8AFB0001800808021AFB1001C3E
+:10F40000000088213202400010400013AFBF0020EE
+:10F410003C020010020210242C42000100021023C2
+:10F42000304341003C020001020210241440000657
+:10F43000347140003C020002020210241440000219
+:10F440003471600034714040000020210000282108
+:10F45000100000360220302132021000104000352A
+:10F4600000002021000028210C004DDB2406004074
+:10F4700024040018000028210C004DDB24060C0099
+:10F4800024040017000028210C004DDB2406040092
+:10F4900024040016000028210C004DDB2406000681
+:10F4A00024040017000028210C004DDB2406250051
+:10F4B00024040016000028210C004DDB2406000661
+:10F4C00024040017000028210C004DDB2406460010
+:10F4D00024040016000028210C004DDB2406000641
+:10F4E00024040017000028210C004DDB24066700CF
+:10F4F00024040016000028210C004DDB2406000621
+:10F500002404001F000028210C004DDB24060010FD
+:10F5100024040009000028210C004DDB24061500FE
+:10F52000240400090000282124061D000C004DDBE6
+:10F53000000000003C04000124846BF03C05000E38
+:10F5400034A501000200302102203821AFA00010B4
+:10F550000C002B3BAFA000148FBF00208FB1001C0C
+:10F560008FB0001803E0000827BD00288F850044F5
+:10F570008F8200443C030001004310253C03000837
+:10F58000AF8200448F8400548F82005400A328244B
+:10F5900010000002248400018F8200540082102396
+:10F5A0002C4200021440FFFC000000008F82004447
+:10F5B0003C03FFFE3463FFFF00431024AF8200448E
+:10F5C0008F8300548F8200541000000224630001D6
+:10F5D0008F820054006210232C4200021440FFFC72
+:10F5E0000000000003E0000800A010218F83004409
+:10F5F0003C02FFF03442FFFF000424800062182424
+:10F600003C0200020082202500641825AF830044DC
+:10F610008F8200443C03FFFE3463FFFF004310244D
+:10F62000AF8200448F8300548F8200541000000288
+:10F63000246300018F820054006210232C420002D8
+:10F640001440FFFC000000008F8200443C030001D6
+:10F6500000431025AF8200448F8300548F820054F2
+:10F6600010000002246300018F8200540062102306
+:10F670002C4200021440FFFC0000000003E00008E0
+:10F68000000000008F8200442403FF7F0043102409
+:10F69000AF8200448F8300548F8200541000000218
+:10F6A000246300018F820054006210232C42000268
+:10F6B0001440FFFC000000008F82004434420080B0
+:10F6C000AF8200448F8300548F82005410000002E8
+:10F6D000246300018F820054006210232C42000238
+:10F6E0001440FFFC0000000003E0000800000000E0
+:10F6F0008F8200443C03FFF03463FFFF004310247B
+:10F70000AF8200448F8200443C0300010043102577
+:10F71000AF8200448F8300548F8200541000000297
+:10F72000246300018F820054006210232C420002E7
+:10F730001440FFFC000000008F8200443C03FFFEE9
+:10F740003463FFFF00431024AF8200448F830054D2
+:10F750008F82005410000002246300018F82005445
+:10F76000006210232C4200021440FFFC0000000045
+:10F7700003E000080000000027BDFFC8AFB300246D
+:10F7800000809821AFBE002C00A0F021AFB2002075
+:10F7900000C0902133C2FFFFAFBF0030AFB50028DB
+:10F7A000AFB1001CAFB0001814400034A7B2001075
+:10F7B0003271FFFF27B20010000080210C004D784D
+:10F7C00024040001261000012E0200201440FFFB3B
+:10F7D000000000000C004D78000020210C004D7846
+:10F7E000240400010C004D78000020210C004D780D
+:10F7F0002404000124100010320200011040000215
+:10F8000000002021240400010C004D7800108042EB
+:10F810001600FFFA320200012410001002301024FA
+:10F820001040000200002021240400010C004D784B
+:10F83000001080421600FFFA023010240C004D78B0
+:10F84000240400010C004D780000202134108000B9
+:10F8500096420000005010241040000200002021B9
+:10F86000240400010C004D78001080421200007545
+:10F87000000000001000FFF6000000003275FFFFDE
+:10F8800027B10010A7A00010000080210C004D78C7
+:10F8900024040001261000012E0200201440FFFB6A
+:10F8A000000000000C004D78000020210C004D7875
+:10F8B000240400010C004D78240400010C004D7854
+:10F8C000000020212410001032020001104000022C
+:10F8D00000002021240400010C004D78001080421B
+:10F8E0001600FFFA320200012410001002B01024AA
+:10F8F0001040000200002021240400010C004D787B
+:10F90000001080421600FFFA02B010240C004DB91E
+:10F91000341080000C004DB9000000000C004D5860
+:10F9200000000000504000050010804296220000B8
+:10F9300000501025A6220000001080421600FFF79C
+:10F94000000000000C004DB90000000033C5FFFFAF
+:10F950002402000154A200042402000297A2001015
+:10F96000100000060052102514A200063271FFFF9D
+:10F9700097A200100012182700431024A7A200101D
+:10F980003271FFFF27B20010000080210C004D787B
+:10F9900024040001261000012E0200201440FFFB69
+:10F9A000000000000C004D78000020210C004D7874
+:10F9B000240400010C004D78000020210C004D783B
+:10F9C0002404000124100010320200011040000243
+:10F9D00000002021240400010C004D78001080421A
+:10F9E0001600FFFA32020001241000100230102429
+:10F9F0001040000200002021240400010C004D787A
+:10FA0000001080421600FFFA023010240C004D78DE
+:10FA1000240400010C004D780000202134108000E7
+:10FA200096420000005010241040000200002021E7
+:10FA3000240400010C004D78001080421600FFF8ED
+:10FA4000000000000C004DB9000000008FBF003026
+:10FA50008FBE002C8FB500288FB300248FB20020FA
+:10FA60008FB1001C8FB0001803E0000827BD0038DC
+:10FA700000000000000000000000000027BDFFE8BB
+:10FA8000AFBF00108EE304B824020008146201E046
+:10FA9000000000003C0200018C426F1C1440000575
+:10FAA000000000000C003DAF8F840224100001D83C
+:10FAB000000000008F8202203C0300080043102455
+:10FAC00010400026240200018F8402248F8202202D
+:10FAD0003C03040000431024104000060000000016
+:10FAE0003C010002AC208FA03C0100021000000B82
+:10FAF000AC208FC03C03000224638FA08C62000006
+:10FB000024420001AC6200002C42000214400003B9
+:10FB1000240200013C010002AC228FC03C02000222
+:10FB20008C428FC01040000630820040104000041C
+:10FB3000240200013C01000210000003AC228FC42B
+:10FB40003C010002AC208FC43C010002AC248F9C1D
+:10FB50003C0100021000000BAC208FD03C010002E1
+:10FB6000AC228FD03C010002AC208FC03C010002CF
+:10FB7000AC208FA03C010002AC208FC43C010002ED
+:10FB8000AC208F9C3C0300028C638F903C020002EF
+:10FB90008C428F94506200042463FFFF3C010002FA
+:10FBA000AC238F942463FFFF2C62000E104001945D
+:10FBB000000310803C010001002208218C226C000F
+:10FBC0000040000800000000240200023C01000286
+:10FBD000AC208FC03C010002AC208FA03C01000291
+:10FBE000AC208F9C3C010002AC208FC43C01000281
+:10FBF000AC208FB83C010002AC208FB0AF80022453
+:10FC00003C010002AC228F903C0200028C428FD05B
+:10FC10001440004F3C02FDFF3442FFFF0C003DAF9B
+:10FC20000282A024AF8002048F8202002403FFFD21
+:10FC300000431024AF8202003C010002AC208FE0A0
+:10FC40008F8300543C0200028C428FB824040001D0
+:10FC50003C010002AC248FCC244200013C01000294
+:10FC6000AC228FB82C4200043C010002AC238FB4BC
+:10FC700014400006240200033C010001AC246D9CEA
+:10FC80003C0100021000015EAC208FB83C01000274
+:10FC90001000015BAC228F908F8300543C02000265
+:10FCA0008C428FB42463D8F0004310232C422710D9
+:10FCB00014400003240200043C010002AC228F9097
+:10FCC0003C0200028C428FD0144000213C02FDFF18
+:10FCD0003442FFFF1000014A0282A0243C040001CC
+:10FCE0008C846F203C0100020C005084AC208FA853
+:10FCF0003C0200028C428FDCAF8202043C02000214
+:10FD00008C428FD0144000123C03FDFF8F8202040E
+:10FD10003463FFFF304200301440012F0283A024DF
+:10FD20003C0300028C638FDC240200053C010002CE
+:10FD3000AC228F903C01000210000131AC238FE017
+:10FD40003C0200028C428FD0104000103C02FDFFAC
+:10FD50003C0200018C426E3C244200013C01000147
+:10FD6000AC226E3C2C42000214400125240200010A
+:10FD70003C010001AC226E443C010001AC206E3C11
+:10FD80003C0100011000011EAC226D9C3C030002EE
+:10FD90008C638FC03442FFFF106001190282A024DF
+:10FDA0003C0200028C428F9C1040011500000000B4
+:10FDB0003C010002AC228FC8240200033C01000277
+:10FDC000AC228FA0100000B8240200063C01000203
+:10FDD000AC208FA88F82020434420040AF8202041C
+:10FDE0003C0200028C428FE0240300073C01000229
+:10FDF000AC238F90344200403C010002AC228FE0E3
+:10FE00003C0200028C428FC0104000050000000040
+:10FE10003C0200028C428F9C104000F02402000241
+:10FE20003C05000224A58FA08CA200002C424E218C
+:10FE3000104000EA240200023C0200028C428FC4FF
+:10FE4000104000EF2404FFBF3C0200028C428F9C54
+:10FE50003C0300028C638FC8004410240064182403
+:10FE600010430004240200013C010002100000E4E1
+:10FE7000AC228F9024020003ACA2000024020008F0
+:10FE80003C010002AC228F903C0200028C428FCCDD
+:10FE90001040000C240200013C0400020C005091B0
+:10FEA0008C848F9C3C0200028C428FE81440000539
+:10FEB000240200013C0200028C428FE41040000644
+:10FEC000240200013C010001AC226D9C3C010002B7
+:10FED000100000CBAC208FB83C0200028C428FB0E7
+:10FEE0003C0300028C638F9C2C420001000210C076
+:10FEF000306300083C010002AC228FB03C010002DC
+:10FF0000AC238FAC8F830054240200093C01000213
+:10FF1000AC228F903C010002100000B9AC238FB4DA
+:10FF20008F8300543C0200028C428FB42463D8F0CB
+:10FF3000004310232C4227101440009F00000000B3
+:10FF40003C0200028C428FC01040000500000000FF
+:10FF50003C0200028C428F9C104000A02402000250
+:10FF60003C03000224638FA08C6200002C424E21CF
+:10FF70001040009A240200023C0200028C428FCC06
+:10FF80001040000E000000003C0200028C428F9CDA
+:10FF90003C010002AC208FCC304200801040002F8A
+:10FFA0002402000C8F820204304200801440000CB6
+:10FFB00024020003100000292402000C3C0200026D
+:10FFC0008C428F9C304200801440000524020003C4
+:10FFD0008F820204304200801040001F2402000380
+:10FFE000AC6200002402000A3C010002AC228F90A7
+:10FFF0003C04000224848FD88C8200003C03000261
+:020000021000EC
+:100000008C638FB000431025AF8202048C83000004
+:100010003C0400028C848FB02402000B3C010002DF
+:10002000AC228F90006418253C010002AC238FE0C5
+:100030003C05000224A58FA08CA200002C424E217A
+:1000400010400066240200023C0200028C428FD065
+:1000500010400005000000002402000C3C010002DA
+:1000600010000067AC228F903C0200028C428FC0CF
+:1000700010400063000000003C0400028C848F9C50
+:1000800010800055308200083C0300028C638FAC66
+:100090001062005B240200033C010002AC248FC804
+:1000A000ACA20000240200063C0100021000005433
+:1000B000AC228F908F82020034420002AF82020095
+:1000C0008F8300542402000D3C010002AC228F906B
+:1000D0003C010002AC238FB48F8300543C02000229
+:1000E0008C428FB42463D8F0004310232C42271095
+:1000F00014400031000000003C0200028C428FD00E
+:10010000104000202402000E3C0300028C638FE4A8
+:100110003C01000214600015AC228F900C003E6D73
+:10012000000000003C0500018CA56D980C00529B5E
+:10013000000020213C0300018C636D982402000420
+:10014000146200052403FFFB3C0200018C426D9405
+:10015000100000032403FFF73C0200018C426D9461
+:10016000004310243C010001AC226D948F830224D3
+:100170003C0202003C010002AC238FEC1000002086
+:100180000282A0253C0200028C428FC01040000574
+:10019000000000003C0200028C428F9C1040000FC7
+:1001A000240200023C0200028C428FA02C424E210D
+:1001B0001040000A240200023C0200028C428FC060
+:1001C0001040000F000000003C0200028C428F9C97
+:1001D0001440000B00000000240200023C01000259
+:1001E00010000007AC228F903C0200028C428FC0AE
+:1001F00010400003000000000C003DAF00000000B4
+:100200008F8202203C03F70000431025AF820220BA
+:100210008FBF001003E0000827BD00183C03000258
+:1002200024638FE88C6200001040000534422000F7
+:100230003C010002AC228FDC10000003AC60000027
+:100240003C010002AC248FDC03E000080000000049
+:1002500027BDFFE030820030AFBF00183C01000234
+:10026000AC228FE4144000673C02FFFF34421F0EB3
+:1002700000821024144000612402003030822000EB
+:100280001040005D3083800000031A0230820001BC
+:10029000000212003C0400018C846F2000621825CB
+:1002A000000331C23C03000124636E4830828000A9
+:1002B00000021202308400010004220000441025D4
+:1002C000000239C2000610800043102100471021AF
+:1002D000904300002402000110620025000000008D
+:1002E00010600007240200021062001324020003C1
+:1002F0001062002C3C05000F1000003700000000C9
+:100300008F8202002403FEFF00431024AF8202000C
+:100310008F8202203C03FFFE3463FFFF0043102462
+:10032000AF8202203C010002AC2090043C0100029C
+:1003300010000034AC20900C8F8202003442010087
+:10034000AF8202008F8202203C03FFFE3463FFFF76
+:1003500000431024AF820220240201003C0100026D
+:10036000AC2290043C01000210000026AC20900C4E
+:100370008F8202002403FEFF00431024AF8202009C
+:100380008F8202203C03000100431025AF8202202F
+:100390003C010002AC2090043C0100021000001956
+:1003A000AC23900C8F82020034420100AF82020025
+:1003B0008F8202203C03000100431025AF820220FF
+:1003C000240201003C010002AC2290043C01000226
+:1003D0001000000CAC23900C34A5FFFF3C0400017E
+:1003E00024846C38AFA300100C002B3BAFA000148A
+:1003F0001000000400000000240200303C01000254
+:10040000AC228FE88FBF001803E0000827BD002052
+:1004100000000000000000000000000027BDFFC831
+:10042000AFB2002800809021AFB3002C00A098212B
+:10043000AFB0002000C080213C04000124846C5037
+:100440003C0500093C0200018C426D9834A59001E6
+:100450000240302102603821AFBF0030AFB100242C
+:10046000A7A0001AAFB000140C002B3BAFA20010E5
+:1004700024020002126200832E6200031040000575
+:10048000240200011262000A000000001000017343
+:100490000000000024020004126200F82402000898
+:1004A000126200F73C02FFEC1000016C000000003B
+:1004B0003C0200018C426D94304200021440000462
+:1004C000001289403C02FFFB3442FFFF02028024FD
+:1004D0003C01000200310821AC308FFC3C0240009E
+:1004E000020210241040004E001023C2308400305D
+:1004F000001013823042001C3C03000124636DD8BD
+:1005000000431021008238213C0200200202102406
+:1005100010400006240201003C01000200310821C5
+:10052000AC229000100000053C0200803C0100025B
+:1005300000310821AC2090003C020080020210240F
+:1005400010400006001219403C0200013C0100026C
+:100550000023082110000005AC2290080012114071
+:100560003C01000200220821AC20900894E4000025
+:100570003C0300018C636F402402000510620010F0
+:10058000A7A400183202400010400002348240004C
+:10059000A7A200182404000194E20002240500042C
+:1005A00024E60002344200010C0045BEA4E2000231
+:1005B00024040001000028210C0045BE27A60018D5
+:1005C0003C0200018C426D98241100013C010001A5
+:1005D000AC316DA414530004320280000C003DAF16
+:1005E00000000000320280001040011C00000000EA
+:1005F0000C003DAF000000003C0300018C636F4025
+:100600002402000510620115240200023C010001D1
+:10061000AC316D9C3C01000110000110AC226D98C2
+:10062000240400012405000427B0001A0C0045BE74
+:100630000200302124040001000028210C0045BEE6
+:10064000020030213C020002005110218C428FF444
+:100650003C0400018C846D983C03BFFF3463FFFFB2
+:100660003C010001AC336DA4004310243C010002A6
+:1006700000310821109300F7AC228FF4100000F72E
+:10068000000000003C02200002021024104000057F
+:10069000240200013C010001AC226F1C1000000488
+:1006A000001289403C010001AC206F1C00128940FF
+:1006B0003C01000200310821AC308FF83C024000C0
+:1006C0000202102414400014000000003C0200014B
+:1006D0008C426F1C10400006240400042405000115
+:1006E0000C004DDB2406200024020001AEE204B819
+:1006F0003C020002005110218C428FF03C03BFFFEE
+:100700003463FFFF004310243C0100020031082144
+:10071000100000D0AC228FF03C0200018C426F1C14
+:10072000104000283C0300A0020310245443000D95
+:100730003C0200203C0200018C426F202403010097
+:100740003C01000200310821AC2390043C0300016D
+:100750003C01000200310821AC23900C1000001570
+:100760003442040002021024104000082403010057
+:100770003C0200018C426F203C0100020031082144
+:10078000AC2390041000000B344208003C020080AF
+:10079000020210241040002E3C0300013C02000124
+:1007A0008C426F203C01000200310821AC23900CE8
+:1007B00034420C003C010001AC226F2010000025E7
+:1007C000240400013C020020020210241040000614
+:1007D000240201003C01000200310821AC229004F7
+:1007E000100000053C0200803C010002003108219D
+:1007F000AC2090043C02008002021024104000074C
+:10080000001219403C0200013C01000200230821B3
+:10081000AC22900C100000062404000100121140CC
+:100820003C01000200220821AC20900C24040001AD
+:100830000000282127B0001E0C00457C020030215A
+:1008400024040001000028210C00457C0200302116
+:10085000240400012405000127B0001C0C00457C85
+:100860000200302124040001240500010C00457C15
+:100870000200302110000077000000003C02FFEC75
+:100880003442FFFF020280243C020008020280255D
+:10089000001211403C01000200220821AC308FF808
+:1008A0003C02200002021024104000090000000059
+:1008B0003C0200018C426E441440000524020001F9
+:1008C0003C010001AC226F1C100000043C024000FF
+:1008D0003C010001AC206F1C3C02400002021024CD
+:1008E0001440001D24020E013C0300018C636F1CA8
+:1008F000AF8202383C010001AC206DB010600005F1
+:10090000240220203C010001AC226F2024020001BF
+:10091000AEE204B83C04BFFF001219403C020002E2
+:10092000004310218C428FF03C0500018CA56D988E
+:100930003484FFFF004410243C01000200230821FE
+:10094000AC228FF02402000110A20044000000003D
+:1009500010000040000000003C0200018C426F1CAF
+:100960001040001C240220003C010001AC226F203A
+:100970003C0300A0020310241443000500121140A0
+:100980003402A0003C0100011000002DAC226F20B9
+:100990003C030002006218218C638FF83C020020A7
+:1009A0000062102410400004240220013C010001D8
+:1009B00010000023AC226F203C0200800062102453
+:1009C0001040001F3402A0013C0100011000001C77
+:1009D000AC226F203C0200200202102410400007CD
+:1009E00000121940240201003C01000200230821EA
+:1009F000AC229004100000063C020080001211405E
+:100A00003C01000200220821AC2090043C0200803E
+:100A10000202102410400006001219403C0200019E
+:100A20003C0100020023082110000005AC22900CBC
+:100A3000001211403C01000200220821AC20900C61
+:100A40003C0300018C636D982402000110620003D6
+:100A5000000000000C003DAF000000008FBF003020
+:100A60008FB3002C8FB200288FB100248FB00020EC
+:100A700003E0000827BD003827BDFFB0AFB3003C3E
+:100A800000009821AFB500400000A821AFB10034AC
+:100A90000000882124020002AFBF0048AFBE00441E
+:100AA000AFB20038AFB00030AFA4002CA7A0001A3E
+:100AB000A7A00018A7A00020A7A0001EA7A00022A2
+:100AC00010A20130A7A0001C2CA2000310400005BA
+:100AD0002402000110A2000A3C0240001000025D46
+:100AE000022010212402000410A2020A240200089D
+:100AF00010A202080220102110000256000000007F
+:100B00008FA8002C000881403C03000200701821CF
+:100B10008C638FFC0062102414400009240400013F
+:100B20003C027FFF3442FFFF006288243C01000248
+:100B300000300821AC318FF4100002460220102151
+:100B4000240500010C00457C27A6001824040001A0
+:100B5000240500010C00457C27A6001897A2001868
+:100B600030420004104000D93C1140003C0200011A
+:100B70008C426F402443FFFF2C620006104000D9D6
+:100B8000000310803C010001002208218C226C68C7
+:100B900000400008000000002404000124050011AA
+:100BA00027B0001A0C00457C02003021240400010B
+:100BB000240500110C00457C0200302197A3001A87
+:100BC00030624000104000023C1500103C15000847
+:100BD00030628000104000AA3C130001100000A801
+:100BE0003C130002240400012405001427B0001A5D
+:100BF0000C00457C0200302124040001240500146F
+:100C00000C00457C0200302197A3001A30621000CE
+:100C1000104000023C1500103C150008306208002E
+:100C2000104000973C130001100000953C13000297
+:100C3000240400012405001927B0001C0C00457C89
+:100C40000200302124040001240500190C00457C19
+:100C50000200302197A2001C304307002402040048
+:100C600010620027286204011040000E24020200D6
+:100C70001062001F286202011040000524020100DA
+:100C80005062001E3C1300011000001E24040001ED
+:100C900024020300506200193C13000210000019E6
+:100CA00024040001240206001062000D28620601DF
+:100CB00010400005240205005062000B3C130002A6
+:100CC0001000001024040001240207001462000D2B
+:100CD000240400013C1300041000000A3C15000825
+:100CE000100000063C130004100000053C1500082D
+:100CF0003C130001100000023C1500083C150010D8
+:100D0000240400012405001827B0001E0C00457CB7
+:100D10000200302124040001240500180C00457C49
+:100D2000020030218FA8002C97A7001E0008114058
+:100D30003C06000200C230218CC68FF497A200222C
+:100D40003C10000126106C5C02002021AFA20010B4
+:100D500097A2001C3C05000C34A503030C002B3BA0
+:100D6000AFA200143C020004166200103C02000115
+:100D70008F84005424030001240200023C0100017E
+:100D8000AC236D9C3C010001AC226D983C0100013C
+:100D9000AC236DA43C010001AC236E243C01000196
+:100DA000AC246F301000004F02B388251662003962
+:100DB0003C0280003C0200018C426E201440001E68
+:100DC0002404001800002021000028210C004DDB25
+:100DD000340680008F8300548F82005402B388252C
+:100DE00010000002246300328F820054006210233E
+:100DF0002C4200331440FFFC000000008F8300549D
+:100E0000240200013C010001AC226E203C010001E3
+:100E1000AC226D9C3C010001AC226D983C010001AC
+:100E2000AC226DA43C010001AC226E243C01000107
+:100E30001000002CAC236F30000028210C004DDB8B
+:100E400024060404000020212405001E27A6001803
+:100E5000240200020C0045BEA7A2001800002021B9
+:100E60000000282127A600180C0045BEA7A00018E6
+:100E700024040018240500020C004DDB24060004A5
+:100E80003C0280000222102502B318251000001534
+:100E90000043882502221025027518250043882565
+:100EA0000200202197A6001C3C0700018CE76D98EA
+:100EB0003C05000C34A50326AFB300100C002B3BFF
+:100EC000AFB1001410000007000000003C11000248
+:100ED000023088218E318FFC3C027FFF3442FFFFBD
+:100EE000022288243C0200018C426DA81040001EA2
+:100EF000000000003C0200018C426F1C1040000208
+:100F00003C022000022288258FA8002C00081140F6
+:100F10003C010002002208218C22900010400003B6
+:100F20003C02002010000005022288253C02FFDF61
+:100F30003442FFFF022288248FA8002C00081140B1
+:100F40003C010002002208218C229008104000037E
+:100F50003C02008010000004022288253C02FF7F32
+:100F60003442FFFF022288248FA8002C0008114081
+:100F70003C01000200220821AC318FF41000013541
+:100F8000022010218FA8002C0008F1403C03000231
+:100F9000007E18218C638FF83C0240000062102410
+:100FA00014400009240400013C027FFF3442FFFF8B
+:100FB000006288243C010002003E0821AC318FF021
+:100FC0001000012402201021000028210C00457C83
+:100FD00027A6001824040001000028210C00457CED
+:100FE00027A60018240400012405000127B20020D0
+:100FF0000C00457C0240302124040001240500013E
+:101000000C00457C0240302124040001240500042A
+:1010100027B1001E0C00457C022030212404000171
+:10102000240500040C00457C02203021240400012A
+:101030002405000527B000220C00457C0200302169
+:1010400024040001240500050C00457C0200302129
+:1010500024040001240500100C00457C27A600187C
+:1010600024040001240500100C00457C27A600186C
+:10107000240400012405000A0C00457C02403021B4
+:10108000240400012405000A0C00457C02403021A4
+:1010900024040001240500180C00457C02203021A6
+:1010A00024040001240500180C00457C0220302196
+:1010B00024040001240500010C00457C27A600182B
+:1010C00024040001240500010C00457C27A600181B
+:1010D00097A2001830420004104000663C11400006
+:1010E0003C0300018C636F34240200051462006726
+:1010F000240400012405001927B0001C0C00457CC5
+:101100000200302124040001240500190C00457C54
+:101110000200302197A2001C304307002402040083
+:1011200010620027286204011040000E2402020011
+:101130001062001F28620201104000052402010015
+:101140005062001E3C1300011000001E3C0200040F
+:1011500024020300506200193C1300021000001921
+:101160003C020004240206001062000D2862060101
+:1011700010400005240205005062000B3C130002E1
+:10118000100000103C020004240207001462000D4D
+:101190003C0200043C1300041000000A3C15000847
+:1011A000100000063C130004100000053C15000868
+:1011B0003C130001100000023C1500083C15001013
+:1011C0003C020004126200173C0280008F8200542F
+:1011D000241000013C010001AC306D9C3C01000179
+:1011E000AC306D983C010001AC306DA43C010001B5
+:1011F000AC306E243C010001AC226F303C02000197
+:101200001662002202758825000020210000282196
+:101210000C004DDB340680003C0100011000001B77
+:10122000AC306E200222102502B318250043882519
+:1012300097A6001C3C0200018C426F1C3C07000179
+:101240008CE76D983C04000124846C5CAFA2001014
+:1012500097A2001E3C05000C34A503233C010001AD
+:10126000AC206E200C002B3BAFA200141000000736
+:10127000000000003C110002023E88218E318FF0F8
+:101280003C027FFF3442FFFF022288243C0200011F
+:101290008C426DA810400069000000003C02000173
+:1012A0008C426F1C104000023C0220000222882564
+:1012B0008FA8002C000811403C01000200220821E8
+:1012C0008C229004104000033C0200201000000516
+:1012D000022288253C02FFDF3442FFFF02228824DD
+:1012E0008FA8002C000811403C01000200220821B8
+:1012F0008C22900C104000033C0200801000004F34
+:10130000022288253C02FF7F3442FFFF1000004B81
+:10131000022288248FA8002C000829403C030002E8
+:10132000006518218C638FF83C0240000062102495
+:10133000144000083C027FFF3442FFFF0062882413
+:101340003C01000200250821AC318FF01000004163
+:10135000022010213C0200018C426DA81040003494
+:101360003C11C00C3C0200018C426E443C04C00C99
+:10137000348420003C0300018C636F1C0002102B9E
+:10138000000210230044102410600003005188253F
+:101390003C022000022288253C0200020045102168
+:1013A0008C429004104000033C0200201000000416
+:1013B000022288253C02FFDF3442FFFF02228824FC
+:1013C0008FA8002C000811403C01000200220821D7
+:1013D0008C22900C104000033C020080100000049E
+:1013E000022288253C02FF7F3442FFFF022288242C
+:1013F0003C0200018C426E30104000023C020800AA
+:10140000022288253C0200018C426E34104000020A
+:101410003C020400022288253C0200018C426E3806
+:10142000104000063C020100100000040222882542
+:101430003C027FFF3442FFFF006288248FA8002C0B
+:10144000000811403C01000200220821AC318FF05D
+:10145000022010218FBF00488FBE00448FB500408E
+:101460008FB3003C8FB200388FB100348FB00030A2
+:1014700003E0000827BD005027BDFFD0AFB2002811
+:1014800000809021AFBF002CAFB10024AFB000208E
+:101490008F8402003C1000018E106D988F86022010
+:1014A000240200021202005C2E020003104000051C
+:1014B000240200011202000A001219401000010C5F
+:1014C0000000000024020004120200BF24020008F1
+:1014D000120200BE00128940100001050000000049
+:1014E0003C05000200A328218CA58FFC3C100002C3
+:1014F000020380218E108FF43C02400000A21024D1
+:10150000104000383C020008020210241040002065
+:10151000348400023C020002004310218C429000FF
+:101520001040000534840020348401003C02002077
+:1015300010000006020280252402FEFF0082202403
+:101540003C02FFDF3442FFFF020280240012114000
+:101550003C010002002208218C2290081040000566
+:101560003C02000100C230253C0200801000001641
+:10157000020280253C02FFFE3442FFFF00C23024FD
+:101580003C02FF7F3442FFFF1000000F0202802464
+:101590002402FEDF008220243C02FFFE3442FFFFD3
+:1015A00000C230243C02FF5F3442FFFF020280246D
+:1015B0003C01000200230821AC2090003C01000205
+:1015C00000230821AC209008AF840200AF860220DF
+:1015D0008F82022034420002AF8202201000000AF3
+:1015E000001211403C02BFFF3442FFFF8F83020014
+:1015F000020280242402FFFD006218240C003DAF8B
+:10160000AF830200001211403C01000200220821B9
+:10161000100000B7AC308FF43C0200018C426F1C0C
+:101620001040006924050004240400010C00457CDE
+:1016300027A6001824040001240500050C00457CA1
+:1016400027A6001A97A3001897A2001A3C040001CD
+:1016500024846E4830630C0000031A8230420C0070
+:1016600000021282A7A2001A00021080004410217A
+:1016700000431021A7A30018904800002402000195
+:101680003103FFFF106200292862000210400005AC
+:101690000000000010600009000000001000003D84
+:1016A0000000000010700013240200031062002CE0
+:1016B0000000000010000037000000008F820200D0
+:1016C0002403FEFF00431024AF8202008F82022019
+:1016D0003C03FFFE3463FFFF00431024AF8202206F
+:1016E0003C010002AC2090043C01000210000032DA
+:1016F000AC20900C8F82020034420100AF820200C5
+:101700008F8202203C03FFFE3463FFFF004310245E
+:10171000AF820220240201003C010002AC229004AE
+:101720003C01000210000024AC20900C8F820200CB
+:101730002403FEFF00431024AF8202008F820220A8
+:101740003C03000100431025AF8202203C0100024F
+:10175000AC2090043C01000210000017AC23900C58
+:101760008F82020034420100AF8202008F82022089
+:101770003C03000100431025AF8202202402010037
+:101780003C010002AC2290043C0100021000000A5F
+:10179000AC23900C3C04000124846C8097A6001AB2
+:1017A00097A700183C05000134A5FFFFAFA8001063
+:1017B0000C002B3BAFA000148F82020034420002C9
+:1017C0001000004BAF820200001289403C0500026D
+:1017D00000B128218CA58FF83C1000020211802155
+:1017E0008E108FF03C02400000A210241440001024
+:1017F000000000003C0200018C426F1C14400005F8
+:101800003C02BFFF8F82020034420002AF8202001E
+:101810003C02BFFF3442FFFF0C003DAF02028024B8
+:101820003C0100020031082110000031AC308FF083
+:101830003C0200018C426F1C104000053C0200205D
+:101840003C0200018C426E44104000253C02002006
+:1018500000A210241040000734840020240201005C
+:101860003C01000200310821AC2290041000000667
+:10187000348401003C01000200310821AC209004B6
+:101880002402FEFF008220243C02008000A21024DB
+:1018900010400007001219403C0200013C01000208
+:1018A00000230821AC22900C1000000800C2302553
+:1018B000001211403C01000200220821AC20900CD3
+:1018C0003C02FFFE3442FFFF00C23024AF8402001E
+:1018D000AF8602208F82022034420002AF820220B3
+:1018E000001211403C01000200220821AC308FF0B0
+:1018F0008FBF002C8FB200288FB100248FB0002042
+:1019000003E0000827BD003000000000000018219F
+:10191000308400FF2405FFDF2406FFBF00641007AA
+:101920003042000110400004000000008F8200449B
+:1019300010000003344200408F820044004610240F
+:10194000AF8200448F82004434420020AF820044C2
+:101950008F82004400451024AF82004424630001BC
+:10196000286200085440FFEE0064100703E00008FE
+:10197000000000002C8200081040001B0000000046
+:101980002405FFDF2406FFBF000418803C0200018D
+:1019900024426E60006218212464000490620000FA
+:1019A00010400004000000008F820044100000037B
+:1019B000344200408F82004400461024AF8200442D
+:1019C0008F82004434420020AF8200448F82004462
+:1019D00000451024AF820044246300010064102BF2
+:1019E0001440FFEE0000000003E0000800000000CB
+:1019F0000000000000000000000000008F8400C410
+:101A00008F8600E08F8700E42402FFF800C22824BC
+:101A100010E5001A27623FF814E2000224E80008EB
+:101A200027683000550500048D0A000030C200040C
+:101A300014400012008050218CE900008F42013CCC
+:101A4000014948230049182B94EB0006106000025E
+:101A500025630050004948210123182B5040000302
+:101A60008F4201FC03E0000800E01021AF8800E88D
+:101A700024420001AF4201FCAF8800E403E000080B
+:101A80000000102103E00008000000008F8300E444
+:101A900027623FF81062000424620008AF8200E869
+:101AA00003E00008AF8200E427623000AF8200E864
+:101AB00003E00008AF8200E403E00008000000003B
+:101AC0000000000000000000000000008F880120DE
+:101AD00027624FE08F8301281502000225090020AC
+:101AE00027694800112300128FA20010AD040000E6
+:101AF000AD050004AD060008A507000E8FA3001475
+:101B0000AD0200188FA20018AD03001C25030016BB
+:101B1000AD020010AD030014AF8901208F4300FC1B
+:101B2000240200012463FFFF03E00008AF4300FC30
+:101B30008F430324000010212463000103E0000808
+:101B4000AF43032403E00008000000008F88010079
+:101B5000276247E08F830108150200022509002053
+:101B6000276940001123000F8FA20010AD04000070
+:101B7000AD050004AD060008A507000E8FA30014F4
+:101B8000AD0200188FA20018AD03001C250300163B
+:101B9000AD020010AD030014AF89010003E000089E
+:101BA000240200018F430328000010212463000158
+:101BB00003E00008AF43032803E000080000000032
+:101BC00000000000000000000000000024486561E3
+:101BD0006465723A202F70726F6A656374732F7236
+:101BE00063732F73772F67652F2E2F6E69632F66B0
+:101BF00077322F636F6D6D6F6E2F66776D61696ED3
+:101C00002E632C7620312E312E322E343520313970
+:101C100039392F30312F32342030303A31303A35A3
+:101C20003520736875616E67204578702024000048
+:101C3000657674526E674600516576744600000002
+:101C400051657674505F46004D657674526E6746F6
+:101C5000000000004D516576744600004D516576D8
+:101C6000505F46005173436F6E495F4600000000AD
+:101C70005173436F6E734600517250726F64460029
+:101C80006261644D656D537A0000000068775665A7
+:101C900072000000626164487756657200000000BF
+:101CA0002A2A4441574E5F41000000007478527860
+:101CB0004266537A00000000626641746E4D726B9A
+:101CC000000000007265645A6F6E6531000000000C
+:101CD000706369436F6E660067656E436F6E660082
+:101CE0002A646D615244666C000000002A50414E27
+:101CF00049432A002E2E2F2E2E2F2E2E2F2E2E2F02
+:101D00002E2E2F7372632F6E69632F6677322F63C7
+:101D10006F6D6D6F6E2F66776D61696E2E6300005B
+:101D2000726362466C616773000000006261645216
+:101D30007852636200000000676C6F62466C6773E4
+:101D4000000000002B5F646973705F6C6F6F700040
+:101D50002B65765F68616E646C65720063616E749A
+:101D600031446D61000000002B715F646D615F7430
+:101D70006F5F6E69635F636B73756D002B685F7374
+:101D8000656E645F646174615F72656164795F63ED
+:101D90006B73756D000000002B685F646D615F728E
+:101DA000645F6173736973745F636B73756D000057
+:101DB00074436B736D4F6E002B715F646D615F7464
+:101DC0006F5F6E69630000002B685F73656E645F10
+:101DD000646174615F726561647900002B685F649F
+:101DE0006D615F72645F61737369737400000000FA
+:101DF00074436B736D4F6666000000002B685F7361
+:101E0000656E645F62645F72656164790000000002
+:101E10006873745352696E67000000006261645316
+:101E200052696E67000000006E69635352696E6705
+:101E30000000000077446D61416C6C4100000000BF
+:101E40002B715F646D615F746F5F686F73745F6344
+:101E50006B73756D000000002B685F6D61635F72CE
+:101E6000785F636F6D705F636B73756D000000006A
+:101E70002B685F646D615F77725F61737369737400
+:101E80005F636B73756D000072436B736D4F6E0013
+:101E90002B715F646D615F746F5F686F73740000B6
+:101EA0002B685F6D61635F72785F636F6D700000B8
+:101EB0002B685F646D615F77725F617373697374C0
+:101EC0000000000072436B736D4F666600000000F7
+:101ED0002B685F726563765F62645F7265616479C7
+:101EE000000000002B685F726563765F6A756D6243
+:101EF0006F5F62645F726561647900002B685F7276
+:101F00006563765F6D696E695F62645F7265616467
+:101F1000790000002B6D685F636F6D6D616E64000A
+:101F20002B685F74696D6572000000002B685F6448
+:101F30006F5F7570646174655F74785F636F6E73F3
+:101F4000000000002B685F646F5F757064617465EA
+:101F50005F72785F70726F64000000002B636B73B8
+:101F6000756D3136000000002B7065656B5F6D612B
+:101F7000635F72785F7761002B7065656B5F6D6181
+:101F8000635F7278000000002B6465715F6D6163B0
+:101F90005F7278002B685F6D61635F72785F617458
+:101FA000746E0000626164526574537A0000000030
+:101FB000727842644266537A000000002B6E756CA2
+:101FC0006C5F68616E646C657200000066774F70CC
+:101FD0004661696C000000002B685F757064617475
+:101FE000655F6C65643400002B685F7570646174B4
+:101FF000655F6C65643600002B685F7570646174A2
+:10200000655F6C6564320000696E74537461746559
+:10201000000000002A2A696E697443700000000005
+:102020002373637265616D0069537461636B4572FC
+:102030000000000070726F62654D656D0000000069
+:102040002A2A4441574E5F42000000002B73775FFD
+:10205000646D615F6173736973745F706C75735FD6
+:1020600074696D65720000002B267072656C6F617B
+:10207000645F77725F646573637200002B26707211
+:10208000656C6F61645F72645F64657363720000A6
+:102090002B685F68665F74696D65720024486561CE
+:1020A0006465723A202F70726F6A656374732F7261
+:1020B00063732F73772F67652F2E2F6E69632F66DB
+:1020C00077322F636F6D6D6F6E2F74696D65722E31
+:1020D000632C7620312E312E322E33352031393992
+:1020E000392F30312F32372031393A30393A3530C3
+:1020F0002068617965732045787020240000000015
+:10210000657674526E67460051657674460000002D
+:1021100051657674505F46004D657674526E674621
+:10212000000000004D516576744600004D51657603
+:10213000505F46005173436F6E495F4600000000D8
+:102140005173436F6E734600517250726F64460054
+:10215000542D446D6152643200000000542D446DD2
+:102160006152643100000000542D446D615264429C
+:1021700000000000542D446D6157723200000000D1
+:10218000542D446D6157723100000000542D446D90
+:1021900061577242000000000000000024486561A1
+:1021A0006465723A202F70726F6A656374732F7260
+:1021B00063732F73772F67652F2E2F6E69632F66DA
+:1021C00077322F636F6D6D6F6E2F636F6D6D616E04
+:1021D000642E632C7620312E312E322E323820316F
+:1021E0003939392F30312F32302031393A34393AB8
+:1021F000343920736875616E67204578702024003B
+:10220000657674526E67460051657674460000002C
+:1022100051657674505F46004D657674526E674620
+:10222000000000004D516576744600004D51657602
+:10223000505F46005173436F6E495F4600000000D7
+:102240005173436F6E734600517250726F64460053
+:102250003F48636D644D6278000000003F636D6429
+:1022600048737453000000003F636D644D634D6418
+:10227000000000003F636D6450726F6D000000004D
+:102280003F636D644C696E6B000000003F636D64DA
+:1022900045727200000086AC00008E5C00008E5C0F
+:1022A00000008DE400008B7800008E3000008E5C12
+:1022B00000008790000088000000899000008A6874
+:1022C00000008A3400008E5C0000887000008B24BF
+:1022D00000008E5C00008B34000087B4000088246E
+:1022E00000000000000000000000000024486561BC
+:1022F0006465723A202F70726F6A656374732F720F
+:1023000063732F73772F67652F2E2F6E69632F6688
+:1023100077322F636F6D6D6F6E2F6D636173742EE7
+:10232000632C7620312E312E322E38203139393837
+:102330002F31322F30382030323A33363A3336208C
+:10234000736875616E672045787020240000000076
+:10235000657674526E6746005165767446000000DB
+:1023600051657674505F46004D657674526E6746CF
+:10237000000000004D516576744600004D516576B1
+:10238000505F46005173436F6E495F460000000086
+:102390005173436F6E734600517250726F64460002
+:1023A0006164644D63447570000000006164644DB5
+:1023B0006346756C0000000064656C4D634E6F45AC
+:1023C00000000000000000000000000024486561DB
+:1023D0006465723A202F70726F6A656374732F722E
+:1023E00063732F73772F67652F2E2F6E69632F66A8
+:1023F00077322F636F6D6D6F6E2F646D612E632C5E
+:102400007620312E312E322E323420313939382F88
+:1024100031322F32312030303A33333A3039207371
+:102420006875616E67204578702024006576745267
+:102430006E674600516576744600000051657674FB
+:10244000505F46004D657674526E6746000000008E
+:102450004D516576744600004D516576505F4600DB
+:102460005173436F6E495F46000000005173436F24
+:102470006E734600517250726F6446007377446DFC
+:10248000614F66660000000031446D614F6E0000D0
+:102490007377446D614F6E002372446D6141544EF9
+:1024A0000000000072446D6141544E300000000095
+:1024B00072446D6141544E310000000072446D6100
+:1024C000344762002A50414E49432A002E2E2F2EB7
+:1024D0002E2F2E2E2F2E2E2F2E2E2F7372632F6E19
+:1024E00069632F6677322F636F6D6D6F6E2F646D2A
+:1024F000612E63002377446D6141544E000000005B
+:1025000077446D6141544E300000000077446D61A6
+:1025100041544E310000000077446D613447620041
+:102520000000000000000000000000002448656179
+:102530006465723A202F70726F6A656374732F72CC
+:1025400063732F73772F67652F2E2F6E69632F6646
+:1025500077322F636F6D6D6F6E2F74726163652EAE
+:10256000632C7620312E312E322E352031393938F8
+:102570002F30392F33302031383A35303A32382045
+:10258000736875616E672045787020240000000034
+:102590000000000000000000000000002448656109
+:1025A0006465723A202F70726F6A656374732F725C
+:1025B00063732F73772F67652F2E2F6E69632F66D6
+:1025C00077322F636F6D6D6F6E2F646174612E6350
+:1025D0002C7620312E312E322E31322031393939BC
+:1025E0002F30312F32302031393A34393A353120D9
+:1025F000736875616E6720457870202400000000C4
+:1026000046575F56455253494F4E3A202331204694
+:1026100072692041707220372031373A35373A35A8
+:1026200032205044542032303030000046575F434F
+:102630004F4D50494C455F54494D453A2031373A4A
+:1026400035373A353200000046575F434F4D504909
+:102650004C455F42593A206465767263730000000E
+:1026600046575F434F4D50494C455F484F53543A8E
+:1026700020636F6D707574650000000046575F43FE
+:102680004F4D50494C455F444F4D41494E3A2065AE
+:102690006E672E616374656F6E2E636F6D00000050
+:1026A00046575F434F4D50494C45523A206763634C
+:1026B0002076657273696F6E20322E372E320000DD
+:1026C00000000000120411000000000024486561B1
+:1026D0006465723A202F70726F6A656374732F722B
+:1026E00063732F73772F67652F2E2F6E69632F66A5
+:1026F00077322F636F6D6D6F6E2F6D656D2E632C4E
+:102700007620312E312E322E3520313939382F3086
+:10271000392F33302031383A35303A303820736829
+:1027200075616E672045787020240000244865613B
+:102730006465723A202F70726F6A656374732F72CA
+:1027400063732F73772F67652F2E2F6E69632F6644
+:1027500077322F636F6D6D6F6E2F73656E642E63AE
+:102760002C7620312E312E322E3434203139393826
+:102770002F31322F32312030303A33333A31382052
+:10278000736875616E672045787020240000000032
+:10279000657674526E674600516576744600000097
+:1027A00051657674505F46004D657674526E67468B
+:1027B000000000004D516576744600004D5165766D
+:1027C000505F46005173436F6E495F460000000042
+:1027D0005173436F6E734600517250726F644600BE
+:1027E00069736E745463705500000000244865617D
+:1027F0006465723A202F70726F6A656374732F720A
+:1028000063732F73772F67652F2E2F6E69632F6683
+:1028100077322F636F6D6D6F6E2F726563762E63E7
+:102820002C7620312E312E322E3533203139393964
+:102830002F30312F31362030323A35353A3433208B
+:10284000736875616E672045787020240000000071
+:10285000657674526E6746005165767446000000D6
+:1028600051657674505F46004D657674526E6746CA
+:10287000000000004D516576744600004D516576AC
+:10288000505F46005173436F6E495F460000000081
+:102890005173436F6E734600517250726F644600FD
+:1028A000724D616343686B300000000072784672BD
+:1028B0006D324C670000000072784E6F53744264B2
+:1028C0000000000072784E6F4D6942640000000005
+:1028D00072784E6F4A6D4264000000007278436B5C
+:1028E000446D614600000000727851446D457846A1
+:1028F00000000000727851446D61460072785144C6
+:102900004C42644600000000727851446D426446B7
+:1029100000000000727843726350616400000000A0
+:1029200072536D51446D614600000000244865619A
+:102930006465723A202F70726F6A656374732F72C8
+:1029400063732F73772F67652F2E2F6E69632F6642
+:1029500077322F636F6D6D6F6E2F6D61632E632CF9
+:102960007620312E312E322E323220313939382F25
+:1029700031322F30382030323A33363A3330207308
+:102980006875616E67204578702024006576745202
+:102990006E67460051657674460000005165767496
+:1029A000505F46004D657674526E67460000000029
+:1029B0004D516576744600004D516576505F460076
+:1029C0005173436F6E495F46000000005173436FBF
+:1029D0006E734600517250726F6446006D616354AD
+:1029E000687265730000000023744D616341544EAA
+:1029F0000000000023724D616341544E000000004E
+:102A000072656D4173737274000000006C696E6BC7
+:102A1000444F574E000000006C696E6B555000002B
+:102A20000000000000000000000000002448656174
+:102A30006465723A202F70726F6A656374732F72C7
+:102A400063732F73772F67652F2E2F6E69632F6641
+:102A500077322F636F6D6D6F6E2F636B73756D2E95
+:102A6000632C7620312E312E322E392031393939EE
+:102A70002F30312F31342030303A30333A3438204F
+:102A8000736875616E67204578702024000000002F
+:102A9000657674526E674600516576744600000094
+:102AA00051657674505F46004D657674526E674688
+:102AB000000000004D516576744600004D5165766A
+:102AC000505F46005173436F6E495F46000000003F
+:102AD0005173436F6E734600517250726F644600BB
+:102AE00000000000000000000000000050726F6253
+:102AF00065506879000000006C6E6B41535352546E
+:102B000000000000000109A400010A1C00010A5095
+:102B100000010A7C0001105000010AA800010B10FE
+:102B2000000111FC00010DC000010C6800010C80C7
+:102B300000010CC400010CEC00010D0C00010D346F
+:102B4000000111FC00010DC000010DF800010E1084
+:102B500000010E4000010E6800010E8800010EB059
+:102B60000000000000010FDC000110080001102C23
+:102B7000000111FC00011050000110780001110843
+:102B80000000000000000000000000000001186CC0
+:102B90000001193C00011A1400011AE400011B4055
+:102BA00000011C1C00011C4400011D2000011D48E7
+:102BB00000011EF000011F18000120C0000122B812
+:102BC0000001254C000124600001254C00012578FE
+:102BD000000120E8000122907273745F676D6969DB
+:102BE00000000000000126080001264000012728FF
+:102BF00000013374000133B4000133CC7365746C8D
+:102C00006F6F7000000000000000000000013BBC7E
+:102C100000013BFC00013C8C00013CD000013D3434
+:102C200000013DC000013DF400013E7C00013F1465
+:102C300000013FE400014024000140A8000140CC15
+:102C4000000141DC646F4261736550670000000061
+:102C500000000000000000000000000073746D61BF
+:102C6000634C4E4B000000006765746D636C6E6BC7
+:102C70000000000000014ED800014ED800014B8C2E
+:102C800000014BD800014C2400014ED87365746DCF
+:102C90006163616374000000000000000000000038
+:102CA0000000000000000000000000000000000024
+:102CB0000000000000000000000000000000000014
+:102CC0000000000000000000000000000000000103
+:102CD000000000010000000100C001FC00003FFCFA
+:102CE00000C00000416C74656F6E204163654E4901
+:102CF000432056000000000000000000000000001B
+:102D0000000000000000000000000000416C74653D
+:102D10006F6E204163654E49432056004242424255
+:102D2000000000000000000000000000001FFFFC89
+:102D3000001FFF7C000000000000000000000000F9
+:102D40000000000000000000000000000060CF0054
+:102D500000000060CF000000000000000000000044
+:102D60000000000000000000000000000000000063
+:102D70000000000000000000000000000000000053
+:102D80000000000000000000000000000000000043
+:102D90000000000000000000000000000000000033
+:102DA0000000000000000000000000030000000020
+:102DB0000000000100000000000000000000000012
+:102DC0000000000100000000000000010000000001
+:102DD00000000000000000000000000000000001F2
+:102DE00000000001000000000000000000000000E2
+:102DF00000000000000000000100000021000000B1
+:102E0000120001400000000000000000200000004F
+:102E1000120000A0000000001200006012000180FB
+:102E2000120001E0000000000000000000000000AF
+:102E30000000000100000000000000000000000091
+:102E40000000000000000000000000000000000280
+:102E5000000000000000000000030001000000016D
+:102E60000003020100000000000000000101010158
+:102E70000101010000010100010100010001000148
+:0C2E800001000101000001010000000041
+:00000001FF
+/* tg2 firmware v12.4.11 */
diff --git a/firmware/adaptec/starfire_rx.bin.ihex b/firmware/adaptec/starfire_rx.bin.ihex
new file mode 100644 (file)
index 0000000..6b1fae0
--- /dev/null
@@ -0,0 +1,53 @@
+:10000000010003DC00000000040004210000008661
+:10001000800000150000180E8100001500006664C5
+:100020001A0040AB00000B06142000110000000075
+:10003000142040220000AAAA14204022000003003D
+:1000400014204022000000001A0040AB00000B14F6
+:1000500014200011000000008300001500000002C1
+:10006000040000210000000000000010000000005B
+:1000700004000421000000870000001000000000C0
+:1000800000000010000000000000801500000000CB
+:100090000000003E00000000000000100000000012
+:1000A0008200001500004000009E8050000000000B
+:1000B000030080150000000086008015000000008D
+:1000C00082000015000080000100001C00000000FC
+:1000D000000050A00000010C4E20D011000060086C
+:1000E0001420D012000040080000F09000007000C2
+:1000F0000000C8B0000030000000404000000000D8
+:10010000001080150000000000A2C1500000400057
+:1001100000A400B000000014000000200000000057
+:100120002500400D0000252500047220000031004C
+:10013000009340700000000000000020000000005C
+:1001400000924460000001842B20C01100000000D8
+:100150000000C42000000540360140180000422D78
+:100160001420001100000000009244600000018390
+:100170003200001F0000003402AC00150000000235
+:1001800000A601100000000842200011000000003D
+:1001900000924060000001030000001E000000000B
+:1001A00000000020000001000000001E0000000010
+:1001B00000924460000000860000408000000000C3
+:1001C0000092C0700000000000924060000001003A
+:1001D0000000C8900000500000A6C1100000000000
+:1001E00000B0C09000000012021C001500000000CA
+:1001F0003200001F0000003400924460000005102F
+:100200004421001100000000420000110000000025
+:1002100083000015000000400092446000000508C3
+:100220004501401800004545008080500000000056
+:10023000622080120000000082000015000008000B
+:100240001520001100000000000000100000000058
+:10025000000000100000000000000010000000007E
+:10026000000000100000000000000010000000006E
+:10027000800000150000EEA4810000150000005F62
+:1002800000000060000000000000412000000000AD
+:1002900000004A000000400000924460000001900D
+:1002A0005601401A000059561400001100000000C9
+:1002B0000093405000000018009300500000001808
+:1002C0003601403A0000002D000643A9000000005E
+:1002D0000000C420000001405601401A0000595699
+:1002E00014000011000000000000001000000000D9
+:1002F0000000001000000000000642A900000000FD
+:1003000000024420000001835601401A00005956A3
+:1003100082000015000020001520001100000000E0
+:1003200082000015000000101520001100000000E0
+:1003300082000015000000101520001100000000D0
+:00000001FF
diff --git a/firmware/adaptec/starfire_tx.bin.ihex b/firmware/adaptec/starfire_tx.bin.ihex
new file mode 100644 (file)
index 0000000..6b1fae0
--- /dev/null
@@ -0,0 +1,53 @@
+:10000000010003DC00000000040004210000008661
+:10001000800000150000180E8100001500006664C5
+:100020001A0040AB00000B06142000110000000075
+:10003000142040220000AAAA14204022000003003D
+:1000400014204022000000001A0040AB00000B14F6
+:1000500014200011000000008300001500000002C1
+:10006000040000210000000000000010000000005B
+:1000700004000421000000870000001000000000C0
+:1000800000000010000000000000801500000000CB
+:100090000000003E00000000000000100000000012
+:1000A0008200001500004000009E8050000000000B
+:1000B000030080150000000086008015000000008D
+:1000C00082000015000080000100001C00000000FC
+:1000D000000050A00000010C4E20D011000060086C
+:1000E0001420D012000040080000F09000007000C2
+:1000F0000000C8B0000030000000404000000000D8
+:10010000001080150000000000A2C1500000400057
+:1001100000A400B000000014000000200000000057
+:100120002500400D0000252500047220000031004C
+:10013000009340700000000000000020000000005C
+:1001400000924460000001842B20C01100000000D8
+:100150000000C42000000540360140180000422D78
+:100160001420001100000000009244600000018390
+:100170003200001F0000003402AC00150000000235
+:1001800000A601100000000842200011000000003D
+:1001900000924060000001030000001E000000000B
+:1001A00000000020000001000000001E0000000010
+:1001B00000924460000000860000408000000000C3
+:1001C0000092C0700000000000924060000001003A
+:1001D0000000C8900000500000A6C1100000000000
+:1001E00000B0C09000000012021C001500000000CA
+:1001F0003200001F0000003400924460000005102F
+:100200004421001100000000420000110000000025
+:1002100083000015000000400092446000000508C3
+:100220004501401800004545008080500000000056
+:10023000622080120000000082000015000008000B
+:100240001520001100000000000000100000000058
+:10025000000000100000000000000010000000007E
+:10026000000000100000000000000010000000006E
+:10027000800000150000EEA4810000150000005F62
+:1002800000000060000000000000412000000000AD
+:1002900000004A000000400000924460000001900D
+:1002A0005601401A000059561400001100000000C9
+:1002B0000093405000000018009300500000001808
+:1002C0003601403A0000002D000643A9000000005E
+:1002D0000000C420000001405601401A0000595699
+:1002E00014000011000000000000001000000000D9
+:1002F0000000001000000000000642A900000000FD
+:1003000000024420000001835601401A00005956A3
+:1003100082000015000020001520001100000000E0
+:1003200082000015000000101520001100000000E0
+:1003300082000015000000101520001100000000D0
+:00000001FF
diff --git a/firmware/tigon/tg3.bin.ihex b/firmware/tigon/tg3.bin.ihex
new file mode 100644 (file)
index 0000000..d842d7c
--- /dev/null
@@ -0,0 +1,175 @@
+:10000000000000000800000000000A80000000005E
+:1000100010000003000000000000000D0000000DB3
+:100020003C1D080037BD3FFC03A0F0213C10080038
+:10003000261000000E000018000000000000000D57
+:100040003C1D080037BD3FFC03A0F0213C10080018
+:10005000261000340E00021C000000000000000DFD
+:1000600000000000000000000000000027BDFFE0CD
+:100070003C1CC000AFBF0018AF80680C0E00004CE5
+:10008000241B210597850000978700029782002C8A
+:100090009783002E3C040800248409C0AFA00014FC
+:1000A000000214000062182500052C00AFA3001008
+:1000B0008F86001000E528250E000060240701024D
+:1000C0003C02AC00344201003C03AC01346301004B
+:1000D000AF8204903C02FFFFAF820494AF83049888
+:1000E000AF82049C24020001AF825CE00E00003F5E
+:1000F000AF825D000E000140000000008FBF0018BD
+:1001000003E0000827BD00202402FFFFAF82540453
+:100110008F83540034630400AF835400AF825404CF
+:100120003C02080024420034AF82541C03E0000863
+:10013000AF80540000000000000000003C020800F6
+:10014000344230003C030800346330003C040800B3
+:10015000348437FF3C010800AC220A6424020040CA
+:100160003C010800AC220A683C010800AC200A608F
+:10017000AC600000246300040083102B5040FFFD9E
+:10018000AC60000003E0000800000000008048218F
+:100190008FAA00103C0208008C420A603C04080050
+:1001A0008C840A688FAB0014244300010044102B98
+:1001B0003C010800AC230A60144000030000402109
+:1001C0003C010800AC200A603C0208008C420A6036
+:1001D0003C0308008C630A64912400000002114073
+:1001E000004310210048102125080001A044000010
+:1001F000290200081440FFF4252900013C020800F0
+:100200008C420A603C0308008C630A648F84680C8B
+:100210000002114000431021AC440008AC45000C22
+:10022000AC460010AC470014AC4A001803E00008CC
+:10023000AC4B001C000000000000000000000000AB
+:1002400000000000000000000000000000000000AE
+:10025000000000000000000000000000000000009E
+:10026000000000000000000000000000000000008E
+:10027000000000000000000000000000000000007E
+:10028000000000000000000000000000000000006E
+:10029000000000000000000000000000000000005E
+:1002A000000000000000000000000000000000004E
+:1002B000000000000000000000000000000000003E
+:1002C000000000000000000000000000000000002E
+:1002D000000000000000000000000000000000001E
+:1002E000000000000000000000000000000000000E
+:1002F00000000000000000000000000000000000FE
+:1003000000000000000000000000000002000008E3
+:10031000000000000A0001E33C0A00010A0001E3BA
+:100320003C0A00020A0001E3000000000A0001E3A9
+:10033000000000000A0001E3000000000A0001E3E1
+:10034000000000000A0001E3000000000A0001E3D1
+:10035000000000000A0001E3000000000A0001E3C1
+:10036000000000000A0001E3000000000A0001E3B1
+:100370003C0A00070A0001E33C0A00080A0001E306
+:100380003C0A00090A0001E3000000000A0001E342
+:10039000000000000A0001E33C0A000B0A0001E330
+:1003A0003C0A000C0A0001E33C0A000D0A0001E3CC
+:1003B000000000000A0001E3000000000A0001E361
+:1003C0003C0A000E0A0001E3000000000A0001E3FD
+:1003D000000000000A0001E3000000000A0001E341
+:1003E000000000000A0001E3000000000A0001E331
+:1003F000000000000A0001E3000000000A0001E321
+:10040000000000000A0001E33C0A00130A0001E3B7
+:100410003C0A001400000000000000000000000082
+:1004200000000000000000000000000000000000CC
+:1004300000000000000000000000000000000000BC
+:1004400000000000000000000000000000000000AC
+:10045000000000000000000000000000000000009C
+:10046000000000000000000000000000000000008C
+:10047000000000000000000000000000000000007C
+:10048000000000000000000000000000000000006C
+:10049000000000000000000000000000000000005C
+:1004A000000000000000000000000000000000004C
+:1004B000000000000000000000000000000000003C
+:1004C000000000000000000000000000000000002C
+:1004D000000000000000000000000000000000001C
+:1004E000000000000000000000000000000000000C
+:1004F00000000000000000000000000000000000FC
+:1005000000000000000000000000000027BDFFE028
+:100510000000182100001021AFBF0018AFB1001477
+:10052000AFB000103C01080000220821AC200A7086
+:100530003C01080000220821AC200A743C0108009C
+:1005400000220821AC200A78246300011860FFF51E
+:100550002442000C241100018F9068103202000424
+:1005600014400005240400013C0208008C420A7873
+:1005700018400003000020210E000182000000004E
+:100580003202000110400003000000000E0001696B
+:10059000000000000A000153AF9150288FBF0018DF
+:1005A0008FB100148FB0001003E0000827BD0020B9
+:1005B0003C0508008CA50A703C0608008CC60A8021
+:1005C0003C0708008CE70A7827BDFFE03C040800E0
+:1005D000248409D0AFBF0018AFA000100E00006047
+:1005E000AFA000140E00017B000020218FBF001877
+:1005F00003E0000827BD0020240200018F8368105B
+:1006000000821004000210270062182403E0000892
+:10061000AF83681027BDFFD8AFBF00241080002E25
+:10062000AFB000208F825CECAFA200188F825CEC30
+:100630003C10080026100A78AFA2001C340280008B
+:10064000AF825CEC8E020000184000160000000033
+:100650003C02080094420A748FA3001C000221C0CF
+:10066000AC8300048FA2001C3C0108000E000201B4
+:10067000AC220A7410400005000000008E02000049
+:10068000244200010A0001DFAE0200003C02080023
+:100690008C420A7000021C02000321C00A0001C53E
+:1006A000AFA2001C0E000201000000001040001F5D
+:1006B000000000008E0200008FA3001C24420001F5
+:1006C0003C010800AC230A703C010800AC230A740A
+:1006D0000A0001DFAE0200003C10080026100A7874
+:1006E0008E02000018400028000000000E000201E9
+:1006F0000000000014400024000000008E020000F2
+:100700003C0308008C630A702442FFFFAFA3001C67
+:1007100018400006AE02000000031402000221C0CF
+:100720008C8200043C010800AC220A7097A2001ED3
+:100730002442FF002C4203001440000B240240001E
+:100740003C040800248409DCAFA00010AFA0001412
+:100750008FA6001C240500080E0000600000382150
+:100760000A0001DF00000000AF825CF83C020800D4
+:100770008C420A408FA3001C24420001AF835CF826
+:100780003C010800AC220A408FBF00248FB000203B
+:1007900003E0000827BD002827BDFFE03C04080057
+:1007A000248409E8000028210000302100003821BD
+:1007B000AFBF0018AFA000100E000060AFA0001483
+:1007C0008FBF001803E0000827BD00208F82680C4F
+:1007D0008F85680C000218270003182B00031823CC
+:1007E000004310240044102100A2282B10A0000672
+:1007F00000000000004018218F82680C0043102B7D
+:100800001440FFFD0000000003E0000800000000AD
+:100810003C0408008C8400003C0308008C630A4000
+:100820000064102B54400002008310230064102346
+:100830002C42000803E000083842000127BDFFE019
+:10084000008028213C04080024840A000000302194
+:1008500000003821AFBF0018AFA000100E000060EC
+:10086000AFA000140A000216000000008FBF00189D
+:1008700003E0000827BD00200000000027BDFFE0C6
+:100880003C1CC000AFBF00180E00004CAF80680CCD
+:100890003C04080024840A10038028210000302131
+:1008A00000003821AFA000100E000060AFA00014BF
+:1008B0002402FFFFAF8254043C0200AA0E0002345F
+:1008C000AF8254348FBF001803E0000827BD00201A
+:1008D00000000000000000000000000027BDFFE84D
+:1008E000AFB0001024100001AFBF00143C01C003E2
+:1008F000AC2000008F8268103042200010400003BE
+:10090000000000000E000246000000000A00023A4B
+:10091000AF9054288FBF00148FB0001003E0000880
+:1009200027BD001827BDFFF88F845D0C3C0200FF37
+:100930003C0308008C630A503442FFF80082102404
+:100940001043001E3C0500FF34A5FFF83C06C00321
+:100950003C074000008518248C6200103C01080010
+:10096000AC230A50304200081040000500871025D3
+:100970008CC2000024420001ACC200000087102598
+:10098000AF825D0C8FA2000024420001AFA20000E4
+:100990008FA200008FA2000024420001AFA200003D
+:1009A0008FA200008F845D0C3C0308008C630A500A
+:1009B000008510241443FFE80085182427BD000893
+:1009C00003E000080000000000000000353730316F
+:1009D000726C734100000000000000005377457600
+:1009E000656E743000000000726C704576656E7440
+:1009F00031000000556E6B6E45766E74000000008D
+:100A0000000000000000000000000000666174614A
+:100A10006C45727200000000000000004D61696EBC
+:100A2000437075420000000000000000000000005C
+:100A300000000000000000000000000000000000B6
+:100A400000000000000000000000000000000000A6
+:100A50000000000000000000000000000000000096
+:0C0A60000000000000000000000000008A
+:00000001FF
+ * Firmware is:
+ *     Derived from proprietary unpublished source code,
+ *     Copyright (C) 2000-2003 Broadcom Corporation.
+ *
+ *     Permission is hereby granted for the distribution of this firmware
+ *     data in hexadecimal or equivalent format, provided this copyright
+ *     notice is accompanying it.
diff --git a/firmware/tigon/tg3_tso.bin.ihex b/firmware/tigon/tg3_tso.bin.ihex
new file mode 100644 (file)
index 0000000..f10c4ef
--- /dev/null
@@ -0,0 +1,446 @@
+:100000000106000008000000000024140E00000398
+:100010000000000008001B24000000001000000386
+:10002000000000000000000D0000000D3C1D080055
+:1000300037BD400003A0F0213C100800261000004E
+:100040000E000010000000000000000D27BDFFE0C2
+:100050003C04FEFEAFBF00180E0005D83484000239
+:100060000E000668000000003C03080090631B6857
+:10007000240200023C04080024841AAC1462000329
+:10008000240500013C04080024841AA0240600066C
+:1000900000003821AFA000100E00067CAFA00014B5
+:1000A0008F625C5034420001AF625C508F625C90A2
+:1000B00034420001AF625C902402FFFF0E00003466
+:1000C000AF6254048FBF001803E0000827BD002072
+:1000D00000000000000000000000000027BDFFE05D
+:1000E000AFBF001CAFB20018AFB100140E00005B30
+:1000F000AFB0001024120002241100018F7068209C
+:100100003202010010400003000000000E0000BB9E
+:10011000000000008F7068203202200010400004B0
+:10012000320200010E0001F024040001320200013D
+:1001300010400003000000000E0000A300000000BB
+:100140003C02080090421B9814520003000000007B
+:100150000E0004C0000000000A00003CAF715028EF
+:100160008FBF001C8FB200188FB100148FB0001029
+:1001700003E0000827BD002027BDFFE03C04080085
+:1001800024841AC0000028210000302100003821FA
+:10019000AFBF0018AFA000100E00067CAFA0001487
+:1001A0003C040800248423D8A48000003C010800FB
+:1001B000A0201B983C010800AC201B9C3C010800BF
+:1001C000AC201BA03C010800AC201BA43C01080093
+:1001D000AC201BAC3C010800AC201BB83C01080063
+:1001E000AC201BBC8F6244343C010800AC221B884D
+:1001F0008F6244383C010800AC221B8C8F62441093
+:10020000AC80F7A83C010800AC201B843C0108002E
+:10021000AC2023E03C010800AC2023C83C010800CE
+:10022000AC2023CC3C010800AC2024003C01080099
+:10023000AC221B908F6200682403000700021702A3
+:1002400010430005000000008F62006800021702E2
+:1002500014400004240200013C0108000A00009739
+:10026000AC20240CAC8200343C04080024841ACC5A
+:100270003C0508008CA5240C00003021000038212A
+:10028000AFA000100E00067CAFA000148FBF0018B6
+:1002900003E0000827BD002027BDFFE03C04080064
+:1002A00024841AD8000028210000302100003821C1
+:1002B000AFBF0018AFA000100E00067CAFA0001466
+:1002C0000E00005B000000000E0000B400002021C2
+:1002D0008FBF001803E0000827BD002024020001A2
+:1002E0008F63682000821004000210270062182427
+:1002F00003E00008AF63682027BDFFD0AFBF002C2C
+:10030000AFB60028AFB50024AFB40020AFB3001CD7
+:10031000AFB20018AFB10014AFB000108F675C5CD3
+:100320003C03080024631BBC8C62000014470005DA
+:100330003C0200FF3C02080090421B981440011947
+:100340003C0200FF3442FFF800E28824AC67000062
+:1003500000111902306300FF30E20003000211C0F7
+:100360000062282500A04021000716023C03080077
+:1003700090631B983044000F1460003600804821C1
+:10038000240200013C010800A0221B980005110076
+:10039000008210253C010800AC201B9C3C01080099
+:1003A000AC201BA03C010800AC201BA43C010800B1
+:1003B000AC201BAC3C010800AC201BB83C01080081
+:1003C000AC201BB03C010800AC201BB43C01080071
+:1003D000A42223D89622000C30437FFF3C01080062
+:1003E000A4222410304280003C010800A4231BC634
+:1003F00010400005240200013C010800AC2223F457
+:100400000A0001022406003E240600363C010800D2
+:10041000AC2023F49622000A3C03080094631BC618
+:100420003C010800AC2023F03C010800AC2023F87C
+:10043000000213020002108000C210210062182185
+:100440003C010800A42223D03C0108000A00011549
+:10045000A4231B969622000C3C010800A42223EC46
+:100460003C04080024841B9C8C82000000021100C4
+:100470003C01080000220821AC311BC88C8200001E
+:10048000000211003C01080000220821AC271BCC0F
+:100490008C82000025030001306601FF000211007C
+:1004A0003C01080000220821AC261BD08C820000F1
+:1004B000000211003C01080000220821AC291BD4D5
+:1004C000962300083C0208008C421BAC0043282104
+:1004D0003C010800AC251BAC9622000A3042000407
+:1004E00014400018000611008F630C143063000FD5
+:1004F0002C6200021440000B3C02C0008F630C14FD
+:100500003C0208008C421B403063000F2442000173
+:100510003C010800AC221B402C6200021040FFF797
+:100520003C02C00000E21825AF635C5C8F625C5047
+:100530003042000210400014000000000A00014791
+:10054000000000003C0308008C631B803C04080092
+:1005500094841B94012210253C010800A42223DA74
+:10056000240200013C010800AC221BB824630001F6
+:100570000085202A3C01080010800003AC231B806A
+:100580003C010800A4251B943C06080024C61B9CC3
+:100590008CC2000024420001ACC20000284200804E
+:1005A00014400005000000000E000656240400025E
+:1005B0000A0001E6000000003C0208008C421BB863
+:1005C00010400078240200013C05080090A51B980B
+:1005D00014A20072000000003C15080096B51B969E
+:1005E0003C0408008C841BAC32A3FFFF0083102A5C
+:1005F0001440006C000000001483000300000000A1
+:100600003C010800AC2523F01060005C0000902144
+:1006100024D600040060A02124D300148EC2000060
+:10062000000281003C110800023088210E000625DE
+:100630008E311BC80040282110A00054000000008B
+:100640009628000A31020040104000052407180CCB
+:100650008E22000C2407188C00021400ACA2001893
+:100660003C030800007018218C631BD03C0208007A
+:10067000005010218C421BD400031D000002140006
+:1006800000621825ACA300148EC300049622000853
+:10069000004320233242FFFF3083FFFF004310213D
+:1006A0000282102A1440000202B23023008030215E
+:1006B0008E62000030C4FFFF00441021AE620000D3
+:1006C0008E220000ACA200008E2200048E63FFF494
+:1006D00000431021ACA20004A4A6000E8E62FFF419
+:1006E00000441021AE62FFF4962300080043102A54
+:1006F00014400005024690218E62FFF0AE60FFF4C8
+:1007000024420001AE62FFF0ACA000083242FFFFBD
+:1007100014540008240203053102008054400001F3
+:1007200034E7001024020905A4A2000C0A0001CB42
+:1007300034E70020A4A2000C3C0208008C4223F005
+:10074000104000033C024B650A0001D3344276544A
+:100750003C02B49A344289ABACA2001C30E2FFFFE9
+:10076000ACA200100E0005A200A020213242FFFF23
+:100770000054102B1440FFA90000000024020002C6
+:100780003C0108000A0001E6A0221B988EC2083C2A
+:10079000244200010A0001E6AEC2083C0E0004C07B
+:1007A000000000008FBF002C8FB600288FB50024FA
+:1007B0008FB400208FB3001C8FB200188FB10014CB
+:1007C0008FB0001003E0000827BD003027BDFFD028
+:1007D000AFBF0028AFB30024AFB20020AFB1001C00
+:1007E000AFB000188F725C9C3C0200FF3442FFF8EF
+:1007F0003C07080024E71BB4024288249623000E1D
+:100800008CE2000000431021ACE200008E220010B8
+:100810003042002014400011008098210E00063B59
+:10082000022020213C02C00002421825AF635C9CDC
+:100830008F625C90304200021040011E00000000F8
+:10084000AF635C9C8F625C903042000210400119E3
+:10085000000000000A00020D000000008E240008C5
+:100860008E23001400041402000231C0000315029C
+:10087000304201FF2442FFFF3042007F0003194253
+:1008800030637800000211002442400000624821D9
+:100890009522000A3084FFFF30420008104000B06B
+:1008A000000429C03C0208008C42240014400024AB
+:1008B00024C5000894C200143C010800A42223D0DF
+:1008C0008CC40010000414023C010800A42223D2AE
+:1008D0003C010800A42423D494C2000E3083FFFFFF
+:1008E000004310233C010800AC22240894C2001AE3
+:1008F0003C010800AC2624003C010800AC32240472
+:100900003C010800AC2223FC3C02C0000242182536
+:10091000AF635C9C8F625C9030420002104000E547
+:1009200000000000AF635C9C8F625C90304200026C
+:10093000104000E0000000000A0002460000000035
+:1009400094C2000E3C030800946323D40043402368
+:100950003103FFFF2C6200081040001C0000000063
+:1009600094C200142442002800A22821000310424F
+:100970001840000B0000202124E6084800403821E0
+:1009800094A300008CC200002484000100431021C5
+:10099000ACC200000087102A1440FFF924A5000211
+:1009A000310200011040001F3C0240003C040800DE
+:1009B000248423FCA0A0000194A300008C820000EA
+:1009C000004310210A000285AC8200008F6268009B
+:1009D0003C030010004310241040000900000000F8
+:1009E00094C2001A3C0308008C6323FC00431021CE
+:1009F0003C010800AC2223FC0A0002863C024000B5
+:100A000094C2001A94C4001C3C0308008C6323FCAD
+:100A100000441023006218213C010800AC2323FC91
+:100A20003C02400002421825AF635C9C8F625C90E0
+:100A3000304200021440FFFC000000009522000A32
+:100A4000304200101040009B000000003C030800F2
+:100A5000946323D43C07080024E724008CE40000BE
+:100A60008F62680024630030008328213C0300105B
+:100A7000004310241440000A0000000094A2000467
+:100A80003C0408008C8424083C0308008C6323FC8D
+:100A900000441023006218213C010800AC2323FC11
+:100AA0003C0408008C8423FC00041C023082FFFFFD
+:100AB000006220210004140200822021000410277B
+:100AC000A4A200063C0308008C6324043C0200FF3F
+:100AD0003442FFF8006288249622000824050001B1
+:100AE00024034000000231C000801021A4C2001A7B
+:100AF000A4C0001CACE000003C010800AC251B6059
+:100B0000AF635CB88F625CB03042000210400003FB
+:100B1000000000003C010800AC201B608E22000891
+:100B2000AF625CB88F625CB03042000210400003DC
+:100B3000000000003C010800AC201B603C020800E3
+:100B40008C421B601040FFEC000000003C040800D9
+:100B50000E00063B8C8424040A00032A00000000D7
+:100B60003C03080090631B982402000214620003F7
+:100B70003C034B650A0002E1000080218E22001C2C
+:100B80003463765410430002241000022410000144
+:100B900000C020210E000350020030212402000377
+:100BA0003C010800A0221B98240200021202000A45
+:100BB000240200013C0308008C6323F0106200064D
+:100BC000000000003C020800944223D800021400F8
+:100BD0000A00031FAE2200143C040800248423DA18
+:100BE0009482000000021400AE2200143C020800AF
+:100BF0008C421BBC3C03C0003C010800A0201B9899
+:100C000000431025AF625C5C8F625C503042000292
+:100C100010400009000000002484F7E28C820000EC
+:100C200000431025AF625C5C8F625C503042000272
+:100C30001440FFFA000000003C02080024421B841C
+:100C40008C43000024630001AC4300008F630C144C
+:100C50003063000F2C6200021440000C3C02400084
+:100C60008F630C143C0208008C421B403063000F61
+:100C7000244200013C010800AC221B402C6200020F
+:100C80001040FFF7000000003C024000024218251F
+:100C9000AF635C9C8F625C90304200021440FFFCAA
+:100CA0000000000012600003000000000E0004C0FD
+:100CB000000000008FBF00288FB300248FB20020F7
+:100CC0008FB1001C8FB0001803E0000827BD003072
+:100CD0008F6344503C04080024841B888C820000ED
+:100CE00000031C020043102B144000073C0380004B
+:100CF0008C8400048F62445000021C020083102B7D
+:100D00001040FFFC3C038000AF6344448F624444C6
+:100D1000004310241440FFFD000000008F6244488F
+:100D200003E000083042FFFF3C0240000082202523
+:100D3000AF645C388F625C30304200021440FFFCCC
+:100D40000000000003E000080000000027BDFFE0F5
+:100D50000080582114C00011256E00083C020800D4
+:100D60008C4223F410400007240200163C010800C6
+:100D7000A42223D22402002A3C0108000A000364B2
+:100D8000A42223D48D670010000714023C01080040
+:100D9000A42223D23C010800A42723D43C04080049
+:100DA000948423D43C030800946323D295CF000697
+:100DB0003C020800944223D00083202301E2C02398
+:100DC0003065FFFF24A2002801C248213082FFFFC6
+:100DD00014C0001A012260219582000C3042003FAD
+:100DE0003C010800A42223D69582000495830006C6
+:100DF0003C010800AC2023E43C010800AC2023E8BF
+:100E000000021400004310253C010800AC221BC066
+:100E1000952200043C010800A4221BC49523000273
+:100E200001E510230043102A1040001024020001A5
+:100E30003C0108000A000398AC2223F83C03080098
+:100E40008C6323E83C02080094421BC40043102139
+:100E5000A52200043C02080094421BC0A5820004A5
+:100E60003C0208008C421BC0A58200063C02080020
+:100E70008C4223F03C0D08008DAD23E43C0A0800B1
+:100E8000144000E58D4A23E83C02080094421BC44C
+:100E9000004A18213063FFFF0062182B2402000271
+:100EA00010C2000D014350233C020800944223D697
+:100EB0003042000910400008000000009582000C3C
+:100EC0003042FFF6A582000C3C020800944223D673
+:100ED0003042000901A268233C0208008C4223F83A
+:100EE0001040004A012038213C020800944223D2DD
+:100EF00000004021A520000A01E21023A5220002E3
+:100F00003082FFFF0002104218400008000030212C
+:100F10000040182194E200002508000100C23021A1
+:100F20000103102A1440FFFB24E7000200061C0204
+:100F300030C2FFFF006230210006140200C23021DF
+:100F400000C0282100061027A522000A0000302139
+:100F50002527000C0000402194E200002508000134
+:100F600000C230212D0200041440FFFB24E70002E0
+:100F70009522000200004021912300090044202313
+:100F8000018038213082FFFFA4E0001000621821A8
+:100F9000000210421840001000C3302100404821D8
+:100FA00094E2000024E7000200C2302130E2007F1A
+:100FB00014400006250800018D6300003C02007FFC
+:100FC0003442FF8000625824256700080109102A76
+:100FD0001440FFF3000000003082000110400005C3
+:100FE00000061C02A0E0000194E2000000C23021D3
+:100FF00000061C0230C2FFFF00623021000614020E
+:1010000000C230210A00047D30C6FFFF2402000226
+:1010100014C20081000000003C0208008C42240C35
+:1010200014400007000000003C020800944223D254
+:101030009523000201E210231062007700000000F7
+:101040003C020800944223D201E21023A5220002B0
+:101050003C0208008C42240C1040001A31E3FFFFD0
+:101060008DC700103C02080094421B9600E040210E
+:1010700000072C0200AA20210043102300823823FD
+:101080000007240230E2FFFF00823821000710270A
+:10109000A522000A3102FFFF3C040800948423D4F7
+:1010A0000045302300E0282100641823006D18213A
+:1010B00000C3302100061C0230C2FFFF0A00047D7D
+:1010C0000062302101203821000040213082FFFFE2
+:1010D0000002104218400008000030210040182192
+:1010E00094E200002508000100C230210103102A0B
+:1010F0001440FFFB24E7000200061C0230C2FFFF81
+:10110000006230210006140200C2302100C02821F4
+:1011100000061027A522000A000030212527000C18
+:101120000000402194E200002508000100C23021A7
+:101130002D0200041440FFFB24E700029522000268
+:101140000000402191230009004420230180382120
+:101150003082FFFFA4E000103C040800948423D4F4
+:101160000062182100C3302100061C0230C2FFFFBC
+:101170000062302100061C023C020800944223D089
+:1011800000C348210044102300021FC20043102165
+:1011900000021043184000100000302100402021C0
+:1011A00094E2000024E7000200C2302130E2007F18
+:1011B00014400006250800018D6300003C02007FFA
+:1011C0003442FF8000625824256700080104102A79
+:1011D0001440FFF3000000003C020800944223EC9E
+:1011E00000C230213122FFFF00C2302100061C0264
+:1011F00030C2FFFF006230210006140200C230211D
+:1012000000C0402100061027A5820010ADC00014C8
+:101210000A00049DADC000008DC7001000E0402111
+:101220001140000700072C0200AA3021000614021A
+:1012300030C3FFFF004330210006140200C2282102
+:1012400000051027A522000A3C030800946323D45C
+:101250003102FFFF01E210210043302300CD302195
+:1012600000061C0230C2FFFF00623021000614029B
+:1012700000C2302100C0402100061027A5820010C6
+:101280003102FFFF00051C0000431025ADC2001015
+:101290003C0208008C4223F4104000052DE205EBCF
+:1012A0001440000225E2FFF234028870A5C2003427
+:1012B0003C030800246323E88C6200002442000100
+:1012C000AC6200003C0408008C8423E43C0208006B
+:1012D0008C421BC03303FFFF0083202100431821F1
+:1012E0000062102B3C010800AC2423E410400003F2
+:1012F0002482FFFF3C010800AC2223E43C010800EB
+:10130000AC231BC003E0000827BD002027BDFFB8A9
+:101310003C05080024A51B96AFBF0044AFBE0040AB
+:10132000AFB7003CAFB60038AFB50034AFB4003053
+:10133000AFB3002CAFB20028AFB10024AFB0002093
+:1013400094A900003C020800944223D03C0308000A
+:101350008C631BB03C0408008C841BAC012210235E
+:101360000064182AA7A9001E106000BEA7A20016DC
+:1013700024BE002297B6001E24B3001A24B700161C
+:101380008FC2000014400008000000008FC2FFF868
+:1013900097A300168FC4FFF4004310210082202A77
+:1013A000148000B00000000097D5081832A2FFFF9B
+:1013B000104000A3000090210040A02100008821DF
+:1013C0000E000625000000000040302114C0000778
+:1013D000000000003C0208008C4223DC2442000193
+:1013E0003C0108000A000596AC2223DC3C100800F2
+:1013F000021180218E101BC89608000A310200409D
+:10140000104000052407180C8E02000C2407188CCD
+:1014100000021400ACC200183102008054400001E8
+:1014200034E700103C020800005110218C421BD010
+:101430003C030800007118218C631BD400021500C6
+:1014400000031C0000431025ACC2001496040008E1
+:101450003242FFFF008210210282102A1440000253
+:1014600002B22823008028218E020000024590212C
+:10147000ACC200008E02000400C020212631001002
+:10148000AC82000430E2FFFFAC800008A485000EAF
+:10149000AC820010240203050E0005A2A482000CF9
+:1014A0003242FFFF0054102B1440FFC53242FFFFB1
+:1014B0000A00058E000000008E6200008E63FFFCB3
+:1014C0000043102A10400067000000008E62FFF009
+:1014D000000289003C100800021180210E00062540
+:1014E0008E101BC80040302114C000050000000011
+:1014F0008E62082C244200010A000596AE62082C78
+:101500009608000A31020040104000052407180C1C
+:101510008E02000C2407188C00021400ACC20018C4
+:101520003C020800005110218C421BD03C030800F3
+:10153000007118218C631BD40002150000031C00ED
+:1015400000431025ACC200148E63FFF4960200081D
+:10155000004320233242FFFF3083FFFF004310216E
+:1015600002C2102A104000030080282197A9001E03
+:10157000013228238E62000030A4FFFF00441021B6
+:10158000AE620000A4C5000E8E020000ACC20000D6
+:101590008E0200048E63FFF400431021ACC20004ED
+:1015A0008E63FFF496020008006418210062102A7E
+:1015B00014400006024590218E62FFF0AE60FFF4F9
+:1015C000244200010A000571AE62FFF0AE63FFF431
+:1015D000ACC000083242FFFF105600033102000485
+:1015E000104000062402030531020080544000012F
+:1015F00034E7001034E7002024020905A4C2000CDF
+:101600008EE300008EE20004146200073C02B49AEC
+:101610008EE208605440000134E704003C024B6550
+:101620000A00058834427654344289ABACC2001CAF
+:1016300030E2FFFFACC200100E0005A200C0202166
+:101640003242FFFF0056102B1440FF9B00000000A9
+:101650008E6200008E63FFFC0043102A1440FF4896
+:10166000000000008FBF00448FBE00408FB7003CD9
+:101670008FB600388FB500348FB400308FB3002C94
+:101680008FB200288FB100248FB0002003E0000843
+:1016900027BD004827BDFFE8AFBF0014AFB0001062
+:1016A0008F6244508F6344100A0005B1008080218E
+:1016B0008F626820304220001040000300000000CC
+:1016C0000E0001F0000020218F6244508F6344100F
+:1016D0003042FFFF0043102B1440FFF500000000D4
+:1016E0008F630C143063000F2C6200021440000B57
+:1016F000000000008F630C143C0208008C421B4069
+:101700003063000F244200013C010800AC221B4062
+:101710002C6200021040FFF700000000AF705C1860
+:101720008F625C103042000210400009000000008F
+:101730008F626820304220001040FFF80000000057
+:101740000E0001F0000020210A0005C40000000086
+:101750008FBF00148FB0001003E0000827BD0018F1
+:1017600000000000000000000000000027BDFFE8AE
+:101770003C1BC000AFBF0014AFB00010AF60680CDE
+:101780008F62680434420082AF6268048F63400055
+:1017900024020B503C010800AC221B5424020B789D
+:1017A0003C010800AC221B6434630002AF634000BC
+:1017B0000E000605008080213C010800A0221B6865
+:1017C000304200FF24030002144300050000000023
+:1017D0003C0208008C421B540A0005F8AC5000C0C3
+:1017E0003C0208008C421B54AC5000BC8F62443455
+:1017F0008F6344388F6444103C010800AC221B5CAA
+:101800003C010800AC231B6C3C010800AC241B58B5
+:101810008FBF00148FB0001003E0000827BD001830
+:101820003C0408008C8700003C03AA553463AA5589
+:101830003C06C003AC8300008CC2000014430007C8
+:10184000240500023C0355AA346355AAAC8300006A
+:101850008CC2000050430001240500013C02080036
+:10186000AC47000003E0000800A0102127BDFFF8EE
+:1018700018800009000028218F63680C8F62680CB3
+:101880001043FFFE0000000024A5000100A4102A60
+:101890001440FFF90000000003E0000827BD000825
+:1018A0008F6344503C0208008C421B5C00031C0206
+:1018B0000043102B144000083C0380003C04080047
+:1018C0008C841B6C8F62445000021C020083102B1E
+:1018D0001040FFFC3C038000AF6344448F624444EB
+:1018E000004310241440FFFD000000008F624448B4
+:1018F00003E000083042FFFF3082FFFF2442E00097
+:101900002C422001144000033C0240000A0006481B
+:101910002402FFFF00822025AF645C388F625C30B8
+:10192000304200021440FFFC0000102103E00008D8
+:10193000000000008F6244503C0308008C631B5879
+:101940000A0006513042FFFF8F6244503042FFFFD1
+:101950000043102B1440FFFC0000000003E00008CF
+:101960000000000027BDFFE0008028213C040800A3
+:1019700024841AF00000302100003821AFBF001885
+:10198000AFA000100E00067CAFA000140A00066095
+:10199000000000008FBF001803E0000827BD0020F2
+:1019A0000000000000000000000000003C020800F1
+:1019B000344230003C030800346330003C0408002B
+:1019C000348437FF3C010800AC221B742402004021
+:1019D0003C010800AC221B783C010800AC201B70C5
+:1019E000AC600000246300040083102B5040FFFD16
+:1019F000AC60000003E00008000000000080482107
+:101A00008FAA00103C0208008C421B703C040800A6
+:101A10008C841B788FAB0014244300010044102BEE
+:101A20003C010800AC231B7014400003000040215F
+:101A30003C010800AC201B703C0208008C421B706B
+:101A40003C0308008C631B749124000000021140C9
+:101A5000004310210048102125080001A044000087
+:101A6000290200081440FFF4252900013C02080067
+:101A70008C421B703C0308008C631B748F64680CE1
+:101A80000002114000431021AC440008AC45000C9A
+:101A9000AC460010AC470014AC4A001803E0000844
+:101AA000AC4B001C00000000000000004D61696E9E
+:101AB00043707542000000004D61696E43707541CE
+:101AC00000000000000000000000000073746B6F55
+:101AD00066666C64496E000073746B6F66662A2AD2
+:101AE0000000000053774576656E743000000000FA
+:101AF000000000000000000000000000666174614A
+:101B00006C45727200000000000000000000000040
+:101B100000000000000000000000000000000000C5
+:101B200000000000000000000000000000000000B5
+:101B300073746B6F66666C645F76312E362E300080
+:101B40000000000000000000000000000000000095
+:0C1B500000000000000000000000000089
+:00000001FF
+ * Firmware is:
+ *     Derived from proprietary unpublished source code,
+ *     Copyright (C) 2000-2003 Broadcom Corporation.
+ *
+ *     Permission is hereby granted for the distribution of this firmware
+ *     data in hexadecimal or equivalent format, provided this copyright
+ *     notice is accompanying it.
diff --git a/firmware/tigon/tg3_tso5.bin.ihex b/firmware/tigon/tg3_tso5.bin.ihex
new file mode 100644 (file)
index 0000000..3367251
--- /dev/null
@@ -0,0 +1,252 @@
+:10000000010200000001000000000FD80C004003B6
+:100010000000000000010F040000000010000003B9
+:10002000000000000000000D0000000D3C1D00015C
+:1000300037BDE00003A0F0213C10000126100000B5
+:100040000C004010000000000000000D27BDFFE084
+:100050003C04FEFEAFBF00180C0042E834840002EE
+:100060000C004364000000003C03000190630F3467
+:10007000240200023C04000124840E9C146200034C
+:10008000240500013C04000124840E902406000293
+:1000900000003821AFA000100C004378AFA000147E
+:1000A0000C00402C000000008FBF001803E0000887
+:1000B00027BD0020000000000000000027BDFFE079
+:1000C000AFBF001CAFB20018AFB100140C0042D497
+:1000D000AFB000103C128000241100018F70681036
+:1000E0003202040010400007000000008F64100876
+:1000F0000092102414400003000000000C00406433
+:10010000000000003C02000190420F561051000315
+:10011000320202001040FFF1000000000C0041B468
+:100120000000000008004034000000008FBF001CE9
+:100130008FB200188FB100148FB0001003E00008D8
+:1001400027BD002027BDFFE03C04000124840EB041
+:10015000000028210000302100003821AFBF001826
+:10016000AFA000100C004378AFA000140000D02115
+:1001700024020130AF6250003C010001A4200F5066
+:100180003C010001A0200F578FBF001803E00008BA
+:1001900027BD002000000000000000003C0300011B
+:1001A00024630F609062000027BDFFF0144000033D
+:1001B0000080C02108004073000048213C0220005C
+:1001C00003021024104000032409000208004073B9
+:1001D000A0600000240900010018104030431F8077
+:1001E000346F80081520004B25EB00283C040001EB
+:1001F000008320218C8480103C05000124A50F7A07
+:1002000000041402A0A200003C010001A0240F7B06
+:100210003C02000100431021944280143C01000183
+:10022000A0220F7C3C0C0001018360218D8C801882
+:10023000304200FF24420008000220C324020001D3
+:100240003C010001A0220F600124102B1040000C83
+:100250000000382124A6000E016028218CA2000095
+:100260008CA3000424A5000824E70001ACC2000010
+:10027000ACC3000400E4102B1440FFF824C60008AF
+:10028000000038213C08000125080F7B9106000082
+:100290003C02000190420F7C2503000D00C3282181
+:1002A0000046102300021FC2004310210002104329
+:1002B0001840000C0000202191020001004610238C
+:1002C00000021FC2004310210002184394A2000044
+:1002D00024E700010082202100E3102A1440FFFBE4
+:1002E00024A5000200041C023082FFFF00622021CE
+:1002F00000041402008220213C02FFFF018210242E
+:100300003083FFFF004310253C010001080040FA44
+:10031000AC220F803C05000124A50F7C90A20000B8
+:100320003C0C0001018360218D8C8018000220C2EA
+:100330001080000E000038210160302124A5000C3F
+:100340008CA200008CA3000424A5000824E700016F
+:10035000ACC20000ACC3000400E4102B1440FFF852
+:1003600024C600083C05000124A50F7C90A20000D3
+:1003700030430007240200041062001128620005C7
+:10038000104000052402000210620008000710C09F
+:10039000080040FA00000000240200061062000E6F
+:1003A000000710C0080040FA0000000000A2182159
+:1003B0009463000C004B1021080040FAA443000095
+:1003C000000710C000A218218C63000C004B102104
+:1003D000080040FAAC43000000A218218C63000C16
+:1003E000004B202100A21021AC8300009442001099
+:1003F000A482000495E700063C02000190420F7CB5
+:100400003C03000190630F7A00E2C8233C02000124
+:1004100090420F7B2463002801E3402124420028FE
+:100420001520001201E2302194C2000C3C010001B1
+:10043000A4220F7894C2000494C300063C0100017A
+:10044000A4200F763C010001A4200F7200021400CA
+:10045000004310253C010001AC220F6C9502000402
+:100460003C01000108004124A4220F703C0200015D
+:1004700094420F703C03000194630F7200431021FB
+:10048000A50200043C02000194420F6CA4C20004C7
+:100490003C0200018C420F6CA4C200063C04000127
+:1004A00094840F723C02000194420F703C0A0001D8
+:1004B000954A0F76004418213063FFFF0062182A26
+:1004C000240200021122000B008320233C030001C0
+:1004D00094630F7830620009104000063062FFF626
+:1004E000A4C2000C3C02000194420F783042000983
+:1004F00001425023240200011122001B2922000284
+:1005000050400005240200021120000731A2FFFF25
+:1005100008004197000000001122001D240200166F
+:100520000800419731A2FFFF3C0E000195CE0F80DD
+:10053000108000050180682101C4202100041C02F4
+:100540003082FFFF00627021000E1027A502000A12
+:100550003C03000190630F7B31A2FFFF00E21021FA
+:100560000800418D004320233C02000194420F808B
+:100570000044202100041C023082FFFF0062202181
+:10058000008070210004102708004185A502000AA0
+:100590003C05000124A50F7A90A30000146200021C
+:1005A00024E2FFF2A5E2003490A2000000E2102352
+:1005B000A50200023C03000194630F803C0200018D
+:1005C00094420F5A30E5FFFF0064182100451023C4
+:1005D0000062202300041C023082FFFF0062202101
+:1005E00000041027A502000A3C03000190630F7C61
+:1005F0002462000114A20005008070210163102113
+:10060000904200000800418500026200246200025E
+:1006100014A20003306200FE004B1021944C000035
+:100620003C02000194420F823183FFFF3C04000131
+:1006300090840F7B0043102100E21021004420230E
+:10064000008A202100041C023082FFFF006220216A
+:100650000004140200822021008068210004102779
+:10066000A4C2001031A2FFFF000E1C0000431025A1
+:100670003C04000124840F72ADE20010948200005B
+:100680003C05000194A50F763C0300018C630F6CC0
+:100690002442000100B92821A48200003322FFFF78
+:1006A000006220210083182B3C010001A4250F7655
+:1006B0001060000324A2FFFF3C010001A4220F767A
+:1006C0003C024000030210253C010001AC240F6CE9
+:1006D000AF62100803E0000827BD00103C030001D2
+:1006E00090630F5627BDFFE824020001AFBF00143E
+:1006F00010620026AFB000108F620CF42442FFFF9E
+:100700003042007F000211008C4340003C01000198
+:10071000AC230F648C434008244440008C5C4004AC
+:1007200030620040144000022402008824020008C5
+:100730003C010001A4220F68306200041040000553
+:10074000240200013C010001A0220F57080041D5FE
+:10075000000314023C010001A0200F570003140203
+:100760003C010001A4220F549483000C24020001D8
+:100770003C010001A4200F503C010001A0220F56B3
+:100780003C010001A4230F62240200011342001E59
+:10079000000000001340000524020003134200671C
+:1007A00000000000080042CF000000003C020001F1
+:1007B00094420F62241A00013C010001A4200F5E44
+:1007C0003C010001A4200F52304407FF00021BC26D
+:1007D000000318233063003E3463003600021242E7
+:1007E0003042003C006218213C010001A4240F5853
+:1007F00000832021246300303C010001A4240F5A0F
+:100800003C010001A4230F5C3C06000124C60F52EA
+:1008100094C5000094C300023C04000194840F5A64
+:10082000006510210044102A104000133C10800085
+:1008300000A31021A4C200003C02A000AF620CF48F
+:100840003C010001A0200F568F6410080090102476
+:1008500014400003000000000C0040640000000091
+:100860008F620CF400501024104000B7000000000C
+:100870000800420F000000003C03000194630F5089
+:1008800000851023A4C40000006218213042FFFF3D
+:100890003C010001A4230F50AF620CE83C020001B0
+:1008A00094420F6834420024AF620CEC94C30002FF
+:1008B0003C02000194420F50146200123C0280007E
+:1008C0003C1080003C02A000AF620CF43C0100012F
+:1008D000A0200F568F6410080090102414400003CD
+:1008E000000000000C004064000000008F620CF467
+:1008F000005010241440FFF700000000080042CF11
+:10090000241A0003AF620CF43C1080008F641008BE
+:100910000090102414400003000000000C0040640C
+:10092000000000008F620CF4005010241440FFF708
+:1009300000000000080042CF241A00033C07000119
+:1009400024E70F5094E2000003821021AF620CE014
+:100950003C0200018C420F64AF620CE43C050001D4
+:1009600094A50F5494E300003C04000194840F58B4
+:100970003C02000194420F5E00A328230082202342
+:1009800030A6FFFF3083FFFF00C3102B144000434D
+:10099000000000003C02000194420F5C00021400C1
+:1009A00000621025AF620CE894E200003C030001F5
+:1009B00094630F5400441021A4E200003042FFFF72
+:1009C000144300213C0200083C02000190420F57F2
+:1009D000104000063C03000C3C02000194420F68EA
+:1009E000346306240800427C0000D0213C02000150
+:1009F00094420F683C03000834630624004310252A
+:100A0000AF620CEC3C1080003C02A000AF620CF422
+:100A10003C010001A0200F568F64100800901024A4
+:100A200014400003000000000C00406400000000BF
+:100A30008F620CF4005010241040001500000000DC
+:100A400008004283000000003C03000194630F682B
+:100A5000344206243C108000006218253C028000CD
+:100A6000AF630CECAF620CF48F641008009010249C
+:100A700014400003000000000C004064000000006F
+:100A80008F620CF4005010241440FFF700000000A7
+:100A90003C010001080042CFA4200F5E3C0200018F
+:100AA00094420F5C0002140000C21025AF620CE8F3
+:100AB0003C02000190420F57104000093C03000C1B
+:100AC0003C02000194420F68346306240000D021E8
+:100AD00000431025AF620CEC080042C13C108000BE
+:100AE0003C02000194420F683C0300083463060492
+:100AF00000431025AF620CEC3C02000194420F5EF3
+:100B0000004510213C010001A4220F5E3C10800032
+:100B10003C02A000AF620CF43C010001A0200F5683
+:100B20008F6410080090102414400003000000009F
+:100B30000C004064000000008F620CF40050102490
+:100B40001440FFF7000000008FBF00148FB00010AA
+:100B500003E0000827BD00180000000027BDFFE0EB
+:100B60003C04000124840EC0000028210000302134
+:100B700000003821AFBF0018AFA000100C00437870
+:100B8000AFA000140000D02124020130AF62500059
+:100B90003C010001A4200F503C010001A0200F5790
+:100BA0008FBF001803E0000827BD002027BDFFE825
+:100BB0003C1BC000AFBF0014AFB00010AF60680CAA
+:100BC0008F62680434420082AF6268048F63400021
+:100BD00024020B503C010001AC220F2024020B78B0
+:100BE0003C010001AC220F3034630002AF634000CF
+:100BF0000C004315008080213C010001A0220F342D
+:100C0000304200FF240300021443000500000000EE
+:100C10003C0200018C420F2008004308AC5000C089
+:100C20003C0200018C420F20AC5000BC8F62443467
+:100C30008F6344388F6444103C010001AC220F28BC
+:100C40003C010001AC230F383C010001AC240F240F
+:100C50008FBF00148FB0001003E0000827BD0018FC
+:100C600003E000082402000127BDFFF818800009F6
+:100C7000000028218F63680C8F62680C1043FFFE10
+:100C80000000000024A5000100A4102A1440FFF970
+:100C90000000000003E0000827BD00088F634450F7
+:100CA0003C0200018C420F2800031C020043102B61
+:100CB000144000083C0380003C0400018C840F3881
+:100CC0008F62445000021C020083102B1040FFFC76
+:100CD0003C038000AF6344448F62444400431024CB
+:100CE0001440FFFD000000008F62444803E000084C
+:100CF0003042FFFF3082FFFF2442E0002C422001FF
+:100D0000144000033C024000080043472402FFFF58
+:100D100000822025AF645C388F625C303042000274
+:100D20001440FFFC0000102103E000080000000058
+:100D30008F6244503C0300018C630F240800435031
+:100D40003042FFFF8F6244503042FFFF0043102BC0
+:100D50001440FFFC0000000003E000080000000059
+:100D600027BDFFE0008028213C04000124840ED030
+:100D70000000302100003821AFBF0018AFA00010E4
+:100D80000C004378AFA000140800435F000000008F
+:100D90008FBF001803E0000827BD00203C020001BF
+:100DA0003442D6003C0300013463D6003C04000109
+:100DB0003484DDFF3C010001AC220F4024020040DE
+:100DC0003C010001AC220F443C010001AC200F3C6F
+:100DD000AC600000246300040083102B5040FFFD32
+:100DE000AC60000003E00008000000000080482123
+:100DF0008FAA00103C0200018C420F3C3C04000111
+:100E00008C840F448FAB0014244300010044102B4A
+:100E10003C010001AC230F3C1440000300004021C2
+:100E20003C010001AC200F3C3C0200018C420F3C15
+:100E30003C0300018C630F4091240000000211402C
+:100E4000004310210048102125080001A0440000A3
+:100E5000290200081440FFF4252900013C0200018A
+:100E60008C420F3C3C0300018C630F408F64680C84
+:100E70000002114000431021AC440008AC45000CB6
+:100E8000AC460010AC470014AC4A001803E0000860
+:100E9000AC4B001C00000000000000004D61696EBA
+:100EA00043707542000000004D61696E43707541EA
+:100EB00000000000000000000000000073746B6F71
+:100EC00066666C64000000000000000073746B6FC5
+:100ED00066666C64000000000000000066617461DA
+:100EE0006C4572720000000000000000000000006D
+:100EF00000000000000000000000000000000000F2
+:100F000000000000000000000000000000000000E1
+:100F100073746B6F66666C645F76312E322E3000B0
+:0C0F2000000000000000000000000000C5
+:00000001FF
+ * Firmware is:
+ *     Derived from proprietary unpublished source code,
+ *     Copyright (C) 2000-2003 Broadcom Corporation.
+ *
+ *     Permission is hereby granted for the distribution of this firmware
+ *     data in hexadecimal or equivalent format, provided this copyright
+ *     notice is accompanying it.
+/* 5705 needs a special version of the TSO firmware.  */
index ff0e81980207a75727d9a845cf8e7fcfbfedd7ec..f9b6e2979aaa9f0cf1e3b751796d03808780797c 100644 (file)
@@ -189,6 +189,8 @@ config OCFS2_FS
        select CONFIGFS_FS
        select JBD2
        select CRC32
+       select QUOTA
+       select QUOTA_TREE
        help
          OCFS2 is a general purpose extent based shared disk cluster file
          system with many similarities to ext3. It supports 64 bit inode
@@ -258,15 +260,14 @@ config OCFS2_DEBUG_FS
          this option for debugging only as it is likely to decrease
          performance of the filesystem.
 
-config OCFS2_COMPAT_JBD
-       bool "Use JBD for compatibility"
+config OCFS2_FS_POSIX_ACL
+       bool "OCFS2 POSIX Access Control Lists"
        depends on OCFS2_FS
+       select FS_POSIX_ACL
        default n
-       select JBD
        help
-         The ocfs2 filesystem now uses JBD2 for its journalling.  JBD2
-         is backwards compatible with JBD.  It is safe to say N here.
-         However, if you really want to use the original JBD, say Y here.
+         Posix Access Control Lists (ACLs) support permissions for users and
+         groups beyond the owner/group/world scheme.
 
 endif # BLOCK
 
@@ -303,6 +304,10 @@ config PRINT_QUOTA_WARNING
          Note that this behavior is currently deprecated and may go away in
          future. Please use notification via netlink socket instead.
 
+# Generic support for tree structured quota files. Seleted when needed.
+config QUOTA_TREE
+        tristate
+
 config QFMT_V1
        tristate "Old quota format support"
        depends on QUOTA
@@ -314,6 +319,7 @@ config QFMT_V1
 config QFMT_V2
        tristate "Quota format v2 support"
        depends on QUOTA
+       select QUOTA_TREE
        help
          This quota format allows using quotas with 32-bit UIDs/GIDs. If you
          need this functionality say Y here.
index e6f423d1d228fc449d7f8559f291ca531d518674..c830611550d3d95726fe40a565d2ee9ff153158a 100644 (file)
@@ -54,6 +54,7 @@ obj-$(CONFIG_GENERIC_ACL)     += generic_acl.o
 obj-$(CONFIG_QUOTA)            += dquot.o
 obj-$(CONFIG_QFMT_V1)          += quota_v1.o
 obj-$(CONFIG_QFMT_V2)          += quota_v2.o
+obj-$(CONFIG_QUOTA_TREE)       += quota_tree.o
 obj-$(CONFIG_QUOTACTL)         += quota.o
 
 obj-$(CONFIG_PROC_FS)          += proc/
index 1377b1240b6eadba12cf89c5b961d5d90d33c594..9246cb4aa018fafa3517685e7d7fa1572f2e5a16 100644 (file)
@@ -628,7 +628,7 @@ static int affs_write_begin_ofs(struct file *file, struct address_space *mapping
        }
 
        index = pos >> PAGE_CACHE_SHIFT;
-       page = __grab_cache_page(mapping, index);
+       page = grab_cache_page_write_begin(mapping, index, flags);
        if (!page)
                return -ENOMEM;
        *pagep = page;
index 415d9c67ac1651b17449614221b81ecda5f431fc..3c4ec7d864c405606f93b8afe0f2963639208e29 100644 (file)
@@ -119,8 +119,7 @@ struct inode *affs_iget(struct super_block *sb, unsigned long ino)
                goto bad_inode;
 #else
                inode->i_mode |= S_IFDIR;
-               inode->i_op = NULL;
-               inode->i_fop = NULL;
+               /* ... and leave ->i_op and ->i_fop pointing to empty */
                break;
 #endif
        case ST_LINKFILE:
index d6b85dab35fcc71a16ba310bb11848c7ae7e891d..3fb36d433621dd2bb71edcc757dbe22390ff2640 100644 (file)
@@ -144,7 +144,7 @@ int afs_write_begin(struct file *file, struct address_space *mapping,
        candidate->state = AFS_WBACK_PENDING;
        init_waitqueue_head(&candidate->waitq);
 
-       page = __grab_cache_page(mapping, index);
+       page = grab_cache_page_write_begin(mapping, index, flags);
        if (!page) {
                kfree(candidate);
                return -ENOMEM;
index c773680d5c605524b37481fdb4fb7fe83b2e7b7e..e1734f2d6e26de60a89e514ac59d57a7a5fba821 100644 (file)
@@ -251,13 +251,11 @@ struct inode *autofs_iget(struct super_block *sb, unsigned long ino)
        inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
        inode->i_nlink = 2;
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
-       inode->i_blocks = 0;
 
        if (ino == AUTOFS_ROOT_INO) {
                inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
                inode->i_op = &autofs_root_inode_operations;
                inode->i_fop = &autofs_root_operations;
-               inode->i_uid = inode->i_gid = 0; /* Changed in read_super */
                goto done;
        } 
        
index 7b19802cfef4b158cee241339c92c8f30ac88dd0..cfc23e53b6f460fef089881acb04dc2087393453 100644 (file)
@@ -455,11 +455,7 @@ struct inode *autofs4_get_inode(struct super_block *sb,
        if (sb->s_root) {
                inode->i_uid = sb->s_root->d_inode->i_uid;
                inode->i_gid = sb->s_root->d_inode->i_gid;
-       } else {
-               inode->i_uid = 0;
-               inode->i_gid = 0;
        }
-       inode->i_blocks = 0;
        inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 
        if (S_ISDIR(inf->mode)) {
index f1f3f4192a609fbbd4be4232b0e525697787be98..b639dcf7c778cfc6f81eca964c8c6748a5840949 100644 (file)
@@ -95,92 +95,55 @@ static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, u
        int has_dumped = 0;
        unsigned long dump_start, dump_size;
        struct user dump;
-#if defined(__alpha__)
+#ifdef __alpha__
 #       define START_DATA(u)   (u.start_data)
-#elif defined(__arm__)
+#else
 #      define START_DATA(u)    ((u.u_tsize << PAGE_SHIFT) + u.start_code)
-#elif defined(__sparc__)
-#       define START_DATA(u)    (u.u_tsize)
-#elif defined(__i386__) || defined(__mc68000__) || defined(__arch_um__)
-#       define START_DATA(u)   (u.u_tsize << PAGE_SHIFT)
 #endif
-#ifdef __sparc__
-#       define START_STACK(u)   ((regs->u_regs[UREG_FP]) & ~(PAGE_SIZE - 1))
-#else
 #       define START_STACK(u)   (u.start_stack)
-#endif
 
        fs = get_fs();
        set_fs(KERNEL_DS);
        has_dumped = 1;
        current->flags |= PF_DUMPCORE;
                strncpy(dump.u_comm, current->comm, sizeof(dump.u_comm));
-#ifndef __sparc__
        dump.u_ar0 = offsetof(struct user, regs);
-#endif
        dump.signal = signr;
        aout_dump_thread(regs, &dump);
 
 /* If the size of the dump file exceeds the rlimit, then see what would happen
    if we wrote the stack, but not the data area.  */
-#ifdef __sparc__
-       if ((dump.u_dsize + dump.u_ssize) > limit)
-               dump.u_dsize = 0;
-#else
        if ((dump.u_dsize + dump.u_ssize+1) * PAGE_SIZE > limit)
                dump.u_dsize = 0;
-#endif
 
 /* Make sure we have enough room to write the stack and data areas. */
-#ifdef __sparc__
-       if (dump.u_ssize > limit)
-               dump.u_ssize = 0;
-#else
        if ((dump.u_ssize + 1) * PAGE_SIZE > limit)
                dump.u_ssize = 0;
-#endif
 
 /* make sure we actually have a data and stack area to dump */
        set_fs(USER_DS);
-#ifdef __sparc__
-       if (!access_ok(VERIFY_READ, (void __user *)START_DATA(dump), dump.u_dsize))
-               dump.u_dsize = 0;
-       if (!access_ok(VERIFY_READ, (void __user *)START_STACK(dump), dump.u_ssize))
-               dump.u_ssize = 0;
-#else
        if (!access_ok(VERIFY_READ, (void __user *)START_DATA(dump), dump.u_dsize << PAGE_SHIFT))
                dump.u_dsize = 0;
        if (!access_ok(VERIFY_READ, (void __user *)START_STACK(dump), dump.u_ssize << PAGE_SHIFT))
                dump.u_ssize = 0;
-#endif
 
        set_fs(KERNEL_DS);
 /* struct user */
        DUMP_WRITE(&dump,sizeof(dump));
 /* Now dump all of the user data.  Include malloced stuff as well */
-#ifndef __sparc__
        DUMP_SEEK(PAGE_SIZE);
-#endif
 /* now we start writing out the user space info */
        set_fs(USER_DS);
 /* Dump the data area */
        if (dump.u_dsize != 0) {
                dump_start = START_DATA(dump);
-#ifdef __sparc__
-               dump_size = dump.u_dsize;
-#else
                dump_size = dump.u_dsize << PAGE_SHIFT;
-#endif
                DUMP_WRITE(dump_start,dump_size);
        }
 /* Now prepare to dump the stack area */
        if (dump.u_ssize != 0) {
                dump_start = START_STACK(dump);
-#ifdef __sparc__
-               dump_size = dump.u_ssize;
-#else
                dump_size = dump.u_ssize << PAGE_SHIFT;
-#endif
                DUMP_WRITE(dump_start,dump_size);
        }
 /* Finally dump the task struct.  Not be used by gdb, but could be useful */
@@ -205,29 +168,24 @@ static unsigned long __user *create_aout_tables(char __user *p, struct linux_bin
        int envc = bprm->envc;
 
        sp = (void __user *)((-(unsigned long)sizeof(char *)) & (unsigned long) p);
-#ifdef __sparc__
-       /* This imposes the proper stack alignment for a new process. */
-       sp = (void __user *) (((unsigned long) sp) & ~7);
-       if ((envc+argc+3)&1) --sp;
-#endif
 #ifdef __alpha__
 /* whee.. test-programs are so much fun. */
        put_user(0, --sp);
        put_user(0, --sp);
        if (bprm->loader) {
                put_user(0, --sp);
-               put_user(0x3eb, --sp);
+               put_user(1003, --sp);
                put_user(bprm->loader, --sp);
-               put_user(0x3ea, --sp);
+               put_user(1002, --sp);
        }
        put_user(bprm->exec, --sp);
-       put_user(0x3e9, --sp);
+       put_user(1001, --sp);
 #endif
        sp -= envc+1;
        envp = (char __user * __user *) sp;
        sp -= argc+1;
        argv = (char __user * __user *) sp;
-#if defined(__i386__) || defined(__mc68000__) || defined(__arm__) || defined(__arch_um__)
+#ifndef __alpha__
        put_user((unsigned long) envp,--sp);
        put_user((unsigned long) argv,--sp);
 #endif
@@ -300,13 +258,8 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                return retval;
 
        /* OK, This is the point of no return */
-#if defined(__alpha__)
+#ifdef __alpha__
        SET_AOUT_PERSONALITY(bprm, ex);
-#elif defined(__sparc__)
-       set_personality(PER_SUNOS);
-#if !defined(__sparc_v9__)
-       memcpy(&current->thread.core_exec, &ex, sizeof(struct exec));
-#endif
 #else
        set_personality(PER_LINUX);
 #endif
@@ -322,24 +275,6 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 
        install_exec_creds(bprm);
        current->flags &= ~PF_FORKNOEXEC;
-#ifdef __sparc__
-       if (N_MAGIC(ex) == NMAGIC) {
-               loff_t pos = fd_offset;
-               /* Fuck me plenty... */
-               /* <AOL></AOL> */
-               down_write(&current->mm->mmap_sem);     
-               error = do_brk(N_TXTADDR(ex), ex.a_text);
-               up_write(&current->mm->mmap_sem);
-               bprm->file->f_op->read(bprm->file, (char *) N_TXTADDR(ex),
-                         ex.a_text, &pos);
-               down_write(&current->mm->mmap_sem);
-               error = do_brk(N_DATADDR(ex), ex.a_data);
-               up_write(&current->mm->mmap_sem);
-               bprm->file->f_op->read(bprm->file, (char *) N_DATADDR(ex),
-                         ex.a_data, &pos);
-               goto beyond_if;
-       }
-#endif
 
        if (N_MAGIC(ex) == OMAGIC) {
                unsigned long text_addr, map_size;
@@ -347,7 +282,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 
                text_addr = N_TXTADDR(ex);
 
-#if defined(__alpha__) || defined(__sparc__)
+#ifdef __alpha__
                pos = fd_offset;
                map_size = ex.a_text+ex.a_data + PAGE_SIZE - 1;
 #else
index f2744ab4e5b35c415724034f3f5a3a328997cf99..e1158cb4fbd6c9568251696e749dbd56b6bdc588 100644 (file)
@@ -496,9 +496,6 @@ static struct inode *bm_get_inode(struct super_block *sb, int mode)
 
        if (inode) {
                inode->i_mode = mode;
-               inode->i_uid = 0;
-               inode->i_gid = 0;
-               inode->i_blocks = 0;
                inode->i_atime = inode->i_mtime = inode->i_ctime =
                        current_fs_time(inode->i_sb);
        }
index 776ae091d3b0d58052aacb899e0954c3b191ae10..a13f09b696f7f2da6adbd3cfeee299c9b6840ac6 100644 (file)
@@ -1996,7 +1996,7 @@ int block_write_begin(struct file *file, struct address_space *mapping,
        page = *pagep;
        if (page == NULL) {
                ownpage = 1;
-               page = __grab_cache_page(mapping, index);
+               page = grab_cache_page_write_begin(mapping, index, flags);
                if (!page) {
                        status = -ENOMEM;
                        goto out;
@@ -2502,7 +2502,7 @@ int nobh_write_begin(struct file *file, struct address_space *mapping,
        from = pos & (PAGE_CACHE_SIZE - 1);
        to = from + len;
 
-       page = __grab_cache_page(mapping, index);
+       page = grab_cache_page_write_begin(mapping, index, flags);
        if (!page)
                return -ENOMEM;
        *pagep = page;
index b1e1fc6a6e6a0247ea9a2b7a0755339f69a597bb..12bb656fbe75881354bdfe1550b453b90f3fa4a3 100644 (file)
@@ -2074,7 +2074,7 @@ static int cifs_write_begin(struct file *file, struct address_space *mapping,
 
        cFYI(1, ("write_begin from %lld len %d", (long long)pos, len));
 
-       page = __grab_cache_page(mapping, index);
+       page = grab_cache_page_write_begin(mapping, index, flags);
        if (!page) {
                rc = -ENOMEM;
                goto out;
index f247da9f4edc2a650f7e59c559f17767d1f8dccd..5ab9896fdcb2cbd93be444b14c2896f90c98e301 100644 (file)
@@ -1641,7 +1641,7 @@ do_expand:
        i_size_write(inode, offset);
        spin_unlock(&inode->i_lock);
 out_truncate:
-       if (inode->i_op && inode->i_op->truncate)
+       if (inode->i_op->truncate)
                inode->i_op->truncate(inode);
        return 0;
 out_sig:
index 466303db2df6acbd11e047338b00739408fa428d..6a347fbc998a4cc3a23f60d3d2e91854db4206b2 100644 (file)
@@ -201,8 +201,7 @@ int coda_release(struct inode *coda_inode, struct file *coda_file)
 int coda_fsync(struct file *coda_file, struct dentry *coda_dentry, int datasync)
 {
        struct file *host_file;
-       struct dentry *host_dentry;
-       struct inode *host_inode, *coda_inode = coda_dentry->d_inode;
+       struct inode *coda_inode = coda_dentry->d_inode;
        struct coda_file_info *cfi;
        int err = 0;
 
@@ -214,14 +213,7 @@ int coda_fsync(struct file *coda_file, struct dentry *coda_dentry, int datasync)
        BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
        host_file = cfi->cfi_container;
 
-       if (host_file->f_op && host_file->f_op->fsync) {
-               host_dentry = host_file->f_path.dentry;
-               host_inode = host_dentry->d_inode;
-               mutex_lock(&host_inode->i_mutex);
-               err = host_file->f_op->fsync(host_file, host_dentry, datasync);
-               mutex_unlock(&host_inode->i_mutex);
-       }
-
+       err = vfs_fsync(host_file, host_file->f_path.dentry, datasync);
        if ( !err && !datasync ) {
                lock_kernel();
                err = venus_fsync(coda_inode->i_sb, coda_i2f(coda_inode));
index 4803ccc944809a57a452721eed36d6656d90af60..5d349d38e0561c4fd66e67bbda76c5f91ca87c69 100644 (file)
@@ -117,8 +117,6 @@ int configfs_setattr(struct dentry * dentry, struct iattr * iattr)
 static inline void set_default_inode_attr(struct inode * inode, mode_t mode)
 {
        inode->i_mode = mode;
-       inode->i_uid = 0;
-       inode->i_gid = 0;
        inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 }
 
@@ -136,7 +134,6 @@ struct inode * configfs_new_inode(mode_t mode, struct configfs_dirent * sd)
 {
        struct inode * inode = new_inode(configfs_sb);
        if (inode) {
-               inode->i_blocks = 0;
                inode->i_mapping->a_ops = &configfs_aops;
                inode->i_mapping->backing_dev_info = &configfs_backing_dev_info;
                inode->i_op = &configfs_inode_operations;
index f40423eb1a14e66b73693f5505a54f00b3bd6f4a..a07338d2d140818770865aca94dfc2337e9527a6 100644 (file)
@@ -83,8 +83,6 @@ static struct inode *get_cramfs_inode(struct super_block *sb,
                        inode->i_op = &page_symlink_inode_operations;
                        inode->i_data.a_ops = &cramfs_aops;
                } else {
-                       inode->i_size = 0;
-                       inode->i_blocks = 0;
                        init_special_inode(inode, inode->i_mode,
                                old_decode_dev(cramfs_inode->size));
                }
index 3dbe2169cf36358730317f3ac563cf985c3cbc0b..81ae9ea3c6e1c34e645e4d2541066ddb1f33a9ad 100644 (file)
@@ -37,9 +37,6 @@ static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t d
 
        if (inode) {
                inode->i_mode = mode;
-               inode->i_uid = 0;
-               inode->i_gid = 0;
-               inode->i_blocks = 0;
                inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
                switch (mode & S_IFMT) {
                default:
index fff96e152c0c16f18c3cecffd4ffae5b0604c2e0..5f3231b9633fd1192c3eb974c49f90e2f7addf89 100644 (file)
@@ -189,8 +189,6 @@ static int mknod_ptmx(struct super_block *sb)
        }
 
        inode->i_ino = 2;
-       inode->i_uid = inode->i_gid = 0;
-       inode->i_blocks = 0;
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
 
        mode = S_IFCHR|opts->ptmxmode;
@@ -300,8 +298,6 @@ devpts_fill_super(struct super_block *s, void *data, int silent)
                goto free_fsi;
        inode->i_ino = 1;
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
-       inode->i_blocks = 0;
-       inode->i_uid = inode->i_gid = 0;
        inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
        inode->i_op = &simple_dir_inode_operations;
        inode->i_fop = &simple_dir_operations;
index c237ccc8581c451e368e3f428278dff3378916aa..61bfff64e5af1368a37801311ebe9aed39f42e1e 100644 (file)
@@ -211,8 +211,6 @@ static struct hlist_head *dquot_hash;
 
 struct dqstats dqstats;
 
-static void dqput(struct dquot *dquot);
-
 static inline unsigned int
 hashfn(const struct super_block *sb, unsigned int id, int type)
 {
@@ -415,6 +413,17 @@ out_dqlock:
        return ret;
 }
 
+void dquot_destroy(struct dquot *dquot)
+{
+       kmem_cache_free(dquot_cachep, dquot);
+}
+EXPORT_SYMBOL(dquot_destroy);
+
+static inline void do_destroy_dquot(struct dquot *dquot)
+{
+       dquot->dq_sb->dq_op->destroy_dquot(dquot);
+}
+
 /* Invalidate all dquots on the list. Note that this function is called after
  * quota is disabled and pointers from inodes removed so there cannot be new
  * quota users. There can still be some users of quotas due to inodes being
@@ -463,9 +472,44 @@ restart:
                remove_dquot_hash(dquot);
                remove_free_dquot(dquot);
                remove_inuse(dquot);
-               kmem_cache_free(dquot_cachep, dquot);
+               do_destroy_dquot(dquot);
+       }
+       spin_unlock(&dq_list_lock);
+}
+
+/* Call callback for every active dquot on given filesystem */
+int dquot_scan_active(struct super_block *sb,
+                     int (*fn)(struct dquot *dquot, unsigned long priv),
+                     unsigned long priv)
+{
+       struct dquot *dquot, *old_dquot = NULL;
+       int ret = 0;
+
+       mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
+       spin_lock(&dq_list_lock);
+       list_for_each_entry(dquot, &inuse_list, dq_inuse) {
+               if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags))
+                       continue;
+               if (dquot->dq_sb != sb)
+                       continue;
+               /* Now we have active dquot so we can just increase use count */
+               atomic_inc(&dquot->dq_count);
+               dqstats.lookups++;
+               spin_unlock(&dq_list_lock);
+               dqput(old_dquot);
+               old_dquot = dquot;
+               ret = fn(dquot, priv);
+               if (ret < 0)
+                       goto out;
+               spin_lock(&dq_list_lock);
+               /* We are safe to continue now because our dquot could not
+                * be moved out of the inuse list while we hold the reference */
        }
        spin_unlock(&dq_list_lock);
+out:
+       dqput(old_dquot);
+       mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
+       return ret;
 }
 
 int vfs_quota_sync(struct super_block *sb, int type)
@@ -479,7 +523,7 @@ int vfs_quota_sync(struct super_block *sb, int type)
        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
                if (type != -1 && cnt != type)
                        continue;
-               if (!sb_has_quota_enabled(sb, cnt))
+               if (!sb_has_quota_active(sb, cnt))
                        continue;
                spin_lock(&dq_list_lock);
                dirty = &dqopt->info[cnt].dqi_dirty_list;
@@ -504,8 +548,8 @@ int vfs_quota_sync(struct super_block *sb, int type)
        }
 
        for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-               if ((cnt == type || type == -1) && sb_has_quota_enabled(sb, cnt)
-                       && info_dirty(&dqopt->info[cnt]))
+               if ((cnt == type || type == -1) && sb_has_quota_active(sb, cnt)
+                   && info_dirty(&dqopt->info[cnt]))
                        sb->dq_op->write_info(sb, cnt);
        spin_lock(&dq_list_lock);
        dqstats.syncs++;
@@ -527,7 +571,7 @@ static void prune_dqcache(int count)
                remove_dquot_hash(dquot);
                remove_free_dquot(dquot);
                remove_inuse(dquot);
-               kmem_cache_free(dquot_cachep, dquot);
+               do_destroy_dquot(dquot);
                count--;
                head = free_dquots.prev;
        }
@@ -558,7 +602,7 @@ static struct shrinker dqcache_shrinker = {
  * NOTE: If you change this function please check whether dqput_blocks() works right...
  * MUST be called with either dqptr_sem or dqonoff_mutex held
  */
-static void dqput(struct dquot *dquot)
+void dqput(struct dquot *dquot)
 {
        int ret;
 
@@ -584,7 +628,7 @@ we_slept:
                /* We have more than one user... nothing to do */
                atomic_dec(&dquot->dq_count);
                /* Releasing dquot during quotaoff phase? */
-               if (!sb_has_quota_enabled(dquot->dq_sb, dquot->dq_type) &&
+               if (!sb_has_quota_active(dquot->dq_sb, dquot->dq_type) &&
                    atomic_read(&dquot->dq_count) == 1)
                        wake_up(&dquot->dq_wait_unused);
                spin_unlock(&dq_list_lock);
@@ -625,11 +669,17 @@ we_slept:
        spin_unlock(&dq_list_lock);
 }
 
+struct dquot *dquot_alloc(struct super_block *sb, int type)
+{
+       return kmem_cache_zalloc(dquot_cachep, GFP_NOFS);
+}
+EXPORT_SYMBOL(dquot_alloc);
+
 static struct dquot *get_empty_dquot(struct super_block *sb, int type)
 {
        struct dquot *dquot;
 
-       dquot = kmem_cache_zalloc(dquot_cachep, GFP_NOFS);
+       dquot = sb->dq_op->alloc_dquot(sb, type);
        if(!dquot)
                return NODQUOT;
 
@@ -646,16 +696,34 @@ static struct dquot *get_empty_dquot(struct super_block *sb, int type)
        return dquot;
 }
 
+/*
+ * Check whether dquot is in memory.
+ * MUST be called with either dqptr_sem or dqonoff_mutex held
+ */
+int dquot_is_cached(struct super_block *sb, unsigned int id, int type)
+{
+       unsigned int hashent = hashfn(sb, id, type);
+       int ret = 0;
+
+        if (!sb_has_quota_active(sb, type))
+               return 0;
+       spin_lock(&dq_list_lock);
+       if (find_dquot(hashent, sb, id, type) != NODQUOT)
+               ret = 1;
+       spin_unlock(&dq_list_lock);
+       return ret;
+}
+
 /*
  * Get reference to dquot
  * MUST be called with either dqptr_sem or dqonoff_mutex held
  */
-static struct dquot *dqget(struct super_block *sb, unsigned int id, int type)
+struct dquot *dqget(struct super_block *sb, unsigned int id, int type)
 {
        unsigned int hashent = hashfn(sb, id, type);
        struct dquot *dquot, *empty = NODQUOT;
 
-        if (!sb_has_quota_enabled(sb, type))
+        if (!sb_has_quota_active(sb, type))
                return NODQUOT;
 we_slept:
        spin_lock(&dq_list_lock);
@@ -682,7 +750,7 @@ we_slept:
                dqstats.lookups++;
                spin_unlock(&dq_list_lock);
                if (empty)
-                       kmem_cache_free(dquot_cachep, empty);
+                       do_destroy_dquot(empty);
        }
        /* Wait for dq_lock - after this we know that either dquot_release() is already
         * finished or it will be canceled due to dq_count > 1 test */
@@ -820,7 +888,7 @@ static void drop_dquot_ref(struct super_block *sb, int type)
        }
 }
 
-static inline void dquot_incr_inodes(struct dquot *dquot, unsigned long number)
+static inline void dquot_incr_inodes(struct dquot *dquot, qsize_t number)
 {
        dquot->dq_dqb.dqb_curinodes += number;
 }
@@ -830,9 +898,10 @@ static inline void dquot_incr_space(struct dquot *dquot, qsize_t number)
        dquot->dq_dqb.dqb_curspace += number;
 }
 
-static inline void dquot_decr_inodes(struct dquot *dquot, unsigned long number)
+static inline void dquot_decr_inodes(struct dquot *dquot, qsize_t number)
 {
-       if (dquot->dq_dqb.dqb_curinodes > number)
+       if (sb_dqopt(dquot->dq_sb)->flags & DQUOT_NEGATIVE_USAGE ||
+           dquot->dq_dqb.dqb_curinodes >= number)
                dquot->dq_dqb.dqb_curinodes -= number;
        else
                dquot->dq_dqb.dqb_curinodes = 0;
@@ -843,11 +912,12 @@ static inline void dquot_decr_inodes(struct dquot *dquot, unsigned long number)
 
 static inline void dquot_decr_space(struct dquot *dquot, qsize_t number)
 {
-       if (dquot->dq_dqb.dqb_curspace > number)
+       if (sb_dqopt(dquot->dq_sb)->flags & DQUOT_NEGATIVE_USAGE ||
+           dquot->dq_dqb.dqb_curspace >= number)
                dquot->dq_dqb.dqb_curspace -= number;
        else
                dquot->dq_dqb.dqb_curspace = 0;
-       if (toqb(dquot->dq_dqb.dqb_curspace) <= dquot->dq_dqb.dqb_bsoftlimit)
+       if (dquot->dq_dqb.dqb_curspace <= dquot->dq_dqb.dqb_bsoftlimit)
                dquot->dq_dqb.dqb_btime = (time_t) 0;
        clear_bit(DQ_BLKS_B, &dquot->dq_flags);
 }
@@ -1023,10 +1093,11 @@ static inline char ignore_hardlimit(struct dquot *dquot)
 }
 
 /* needs dq_data_lock */
-static int check_idq(struct dquot *dquot, ulong inodes, char *warntype)
+static int check_idq(struct dquot *dquot, qsize_t inodes, char *warntype)
 {
        *warntype = QUOTA_NL_NOWARN;
-       if (inodes <= 0 || test_bit(DQ_FAKE_B, &dquot->dq_flags))
+       if (!sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_type) ||
+           test_bit(DQ_FAKE_B, &dquot->dq_flags))
                return QUOTA_OK;
 
        if (dquot->dq_dqb.dqb_ihardlimit &&
@@ -1058,11 +1129,12 @@ static int check_idq(struct dquot *dquot, ulong inodes, char *warntype)
 static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *warntype)
 {
        *warntype = QUOTA_NL_NOWARN;
-       if (space <= 0 || test_bit(DQ_FAKE_B, &dquot->dq_flags))
+       if (!sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_type) ||
+           test_bit(DQ_FAKE_B, &dquot->dq_flags))
                return QUOTA_OK;
 
        if (dquot->dq_dqb.dqb_bhardlimit &&
-          toqb(dquot->dq_dqb.dqb_curspace + space) > dquot->dq_dqb.dqb_bhardlimit &&
+           dquot->dq_dqb.dqb_curspace + space > dquot->dq_dqb.dqb_bhardlimit &&
             !ignore_hardlimit(dquot)) {
                if (!prealloc)
                        *warntype = QUOTA_NL_BHARDWARN;
@@ -1070,7 +1142,7 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *war
        }
 
        if (dquot->dq_dqb.dqb_bsoftlimit &&
-          toqb(dquot->dq_dqb.dqb_curspace + space) > dquot->dq_dqb.dqb_bsoftlimit &&
+           dquot->dq_dqb.dqb_curspace + space > dquot->dq_dqb.dqb_bsoftlimit &&
            dquot->dq_dqb.dqb_btime && get_seconds() >= dquot->dq_dqb.dqb_btime &&
             !ignore_hardlimit(dquot)) {
                if (!prealloc)
@@ -1079,7 +1151,7 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *war
        }
 
        if (dquot->dq_dqb.dqb_bsoftlimit &&
-          toqb(dquot->dq_dqb.dqb_curspace + space) > dquot->dq_dqb.dqb_bsoftlimit &&
+           dquot->dq_dqb.dqb_curspace + space > dquot->dq_dqb.dqb_bsoftlimit &&
            dquot->dq_dqb.dqb_btime == 0) {
                if (!prealloc) {
                        *warntype = QUOTA_NL_BSOFTWARN;
@@ -1096,10 +1168,11 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *war
        return QUOTA_OK;
 }
 
-static int info_idq_free(struct dquot *dquot, ulong inodes)
+static int info_idq_free(struct dquot *dquot, qsize_t inodes)
 {
        if (test_bit(DQ_FAKE_B, &dquot->dq_flags) ||
-           dquot->dq_dqb.dqb_curinodes <= dquot->dq_dqb.dqb_isoftlimit)
+           dquot->dq_dqb.dqb_curinodes <= dquot->dq_dqb.dqb_isoftlimit ||
+           !sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_type))
                return QUOTA_NL_NOWARN;
 
        if (dquot->dq_dqb.dqb_curinodes - inodes <= dquot->dq_dqb.dqb_isoftlimit)
@@ -1113,15 +1186,13 @@ static int info_idq_free(struct dquot *dquot, ulong inodes)
 static int info_bdq_free(struct dquot *dquot, qsize_t space)
 {
        if (test_bit(DQ_FAKE_B, &dquot->dq_flags) ||
-           toqb(dquot->dq_dqb.dqb_curspace) <= dquot->dq_dqb.dqb_bsoftlimit)
+           dquot->dq_dqb.dqb_curspace <= dquot->dq_dqb.dqb_bsoftlimit)
                return QUOTA_NL_NOWARN;
 
-       if (toqb(dquot->dq_dqb.dqb_curspace - space) <=
-           dquot->dq_dqb.dqb_bsoftlimit)
+       if (dquot->dq_dqb.dqb_curspace - space <= dquot->dq_dqb.dqb_bsoftlimit)
                return QUOTA_NL_BSOFTBELOW;
-       if (toqb(dquot->dq_dqb.dqb_curspace) >= dquot->dq_dqb.dqb_bhardlimit &&
-           toqb(dquot->dq_dqb.dqb_curspace - space) <
-                                               dquot->dq_dqb.dqb_bhardlimit)
+       if (dquot->dq_dqb.dqb_curspace >= dquot->dq_dqb.dqb_bhardlimit &&
+           dquot->dq_dqb.dqb_curspace - space < dquot->dq_dqb.dqb_bhardlimit)
                return QUOTA_NL_BHARDBELOW;
        return QUOTA_NL_NOWARN;
 }
@@ -1166,17 +1237,23 @@ out_err:
  *     Release all quotas referenced by inode
  *     Transaction must be started at an entry
  */
-int dquot_drop(struct inode *inode)
+int dquot_drop_locked(struct inode *inode)
 {
        int cnt;
 
-       down_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
                if (inode->i_dquot[cnt] != NODQUOT) {
                        dqput(inode->i_dquot[cnt]);
                        inode->i_dquot[cnt] = NODQUOT;
                }
        }
+       return 0;
+}
+
+int dquot_drop(struct inode *inode)
+{
+       down_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
+       dquot_drop_locked(inode);
        up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
        return 0;
 }
@@ -1264,7 +1341,7 @@ warn_put_all:
 /*
  * This operation can block, but only after everything is updated
  */
-int dquot_alloc_inode(const struct inode *inode, unsigned long number)
+int dquot_alloc_inode(const struct inode *inode, qsize_t number)
 {
        int cnt, ret = NO_QUOTA;
        char warntype[MAXQUOTAS];
@@ -1349,7 +1426,7 @@ out_sub:
 /*
  * This operation can block, but only after everything is updated
  */
-int dquot_free_inode(const struct inode *inode, unsigned long number)
+int dquot_free_inode(const struct inode *inode, qsize_t number)
 {
        unsigned int cnt;
        char warntype[MAXQUOTAS];
@@ -1495,7 +1572,7 @@ warn_put_all:
 /* Wrapper for transferring ownership of an inode */
 int vfs_dq_transfer(struct inode *inode, struct iattr *iattr)
 {
-       if (sb_any_quota_enabled(inode->i_sb) && !IS_NOQUOTA(inode)) {
+       if (sb_any_quota_active(inode->i_sb) && !IS_NOQUOTA(inode)) {
                vfs_dq_init(inode);
                if (inode->i_sb->dq_op->transfer(inode, iattr) == NO_QUOTA)
                        return 1;
@@ -1533,54 +1610,27 @@ struct dquot_operations dquot_operations = {
        .acquire_dquot  = dquot_acquire,
        .release_dquot  = dquot_release,
        .mark_dirty     = dquot_mark_dquot_dirty,
-       .write_info     = dquot_commit_info
+       .write_info     = dquot_commit_info,
+       .alloc_dquot    = dquot_alloc,
+       .destroy_dquot  = dquot_destroy,
 };
 
-static inline void set_enable_flags(struct quota_info *dqopt, int type)
-{
-       switch (type) {
-               case USRQUOTA:
-                       dqopt->flags |= DQUOT_USR_ENABLED;
-                       dqopt->flags &= ~DQUOT_USR_SUSPENDED;
-                       break;
-               case GRPQUOTA:
-                       dqopt->flags |= DQUOT_GRP_ENABLED;
-                       dqopt->flags &= ~DQUOT_GRP_SUSPENDED;
-                       break;
-       }
-}
-
-static inline void reset_enable_flags(struct quota_info *dqopt, int type,
-                                     int remount)
-{
-       switch (type) {
-               case USRQUOTA:
-                       dqopt->flags &= ~DQUOT_USR_ENABLED;
-                       if (remount)
-                               dqopt->flags |= DQUOT_USR_SUSPENDED;
-                       else
-                               dqopt->flags &= ~DQUOT_USR_SUSPENDED;
-                       break;
-               case GRPQUOTA:
-                       dqopt->flags &= ~DQUOT_GRP_ENABLED;
-                       if (remount)
-                               dqopt->flags |= DQUOT_GRP_SUSPENDED;
-                       else
-                               dqopt->flags &= ~DQUOT_GRP_SUSPENDED;
-                       break;
-       }
-}
-
-
 /*
  * Turn quota off on a device. type == -1 ==> quotaoff for all types (umount)
  */
-int vfs_quota_off(struct super_block *sb, int type, int remount)
+int vfs_quota_disable(struct super_block *sb, int type, unsigned int flags)
 {
        int cnt, ret = 0;
        struct quota_info *dqopt = sb_dqopt(sb);
        struct inode *toputinode[MAXQUOTAS];
 
+       /* Cannot turn off usage accounting without turning off limits, or
+        * suspend quotas and simultaneously turn quotas off. */
+       if ((flags & DQUOT_USAGE_ENABLED && !(flags & DQUOT_LIMITS_ENABLED))
+           || (flags & DQUOT_SUSPENDED && flags & (DQUOT_LIMITS_ENABLED |
+           DQUOT_USAGE_ENABLED)))
+               return -EINVAL;
+
        /* We need to serialize quota_off() for device */
        mutex_lock(&dqopt->dqonoff_mutex);
 
@@ -1589,7 +1639,7 @@ int vfs_quota_off(struct super_block *sb, int type, int remount)
         * sometimes we are called when fill_super() failed and calling
         * sync_fs() in such cases does no good.
         */
-       if (!sb_any_quota_enabled(sb) && !sb_any_quota_suspended(sb)) {
+       if (!sb_any_quota_loaded(sb)) {
                mutex_unlock(&dqopt->dqonoff_mutex);
                return 0;
        }
@@ -1597,17 +1647,28 @@ int vfs_quota_off(struct super_block *sb, int type, int remount)
                toputinode[cnt] = NULL;
                if (type != -1 && cnt != type)
                        continue;
-               /* If we keep inodes of quota files after remount and quotaoff
-                * is called, drop kept inodes. */
-               if (!remount && sb_has_quota_suspended(sb, cnt)) {
-                       iput(dqopt->files[cnt]);
-                       dqopt->files[cnt] = NULL;
-                       reset_enable_flags(dqopt, cnt, 0);
+               if (!sb_has_quota_loaded(sb, cnt))
                        continue;
+
+               if (flags & DQUOT_SUSPENDED) {
+                       dqopt->flags |=
+                               dquot_state_flag(DQUOT_SUSPENDED, cnt);
+               } else {
+                       dqopt->flags &= ~dquot_state_flag(flags, cnt);
+                       /* Turning off suspended quotas? */
+                       if (!sb_has_quota_loaded(sb, cnt) &&
+                           sb_has_quota_suspended(sb, cnt)) {
+                               dqopt->flags &= ~dquot_state_flag(
+                                                       DQUOT_SUSPENDED, cnt);
+                               iput(dqopt->files[cnt]);
+                               dqopt->files[cnt] = NULL;
+                               continue;
+                       }
                }
-               if (!sb_has_quota_enabled(sb, cnt))
+
+               /* We still have to keep quota loaded? */
+               if (sb_has_quota_loaded(sb, cnt) && !(flags & DQUOT_SUSPENDED))
                        continue;
-               reset_enable_flags(dqopt, cnt, remount);
 
                /* Note: these are blocking operations */
                drop_dquot_ref(sb, cnt);
@@ -1623,7 +1684,7 @@ int vfs_quota_off(struct super_block *sb, int type, int remount)
                put_quota_format(dqopt->info[cnt].dqi_format);
 
                toputinode[cnt] = dqopt->files[cnt];
-               if (!remount)
+               if (!sb_has_quota_loaded(sb, cnt))
                        dqopt->files[cnt] = NULL;
                dqopt->info[cnt].dqi_flags = 0;
                dqopt->info[cnt].dqi_igrace = 0;
@@ -1631,6 +1692,11 @@ int vfs_quota_off(struct super_block *sb, int type, int remount)
                dqopt->ops[cnt] = NULL;
        }
        mutex_unlock(&dqopt->dqonoff_mutex);
+
+       /* Skip syncing and setting flags if quota files are hidden */
+       if (dqopt->flags & DQUOT_QUOTA_SYS_FILE)
+               goto put_inodes;
+
        /* Sync the superblock so that buffers with quota data are written to
         * disk (and so userspace sees correct data afterwards). */
        if (sb->s_op->sync_fs)
@@ -1646,7 +1712,7 @@ int vfs_quota_off(struct super_block *sb, int type, int remount)
                        mutex_lock(&dqopt->dqonoff_mutex);
                        /* If quota was reenabled in the meantime, we have
                         * nothing to do */
-                       if (!sb_has_quota_enabled(sb, cnt)) {
+                       if (!sb_has_quota_loaded(sb, cnt)) {
                                mutex_lock_nested(&toputinode[cnt]->i_mutex, I_MUTEX_QUOTA);
                                toputinode[cnt]->i_flags &= ~(S_IMMUTABLE |
                                  S_NOATIME | S_NOQUOTA);
@@ -1655,26 +1721,43 @@ int vfs_quota_off(struct super_block *sb, int type, int remount)
                                mark_inode_dirty(toputinode[cnt]);
                        }
                        mutex_unlock(&dqopt->dqonoff_mutex);
+               }
+       if (sb->s_bdev)
+               invalidate_bdev(sb->s_bdev);
+put_inodes:
+       for (cnt = 0; cnt < MAXQUOTAS; cnt++)
+               if (toputinode[cnt]) {
                        /* On remount RO, we keep the inode pointer so that we
-                        * can reenable quota on the subsequent remount RW.
-                        * But we have better not keep inode pointer when there
-                        * is pending delete on the quota file... */
-                       if (!remount)
+                        * can reenable quota on the subsequent remount RW. We
+                        * have to check 'flags' variable and not use sb_has_
+                        * function because another quotaon / quotaoff could
+                        * change global state before we got here. We refuse
+                        * to suspend quotas when there is pending delete on
+                        * the quota file... */
+                       if (!(flags & DQUOT_SUSPENDED))
                                iput(toputinode[cnt]);
                        else if (!toputinode[cnt]->i_nlink)
                                ret = -EBUSY;
                }
-       if (sb->s_bdev)
-               invalidate_bdev(sb->s_bdev);
        return ret;
 }
 
+int vfs_quota_off(struct super_block *sb, int type, int remount)
+{
+       return vfs_quota_disable(sb, type, remount ? DQUOT_SUSPENDED :
+                                (DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED));
+}
+
 /*
  *     Turn quotas on on a device
  */
 
-/* Helper function when we already have the inode */
-static int vfs_quota_on_inode(struct inode *inode, int type, int format_id)
+/*
+ * Helper function to turn quotas on when we already have the inode of
+ * quota file and no quota information is loaded.
+ */
+static int vfs_load_quota_inode(struct inode *inode, int type, int format_id,
+       unsigned int flags)
 {
        struct quota_format_type *fmt = find_quota_format(format_id);
        struct super_block *sb = inode->i_sb;
@@ -1696,27 +1779,37 @@ static int vfs_quota_on_inode(struct inode *inode, int type, int format_id)
                error = -EINVAL;
                goto out_fmt;
        }
+       /* Usage always has to be set... */
+       if (!(flags & DQUOT_USAGE_ENABLED)) {
+               error = -EINVAL;
+               goto out_fmt;
+       }
 
-       /* As we bypass the pagecache we must now flush the inode so that
-        * we see all the changes from userspace... */
-       write_inode_now(inode, 1);
-       /* And now flush the block cache so that kernel sees the changes */
-       invalidate_bdev(sb->s_bdev);
+       if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE)) {
+               /* As we bypass the pagecache we must now flush the inode so
+                * that we see all the changes from userspace... */
+               write_inode_now(inode, 1);
+               /* And now flush the block cache so that kernel sees the
+                * changes */
+               invalidate_bdev(sb->s_bdev);
+       }
        mutex_lock(&inode->i_mutex);
        mutex_lock(&dqopt->dqonoff_mutex);
-       if (sb_has_quota_enabled(sb, type) ||
-                       sb_has_quota_suspended(sb, type)) {
+       if (sb_has_quota_loaded(sb, type)) {
                error = -EBUSY;
                goto out_lock;
        }
-       /* We don't want quota and atime on quota files (deadlocks possible)
-        * Also nobody should write to the file - we use special IO operations
-        * which ignore the immutable bit. */
-       down_write(&dqopt->dqptr_sem);
-       oldflags = inode->i_flags & (S_NOATIME | S_IMMUTABLE | S_NOQUOTA);
-       inode->i_flags |= S_NOQUOTA | S_NOATIME | S_IMMUTABLE;
-       up_write(&dqopt->dqptr_sem);
-       sb->dq_op->drop(inode);
+
+       if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE)) {
+               /* We don't want quota and atime on quota files (deadlocks
+                * possible) Also nobody should write to the file - we use
+                * special IO operations which ignore the immutable bit. */
+               down_write(&dqopt->dqptr_sem);
+               oldflags = inode->i_flags & (S_NOATIME | S_IMMUTABLE | S_NOQUOTA);
+               inode->i_flags |= S_NOQUOTA | S_NOATIME | S_IMMUTABLE;
+               up_write(&dqopt->dqptr_sem);
+               sb->dq_op->drop(inode);
+       }
 
        error = -EIO;
        dqopt->files[type] = igrab(inode);
@@ -1737,7 +1830,7 @@ static int vfs_quota_on_inode(struct inode *inode, int type, int format_id)
        }
        mutex_unlock(&dqopt->dqio_mutex);
        mutex_unlock(&inode->i_mutex);
-       set_enable_flags(dqopt, type);
+       dqopt->flags |= dquot_state_flag(flags, type);
 
        add_dquot_ref(sb, type);
        mutex_unlock(&dqopt->dqonoff_mutex);
@@ -1770,20 +1863,23 @@ static int vfs_quota_on_remount(struct super_block *sb, int type)
        struct quota_info *dqopt = sb_dqopt(sb);
        struct inode *inode;
        int ret;
+       unsigned int flags;
 
        mutex_lock(&dqopt->dqonoff_mutex);
        if (!sb_has_quota_suspended(sb, type)) {
                mutex_unlock(&dqopt->dqonoff_mutex);
                return 0;
        }
-       BUG_ON(sb_has_quota_enabled(sb, type));
-
        inode = dqopt->files[type];
        dqopt->files[type] = NULL;
-       reset_enable_flags(dqopt, type, 0);
+       flags = dqopt->flags & dquot_state_flag(DQUOT_USAGE_ENABLED |
+                                               DQUOT_LIMITS_ENABLED, type);
+       dqopt->flags &= ~dquot_state_flag(DQUOT_STATE_FLAGS, type);
        mutex_unlock(&dqopt->dqonoff_mutex);
 
-       ret = vfs_quota_on_inode(inode, type, dqopt->info[type].dqi_fmt_id);
+       flags = dquot_generic_flag(flags, type);
+       ret = vfs_load_quota_inode(inode, type, dqopt->info[type].dqi_fmt_id,
+                                  flags);
        iput(inode);
 
        return ret;
@@ -1799,12 +1895,12 @@ int vfs_quota_on_path(struct super_block *sb, int type, int format_id,
        if (path->mnt->mnt_sb != sb)
                error = -EXDEV;
        else
-               error = vfs_quota_on_inode(path->dentry->d_inode, type,
-                                          format_id);
+               error = vfs_load_quota_inode(path->dentry->d_inode, type,
+                                            format_id, DQUOT_USAGE_ENABLED |
+                                            DQUOT_LIMITS_ENABLED);
        return error;
 }
 
-/* Actual function called from quotactl() */
 int vfs_quota_on(struct super_block *sb, int type, int format_id, char *name,
                 int remount)
 {
@@ -1822,6 +1918,50 @@ int vfs_quota_on(struct super_block *sb, int type, int format_id, char *name,
        return error;
 }
 
+/*
+ * More powerful function for turning on quotas allowing setting
+ * of individual quota flags
+ */
+int vfs_quota_enable(struct inode *inode, int type, int format_id,
+               unsigned int flags)
+{
+       int ret = 0;
+       struct super_block *sb = inode->i_sb;
+       struct quota_info *dqopt = sb_dqopt(sb);
+
+       /* Just unsuspend quotas? */
+       if (flags & DQUOT_SUSPENDED)
+               return vfs_quota_on_remount(sb, type);
+       if (!flags)
+               return 0;
+       /* Just updating flags needed? */
+       if (sb_has_quota_loaded(sb, type)) {
+               mutex_lock(&dqopt->dqonoff_mutex);
+               /* Now do a reliable test... */
+               if (!sb_has_quota_loaded(sb, type)) {
+                       mutex_unlock(&dqopt->dqonoff_mutex);
+                       goto load_quota;
+               }
+               if (flags & DQUOT_USAGE_ENABLED &&
+                   sb_has_quota_usage_enabled(sb, type)) {
+                       ret = -EBUSY;
+                       goto out_lock;
+               }
+               if (flags & DQUOT_LIMITS_ENABLED &&
+                   sb_has_quota_limits_enabled(sb, type)) {
+                       ret = -EBUSY;
+                       goto out_lock;
+               }
+               sb_dqopt(sb)->flags |= dquot_state_flag(flags, type);
+out_lock:
+               mutex_unlock(&dqopt->dqonoff_mutex);
+               return ret;
+       }
+
+load_quota:
+       return vfs_load_quota_inode(inode, type, format_id, flags);
+}
+
 /*
  * This function is used when filesystem needs to initialize quotas
  * during mount time.
@@ -1843,7 +1983,8 @@ int vfs_quota_on_mount(struct super_block *sb, char *qf_name,
 
        error = security_quota_on(dentry);
        if (!error)
-               error = vfs_quota_on_inode(dentry->d_inode, type, format_id);
+               error = vfs_load_quota_inode(dentry->d_inode, type, format_id,
+                               DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED);
 
 out:
        dput(dentry);
@@ -1866,14 +2007,24 @@ int vfs_dq_quota_on_remount(struct super_block *sb)
        return ret;
 }
 
+static inline qsize_t qbtos(qsize_t blocks)
+{
+       return blocks << QIF_DQBLKSIZE_BITS;
+}
+
+static inline qsize_t stoqb(qsize_t space)
+{
+       return (space + QIF_DQBLKSIZE - 1) >> QIF_DQBLKSIZE_BITS;
+}
+
 /* Generic routine for getting common part of quota structure */
 static void do_get_dqblk(struct dquot *dquot, struct if_dqblk *di)
 {
        struct mem_dqblk *dm = &dquot->dq_dqb;
 
        spin_lock(&dq_data_lock);
-       di->dqb_bhardlimit = dm->dqb_bhardlimit;
-       di->dqb_bsoftlimit = dm->dqb_bsoftlimit;
+       di->dqb_bhardlimit = stoqb(dm->dqb_bhardlimit);
+       di->dqb_bsoftlimit = stoqb(dm->dqb_bsoftlimit);
        di->dqb_curspace = dm->dqb_curspace;
        di->dqb_ihardlimit = dm->dqb_ihardlimit;
        di->dqb_isoftlimit = dm->dqb_isoftlimit;
@@ -1918,28 +2069,36 @@ static int do_set_dqblk(struct dquot *dquot, struct if_dqblk *di)
        if (di->dqb_valid & QIF_SPACE) {
                dm->dqb_curspace = di->dqb_curspace;
                check_blim = 1;
+               __set_bit(DQ_LASTSET_B + QIF_SPACE_B, &dquot->dq_flags);
        }
        if (di->dqb_valid & QIF_BLIMITS) {
-               dm->dqb_bsoftlimit = di->dqb_bsoftlimit;
-               dm->dqb_bhardlimit = di->dqb_bhardlimit;
+               dm->dqb_bsoftlimit = qbtos(di->dqb_bsoftlimit);
+               dm->dqb_bhardlimit = qbtos(di->dqb_bhardlimit);
                check_blim = 1;
+               __set_bit(DQ_LASTSET_B + QIF_BLIMITS_B, &dquot->dq_flags);
        }
        if (di->dqb_valid & QIF_INODES) {
                dm->dqb_curinodes = di->dqb_curinodes;
                check_ilim = 1;
+               __set_bit(DQ_LASTSET_B + QIF_INODES_B, &dquot->dq_flags);
        }
        if (di->dqb_valid & QIF_ILIMITS) {
                dm->dqb_isoftlimit = di->dqb_isoftlimit;
                dm->dqb_ihardlimit = di->dqb_ihardlimit;
                check_ilim = 1;
+               __set_bit(DQ_LASTSET_B + QIF_ILIMITS_B, &dquot->dq_flags);
        }
-       if (di->dqb_valid & QIF_BTIME)
+       if (di->dqb_valid & QIF_BTIME) {
                dm->dqb_btime = di->dqb_btime;
-       if (di->dqb_valid & QIF_ITIME)
+               __set_bit(DQ_LASTSET_B + QIF_BTIME_B, &dquot->dq_flags);
+       }
+       if (di->dqb_valid & QIF_ITIME) {
                dm->dqb_itime = di->dqb_itime;
+               __set_bit(DQ_LASTSET_B + QIF_ITIME_B, &dquot->dq_flags);
+       }
 
        if (check_blim) {
-               if (!dm->dqb_bsoftlimit || toqb(dm->dqb_curspace) < dm->dqb_bsoftlimit) {
+               if (!dm->dqb_bsoftlimit || dm->dqb_curspace < dm->dqb_bsoftlimit) {
                        dm->dqb_btime = 0;
                        clear_bit(DQ_BLKS_B, &dquot->dq_flags);
                }
@@ -1970,12 +2129,14 @@ int vfs_set_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *d
        int rc;
 
        mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
-       if (!(dquot = dqget(sb, id, type))) {
-               mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
-               return -ESRCH;
+       dquot = dqget(sb, id, type);
+       if (!dquot) {
+               rc = -ESRCH;
+               goto out;
        }
        rc = do_set_dqblk(dquot, di);
        dqput(dquot);
+out:
        mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
        return rc;
 }
@@ -1986,7 +2147,7 @@ int vfs_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii)
        struct mem_dqinfo *mi;
   
        mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
-       if (!sb_has_quota_enabled(sb, type)) {
+       if (!sb_has_quota_active(sb, type)) {
                mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
                return -ESRCH;
        }
@@ -2005,11 +2166,12 @@ int vfs_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii)
 int vfs_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii)
 {
        struct mem_dqinfo *mi;
+       int err = 0;
 
        mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
-       if (!sb_has_quota_enabled(sb, type)) {
-               mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
-               return -ESRCH;
+       if (!sb_has_quota_active(sb, type)) {
+               err = -ESRCH;
+               goto out;
        }
        mi = sb_dqopt(sb)->info + type;
        spin_lock(&dq_data_lock);
@@ -2023,8 +2185,9 @@ int vfs_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii)
        mark_info_dirty(sb, type);
        /* Force write to disk */
        sb->dq_op->write_info(sb, type);
+out:
        mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
-       return 0;
+       return err;
 }
 
 struct quotactl_ops vfs_quotactl_ops = {
@@ -2186,10 +2349,13 @@ EXPORT_SYMBOL(register_quota_format);
 EXPORT_SYMBOL(unregister_quota_format);
 EXPORT_SYMBOL(dqstats);
 EXPORT_SYMBOL(dq_data_lock);
+EXPORT_SYMBOL(vfs_quota_enable);
 EXPORT_SYMBOL(vfs_quota_on);
 EXPORT_SYMBOL(vfs_quota_on_path);
 EXPORT_SYMBOL(vfs_quota_on_mount);
+EXPORT_SYMBOL(vfs_quota_disable);
 EXPORT_SYMBOL(vfs_quota_off);
+EXPORT_SYMBOL(dquot_scan_active);
 EXPORT_SYMBOL(vfs_quota_sync);
 EXPORT_SYMBOL(vfs_get_dqinfo);
 EXPORT_SYMBOL(vfs_set_dqinfo);
@@ -2202,7 +2368,11 @@ EXPORT_SYMBOL(dquot_release);
 EXPORT_SYMBOL(dquot_mark_dquot_dirty);
 EXPORT_SYMBOL(dquot_initialize);
 EXPORT_SYMBOL(dquot_drop);
+EXPORT_SYMBOL(dquot_drop_locked);
 EXPORT_SYMBOL(vfs_dq_drop);
+EXPORT_SYMBOL(dqget);
+EXPORT_SYMBOL(dqput);
+EXPORT_SYMBOL(dquot_is_cached);
 EXPORT_SYMBOL(dquot_alloc_space);
 EXPORT_SYMBOL(dquot_alloc_inode);
 EXPORT_SYMBOL(dquot_free_space);
index eb3dc4c7ac066c45c99d26218ccda7f623cae9c6..713834371229b2d011d8355d6365810ab2b9eafe 100644 (file)
@@ -275,18 +275,9 @@ static int ecryptfs_release(struct inode *inode, struct file *file)
 static int
 ecryptfs_fsync(struct file *file, struct dentry *dentry, int datasync)
 {
-       struct file *lower_file = ecryptfs_file_to_lower(file);
-       struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
-       struct inode *lower_inode = lower_dentry->d_inode;
-       int rc = -EINVAL;
-
-       if (lower_inode->i_fop->fsync) {
-               mutex_lock(&lower_inode->i_mutex);
-               rc = lower_inode->i_fop->fsync(lower_file, lower_dentry,
-                                              datasync);
-               mutex_unlock(&lower_inode->i_mutex);
-       }
-       return rc;
+       return vfs_fsync(ecryptfs_file_to_lower(file),
+                        ecryptfs_dentry_to_lower(dentry),
+                        datasync);
 }
 
 static int ecryptfs_fasync(int fd, struct file *file, int flag)
index 5e78fc179886e6364f4a0d3a7019ee2d5274d9fb..0111906a8877301102513cf51a8df2c9c03bc85d 100644 (file)
@@ -612,8 +612,7 @@ ecryptfs_readlink(struct dentry *dentry, char __user * buf, int bufsiz)
        struct ecryptfs_crypt_stat *crypt_stat;
 
        lower_dentry = ecryptfs_dentry_to_lower(dentry);
-       if (!lower_dentry->d_inode->i_op ||
-           !lower_dentry->d_inode->i_op->readlink) {
+       if (!lower_dentry->d_inode->i_op->readlink) {
                rc = -EINVAL;
                goto out;
        }
index 04d7b3fa1ac6cd7679237cd2188a385c67bf960c..46cec2b69796d01d21cc0c92f14c345091aa0b85 100644 (file)
@@ -288,7 +288,7 @@ static int ecryptfs_write_begin(struct file *file,
        loff_t prev_page_end_size;
        int rc = 0;
 
-       page = __grab_cache_page(mapping, index);
+       page = grab_cache_page_write_begin(mapping, index, flags);
        if (!page)
                return -ENOMEM;
        *pagep = page;
index dfbf7009fbe78893a9516227629018dea44e85f4..9c33f542dc7785da628c2943c3626c878e0df07b 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
 #include <linux/audit.h>
 #include <linux/tracehook.h>
 #include <linux/kmod.h>
+#include <linux/fsnotify.h>
 
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
 #include <asm/tlb.h>
 #include "internal.h"
 
-#ifdef __alpha__
-/* for /sbin/loader handling in search_binary_handler() */
-#include <linux/a.out.h>
-#endif
-
 int core_uses_pid;
 char core_pattern[CORENAME_MAX_SIZE] = "core";
 int suid_dumpable = 0;
@@ -137,6 +133,8 @@ asmlinkage long sys_uselib(const char __user * library)
        if (IS_ERR(file))
                goto out;
 
+       fsnotify_open(file->f_path.dentry);
+
        error = -ENOEXEC;
        if(file->f_op) {
                struct linux_binfmt * fmt;
@@ -689,6 +687,8 @@ struct file *open_exec(const char *name)
        if (IS_ERR(file))
                return file;
 
+       fsnotify_open(file->f_path.dentry);
+
        err = deny_write_access(file);
        if (err) {
                fput(file);
@@ -1172,41 +1172,7 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
        unsigned int depth = bprm->recursion_depth;
        int try,retval;
        struct linux_binfmt *fmt;
-#ifdef __alpha__
-       /* handle /sbin/loader.. */
-       {
-           struct exec * eh = (struct exec *) bprm->buf;
-
-           if (!bprm->loader && eh->fh.f_magic == 0x183 &&
-               (eh->fh.f_flags & 0x3000) == 0x3000)
-           {
-               struct file * file;
-               unsigned long loader;
 
-               allow_write_access(bprm->file);
-               fput(bprm->file);
-               bprm->file = NULL;
-
-               loader = bprm->vma->vm_end - sizeof(void *);
-
-               file = open_exec("/sbin/loader");
-               retval = PTR_ERR(file);
-               if (IS_ERR(file))
-                       return retval;
-
-               /* Remember if the application is TASO.  */
-               bprm->taso = eh->ah.entry < 0x100000000UL;
-
-               bprm->file = file;
-               bprm->loader = loader;
-               retval = prepare_binprm(bprm);
-               if (retval<0)
-                       return retval;
-               /* should call search_binary_handler recursively here,
-                  but it does not matter */
-           }
-       }
-#endif
        retval = security_bprm_check(bprm);
        if (retval)
                return retval;
index c4bdccf976b59a6d8988b05273dc4df2162e125e..5fa453b49a649dd63e681c042742320b6f54a0bf 100644 (file)
@@ -1161,7 +1161,7 @@ static int ext3_write_begin(struct file *file, struct address_space *mapping,
        to = from + len;
 
 retry:
-       page = __grab_cache_page(mapping, index);
+       page = grab_cache_page_write_begin(mapping, index, flags);
        if (!page)
                return -ENOMEM;
        *pagep = page;
index 297ea8dfac7cc8a6a65a8be491b9de8ac5346bce..1dd2abe6313e3b656f42af6e2ebd63e2ec02a98c 100644 (file)
@@ -2175,8 +2175,7 @@ retry:
                 * We have a transaction open.  All is sweetness.  It also sets
                 * i_size in generic_commit_write().
                 */
-               err = __page_symlink(inode, symname, l,
-                               mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS);
+               err = __page_symlink(inode, symname, l, 1);
                if (err) {
                        drop_nlink(inode);
                        unlock_new_inode(inode);
index f6c94f232ec1e8fee05e47dfcc54b234c82e7cf0..c22d01467bd18bf3b3d8f2c69508c53c6b38d07e 100644 (file)
@@ -713,7 +713,9 @@ static struct dquot_operations ext3_quota_operations = {
        .acquire_dquot  = ext3_acquire_dquot,
        .release_dquot  = ext3_release_dquot,
        .mark_dirty     = ext3_mark_dquot_dirty,
-       .write_info     = ext3_write_info
+       .write_info     = ext3_write_info,
+       .alloc_dquot    = dquot_alloc,
+       .destroy_dquot  = dquot_destroy,
 };
 
 static struct quotactl_ops ext3_qctl_operations = {
@@ -1035,8 +1037,7 @@ static int parse_options (char *options, struct super_block *sb,
                case Opt_grpjquota:
                        qtype = GRPQUOTA;
 set_qf_name:
-                       if ((sb_any_quota_enabled(sb) ||
-                            sb_any_quota_suspended(sb)) &&
+                       if (sb_any_quota_loaded(sb) &&
                            !sbi->s_qf_names[qtype]) {
                                printk(KERN_ERR
                                        "EXT3-fs: Cannot change journaled "
@@ -1075,8 +1076,7 @@ set_qf_name:
                case Opt_offgrpjquota:
                        qtype = GRPQUOTA;
 clear_qf_name:
-                       if ((sb_any_quota_enabled(sb) ||
-                            sb_any_quota_suspended(sb)) &&
+                       if (sb_any_quota_loaded(sb) &&
                            sbi->s_qf_names[qtype]) {
                                printk(KERN_ERR "EXT3-fs: Cannot change "
                                        "journaled quota options when "
@@ -1095,8 +1095,7 @@ clear_qf_name:
                case Opt_jqfmt_vfsv0:
                        qfmt = QFMT_VFS_V0;
 set_qf_format:
-                       if ((sb_any_quota_enabled(sb) ||
-                            sb_any_quota_suspended(sb)) &&
+                       if (sb_any_quota_loaded(sb) &&
                            sbi->s_jquota_fmt != qfmt) {
                                printk(KERN_ERR "EXT3-fs: Cannot change "
                                        "journaled quota options when "
@@ -1115,8 +1114,7 @@ set_qf_format:
                        set_opt(sbi->s_mount_opt, GRPQUOTA);
                        break;
                case Opt_noquota:
-                       if (sb_any_quota_enabled(sb) ||
-                           sb_any_quota_suspended(sb)) {
+                       if (sb_any_quota_loaded(sb)) {
                                printk(KERN_ERR "EXT3-fs: Cannot change quota "
                                        "options when quota turned on.\n");
                                return 0;
index 445fde603df800cb4a1bf8144f34eb9aeb17b52a..b21f16713db0c1e2ad9a3a921082c60648643de7 100644 (file)
@@ -146,4 +146,10 @@ struct ext4_sb_info {
        struct flex_groups *s_flex_groups;
 };
 
+static inline spinlock_t *
+sb_bgl_lock(struct ext4_sb_info *sbi, unsigned int block_group)
+{
+       return bgl_lock_ptr(&sbi->s_blockgroup_lock, block_group);
+}
+
 #endif /* _EXT4_SB */
index 7c3325e0b005e152606f04bb8062fab18ab333ac..6702a49992a63e45aae49998e38c94b9723c7acc 100644 (file)
@@ -1346,7 +1346,7 @@ retry:
                goto out;
        }
 
-       page = __grab_cache_page(mapping, index);
+       page = grab_cache_page_write_begin(mapping, index, flags);
        if (!page) {
                ext4_journal_stop(handle);
                ret = -ENOMEM;
@@ -2550,7 +2550,7 @@ retry:
                goto out;
        }
 
-       page = __grab_cache_page(mapping, index);
+       page = grab_cache_page_write_begin(mapping, index, flags);
        if (!page) {
                ext4_journal_stop(handle);
                ret = -ENOMEM;
index da98a9012fa587a1583d9d714b888cc6ba321e27..9fd2a5e1be4dba61c58f44db91429b9ae14e79c8 100644 (file)
@@ -2212,8 +2212,7 @@ retry:
                 * We have a transaction open.  All is sweetness.  It also sets
                 * i_size in generic_commit_write().
                 */
-               err = __page_symlink(inode, symname, l,
-                               mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS);
+               err = __page_symlink(inode, symname, l, 1);
                if (err) {
                        clear_nlink(inode);
                        unlock_new_inode(inode);
index 04158ad74dbbc7192587f8d140d4cb8305bd8e46..9494bb2493901b353ad2f3be6f93535600896624 100644 (file)
@@ -803,7 +803,9 @@ static struct dquot_operations ext4_quota_operations = {
        .acquire_dquot  = ext4_acquire_dquot,
        .release_dquot  = ext4_release_dquot,
        .mark_dirty     = ext4_mark_dquot_dirty,
-       .write_info     = ext4_write_info
+       .write_info     = ext4_write_info,
+       .alloc_dquot    = dquot_alloc,
+       .destroy_dquot  = dquot_destroy,
 };
 
 static struct quotactl_ops ext4_qctl_operations = {
@@ -1142,8 +1144,7 @@ static int parse_options(char *options, struct super_block *sb,
                case Opt_grpjquota:
                        qtype = GRPQUOTA;
 set_qf_name:
-                       if ((sb_any_quota_enabled(sb) ||
-                            sb_any_quota_suspended(sb)) &&
+                       if (sb_any_quota_loaded(sb) &&
                            !sbi->s_qf_names[qtype]) {
                                printk(KERN_ERR
                                       "EXT4-fs: Cannot change journaled "
@@ -1182,8 +1183,7 @@ set_qf_name:
                case Opt_offgrpjquota:
                        qtype = GRPQUOTA;
 clear_qf_name:
-                       if ((sb_any_quota_enabled(sb) ||
-                            sb_any_quota_suspended(sb)) &&
+                       if (sb_any_quota_loaded(sb) &&
                            sbi->s_qf_names[qtype]) {
                                printk(KERN_ERR "EXT4-fs: Cannot change "
                                        "journaled quota options when "
@@ -1202,8 +1202,7 @@ clear_qf_name:
                case Opt_jqfmt_vfsv0:
                        qfmt = QFMT_VFS_V0;
 set_qf_format:
-                       if ((sb_any_quota_enabled(sb) ||
-                            sb_any_quota_suspended(sb)) &&
+                       if (sb_any_quota_loaded(sb) &&
                            sbi->s_jquota_fmt != qfmt) {
                                printk(KERN_ERR "EXT4-fs: Cannot change "
                                        "journaled quota options when "
@@ -1222,7 +1221,7 @@ set_qf_format:
                        set_opt(sbi->s_mount_opt, GRPQUOTA);
                        break;
                case Opt_noquota:
-                       if (sb_any_quota_enabled(sb)) {
+                       if (sb_any_quota_loaded(sb)) {
                                printk(KERN_ERR "EXT4-fs: Cannot change quota "
                                        "options when quota turned on.\n");
                                return 0;
index d0e20ced62ddd73fafdd6dec830d53fa479189bf..d488dcd7f2bbf0a14a4e23ebe328703b0b5b0d1c 100644 (file)
@@ -253,24 +253,27 @@ static int __init proc_filesystems_init(void)
 module_init(proc_filesystems_init);
 #endif
 
-struct file_system_type *get_fs_type(const char *name)
+static struct file_system_type *__get_fs_type(const char *name, int len)
 {
        struct file_system_type *fs;
-       const char *dot = strchr(name, '.');
-       unsigned len = dot ? dot - name : strlen(name);
 
        read_lock(&file_systems_lock);
        fs = *(find_filesystem(name, len));
        if (fs && !try_module_get(fs->owner))
                fs = NULL;
        read_unlock(&file_systems_lock);
-       if (!fs && (request_module("%.*s", len, name) == 0)) {
-               read_lock(&file_systems_lock);
-               fs = *(find_filesystem(name, len));
-               if (fs && !try_module_get(fs->owner))
-                       fs = NULL;
-               read_unlock(&file_systems_lock);
-       }
+       return fs;
+}
+
+struct file_system_type *get_fs_type(const char *name)
+{
+       struct file_system_type *fs;
+       const char *dot = strchr(name, '.');
+       int len = dot ? dot - name : strlen(name);
+
+       fs = __get_fs_type(name, len);
+       if (!fs && (request_module("%.*s", len, name) == 0))
+               fs = __get_fs_type(name, len);
 
        if (dot && fs && !(fs->fs_flags & FS_HAS_SUBTYPE)) {
                put_filesystem(fs);
index 34930a964b8258067ec957f9e5ff2a974c09cc58..4c9ee7011265a69faded2eee357fb23a37168bb1 100644 (file)
@@ -646,7 +646,7 @@ static int fuse_write_begin(struct file *file, struct address_space *mapping,
 {
        pgoff_t index = pos >> PAGE_CACHE_SHIFT;
 
-       *pagep = __grab_cache_page(mapping, index);
+       *pagep = grab_cache_page_write_begin(mapping, index, flags);
        if (!*pagep)
                return -ENOMEM;
        return 0;
@@ -779,7 +779,7 @@ static ssize_t fuse_fill_write_pages(struct fuse_req *req,
                        break;
 
                err = -ENOMEM;
-               page = __grab_cache_page(mapping, index);
+               page = grab_cache_page_write_begin(mapping, index, 0);
                if (!page)
                        break;
 
index 27563816e1c5a0f086657b12b0fab0cbc861fbef..15f710f2d4da1cf6aa1e9dea10f017788f442d54 100644 (file)
@@ -675,7 +675,7 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping,
                goto out_trans_fail;
 
        error = -ENOMEM;
-       page = __grab_cache_page(mapping, index);
+       page = grab_cache_page_write_begin(mapping, index, flags);
        *pagep = page;
        if (unlikely(!page))
                goto out_endtrans;
index 3a31451ac1704a86ef3d3b7ae9e9a73240ff29ad..5c538e0ec14beeba40899ea9eb20b83b8446388e 100644 (file)
@@ -501,7 +501,7 @@ int hostfs_write_begin(struct file *file, struct address_space *mapping,
 {
        pgoff_t index = pos >> PAGE_CACHE_SHIFT;
 
-       *pagep = __grab_cache_page(mapping, index);
+       *pagep = grab_cache_page_write_begin(mapping, index, flags);
        if (!*pagep)
                return -ENOMEM;
        return 0;
index 7d479ce3aceb602c687a7f022a7d3d6c1284de0f..0ab0c6f5f4383d177f07ae200163e6a3d80d703b 100644 (file)
@@ -506,7 +506,6 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb, uid_t uid,
                inode->i_mode = mode;
                inode->i_uid = uid;
                inode->i_gid = gid;
-               inode->i_blocks = 0;
                inode->i_mapping->a_ops = &hugetlbfs_aops;
                inode->i_mapping->backing_dev_info =&hugetlbfs_backing_dev_info;
                inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
index 7de1cda9248911241ead5c5c08f6033956bbe343..bd48e5e6d3e812b9965e8d2eca8fca0eab9e33ae 100644 (file)
@@ -131,6 +131,8 @@ struct inode *inode_init_always(struct super_block *sb, struct inode *inode)
        inode->i_op = &empty_iops;
        inode->i_fop = &empty_fops;
        inode->i_nlink = 1;
+       inode->i_uid = 0;
+       inode->i_gid = 0;
        atomic_set(&inode->i_writecount, 0);
        inode->i_size = 0;
        inode->i_blocks = 0;
index 3f8af0f1505b8d65bab47437a9fe707cfd8be4b1..6147ec3643a0ebd6280c478f0032fd8a0f051cd4 100644 (file)
@@ -855,10 +855,6 @@ root_found:
        }
        sbi->s_joliet_level = joliet_level;
 
-       /* check the root inode */
-       if (!inode->i_op)
-               goto out_bad_root;
-
        /* Make sure the root inode is a directory */
        if (!S_ISDIR(inode->i_mode)) {
                printk(KERN_WARNING
@@ -886,8 +882,6 @@ root_found:
        /*
         * Display error messages and free resources.
         */
-out_bad_root:
-       printk(KERN_WARNING "%s: root inode not initialized\n", __func__);
 out_iput:
        iput(inode);
        goto out_no_inode;
index ebc667bc54a8e1ac3c28e8ab6a40ce83f5274ad9..c8a1bace685a83b1b6944de6e7e5ad13faa4f61b 100644 (file)
@@ -509,6 +509,10 @@ void jbd2_journal_commit_transaction(journal_t *journal)
                if (is_journal_aborted(journal)) {
                        clear_buffer_jbddirty(jh2bh(jh));
                        JBUFFER_TRACE(jh, "journal is aborting: refile");
+                       jbd2_buffer_abort_trigger(jh,
+                                                 jh->b_frozen_data ?
+                                                 jh->b_frozen_triggers :
+                                                 jh->b_triggers);
                        jbd2_journal_refile_buffer(journal, jh);
                        /* If that was the last one, we need to clean up
                         * any descriptor buffers which may have been
@@ -844,6 +848,9 @@ restart_loop:
                 * data.
                 *
                 * Otherwise, we can just throw away the frozen data now.
+                *
+                * We also know that the frozen data has already fired
+                * its triggers if they exist, so we can clear that too.
                 */
                if (jh->b_committed_data) {
                        jbd2_free(jh->b_committed_data, bh->b_size);
@@ -851,10 +858,12 @@ restart_loop:
                        if (jh->b_frozen_data) {
                                jh->b_committed_data = jh->b_frozen_data;
                                jh->b_frozen_data = NULL;
+                               jh->b_frozen_triggers = NULL;
                        }
                } else if (jh->b_frozen_data) {
                        jbd2_free(jh->b_frozen_data, bh->b_size);
                        jh->b_frozen_data = NULL;
+                       jh->b_frozen_triggers = NULL;
                }
 
                spin_lock(&journal->j_list_lock);
index e70d657a19f810ad5f3c714e6bfff6e5303d226d..f6bff9d6f8df8193e6fc13f1a2b1763124d29cb6 100644 (file)
@@ -50,6 +50,7 @@ EXPORT_SYMBOL(jbd2_journal_unlock_updates);
 EXPORT_SYMBOL(jbd2_journal_get_write_access);
 EXPORT_SYMBOL(jbd2_journal_get_create_access);
 EXPORT_SYMBOL(jbd2_journal_get_undo_access);
+EXPORT_SYMBOL(jbd2_journal_set_triggers);
 EXPORT_SYMBOL(jbd2_journal_dirty_metadata);
 EXPORT_SYMBOL(jbd2_journal_release_buffer);
 EXPORT_SYMBOL(jbd2_journal_forget);
@@ -290,6 +291,7 @@ int jbd2_journal_write_metadata_buffer(transaction_t *transaction,
        struct page *new_page;
        unsigned int new_offset;
        struct buffer_head *bh_in = jh2bh(jh_in);
+       struct jbd2_buffer_trigger_type *triggers;
 
        /*
         * The buffer really shouldn't be locked: only the current committing
@@ -314,12 +316,22 @@ repeat:
                done_copy_out = 1;
                new_page = virt_to_page(jh_in->b_frozen_data);
                new_offset = offset_in_page(jh_in->b_frozen_data);
+               triggers = jh_in->b_frozen_triggers;
        } else {
                new_page = jh2bh(jh_in)->b_page;
                new_offset = offset_in_page(jh2bh(jh_in)->b_data);
+               triggers = jh_in->b_triggers;
        }
 
        mapped_data = kmap_atomic(new_page, KM_USER0);
+       /*
+        * Fire any commit trigger.  Do this before checking for escaping,
+        * as the trigger may modify the magic offset.  If a copy-out
+        * happens afterwards, it will have the correct data in the buffer.
+        */
+       jbd2_buffer_commit_trigger(jh_in, mapped_data + new_offset,
+                                  triggers);
+
        /*
         * Check for escaping
         */
@@ -352,6 +364,13 @@ repeat:
                new_page = virt_to_page(tmp);
                new_offset = offset_in_page(tmp);
                done_copy_out = 1;
+
+               /*
+                * This isn't strictly necessary, as we're using frozen
+                * data for the escaping, but it keeps consistency with
+                * b_frozen_data usage.
+                */
+               jh_in->b_frozen_triggers = jh_in->b_triggers;
        }
 
        /*
index 39b7805a599a79fd80c0150073cbf0f473fe8bcf..4f925a4f3d05051ec7b1edd65c50ecdabe27000a 100644 (file)
@@ -741,6 +741,12 @@ done:
                source = kmap_atomic(page, KM_USER0);
                memcpy(jh->b_frozen_data, source+offset, jh2bh(jh)->b_size);
                kunmap_atomic(source, KM_USER0);
+
+               /*
+                * Now that the frozen data is saved off, we need to store
+                * any matching triggers.
+                */
+               jh->b_frozen_triggers = jh->b_triggers;
        }
        jbd_unlock_bh_state(bh);
 
@@ -943,6 +949,47 @@ out:
        return err;
 }
 
+/**
+ * void jbd2_journal_set_triggers() - Add triggers for commit writeout
+ * @bh: buffer to trigger on
+ * @type: struct jbd2_buffer_trigger_type containing the trigger(s).
+ *
+ * Set any triggers on this journal_head.  This is always safe, because
+ * triggers for a committing buffer will be saved off, and triggers for
+ * a running transaction will match the buffer in that transaction.
+ *
+ * Call with NULL to clear the triggers.
+ */
+void jbd2_journal_set_triggers(struct buffer_head *bh,
+                              struct jbd2_buffer_trigger_type *type)
+{
+       struct journal_head *jh = bh2jh(bh);
+
+       jh->b_triggers = type;
+}
+
+void jbd2_buffer_commit_trigger(struct journal_head *jh, void *mapped_data,
+                               struct jbd2_buffer_trigger_type *triggers)
+{
+       struct buffer_head *bh = jh2bh(jh);
+
+       if (!triggers || !triggers->t_commit)
+               return;
+
+       triggers->t_commit(triggers, bh, mapped_data, bh->b_size);
+}
+
+void jbd2_buffer_abort_trigger(struct journal_head *jh,
+                              struct jbd2_buffer_trigger_type *triggers)
+{
+       if (!triggers || !triggers->t_abort)
+               return;
+
+       triggers->t_abort(triggers, jh2bh(jh));
+}
+
+
+
 /**
  * int jbd2_journal_dirty_metadata() -  mark a buffer as containing dirty metadata
  * @handle: transaction to add buffer to.
index 5a98aa87c8530b169ec0453f977860550df73f38..5edc2bf2058134505369a0f7844363f7e3a2ecfd 100644 (file)
@@ -132,7 +132,7 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
        uint32_t pageofs = index << PAGE_CACHE_SHIFT;
        int ret = 0;
 
-       pg = __grab_cache_page(mapping, index);
+       pg = grab_cache_page_write_begin(mapping, index, flags);
        if (!pg)
                return -ENOMEM;
        *pagep = pg;
index d6363d8309d0c5e53370c073e5e620a250d2567a..0f94381ca6d081a6e50af4c33f8228d60f10318a 100644 (file)
@@ -58,9 +58,9 @@
 
 /*
  * __mark_inode_dirty expects inodes to be hashed.  Since we don't want
- * special inodes in the fileset inode space, we hash them to a dummy head
+ * special inodes in the fileset inode space, we make them appear hashed,
+ * but do not put on any lists.
  */
-static HLIST_HEAD(aggregate_hash);
 
 /*
  * imap locks
@@ -496,7 +496,11 @@ struct inode *diReadSpecial(struct super_block *sb, ino_t inum, int secondary)
        /* release the page */
        release_metapage(mp);
 
-       hlist_add_head(&ip->i_hash, &aggregate_hash);
+       /*
+        * that will look hashed, but won't be on any list; hlist_del()
+        * will work fine and require no locking.
+        */
+       ip->i_hash.pprev = &ip->i_hash.next;
 
        return (ip);
 }
index e960a8321902cad9398447f3434f31f90a0f2b3c..49b44099dabbb9cef010c2394c8ba110440edee4 100644 (file)
@@ -231,7 +231,6 @@ int get_sb_pseudo(struct file_system_type *fs_type, char *name,
         */
        root->i_ino = 1;
        root->i_mode = S_IFDIR | S_IRUSR | S_IWUSR;
-       root->i_uid = root->i_gid = 0;
        root->i_atime = root->i_mtime = root->i_ctime = CURRENT_TIME;
        dentry = d_alloc(NULL, &d_name);
        if (!dentry) {
@@ -360,7 +359,7 @@ int simple_write_begin(struct file *file, struct address_space *mapping,
        index = pos >> PAGE_CACHE_SHIFT;
        from = pos & (PAGE_CACHE_SIZE - 1);
 
-       page = __grab_cache_page(mapping, index);
+       page = grab_cache_page_write_begin(mapping, index, flags);
        if (!page)
                return -ENOMEM;
 
@@ -436,8 +435,6 @@ int simple_fill_super(struct super_block *s, int magic, struct tree_descr *files
         */
        inode->i_ino = 1;
        inode->i_mode = S_IFDIR | 0755;
-       inode->i_uid = inode->i_gid = 0;
-       inode->i_blocks = 0;
        inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
        inode->i_op = &simple_dir_inode_operations;
        inode->i_fop = &simple_dir_operations;
@@ -464,8 +461,6 @@ int simple_fill_super(struct super_block *s, int magic, struct tree_descr *files
                if (!inode)
                        goto out;
                inode->i_mode = S_IFREG | files->mode;
-               inode->i_uid = inode->i_gid = 0;
-               inode->i_blocks = 0;
                inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
                inode->i_fop = files->ops;
                inode->i_ino = i;
index dd5c9f0bf82994d39020b6b9ad534cc094170ad9..f05bed242422eed8172c3a6acdc6b9838428eec4 100644 (file)
@@ -257,7 +257,7 @@ int inode_permission(struct inode *inode, int mask)
                        return -EACCES;
        }
 
-       if (inode->i_op && inode->i_op->permission)
+       if (inode->i_op->permission)
                retval = inode->i_op->permission(inode, mask);
        else
                retval = generic_permission(inode, mask, NULL);
@@ -432,7 +432,7 @@ static int exec_permission_lite(struct inode *inode)
 {
        umode_t mode = inode->i_mode;
 
-       if (inode->i_op && inode->i_op->permission)
+       if (inode->i_op->permission)
                return -EAGAIN;
 
        if (current_fsuid() == inode->i_uid)
@@ -908,9 +908,6 @@ static int __link_path_walk(const char *name, struct nameidata *nd)
                inode = next.dentry->d_inode;
                if (!inode)
                        goto out_dput;
-               err = -ENOTDIR; 
-               if (!inode->i_op)
-                       goto out_dput;
 
                if (inode->i_op->follow_link) {
                        err = do_follow_link(&next, nd);
@@ -920,9 +917,6 @@ static int __link_path_walk(const char *name, struct nameidata *nd)
                        inode = nd->path.dentry->d_inode;
                        if (!inode)
                                break;
-                       err = -ENOTDIR; 
-                       if (!inode->i_op)
-                               break;
                } else
                        path_to_nameidata(&next, nd);
                err = -ENOTDIR; 
@@ -961,7 +955,7 @@ last_component:
                        break;
                inode = next.dentry->d_inode;
                if ((lookup_flags & LOOKUP_FOLLOW)
-                   && inode && inode->i_op && inode->i_op->follow_link) {
+                   && inode && inode->i_op->follow_link) {
                        err = do_follow_link(&next, nd);
                        if (err)
                                goto return_err;
@@ -973,7 +967,7 @@ last_component:
                        break;
                if (lookup_flags & LOOKUP_DIRECTORY) {
                        err = -ENOTDIR; 
-                       if (!inode->i_op || !inode->i_op->lookup)
+                       if (!inode->i_op->lookup)
                                break;
                }
                goto return_base;
@@ -1469,7 +1463,7 @@ int vfs_create(struct inode *dir, struct dentry *dentry, int mode,
        if (error)
                return error;
 
-       if (!dir->i_op || !dir->i_op->create)
+       if (!dir->i_op->create)
                return -EACCES; /* shouldn't it be ENOSYS? */
        mode &= S_IALLUGO;
        mode |= S_IFREG;
@@ -1752,7 +1746,7 @@ do_last:
        error = -ENOENT;
        if (!path.dentry->d_inode)
                goto exit_dput;
-       if (path.dentry->d_inode->i_op && path.dentry->d_inode->i_op->follow_link)
+       if (path.dentry->d_inode->i_op->follow_link)
                goto do_link;
 
        path_to_nameidata(&path, &nd);
@@ -1933,7 +1927,7 @@ int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
        if ((S_ISCHR(mode) || S_ISBLK(mode)) && !capable(CAP_MKNOD))
                return -EPERM;
 
-       if (!dir->i_op || !dir->i_op->mknod)
+       if (!dir->i_op->mknod)
                return -EPERM;
 
        error = devcgroup_inode_mknod(mode, dev);
@@ -2035,7 +2029,7 @@ int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        if (error)
                return error;
 
-       if (!dir->i_op || !dir->i_op->mkdir)
+       if (!dir->i_op->mkdir)
                return -EPERM;
 
        mode &= (S_IRWXUGO|S_ISVTX);
@@ -2126,7 +2120,7 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry)
        if (error)
                return error;
 
-       if (!dir->i_op || !dir->i_op->rmdir)
+       if (!dir->i_op->rmdir)
                return -EPERM;
 
        DQUOT_INIT(dir);
@@ -2213,7 +2207,7 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry)
        if (error)
                return error;
 
-       if (!dir->i_op || !dir->i_op->unlink)
+       if (!dir->i_op->unlink)
                return -EPERM;
 
        DQUOT_INIT(dir);
@@ -2320,7 +2314,7 @@ int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname)
        if (error)
                return error;
 
-       if (!dir->i_op || !dir->i_op->symlink)
+       if (!dir->i_op->symlink)
                return -EPERM;
 
        error = security_inode_symlink(dir, dentry, oldname);
@@ -2401,7 +2395,7 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de
         */
        if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
                return -EPERM;
-       if (!dir->i_op || !dir->i_op->link)
+       if (!dir->i_op->link)
                return -EPERM;
        if (S_ISDIR(inode->i_mode))
                return -EPERM;
@@ -2608,7 +2602,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        if (error)
                return error;
 
-       if (!old_dir->i_op || !old_dir->i_op->rename)
+       if (!old_dir->i_op->rename)
                return -EPERM;
 
        DQUOT_INIT(old_dir);
@@ -2817,18 +2811,23 @@ void page_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie)
        }
 }
 
-int __page_symlink(struct inode *inode, const char *symname, int len,
-               gfp_t gfp_mask)
+/*
+ * The nofs argument instructs pagecache_write_begin to pass AOP_FLAG_NOFS
+ */
+int __page_symlink(struct inode *inode, const char *symname, int len, int nofs)
 {
        struct address_space *mapping = inode->i_mapping;
        struct page *page;
        void *fsdata;
        int err;
        char *kaddr;
+       unsigned int flags = AOP_FLAG_UNINTERRUPTIBLE;
+       if (nofs)
+               flags |= AOP_FLAG_NOFS;
 
 retry:
        err = pagecache_write_begin(NULL, mapping, 0, len-1,
-                               AOP_FLAG_UNINTERRUPTIBLE, &page, &fsdata);
+                               flags, &page, &fsdata);
        if (err)
                goto fail;
 
@@ -2852,7 +2851,7 @@ fail:
 int page_symlink(struct inode *inode, const char *symname, int len)
 {
        return __page_symlink(inode, symname, len,
-                       mapping_gfp_mask(inode->i_mapping));
+                       !(mapping_gfp_mask(inode->i_mapping) & __GFP_FS));
 }
 
 const struct inode_operations page_symlink_inode_operations = {
index d319b49f8f06f4046c408afe8a290a9e05b7920e..90f292b520d25eec248a9728b7d61cf20cd061f9 100644 (file)
@@ -354,7 +354,7 @@ static int nfs_write_begin(struct file *file, struct address_space *mapping,
                file->f_path.dentry->d_name.name,
                mapping->host->i_ino, len, (long long) pos);
 
-       page = __grab_cache_page(mapping, index);
+       page = grab_cache_page_write_begin(mapping, index, flags);
        if (!page)
                return -ENOMEM;
        *pagep = page;
index d1c5f787b365dc727fb65b81ca33e3cfb0ca2555..44aa92aba891c96fa7061ee5dda5bc6aaf6f0fec 100644 (file)
@@ -744,45 +744,16 @@ nfsd_close(struct file *filp)
        fput(filp);
 }
 
-/*
- * Sync a file
- * As this calls fsync (not fdatasync) there is no need for a write_inode
- * after it.
- */
-static inline int nfsd_dosync(struct file *filp, struct dentry *dp,
-                             const struct file_operations *fop)
-{
-       struct inode *inode = dp->d_inode;
-       int (*fsync) (struct file *, struct dentry *, int);
-       int err;
-
-       err = filemap_fdatawrite(inode->i_mapping);
-       if (err == 0 && fop && (fsync = fop->fsync))
-               err = fsync(filp, dp, 0);
-       if (err == 0)
-               err = filemap_fdatawait(inode->i_mapping);
-
-       return err;
-}
-       
-
 static int
 nfsd_sync(struct file *filp)
 {
-        int err;
-       struct inode *inode = filp->f_path.dentry->d_inode;
-       dprintk("nfsd: sync file %s\n", filp->f_path.dentry->d_name.name);
-       mutex_lock(&inode->i_mutex);
-       err=nfsd_dosync(filp, filp->f_path.dentry, filp->f_op);
-       mutex_unlock(&inode->i_mutex);
-
-       return err;
+       return vfs_fsync(filp, filp->f_path.dentry, 0);
 }
 
 int
-nfsd_sync_dir(struct dentry *dp)
+nfsd_sync_dir(struct dentry *dentry)
 {
-       return nfsd_dosync(NULL, dp, dp->d_inode->i_fop);
+       return vfs_fsync(NULL, dentry, 0);
 }
 
 /*
@@ -1211,7 +1182,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
        dirp = dentry->d_inode;
 
        err = nfserr_notdir;
-       if(!dirp->i_op || !dirp->i_op->lookup)
+       if (!dirp->i_op->lookup)
                goto out;
        /*
         * Check whether the response file handle has been verified yet.
@@ -1347,7 +1318,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
        /* Get all the sanity checks out of the way before
         * we lock the parent. */
        err = nfserr_notdir;
-       if(!dirp->i_op || !dirp->i_op->lookup)
+       if (!dirp->i_op->lookup)
                goto out;
        fh_lock_nested(fhp, I_MUTEX_PARENT);
 
@@ -1482,7 +1453,7 @@ nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp)
        inode = dentry->d_inode;
 
        err = nfserr_inval;
-       if (!inode->i_op || !inode->i_op->readlink)
+       if (!inode->i_op->readlink)
                goto out;
 
        touch_atime(fhp->fh_export->ex_path.mnt, dentry);
@@ -2162,7 +2133,7 @@ nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl)
        size_t size;
        int error;
 
-       if (!IS_POSIXACL(inode) || !inode->i_op ||
+       if (!IS_POSIXACL(inode) ||
            !inode->i_op->setxattr || !inode->i_op->removexattr)
                return -EOPNOTSUPP;
        switch(type) {
index 400f8064a548cc7777ca605db6477fc4b2379891..81b8644b0136cdb84fa9f254f329f7104fe4e7d3 100644 (file)
@@ -704,7 +704,7 @@ fput_and_out:
        return ret;
 }
 
-asmlinkage long sys_inotify_rm_watch(int fd, u32 wd)
+asmlinkage long sys_inotify_rm_watch(int fd, __s32 wd)
 {
        struct file *filp;
        struct inotify_device *dev;
index e9da092e27723a91d5c2bc9bd60a1645b494ca00..86bef156cf0a15b277d879021b24138a333d4eeb 100644 (file)
@@ -1406,9 +1406,6 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
                ni->allocated_size = sle64_to_cpu(
                                a->data.non_resident.allocated_size);
        }
-       /* Setup the operations for this attribute inode. */
-       vi->i_op = NULL;
-       vi->i_fop = NULL;
        if (NInoMstProtected(ni))
                vi->i_mapping->a_ops = &ntfs_mst_aops;
        else
index 589dcdfdfe3cfebab34e7186f46a09407985e774..01596079dd631022281eca93b34574cb8f4659ed 100644 (file)
@@ -12,6 +12,7 @@ obj-$(CONFIG_OCFS2_FS_USERSPACE_CLUSTER) += ocfs2_stack_user.o
 ocfs2-objs := \
        alloc.o                 \
        aops.o                  \
+       blockcheck.o            \
        buffer_head_io.o        \
        dcache.o                \
        dir.o                   \
@@ -35,8 +36,14 @@ ocfs2-objs := \
        sysfile.o               \
        uptodate.o              \
        ver.o                   \
+       quota_local.o           \
+       quota_global.o          \
        xattr.o
 
+ifeq ($(CONFIG_OCFS2_FS_POSIX_ACL),y)
+ocfs2-objs += acl.o
+endif
+
 ocfs2_stackglue-objs := stackglue.o
 ocfs2_stack_o2cb-objs := stack_o2cb.o
 ocfs2_stack_user-objs := stack_user.o
diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c
new file mode 100644 (file)
index 0000000..12dfb44
--- /dev/null
@@ -0,0 +1,479 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * acl.c
+ *
+ * Copyright (C) 2004, 2008 Oracle.  All rights reserved.
+ *
+ * CREDITS:
+ * Lots of code in this file is copy from linux/fs/ext3/acl.c.
+ * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+
+#define MLOG_MASK_PREFIX ML_INODE
+#include <cluster/masklog.h>
+
+#include "ocfs2.h"
+#include "alloc.h"
+#include "dlmglue.h"
+#include "file.h"
+#include "ocfs2_fs.h"
+
+#include "xattr.h"
+#include "acl.h"
+
+/*
+ * Convert from xattr value to acl struct.
+ */
+static struct posix_acl *ocfs2_acl_from_xattr(const void *value, size_t size)
+{
+       int n, count;
+       struct posix_acl *acl;
+
+       if (!value)
+               return NULL;
+       if (size < sizeof(struct posix_acl_entry))
+               return ERR_PTR(-EINVAL);
+
+       count = size / sizeof(struct posix_acl_entry);
+       if (count < 0)
+               return ERR_PTR(-EINVAL);
+       if (count == 0)
+               return NULL;
+
+       acl = posix_acl_alloc(count, GFP_NOFS);
+       if (!acl)
+               return ERR_PTR(-ENOMEM);
+       for (n = 0; n < count; n++) {
+               struct ocfs2_acl_entry *entry =
+                       (struct ocfs2_acl_entry *)value;
+
+               acl->a_entries[n].e_tag  = le16_to_cpu(entry->e_tag);
+               acl->a_entries[n].e_perm = le16_to_cpu(entry->e_perm);
+               acl->a_entries[n].e_id   = le32_to_cpu(entry->e_id);
+               value += sizeof(struct posix_acl_entry);
+
+       }
+       return acl;
+}
+
+/*
+ * Convert acl struct to xattr value.
+ */
+static void *ocfs2_acl_to_xattr(const struct posix_acl *acl, size_t *size)
+{
+       struct ocfs2_acl_entry *entry = NULL;
+       char *ocfs2_acl;
+       size_t n;
+
+       *size = acl->a_count * sizeof(struct posix_acl_entry);
+
+       ocfs2_acl = kmalloc(*size, GFP_NOFS);
+       if (!ocfs2_acl)
+               return ERR_PTR(-ENOMEM);
+
+       entry = (struct ocfs2_acl_entry *)ocfs2_acl;
+       for (n = 0; n < acl->a_count; n++, entry++) {
+               entry->e_tag  = cpu_to_le16(acl->a_entries[n].e_tag);
+               entry->e_perm = cpu_to_le16(acl->a_entries[n].e_perm);
+               entry->e_id   = cpu_to_le32(acl->a_entries[n].e_id);
+       }
+       return ocfs2_acl;
+}
+
+static struct posix_acl *ocfs2_get_acl_nolock(struct inode *inode,
+                                             int type,
+                                             struct buffer_head *di_bh)
+{
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       int name_index;
+       char *value = NULL;
+       struct posix_acl *acl;
+       int retval;
+
+       if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
+               return NULL;
+
+       switch (type) {
+       case ACL_TYPE_ACCESS:
+               name_index = OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS;
+               break;
+       case ACL_TYPE_DEFAULT:
+               name_index = OCFS2_XATTR_INDEX_POSIX_ACL_DEFAULT;
+               break;
+       default:
+               return ERR_PTR(-EINVAL);
+       }
+
+       retval = ocfs2_xattr_get_nolock(inode, di_bh, name_index, "", NULL, 0);
+       if (retval > 0) {
+               value = kmalloc(retval, GFP_NOFS);
+               if (!value)
+                       return ERR_PTR(-ENOMEM);
+               retval = ocfs2_xattr_get_nolock(inode, di_bh, name_index,
+                                               "", value, retval);
+       }
+
+       if (retval > 0)
+               acl = ocfs2_acl_from_xattr(value, retval);
+       else if (retval == -ENODATA || retval == 0)
+               acl = NULL;
+       else
+               acl = ERR_PTR(retval);
+
+       kfree(value);
+
+       return acl;
+}
+
+
+/*
+ * Get posix acl.
+ */
+static struct posix_acl *ocfs2_get_acl(struct inode *inode, int type)
+{
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       struct buffer_head *di_bh = NULL;
+       struct posix_acl *acl;
+       int ret;
+
+       if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
+               return NULL;
+
+       ret = ocfs2_inode_lock(inode, &di_bh, 0);
+       if (ret < 0) {
+               mlog_errno(ret);
+               acl = ERR_PTR(ret);
+               return acl;
+       }
+
+       acl = ocfs2_get_acl_nolock(inode, type, di_bh);
+
+       ocfs2_inode_unlock(inode, 0);
+
+       brelse(di_bh);
+
+       return acl;
+}
+
+/*
+ * Set the access or default ACL of an inode.
+ */
+static int ocfs2_set_acl(handle_t *handle,
+                        struct inode *inode,
+                        struct buffer_head *di_bh,
+                        int type,
+                        struct posix_acl *acl,
+                        struct ocfs2_alloc_context *meta_ac,
+                        struct ocfs2_alloc_context *data_ac)
+{
+       int name_index;
+       void *value = NULL;
+       size_t size = 0;
+       int ret;
+
+       if (S_ISLNK(inode->i_mode))
+               return -EOPNOTSUPP;
+
+       switch (type) {
+       case ACL_TYPE_ACCESS:
+               name_index = OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS;
+               if (acl) {
+                       mode_t mode = inode->i_mode;
+                       ret = posix_acl_equiv_mode(acl, &mode);
+                       if (ret < 0)
+                               return ret;
+                       else {
+                               inode->i_mode = mode;
+                               if (ret == 0)
+                                       acl = NULL;
+                       }
+               }
+               break;
+       case ACL_TYPE_DEFAULT:
+               name_index = OCFS2_XATTR_INDEX_POSIX_ACL_DEFAULT;
+               if (!S_ISDIR(inode->i_mode))
+                       return acl ? -EACCES : 0;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (acl) {
+               value = ocfs2_acl_to_xattr(acl, &size);
+               if (IS_ERR(value))
+                       return (int)PTR_ERR(value);
+       }
+
+       if (handle)
+               ret = ocfs2_xattr_set_handle(handle, inode, di_bh, name_index,
+                                            "", value, size, 0,
+                                            meta_ac, data_ac);
+       else
+               ret = ocfs2_xattr_set(inode, name_index, "", value, size, 0);
+
+       kfree(value);
+
+       return ret;
+}
+
+int ocfs2_check_acl(struct inode *inode, int mask)
+{
+       struct posix_acl *acl = ocfs2_get_acl(inode, ACL_TYPE_ACCESS);
+
+       if (IS_ERR(acl))
+               return PTR_ERR(acl);
+       if (acl) {
+               int ret = posix_acl_permission(inode, acl, mask);
+               posix_acl_release(acl);
+               return ret;
+       }
+
+       return -EAGAIN;
+}
+
+int ocfs2_acl_chmod(struct inode *inode)
+{
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       struct posix_acl *acl, *clone;
+       int ret;
+
+       if (S_ISLNK(inode->i_mode))
+               return -EOPNOTSUPP;
+
+       if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
+               return 0;
+
+       acl = ocfs2_get_acl(inode, ACL_TYPE_ACCESS);
+       if (IS_ERR(acl) || !acl)
+               return PTR_ERR(acl);
+       clone = posix_acl_clone(acl, GFP_KERNEL);
+       posix_acl_release(acl);
+       if (!clone)
+               return -ENOMEM;
+       ret = posix_acl_chmod_masq(clone, inode->i_mode);
+       if (!ret)
+               ret = ocfs2_set_acl(NULL, inode, NULL, ACL_TYPE_ACCESS,
+                                   clone, NULL, NULL);
+       posix_acl_release(clone);
+       return ret;
+}
+
+/*
+ * Initialize the ACLs of a new inode. If parent directory has default ACL,
+ * then clone to new inode. Called from ocfs2_mknod.
+ */
+int ocfs2_init_acl(handle_t *handle,
+                  struct inode *inode,
+                  struct inode *dir,
+                  struct buffer_head *di_bh,
+                  struct buffer_head *dir_bh,
+                  struct ocfs2_alloc_context *meta_ac,
+                  struct ocfs2_alloc_context *data_ac)
+{
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       struct posix_acl *acl = NULL;
+       int ret = 0;
+
+       if (!S_ISLNK(inode->i_mode)) {
+               if (osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) {
+                       acl = ocfs2_get_acl_nolock(dir, ACL_TYPE_DEFAULT,
+                                                  dir_bh);
+                       if (IS_ERR(acl))
+                               return PTR_ERR(acl);
+               }
+               if (!acl)
+                       inode->i_mode &= ~current->fs->umask;
+       }
+       if ((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) && acl) {
+               struct posix_acl *clone;
+               mode_t mode;
+
+               if (S_ISDIR(inode->i_mode)) {
+                       ret = ocfs2_set_acl(handle, inode, di_bh,
+                                           ACL_TYPE_DEFAULT, acl,
+                                           meta_ac, data_ac);
+                       if (ret)
+                               goto cleanup;
+               }
+               clone = posix_acl_clone(acl, GFP_NOFS);
+               ret = -ENOMEM;
+               if (!clone)
+                       goto cleanup;
+
+               mode = inode->i_mode;
+               ret = posix_acl_create_masq(clone, &mode);
+               if (ret >= 0) {
+                       inode->i_mode = mode;
+                       if (ret > 0) {
+                               ret = ocfs2_set_acl(handle, inode,
+                                                   di_bh, ACL_TYPE_ACCESS,
+                                                   clone, meta_ac, data_ac);
+                       }
+               }
+               posix_acl_release(clone);
+       }
+cleanup:
+       posix_acl_release(acl);
+       return ret;
+}
+
+static size_t ocfs2_xattr_list_acl_access(struct inode *inode,
+                                         char *list,
+                                         size_t list_len,
+                                         const char *name,
+                                         size_t name_len)
+{
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
+
+       if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
+               return 0;
+
+       if (list && size <= list_len)
+               memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
+       return size;
+}
+
+static size_t ocfs2_xattr_list_acl_default(struct inode *inode,
+                                          char *list,
+                                          size_t list_len,
+                                          const char *name,
+                                          size_t name_len)
+{
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
+
+       if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
+               return 0;
+
+       if (list && size <= list_len)
+               memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
+       return size;
+}
+
+static int ocfs2_xattr_get_acl(struct inode *inode,
+                              int type,
+                              void *buffer,
+                              size_t size)
+{
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       struct posix_acl *acl;
+       int ret;
+
+       if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
+               return -EOPNOTSUPP;
+
+       acl = ocfs2_get_acl(inode, type);
+       if (IS_ERR(acl))
+               return PTR_ERR(acl);
+       if (acl == NULL)
+               return -ENODATA;
+       ret = posix_acl_to_xattr(acl, buffer, size);
+       posix_acl_release(acl);
+
+       return ret;
+}
+
+static int ocfs2_xattr_get_acl_access(struct inode *inode,
+                                     const char *name,
+                                     void *buffer,
+                                     size_t size)
+{
+       if (strcmp(name, "") != 0)
+               return -EINVAL;
+       return ocfs2_xattr_get_acl(inode, ACL_TYPE_ACCESS, buffer, size);
+}
+
+static int ocfs2_xattr_get_acl_default(struct inode *inode,
+                                      const char *name,
+                                      void *buffer,
+                                      size_t size)
+{
+       if (strcmp(name, "") != 0)
+               return -EINVAL;
+       return ocfs2_xattr_get_acl(inode, ACL_TYPE_DEFAULT, buffer, size);
+}
+
+static int ocfs2_xattr_set_acl(struct inode *inode,
+                              int type,
+                              const void *value,
+                              size_t size)
+{
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       struct posix_acl *acl;
+       int ret = 0;
+
+       if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
+               return -EOPNOTSUPP;
+
+       if (!is_owner_or_cap(inode))
+               return -EPERM;
+
+       if (value) {
+               acl = posix_acl_from_xattr(value, size);
+               if (IS_ERR(acl))
+                       return PTR_ERR(acl);
+               else if (acl) {
+                       ret = posix_acl_valid(acl);
+                       if (ret)
+                               goto cleanup;
+               }
+       } else
+               acl = NULL;
+
+       ret = ocfs2_set_acl(NULL, inode, NULL, type, acl, NULL, NULL);
+
+cleanup:
+       posix_acl_release(acl);
+       return ret;
+}
+
+static int ocfs2_xattr_set_acl_access(struct inode *inode,
+                                     const char *name,
+                                     const void *value,
+                                     size_t size,
+                                     int flags)
+{
+       if (strcmp(name, "") != 0)
+               return -EINVAL;
+       return ocfs2_xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size);
+}
+
+static int ocfs2_xattr_set_acl_default(struct inode *inode,
+                                      const char *name,
+                                      const void *value,
+                                      size_t size,
+                                      int flags)
+{
+       if (strcmp(name, "") != 0)
+               return -EINVAL;
+       return ocfs2_xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size);
+}
+
+struct xattr_handler ocfs2_xattr_acl_access_handler = {
+       .prefix = POSIX_ACL_XATTR_ACCESS,
+       .list   = ocfs2_xattr_list_acl_access,
+       .get    = ocfs2_xattr_get_acl_access,
+       .set    = ocfs2_xattr_set_acl_access,
+};
+
+struct xattr_handler ocfs2_xattr_acl_default_handler = {
+       .prefix = POSIX_ACL_XATTR_DEFAULT,
+       .list   = ocfs2_xattr_list_acl_default,
+       .get    = ocfs2_xattr_get_acl_default,
+       .set    = ocfs2_xattr_set_acl_default,
+};
diff --git a/fs/ocfs2/acl.h b/fs/ocfs2/acl.h
new file mode 100644 (file)
index 0000000..8f6389e
--- /dev/null
@@ -0,0 +1,58 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * acl.h
+ *
+ * Copyright (C) 2004, 2008 Oracle.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef OCFS2_ACL_H
+#define OCFS2_ACL_H
+
+#include <linux/posix_acl_xattr.h>
+
+struct ocfs2_acl_entry {
+       __le16 e_tag;
+       __le16 e_perm;
+       __le32 e_id;
+};
+
+#ifdef CONFIG_OCFS2_FS_POSIX_ACL
+
+extern int ocfs2_check_acl(struct inode *, int);
+extern int ocfs2_acl_chmod(struct inode *);
+extern int ocfs2_init_acl(handle_t *, struct inode *, struct inode *,
+                         struct buffer_head *, struct buffer_head *,
+                         struct ocfs2_alloc_context *,
+                         struct ocfs2_alloc_context *);
+
+#else /* CONFIG_OCFS2_FS_POSIX_ACL*/
+
+#define ocfs2_check_acl NULL
+static inline int ocfs2_acl_chmod(struct inode *inode)
+{
+       return 0;
+}
+static inline int ocfs2_init_acl(handle_t *handle,
+                                struct inode *inode,
+                                struct inode *dir,
+                                struct buffer_head *di_bh,
+                                struct buffer_head *dir_bh,
+                                struct ocfs2_alloc_context *meta_ac,
+                                struct ocfs2_alloc_context *data_ac)
+{
+       return 0;
+}
+
+#endif /* CONFIG_OCFS2_FS_POSIX_ACL*/
+
+#endif /* OCFS2_ACL_H */
index 0cc2deb9394c02e1a961c0a1366ae5737b8f32bc..54ff4c77aaa30c9eee1b001e2d7cd79fbff82cc1 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/slab.h>
 #include <linux/highmem.h>
 #include <linux/swap.h>
+#include <linux/quotaops.h>
 
 #define MLOG_MASK_PREFIX ML_DISK_ALLOC
 #include <cluster/masklog.h>
@@ -36,6 +37,7 @@
 
 #include "alloc.h"
 #include "aops.h"
+#include "blockcheck.h"
 #include "dlmglue.h"
 #include "extent_map.h"
 #include "inode.h"
@@ -46,6 +48,7 @@
 #include "file.h"
 #include "super.h"
 #include "uptodate.h"
+#include "xattr.h"
 
 #include "buffer_head_io.h"
 
@@ -187,20 +190,12 @@ static int ocfs2_dinode_insert_check(struct inode *inode,
 static int ocfs2_dinode_sanity_check(struct inode *inode,
                                     struct ocfs2_extent_tree *et)
 {
-       int ret = 0;
-       struct ocfs2_dinode *di;
+       struct ocfs2_dinode *di = et->et_object;
 
        BUG_ON(et->et_ops != &ocfs2_dinode_et_ops);
+       BUG_ON(!OCFS2_IS_VALID_DINODE(di));
 
-       di = et->et_object;
-       if (!OCFS2_IS_VALID_DINODE(di)) {
-               ret = -EIO;
-               ocfs2_error(inode->i_sb,
-                       "Inode %llu has invalid path root",
-                       (unsigned long long)OCFS2_I(inode)->ip_blkno);
-       }
-
-       return ret;
+       return 0;
 }
 
 static void ocfs2_dinode_fill_root_el(struct ocfs2_extent_tree *et)
@@ -213,36 +208,33 @@ static void ocfs2_dinode_fill_root_el(struct ocfs2_extent_tree *et)
 
 static void ocfs2_xattr_value_fill_root_el(struct ocfs2_extent_tree *et)
 {
-       struct ocfs2_xattr_value_root *xv = et->et_object;
+       struct ocfs2_xattr_value_buf *vb = et->et_object;
 
-       et->et_root_el = &xv->xr_list;
+       et->et_root_el = &vb->vb_xv->xr_list;
 }
 
 static void ocfs2_xattr_value_set_last_eb_blk(struct ocfs2_extent_tree *et,
                                              u64 blkno)
 {
-       struct ocfs2_xattr_value_root *xv =
-               (struct ocfs2_xattr_value_root *)et->et_object;
+       struct ocfs2_xattr_value_buf *vb = et->et_object;
 
-       xv->xr_last_eb_blk = cpu_to_le64(blkno);
+       vb->vb_xv->xr_last_eb_blk = cpu_to_le64(blkno);
 }
 
 static u64 ocfs2_xattr_value_get_last_eb_blk(struct ocfs2_extent_tree *et)
 {
-       struct ocfs2_xattr_value_root *xv =
-               (struct ocfs2_xattr_value_root *) et->et_object;
+       struct ocfs2_xattr_value_buf *vb = et->et_object;
 
-       return le64_to_cpu(xv->xr_last_eb_blk);
+       return le64_to_cpu(vb->vb_xv->xr_last_eb_blk);
 }
 
 static void ocfs2_xattr_value_update_clusters(struct inode *inode,
                                              struct ocfs2_extent_tree *et,
                                              u32 clusters)
 {
-       struct ocfs2_xattr_value_root *xv =
-               (struct ocfs2_xattr_value_root *)et->et_object;
+       struct ocfs2_xattr_value_buf *vb = et->et_object;
 
-       le32_add_cpu(&xv->xr_clusters, clusters);
+       le32_add_cpu(&vb->vb_xv->xr_clusters, clusters);
 }
 
 static struct ocfs2_extent_tree_operations ocfs2_xattr_value_et_ops = {
@@ -304,11 +296,13 @@ static struct ocfs2_extent_tree_operations ocfs2_xattr_tree_et_ops = {
 static void __ocfs2_init_extent_tree(struct ocfs2_extent_tree *et,
                                     struct inode *inode,
                                     struct buffer_head *bh,
+                                    ocfs2_journal_access_func access,
                                     void *obj,
                                     struct ocfs2_extent_tree_operations *ops)
 {
        et->et_ops = ops;
        et->et_root_bh = bh;
+       et->et_root_journal_access = access;
        if (!obj)
                obj = (void *)bh->b_data;
        et->et_object = obj;
@@ -324,23 +318,23 @@ void ocfs2_init_dinode_extent_tree(struct ocfs2_extent_tree *et,
                                   struct inode *inode,
                                   struct buffer_head *bh)
 {
-       __ocfs2_init_extent_tree(et, inode, bh, NULL, &ocfs2_dinode_et_ops);
+       __ocfs2_init_extent_tree(et, inode, bh, ocfs2_journal_access_di,
+                                NULL, &ocfs2_dinode_et_ops);
 }
 
 void ocfs2_init_xattr_tree_extent_tree(struct ocfs2_extent_tree *et,
                                       struct inode *inode,
                                       struct buffer_head *bh)
 {
-       __ocfs2_init_extent_tree(et, inode, bh, NULL,
-                                &ocfs2_xattr_tree_et_ops);
+       __ocfs2_init_extent_tree(et, inode, bh, ocfs2_journal_access_xb,
+                                NULL, &ocfs2_xattr_tree_et_ops);
 }
 
 void ocfs2_init_xattr_value_extent_tree(struct ocfs2_extent_tree *et,
                                        struct inode *inode,
-                                       struct buffer_head *bh,
-                                       struct ocfs2_xattr_value_root *xv)
+                                       struct ocfs2_xattr_value_buf *vb)
 {
-       __ocfs2_init_extent_tree(et, inode, bh, xv,
+       __ocfs2_init_extent_tree(et, inode, vb->vb_bh, vb->vb_access, vb,
                                 &ocfs2_xattr_value_et_ops);
 }
 
@@ -362,6 +356,15 @@ static inline void ocfs2_et_update_clusters(struct inode *inode,
        et->et_ops->eo_update_clusters(inode, et, clusters);
 }
 
+static inline int ocfs2_et_root_journal_access(handle_t *handle,
+                                              struct inode *inode,
+                                              struct ocfs2_extent_tree *et,
+                                              int type)
+{
+       return et->et_root_journal_access(handle, inode, et->et_root_bh,
+                                         type);
+}
+
 static inline int ocfs2_et_insert_check(struct inode *inode,
                                        struct ocfs2_extent_tree *et,
                                        struct ocfs2_extent_rec *rec)
@@ -402,12 +405,14 @@ struct ocfs2_path_item {
 #define OCFS2_MAX_PATH_DEPTH   5
 
 struct ocfs2_path {
-       int                     p_tree_depth;
-       struct ocfs2_path_item  p_node[OCFS2_MAX_PATH_DEPTH];
+       int                             p_tree_depth;
+       ocfs2_journal_access_func       p_root_access;
+       struct ocfs2_path_item          p_node[OCFS2_MAX_PATH_DEPTH];
 };
 
 #define path_root_bh(_path) ((_path)->p_node[0].bh)
 #define path_root_el(_path) ((_path)->p_node[0].el)
+#define path_root_access(_path)((_path)->p_root_access)
 #define path_leaf_bh(_path) ((_path)->p_node[(_path)->p_tree_depth].bh)
 #define path_leaf_el(_path) ((_path)->p_node[(_path)->p_tree_depth].el)
 #define path_num_items(_path) ((_path)->p_tree_depth + 1)
@@ -440,6 +445,8 @@ static void ocfs2_reinit_path(struct ocfs2_path *path, int keep_root)
         */
        if (keep_root)
                depth = le16_to_cpu(path_root_el(path)->l_tree_depth);
+       else
+               path_root_access(path) = NULL;
 
        path->p_tree_depth = depth;
 }
@@ -465,6 +472,7 @@ static void ocfs2_cp_path(struct ocfs2_path *dest, struct ocfs2_path *src)
 
        BUG_ON(path_root_bh(dest) != path_root_bh(src));
        BUG_ON(path_root_el(dest) != path_root_el(src));
+       BUG_ON(path_root_access(dest) != path_root_access(src));
 
        ocfs2_reinit_path(dest, 1);
 
@@ -486,6 +494,7 @@ static void ocfs2_mv_path(struct ocfs2_path *dest, struct ocfs2_path *src)
        int i;
 
        BUG_ON(path_root_bh(dest) != path_root_bh(src));
+       BUG_ON(path_root_access(dest) != path_root_access(src));
 
        for(i = 1; i < OCFS2_MAX_PATH_DEPTH; i++) {
                brelse(dest->p_node[i].bh);
@@ -521,7 +530,8 @@ static inline void ocfs2_path_insert_eb(struct ocfs2_path *path, int index,
 }
 
 static struct ocfs2_path *ocfs2_new_path(struct buffer_head *root_bh,
-                                        struct ocfs2_extent_list *root_el)
+                                        struct ocfs2_extent_list *root_el,
+                                        ocfs2_journal_access_func access)
 {
        struct ocfs2_path *path;
 
@@ -533,11 +543,48 @@ static struct ocfs2_path *ocfs2_new_path(struct buffer_head *root_bh,
                get_bh(root_bh);
                path_root_bh(path) = root_bh;
                path_root_el(path) = root_el;
+               path_root_access(path) = access;
        }
 
        return path;
 }
 
+static struct ocfs2_path *ocfs2_new_path_from_path(struct ocfs2_path *path)
+{
+       return ocfs2_new_path(path_root_bh(path), path_root_el(path),
+                             path_root_access(path));
+}
+
+static struct ocfs2_path *ocfs2_new_path_from_et(struct ocfs2_extent_tree *et)
+{
+       return ocfs2_new_path(et->et_root_bh, et->et_root_el,
+                             et->et_root_journal_access);
+}
+
+/*
+ * Journal the buffer at depth idx.  All idx>0 are extent_blocks,
+ * otherwise it's the root_access function.
+ *
+ * I don't like the way this function's name looks next to
+ * ocfs2_journal_access_path(), but I don't have a better one.
+ */
+static int ocfs2_path_bh_journal_access(handle_t *handle,
+                                       struct inode *inode,
+                                       struct ocfs2_path *path,
+                                       int idx)
+{
+       ocfs2_journal_access_func access = path_root_access(path);
+
+       if (!access)
+               access = ocfs2_journal_access;
+
+       if (idx)
+               access = ocfs2_journal_access_eb;
+
+       return access(handle, inode, path->p_node[idx].bh,
+                     OCFS2_JOURNAL_ACCESS_WRITE);
+}
+
 /*
  * Convenience function to journal all components in a path.
  */
@@ -550,8 +597,7 @@ static int ocfs2_journal_access_path(struct inode *inode, handle_t *handle,
                goto out;
 
        for(i = 0; i < path_num_items(path); i++) {
-               ret = ocfs2_journal_access(handle, inode, path->p_node[i].bh,
-                                          OCFS2_JOURNAL_ACCESS_WRITE);
+               ret = ocfs2_path_bh_journal_access(handle, inode, path, i);
                if (ret < 0) {
                        mlog_errno(ret);
                        goto out;
@@ -686,6 +732,80 @@ struct ocfs2_merge_ctxt {
        int                     c_split_covers_rec;
 };
 
+static int ocfs2_validate_extent_block(struct super_block *sb,
+                                      struct buffer_head *bh)
+{
+       int rc;
+       struct ocfs2_extent_block *eb =
+               (struct ocfs2_extent_block *)bh->b_data;
+
+       mlog(0, "Validating extent block %llu\n",
+            (unsigned long long)bh->b_blocknr);
+
+       BUG_ON(!buffer_uptodate(bh));
+
+       /*
+        * If the ecc fails, we return the error but otherwise
+        * leave the filesystem running.  We know any error is
+        * local to this block.
+        */
+       rc = ocfs2_validate_meta_ecc(sb, bh->b_data, &eb->h_check);
+       if (rc) {
+               mlog(ML_ERROR, "Checksum failed for extent block %llu\n",
+                    (unsigned long long)bh->b_blocknr);
+               return rc;
+       }
+
+       /*
+        * Errors after here are fatal.
+        */
+
+       if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {
+               ocfs2_error(sb,
+                           "Extent block #%llu has bad signature %.*s",
+                           (unsigned long long)bh->b_blocknr, 7,
+                           eb->h_signature);
+               return -EINVAL;
+       }
+
+       if (le64_to_cpu(eb->h_blkno) != bh->b_blocknr) {
+               ocfs2_error(sb,
+                           "Extent block #%llu has an invalid h_blkno "
+                           "of %llu",
+                           (unsigned long long)bh->b_blocknr,
+                           (unsigned long long)le64_to_cpu(eb->h_blkno));
+               return -EINVAL;
+       }
+
+       if (le32_to_cpu(eb->h_fs_generation) != OCFS2_SB(sb)->fs_generation) {
+               ocfs2_error(sb,
+                           "Extent block #%llu has an invalid "
+                           "h_fs_generation of #%u",
+                           (unsigned long long)bh->b_blocknr,
+                           le32_to_cpu(eb->h_fs_generation));
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+int ocfs2_read_extent_block(struct inode *inode, u64 eb_blkno,
+                           struct buffer_head **bh)
+{
+       int rc;
+       struct buffer_head *tmp = *bh;
+
+       rc = ocfs2_read_block(inode, eb_blkno, &tmp,
+                             ocfs2_validate_extent_block);
+
+       /* If ocfs2_read_block() got us a new bh, pass it up. */
+       if (!rc && !*bh)
+               *bh = tmp;
+
+       return rc;
+}
+
+
 /*
  * How many free extents have we got before we need more meta data?
  */
@@ -705,8 +825,7 @@ int ocfs2_num_free_extents(struct ocfs2_super *osb,
        last_eb_blk = ocfs2_et_get_last_eb_blk(et);
 
        if (last_eb_blk) {
-               retval = ocfs2_read_block(inode, last_eb_blk,
-                                         &eb_bh);
+               retval = ocfs2_read_extent_block(inode, last_eb_blk, &eb_bh);
                if (retval < 0) {
                        mlog_errno(retval);
                        goto bail;
@@ -768,8 +887,8 @@ static int ocfs2_create_new_meta_bhs(struct ocfs2_super *osb,
                        }
                        ocfs2_set_new_buffer_uptodate(inode, bhs[i]);
 
-                       status = ocfs2_journal_access(handle, inode, bhs[i],
-                                                     OCFS2_JOURNAL_ACCESS_CREATE);
+                       status = ocfs2_journal_access_eb(handle, inode, bhs[i],
+                                                        OCFS2_JOURNAL_ACCESS_CREATE);
                        if (status < 0) {
                                mlog_errno(status);
                                goto bail;
@@ -908,15 +1027,12 @@ static int ocfs2_add_branch(struct ocfs2_super *osb,
        for(i = 0; i < new_blocks; i++) {
                bh = new_eb_bhs[i];
                eb = (struct ocfs2_extent_block *) bh->b_data;
-               if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {
-                       OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, eb);
-                       status = -EIO;
-                       goto bail;
-               }
+               /* ocfs2_create_new_meta_bhs() should create it right! */
+               BUG_ON(!OCFS2_IS_VALID_EXTENT_BLOCK(eb));
                eb_el = &eb->h_list;
 
-               status = ocfs2_journal_access(handle, inode, bh,
-                                             OCFS2_JOURNAL_ACCESS_CREATE);
+               status = ocfs2_journal_access_eb(handle, inode, bh,
+                                                OCFS2_JOURNAL_ACCESS_CREATE);
                if (status < 0) {
                        mlog_errno(status);
                        goto bail;
@@ -955,21 +1071,21 @@ static int ocfs2_add_branch(struct ocfs2_super *osb,
         * journal_dirty erroring as it won't unless we've aborted the
         * handle (in which case we would never be here) so reserving
         * the write with journal_access is all we need to do. */
-       status = ocfs2_journal_access(handle, inode, *last_eb_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_journal_access_eb(handle, inode, *last_eb_bh,
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
        }
-       status = ocfs2_journal_access(handle, inode, et->et_root_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_et_root_journal_access(handle, inode, et,
+                                             OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
        }
        if (eb_bh) {
-               status = ocfs2_journal_access(handle, inode, eb_bh,
-                                             OCFS2_JOURNAL_ACCESS_WRITE);
+               status = ocfs2_journal_access_eb(handle, inode, eb_bh,
+                                                OCFS2_JOURNAL_ACCESS_WRITE);
                if (status < 0) {
                        mlog_errno(status);
                        goto bail;
@@ -1052,17 +1168,14 @@ static int ocfs2_shift_tree_depth(struct ocfs2_super *osb,
        }
 
        eb = (struct ocfs2_extent_block *) new_eb_bh->b_data;
-       if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {
-               OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, eb);
-               status = -EIO;
-               goto bail;
-       }
+       /* ocfs2_create_new_meta_bhs() should create it right! */
+       BUG_ON(!OCFS2_IS_VALID_EXTENT_BLOCK(eb));
 
        eb_el = &eb->h_list;
        root_el = et->et_root_el;
 
-       status = ocfs2_journal_access(handle, inode, new_eb_bh,
-                                     OCFS2_JOURNAL_ACCESS_CREATE);
+       status = ocfs2_journal_access_eb(handle, inode, new_eb_bh,
+                                        OCFS2_JOURNAL_ACCESS_CREATE);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -1080,8 +1193,8 @@ static int ocfs2_shift_tree_depth(struct ocfs2_super *osb,
                goto bail;
        }
 
-       status = ocfs2_journal_access(handle, inode, et->et_root_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_et_root_journal_access(handle, inode, et,
+                                             OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -1176,18 +1289,13 @@ static int ocfs2_find_branch_target(struct ocfs2_super *osb,
                brelse(bh);
                bh = NULL;
 
-               status = ocfs2_read_block(inode, blkno, &bh);
+               status = ocfs2_read_extent_block(inode, blkno, &bh);
                if (status < 0) {
                        mlog_errno(status);
                        goto bail;
                }
 
                eb = (struct ocfs2_extent_block *) bh->b_data;
-               if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {
-                       OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, eb);
-                       status = -EIO;
-                       goto bail;
-               }
                el = &eb->h_list;
 
                if (le16_to_cpu(el->l_next_free_rec) <
@@ -1540,7 +1648,7 @@ static int __ocfs2_find_path(struct inode *inode,
 
                brelse(bh);
                bh = NULL;
-               ret = ocfs2_read_block(inode, blkno, &bh);
+               ret = ocfs2_read_extent_block(inode, blkno, &bh);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -1548,11 +1656,6 @@ static int __ocfs2_find_path(struct inode *inode,
 
                eb = (struct ocfs2_extent_block *) bh->b_data;
                el = &eb->h_list;
-               if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {
-                       OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, eb);
-                       ret = -EIO;
-                       goto out;
-               }
 
                if (le16_to_cpu(el->l_next_free_rec) >
                    le16_to_cpu(el->l_count)) {
@@ -1860,25 +1963,23 @@ static int ocfs2_rotate_subtree_right(struct inode *inode,
        root_bh = left_path->p_node[subtree_index].bh;
        BUG_ON(root_bh != right_path->p_node[subtree_index].bh);
 
-       ret = ocfs2_journal_access(handle, inode, root_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = ocfs2_path_bh_journal_access(handle, inode, right_path,
+                                          subtree_index);
        if (ret) {
                mlog_errno(ret);
                goto out;
        }
 
        for(i = subtree_index + 1; i < path_num_items(right_path); i++) {
-               ret = ocfs2_journal_access(handle, inode,
-                                          right_path->p_node[i].bh,
-                                          OCFS2_JOURNAL_ACCESS_WRITE);
+               ret = ocfs2_path_bh_journal_access(handle, inode,
+                                                  right_path, i);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
                }
 
-               ret = ocfs2_journal_access(handle, inode,
-                                          left_path->p_node[i].bh,
-                                          OCFS2_JOURNAL_ACCESS_WRITE);
+               ret = ocfs2_path_bh_journal_access(handle, inode,
+                                                  left_path, i);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -2102,8 +2203,7 @@ static int ocfs2_rotate_tree_right(struct inode *inode,
 
        *ret_left_path = NULL;
 
-       left_path = ocfs2_new_path(path_root_bh(right_path),
-                                  path_root_el(right_path));
+       left_path = ocfs2_new_path_from_path(right_path);
        if (!left_path) {
                ret = -ENOMEM;
                mlog_errno(ret);
@@ -2398,9 +2498,9 @@ static int ocfs2_rotate_subtree_left(struct inode *inode, handle_t *handle,
                        return -EAGAIN;
 
                if (le16_to_cpu(right_leaf_el->l_next_free_rec) > 1) {
-                       ret = ocfs2_journal_access(handle, inode,
-                                                  path_leaf_bh(right_path),
-                                                  OCFS2_JOURNAL_ACCESS_WRITE);
+                       ret = ocfs2_journal_access_eb(handle, inode,
+                                                     path_leaf_bh(right_path),
+                                                     OCFS2_JOURNAL_ACCESS_WRITE);
                        if (ret) {
                                mlog_errno(ret);
                                goto out;
@@ -2417,8 +2517,8 @@ static int ocfs2_rotate_subtree_left(struct inode *inode, handle_t *handle,
                 * We have to update i_last_eb_blk during the meta
                 * data delete.
                 */
-               ret = ocfs2_journal_access(handle, inode, et_root_bh,
-                                          OCFS2_JOURNAL_ACCESS_WRITE);
+               ret = ocfs2_et_root_journal_access(handle, inode, et,
+                                                  OCFS2_JOURNAL_ACCESS_WRITE);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -2433,25 +2533,23 @@ static int ocfs2_rotate_subtree_left(struct inode *inode, handle_t *handle,
         */
        BUG_ON(right_has_empty && !del_right_subtree);
 
-       ret = ocfs2_journal_access(handle, inode, root_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = ocfs2_path_bh_journal_access(handle, inode, right_path,
+                                          subtree_index);
        if (ret) {
                mlog_errno(ret);
                goto out;
        }
 
        for(i = subtree_index + 1; i < path_num_items(right_path); i++) {
-               ret = ocfs2_journal_access(handle, inode,
-                                          right_path->p_node[i].bh,
-                                          OCFS2_JOURNAL_ACCESS_WRITE);
+               ret = ocfs2_path_bh_journal_access(handle, inode,
+                                                  right_path, i);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
                }
 
-               ret = ocfs2_journal_access(handle, inode,
-                                          left_path->p_node[i].bh,
-                                          OCFS2_JOURNAL_ACCESS_WRITE);
+               ret = ocfs2_path_bh_journal_access(handle, inode,
+                                                  left_path, i);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -2596,16 +2694,17 @@ out:
 
 static int ocfs2_rotate_rightmost_leaf_left(struct inode *inode,
                                            handle_t *handle,
-                                           struct buffer_head *bh,
-                                           struct ocfs2_extent_list *el)
+                                           struct ocfs2_path *path)
 {
        int ret;
+       struct buffer_head *bh = path_leaf_bh(path);
+       struct ocfs2_extent_list *el = path_leaf_el(path);
 
        if (!ocfs2_is_empty_extent(&el->l_recs[0]))
                return 0;
 
-       ret = ocfs2_journal_access(handle, inode, bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = ocfs2_path_bh_journal_access(handle, inode, path,
+                                          path_num_items(path) - 1);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -2644,8 +2743,7 @@ static int __ocfs2_rotate_tree_left(struct inode *inode,
                goto out;
        }
 
-       left_path = ocfs2_new_path(path_root_bh(path),
-                                  path_root_el(path));
+       left_path = ocfs2_new_path_from_path(path);
        if (!left_path) {
                ret = -ENOMEM;
                mlog_errno(ret);
@@ -2654,8 +2752,7 @@ static int __ocfs2_rotate_tree_left(struct inode *inode,
 
        ocfs2_cp_path(left_path, path);
 
-       right_path = ocfs2_new_path(path_root_bh(path),
-                                   path_root_el(path));
+       right_path = ocfs2_new_path_from_path(path);
        if (!right_path) {
                ret = -ENOMEM;
                mlog_errno(ret);
@@ -2689,9 +2786,8 @@ static int __ocfs2_rotate_tree_left(struct inode *inode,
                 * Caller might still want to make changes to the
                 * tree root, so re-add it to the journal here.
                 */
-               ret = ocfs2_journal_access(handle, inode,
-                                          path_root_bh(left_path),
-                                          OCFS2_JOURNAL_ACCESS_WRITE);
+               ret = ocfs2_path_bh_journal_access(handle, inode,
+                                                  left_path, 0);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -2785,8 +2881,7 @@ static int ocfs2_remove_rightmost_path(struct inode *inode, handle_t *handle,
                 * We have a path to the left of this one - it needs
                 * an update too.
                 */
-               left_path = ocfs2_new_path(path_root_bh(path),
-                                          path_root_el(path));
+               left_path = ocfs2_new_path_from_path(path);
                if (!left_path) {
                        ret = -ENOMEM;
                        mlog_errno(ret);
@@ -2875,8 +2970,7 @@ rightmost_no_delete:
                 * it up front.
                 */
                ret = ocfs2_rotate_rightmost_leaf_left(inode, handle,
-                                                      path_leaf_bh(path),
-                                                      path_leaf_el(path));
+                                                      path);
                if (ret)
                        mlog_errno(ret);
                goto out;
@@ -3027,8 +3121,7 @@ static int ocfs2_get_right_path(struct inode *inode,
        /* This function shouldn't be called for the rightmost leaf. */
        BUG_ON(right_cpos == 0);
 
-       right_path = ocfs2_new_path(path_root_bh(left_path),
-                                   path_root_el(left_path));
+       right_path = ocfs2_new_path_from_path(left_path);
        if (!right_path) {
                ret = -ENOMEM;
                mlog_errno(ret);
@@ -3111,8 +3204,8 @@ static int ocfs2_merge_rec_right(struct inode *inode,
                root_bh = left_path->p_node[subtree_index].bh;
                BUG_ON(root_bh != right_path->p_node[subtree_index].bh);
 
-               ret = ocfs2_journal_access(handle, inode, root_bh,
-                                          OCFS2_JOURNAL_ACCESS_WRITE);
+               ret = ocfs2_path_bh_journal_access(handle, inode, right_path,
+                                                  subtree_index);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -3120,17 +3213,15 @@ static int ocfs2_merge_rec_right(struct inode *inode,
 
                for (i = subtree_index + 1;
                     i < path_num_items(right_path); i++) {
-                       ret = ocfs2_journal_access(handle, inode,
-                                                  right_path->p_node[i].bh,
-                                                  OCFS2_JOURNAL_ACCESS_WRITE);
+                       ret = ocfs2_path_bh_journal_access(handle, inode,
+                                                          right_path, i);
                        if (ret) {
                                mlog_errno(ret);
                                goto out;
                        }
 
-                       ret = ocfs2_journal_access(handle, inode,
-                                                  left_path->p_node[i].bh,
-                                                  OCFS2_JOURNAL_ACCESS_WRITE);
+                       ret = ocfs2_path_bh_journal_access(handle, inode,
+                                                          left_path, i);
                        if (ret) {
                                mlog_errno(ret);
                                goto out;
@@ -3142,8 +3233,8 @@ static int ocfs2_merge_rec_right(struct inode *inode,
                right_rec = &el->l_recs[index + 1];
        }
 
-       ret = ocfs2_journal_access(handle, inode, bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = ocfs2_path_bh_journal_access(handle, inode, left_path,
+                                          path_num_items(left_path) - 1);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -3199,8 +3290,7 @@ static int ocfs2_get_left_path(struct inode *inode,
        /* This function shouldn't be called for the leftmost leaf. */
        BUG_ON(left_cpos == 0);
 
-       left_path = ocfs2_new_path(path_root_bh(right_path),
-                                  path_root_el(right_path));
+       left_path = ocfs2_new_path_from_path(right_path);
        if (!left_path) {
                ret = -ENOMEM;
                mlog_errno(ret);
@@ -3283,8 +3373,8 @@ static int ocfs2_merge_rec_left(struct inode *inode,
                root_bh = left_path->p_node[subtree_index].bh;
                BUG_ON(root_bh != right_path->p_node[subtree_index].bh);
 
-               ret = ocfs2_journal_access(handle, inode, root_bh,
-                                          OCFS2_JOURNAL_ACCESS_WRITE);
+               ret = ocfs2_path_bh_journal_access(handle, inode, right_path,
+                                                  subtree_index);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -3292,17 +3382,15 @@ static int ocfs2_merge_rec_left(struct inode *inode,
 
                for (i = subtree_index + 1;
                     i < path_num_items(right_path); i++) {
-                       ret = ocfs2_journal_access(handle, inode,
-                                                  right_path->p_node[i].bh,
-                                                  OCFS2_JOURNAL_ACCESS_WRITE);
+                       ret = ocfs2_path_bh_journal_access(handle, inode,
+                                                          right_path, i);
                        if (ret) {
                                mlog_errno(ret);
                                goto out;
                        }
 
-                       ret = ocfs2_journal_access(handle, inode,
-                                                  left_path->p_node[i].bh,
-                                                  OCFS2_JOURNAL_ACCESS_WRITE);
+                       ret = ocfs2_path_bh_journal_access(handle, inode,
+                                                          left_path, i);
                        if (ret) {
                                mlog_errno(ret);
                                goto out;
@@ -3314,8 +3402,8 @@ static int ocfs2_merge_rec_left(struct inode *inode,
                        has_empty_extent = 1;
        }
 
-       ret = ocfs2_journal_access(handle, inode, bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = ocfs2_path_bh_journal_access(handle, inode, right_path,
+                                          path_num_items(right_path) - 1);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -3732,8 +3820,7 @@ static int ocfs2_append_rec_to_path(struct inode *inode, handle_t *handle,
                 * leftmost leaf.
                 */
                if (left_cpos) {
-                       left_path = ocfs2_new_path(path_root_bh(right_path),
-                                                  path_root_el(right_path));
+                       left_path = ocfs2_new_path_from_path(right_path);
                        if (!left_path) {
                                ret = -ENOMEM;
                                mlog_errno(ret);
@@ -3958,8 +4045,8 @@ static int ocfs2_do_insert_extent(struct inode *inode,
 
        el = et->et_root_el;
 
-       ret = ocfs2_journal_access(handle, inode, et->et_root_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = ocfs2_et_root_journal_access(handle, inode, et,
+                                          OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -3970,7 +4057,7 @@ static int ocfs2_do_insert_extent(struct inode *inode,
                goto out_update_clusters;
        }
 
-       right_path = ocfs2_new_path(et->et_root_bh, et->et_root_el);
+       right_path = ocfs2_new_path_from_et(et);
        if (!right_path) {
                ret = -ENOMEM;
                mlog_errno(ret);
@@ -4020,8 +4107,8 @@ static int ocfs2_do_insert_extent(struct inode *inode,
                 * ocfs2_rotate_tree_right() might have extended the
                 * transaction without re-journaling our tree root.
                 */
-               ret = ocfs2_journal_access(handle, inode, et->et_root_bh,
-                                          OCFS2_JOURNAL_ACCESS_WRITE);
+               ret = ocfs2_et_root_journal_access(handle, inode, et,
+                                                  OCFS2_JOURNAL_ACCESS_WRITE);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -4082,8 +4169,7 @@ ocfs2_figure_merge_contig_type(struct inode *inode, struct ocfs2_path *path,
                        goto out;
 
                if (left_cpos != 0) {
-                       left_path = ocfs2_new_path(path_root_bh(path),
-                                                  path_root_el(path));
+                       left_path = ocfs2_new_path_from_path(path);
                        if (!left_path)
                                goto out;
 
@@ -4097,8 +4183,15 @@ ocfs2_figure_merge_contig_type(struct inode *inode, struct ocfs2_path *path,
                            le16_to_cpu(new_el->l_count)) {
                                bh = path_leaf_bh(left_path);
                                eb = (struct ocfs2_extent_block *)bh->b_data;
-                               OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb,
-                                                                eb);
+                               ocfs2_error(inode->i_sb,
+                                           "Extent block #%llu has an "
+                                           "invalid l_next_free_rec of "
+                                           "%d.  It should have "
+                                           "matched the l_count of %d",
+                                           (unsigned long long)le64_to_cpu(eb->h_blkno),
+                                           le16_to_cpu(new_el->l_next_free_rec),
+                                           le16_to_cpu(new_el->l_count));
+                               status = -EINVAL;
                                goto out;
                        }
                        rec = &new_el->l_recs[
@@ -4132,8 +4225,7 @@ ocfs2_figure_merge_contig_type(struct inode *inode, struct ocfs2_path *path,
                if (right_cpos == 0)
                        goto out;
 
-               right_path = ocfs2_new_path(path_root_bh(path),
-                                           path_root_el(path));
+               right_path = ocfs2_new_path_from_path(path);
                if (!right_path)
                        goto out;
 
@@ -4147,8 +4239,12 @@ ocfs2_figure_merge_contig_type(struct inode *inode, struct ocfs2_path *path,
                        if (le16_to_cpu(new_el->l_next_free_rec) <= 1) {
                                bh = path_leaf_bh(right_path);
                                eb = (struct ocfs2_extent_block *)bh->b_data;
-                               OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb,
-                                                                eb);
+                               ocfs2_error(inode->i_sb,
+                                           "Extent block #%llu has an "
+                                           "invalid l_next_free_rec of %d",
+                                           (unsigned long long)le64_to_cpu(eb->h_blkno),
+                                           le16_to_cpu(new_el->l_next_free_rec));
+                               status = -EINVAL;
                                goto out;
                        }
                        rec = &new_el->l_recs[1];
@@ -4294,7 +4390,9 @@ static int ocfs2_figure_insert_type(struct inode *inode,
                 * ocfs2_figure_insert_type() and ocfs2_add_branch()
                 * may want it later.
                 */
-               ret = ocfs2_read_block(inode, ocfs2_et_get_last_eb_blk(et), &bh);
+               ret = ocfs2_read_extent_block(inode,
+                                             ocfs2_et_get_last_eb_blk(et),
+                                             &bh);
                if (ret) {
                        mlog_exit(ret);
                        goto out;
@@ -4320,7 +4418,7 @@ static int ocfs2_figure_insert_type(struct inode *inode,
                return 0;
        }
 
-       path = ocfs2_new_path(et->et_root_bh, et->et_root_el);
+       path = ocfs2_new_path_from_et(et);
        if (!path) {
                ret = -ENOMEM;
                mlog_errno(ret);
@@ -4531,9 +4629,9 @@ int ocfs2_add_clusters_in_btree(struct ocfs2_super *osb,
 
        BUG_ON(num_bits > clusters_to_add);
 
-       /* reserve our write early -- insert_extent may update the inode */
-       status = ocfs2_journal_access(handle, inode, et->et_root_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       /* reserve our write early -- insert_extent may update the tree root */
+       status = ocfs2_et_root_journal_access(handle, inode, et,
+                                             OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto leave;
@@ -4760,20 +4858,15 @@ static int __ocfs2_mark_extent_written(struct inode *inode,
        if (path->p_tree_depth) {
                struct ocfs2_extent_block *eb;
 
-               ret = ocfs2_read_block(inode, ocfs2_et_get_last_eb_blk(et),
-                                      &last_eb_bh);
+               ret = ocfs2_read_extent_block(inode,
+                                             ocfs2_et_get_last_eb_blk(et),
+                                             &last_eb_bh);
                if (ret) {
                        mlog_exit(ret);
                        goto out;
                }
 
                eb = (struct ocfs2_extent_block *) last_eb_bh->b_data;
-               if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {
-                       OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, eb);
-                       ret = -EROFS;
-                       goto out;
-               }
-
                rightmost_el = &eb->h_list;
        } else
                rightmost_el = path_root_el(path);
@@ -4854,7 +4947,7 @@ int ocfs2_mark_extent_written(struct inode *inode,
        if (et->et_ops == &ocfs2_dinode_et_ops)
                ocfs2_extent_map_trunc(inode, 0);
 
-       left_path = ocfs2_new_path(et->et_root_bh, et->et_root_el);
+       left_path = ocfs2_new_path_from_et(et);
        if (!left_path) {
                ret = -ENOMEM;
                mlog_errno(ret);
@@ -4918,8 +5011,9 @@ static int ocfs2_split_tree(struct inode *inode, struct ocfs2_extent_tree *et,
 
        depth = path->p_tree_depth;
        if (depth > 0) {
-               ret = ocfs2_read_block(inode, ocfs2_et_get_last_eb_blk(et),
-                                      &last_eb_bh);
+               ret = ocfs2_read_extent_block(inode,
+                                             ocfs2_et_get_last_eb_blk(et),
+                                             &last_eb_bh);
                if (ret < 0) {
                        mlog_errno(ret);
                        goto out;
@@ -5025,8 +5119,7 @@ static int ocfs2_truncate_rec(struct inode *inode, handle_t *handle,
                }
 
                if (left_cpos && le16_to_cpu(el->l_next_free_rec) > 1) {
-                       left_path = ocfs2_new_path(path_root_bh(path),
-                                                  path_root_el(path));
+                       left_path = ocfs2_new_path_from_path(path);
                        if (!left_path) {
                                ret = -ENOMEM;
                                mlog_errno(ret);
@@ -5135,7 +5228,7 @@ int ocfs2_remove_extent(struct inode *inode,
 
        ocfs2_extent_map_trunc(inode, 0);
 
-       path = ocfs2_new_path(et->et_root_bh, et->et_root_el);
+       path = ocfs2_new_path_from_et(et);
        if (!path) {
                ret = -ENOMEM;
                mlog_errno(ret);
@@ -5255,6 +5348,78 @@ out:
        return ret;
 }
 
+int ocfs2_remove_btree_range(struct inode *inode,
+                            struct ocfs2_extent_tree *et,
+                            u32 cpos, u32 phys_cpos, u32 len,
+                            struct ocfs2_cached_dealloc_ctxt *dealloc)
+{
+       int ret;
+       u64 phys_blkno = ocfs2_clusters_to_blocks(inode->i_sb, phys_cpos);
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       struct inode *tl_inode = osb->osb_tl_inode;
+       handle_t *handle;
+       struct ocfs2_alloc_context *meta_ac = NULL;
+
+       ret = ocfs2_lock_allocators(inode, et, 0, 1, NULL, &meta_ac);
+       if (ret) {
+               mlog_errno(ret);
+               return ret;
+       }
+
+       mutex_lock(&tl_inode->i_mutex);
+
+       if (ocfs2_truncate_log_needs_flush(osb)) {
+               ret = __ocfs2_flush_truncate_log(osb);
+               if (ret < 0) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+       }
+
+       handle = ocfs2_start_trans(osb, ocfs2_remove_extent_credits(osb->sb));
+       if (IS_ERR(handle)) {
+               ret = PTR_ERR(handle);
+               mlog_errno(ret);
+               goto out;
+       }
+
+       ret = ocfs2_et_root_journal_access(handle, inode, et,
+                                          OCFS2_JOURNAL_ACCESS_WRITE);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       ret = ocfs2_remove_extent(inode, et, cpos, len, handle, meta_ac,
+                                 dealloc);
+       if (ret) {
+               mlog_errno(ret);
+               goto out_commit;
+       }
+
+       ocfs2_et_update_clusters(inode, et, -len);
+
+       ret = ocfs2_journal_dirty(handle, et->et_root_bh);
+       if (ret) {
+               mlog_errno(ret);
+               goto out_commit;
+       }
+
+       ret = ocfs2_truncate_log_append(osb, handle, phys_blkno, len);
+       if (ret)
+               mlog_errno(ret);
+
+out_commit:
+       ocfs2_commit_trans(osb, handle);
+out:
+       mutex_unlock(&tl_inode->i_mutex);
+
+       if (meta_ac)
+               ocfs2_free_alloc_context(meta_ac);
+
+       return ret;
+}
+
 int ocfs2_truncate_log_needs_flush(struct ocfs2_super *osb)
 {
        struct buffer_head *tl_bh = osb->osb_tl_bh;
@@ -5308,13 +5473,13 @@ int ocfs2_truncate_log_append(struct ocfs2_super *osb,
        start_cluster = ocfs2_blocks_to_clusters(osb->sb, start_blk);
 
        di = (struct ocfs2_dinode *) tl_bh->b_data;
-       tl = &di->id2.i_dealloc;
-       if (!OCFS2_IS_VALID_DINODE(di)) {
-               OCFS2_RO_ON_INVALID_DINODE(osb->sb, di);
-               status = -EIO;
-               goto bail;
-       }
 
+       /* tl_bh is loaded from ocfs2_truncate_log_init().  It's validated
+        * by the underlying call to ocfs2_read_inode_block(), so any
+        * corruption is a code bug */
+       BUG_ON(!OCFS2_IS_VALID_DINODE(di));
+
+       tl = &di->id2.i_dealloc;
        tl_count = le16_to_cpu(tl->tl_count);
        mlog_bug_on_msg(tl_count > ocfs2_truncate_recs_per_inode(osb->sb) ||
                        tl_count == 0,
@@ -5332,8 +5497,8 @@ int ocfs2_truncate_log_append(struct ocfs2_super *osb,
                goto bail;
        }
 
-       status = ocfs2_journal_access(handle, tl_inode, tl_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_journal_access_di(handle, tl_inode, tl_bh,
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -5394,8 +5559,8 @@ static int ocfs2_replay_truncate_records(struct ocfs2_super *osb,
        while (i >= 0) {
                /* Caller has given us at least enough credits to
                 * update the truncate log dinode */
-               status = ocfs2_journal_access(handle, tl_inode, tl_bh,
-                                             OCFS2_JOURNAL_ACCESS_WRITE);
+               status = ocfs2_journal_access_di(handle, tl_inode, tl_bh,
+                                                OCFS2_JOURNAL_ACCESS_WRITE);
                if (status < 0) {
                        mlog_errno(status);
                        goto bail;
@@ -5464,13 +5629,13 @@ int __ocfs2_flush_truncate_log(struct ocfs2_super *osb)
        BUG_ON(mutex_trylock(&tl_inode->i_mutex));
 
        di = (struct ocfs2_dinode *) tl_bh->b_data;
-       tl = &di->id2.i_dealloc;
-       if (!OCFS2_IS_VALID_DINODE(di)) {
-               OCFS2_RO_ON_INVALID_DINODE(osb->sb, di);
-               status = -EIO;
-               goto out;
-       }
 
+       /* tl_bh is loaded from ocfs2_truncate_log_init().  It's validated
+        * by the underlying call to ocfs2_read_inode_block(), so any
+        * corruption is a code bug */
+       BUG_ON(!OCFS2_IS_VALID_DINODE(di));
+
+       tl = &di->id2.i_dealloc;
        num_to_flush = le16_to_cpu(tl->tl_used);
        mlog(0, "Flush %u records from truncate log #%llu\n",
             num_to_flush, (unsigned long long)OCFS2_I(tl_inode)->ip_blkno);
@@ -5586,7 +5751,7 @@ static int ocfs2_get_truncate_log_info(struct ocfs2_super *osb,
                goto bail;
        }
 
-       status = ocfs2_read_block(inode, OCFS2_I(inode)->ip_blkno, &bh);
+       status = ocfs2_read_inode_block(inode, &bh);
        if (status < 0) {
                iput(inode);
                mlog_errno(status);
@@ -5625,13 +5790,13 @@ int ocfs2_begin_truncate_log_recovery(struct ocfs2_super *osb,
        }
 
        di = (struct ocfs2_dinode *) tl_bh->b_data;
-       tl = &di->id2.i_dealloc;
-       if (!OCFS2_IS_VALID_DINODE(di)) {
-               OCFS2_RO_ON_INVALID_DINODE(tl_inode->i_sb, di);
-               status = -EIO;
-               goto bail;
-       }
 
+       /* tl_bh is loaded from ocfs2_get_truncate_log_info().  It's
+        * validated by the underlying call to ocfs2_read_inode_block(),
+        * so any corruption is a code bug */
+       BUG_ON(!OCFS2_IS_VALID_DINODE(di));
+
+       tl = &di->id2.i_dealloc;
        if (le16_to_cpu(tl->tl_used)) {
                mlog(0, "We'll have %u logs to recover\n",
                     le16_to_cpu(tl->tl_used));
@@ -5651,6 +5816,7 @@ int ocfs2_begin_truncate_log_recovery(struct ocfs2_super *osb,
                 * tl_used. */
                tl->tl_used = 0;
 
+               ocfs2_compute_meta_ecc(osb->sb, tl_bh->b_data, &di->i_check);
                status = ocfs2_write_block(osb, tl_bh, tl_inode);
                if (status < 0) {
                        mlog_errno(status);
@@ -5800,7 +5966,10 @@ int ocfs2_truncate_log_init(struct ocfs2_super *osb)
  */
 
 /*
- * Describes a single block free from a suballocator
+ * Describe a single bit freed from a suballocator.  For the block
+ * suballocators, it represents one block.  For the global cluster
+ * allocator, it represents some clusters and free_bit indicates
+ * clusters number.
  */
 struct ocfs2_cached_block_free {
        struct ocfs2_cached_block_free          *free_next;
@@ -5815,10 +5984,10 @@ struct ocfs2_per_slot_free_list {
        struct ocfs2_cached_block_free          *f_first;
 };
 
-static int ocfs2_free_cached_items(struct ocfs2_super *osb,
-                                  int sysfile_type,
-                                  int slot,
-                                  struct ocfs2_cached_block_free *head)
+static int ocfs2_free_cached_blocks(struct ocfs2_super *osb,
+                                   int sysfile_type,
+                                   int slot,
+                                   struct ocfs2_cached_block_free *head)
 {
        int ret;
        u64 bg_blkno;
@@ -5893,6 +6062,82 @@ out:
        return ret;
 }
 
+int ocfs2_cache_cluster_dealloc(struct ocfs2_cached_dealloc_ctxt *ctxt,
+                               u64 blkno, unsigned int bit)
+{
+       int ret = 0;
+       struct ocfs2_cached_block_free *item;
+
+       item = kmalloc(sizeof(*item), GFP_NOFS);
+       if (item == NULL) {
+               ret = -ENOMEM;
+               mlog_errno(ret);
+               return ret;
+       }
+
+       mlog(0, "Insert clusters: (bit %u, blk %llu)\n",
+            bit, (unsigned long long)blkno);
+
+       item->free_blk = blkno;
+       item->free_bit = bit;
+       item->free_next = ctxt->c_global_allocator;
+
+       ctxt->c_global_allocator = item;
+       return ret;
+}
+
+static int ocfs2_free_cached_clusters(struct ocfs2_super *osb,
+                                     struct ocfs2_cached_block_free *head)
+{
+       struct ocfs2_cached_block_free *tmp;
+       struct inode *tl_inode = osb->osb_tl_inode;
+       handle_t *handle;
+       int ret = 0;
+
+       mutex_lock(&tl_inode->i_mutex);
+
+       while (head) {
+               if (ocfs2_truncate_log_needs_flush(osb)) {
+                       ret = __ocfs2_flush_truncate_log(osb);
+                       if (ret < 0) {
+                               mlog_errno(ret);
+                               break;
+                       }
+               }
+
+               handle = ocfs2_start_trans(osb, OCFS2_TRUNCATE_LOG_UPDATE);
+               if (IS_ERR(handle)) {
+                       ret = PTR_ERR(handle);
+                       mlog_errno(ret);
+                       break;
+               }
+
+               ret = ocfs2_truncate_log_append(osb, handle, head->free_blk,
+                                               head->free_bit);
+
+               ocfs2_commit_trans(osb, handle);
+               tmp = head;
+               head = head->free_next;
+               kfree(tmp);
+
+               if (ret < 0) {
+                       mlog_errno(ret);
+                       break;
+               }
+       }
+
+       mutex_unlock(&tl_inode->i_mutex);
+
+       while (head) {
+               /* Premature exit may have left some dangling items. */
+               tmp = head;
+               head = head->free_next;
+               kfree(tmp);
+       }
+
+       return ret;
+}
+
 int ocfs2_run_deallocs(struct ocfs2_super *osb,
                       struct ocfs2_cached_dealloc_ctxt *ctxt)
 {
@@ -5908,8 +6153,10 @@ int ocfs2_run_deallocs(struct ocfs2_super *osb,
                if (fl->f_first) {
                        mlog(0, "Free items: (type %u, slot %d)\n",
                             fl->f_inode_type, fl->f_slot);
-                       ret2 = ocfs2_free_cached_items(osb, fl->f_inode_type,
-                                                      fl->f_slot, fl->f_first);
+                       ret2 = ocfs2_free_cached_blocks(osb,
+                                                       fl->f_inode_type,
+                                                       fl->f_slot,
+                                                       fl->f_first);
                        if (ret2)
                                mlog_errno(ret2);
                        if (!ret)
@@ -5920,6 +6167,17 @@ int ocfs2_run_deallocs(struct ocfs2_super *osb,
                kfree(fl);
        }
 
+       if (ctxt->c_global_allocator) {
+               ret2 = ocfs2_free_cached_clusters(osb,
+                                                 ctxt->c_global_allocator);
+               if (ret2)
+                       mlog_errno(ret2);
+               if (!ret)
+                       ret = ret2;
+
+               ctxt->c_global_allocator = NULL;
+       }
+
        return ret;
 }
 
@@ -6075,11 +6333,10 @@ static int ocfs2_find_new_last_ext_blk(struct inode *inode,
 
        eb = (struct ocfs2_extent_block *) bh->b_data;
        el = &eb->h_list;
-       if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {
-               OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, eb);
-               ret = -EROFS;
-               goto out;
-       }
+
+       /* ocfs2_find_leaf() gets the eb from ocfs2_read_extent_block().
+        * Any corruption is a code bug. */
+       BUG_ON(!OCFS2_IS_VALID_EXTENT_BLOCK(eb));
 
        *new_last_eb = bh;
        get_bh(*new_last_eb);
@@ -6326,8 +6583,8 @@ static int ocfs2_do_truncate(struct ocfs2_super *osb,
        }
 
        if (last_eb_bh) {
-               status = ocfs2_journal_access(handle, inode, last_eb_bh,
-                                             OCFS2_JOURNAL_ACCESS_WRITE);
+               status = ocfs2_journal_access_eb(handle, inode, last_eb_bh,
+                                                OCFS2_JOURNAL_ACCESS_WRITE);
                if (status < 0) {
                        mlog_errno(status);
                        goto bail;
@@ -6350,6 +6607,8 @@ static int ocfs2_do_truncate(struct ocfs2_super *osb,
                goto bail;
        }
 
+       vfs_dq_free_space_nodirty(inode,
+                       ocfs2_clusters_to_bytes(osb->sb, clusters_to_del));
        spin_lock(&OCFS2_I(inode)->ip_lock);
        OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters) -
                                      clusters_to_del;
@@ -6436,11 +6695,6 @@ static void ocfs2_map_and_dirty_page(struct inode *inode, handle_t *handle,
                mlog_errno(ret);
        else if (ocfs2_should_order_data(inode)) {
                ret = ocfs2_jbd2_file_inode(handle, inode);
-#ifdef CONFIG_OCFS2_COMPAT_JBD
-               ret = walk_page_buffers(handle, page_buffers(page),
-                                       from, to, &partial,
-                                       ocfs2_journal_dirty_data);
-#endif
                if (ret < 0)
                        mlog_errno(ret);
        }
@@ -6663,6 +6917,7 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode,
        struct page **pages = NULL;
        loff_t end = osb->s_clustersize;
        struct ocfs2_extent_tree et;
+       int did_quota = 0;
 
        has_data = i_size_read(inode) ? 1 : 0;
 
@@ -6682,15 +6937,16 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode,
                }
        }
 
-       handle = ocfs2_start_trans(osb, OCFS2_INLINE_TO_EXTENTS_CREDITS);
+       handle = ocfs2_start_trans(osb,
+                                  ocfs2_inline_to_extents_credits(osb->sb));
        if (IS_ERR(handle)) {
                ret = PTR_ERR(handle);
                mlog_errno(ret);
                goto out_unlock;
        }
 
-       ret = ocfs2_journal_access(handle, inode, di_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = ocfs2_journal_access_di(handle, inode, di_bh,
+                                     OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
                goto out_commit;
@@ -6701,6 +6957,13 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode,
                unsigned int page_end;
                u64 phys;
 
+               if (vfs_dq_alloc_space_nodirty(inode,
+                                      ocfs2_clusters_to_bytes(osb->sb, 1))) {
+                       ret = -EDQUOT;
+                       goto out_commit;
+               }
+               did_quota = 1;
+
                ret = ocfs2_claim_clusters(osb, handle, data_ac, 1, &bit_off,
                                           &num);
                if (ret) {
@@ -6774,6 +7037,10 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode,
        }
 
 out_commit:
+       if (ret < 0 && did_quota)
+               vfs_dq_free_space_nodirty(inode,
+                                         ocfs2_clusters_to_bytes(osb->sb, 1));
+
        ocfs2_commit_trans(osb, handle);
 
 out_unlock:
@@ -6813,7 +7080,8 @@ int ocfs2_commit_truncate(struct ocfs2_super *osb,
        new_highest_cpos = ocfs2_clusters_for_bytes(osb->sb,
                                                     i_size_read(inode));
 
-       path = ocfs2_new_path(fe_bh, &di->id2.i_list);
+       path = ocfs2_new_path(fe_bh, &di->id2.i_list,
+                             ocfs2_journal_access_di);
        if (!path) {
                status = -ENOMEM;
                mlog_errno(status);
@@ -6984,20 +7252,14 @@ int ocfs2_prepare_truncate(struct ocfs2_super *osb,
        ocfs2_init_dealloc_ctxt(&(*tc)->tc_dealloc);
 
        if (fe->id2.i_list.l_tree_depth) {
-               status = ocfs2_read_block(inode, le64_to_cpu(fe->i_last_eb_blk),
-                                         &last_eb_bh);
+               status = ocfs2_read_extent_block(inode,
+                                                le64_to_cpu(fe->i_last_eb_blk),
+                                                &last_eb_bh);
                if (status < 0) {
                        mlog_errno(status);
                        goto bail;
                }
                eb = (struct ocfs2_extent_block *) last_eb_bh->b_data;
-               if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {
-                       OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, eb);
-
-                       brelse(last_eb_bh);
-                       status = -EIO;
-                       goto bail;
-               }
        }
 
        (*tc)->tc_last_eb_bh = last_eb_bh;
@@ -7052,8 +7314,8 @@ int ocfs2_truncate_inline(struct inode *inode, struct buffer_head *di_bh,
                goto out;
        }
 
-       ret = ocfs2_journal_access(handle, inode, di_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = ocfs2_journal_access_di(handle, inode, di_bh,
+                                     OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
                goto out_commit;
index 70257c84cfbe46c092bb78d6f6f2ae00b38505b3..cceff5c37f47c5872284d5ab43fafab9f9e27db1 100644 (file)
@@ -45,7 +45,9 @@
  *
  * ocfs2_extent_tree contains info for the root of the b-tree, it must have a
  * root ocfs2_extent_list and a root_bh so that they can be used in the b-tree
- * functions.
+ * functions.  With metadata ecc, we now call different journal_access
+ * functions for each type of metadata, so it must have the
+ * root_journal_access function.
  * ocfs2_extent_tree_operations abstract the normal operations we do for
  * the root of extent b-tree.
  */
@@ -54,6 +56,7 @@ struct ocfs2_extent_tree {
        struct ocfs2_extent_tree_operations     *et_ops;
        struct buffer_head                      *et_root_bh;
        struct ocfs2_extent_list                *et_root_el;
+       ocfs2_journal_access_func               et_root_journal_access;
        void                                    *et_object;
        unsigned int                            et_max_leaf_clusters;
 };
@@ -68,10 +71,18 @@ void ocfs2_init_dinode_extent_tree(struct ocfs2_extent_tree *et,
 void ocfs2_init_xattr_tree_extent_tree(struct ocfs2_extent_tree *et,
                                       struct inode *inode,
                                       struct buffer_head *bh);
+struct ocfs2_xattr_value_buf;
 void ocfs2_init_xattr_value_extent_tree(struct ocfs2_extent_tree *et,
                                        struct inode *inode,
-                                       struct buffer_head *bh,
-                                       struct ocfs2_xattr_value_root *xv);
+                                       struct ocfs2_xattr_value_buf *vb);
+
+/*
+ * Read an extent block into *bh.  If *bh is NULL, a bh will be
+ * allocated.  This is a cached read.  The extent block will be validated
+ * with ocfs2_validate_extent_block().
+ */
+int ocfs2_read_extent_block(struct inode *inode, u64 eb_blkno,
+                           struct buffer_head **bh);
 
 struct ocfs2_alloc_context;
 int ocfs2_insert_extent(struct ocfs2_super *osb,
@@ -110,6 +121,11 @@ int ocfs2_remove_extent(struct inode *inode,
                        u32 cpos, u32 len, handle_t *handle,
                        struct ocfs2_alloc_context *meta_ac,
                        struct ocfs2_cached_dealloc_ctxt *dealloc);
+int ocfs2_remove_btree_range(struct inode *inode,
+                            struct ocfs2_extent_tree *et,
+                            u32 cpos, u32 phys_cpos, u32 len,
+                            struct ocfs2_cached_dealloc_ctxt *dealloc);
+
 int ocfs2_num_free_extents(struct ocfs2_super *osb,
                           struct inode *inode,
                           struct ocfs2_extent_tree *et);
@@ -167,10 +183,18 @@ int __ocfs2_flush_truncate_log(struct ocfs2_super *osb);
  */
 struct ocfs2_cached_dealloc_ctxt {
        struct ocfs2_per_slot_free_list         *c_first_suballocator;
+       struct ocfs2_cached_block_free          *c_global_allocator;
 };
 static inline void ocfs2_init_dealloc_ctxt(struct ocfs2_cached_dealloc_ctxt *c)
 {
        c->c_first_suballocator = NULL;
+       c->c_global_allocator = NULL;
+}
+int ocfs2_cache_cluster_dealloc(struct ocfs2_cached_dealloc_ctxt *ctxt,
+                               u64 blkno, unsigned int bit);
+static inline int ocfs2_dealloc_has_cluster(struct ocfs2_cached_dealloc_ctxt *c)
+{
+       return c->c_global_allocator != NULL;
 }
 int ocfs2_run_deallocs(struct ocfs2_super *osb,
                       struct ocfs2_cached_dealloc_ctxt *ctxt);
index c22543b3342062f0308ec06a6f74f2334291727f..a067a6cffb01b43c43809d0ceefd4eb3aca28557 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/swap.h>
 #include <linux/pipe_fs_i.h>
 #include <linux/mpage.h>
+#include <linux/quotaops.h>
 
 #define MLOG_MASK_PREFIX ML_FILE_IO
 #include <cluster/masklog.h>
@@ -68,20 +69,13 @@ static int ocfs2_symlink_get_block(struct inode *inode, sector_t iblock,
                goto bail;
        }
 
-       status = ocfs2_read_block(inode, OCFS2_I(inode)->ip_blkno, &bh);
+       status = ocfs2_read_inode_block(inode, &bh);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
        }
        fe = (struct ocfs2_dinode *) bh->b_data;
 
-       if (!OCFS2_IS_VALID_DINODE(fe)) {
-               mlog(ML_ERROR, "Invalid dinode #%llu: signature = %.*s\n",
-                    (unsigned long long)le64_to_cpu(fe->i_blkno), 7,
-                    fe->i_signature);
-               goto bail;
-       }
-
        if ((u64)iblock >= ocfs2_clusters_to_blocks(inode->i_sb,
                                                    le32_to_cpu(fe->i_clusters))) {
                mlog(ML_ERROR, "block offset is outside the allocated size: "
@@ -262,7 +256,7 @@ static int ocfs2_readpage_inline(struct inode *inode, struct page *page)
        BUG_ON(!PageLocked(page));
        BUG_ON(!(OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL));
 
-       ret = ocfs2_read_block(inode, OCFS2_I(inode)->ip_blkno, &di_bh);
+       ret = ocfs2_read_inode_block(inode, &di_bh);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -481,12 +475,6 @@ handle_t *ocfs2_start_walk_page_trans(struct inode *inode,
 
        if (ocfs2_should_order_data(inode)) {
                ret = ocfs2_jbd2_file_inode(handle, inode);
-#ifdef CONFIG_OCFS2_COMPAT_JBD
-               ret = walk_page_buffers(handle,
-                                       page_buffers(page),
-                                       from, to, NULL,
-                                       ocfs2_journal_dirty_data);
-#endif
                if (ret < 0)
                        mlog_errno(ret);
        }
@@ -1072,15 +1060,8 @@ static void ocfs2_write_failure(struct inode *inode,
                tmppage = wc->w_pages[i];
 
                if (page_has_buffers(tmppage)) {
-                       if (ocfs2_should_order_data(inode)) {
+                       if (ocfs2_should_order_data(inode))
                                ocfs2_jbd2_file_inode(wc->w_handle, inode);
-#ifdef CONFIG_OCFS2_COMPAT_JBD
-                               walk_page_buffers(wc->w_handle,
-                                                 page_buffers(tmppage),
-                                                 from, to, NULL,
-                                                 ocfs2_journal_dirty_data);
-#endif
-                       }
 
                        block_commit_write(tmppage, from, to);
                }
@@ -1531,8 +1512,8 @@ static int ocfs2_write_begin_inline(struct address_space *mapping,
                goto out;
        }
 
-       ret = ocfs2_journal_access(handle, inode, wc->w_di_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = ocfs2_journal_access_di(handle, inode, wc->w_di_bh,
+                                     OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                ocfs2_commit_trans(osb, handle);
 
@@ -1750,15 +1731,20 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
 
        wc->w_handle = handle;
 
+       if (clusters_to_alloc && vfs_dq_alloc_space_nodirty(inode,
+                       ocfs2_clusters_to_bytes(osb->sb, clusters_to_alloc))) {
+               ret = -EDQUOT;
+               goto out_commit;
+       }
        /*
         * We don't want this to fail in ocfs2_write_end(), so do it
         * here.
         */
-       ret = ocfs2_journal_access(handle, inode, wc->w_di_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = ocfs2_journal_access_di(handle, inode, wc->w_di_bh,
+                                     OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
-               goto out_commit;
+               goto out_quota;
        }
 
        /*
@@ -1771,14 +1757,14 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
                                         mmap_page);
        if (ret) {
                mlog_errno(ret);
-               goto out_commit;
+               goto out_quota;
        }
 
        ret = ocfs2_write_cluster_by_desc(mapping, data_ac, meta_ac, wc, pos,
                                          len);
        if (ret) {
                mlog_errno(ret);
-               goto out_commit;
+               goto out_quota;
        }
 
        if (data_ac)
@@ -1790,6 +1776,10 @@ success:
        *pagep = wc->w_target_page;
        *fsdata = wc;
        return 0;
+out_quota:
+       if (clusters_to_alloc)
+               vfs_dq_free_space(inode,
+                         ocfs2_clusters_to_bytes(osb->sb, clusters_to_alloc));
 out_commit:
        ocfs2_commit_trans(osb, handle);
 
@@ -1919,15 +1909,8 @@ int ocfs2_write_end_nolock(struct address_space *mapping,
                }
 
                if (page_has_buffers(tmppage)) {
-                       if (ocfs2_should_order_data(inode)) {
+                       if (ocfs2_should_order_data(inode))
                                ocfs2_jbd2_file_inode(wc->w_handle, inode);
-#ifdef CONFIG_OCFS2_COMPAT_JBD
-                               walk_page_buffers(wc->w_handle,
-                                                 page_buffers(tmppage),
-                                                 from, to, NULL,
-                                                 ocfs2_journal_dirty_data);
-#endif
-                       }
                        block_commit_write(tmppage, from, to);
                }
        }
diff --git a/fs/ocfs2/blockcheck.c b/fs/ocfs2/blockcheck.c
new file mode 100644 (file)
index 0000000..2a947c4
--- /dev/null
@@ -0,0 +1,477 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * blockcheck.c
+ *
+ * Checksum and ECC codes for the OCFS2 userspace library.
+ *
+ * Copyright (C) 2006, 2008 Oracle.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License, version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/crc32.h>
+#include <linux/buffer_head.h>
+#include <linux/bitops.h>
+#include <asm/byteorder.h>
+
+#include <cluster/masklog.h>
+
+#include "ocfs2.h"
+
+#include "blockcheck.h"
+
+
+/*
+ * We use the following conventions:
+ *
+ * d = # data bits
+ * p = # parity bits
+ * c = # total code bits (d + p)
+ */
+
+
+/*
+ * Calculate the bit offset in the hamming code buffer based on the bit's
+ * offset in the data buffer.  Since the hamming code reserves all
+ * power-of-two bits for parity, the data bit number and the code bit
+ * number are offest by all the parity bits beforehand.
+ *
+ * Recall that bit numbers in hamming code are 1-based.  This function
+ * takes the 0-based data bit from the caller.
+ *
+ * An example.  Take bit 1 of the data buffer.  1 is a power of two (2^0),
+ * so it's a parity bit.  2 is a power of two (2^1), so it's a parity bit.
+ * 3 is not a power of two.  So bit 1 of the data buffer ends up as bit 3
+ * in the code buffer.
+ *
+ * The caller can pass in *p if it wants to keep track of the most recent
+ * number of parity bits added.  This allows the function to start the
+ * calculation at the last place.
+ */
+static unsigned int calc_code_bit(unsigned int i, unsigned int *p_cache)
+{
+       unsigned int b, p = 0;
+
+       /*
+        * Data bits are 0-based, but we're talking code bits, which
+        * are 1-based.
+        */
+       b = i + 1;
+
+       /* Use the cache if it is there */
+       if (p_cache)
+               p = *p_cache;
+        b += p;
+
+       /*
+        * For every power of two below our bit number, bump our bit.
+        *
+        * We compare with (b + 1) because we have to compare with what b
+        * would be _if_ it were bumped up by the parity bit.  Capice?
+        *
+        * p is set above.
+        */
+       for (; (1 << p) < (b + 1); p++)
+               b++;
+
+       if (p_cache)
+               *p_cache = p;
+
+       return b;
+}
+
+/*
+ * This is the low level encoder function.  It can be called across
+ * multiple hunks just like the crc32 code.  'd' is the number of bits
+ * _in_this_hunk_.  nr is the bit offset of this hunk.  So, if you had
+ * two 512B buffers, you would do it like so:
+ *
+ * parity = ocfs2_hamming_encode(0, buf1, 512 * 8, 0);
+ * parity = ocfs2_hamming_encode(parity, buf2, 512 * 8, 512 * 8);
+ *
+ * If you just have one buffer, use ocfs2_hamming_encode_block().
+ */
+u32 ocfs2_hamming_encode(u32 parity, void *data, unsigned int d, unsigned int nr)
+{
+       unsigned int i, b, p = 0;
+
+       BUG_ON(!d);
+
+       /*
+        * b is the hamming code bit number.  Hamming code specifies a
+        * 1-based array, but C uses 0-based.  So 'i' is for C, and 'b' is
+        * for the algorithm.
+        *
+        * The i++ in the for loop is so that the start offset passed
+        * to ocfs2_find_next_bit_set() is one greater than the previously
+        * found bit.
+        */
+       for (i = 0; (i = ocfs2_find_next_bit(data, d, i)) < d; i++)
+       {
+               /*
+                * i is the offset in this hunk, nr + i is the total bit
+                * offset.
+                */
+               b = calc_code_bit(nr + i, &p);
+
+               /*
+                * Data bits in the resultant code are checked by
+                * parity bits that are part of the bit number
+                * representation.  Huh?
+                *
+                * <wikipedia href="http://en.wikipedia.org/wiki/Hamming_code">
+                * In other words, the parity bit at position 2^k
+                * checks bits in positions having bit k set in
+                * their binary representation.  Conversely, for
+                * instance, bit 13, i.e. 1101(2), is checked by
+                * bits 1000(2) = 8, 0100(2)=4 and 0001(2) = 1.
+                * </wikipedia>
+                *
+                * Note that 'k' is the _code_ bit number.  'b' in
+                * our loop.
+                */
+               parity ^= b;
+       }
+
+       /* While the data buffer was treated as little endian, the
+        * return value is in host endian. */
+       return parity;
+}
+
+u32 ocfs2_hamming_encode_block(void *data, unsigned int blocksize)
+{
+       return ocfs2_hamming_encode(0, data, blocksize * 8, 0);
+}
+
+/*
+ * Like ocfs2_hamming_encode(), this can handle hunks.  nr is the bit
+ * offset of the current hunk.  If bit to be fixed is not part of the
+ * current hunk, this does nothing.
+ *
+ * If you only have one hunk, use ocfs2_hamming_fix_block().
+ */
+void ocfs2_hamming_fix(void *data, unsigned int d, unsigned int nr,
+                      unsigned int fix)
+{
+       unsigned int i, b;
+
+       BUG_ON(!d);
+
+       /*
+        * If the bit to fix has an hweight of 1, it's a parity bit.  One
+        * busted parity bit is its own error.  Nothing to do here.
+        */
+       if (hweight32(fix) == 1)
+               return;
+
+       /*
+        * nr + d is the bit right past the data hunk we're looking at.
+        * If fix after that, nothing to do
+        */
+       if (fix >= calc_code_bit(nr + d, NULL))
+               return;
+
+       /*
+        * nr is the offset in the data hunk we're starting at.  Let's
+        * start b at the offset in the code buffer.  See hamming_encode()
+        * for a more detailed description of 'b'.
+        */
+       b = calc_code_bit(nr, NULL);
+       /* If the fix is before this hunk, nothing to do */
+       if (fix < b)
+               return;
+
+       for (i = 0; i < d; i++, b++)
+       {
+               /* Skip past parity bits */
+               while (hweight32(b) == 1)
+                       b++;
+
+               /*
+                * i is the offset in this data hunk.
+                * nr + i is the offset in the total data buffer.
+                * b is the offset in the total code buffer.
+                *
+                * Thus, when b == fix, bit i in the current hunk needs
+                * fixing.
+                */
+               if (b == fix)
+               {
+                       if (ocfs2_test_bit(i, data))
+                               ocfs2_clear_bit(i, data);
+                       else
+                               ocfs2_set_bit(i, data);
+                       break;
+               }
+       }
+}
+
+void ocfs2_hamming_fix_block(void *data, unsigned int blocksize,
+                            unsigned int fix)
+{
+       ocfs2_hamming_fix(data, blocksize * 8, 0, fix);
+}
+
+/*
+ * This function generates check information for a block.
+ * data is the block to be checked.  bc is a pointer to the
+ * ocfs2_block_check structure describing the crc32 and the ecc.
+ *
+ * bc should be a pointer inside data, as the function will
+ * take care of zeroing it before calculating the check information.  If
+ * bc does not point inside data, the caller must make sure any inline
+ * ocfs2_block_check structures are zeroed.
+ *
+ * The data buffer must be in on-disk endian (little endian for ocfs2).
+ * bc will be filled with little-endian values and will be ready to go to
+ * disk.
+ */
+void ocfs2_block_check_compute(void *data, size_t blocksize,
+                              struct ocfs2_block_check *bc)
+{
+       u32 crc;
+       u32 ecc;
+
+       memset(bc, 0, sizeof(struct ocfs2_block_check));
+
+       crc = crc32_le(~0, data, blocksize);
+       ecc = ocfs2_hamming_encode_block(data, blocksize);
+
+       /*
+        * No ecc'd ocfs2 structure is larger than 4K, so ecc will be no
+        * larger than 16 bits.
+        */
+       BUG_ON(ecc > USHORT_MAX);
+
+       bc->bc_crc32e = cpu_to_le32(crc);
+       bc->bc_ecc = cpu_to_le16((u16)ecc);
+}
+
+/*
+ * This function validates existing check information.  Like _compute,
+ * the function will take care of zeroing bc before calculating check codes.
+ * If bc is not a pointer inside data, the caller must have zeroed any
+ * inline ocfs2_block_check structures.
+ *
+ * Again, the data passed in should be the on-disk endian.
+ */
+int ocfs2_block_check_validate(void *data, size_t blocksize,
+                              struct ocfs2_block_check *bc)
+{
+       int rc = 0;
+       struct ocfs2_block_check check;
+       u32 crc, ecc;
+
+       check.bc_crc32e = le32_to_cpu(bc->bc_crc32e);
+       check.bc_ecc = le16_to_cpu(bc->bc_ecc);
+
+       memset(bc, 0, sizeof(struct ocfs2_block_check));
+
+       /* Fast path - if the crc32 validates, we're good to go */
+       crc = crc32_le(~0, data, blocksize);
+       if (crc == check.bc_crc32e)
+               goto out;
+
+       mlog(ML_ERROR,
+            "CRC32 failed: stored: %u, computed %u.  Applying ECC.\n",
+            (unsigned int)check.bc_crc32e, (unsigned int)crc);
+
+       /* Ok, try ECC fixups */
+       ecc = ocfs2_hamming_encode_block(data, blocksize);
+       ocfs2_hamming_fix_block(data, blocksize, ecc ^ check.bc_ecc);
+
+       /* And check the crc32 again */
+       crc = crc32_le(~0, data, blocksize);
+       if (crc == check.bc_crc32e)
+               goto out;
+
+       mlog(ML_ERROR, "Fixed CRC32 failed: stored: %u, computed %u\n",
+            (unsigned int)check.bc_crc32e, (unsigned int)crc);
+
+       rc = -EIO;
+
+out:
+       bc->bc_crc32e = cpu_to_le32(check.bc_crc32e);
+       bc->bc_ecc = cpu_to_le16(check.bc_ecc);
+
+       return rc;
+}
+
+/*
+ * This function generates check information for a list of buffer_heads.
+ * bhs is the blocks to be checked.  bc is a pointer to the
+ * ocfs2_block_check structure describing the crc32 and the ecc.
+ *
+ * bc should be a pointer inside data, as the function will
+ * take care of zeroing it before calculating the check information.  If
+ * bc does not point inside data, the caller must make sure any inline
+ * ocfs2_block_check structures are zeroed.
+ *
+ * The data buffer must be in on-disk endian (little endian for ocfs2).
+ * bc will be filled with little-endian values and will be ready to go to
+ * disk.
+ */
+void ocfs2_block_check_compute_bhs(struct buffer_head **bhs, int nr,
+                                  struct ocfs2_block_check *bc)
+{
+       int i;
+       u32 crc, ecc;
+
+       BUG_ON(nr < 0);
+
+       if (!nr)
+               return;
+
+       memset(bc, 0, sizeof(struct ocfs2_block_check));
+
+       for (i = 0, crc = ~0, ecc = 0; i < nr; i++) {
+               crc = crc32_le(crc, bhs[i]->b_data, bhs[i]->b_size);
+               /*
+                * The number of bits in a buffer is obviously b_size*8.
+                * The offset of this buffer is b_size*i, so the bit offset
+                * of this buffer is b_size*8*i.
+                */
+               ecc = (u16)ocfs2_hamming_encode(ecc, bhs[i]->b_data,
+                                               bhs[i]->b_size * 8,
+                                               bhs[i]->b_size * 8 * i);
+       }
+
+       /*
+        * No ecc'd ocfs2 structure is larger than 4K, so ecc will be no
+        * larger than 16 bits.
+        */
+       BUG_ON(ecc > USHORT_MAX);
+
+       bc->bc_crc32e = cpu_to_le32(crc);
+       bc->bc_ecc = cpu_to_le16((u16)ecc);
+}
+
+/*
+ * This function validates existing check information on a list of
+ * buffer_heads.  Like _compute_bhs, the function will take care of
+ * zeroing bc before calculating check codes.  If bc is not a pointer
+ * inside data, the caller must have zeroed any inline
+ * ocfs2_block_check structures.
+ *
+ * Again, the data passed in should be the on-disk endian.
+ */
+int ocfs2_block_check_validate_bhs(struct buffer_head **bhs, int nr,
+                                  struct ocfs2_block_check *bc)
+{
+       int i, rc = 0;
+       struct ocfs2_block_check check;
+       u32 crc, ecc, fix;
+
+       BUG_ON(nr < 0);
+
+       if (!nr)
+               return 0;
+
+       check.bc_crc32e = le32_to_cpu(bc->bc_crc32e);
+       check.bc_ecc = le16_to_cpu(bc->bc_ecc);
+
+       memset(bc, 0, sizeof(struct ocfs2_block_check));
+
+       /* Fast path - if the crc32 validates, we're good to go */
+       for (i = 0, crc = ~0; i < nr; i++)
+               crc = crc32_le(crc, bhs[i]->b_data, bhs[i]->b_size);
+       if (crc == check.bc_crc32e)
+               goto out;
+
+       mlog(ML_ERROR,
+            "CRC32 failed: stored: %u, computed %u.  Applying ECC.\n",
+            (unsigned int)check.bc_crc32e, (unsigned int)crc);
+
+       /* Ok, try ECC fixups */
+       for (i = 0, ecc = 0; i < nr; i++) {
+               /*
+                * The number of bits in a buffer is obviously b_size*8.
+                * The offset of this buffer is b_size*i, so the bit offset
+                * of this buffer is b_size*8*i.
+                */
+               ecc = (u16)ocfs2_hamming_encode(ecc, bhs[i]->b_data,
+                                               bhs[i]->b_size * 8,
+                                               bhs[i]->b_size * 8 * i);
+       }
+       fix = ecc ^ check.bc_ecc;
+       for (i = 0; i < nr; i++) {
+               /*
+                * Try the fix against each buffer.  It will only affect
+                * one of them.
+                */
+               ocfs2_hamming_fix(bhs[i]->b_data, bhs[i]->b_size * 8,
+                                 bhs[i]->b_size * 8 * i, fix);
+       }
+
+       /* And check the crc32 again */
+       for (i = 0, crc = ~0; i < nr; i++)
+               crc = crc32_le(crc, bhs[i]->b_data, bhs[i]->b_size);
+       if (crc == check.bc_crc32e)
+               goto out;
+
+       mlog(ML_ERROR, "Fixed CRC32 failed: stored: %u, computed %u\n",
+            (unsigned int)check.bc_crc32e, (unsigned int)crc);
+
+       rc = -EIO;
+
+out:
+       bc->bc_crc32e = cpu_to_le32(check.bc_crc32e);
+       bc->bc_ecc = cpu_to_le16(check.bc_ecc);
+
+       return rc;
+}
+
+/*
+ * These are the main API.  They check the superblock flag before
+ * calling the underlying operations.
+ *
+ * They expect the buffer(s) to be in disk format.
+ */
+void ocfs2_compute_meta_ecc(struct super_block *sb, void *data,
+                           struct ocfs2_block_check *bc)
+{
+       if (ocfs2_meta_ecc(OCFS2_SB(sb)))
+               ocfs2_block_check_compute(data, sb->s_blocksize, bc);
+}
+
+int ocfs2_validate_meta_ecc(struct super_block *sb, void *data,
+                           struct ocfs2_block_check *bc)
+{
+       int rc = 0;
+
+       if (ocfs2_meta_ecc(OCFS2_SB(sb)))
+               rc = ocfs2_block_check_validate(data, sb->s_blocksize, bc);
+
+       return rc;
+}
+
+void ocfs2_compute_meta_ecc_bhs(struct super_block *sb,
+                               struct buffer_head **bhs, int nr,
+                               struct ocfs2_block_check *bc)
+{
+       if (ocfs2_meta_ecc(OCFS2_SB(sb)))
+               ocfs2_block_check_compute_bhs(bhs, nr, bc);
+}
+
+int ocfs2_validate_meta_ecc_bhs(struct super_block *sb,
+                               struct buffer_head **bhs, int nr,
+                               struct ocfs2_block_check *bc)
+{
+       int rc = 0;
+
+       if (ocfs2_meta_ecc(OCFS2_SB(sb)))
+               rc = ocfs2_block_check_validate_bhs(bhs, nr, bc);
+
+       return rc;
+}
+
diff --git a/fs/ocfs2/blockcheck.h b/fs/ocfs2/blockcheck.h
new file mode 100644 (file)
index 0000000..70ec3fe
--- /dev/null
@@ -0,0 +1,82 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * blockcheck.h
+ *
+ * Checksum and ECC codes for the OCFS2 userspace library.
+ *
+ * Copyright (C) 2004, 2008 Oracle.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License, version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef OCFS2_BLOCKCHECK_H
+#define OCFS2_BLOCKCHECK_H
+
+
+/* High level block API */
+void ocfs2_compute_meta_ecc(struct super_block *sb, void *data,
+                           struct ocfs2_block_check *bc);
+int ocfs2_validate_meta_ecc(struct super_block *sb, void *data,
+                           struct ocfs2_block_check *bc);
+void ocfs2_compute_meta_ecc_bhs(struct super_block *sb,
+                               struct buffer_head **bhs, int nr,
+                               struct ocfs2_block_check *bc);
+int ocfs2_validate_meta_ecc_bhs(struct super_block *sb,
+                               struct buffer_head **bhs, int nr,
+                               struct ocfs2_block_check *bc);
+
+/* Lower level API */
+void ocfs2_block_check_compute(void *data, size_t blocksize,
+                              struct ocfs2_block_check *bc);
+int ocfs2_block_check_validate(void *data, size_t blocksize,
+                              struct ocfs2_block_check *bc);
+void ocfs2_block_check_compute_bhs(struct buffer_head **bhs, int nr,
+                                  struct ocfs2_block_check *bc);
+int ocfs2_block_check_validate_bhs(struct buffer_head **bhs, int nr,
+                                  struct ocfs2_block_check *bc);
+
+/*
+ * Hamming code functions
+ */
+
+/*
+ * Encoding hamming code parity bits for a buffer.
+ *
+ * This is the low level encoder function.  It can be called across
+ * multiple hunks just like the crc32 code.  'd' is the number of bits
+ * _in_this_hunk_.  nr is the bit offset of this hunk.  So, if you had
+ * two 512B buffers, you would do it like so:
+ *
+ * parity = ocfs2_hamming_encode(0, buf1, 512 * 8, 0);
+ * parity = ocfs2_hamming_encode(parity, buf2, 512 * 8, 512 * 8);
+ *
+ * If you just have one buffer, use ocfs2_hamming_encode_block().
+ */
+u32 ocfs2_hamming_encode(u32 parity, void *data, unsigned int d,
+                        unsigned int nr);
+/*
+ * Fix a buffer with a bit error.  The 'fix' is the original parity
+ * xor'd with the parity calculated now.
+ *
+ * Like ocfs2_hamming_encode(), this can handle hunks.  nr is the bit
+ * offset of the current hunk.  If bit to be fixed is not part of the
+ * current hunk, this does nothing.
+ *
+ * If you only have one buffer, use ocfs2_hamming_fix_block().
+ */
+void ocfs2_hamming_fix(void *data, unsigned int d, unsigned int nr,
+                      unsigned int fix);
+
+/* Convenience wrappers for a single buffer of data */
+extern u32 ocfs2_hamming_encode_block(void *data, unsigned int blocksize);
+extern void ocfs2_hamming_fix_block(void *data, unsigned int blocksize,
+                                   unsigned int fix);
+#endif
index 3a178ec48d7c760222970e9af62af615a1e5de35..15c8e6deee2ec76c06ac9c45105b4b6d4c3e93c9 100644 (file)
 
 #include "buffer_head_io.h"
 
+/*
+ * Bits on bh->b_state used by ocfs2.
+ *
+ * These MUST be after the JBD2 bits.  Hence, we use BH_JBDPrivateStart.
+ */
+enum ocfs2_state_bits {
+       BH_NeedsValidate = BH_JBDPrivateStart,
+};
+
+/* Expand the magic b_state functions */
+BUFFER_FNS(NeedsValidate, needs_validate);
+
 int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh,
                      struct inode *inode)
 {
@@ -166,7 +178,9 @@ bail:
 }
 
 int ocfs2_read_blocks(struct inode *inode, u64 block, int nr,
-                     struct buffer_head *bhs[], int flags)
+                     struct buffer_head *bhs[], int flags,
+                     int (*validate)(struct super_block *sb,
+                                     struct buffer_head *bh))
 {
        int status = 0;
        int i, ignore_cache = 0;
@@ -298,6 +312,8 @@ int ocfs2_read_blocks(struct inode *inode, u64 block, int nr,
 
                        clear_buffer_uptodate(bh);
                        get_bh(bh); /* for end_buffer_read_sync() */
+                       if (validate)
+                               set_buffer_needs_validate(bh);
                        bh->b_end_io = end_buffer_read_sync;
                        submit_bh(READ, bh);
                        continue;
@@ -328,6 +344,20 @@ int ocfs2_read_blocks(struct inode *inode, u64 block, int nr,
                                bhs[i] = NULL;
                                continue;
                        }
+
+                       if (buffer_needs_validate(bh)) {
+                               /* We never set NeedsValidate if the
+                                * buffer was held by the journal, so
+                                * that better not have changed */
+                               BUG_ON(buffer_jbd(bh));
+                               clear_buffer_needs_validate(bh);
+                               status = validate(inode->i_sb, bh);
+                               if (status) {
+                                       put_bh(bh);
+                                       bhs[i] = NULL;
+                                       continue;
+                               }
+                       }
                }
 
                /* Always set the buffer in the cache, even if it was
index 75e1dcb1ade7d19d92a70684f1d3daaf851c67ed..c75d682dadd8ee3ac1b29c7b7978d73212656db4 100644 (file)
 void ocfs2_end_buffer_io_sync(struct buffer_head *bh,
                             int uptodate);
 
-static inline int ocfs2_read_block(struct inode               *inode,
-                                  u64                  off,
-                                  struct buffer_head **bh);
-
 int ocfs2_write_block(struct ocfs2_super          *osb,
                      struct buffer_head  *bh,
                      struct inode        *inode);
-int ocfs2_read_blocks(struct inode       *inode,
-                     u64                  block,
-                     int                  nr,
-                     struct buffer_head  *bhs[],
-                     int                  flags);
 int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block,
                           unsigned int nr, struct buffer_head *bhs[]);
 
+/*
+ * If not NULL, validate() will be called on a buffer that is freshly
+ * read from disk.  It will not be called if the buffer was in cache.
+ * Note that if validate() is being used for this buffer, it needs to
+ * be set even for a READAHEAD call, as it marks the buffer for later
+ * validation.
+ */
+int ocfs2_read_blocks(struct inode *inode, u64 block, int nr,
+                     struct buffer_head *bhs[], int flags,
+                     int (*validate)(struct super_block *sb,
+                                     struct buffer_head *bh));
+
 int ocfs2_write_super_or_backup(struct ocfs2_super *osb,
                                struct buffer_head *bh);
 
@@ -53,7 +56,9 @@ int ocfs2_write_super_or_backup(struct ocfs2_super *osb,
 #define OCFS2_BH_READAHEAD         8
 
 static inline int ocfs2_read_block(struct inode *inode, u64 off,
-                                  struct buffer_head **bh)
+                                  struct buffer_head **bh,
+                                  int (*validate)(struct super_block *sb,
+                                                  struct buffer_head *bh))
 {
        int status = 0;
 
@@ -63,7 +68,7 @@ static inline int ocfs2_read_block(struct inode *inode, u64 off,
                goto bail;
        }
 
-       status = ocfs2_read_blocks(inode, off, 1, bh, 0);
+       status = ocfs2_read_blocks(inode, off, 1, bh, 0, validate);
 
 bail:
        return status;
index d8a0cb92cef62a6b108696b0a9dae36dcfc9768a..96df5416993ee4335d283e1ba0d619bdbb2ea4f4 100644 (file)
@@ -110,6 +110,7 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = {
        define_mask(QUORUM),
        define_mask(EXPORT),
        define_mask(XATTR),
+       define_mask(QUOTA),
        define_mask(ERROR),
        define_mask(NOTICE),
        define_mask(KTHREAD),
index 57670c6804713454f02f2a6b18ed5ca41bbbfe6b..7e72a81bc2d4e1923f23debe1d371da66e42c72b 100644 (file)
 #define ML_QUORUM      0x0000000008000000ULL /* net connection quorum */
 #define ML_EXPORT      0x0000000010000000ULL /* ocfs2 export operations */
 #define ML_XATTR       0x0000000020000000ULL /* ocfs2 extended attributes */
+#define ML_QUOTA       0x0000000040000000ULL /* ocfs2 quota operations */
 /* bits that are infrequently given and frequently matched in the high word */
 #define ML_ERROR       0x0000000100000000ULL /* sent to KERN_ERR */
 #define ML_NOTICE      0x0000000200000000ULL /* setn to KERN_NOTICE */
index 026e6eb85187844b60ba55eb9893651090ac1c4f..f2c4098cf337fd077b1d77835144cc454ce5e8dc 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/highmem.h>
+#include <linux/quotaops.h>
 
 #define MLOG_MASK_PREFIX ML_NAMEI
 #include <cluster/masklog.h>
@@ -47,6 +48,7 @@
 #include "ocfs2.h"
 
 #include "alloc.h"
+#include "blockcheck.h"
 #include "dir.h"
 #include "dlmglue.h"
 #include "extent_map.h"
@@ -82,47 +84,72 @@ static int ocfs2_do_extend_dir(struct super_block *sb,
                               struct ocfs2_alloc_context *meta_ac,
                               struct buffer_head **new_bh);
 
-static struct buffer_head *ocfs2_bread(struct inode *inode,
-                                      int block, int *err, int reada)
+/*
+ * These are distinct checks because future versions of the file system will
+ * want to have a trailing dirent structure independent of indexing.
+ */
+static int ocfs2_dir_has_trailer(struct inode *dir)
 {
-       struct buffer_head *bh = NULL;
-       int tmperr;
-       u64 p_blkno;
-       int readflags = 0;
+       if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL)
+               return 0;
 
-       if (reada)
-               readflags |= OCFS2_BH_READAHEAD;
+       return ocfs2_meta_ecc(OCFS2_SB(dir->i_sb));
+}
 
-       if (((u64)block << inode->i_sb->s_blocksize_bits) >=
-           i_size_read(inode)) {
-               BUG_ON(!reada);
-               return NULL;
-       }
+static int ocfs2_supports_dir_trailer(struct ocfs2_super *osb)
+{
+       return ocfs2_meta_ecc(osb);
+}
 
-       down_read(&OCFS2_I(inode)->ip_alloc_sem);
-       tmperr = ocfs2_extent_map_get_blocks(inode, block, &p_blkno, NULL,
-                                            NULL);
-       up_read(&OCFS2_I(inode)->ip_alloc_sem);
-       if (tmperr < 0) {
-               mlog_errno(tmperr);
-               goto fail;
-       }
+static inline unsigned int ocfs2_dir_trailer_blk_off(struct super_block *sb)
+{
+       return sb->s_blocksize - sizeof(struct ocfs2_dir_block_trailer);
+}
 
-       tmperr = ocfs2_read_blocks(inode, p_blkno, 1, &bh, readflags);
-       if (tmperr < 0)
-               goto fail;
+#define ocfs2_trailer_from_bh(_bh, _sb) ((struct ocfs2_dir_block_trailer *) ((_bh)->b_data + ocfs2_dir_trailer_blk_off((_sb))))
 
-       tmperr = 0;
+/* XXX ocfs2_block_dqtrailer() is similar but not quite - can we make
+ * them more consistent? */
+struct ocfs2_dir_block_trailer *ocfs2_dir_trailer_from_size(int blocksize,
+                                                           void *data)
+{
+       char *p = data;
 
-       *err = 0;
-       return bh;
+       p += blocksize - sizeof(struct ocfs2_dir_block_trailer);
+       return (struct ocfs2_dir_block_trailer *)p;
+}
 
-fail:
-       brelse(bh);
-       bh = NULL;
+/*
+ * XXX: This is executed once on every dirent. We should consider optimizing
+ * it.
+ */
+static int ocfs2_skip_dir_trailer(struct inode *dir,
+                                 struct ocfs2_dir_entry *de,
+                                 unsigned long offset,
+                                 unsigned long blklen)
+{
+       unsigned long toff = blklen - sizeof(struct ocfs2_dir_block_trailer);
 
-       *err = -EIO;
-       return NULL;
+       if (!ocfs2_dir_has_trailer(dir))
+               return 0;
+
+       if (offset != toff)
+               return 0;
+
+       return 1;
+}
+
+static void ocfs2_init_dir_trailer(struct inode *inode,
+                                  struct buffer_head *bh)
+{
+       struct ocfs2_dir_block_trailer *trailer;
+
+       trailer = ocfs2_trailer_from_bh(bh, inode->i_sb);
+       strcpy(trailer->db_signature, OCFS2_DIR_TRAILER_SIGNATURE);
+       trailer->db_compat_rec_len =
+                       cpu_to_le16(sizeof(struct ocfs2_dir_block_trailer));
+       trailer->db_parent_dinode = cpu_to_le64(OCFS2_I(inode)->ip_blkno);
+       trailer->db_blkno = cpu_to_le64(bh->b_blocknr);
 }
 
 /*
@@ -231,7 +258,7 @@ static struct buffer_head *ocfs2_find_entry_id(const char *name,
        struct ocfs2_dinode *di;
        struct ocfs2_inline_data *data;
 
-       ret = ocfs2_read_block(dir, OCFS2_I(dir)->ip_blkno, &di_bh);
+       ret = ocfs2_read_inode_block(dir, &di_bh);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -250,6 +277,108 @@ out:
        return NULL;
 }
 
+static int ocfs2_validate_dir_block(struct super_block *sb,
+                                   struct buffer_head *bh)
+{
+       int rc;
+       struct ocfs2_dir_block_trailer *trailer =
+               ocfs2_trailer_from_bh(bh, sb);
+
+
+       /*
+        * We don't validate dirents here, that's handled
+        * in-place when the code walks them.
+        */
+       mlog(0, "Validating dirblock %llu\n",
+            (unsigned long long)bh->b_blocknr);
+
+       BUG_ON(!buffer_uptodate(bh));
+
+       /*
+        * If the ecc fails, we return the error but otherwise
+        * leave the filesystem running.  We know any error is
+        * local to this block.
+        *
+        * Note that we are safe to call this even if the directory
+        * doesn't have a trailer.  Filesystems without metaecc will do
+        * nothing, and filesystems with it will have one.
+        */
+       rc = ocfs2_validate_meta_ecc(sb, bh->b_data, &trailer->db_check);
+       if (rc)
+               mlog(ML_ERROR, "Checksum failed for dinode %llu\n",
+                    (unsigned long long)bh->b_blocknr);
+
+       return rc;
+}
+
+/*
+ * This function forces all errors to -EIO for consistency with its
+ * predecessor, ocfs2_bread().  We haven't audited what returning the
+ * real error codes would do to callers.  We log the real codes with
+ * mlog_errno() before we squash them.
+ */
+static int ocfs2_read_dir_block(struct inode *inode, u64 v_block,
+                               struct buffer_head **bh, int flags)
+{
+       int rc = 0;
+       struct buffer_head *tmp = *bh;
+       struct ocfs2_dir_block_trailer *trailer;
+
+       rc = ocfs2_read_virt_blocks(inode, v_block, 1, &tmp, flags,
+                                   ocfs2_validate_dir_block);
+       if (rc) {
+               mlog_errno(rc);
+               goto out;
+       }
+
+       /*
+        * We check the trailer here rather than in
+        * ocfs2_validate_dir_block() because that function doesn't have
+        * the inode to test.
+        */
+       if (!(flags & OCFS2_BH_READAHEAD) &&
+           ocfs2_dir_has_trailer(inode)) {
+               trailer = ocfs2_trailer_from_bh(tmp, inode->i_sb);
+               if (!OCFS2_IS_VALID_DIR_TRAILER(trailer)) {
+                       rc = -EINVAL;
+                       ocfs2_error(inode->i_sb,
+                                   "Invalid dirblock #%llu: "
+                                   "signature = %.*s\n",
+                                   (unsigned long long)tmp->b_blocknr, 7,
+                                   trailer->db_signature);
+                       goto out;
+               }
+               if (le64_to_cpu(trailer->db_blkno) != tmp->b_blocknr) {
+                       rc = -EINVAL;
+                       ocfs2_error(inode->i_sb,
+                                   "Directory block #%llu has an invalid "
+                                   "db_blkno of %llu",
+                                   (unsigned long long)tmp->b_blocknr,
+                                   (unsigned long long)le64_to_cpu(trailer->db_blkno));
+                       goto out;
+               }
+               if (le64_to_cpu(trailer->db_parent_dinode) !=
+                   OCFS2_I(inode)->ip_blkno) {
+                       rc = -EINVAL;
+                       ocfs2_error(inode->i_sb,
+                                   "Directory block #%llu on dinode "
+                                   "#%llu has an invalid parent_dinode "
+                                   "of %llu",
+                                   (unsigned long long)tmp->b_blocknr,
+                                   (unsigned long long)OCFS2_I(inode)->ip_blkno,
+                                   (unsigned long long)le64_to_cpu(trailer->db_blkno));
+                       goto out;
+               }
+       }
+
+       /* If ocfs2_read_virt_blocks() got us a new bh, pass it up. */
+       if (!*bh)
+               *bh = tmp;
+
+out:
+       return rc ? -EIO : 0;
+}
+
 static struct buffer_head *ocfs2_find_entry_el(const char *name, int namelen,
                                               struct inode *dir,
                                               struct ocfs2_dir_entry **res_dir)
@@ -296,15 +425,17 @@ restart:
                                }
                                num++;
 
-                               bh = ocfs2_bread(dir, b++, &err, 1);
+                               bh = NULL;
+                               err = ocfs2_read_dir_block(dir, b++, &bh,
+                                                          OCFS2_BH_READAHEAD);
                                bh_use[ra_max] = bh;
                        }
                }
                if ((bh = bh_use[ra_ptr++]) == NULL)
                        goto next;
-               if (ocfs2_read_block(dir, block, &bh)) {
+               if (ocfs2_read_dir_block(dir, block, &bh, 0)) {
                        /* read error, skip block & hope for the best.
-                        * ocfs2_read_block() has released the bh. */
+                        * ocfs2_read_dir_block() has released the bh. */
                        ocfs2_error(dir->i_sb, "reading directory %llu, "
                                    "offset %lu\n",
                                    (unsigned long long)OCFS2_I(dir)->ip_blkno,
@@ -381,14 +512,18 @@ int ocfs2_update_entry(struct inode *dir, handle_t *handle,
                       struct inode *new_entry_inode)
 {
        int ret;
+       ocfs2_journal_access_func access = ocfs2_journal_access_db;
 
        /*
         * The same code works fine for both inline-data and extent
-        * based directories, so no need to split this up.
+        * based directories, so no need to split this up.  The only
+        * difference is the journal_access function.
         */
 
-       ret = ocfs2_journal_access(handle, dir, de_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL)
+               access = ocfs2_journal_access_di;
+
+       ret = access(handle, dir, de_bh, OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -410,9 +545,13 @@ static int __ocfs2_delete_entry(handle_t *handle, struct inode *dir,
 {
        struct ocfs2_dir_entry *de, *pde;
        int i, status = -ENOENT;
+       ocfs2_journal_access_func access = ocfs2_journal_access_db;
 
        mlog_entry("(0x%p, 0x%p, 0x%p, 0x%p)\n", handle, dir, de_del, bh);
 
+       if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL)
+               access = ocfs2_journal_access_di;
+
        i = 0;
        pde = NULL;
        de = (struct ocfs2_dir_entry *) first_de;
@@ -423,8 +562,8 @@ static int __ocfs2_delete_entry(handle_t *handle, struct inode *dir,
                        goto bail;
                }
                if (de == de_del)  {
-                       status = ocfs2_journal_access(handle, dir, bh,
-                                                     OCFS2_JOURNAL_ACCESS_WRITE);
+                       status = access(handle, dir, bh,
+                                       OCFS2_JOURNAL_ACCESS_WRITE);
                        if (status < 0) {
                                status = -EIO;
                                mlog_errno(status);
@@ -458,7 +597,7 @@ static inline int ocfs2_delete_entry_id(handle_t *handle,
        struct ocfs2_dinode *di;
        struct ocfs2_inline_data *data;
 
-       ret = ocfs2_read_block(dir, OCFS2_I(dir)->ip_blkno, &di_bh);
+       ret = ocfs2_read_inode_block(dir, &di_bh);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -576,6 +715,16 @@ int __ocfs2_add_entry(handle_t *handle,
                        goto bail;
                }
 
+               /* We're guaranteed that we should have space, so we
+                * can't possibly have hit the trailer...right? */
+               mlog_bug_on_msg(ocfs2_skip_dir_trailer(dir, de, offset, size),
+                               "Hit dir trailer trying to insert %.*s "
+                               "(namelen %d) into directory %llu.  "
+                               "offset is %lu, trailer offset is %d\n",
+                               namelen, name, namelen,
+                               (unsigned long long)parent_fe_bh->b_blocknr,
+                               offset, ocfs2_dir_trailer_blk_off(dir->i_sb));
+
                if (ocfs2_dirent_would_fit(de, rec_len)) {
                        dir->i_mtime = dir->i_ctime = CURRENT_TIME;
                        retval = ocfs2_mark_inode_dirty(handle, dir, parent_fe_bh);
@@ -584,8 +733,14 @@ int __ocfs2_add_entry(handle_t *handle,
                                goto bail;
                        }
 
-                       status = ocfs2_journal_access(handle, dir, insert_bh,
-                                                     OCFS2_JOURNAL_ACCESS_WRITE);
+                       if (insert_bh == parent_fe_bh)
+                               status = ocfs2_journal_access_di(handle, dir,
+                                                                insert_bh,
+                                                                OCFS2_JOURNAL_ACCESS_WRITE);
+                       else
+                               status = ocfs2_journal_access_db(handle, dir,
+                                                                insert_bh,
+                                                                OCFS2_JOURNAL_ACCESS_WRITE);
                        /* By now the buffer is marked for journaling */
                        offset += le16_to_cpu(de->rec_len);
                        if (le64_to_cpu(de->inode)) {
@@ -611,6 +766,7 @@ int __ocfs2_add_entry(handle_t *handle,
                        retval = 0;
                        goto bail;
                }
+
                offset += le16_to_cpu(de->rec_len);
                de = (struct ocfs2_dir_entry *) ((char *) de + le16_to_cpu(de->rec_len));
        }
@@ -636,7 +792,7 @@ static int ocfs2_dir_foreach_blk_id(struct inode *inode,
        struct ocfs2_inline_data *data;
        struct ocfs2_dir_entry *de;
 
-       ret = ocfs2_read_block(inode, OCFS2_I(inode)->ip_blkno, &di_bh);
+       ret = ocfs2_read_inode_block(inode, &di_bh);
        if (ret) {
                mlog(ML_ERROR, "Unable to read inode block for dir %llu\n",
                     (unsigned long long)OCFS2_I(inode)->ip_blkno);
@@ -724,7 +880,6 @@ static int ocfs2_dir_foreach_blk_el(struct inode *inode,
        int i, stored;
        struct buffer_head * bh, * tmp;
        struct ocfs2_dir_entry * de;
-       int err;
        struct super_block * sb = inode->i_sb;
        unsigned int ra_sectors = 16;
 
@@ -735,12 +890,8 @@ static int ocfs2_dir_foreach_blk_el(struct inode *inode,
 
        while (!error && !stored && *f_pos < i_size_read(inode)) {
                blk = (*f_pos) >> sb->s_blocksize_bits;
-               bh = ocfs2_bread(inode, blk, &err, 0);
-               if (!bh) {
-                       mlog(ML_ERROR,
-                            "directory #%llu contains a hole at offset %lld\n",
-                            (unsigned long long)OCFS2_I(inode)->ip_blkno,
-                            *f_pos);
+               if (ocfs2_read_dir_block(inode, blk, &bh, 0)) {
+                       /* Skip the corrupt dirblock and keep trying */
                        *f_pos += sb->s_blocksize - offset;
                        continue;
                }
@@ -754,8 +905,10 @@ static int ocfs2_dir_foreach_blk_el(struct inode *inode,
                    || (((last_ra_blk - blk) << 9) <= (ra_sectors / 2))) {
                        for (i = ra_sectors >> (sb->s_blocksize_bits - 9);
                             i > 0; i--) {
-                               tmp = ocfs2_bread(inode, ++blk, &err, 1);
-                               brelse(tmp);
+                               tmp = NULL;
+                               if (!ocfs2_read_dir_block(inode, ++blk, &tmp,
+                                                         OCFS2_BH_READAHEAD))
+                                       brelse(tmp);
                        }
                        last_ra_blk = blk;
                        ra_sectors = 8;
@@ -828,6 +981,7 @@ revalidate:
                }
                offset = 0;
                brelse(bh);
+               bh = NULL;
        }
 
        stored = 0;
@@ -1050,9 +1204,15 @@ int ocfs2_empty_dir(struct inode *inode)
        return !priv.seen_other;
 }
 
-static void ocfs2_fill_initial_dirents(struct inode *inode,
-                                      struct inode *parent,
-                                      char *start, unsigned int size)
+/*
+ * Fills "." and ".." dirents in a new directory block. Returns dirent for
+ * "..", which might be used during creation of a directory with a trailing
+ * header. It is otherwise safe to ignore the return code.
+ */
+static struct ocfs2_dir_entry *ocfs2_fill_initial_dirents(struct inode *inode,
+                                                         struct inode *parent,
+                                                         char *start,
+                                                         unsigned int size)
 {
        struct ocfs2_dir_entry *de = (struct ocfs2_dir_entry *)start;
 
@@ -1069,6 +1229,8 @@ static void ocfs2_fill_initial_dirents(struct inode *inode,
        de->name_len = 2;
        strcpy(de->name, "..");
        ocfs2_set_de_type(de, S_IFDIR);
+
+       return de;
 }
 
 /*
@@ -1086,8 +1248,8 @@ static int ocfs2_fill_new_dir_id(struct ocfs2_super *osb,
        struct ocfs2_inline_data *data = &di->id2.i_data;
        unsigned int size = le16_to_cpu(data->id_count);
 
-       ret = ocfs2_journal_access(handle, inode, di_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = ocfs2_journal_access_di(handle, inode, di_bh,
+                                     OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -1121,10 +1283,15 @@ static int ocfs2_fill_new_dir_el(struct ocfs2_super *osb,
                                 struct ocfs2_alloc_context *data_ac)
 {
        int status;
+       unsigned int size = osb->sb->s_blocksize;
        struct buffer_head *new_bh = NULL;
+       struct ocfs2_dir_entry *de;
 
        mlog_entry_void();
 
+       if (ocfs2_supports_dir_trailer(osb))
+               size = ocfs2_dir_trailer_blk_off(parent->i_sb);
+
        status = ocfs2_do_extend_dir(osb->sb, handle, inode, fe_bh,
                                     data_ac, NULL, &new_bh);
        if (status < 0) {
@@ -1134,16 +1301,17 @@ static int ocfs2_fill_new_dir_el(struct ocfs2_super *osb,
 
        ocfs2_set_new_buffer_uptodate(inode, new_bh);
 
-       status = ocfs2_journal_access(handle, inode, new_bh,
-                                     OCFS2_JOURNAL_ACCESS_CREATE);
+       status = ocfs2_journal_access_db(handle, inode, new_bh,
+                                        OCFS2_JOURNAL_ACCESS_CREATE);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
        }
        memset(new_bh->b_data, 0, osb->sb->s_blocksize);
 
-       ocfs2_fill_initial_dirents(inode, parent, new_bh->b_data,
-                                  osb->sb->s_blocksize);
+       de = ocfs2_fill_initial_dirents(inode, parent, new_bh->b_data, size);
+       if (ocfs2_supports_dir_trailer(osb))
+               ocfs2_init_dir_trailer(inode, new_bh);
 
        status = ocfs2_journal_dirty(handle, new_bh);
        if (status < 0) {
@@ -1184,13 +1352,27 @@ int ocfs2_fill_new_dir(struct ocfs2_super *osb,
                                     data_ac);
 }
 
+/*
+ * Expand rec_len of the rightmost dirent in a directory block so that it
+ * contains the end of our valid space for dirents. We do this during
+ * expansion from an inline directory to one with extents. The first dir block
+ * in that case is taken from the inline data portion of the inode block.
+ *
+ * We add the dir trailer if this filesystem wants it.
+ */
 static void ocfs2_expand_last_dirent(char *start, unsigned int old_size,
-                                    unsigned int new_size)
+                                    struct super_block *sb)
 {
        struct ocfs2_dir_entry *de;
        struct ocfs2_dir_entry *prev_de;
        char *de_buf, *limit;
-       unsigned int bytes = new_size - old_size;
+       unsigned int new_size = sb->s_blocksize;
+       unsigned int bytes;
+
+       if (ocfs2_supports_dir_trailer(OCFS2_SB(sb)))
+               new_size = ocfs2_dir_trailer_blk_off(sb);
+
+       bytes = new_size - old_size;
 
        limit = start + old_size;
        de_buf = start;
@@ -1216,9 +1398,9 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
                                   unsigned int blocks_wanted,
                                   struct buffer_head **first_block_bh)
 {
-       int ret, credits = OCFS2_INLINE_TO_EXTENTS_CREDITS;
        u32 alloc, bit_off, len;
        struct super_block *sb = dir->i_sb;
+       int ret, credits = ocfs2_inline_to_extents_credits(sb);
        u64 blkno, bytes = blocks_wanted << sb->s_blocksize_bits;
        struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
        struct ocfs2_inode_info *oi = OCFS2_I(dir);
@@ -1227,6 +1409,7 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
        struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
        handle_t *handle;
        struct ocfs2_extent_tree et;
+       int did_quota = 0;
 
        ocfs2_init_dinode_extent_tree(&et, dir, di_bh);
 
@@ -1264,6 +1447,12 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
                goto out_sem;
        }
 
+       if (vfs_dq_alloc_space_nodirty(dir,
+                               ocfs2_clusters_to_bytes(osb->sb, alloc))) {
+               ret = -EDQUOT;
+               goto out_commit;
+       }
+       did_quota = 1;
        /*
         * Try to claim as many clusters as the bitmap can give though
         * if we only get one now, that's enough to continue. The rest
@@ -1290,8 +1479,8 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
 
        ocfs2_set_new_buffer_uptodate(dir, dirdata_bh);
 
-       ret = ocfs2_journal_access(handle, dir, dirdata_bh,
-                                  OCFS2_JOURNAL_ACCESS_CREATE);
+       ret = ocfs2_journal_access_db(handle, dir, dirdata_bh,
+                                     OCFS2_JOURNAL_ACCESS_CREATE);
        if (ret) {
                mlog_errno(ret);
                goto out_commit;
@@ -1300,8 +1489,9 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
        memcpy(dirdata_bh->b_data, di->id2.i_data.id_data, i_size_read(dir));
        memset(dirdata_bh->b_data + i_size_read(dir), 0,
               sb->s_blocksize - i_size_read(dir));
-       ocfs2_expand_last_dirent(dirdata_bh->b_data, i_size_read(dir),
-                                sb->s_blocksize);
+       ocfs2_expand_last_dirent(dirdata_bh->b_data, i_size_read(dir), sb);
+       if (ocfs2_supports_dir_trailer(osb))
+               ocfs2_init_dir_trailer(dir, dirdata_bh);
 
        ret = ocfs2_journal_dirty(handle, dirdata_bh);
        if (ret) {
@@ -1317,8 +1507,8 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
         * We let the later dirent insert modify c/mtime - to the user
         * the data hasn't changed.
         */
-       ret = ocfs2_journal_access(handle, dir, di_bh,
-                                  OCFS2_JOURNAL_ACCESS_CREATE);
+       ret = ocfs2_journal_access_di(handle, dir, di_bh,
+                                     OCFS2_JOURNAL_ACCESS_CREATE);
        if (ret) {
                mlog_errno(ret);
                goto out_commit;
@@ -1386,6 +1576,9 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
        dirdata_bh = NULL;
 
 out_commit:
+       if (ret < 0 && did_quota)
+               vfs_dq_free_space_nodirty(dir,
+                       ocfs2_clusters_to_bytes(osb->sb, 2));
        ocfs2_commit_trans(osb, handle);
 
 out_sem:
@@ -1410,7 +1603,7 @@ static int ocfs2_do_extend_dir(struct super_block *sb,
                               struct buffer_head **new_bh)
 {
        int status;
-       int extend;
+       int extend, did_quota = 0;
        u64 p_blkno, v_blkno;
 
        spin_lock(&OCFS2_I(dir)->ip_lock);
@@ -1420,6 +1613,13 @@ static int ocfs2_do_extend_dir(struct super_block *sb,
        if (extend) {
                u32 offset = OCFS2_I(dir)->ip_clusters;
 
+               if (vfs_dq_alloc_space_nodirty(dir,
+                                       ocfs2_clusters_to_bytes(sb, 1))) {
+                       status = -EDQUOT;
+                       goto bail;
+               }
+               did_quota = 1;
+
                status = ocfs2_add_inode_data(OCFS2_SB(sb), dir, &offset,
                                              1, 0, parent_fe_bh, handle,
                                              data_ac, meta_ac, NULL);
@@ -1445,6 +1645,8 @@ static int ocfs2_do_extend_dir(struct super_block *sb,
        }
        status = 0;
 bail:
+       if (did_quota && status < 0)
+               vfs_dq_free_space_nodirty(dir, ocfs2_clusters_to_bytes(sb, 1));
        mlog_exit(status);
        return status;
 }
@@ -1569,16 +1771,22 @@ do_extend:
 
        ocfs2_set_new_buffer_uptodate(dir, new_bh);
 
-       status = ocfs2_journal_access(handle, dir, new_bh,
-                                     OCFS2_JOURNAL_ACCESS_CREATE);
+       status = ocfs2_journal_access_db(handle, dir, new_bh,
+                                        OCFS2_JOURNAL_ACCESS_CREATE);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
        }
        memset(new_bh->b_data, 0, sb->s_blocksize);
+
        de = (struct ocfs2_dir_entry *) new_bh->b_data;
        de->inode = 0;
-       de->rec_len = cpu_to_le16(sb->s_blocksize);
+       if (ocfs2_dir_has_trailer(dir)) {
+               de->rec_len = cpu_to_le16(ocfs2_dir_trailer_blk_off(sb));
+               ocfs2_init_dir_trailer(dir, new_bh);
+       } else {
+               de->rec_len = cpu_to_le16(sb->s_blocksize);
+       }
        status = ocfs2_journal_dirty(handle, new_bh);
        if (status < 0) {
                mlog_errno(status);
@@ -1620,11 +1828,21 @@ static int ocfs2_find_dir_space_id(struct inode *dir, struct buffer_head *di_bh,
                                   unsigned int *blocks_wanted)
 {
        int ret;
+       struct super_block *sb = dir->i_sb;
        struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
        struct ocfs2_dir_entry *de, *last_de = NULL;
        char *de_buf, *limit;
        unsigned long offset = 0;
-       unsigned int rec_len, new_rec_len;
+       unsigned int rec_len, new_rec_len, free_space = dir->i_sb->s_blocksize;
+
+       /*
+        * This calculates how many free bytes we'd have in block zero, should
+        * this function force expansion to an extent tree.
+        */
+       if (ocfs2_supports_dir_trailer(OCFS2_SB(sb)))
+               free_space = ocfs2_dir_trailer_blk_off(sb) - i_size_read(dir);
+       else
+               free_space = dir->i_sb->s_blocksize - i_size_read(dir);
 
        de_buf = di->id2.i_data.id_data;
        limit = de_buf + i_size_read(dir);
@@ -1641,6 +1859,11 @@ static int ocfs2_find_dir_space_id(struct inode *dir, struct buffer_head *di_bh,
                        ret = -EEXIST;
                        goto out;
                }
+               /*
+                * No need to check for a trailing dirent record here as
+                * they're not used for inline dirs.
+                */
+
                if (ocfs2_dirent_would_fit(de, rec_len)) {
                        /* Ok, we found a spot. Return this bh and let
                         * the caller actually fill it in. */
@@ -1661,7 +1884,7 @@ static int ocfs2_find_dir_space_id(struct inode *dir, struct buffer_head *di_bh,
         * dirent can be found.
         */
        *blocks_wanted = 1;
-       new_rec_len = le16_to_cpu(last_de->rec_len) + (dir->i_sb->s_blocksize - i_size_read(dir));
+       new_rec_len = le16_to_cpu(last_de->rec_len) + free_space;
        if (new_rec_len < (rec_len + OCFS2_DIR_REC_LEN(last_de->name_len)))
                *blocks_wanted = 2;
 
@@ -1679,9 +1902,10 @@ static int ocfs2_find_dir_space_el(struct inode *dir, const char *name,
        struct ocfs2_dir_entry *de;
        struct super_block *sb = dir->i_sb;
        int status;
+       int blocksize = dir->i_sb->s_blocksize;
 
-       bh = ocfs2_bread(dir, 0, &status, 0);
-       if (!bh) {
+       status = ocfs2_read_dir_block(dir, 0, &bh, 0);
+       if (status) {
                mlog_errno(status);
                goto bail;
        }
@@ -1702,11 +1926,10 @@ static int ocfs2_find_dir_space_el(struct inode *dir, const char *name,
                                status = -ENOSPC;
                                goto bail;
                        }
-                       bh = ocfs2_bread(dir,
-                                        offset >> sb->s_blocksize_bits,
-                                        &status,
-                                        0);
-                       if (!bh) {
+                       status = ocfs2_read_dir_block(dir,
+                                            offset >> sb->s_blocksize_bits,
+                                            &bh, 0);
+                       if (status) {
                                mlog_errno(status);
                                goto bail;
                        }
@@ -1721,6 +1944,11 @@ static int ocfs2_find_dir_space_el(struct inode *dir, const char *name,
                        status = -EEXIST;
                        goto bail;
                }
+
+               if (ocfs2_skip_dir_trailer(dir, de, offset % blocksize,
+                                          blocksize))
+                       goto next;
+
                if (ocfs2_dirent_would_fit(de, rec_len)) {
                        /* Ok, we found a spot. Return this bh and let
                         * the caller actually fill it in. */
@@ -1729,6 +1957,7 @@ static int ocfs2_find_dir_space_el(struct inode *dir, const char *name,
                        status = 0;
                        goto bail;
                }
+next:
                offset += le16_to_cpu(de->rec_len);
                de = (struct ocfs2_dir_entry *)((char *) de + le16_to_cpu(de->rec_len));
        }
index ce48b9080d87c8b2a69839b9b33ee8433f2ee786..c511e2e18e9f064ff67d7b3299bad90f4fd99a94 100644 (file)
@@ -83,4 +83,6 @@ int ocfs2_fill_new_dir(struct ocfs2_super *osb,
                       struct buffer_head *fe_bh,
                       struct ocfs2_alloc_context *data_ac);
 
+struct ocfs2_dir_block_trailer *ocfs2_dir_trailer_from_size(int blocksize,
+                                                           void *data);
 #endif /* OCFS2_DIR_H */
index 644bee55d8ba4ccfb5ff29a489e2494274580c2f..d07ddbe4b2836d3e3e6d0f002808d8c36ef6c591 100644 (file)
@@ -275,6 +275,7 @@ int dlm_proxy_ast_handler(struct o2net_msg *msg, u32 len, void *data,
        struct list_head *iter, *head=NULL;
        u64 cookie;
        u32 flags;
+       u8 node;
 
        if (!dlm_grab(dlm)) {
                dlm_error(DLM_REJECTED);
@@ -286,18 +287,21 @@ int dlm_proxy_ast_handler(struct o2net_msg *msg, u32 len, void *data,
 
        name = past->name;
        locklen = past->namelen;
-       cookie = be64_to_cpu(past->cookie);
+       cookie = past->cookie;
        flags = be32_to_cpu(past->flags);
+       node = past->node_idx;
 
        if (locklen > DLM_LOCKID_NAME_MAX) {
                ret = DLM_IVBUFLEN;
-               mlog(ML_ERROR, "Invalid name length in proxy ast handler!\n");
+               mlog(ML_ERROR, "Invalid name length (%d) in proxy ast "
+                    "handler!\n", locklen);
                goto leave;
        }
 
        if ((flags & (LKM_PUT_LVB|LKM_GET_LVB)) ==
             (LKM_PUT_LVB|LKM_GET_LVB)) {
-               mlog(ML_ERROR, "both PUT and GET lvb specified\n");
+               mlog(ML_ERROR, "Both PUT and GET lvb specified, (0x%x)\n",
+                    flags);
                ret = DLM_BADARGS;
                goto leave;
        }
@@ -310,22 +314,21 @@ int dlm_proxy_ast_handler(struct o2net_msg *msg, u32 len, void *data,
        if (past->type != DLM_AST &&
            past->type != DLM_BAST) {
                mlog(ML_ERROR, "Unknown ast type! %d, cookie=%u:%llu"
-                    "name=%.*s\n", past->type, 
-                    dlm_get_lock_cookie_node(cookie),
-                    dlm_get_lock_cookie_seq(cookie),
-                    locklen, name);
+                    "name=%.*s, node=%u\n", past->type,
+                    dlm_get_lock_cookie_node(be64_to_cpu(cookie)),
+                    dlm_get_lock_cookie_seq(be64_to_cpu(cookie)),
+                    locklen, name, node);
                ret = DLM_IVLOCKID;
                goto leave;
        }
 
        res = dlm_lookup_lockres(dlm, name, locklen);
        if (!res) {
-               mlog(0, "got %sast for unknown lockres! "
-                    "cookie=%u:%llu, name=%.*s, namelen=%u\n",
-                    past->type == DLM_AST ? "" : "b",
-                    dlm_get_lock_cookie_node(cookie),
-                    dlm_get_lock_cookie_seq(cookie),
-                    locklen, name, locklen);
+               mlog(0, "Got %sast for unknown lockres! cookie=%u:%llu, "
+                    "name=%.*s, node=%u\n", (past->type == DLM_AST ? "" : "b"),
+                    dlm_get_lock_cookie_node(be64_to_cpu(cookie)),
+                    dlm_get_lock_cookie_seq(be64_to_cpu(cookie)),
+                    locklen, name, node);
                ret = DLM_IVLOCKID;
                goto leave;
        }
@@ -337,12 +340,12 @@ int dlm_proxy_ast_handler(struct o2net_msg *msg, u32 len, void *data,
 
        spin_lock(&res->spinlock);
        if (res->state & DLM_LOCK_RES_RECOVERING) {
-               mlog(0, "responding with DLM_RECOVERING!\n");
+               mlog(0, "Responding with DLM_RECOVERING!\n");
                ret = DLM_RECOVERING;
                goto unlock_out;
        }
        if (res->state & DLM_LOCK_RES_MIGRATING) {
-               mlog(0, "responding with DLM_MIGRATING!\n");
+               mlog(0, "Responding with DLM_MIGRATING!\n");
                ret = DLM_MIGRATING;
                goto unlock_out;
        }
@@ -351,7 +354,7 @@ int dlm_proxy_ast_handler(struct o2net_msg *msg, u32 len, void *data,
        lock = NULL;
        list_for_each(iter, head) {
                lock = list_entry (iter, struct dlm_lock, list);
-               if (be64_to_cpu(lock->ml.cookie) == cookie)
+               if (lock->ml.cookie == cookie)
                        goto do_ast;
        }
 
@@ -363,15 +366,15 @@ int dlm_proxy_ast_handler(struct o2net_msg *msg, u32 len, void *data,
 
        list_for_each(iter, head) {
                lock = list_entry (iter, struct dlm_lock, list);
-               if (be64_to_cpu(lock->ml.cookie) == cookie)
+               if (lock->ml.cookie == cookie)
                        goto do_ast;
        }
 
-       mlog(0, "got %sast for unknown lock!  cookie=%u:%llu, "
-            "name=%.*s, namelen=%u\n", past->type == DLM_AST ? "" : "b", 
-            dlm_get_lock_cookie_node(cookie),
-            dlm_get_lock_cookie_seq(cookie),
-            locklen, name, locklen);
+       mlog(0, "Got %sast for unknown lock! cookie=%u:%llu, name=%.*s, "
+            "node=%u\n", past->type == DLM_AST ? "" : "b",
+            dlm_get_lock_cookie_node(be64_to_cpu(cookie)),
+            dlm_get_lock_cookie_seq(be64_to_cpu(cookie)),
+            locklen, name, node);
 
        ret = DLM_NORMAL;
 unlock_out:
@@ -383,8 +386,8 @@ do_ast:
        if (past->type == DLM_AST) {
                /* do not alter lock refcount.  switching lists. */
                list_move_tail(&lock->list, &res->granted);
-               mlog(0, "ast: adding to granted list... type=%d, "
-                         "convert_type=%d\n", lock->ml.type, lock->ml.convert_type);
+               mlog(0, "ast: Adding to granted list... type=%d, "
+                    "convert_type=%d\n", lock->ml.type, lock->ml.convert_type);
                if (lock->ml.convert_type != LKM_IVMODE) {
                        lock->ml.type = lock->ml.convert_type;
                        lock->ml.convert_type = LKM_IVMODE;
@@ -408,7 +411,6 @@ do_ast:
                dlm_do_local_bast(dlm, res, lock, past->blocked_type);
 
 leave:
-
        if (res)
                dlm_lockres_put(res);
 
index d5a86fb81a4902adff4426b552cd3ae19a5d926d..bb53714813abb716dca2bb2fe793ee64dd36a8e9 100644 (file)
@@ -140,6 +140,7 @@ struct dlm_ctxt
        unsigned int purge_count;
        spinlock_t spinlock;
        spinlock_t ast_lock;
+       spinlock_t track_lock;
        char *name;
        u8 node_num;
        u32 key;
@@ -316,6 +317,8 @@ struct dlm_lock_resource
         * put on a list for the dlm thread to run. */
        unsigned long    last_used;
 
+       struct dlm_ctxt *dlm;
+
        unsigned migration_pending:1;
        atomic_t asts_reserved;
        spinlock_t spinlock;
index 1b81dcba175d083ba5cefad5178c2c1a8a3ef271..b32f60a5acfb9e4353ce3ad61d009bb6858d158f 100644 (file)
@@ -630,43 +630,38 @@ static void *lockres_seq_start(struct seq_file *m, loff_t *pos)
 {
        struct debug_lockres *dl = m->private;
        struct dlm_ctxt *dlm = dl->dl_ctxt;
+       struct dlm_lock_resource *oldres = dl->dl_res;
        struct dlm_lock_resource *res = NULL;
+       struct list_head *track_list;
 
-       spin_lock(&dlm->spinlock);
+       spin_lock(&dlm->track_lock);
+       if (oldres)
+               track_list = &oldres->tracking;
+       else
+               track_list = &dlm->tracking_list;
 
-       if (dl->dl_res) {
-               list_for_each_entry(res, &dl->dl_res->tracking, tracking) {
-                       if (dl->dl_res) {
-                               dlm_lockres_put(dl->dl_res);
-                               dl->dl_res = NULL;
-                       }
-                       if (&res->tracking == &dlm->tracking_list) {
-                               mlog(0, "End of list found, %p\n", res);
-                               dl = NULL;
-                               break;
-                       }
+       list_for_each_entry(res, track_list, tracking) {
+               if (&res->tracking == &dlm->tracking_list)
+                       res = NULL;
+               else
                        dlm_lockres_get(res);
-                       dl->dl_res = res;
-                       break;
-               }
-       } else {
-               if (!list_empty(&dlm->tracking_list)) {
-                       list_for_each_entry(res, &dlm->tracking_list, tracking)
-                               break;
-                       dlm_lockres_get(res);
-                       dl->dl_res = res;
-               } else
-                       dl = NULL;
+               break;
        }
+       spin_unlock(&dlm->track_lock);
 
-       if (dl) {
-               spin_lock(&dl->dl_res->spinlock);
-               dump_lockres(dl->dl_res, dl->dl_buf, dl->dl_len - 1);
-               spin_unlock(&dl->dl_res->spinlock);
-       }
+       if (oldres)
+               dlm_lockres_put(oldres);
 
-       spin_unlock(&dlm->spinlock);
+       dl->dl_res = res;
+
+       if (res) {
+               spin_lock(&res->spinlock);
+               dump_lockres(res, dl->dl_buf, dl->dl_len - 1);
+               spin_unlock(&res->spinlock);
+       } else
+               dl = NULL;
 
+       /* passed to seq_show */
        return dl;
 }
 
index 63f8125824e8200a08c5daa3bebdcec6bf8374e1..d8d578f4561389f2b5083fdd03d4a66ebfeee1a9 100644 (file)
@@ -1550,6 +1550,7 @@ static struct dlm_ctxt *dlm_alloc_ctxt(const char *domain,
        spin_lock_init(&dlm->spinlock);
        spin_lock_init(&dlm->master_lock);
        spin_lock_init(&dlm->ast_lock);
+       spin_lock_init(&dlm->track_lock);
        INIT_LIST_HEAD(&dlm->list);
        INIT_LIST_HEAD(&dlm->dirty_list);
        INIT_LIST_HEAD(&dlm->reco.resources);
index 6f7a77d5402001071f4f75a6f7ccbf5cf666a537..1c9efb406a96b98a36fa5ae5450198b6e8e8a067 100644 (file)
@@ -341,7 +341,6 @@ static struct inode *dlmfs_get_root_inode(struct super_block *sb)
                inode->i_mode = mode;
                inode->i_uid = current_fsuid();
                inode->i_gid = current_fsgid();
-               inode->i_blocks = 0;
                inode->i_mapping->backing_dev_info = &dlmfs_backing_dev_info;
                inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
                inc_nlink(inode);
@@ -367,7 +366,6 @@ static struct inode *dlmfs_get_inode(struct inode *parent,
        inode->i_mode = mode;
        inode->i_uid = current_fsuid();
        inode->i_gid = current_fsgid();
-       inode->i_blocks = 0;
        inode->i_mapping->backing_dev_info = &dlmfs_backing_dev_info;
        inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 
index 44f87caf36834fda999768a06448953afcaa6ef4..54e182a27caf81a86b96fb9cc133b5776346e028 100644 (file)
@@ -505,8 +505,10 @@ void dlm_change_lockres_owner(struct dlm_ctxt *dlm,
 static void dlm_lockres_release(struct kref *kref)
 {
        struct dlm_lock_resource *res;
+       struct dlm_ctxt *dlm;
 
        res = container_of(kref, struct dlm_lock_resource, refs);
+       dlm = res->dlm;
 
        /* This should not happen -- all lockres' have a name
         * associated with them at init time. */
@@ -515,6 +517,7 @@ static void dlm_lockres_release(struct kref *kref)
        mlog(0, "destroying lockres %.*s\n", res->lockname.len,
             res->lockname.name);
 
+       spin_lock(&dlm->track_lock);
        if (!list_empty(&res->tracking))
                list_del_init(&res->tracking);
        else {
@@ -522,6 +525,9 @@ static void dlm_lockres_release(struct kref *kref)
                     res->lockname.len, res->lockname.name);
                dlm_print_one_lock_resource(res);
        }
+       spin_unlock(&dlm->track_lock);
+
+       dlm_put(dlm);
 
        if (!hlist_unhashed(&res->hash_node) ||
            !list_empty(&res->granted) ||
@@ -595,6 +601,10 @@ static void dlm_init_lockres(struct dlm_ctxt *dlm,
        res->migration_pending = 0;
        res->inflight_locks = 0;
 
+       /* put in dlm_lockres_release */
+       dlm_grab(dlm);
+       res->dlm = dlm;
+
        kref_init(&res->refs);
 
        /* just for consistency */
@@ -722,14 +732,21 @@ lookup:
        if (tmpres) {
                int dropping_ref = 0;
 
+               spin_unlock(&dlm->spinlock);
+
                spin_lock(&tmpres->spinlock);
+               /* We wait for the other thread that is mastering the resource */
+               if (tmpres->owner == DLM_LOCK_RES_OWNER_UNKNOWN) {
+                       __dlm_wait_on_lockres(tmpres);
+                       BUG_ON(tmpres->owner == DLM_LOCK_RES_OWNER_UNKNOWN);
+               }
+
                if (tmpres->owner == dlm->node_num) {
                        BUG_ON(tmpres->state & DLM_LOCK_RES_DROPPING_REF);
                        dlm_lockres_grab_inflight_ref(dlm, tmpres);
                } else if (tmpres->state & DLM_LOCK_RES_DROPPING_REF)
                        dropping_ref = 1;
                spin_unlock(&tmpres->spinlock);
-               spin_unlock(&dlm->spinlock);
 
                /* wait until done messaging the master, drop our ref to allow
                 * the lockres to be purged, start over. */
@@ -2949,7 +2966,7 @@ static int dlm_do_migrate_request(struct dlm_ctxt *dlm,
                                  struct dlm_node_iter *iter)
 {
        struct dlm_migrate_request migrate;
-       int ret, status = 0;
+       int ret, skip, status = 0;
        int nodenum;
 
        memset(&migrate, 0, sizeof(migrate));
@@ -2966,12 +2983,27 @@ static int dlm_do_migrate_request(struct dlm_ctxt *dlm,
                    nodenum == new_master)
                        continue;
 
+               /* We could race exit domain. If exited, skip. */
+               spin_lock(&dlm->spinlock);
+               skip = (!test_bit(nodenum, dlm->domain_map));
+               spin_unlock(&dlm->spinlock);
+               if (skip) {
+                       clear_bit(nodenum, iter->node_map);
+                       continue;
+               }
+
                ret = o2net_send_message(DLM_MIGRATE_REQUEST_MSG, dlm->key,
                                         &migrate, sizeof(migrate), nodenum,
                                         &status);
-               if (ret < 0)
-                       mlog_errno(ret);
-               else if (status < 0) {
+               if (ret < 0) {
+                       mlog(0, "migrate_request returned %d!\n", ret);
+                       if (!dlm_is_host_down(ret)) {
+                               mlog(ML_ERROR, "unhandled error=%d!\n", ret);
+                               BUG();
+                       }
+                       clear_bit(nodenum, iter->node_map);
+                       ret = 0;
+               } else if (status < 0) {
                        mlog(0, "migrate request (node %u) returned %d!\n",
                             nodenum, status);
                        ret = status;
index 4060bb328bc8a08c22bbd77c59835d757ebdcda5..d1295203029fd927131e626c44f97def0433a918 100644 (file)
@@ -181,7 +181,8 @@ static int dlm_purge_lockres(struct dlm_ctxt *dlm,
 
                spin_lock(&res->spinlock);
                /* This ensures that clear refmap is sent after the set */
-               __dlm_wait_on_lockres_flags(res, DLM_LOCK_RES_SETREF_INPROG);
+               __dlm_wait_on_lockres_flags(res, (DLM_LOCK_RES_SETREF_INPROG |
+                                                 DLM_LOCK_RES_MIGRATING));
                spin_unlock(&res->spinlock);
 
                /* clear our bit from the master's refmap, ignore errors */
index 6e6cc0a2e5f7a51ed9c5e3b72e4ae90471ea77a7..f731ab4917951feae22d07b30d837a2ca7e0994b 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 #include <linux/time.h>
+#include <linux/quotaops.h>
 
 #define MLOG_MASK_PREFIX ML_DLM_GLUE
 #include <cluster/masklog.h>
@@ -51,6 +52,7 @@
 #include "slot_map.h"
 #include "super.h"
 #include "uptodate.h"
+#include "quota.h"
 
 #include "buffer_head_io.h"
 
@@ -68,6 +70,7 @@ struct ocfs2_mask_waiter {
 static struct ocfs2_super *ocfs2_get_dentry_osb(struct ocfs2_lock_res *lockres);
 static struct ocfs2_super *ocfs2_get_inode_osb(struct ocfs2_lock_res *lockres);
 static struct ocfs2_super *ocfs2_get_file_osb(struct ocfs2_lock_res *lockres);
+static struct ocfs2_super *ocfs2_get_qinfo_osb(struct ocfs2_lock_res *lockres);
 
 /*
  * Return value from ->downconvert_worker functions.
@@ -102,6 +105,7 @@ static int ocfs2_dentry_convert_worker(struct ocfs2_lock_res *lockres,
 static void ocfs2_dentry_post_unlock(struct ocfs2_super *osb,
                                     struct ocfs2_lock_res *lockres);
 
+static void ocfs2_set_qinfo_lvb(struct ocfs2_lock_res *lockres);
 
 #define mlog_meta_lvb(__level, __lockres) ocfs2_dump_meta_lvb_info(__level, __PRETTY_FUNCTION__, __LINE__, __lockres)
 
@@ -111,8 +115,7 @@ static void ocfs2_dump_meta_lvb_info(u64 level,
                                     unsigned int line,
                                     struct ocfs2_lock_res *lockres)
 {
-       struct ocfs2_meta_lvb *lvb =
-               (struct ocfs2_meta_lvb *)ocfs2_dlm_lvb(&lockres->l_lksb);
+       struct ocfs2_meta_lvb *lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
 
        mlog(level, "LVB information for %s (called from %s:%u):\n",
             lockres->l_name, function, line);
@@ -258,6 +261,12 @@ static struct ocfs2_lock_res_ops ocfs2_flock_lops = {
        .flags          = 0,
 };
 
+static struct ocfs2_lock_res_ops ocfs2_qinfo_lops = {
+       .set_lvb        = ocfs2_set_qinfo_lvb,
+       .get_osb        = ocfs2_get_qinfo_osb,
+       .flags          = LOCK_TYPE_REQUIRES_REFRESH | LOCK_TYPE_USES_LVB,
+};
+
 static inline int ocfs2_is_inode_lock(struct ocfs2_lock_res *lockres)
 {
        return lockres->l_type == OCFS2_LOCK_TYPE_META ||
@@ -279,6 +288,13 @@ static inline struct ocfs2_dentry_lock *ocfs2_lock_res_dl(struct ocfs2_lock_res
        return (struct ocfs2_dentry_lock *)lockres->l_priv;
 }
 
+static inline struct ocfs2_mem_dqinfo *ocfs2_lock_res_qinfo(struct ocfs2_lock_res *lockres)
+{
+       BUG_ON(lockres->l_type != OCFS2_LOCK_TYPE_QINFO);
+
+       return (struct ocfs2_mem_dqinfo *)lockres->l_priv;
+}
+
 static inline struct ocfs2_super *ocfs2_get_lockres_osb(struct ocfs2_lock_res *lockres)
 {
        if (lockres->l_ops->get_osb)
@@ -507,6 +523,13 @@ static struct ocfs2_super *ocfs2_get_inode_osb(struct ocfs2_lock_res *lockres)
        return OCFS2_SB(inode->i_sb);
 }
 
+static struct ocfs2_super *ocfs2_get_qinfo_osb(struct ocfs2_lock_res *lockres)
+{
+       struct ocfs2_mem_dqinfo *info = lockres->l_priv;
+
+       return OCFS2_SB(info->dqi_gi.dqi_sb);
+}
+
 static struct ocfs2_super *ocfs2_get_file_osb(struct ocfs2_lock_res *lockres)
 {
        struct ocfs2_file_private *fp = lockres->l_priv;
@@ -609,6 +632,17 @@ void ocfs2_file_lock_res_init(struct ocfs2_lock_res *lockres,
        lockres->l_flags |= OCFS2_LOCK_NOCACHE;
 }
 
+void ocfs2_qinfo_lock_res_init(struct ocfs2_lock_res *lockres,
+                              struct ocfs2_mem_dqinfo *info)
+{
+       ocfs2_lock_res_init_once(lockres);
+       ocfs2_build_lock_name(OCFS2_LOCK_TYPE_QINFO, info->dqi_gi.dqi_type,
+                             0, lockres->l_name);
+       ocfs2_lock_res_init_common(OCFS2_SB(info->dqi_gi.dqi_sb), lockres,
+                                  OCFS2_LOCK_TYPE_QINFO, &ocfs2_qinfo_lops,
+                                  info);
+}
+
 void ocfs2_lock_res_free(struct ocfs2_lock_res *res)
 {
        mlog_entry_void();
@@ -1829,7 +1863,7 @@ static void __ocfs2_stuff_meta_lvb(struct inode *inode)
 
        mlog_entry_void();
 
-       lvb = (struct ocfs2_meta_lvb *)ocfs2_dlm_lvb(&lockres->l_lksb);
+       lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
 
        /*
         * Invalidate the LVB of a deleted inode - this way other
@@ -1881,7 +1915,7 @@ static void ocfs2_refresh_inode_from_lvb(struct inode *inode)
 
        mlog_meta_lvb(0, lockres);
 
-       lvb = (struct ocfs2_meta_lvb *)ocfs2_dlm_lvb(&lockres->l_lksb);
+       lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
 
        /* We're safe here without the lockres lock... */
        spin_lock(&oi->ip_lock);
@@ -1916,8 +1950,7 @@ static void ocfs2_refresh_inode_from_lvb(struct inode *inode)
 static inline int ocfs2_meta_lvb_is_trustable(struct inode *inode,
                                              struct ocfs2_lock_res *lockres)
 {
-       struct ocfs2_meta_lvb *lvb =
-               (struct ocfs2_meta_lvb *)ocfs2_dlm_lvb(&lockres->l_lksb);
+       struct ocfs2_meta_lvb *lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
 
        if (lvb->lvb_version == OCFS2_LVB_VERSION
            && be32_to_cpu(lvb->lvb_igeneration) == inode->i_generation)
@@ -2024,7 +2057,7 @@ static int ocfs2_inode_lock_update(struct inode *inode,
        } else {
                /* Boo, we have to go to disk. */
                /* read bh, cast, ocfs2_refresh_inode */
-               status = ocfs2_read_block(inode, oi->ip_blkno, bh);
+               status = ocfs2_read_inode_block(inode, bh);
                if (status < 0) {
                        mlog_errno(status);
                        goto bail_refresh;
@@ -2032,18 +2065,14 @@ static int ocfs2_inode_lock_update(struct inode *inode,
                fe = (struct ocfs2_dinode *) (*bh)->b_data;
 
                /* This is a good chance to make sure we're not
-                * locking an invalid object.
+                * locking an invalid object.  ocfs2_read_inode_block()
+                * already checked that the inode block is sane.
                 *
                 * We bug on a stale inode here because we checked
                 * above whether it was wiped from disk. The wiping
                 * node provides a guarantee that we receive that
                 * message and can mark the inode before dropping any
                 * locks associated with it. */
-               if (!OCFS2_IS_VALID_DINODE(fe)) {
-                       OCFS2_RO_ON_INVALID_DINODE(inode->i_sb, fe);
-                       status = -EIO;
-                       goto bail_refresh;
-               }
                mlog_bug_on_msg(inode->i_generation !=
                                le32_to_cpu(fe->i_generation),
                                "Invalid dinode %llu disk generation: %u "
@@ -2085,7 +2114,7 @@ static int ocfs2_assign_bh(struct inode *inode,
                return 0;
        }
 
-       status = ocfs2_read_block(inode, OCFS2_I(inode)->ip_blkno, ret_bh);
+       status = ocfs2_read_inode_block(inode, ret_bh);
        if (status < 0)
                mlog_errno(status);
 
@@ -3449,6 +3478,117 @@ static int ocfs2_dentry_convert_worker(struct ocfs2_lock_res *lockres,
        return UNBLOCK_CONTINUE_POST;
 }
 
+static void ocfs2_set_qinfo_lvb(struct ocfs2_lock_res *lockres)
+{
+       struct ocfs2_qinfo_lvb *lvb;
+       struct ocfs2_mem_dqinfo *oinfo = ocfs2_lock_res_qinfo(lockres);
+       struct mem_dqinfo *info = sb_dqinfo(oinfo->dqi_gi.dqi_sb,
+                                           oinfo->dqi_gi.dqi_type);
+
+       mlog_entry_void();
+
+       lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
+       lvb->lvb_version = OCFS2_QINFO_LVB_VERSION;
+       lvb->lvb_bgrace = cpu_to_be32(info->dqi_bgrace);
+       lvb->lvb_igrace = cpu_to_be32(info->dqi_igrace);
+       lvb->lvb_syncms = cpu_to_be32(oinfo->dqi_syncms);
+       lvb->lvb_blocks = cpu_to_be32(oinfo->dqi_gi.dqi_blocks);
+       lvb->lvb_free_blk = cpu_to_be32(oinfo->dqi_gi.dqi_free_blk);
+       lvb->lvb_free_entry = cpu_to_be32(oinfo->dqi_gi.dqi_free_entry);
+
+       mlog_exit_void();
+}
+
+void ocfs2_qinfo_unlock(struct ocfs2_mem_dqinfo *oinfo, int ex)
+{
+       struct ocfs2_lock_res *lockres = &oinfo->dqi_gqlock;
+       struct ocfs2_super *osb = OCFS2_SB(oinfo->dqi_gi.dqi_sb);
+       int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
+
+       mlog_entry_void();
+       if (!ocfs2_is_hard_readonly(osb) && !ocfs2_mount_local(osb))
+               ocfs2_cluster_unlock(osb, lockres, level);
+       mlog_exit_void();
+}
+
+static int ocfs2_refresh_qinfo(struct ocfs2_mem_dqinfo *oinfo)
+{
+       struct mem_dqinfo *info = sb_dqinfo(oinfo->dqi_gi.dqi_sb,
+                                           oinfo->dqi_gi.dqi_type);
+       struct ocfs2_lock_res *lockres = &oinfo->dqi_gqlock;
+       struct ocfs2_qinfo_lvb *lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
+       struct buffer_head *bh = NULL;
+       struct ocfs2_global_disk_dqinfo *gdinfo;
+       int status = 0;
+
+       if (lvb->lvb_version == OCFS2_QINFO_LVB_VERSION) {
+               info->dqi_bgrace = be32_to_cpu(lvb->lvb_bgrace);
+               info->dqi_igrace = be32_to_cpu(lvb->lvb_igrace);
+               oinfo->dqi_syncms = be32_to_cpu(lvb->lvb_syncms);
+               oinfo->dqi_gi.dqi_blocks = be32_to_cpu(lvb->lvb_blocks);
+               oinfo->dqi_gi.dqi_free_blk = be32_to_cpu(lvb->lvb_free_blk);
+               oinfo->dqi_gi.dqi_free_entry =
+                                       be32_to_cpu(lvb->lvb_free_entry);
+       } else {
+               status = ocfs2_read_quota_block(oinfo->dqi_gqinode, 0, &bh);
+               if (status) {
+                       mlog_errno(status);
+                       goto bail;
+               }
+               gdinfo = (struct ocfs2_global_disk_dqinfo *)
+                                       (bh->b_data + OCFS2_GLOBAL_INFO_OFF);
+               info->dqi_bgrace = le32_to_cpu(gdinfo->dqi_bgrace);
+               info->dqi_igrace = le32_to_cpu(gdinfo->dqi_igrace);
+               oinfo->dqi_syncms = le32_to_cpu(gdinfo->dqi_syncms);
+               oinfo->dqi_gi.dqi_blocks = le32_to_cpu(gdinfo->dqi_blocks);
+               oinfo->dqi_gi.dqi_free_blk = le32_to_cpu(gdinfo->dqi_free_blk);
+               oinfo->dqi_gi.dqi_free_entry =
+                                       le32_to_cpu(gdinfo->dqi_free_entry);
+               brelse(bh);
+               ocfs2_track_lock_refresh(lockres);
+       }
+
+bail:
+       return status;
+}
+
+/* Lock quota info, this function expects at least shared lock on the quota file
+ * so that we can safely refresh quota info from disk. */
+int ocfs2_qinfo_lock(struct ocfs2_mem_dqinfo *oinfo, int ex)
+{
+       struct ocfs2_lock_res *lockres = &oinfo->dqi_gqlock;
+       struct ocfs2_super *osb = OCFS2_SB(oinfo->dqi_gi.dqi_sb);
+       int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
+       int status = 0;
+
+       mlog_entry_void();
+
+       /* On RO devices, locking really isn't needed... */
+       if (ocfs2_is_hard_readonly(osb)) {
+               if (ex)
+                       status = -EROFS;
+               goto bail;
+       }
+       if (ocfs2_mount_local(osb))
+               goto bail;
+
+       status = ocfs2_cluster_lock(osb, lockres, level, 0, 0);
+       if (status < 0) {
+               mlog_errno(status);
+               goto bail;
+       }
+       if (!ocfs2_should_refresh_lock_res(lockres))
+               goto bail;
+       /* OK, we have the lock but we need to refresh the quota info */
+       status = ocfs2_refresh_qinfo(oinfo);
+       if (status)
+               ocfs2_qinfo_unlock(oinfo, ex);
+       ocfs2_complete_lock_res_refresh(lockres, status);
+bail:
+       mlog_exit(status);
+       return status;
+}
+
 /*
  * This is the filesystem locking protocol.  It provides the lock handling
  * hooks for the underlying DLM.  It has a maximum version number.
index 2bb01f09c1b11eb39bbb6efa35a438f69f1cd8bb..3f8d9986b8e0e82d9f8b938ef9d648669b14fff0 100644 (file)
@@ -49,6 +49,19 @@ struct ocfs2_meta_lvb {
        __be32       lvb_reserved2;
 };
 
+#define OCFS2_QINFO_LVB_VERSION 1
+
+struct ocfs2_qinfo_lvb {
+       __u8    lvb_version;
+       __u8    lvb_reserved[3];
+       __be32  lvb_bgrace;
+       __be32  lvb_igrace;
+       __be32  lvb_syncms;
+       __be32  lvb_blocks;
+       __be32  lvb_free_blk;
+       __be32  lvb_free_entry;
+};
+
 /* ocfs2_inode_lock_full() 'arg_flags' flags */
 /* don't wait on recovery. */
 #define OCFS2_META_LOCK_RECOVERY       (0x01)
@@ -69,6 +82,9 @@ void ocfs2_dentry_lock_res_init(struct ocfs2_dentry_lock *dl,
 struct ocfs2_file_private;
 void ocfs2_file_lock_res_init(struct ocfs2_lock_res *lockres,
                              struct ocfs2_file_private *fp);
+struct ocfs2_mem_dqinfo;
+void ocfs2_qinfo_lock_res_init(struct ocfs2_lock_res *lockres,
+                               struct ocfs2_mem_dqinfo *info);
 void ocfs2_lock_res_free(struct ocfs2_lock_res *res);
 int ocfs2_create_new_inode_locks(struct inode *inode);
 int ocfs2_drop_inode_locks(struct inode *inode);
@@ -103,6 +119,9 @@ int ocfs2_dentry_lock(struct dentry *dentry, int ex);
 void ocfs2_dentry_unlock(struct dentry *dentry, int ex);
 int ocfs2_file_lock(struct file *file, int ex, int trylock);
 void ocfs2_file_unlock(struct file *file);
+int ocfs2_qinfo_lock(struct ocfs2_mem_dqinfo *oinfo, int ex);
+void ocfs2_qinfo_unlock(struct ocfs2_mem_dqinfo *oinfo, int ex);
+
 
 void ocfs2_mark_lockres_freeing(struct ocfs2_lock_res *lockres);
 void ocfs2_simple_drop_lockres(struct ocfs2_super *osb,
index 2baedac582341dbb60986840b29daded17521842..f2bb1a04d2530451f137b091923025b5d9cad555 100644 (file)
@@ -293,7 +293,7 @@ static int ocfs2_last_eb_is_empty(struct inode *inode,
        struct ocfs2_extent_block *eb;
        struct ocfs2_extent_list *el;
 
-       ret = ocfs2_read_block(inode, last_eb_blk, &eb_bh);
+       ret = ocfs2_read_extent_block(inode, last_eb_blk, &eb_bh);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -302,12 +302,6 @@ static int ocfs2_last_eb_is_empty(struct inode *inode,
        eb = (struct ocfs2_extent_block *) eb_bh->b_data;
        el = &eb->h_list;
 
-       if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {
-               ret = -EROFS;
-               OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, eb);
-               goto out;
-       }
-
        if (el->l_tree_depth) {
                ocfs2_error(inode->i_sb,
                            "Inode %lu has non zero tree depth in "
@@ -381,23 +375,16 @@ static int ocfs2_figure_hole_clusters(struct inode *inode,
                if (le64_to_cpu(eb->h_next_leaf_blk) == 0ULL)
                        goto no_more_extents;
 
-               ret = ocfs2_read_block(inode,
-                                      le64_to_cpu(eb->h_next_leaf_blk),
-                                      &next_eb_bh);
+               ret = ocfs2_read_extent_block(inode,
+                                             le64_to_cpu(eb->h_next_leaf_blk),
+                                             &next_eb_bh);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
                }
-               next_eb = (struct ocfs2_extent_block *)next_eb_bh->b_data;
-
-               if (!OCFS2_IS_VALID_EXTENT_BLOCK(next_eb)) {
-                       ret = -EROFS;
-                       OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, next_eb);
-                       goto out;
-               }
 
+               next_eb = (struct ocfs2_extent_block *)next_eb_bh->b_data;
                el = &next_eb->h_list;
-
                i = ocfs2_search_for_hole_index(el, v_cluster);
        }
 
@@ -630,7 +617,7 @@ int ocfs2_get_clusters(struct inode *inode, u32 v_cluster,
        if (ret == 0)
                goto out;
 
-       ret = ocfs2_read_block(inode, OCFS2_I(inode)->ip_blkno, &di_bh);
+       ret = ocfs2_read_inode_block(inode, &di_bh);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -819,3 +806,74 @@ out:
 
        return ret;
 }
+
+int ocfs2_read_virt_blocks(struct inode *inode, u64 v_block, int nr,
+                          struct buffer_head *bhs[], int flags,
+                          int (*validate)(struct super_block *sb,
+                                          struct buffer_head *bh))
+{
+       int rc = 0;
+       u64 p_block, p_count;
+       int i, count, done = 0;
+
+       mlog_entry("(inode = %p, v_block = %llu, nr = %d, bhs = %p, "
+                  "flags = %x, validate = %p)\n",
+                  inode, (unsigned long long)v_block, nr, bhs, flags,
+                  validate);
+
+       if (((v_block + nr - 1) << inode->i_sb->s_blocksize_bits) >=
+           i_size_read(inode)) {
+               BUG_ON(!(flags & OCFS2_BH_READAHEAD));
+               goto out;
+       }
+
+       while (done < nr) {
+               down_read(&OCFS2_I(inode)->ip_alloc_sem);
+               rc = ocfs2_extent_map_get_blocks(inode, v_block + done,
+                                                &p_block, &p_count, NULL);
+               up_read(&OCFS2_I(inode)->ip_alloc_sem);
+               if (rc) {
+                       mlog_errno(rc);
+                       break;
+               }
+
+               if (!p_block) {
+                       rc = -EIO;
+                       mlog(ML_ERROR,
+                            "Inode #%llu contains a hole at offset %llu\n",
+                            (unsigned long long)OCFS2_I(inode)->ip_blkno,
+                            (unsigned long long)(v_block + done) <<
+                            inode->i_sb->s_blocksize_bits);
+                       break;
+               }
+
+               count = nr - done;
+               if (p_count < count)
+                       count = p_count;
+
+               /*
+                * If the caller passed us bhs, they should have come
+                * from a previous readahead call to this function.  Thus,
+                * they should have the right b_blocknr.
+                */
+               for (i = 0; i < count; i++) {
+                       if (!bhs[done + i])
+                               continue;
+                       BUG_ON(bhs[done + i]->b_blocknr != (p_block + i));
+               }
+
+               rc = ocfs2_read_blocks(inode, p_block, count, bhs + done,
+                                      flags, validate);
+               if (rc) {
+                       mlog_errno(rc);
+                       break;
+               }
+               done += count;
+       }
+
+out:
+       mlog_exit(rc);
+       return rc;
+}
+
+
index 1c4aa8b06f348c89b4560f733cdd0e1aefe9e852..b7dd9731b4629a942d10c44472d925dc49738fa7 100644 (file)
@@ -57,4 +57,28 @@ int ocfs2_xattr_get_clusters(struct inode *inode, u32 v_cluster,
                             u32 *p_cluster, u32 *num_clusters,
                             struct ocfs2_extent_list *el);
 
+int ocfs2_read_virt_blocks(struct inode *inode, u64 v_block, int nr,
+                          struct buffer_head *bhs[], int flags,
+                          int (*validate)(struct super_block *sb,
+                                          struct buffer_head *bh));
+static inline int ocfs2_read_virt_block(struct inode *inode, u64 v_block,
+                                       struct buffer_head **bh,
+                                       int (*validate)(struct super_block *sb,
+                                                       struct buffer_head *bh))
+{
+       int status = 0;
+
+       if (bh == NULL) {
+               printk("ocfs2: bh == NULL\n");
+               status = -EINVAL;
+               goto bail;
+       }
+
+       status = ocfs2_read_virt_blocks(inode, v_block, 1, bh, 0, validate);
+
+bail:
+       return status;
+}
+
+
 #endif  /* _EXTENT_MAP_H */
index e2570a3bc2b202e2abb833be86ffc7750cc635c7..e8f795f978aaae80c865d8ed55e694fcbcf35fa1 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/mount.h>
 #include <linux/writeback.h>
 #include <linux/falloc.h>
+#include <linux/quotaops.h>
 
 #define MLOG_MASK_PREFIX ML_INODE
 #include <cluster/masklog.h>
@@ -56,6 +57,8 @@
 #include "suballoc.h"
 #include "super.h"
 #include "xattr.h"
+#include "acl.h"
+#include "quota.h"
 
 #include "buffer_head_io.h"
 
@@ -253,8 +256,8 @@ int ocfs2_update_inode_atime(struct inode *inode,
                goto out;
        }
 
-       ret = ocfs2_journal_access(handle, inode, bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = ocfs2_journal_access_di(handle, inode, bh,
+                                     OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
                goto out_commit;
@@ -303,9 +306,9 @@ bail:
        return status;
 }
 
-static int ocfs2_simple_size_update(struct inode *inode,
-                                   struct buffer_head *di_bh,
-                                   u64 new_i_size)
+int ocfs2_simple_size_update(struct inode *inode,
+                            struct buffer_head *di_bh,
+                            u64 new_i_size)
 {
        int ret;
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
@@ -350,8 +353,8 @@ static int ocfs2_orphan_for_truncate(struct ocfs2_super *osb,
                goto out;
        }
 
-       status = ocfs2_journal_access(handle, inode, fe_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_journal_access_di(handle, inode, fe_bh,
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto out_commit;
@@ -401,12 +404,9 @@ static int ocfs2_truncate_file(struct inode *inode,
                   (unsigned long long)OCFS2_I(inode)->ip_blkno,
                   (unsigned long long)new_i_size);
 
+       /* We trust di_bh because it comes from ocfs2_inode_lock(), which
+        * already validated it */
        fe = (struct ocfs2_dinode *) di_bh->b_data;
-       if (!OCFS2_IS_VALID_DINODE(fe)) {
-               OCFS2_RO_ON_INVALID_DINODE(inode->i_sb, fe);
-               status = -EIO;
-               goto bail;
-       }
 
        mlog_bug_on_msg(le64_to_cpu(fe->i_size) != i_size_read(inode),
                        "Inode %llu, inode i_size = %lld != di "
@@ -536,6 +536,7 @@ static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start,
        enum ocfs2_alloc_restarted why;
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
        struct ocfs2_extent_tree et;
+       int did_quota = 0;
 
        mlog_entry("(clusters_to_add = %u)\n", clusters_to_add);
 
@@ -545,18 +546,12 @@ static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start,
         */
        BUG_ON(mark_unwritten && !ocfs2_sparse_alloc(osb));
 
-       status = ocfs2_read_block(inode, OCFS2_I(inode)->ip_blkno, &bh);
+       status = ocfs2_read_inode_block(inode, &bh);
        if (status < 0) {
                mlog_errno(status);
                goto leave;
        }
-
        fe = (struct ocfs2_dinode *) bh->b_data;
-       if (!OCFS2_IS_VALID_DINODE(fe)) {
-               OCFS2_RO_ON_INVALID_DINODE(inode->i_sb, fe);
-               status = -EIO;
-               goto leave;
-       }
 
 restart_all:
        BUG_ON(le32_to_cpu(fe->i_clusters) != OCFS2_I(inode)->ip_clusters);
@@ -585,11 +580,18 @@ restart_all:
        }
 
 restarted_transaction:
+       if (vfs_dq_alloc_space_nodirty(inode, ocfs2_clusters_to_bytes(osb->sb,
+           clusters_to_add))) {
+               status = -EDQUOT;
+               goto leave;
+       }
+       did_quota = 1;
+
        /* reserve a write to the file entry early on - that we if we
         * run out of credits in the allocation path, we can still
         * update i_size. */
-       status = ocfs2_journal_access(handle, inode, bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_journal_access_di(handle, inode, bh,
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto leave;
@@ -622,6 +624,10 @@ restarted_transaction:
        spin_lock(&OCFS2_I(inode)->ip_lock);
        clusters_to_add -= (OCFS2_I(inode)->ip_clusters - prev_clusters);
        spin_unlock(&OCFS2_I(inode)->ip_lock);
+       /* Release unused quota reservation */
+       vfs_dq_free_space(inode,
+                       ocfs2_clusters_to_bytes(osb->sb, clusters_to_add));
+       did_quota = 0;
 
        if (why != RESTART_NONE && clusters_to_add) {
                if (why == RESTART_META) {
@@ -654,6 +660,9 @@ restarted_transaction:
             OCFS2_I(inode)->ip_clusters, (long long)i_size_read(inode));
 
 leave:
+       if (status < 0 && did_quota)
+               vfs_dq_free_space(inode,
+                       ocfs2_clusters_to_bytes(osb->sb, clusters_to_add));
        if (handle) {
                ocfs2_commit_trans(osb, handle);
                handle = NULL;
@@ -885,6 +894,9 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
        struct ocfs2_super *osb = OCFS2_SB(sb);
        struct buffer_head *bh = NULL;
        handle_t *handle = NULL;
+       int locked[MAXQUOTAS] = {0, 0};
+       int credits, qtype;
+       struct ocfs2_mem_dqinfo *oinfo;
 
        mlog_entry("(0x%p, '%.*s')\n", dentry,
                   dentry->d_name.len, dentry->d_name.name);
@@ -955,11 +967,47 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
                }
        }
 
-       handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
-       if (IS_ERR(handle)) {
-               status = PTR_ERR(handle);
-               mlog_errno(status);
-               goto bail_unlock;
+       if ((attr->ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
+           (attr->ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) {
+               credits = OCFS2_INODE_UPDATE_CREDITS;
+               if (attr->ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid
+                   && OCFS2_HAS_RO_COMPAT_FEATURE(sb,
+                   OCFS2_FEATURE_RO_COMPAT_USRQUOTA)) {
+                       oinfo = sb_dqinfo(sb, USRQUOTA)->dqi_priv;
+                       status = ocfs2_lock_global_qf(oinfo, 1);
+                       if (status < 0)
+                               goto bail_unlock;
+                       credits += ocfs2_calc_qinit_credits(sb, USRQUOTA) +
+                               ocfs2_calc_qdel_credits(sb, USRQUOTA);
+                       locked[USRQUOTA] = 1;
+               }
+               if (attr->ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid
+                   && OCFS2_HAS_RO_COMPAT_FEATURE(sb,
+                   OCFS2_FEATURE_RO_COMPAT_GRPQUOTA)) {
+                       oinfo = sb_dqinfo(sb, GRPQUOTA)->dqi_priv;
+                       status = ocfs2_lock_global_qf(oinfo, 1);
+                       if (status < 0)
+                               goto bail_unlock;
+                       credits += ocfs2_calc_qinit_credits(sb, GRPQUOTA) +
+                                  ocfs2_calc_qdel_credits(sb, GRPQUOTA);
+                       locked[GRPQUOTA] = 1;
+               }
+               handle = ocfs2_start_trans(osb, credits);
+               if (IS_ERR(handle)) {
+                       status = PTR_ERR(handle);
+                       mlog_errno(status);
+                       goto bail_unlock;
+               }
+               status = vfs_dq_transfer(inode, attr) ? -EDQUOT : 0;
+               if (status < 0)
+                       goto bail_commit;
+       } else {
+               handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
+               if (IS_ERR(handle)) {
+                       status = PTR_ERR(handle);
+                       mlog_errno(status);
+                       goto bail_unlock;
+               }
        }
 
        /*
@@ -982,6 +1030,12 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
 bail_commit:
        ocfs2_commit_trans(osb, handle);
 bail_unlock:
+       for (qtype = 0; qtype < MAXQUOTAS; qtype++) {
+               if (!locked[qtype])
+                       continue;
+               oinfo = sb_dqinfo(sb, qtype)->dqi_priv;
+               ocfs2_unlock_global_qf(oinfo, 1);
+       }
        ocfs2_inode_unlock(inode, 1);
 bail_unlock_rw:
        if (size_change)
@@ -989,6 +1043,12 @@ bail_unlock_rw:
 bail:
        brelse(bh);
 
+       if (!status && attr->ia_valid & ATTR_MODE) {
+               status = ocfs2_acl_chmod(inode);
+               if (status < 0)
+                       mlog_errno(status);
+       }
+
        mlog_exit(status);
        return status;
 }
@@ -1035,7 +1095,7 @@ int ocfs2_permission(struct inode *inode, int mask)
                goto out;
        }
 
-       ret = generic_permission(inode, mask, NULL);
+       ret = generic_permission(inode, mask, ocfs2_check_acl);
 
        ocfs2_inode_unlock(inode, 0);
 out:
@@ -1061,8 +1121,8 @@ static int __ocfs2_write_remove_suid(struct inode *inode,
                goto out;
        }
 
-       ret = ocfs2_journal_access(handle, inode, bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = ocfs2_journal_access_di(handle, inode, bh,
+                                     OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret < 0) {
                mlog_errno(ret);
                goto out_trans;
@@ -1128,9 +1188,8 @@ static int ocfs2_write_remove_suid(struct inode *inode)
 {
        int ret;
        struct buffer_head *bh = NULL;
-       struct ocfs2_inode_info *oi = OCFS2_I(inode);
 
-       ret = ocfs2_read_block(inode, oi->ip_blkno, &bh);
+       ret = ocfs2_read_inode_block(inode, &bh);
        if (ret < 0) {
                mlog_errno(ret);
                goto out;
@@ -1156,8 +1215,7 @@ static int ocfs2_allocate_unwritten_extents(struct inode *inode,
        struct buffer_head *di_bh = NULL;
 
        if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) {
-               ret = ocfs2_read_block(inode, OCFS2_I(inode)->ip_blkno,
-                                      &di_bh);
+               ret = ocfs2_read_inode_block(inode, &di_bh);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -1226,83 +1284,6 @@ out:
        return ret;
 }
 
-static int __ocfs2_remove_inode_range(struct inode *inode,
-                                     struct buffer_head *di_bh,
-                                     u32 cpos, u32 phys_cpos, u32 len,
-                                     struct ocfs2_cached_dealloc_ctxt *dealloc)
-{
-       int ret;
-       u64 phys_blkno = ocfs2_clusters_to_blocks(inode->i_sb, phys_cpos);
-       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
-       struct inode *tl_inode = osb->osb_tl_inode;
-       handle_t *handle;
-       struct ocfs2_alloc_context *meta_ac = NULL;
-       struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
-       struct ocfs2_extent_tree et;
-
-       ocfs2_init_dinode_extent_tree(&et, inode, di_bh);
-
-       ret = ocfs2_lock_allocators(inode, &et, 0, 1, NULL, &meta_ac);
-       if (ret) {
-               mlog_errno(ret);
-               return ret;
-       }
-
-       mutex_lock(&tl_inode->i_mutex);
-
-       if (ocfs2_truncate_log_needs_flush(osb)) {
-               ret = __ocfs2_flush_truncate_log(osb);
-               if (ret < 0) {
-                       mlog_errno(ret);
-                       goto out;
-               }
-       }
-
-       handle = ocfs2_start_trans(osb, OCFS2_REMOVE_EXTENT_CREDITS);
-       if (IS_ERR(handle)) {
-               ret = PTR_ERR(handle);
-               mlog_errno(ret);
-               goto out;
-       }
-
-       ret = ocfs2_journal_access(handle, inode, di_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
-       if (ret) {
-               mlog_errno(ret);
-               goto out;
-       }
-
-       ret = ocfs2_remove_extent(inode, &et, cpos, len, handle, meta_ac,
-                                 dealloc);
-       if (ret) {
-               mlog_errno(ret);
-               goto out_commit;
-       }
-
-       OCFS2_I(inode)->ip_clusters -= len;
-       di->i_clusters = cpu_to_le32(OCFS2_I(inode)->ip_clusters);
-
-       ret = ocfs2_journal_dirty(handle, di_bh);
-       if (ret) {
-               mlog_errno(ret);
-               goto out_commit;
-       }
-
-       ret = ocfs2_truncate_log_append(osb, handle, phys_blkno, len);
-       if (ret)
-               mlog_errno(ret);
-
-out_commit:
-       ocfs2_commit_trans(osb, handle);
-out:
-       mutex_unlock(&tl_inode->i_mutex);
-
-       if (meta_ac)
-               ocfs2_free_alloc_context(meta_ac);
-
-       return ret;
-}
-
 /*
  * Truncate a byte range, avoiding pages within partial clusters. This
  * preserves those pages for the zeroing code to write to.
@@ -1402,7 +1383,9 @@ static int ocfs2_remove_inode_range(struct inode *inode,
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
        struct ocfs2_cached_dealloc_ctxt dealloc;
        struct address_space *mapping = inode->i_mapping;
+       struct ocfs2_extent_tree et;
 
+       ocfs2_init_dinode_extent_tree(&et, inode, di_bh);
        ocfs2_init_dealloc_ctxt(&dealloc);
 
        if (byte_len == 0)
@@ -1458,9 +1441,9 @@ static int ocfs2_remove_inode_range(struct inode *inode,
 
                /* Only do work for non-holes */
                if (phys_cpos != 0) {
-                       ret = __ocfs2_remove_inode_range(inode, di_bh, cpos,
-                                                        phys_cpos, alloc_size,
-                                                        &dealloc);
+                       ret = ocfs2_remove_btree_range(inode, &et, cpos,
+                                                      phys_cpos, alloc_size,
+                                                      &dealloc);
                        if (ret) {
                                mlog_errno(ret);
                                goto out;
index e92382cbca5fb94c20b963d465c90853a8ab84de..172f9fbc9fc7c3c35841b2bf0ad85766d2c55c7e 100644 (file)
@@ -51,6 +51,9 @@ int ocfs2_add_inode_data(struct ocfs2_super *osb,
                         struct ocfs2_alloc_context *data_ac,
                         struct ocfs2_alloc_context *meta_ac,
                         enum ocfs2_alloc_restarted *reason_ret);
+int ocfs2_simple_size_update(struct inode *inode,
+                            struct buffer_head *di_bh,
+                            u64 new_i_size);
 int ocfs2_extend_no_holes(struct inode *inode, u64 new_i_size,
                          u64 zero_to);
 int ocfs2_setattr(struct dentry *dentry, struct iattr *attr);
index 7aa00d5118748f392251acf5b76605350eefcd98..229e707bc050629c0ad372b14c75194bf4b97f3d 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/slab.h>
 #include <linux/highmem.h>
 #include <linux/pagemap.h>
+#include <linux/quotaops.h>
 
 #include <asm/byteorder.h>
 
@@ -37,6 +38,7 @@
 #include "ocfs2.h"
 
 #include "alloc.h"
+#include "blockcheck.h"
 #include "dlmglue.h"
 #include "extent_map.h"
 #include "file.h"
@@ -214,12 +216,11 @@ static int ocfs2_init_locked_inode(struct inode *inode, void *opaque)
        return 0;
 }
 
-int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
-                        int create_ino)
+void ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
+                         int create_ino)
 {
        struct super_block *sb;
        struct ocfs2_super *osb;
-       int status = -EINVAL;
        int use_plocks = 1;
 
        mlog_entry("(0x%p, size:%llu)\n", inode,
@@ -232,25 +233,17 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
            ocfs2_mount_local(osb) || !ocfs2_stack_supports_plocks())
                use_plocks = 0;
 
-       /* this means that read_inode cannot create a superblock inode
-        * today.  change if needed. */
-       if (!OCFS2_IS_VALID_DINODE(fe) ||
-           !(fe->i_flags & cpu_to_le32(OCFS2_VALID_FL))) {
-               mlog(0, "Invalid dinode: i_ino=%lu, i_blkno=%llu, "
-                    "signature = %.*s, flags = 0x%x\n",
-                    inode->i_ino,
-                    (unsigned long long)le64_to_cpu(fe->i_blkno), 7,
-                    fe->i_signature, le32_to_cpu(fe->i_flags));
-               goto bail;
-       }
+       /*
+        * These have all been checked by ocfs2_read_inode_block() or set
+        * by ocfs2_mknod_locked(), so a failure is a code bug.
+        */
+       BUG_ON(!OCFS2_IS_VALID_DINODE(fe));  /* This means that read_inode
+                                               cannot create a superblock
+                                               inode today.  change if
+                                               that is needed. */
+       BUG_ON(!(fe->i_flags & cpu_to_le32(OCFS2_VALID_FL)));
+       BUG_ON(le32_to_cpu(fe->i_fs_generation) != osb->fs_generation);
 
-       if (le32_to_cpu(fe->i_fs_generation) != osb->fs_generation) {
-               mlog(ML_ERROR, "file entry generation does not match "
-                    "superblock! osb->fs_generation=%x, "
-                    "fe->i_fs_generation=%x\n",
-                    osb->fs_generation, le32_to_cpu(fe->i_fs_generation));
-               goto bail;
-       }
 
        OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters);
        OCFS2_I(inode)->ip_attr = le32_to_cpu(fe->i_attr);
@@ -284,14 +277,18 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
 
        inode->i_nlink = le16_to_cpu(fe->i_links_count);
 
-       if (fe->i_flags & cpu_to_le32(OCFS2_SYSTEM_FL))
+       if (fe->i_flags & cpu_to_le32(OCFS2_SYSTEM_FL)) {
                OCFS2_I(inode)->ip_flags |= OCFS2_INODE_SYSTEM_FILE;
+               inode->i_flags |= S_NOQUOTA;
+       }
 
        if (fe->i_flags & cpu_to_le32(OCFS2_LOCAL_ALLOC_FL)) {
                OCFS2_I(inode)->ip_flags |= OCFS2_INODE_BITMAP;
                mlog(0, "local alloc inode: i_ino=%lu\n", inode->i_ino);
        } else if (fe->i_flags & cpu_to_le32(OCFS2_BITMAP_FL)) {
                OCFS2_I(inode)->ip_flags |= OCFS2_INODE_BITMAP;
+       } else if (fe->i_flags & cpu_to_le32(OCFS2_QUOTA_FL)) {
+               inode->i_flags |= S_NOQUOTA;
        } else if (fe->i_flags & cpu_to_le32(OCFS2_SUPER_BLOCK_FL)) {
                mlog(0, "superblock inode: i_ino=%lu\n", inode->i_ino);
                /* we can't actually hit this as read_inode can't
@@ -354,10 +351,7 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
 
        ocfs2_set_inode_flags(inode);
 
-       status = 0;
-bail:
-       mlog_exit(status);
-       return status;
+       mlog_exit_void();
 }
 
 static int ocfs2_read_locked_inode(struct inode *inode,
@@ -460,11 +454,14 @@ static int ocfs2_read_locked_inode(struct inode *inode,
                }
        }
 
-       if (can_lock)
-               status = ocfs2_read_blocks(inode, args->fi_blkno, 1, &bh,
-                                          OCFS2_BH_IGNORE_CACHE);
-       else
+       if (can_lock) {
+               status = ocfs2_read_inode_block_full(inode, &bh,
+                                                    OCFS2_BH_IGNORE_CACHE);
+       } else {
                status = ocfs2_read_blocks_sync(osb, args->fi_blkno, 1, &bh);
+               if (!status)
+                       status = ocfs2_validate_inode_block(osb->sb, bh);
+       }
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -472,12 +469,6 @@ static int ocfs2_read_locked_inode(struct inode *inode,
 
        status = -EINVAL;
        fe = (struct ocfs2_dinode *) bh->b_data;
-       if (!OCFS2_IS_VALID_DINODE(fe)) {
-               mlog(0, "Invalid dinode #%llu: signature = %.*s\n",
-                    (unsigned long long)args->fi_blkno, 7,
-                    fe->i_signature);
-               goto bail;
-       }
 
        /*
         * This is a code bug. Right now the caller needs to
@@ -491,10 +482,9 @@ static int ocfs2_read_locked_inode(struct inode *inode,
 
        if (S_ISCHR(le16_to_cpu(fe->i_mode)) ||
            S_ISBLK(le16_to_cpu(fe->i_mode)))
-               inode->i_rdev = huge_decode_dev(le64_to_cpu(fe->id1.dev1.i_rdev));
+               inode->i_rdev = huge_decode_dev(le64_to_cpu(fe->id1.dev1.i_rdev));
 
-       if (ocfs2_populate_inode(inode, fe, 0) < 0)
-               goto bail;
+       ocfs2_populate_inode(inode, fe, 0);
 
        BUG_ON(args->fi_blkno != le64_to_cpu(fe->i_blkno));
 
@@ -547,8 +537,8 @@ static int ocfs2_truncate_for_delete(struct ocfs2_super *osb,
                        goto out;
                }
 
-               status = ocfs2_journal_access(handle, inode, fe_bh,
-                                             OCFS2_JOURNAL_ACCESS_WRITE);
+               status = ocfs2_journal_access_di(handle, inode, fe_bh,
+                                                OCFS2_JOURNAL_ACCESS_WRITE);
                if (status < 0) {
                        mlog_errno(status);
                        goto out;
@@ -615,7 +605,8 @@ static int ocfs2_remove_inode(struct inode *inode,
                goto bail;
        }
 
-       handle = ocfs2_start_trans(osb, OCFS2_DELETE_INODE_CREDITS);
+       handle = ocfs2_start_trans(osb, OCFS2_DELETE_INODE_CREDITS +
+                                       ocfs2_quota_trans_credits(inode->i_sb));
        if (IS_ERR(handle)) {
                status = PTR_ERR(handle);
                mlog_errno(status);
@@ -630,8 +621,8 @@ static int ocfs2_remove_inode(struct inode *inode,
        }
 
        /* set the inodes dtime */
-       status = ocfs2_journal_access(handle, inode, di_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_journal_access_di(handle, inode, di_bh,
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto bail_commit;
@@ -647,6 +638,7 @@ static int ocfs2_remove_inode(struct inode *inode,
        }
 
        ocfs2_remove_from_cache(inode, di_bh);
+       vfs_dq_free_inode(inode);
 
        status = ocfs2_free_dinode(handle, inode_alloc_inode,
                                   inode_alloc_bh, di);
@@ -929,7 +921,10 @@ void ocfs2_delete_inode(struct inode *inode)
 
        mlog_entry("(inode->i_ino = %lu)\n", inode->i_ino);
 
-       if (is_bad_inode(inode)) {
+       /* When we fail in read_inode() we mark inode as bad. The second test
+        * catches the case when inode allocation fails before allocating
+        * a block for inode. */
+       if (is_bad_inode(inode) || !OCFS2_I(inode)->ip_blkno) {
                mlog(0, "Skipping delete of bad inode\n");
                goto bail;
        }
@@ -1195,8 +1190,8 @@ int ocfs2_mark_inode_dirty(handle_t *handle,
        mlog_entry("(inode %llu)\n",
                   (unsigned long long)OCFS2_I(inode)->ip_blkno);
 
-       status = ocfs2_journal_access(handle, inode, bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_journal_access_di(handle, inode, bh,
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto leave;
@@ -1264,3 +1259,89 @@ void ocfs2_refresh_inode(struct inode *inode,
 
        spin_unlock(&OCFS2_I(inode)->ip_lock);
 }
+
+int ocfs2_validate_inode_block(struct super_block *sb,
+                              struct buffer_head *bh)
+{
+       int rc;
+       struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data;
+
+       mlog(0, "Validating dinode %llu\n",
+            (unsigned long long)bh->b_blocknr);
+
+       BUG_ON(!buffer_uptodate(bh));
+
+       /*
+        * If the ecc fails, we return the error but otherwise
+        * leave the filesystem running.  We know any error is
+        * local to this block.
+        */
+       rc = ocfs2_validate_meta_ecc(sb, bh->b_data, &di->i_check);
+       if (rc) {
+               mlog(ML_ERROR, "Checksum failed for dinode %llu\n",
+                    (unsigned long long)bh->b_blocknr);
+               goto bail;
+       }
+
+       /*
+        * Errors after here are fatal.
+        */
+
+       rc = -EINVAL;
+
+       if (!OCFS2_IS_VALID_DINODE(di)) {
+               ocfs2_error(sb, "Invalid dinode #%llu: signature = %.*s\n",
+                           (unsigned long long)bh->b_blocknr, 7,
+                           di->i_signature);
+               goto bail;
+       }
+
+       if (le64_to_cpu(di->i_blkno) != bh->b_blocknr) {
+               ocfs2_error(sb, "Invalid dinode #%llu: i_blkno is %llu\n",
+                           (unsigned long long)bh->b_blocknr,
+                           (unsigned long long)le64_to_cpu(di->i_blkno));
+               goto bail;
+       }
+
+       if (!(di->i_flags & cpu_to_le32(OCFS2_VALID_FL))) {
+               ocfs2_error(sb,
+                           "Invalid dinode #%llu: OCFS2_VALID_FL not set\n",
+                           (unsigned long long)bh->b_blocknr);
+               goto bail;
+       }
+
+       if (le32_to_cpu(di->i_fs_generation) !=
+           OCFS2_SB(sb)->fs_generation) {
+               ocfs2_error(sb,
+                           "Invalid dinode #%llu: fs_generation is %u\n",
+                           (unsigned long long)bh->b_blocknr,
+                           le32_to_cpu(di->i_fs_generation));
+               goto bail;
+       }
+
+       rc = 0;
+
+bail:
+       return rc;
+}
+
+int ocfs2_read_inode_block_full(struct inode *inode, struct buffer_head **bh,
+                               int flags)
+{
+       int rc;
+       struct buffer_head *tmp = *bh;
+
+       rc = ocfs2_read_blocks(inode, OCFS2_I(inode)->ip_blkno, 1, &tmp,
+                              flags, ocfs2_validate_inode_block);
+
+       /* If ocfs2_read_blocks() got us a new bh, pass it up. */
+       if (!rc && !*bh)
+               *bh = tmp;
+
+       return rc;
+}
+
+int ocfs2_read_inode_block(struct inode *inode, struct buffer_head **bh)
+{
+       return ocfs2_read_inode_block_full(inode, bh, 0);
+}
index 2f37af9bcc4aa262197ca0f3108941c4d7d551fb..eb3c302b38d34c15d96057ff4484e22ba9574999 100644 (file)
@@ -128,8 +128,8 @@ struct inode *ocfs2_iget(struct ocfs2_super *osb, u64 feoff, unsigned flags,
                         int sysfile_type);
 int ocfs2_inode_init_private(struct inode *inode);
 int ocfs2_inode_revalidate(struct dentry *dentry);
-int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
-                        int create_ino);
+void ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
+                         int create_ino);
 void ocfs2_read_inode(struct inode *inode);
 void ocfs2_read_inode2(struct inode *inode, void *opaque);
 ssize_t ocfs2_rw_direct(int rw, struct file *filp, char *buf,
@@ -142,6 +142,8 @@ int ocfs2_mark_inode_dirty(handle_t *handle,
                           struct buffer_head *bh);
 int ocfs2_aio_read(struct file *file, struct kiocb *req, struct iocb *iocb);
 int ocfs2_aio_write(struct file *file, struct kiocb *req, struct iocb *iocb);
+struct buffer_head *ocfs2_bread(struct inode *inode,
+                               int block, int *err, int reada);
 
 void ocfs2_set_inode_flags(struct inode *inode);
 void ocfs2_get_inode_flags(struct ocfs2_inode_info *oi);
@@ -153,4 +155,16 @@ static inline blkcnt_t ocfs2_inode_sector_count(struct inode *inode)
        return (blkcnt_t)(OCFS2_I(inode)->ip_clusters << c_to_s_bits);
 }
 
+/* Validate that a bh contains a valid inode */
+int ocfs2_validate_inode_block(struct super_block *sb,
+                              struct buffer_head *bh);
+/*
+ * Read an inode block into *bh.  If *bh is NULL, a bh will be allocated.
+ * This is a cached read.  The inode will be validated with
+ * ocfs2_validate_inode_block().
+ */
+int ocfs2_read_inode_block(struct inode *inode, struct buffer_head **bh);
+/* The same, but can be passed OCFS2_BH_* flags */
+int ocfs2_read_inode_block_full(struct inode *inode, struct buffer_head **bh,
+                               int flags);
 #endif /* OCFS2_INODE_H */
index 99fe9d584f3c25843ab1caefcce175f2ccdbb60c..57d7d25a2b9a3b9e0a68c7bf8f1348832e69cb25 100644 (file)
@@ -35,6 +35,7 @@
 #include "ocfs2.h"
 
 #include "alloc.h"
+#include "blockcheck.h"
 #include "dir.h"
 #include "dlmglue.h"
 #include "extent_map.h"
@@ -45,6 +46,7 @@
 #include "slot_map.h"
 #include "super.h"
 #include "sysfile.h"
+#include "quota.h"
 
 #include "buffer_head_io.h"
 
@@ -52,10 +54,10 @@ DEFINE_SPINLOCK(trans_inc_lock);
 
 static int ocfs2_force_read_journal(struct inode *inode);
 static int ocfs2_recover_node(struct ocfs2_super *osb,
-                             int node_num);
+                             int node_num, int slot_num);
 static int __ocfs2_recovery_thread(void *arg);
 static int ocfs2_commit_cache(struct ocfs2_super *osb);
-static int ocfs2_wait_on_mount(struct ocfs2_super *osb);
+static int __ocfs2_wait_on_mount(struct ocfs2_super *osb, int quota);
 static int ocfs2_journal_toggle_dirty(struct ocfs2_super *osb,
                                      int dirty, int replayed);
 static int ocfs2_trylock_journal(struct ocfs2_super *osb,
@@ -64,6 +66,17 @@ static int ocfs2_recover_orphans(struct ocfs2_super *osb,
                                 int slot);
 static int ocfs2_commit_thread(void *arg);
 
+static inline int ocfs2_wait_on_mount(struct ocfs2_super *osb)
+{
+       return __ocfs2_wait_on_mount(osb, 0);
+}
+
+static inline int ocfs2_wait_on_quotas(struct ocfs2_super *osb)
+{
+       return __ocfs2_wait_on_mount(osb, 1);
+}
+
+
 
 /*
  * The recovery_list is a simple linked list of node numbers to recover.
@@ -256,11 +269,9 @@ handle_t *ocfs2_start_trans(struct ocfs2_super *osb, int max_buffs)
        BUG_ON(osb->journal->j_state == OCFS2_JOURNAL_FREE);
        BUG_ON(max_buffs <= 0);
 
-       /* JBD might support this, but our journalling code doesn't yet. */
-       if (journal_current_handle()) {
-               mlog(ML_ERROR, "Recursive transaction attempted!\n");
-               BUG();
-       }
+       /* Nested transaction? Just return the handle... */
+       if (journal_current_handle())
+               return jbd2_journal_start(journal, max_buffs);
 
        down_read(&osb->journal->j_trans_barrier);
 
@@ -285,16 +296,18 @@ handle_t *ocfs2_start_trans(struct ocfs2_super *osb, int max_buffs)
 int ocfs2_commit_trans(struct ocfs2_super *osb,
                       handle_t *handle)
 {
-       int ret;
+       int ret, nested;
        struct ocfs2_journal *journal = osb->journal;
 
        BUG_ON(!handle);
 
+       nested = handle->h_ref > 1;
        ret = jbd2_journal_stop(handle);
        if (ret < 0)
                mlog_errno(ret);
 
-       up_read(&journal->j_trans_barrier);
+       if (!nested)
+               up_read(&journal->j_trans_barrier);
 
        return ret;
 }
@@ -357,10 +370,137 @@ bail:
        return status;
 }
 
-int ocfs2_journal_access(handle_t *handle,
-                        struct inode *inode,
-                        struct buffer_head *bh,
-                        int type)
+struct ocfs2_triggers {
+       struct jbd2_buffer_trigger_type ot_triggers;
+       int                             ot_offset;
+};
+
+static inline struct ocfs2_triggers *to_ocfs2_trigger(struct jbd2_buffer_trigger_type *triggers)
+{
+       return container_of(triggers, struct ocfs2_triggers, ot_triggers);
+}
+
+static void ocfs2_commit_trigger(struct jbd2_buffer_trigger_type *triggers,
+                                struct buffer_head *bh,
+                                void *data, size_t size)
+{
+       struct ocfs2_triggers *ot = to_ocfs2_trigger(triggers);
+
+       /*
+        * We aren't guaranteed to have the superblock here, so we
+        * must unconditionally compute the ecc data.
+        * __ocfs2_journal_access() will only set the triggers if
+        * metaecc is enabled.
+        */
+       ocfs2_block_check_compute(data, size, data + ot->ot_offset);
+}
+
+/*
+ * Quota blocks have their own trigger because the struct ocfs2_block_check
+ * offset depends on the blocksize.
+ */
+static void ocfs2_dq_commit_trigger(struct jbd2_buffer_trigger_type *triggers,
+                                struct buffer_head *bh,
+                                void *data, size_t size)
+{
+       struct ocfs2_disk_dqtrailer *dqt =
+               ocfs2_block_dqtrailer(size, data);
+
+       /*
+        * We aren't guaranteed to have the superblock here, so we
+        * must unconditionally compute the ecc data.
+        * __ocfs2_journal_access() will only set the triggers if
+        * metaecc is enabled.
+        */
+       ocfs2_block_check_compute(data, size, &dqt->dq_check);
+}
+
+/*
+ * Directory blocks also have their own trigger because the
+ * struct ocfs2_block_check offset depends on the blocksize.
+ */
+static void ocfs2_db_commit_trigger(struct jbd2_buffer_trigger_type *triggers,
+                                struct buffer_head *bh,
+                                void *data, size_t size)
+{
+       struct ocfs2_dir_block_trailer *trailer =
+               ocfs2_dir_trailer_from_size(size, data);
+
+       /*
+        * We aren't guaranteed to have the superblock here, so we
+        * must unconditionally compute the ecc data.
+        * __ocfs2_journal_access() will only set the triggers if
+        * metaecc is enabled.
+        */
+       ocfs2_block_check_compute(data, size, &trailer->db_check);
+}
+
+static void ocfs2_abort_trigger(struct jbd2_buffer_trigger_type *triggers,
+                               struct buffer_head *bh)
+{
+       mlog(ML_ERROR,
+            "ocfs2_abort_trigger called by JBD2.  bh = 0x%lx, "
+            "bh->b_blocknr = %llu\n",
+            (unsigned long)bh,
+            (unsigned long long)bh->b_blocknr);
+
+       /* We aren't guaranteed to have the superblock here - but if we
+        * don't, it'll just crash. */
+       ocfs2_error(bh->b_assoc_map->host->i_sb,
+                   "JBD2 has aborted our journal, ocfs2 cannot continue\n");
+}
+
+static struct ocfs2_triggers di_triggers = {
+       .ot_triggers = {
+               .t_commit = ocfs2_commit_trigger,
+               .t_abort = ocfs2_abort_trigger,
+       },
+       .ot_offset      = offsetof(struct ocfs2_dinode, i_check),
+};
+
+static struct ocfs2_triggers eb_triggers = {
+       .ot_triggers = {
+               .t_commit = ocfs2_commit_trigger,
+               .t_abort = ocfs2_abort_trigger,
+       },
+       .ot_offset      = offsetof(struct ocfs2_extent_block, h_check),
+};
+
+static struct ocfs2_triggers gd_triggers = {
+       .ot_triggers = {
+               .t_commit = ocfs2_commit_trigger,
+               .t_abort = ocfs2_abort_trigger,
+       },
+       .ot_offset      = offsetof(struct ocfs2_group_desc, bg_check),
+};
+
+static struct ocfs2_triggers db_triggers = {
+       .ot_triggers = {
+               .t_commit = ocfs2_db_commit_trigger,
+               .t_abort = ocfs2_abort_trigger,
+       },
+};
+
+static struct ocfs2_triggers xb_triggers = {
+       .ot_triggers = {
+               .t_commit = ocfs2_commit_trigger,
+               .t_abort = ocfs2_abort_trigger,
+       },
+       .ot_offset      = offsetof(struct ocfs2_xattr_block, xb_check),
+};
+
+static struct ocfs2_triggers dq_triggers = {
+       .ot_triggers = {
+               .t_commit = ocfs2_dq_commit_trigger,
+               .t_abort = ocfs2_abort_trigger,
+       },
+};
+
+static int __ocfs2_journal_access(handle_t *handle,
+                                 struct inode *inode,
+                                 struct buffer_head *bh,
+                                 struct ocfs2_triggers *triggers,
+                                 int type)
 {
        int status;
 
@@ -406,6 +546,8 @@ int ocfs2_journal_access(handle_t *handle,
                status = -EINVAL;
                mlog(ML_ERROR, "Uknown access type!\n");
        }
+       if (!status && ocfs2_meta_ecc(OCFS2_SB(inode->i_sb)) && triggers)
+               jbd2_journal_set_triggers(bh, &triggers->ot_triggers);
        mutex_unlock(&OCFS2_I(inode)->ip_io_mutex);
 
        if (status < 0)
@@ -416,6 +558,54 @@ int ocfs2_journal_access(handle_t *handle,
        return status;
 }
 
+int ocfs2_journal_access_di(handle_t *handle, struct inode *inode,
+                              struct buffer_head *bh, int type)
+{
+       return __ocfs2_journal_access(handle, inode, bh, &di_triggers,
+                                     type);
+}
+
+int ocfs2_journal_access_eb(handle_t *handle, struct inode *inode,
+                           struct buffer_head *bh, int type)
+{
+       return __ocfs2_journal_access(handle, inode, bh, &eb_triggers,
+                                     type);
+}
+
+int ocfs2_journal_access_gd(handle_t *handle, struct inode *inode,
+                           struct buffer_head *bh, int type)
+{
+       return __ocfs2_journal_access(handle, inode, bh, &gd_triggers,
+                                     type);
+}
+
+int ocfs2_journal_access_db(handle_t *handle, struct inode *inode,
+                           struct buffer_head *bh, int type)
+{
+       return __ocfs2_journal_access(handle, inode, bh, &db_triggers,
+                                     type);
+}
+
+int ocfs2_journal_access_xb(handle_t *handle, struct inode *inode,
+                           struct buffer_head *bh, int type)
+{
+       return __ocfs2_journal_access(handle, inode, bh, &xb_triggers,
+                                     type);
+}
+
+int ocfs2_journal_access_dq(handle_t *handle, struct inode *inode,
+                           struct buffer_head *bh, int type)
+{
+       return __ocfs2_journal_access(handle, inode, bh, &dq_triggers,
+                                     type);
+}
+
+int ocfs2_journal_access(handle_t *handle, struct inode *inode,
+                        struct buffer_head *bh, int type)
+{
+       return __ocfs2_journal_access(handle, inode, bh, NULL, type);
+}
+
 int ocfs2_journal_dirty(handle_t *handle,
                        struct buffer_head *bh)
 {
@@ -434,20 +624,6 @@ int ocfs2_journal_dirty(handle_t *handle,
        return status;
 }
 
-#ifdef CONFIG_OCFS2_COMPAT_JBD
-int ocfs2_journal_dirty_data(handle_t *handle,
-                            struct buffer_head *bh)
-{
-       int err = journal_dirty_data(handle, bh);
-       if (err)
-               mlog_errno(err);
-       /* TODO: When we can handle it, abort the handle and go RO on
-        * error here. */
-
-       return err;
-}
-#endif
-
 #define OCFS2_DEFAULT_COMMIT_INTERVAL  (HZ * JBD2_DEFAULT_MAX_COMMIT_AGE)
 
 void ocfs2_set_journal_params(struct ocfs2_super *osb)
@@ -587,17 +763,11 @@ static int ocfs2_journal_toggle_dirty(struct ocfs2_super *osb,
        mlog_entry_void();
 
        fe = (struct ocfs2_dinode *)bh->b_data;
-       if (!OCFS2_IS_VALID_DINODE(fe)) {
-               /* This is called from startup/shutdown which will
-                * handle the errors in a specific manner, so no need
-                * to call ocfs2_error() here. */
-               mlog(ML_ERROR, "Journal dinode %llu  has invalid "
-                    "signature: %.*s",
-                    (unsigned long long)le64_to_cpu(fe->i_blkno), 7,
-                    fe->i_signature);
-               status = -EIO;
-               goto out;
-       }
+
+       /* The journal bh on the osb always comes from ocfs2_journal_init()
+        * and was validated there inside ocfs2_inode_lock_full().  It's a
+        * code bug if we mess it up. */
+       BUG_ON(!OCFS2_IS_VALID_DINODE(fe));
 
        flags = le32_to_cpu(fe->id1.journal1.ij_flags);
        if (dirty)
@@ -609,11 +779,11 @@ static int ocfs2_journal_toggle_dirty(struct ocfs2_super *osb,
        if (replayed)
                ocfs2_bump_recovery_generation(fe);
 
+       ocfs2_compute_meta_ecc(osb->sb, bh->b_data, &fe->i_check);
        status = ocfs2_write_block(osb, bh, journal->j_inode);
        if (status < 0)
                mlog_errno(status);
 
-out:
        mlog_exit(status);
        return status;
 }
@@ -878,6 +1048,7 @@ struct ocfs2_la_recovery_item {
        int                     lri_slot;
        struct ocfs2_dinode     *lri_la_dinode;
        struct ocfs2_dinode     *lri_tl_dinode;
+       struct ocfs2_quota_recovery *lri_qrec;
 };
 
 /* Does the second half of the recovery process. By this point, the
@@ -898,6 +1069,7 @@ void ocfs2_complete_recovery(struct work_struct *work)
        struct ocfs2_super *osb = journal->j_osb;
        struct ocfs2_dinode *la_dinode, *tl_dinode;
        struct ocfs2_la_recovery_item *item, *n;
+       struct ocfs2_quota_recovery *qrec;
        LIST_HEAD(tmp_la_list);
 
        mlog_entry_void();
@@ -913,6 +1085,8 @@ void ocfs2_complete_recovery(struct work_struct *work)
 
                mlog(0, "Complete recovery for slot %d\n", item->lri_slot);
 
+               ocfs2_wait_on_quotas(osb);
+
                la_dinode = item->lri_la_dinode;
                if (la_dinode) {
                        mlog(0, "Clean up local alloc %llu\n",
@@ -943,6 +1117,16 @@ void ocfs2_complete_recovery(struct work_struct *work)
                if (ret < 0)
                        mlog_errno(ret);
 
+               qrec = item->lri_qrec;
+               if (qrec) {
+                       mlog(0, "Recovering quota files");
+                       ret = ocfs2_finish_quota_recovery(osb, qrec,
+                                                         item->lri_slot);
+                       if (ret < 0)
+                               mlog_errno(ret);
+                       /* Recovery info is already freed now */
+               }
+
                kfree(item);
        }
 
@@ -956,7 +1140,8 @@ void ocfs2_complete_recovery(struct work_struct *work)
 static void ocfs2_queue_recovery_completion(struct ocfs2_journal *journal,
                                            int slot_num,
                                            struct ocfs2_dinode *la_dinode,
-                                           struct ocfs2_dinode *tl_dinode)
+                                           struct ocfs2_dinode *tl_dinode,
+                                           struct ocfs2_quota_recovery *qrec)
 {
        struct ocfs2_la_recovery_item *item;
 
@@ -971,6 +1156,9 @@ static void ocfs2_queue_recovery_completion(struct ocfs2_journal *journal,
                if (tl_dinode)
                        kfree(tl_dinode);
 
+               if (qrec)
+                       ocfs2_free_quota_recovery(qrec);
+
                mlog_errno(-ENOMEM);
                return;
        }
@@ -979,6 +1167,7 @@ static void ocfs2_queue_recovery_completion(struct ocfs2_journal *journal,
        item->lri_la_dinode = la_dinode;
        item->lri_slot = slot_num;
        item->lri_tl_dinode = tl_dinode;
+       item->lri_qrec = qrec;
 
        spin_lock(&journal->j_lock);
        list_add_tail(&item->lri_list, &journal->j_la_cleanups);
@@ -998,6 +1187,7 @@ void ocfs2_complete_mount_recovery(struct ocfs2_super *osb)
                ocfs2_queue_recovery_completion(journal,
                                                osb->slot_num,
                                                osb->local_alloc_copy,
+                                               NULL,
                                                NULL);
                ocfs2_schedule_truncate_log_flush(osb, 0);
 
@@ -1006,11 +1196,26 @@ void ocfs2_complete_mount_recovery(struct ocfs2_super *osb)
        }
 }
 
+void ocfs2_complete_quota_recovery(struct ocfs2_super *osb)
+{
+       if (osb->quota_rec) {
+               ocfs2_queue_recovery_completion(osb->journal,
+                                               osb->slot_num,
+                                               NULL,
+                                               NULL,
+                                               osb->quota_rec);
+               osb->quota_rec = NULL;
+       }
+}
+
 static int __ocfs2_recovery_thread(void *arg)
 {
-       int status, node_num;
+       int status, node_num, slot_num;
        struct ocfs2_super *osb = arg;
        struct ocfs2_recovery_map *rm = osb->recovery_map;
+       int *rm_quota = NULL;
+       int rm_quota_used = 0, i;
+       struct ocfs2_quota_recovery *qrec;
 
        mlog_entry_void();
 
@@ -1019,6 +1224,11 @@ static int __ocfs2_recovery_thread(void *arg)
                goto bail;
        }
 
+       rm_quota = kzalloc(osb->max_slots * sizeof(int), GFP_NOFS);
+       if (!rm_quota) {
+               status = -ENOMEM;
+               goto bail;
+       }
 restart:
        status = ocfs2_super_lock(osb, 1);
        if (status < 0) {
@@ -1032,8 +1242,28 @@ restart:
                 * clear it until ocfs2_recover_node() has succeeded. */
                node_num = rm->rm_entries[0];
                spin_unlock(&osb->osb_lock);
-
-               status = ocfs2_recover_node(osb, node_num);
+               mlog(0, "checking node %d\n", node_num);
+               slot_num = ocfs2_node_num_to_slot(osb, node_num);
+               if (slot_num == -ENOENT) {
+                       status = 0;
+                       mlog(0, "no slot for this node, so no recovery"
+                            "required.\n");
+                       goto skip_recovery;
+               }
+               mlog(0, "node %d was using slot %d\n", node_num, slot_num);
+
+               /* It is a bit subtle with quota recovery. We cannot do it
+                * immediately because we have to obtain cluster locks from
+                * quota files and we also don't want to just skip it because
+                * then quota usage would be out of sync until some node takes
+                * the slot. So we remember which nodes need quota recovery
+                * and when everything else is done, we recover quotas. */
+               for (i = 0; i < rm_quota_used && rm_quota[i] != slot_num; i++);
+               if (i == rm_quota_used)
+                       rm_quota[rm_quota_used++] = slot_num;
+
+               status = ocfs2_recover_node(osb, node_num, slot_num);
+skip_recovery:
                if (!status) {
                        ocfs2_recovery_map_clear(osb, node_num);
                } else {
@@ -1055,13 +1285,27 @@ restart:
        if (status < 0)
                mlog_errno(status);
 
+       /* Now it is right time to recover quotas... We have to do this under
+        * superblock lock so that noone can start using the slot (and crash)
+        * before we recover it */
+       for (i = 0; i < rm_quota_used; i++) {
+               qrec = ocfs2_begin_quota_recovery(osb, rm_quota[i]);
+               if (IS_ERR(qrec)) {
+                       status = PTR_ERR(qrec);
+                       mlog_errno(status);
+                       continue;
+               }
+               ocfs2_queue_recovery_completion(osb->journal, rm_quota[i],
+                                               NULL, NULL, qrec);
+       }
+
        ocfs2_super_unlock(osb, 1);
 
        /* We always run recovery on our own orphan dir - the dead
         * node(s) may have disallowd a previos inode delete. Re-processing
         * is therefore required. */
        ocfs2_queue_recovery_completion(osb->journal, osb->slot_num, NULL,
-                                       NULL);
+                                       NULL, NULL);
 
 bail:
        mutex_lock(&osb->recovery_lock);
@@ -1076,6 +1320,9 @@ bail:
 
        mutex_unlock(&osb->recovery_lock);
 
+       if (rm_quota)
+               kfree(rm_quota);
+
        mlog_exit(status);
        /* no one is callint kthread_stop() for us so the kthread() api
         * requires that we call do_exit().  And it isn't exported, but
@@ -1135,8 +1382,7 @@ static int ocfs2_read_journal_inode(struct ocfs2_super *osb,
        }
        SET_INODE_JOURNAL(inode);
 
-       status = ocfs2_read_blocks(inode, OCFS2_I(inode)->ip_blkno, 1, bh,
-                                  OCFS2_BH_IGNORE_CACHE);
+       status = ocfs2_read_inode_block_full(inode, bh, OCFS2_BH_IGNORE_CACHE);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -1268,6 +1514,7 @@ static int ocfs2_replay_journal(struct ocfs2_super *osb,
        osb->slot_recovery_generations[slot_num] =
                                        ocfs2_get_recovery_generation(fe);
 
+       ocfs2_compute_meta_ecc(osb->sb, bh->b_data, &fe->i_check);
        status = ocfs2_write_block(osb, bh, inode);
        if (status < 0)
                mlog_errno(status);
@@ -1304,31 +1551,19 @@ done:
  * far less concerning.
  */
 static int ocfs2_recover_node(struct ocfs2_super *osb,
-                             int node_num)
+                             int node_num, int slot_num)
 {
        int status = 0;
-       int slot_num;
        struct ocfs2_dinode *la_copy = NULL;
        struct ocfs2_dinode *tl_copy = NULL;
 
-       mlog_entry("(node_num=%d, osb->node_num = %d)\n",
-                  node_num, osb->node_num);
-
-       mlog(0, "checking node %d\n", node_num);
+       mlog_entry("(node_num=%d, slot_num=%d, osb->node_num = %d)\n",
+                  node_num, slot_num, osb->node_num);
 
        /* Should not ever be called to recover ourselves -- in that
         * case we should've called ocfs2_journal_load instead. */
        BUG_ON(osb->node_num == node_num);
 
-       slot_num = ocfs2_node_num_to_slot(osb, node_num);
-       if (slot_num == -ENOENT) {
-               status = 0;
-               mlog(0, "no slot for this node, so no recovery required.\n");
-               goto done;
-       }
-
-       mlog(0, "node %d was using slot %d\n", node_num, slot_num);
-
        status = ocfs2_replay_journal(osb, node_num, slot_num);
        if (status < 0) {
                if (status == -EBUSY) {
@@ -1364,7 +1599,7 @@ static int ocfs2_recover_node(struct ocfs2_super *osb,
 
        /* This will kfree the memory pointed to by la_copy and tl_copy */
        ocfs2_queue_recovery_completion(osb->journal, slot_num, la_copy,
-                                       tl_copy);
+                                       tl_copy, NULL);
 
        status = 0;
 done:
@@ -1659,13 +1894,14 @@ static int ocfs2_recover_orphans(struct ocfs2_super *osb,
        return ret;
 }
 
-static int ocfs2_wait_on_mount(struct ocfs2_super *osb)
+static int __ocfs2_wait_on_mount(struct ocfs2_super *osb, int quota)
 {
        /* This check is good because ocfs2 will wait on our recovery
         * thread before changing it to something other than MOUNTED
         * or DISABLED. */
        wait_event(osb->osb_mount_event,
-                  atomic_read(&osb->vol_state) == VOLUME_MOUNTED ||
+                 (!quota && atomic_read(&osb->vol_state) == VOLUME_MOUNTED) ||
+                  atomic_read(&osb->vol_state) == VOLUME_MOUNTED_QUOTAS ||
                   atomic_read(&osb->vol_state) == VOLUME_DISABLED);
 
        /* If there's an error on mount, then we may never get to the
index d4d14e9a3cea123718e9314c469d6c011a5884ca..3c3532e1307c838495b60e52d9eb9eada0ab69fd 100644 (file)
 #define OCFS2_JOURNAL_H
 
 #include <linux/fs.h>
-#ifndef CONFIG_OCFS2_COMPAT_JBD
-# include <linux/jbd2.h>
-#else
-# include <linux/jbd.h>
-# include "ocfs2_jbd_compat.h"
-#endif
+#include <linux/jbd2.h>
 
 enum ocfs2_journal_state {
        OCFS2_JOURNAL_FREE = 0,
@@ -173,6 +168,7 @@ void   ocfs2_recovery_thread(struct ocfs2_super *osb,
                             int node_num);
 int    ocfs2_mark_dead_nodes(struct ocfs2_super *osb);
 void   ocfs2_complete_mount_recovery(struct ocfs2_super *osb);
+void ocfs2_complete_quota_recovery(struct ocfs2_super *osb);
 
 static inline void ocfs2_start_checkpoint(struct ocfs2_super *osb)
 {
@@ -216,9 +212,12 @@ static inline void ocfs2_checkpoint_inode(struct inode *inode)
  *  ocfs2_extend_trans     - Extend a handle by nblocks credits. This may
  *                          commit the handle to disk in the process, but will
  *                          not release any locks taken during the transaction.
- *  ocfs2_journal_access   - Notify the handle that we want to journal this
+ *  ocfs2_journal_access* - Notify the handle that we want to journal this
  *                          buffer. Will have to call ocfs2_journal_dirty once
  *                          we've actually dirtied it. Type is one of . or .
+ *                          Always call the specific flavor of
+ *                          ocfs2_journal_access_*() unless you intend to
+ *                          manage the checksum by hand.
  *  ocfs2_journal_dirty    - Mark a journalled buffer as having dirty data.
  *  ocfs2_jbd2_file_inode  - Mark an inode so that its data goes out before
  *                           the current handle commits.
@@ -248,10 +247,29 @@ int                            ocfs2_extend_trans(handle_t *handle, int nblocks);
 #define OCFS2_JOURNAL_ACCESS_WRITE  1
 #define OCFS2_JOURNAL_ACCESS_UNDO   2
 
-int                  ocfs2_journal_access(handle_t *handle,
-                                         struct inode *inode,
-                                         struct buffer_head *bh,
-                                         int type);
+
+/* ocfs2_inode */
+int ocfs2_journal_access_di(handle_t *handle, struct inode *inode,
+                           struct buffer_head *bh, int type);
+/* ocfs2_extent_block */
+int ocfs2_journal_access_eb(handle_t *handle, struct inode *inode,
+                           struct buffer_head *bh, int type);
+/* ocfs2_group_desc */
+int ocfs2_journal_access_gd(handle_t *handle, struct inode *inode,
+                           struct buffer_head *bh, int type);
+/* ocfs2_xattr_block */
+int ocfs2_journal_access_xb(handle_t *handle, struct inode *inode,
+                           struct buffer_head *bh, int type);
+/* quota blocks */
+int ocfs2_journal_access_dq(handle_t *handle, struct inode *inode,
+                           struct buffer_head *bh, int type);
+/* dirblock */
+int ocfs2_journal_access_db(handle_t *handle, struct inode *inode,
+                           struct buffer_head *bh, int type);
+/* Anything that has no ecc */
+int ocfs2_journal_access(handle_t *handle, struct inode *inode,
+                        struct buffer_head *bh, int type);
+
 /*
  * A word about the journal_access/journal_dirty "dance". It is
  * entirely legal to journal_access a buffer more than once (as long
@@ -273,10 +291,6 @@ int                  ocfs2_journal_access(handle_t *handle,
  */
 int                  ocfs2_journal_dirty(handle_t *handle,
                                         struct buffer_head *bh);
-#ifdef CONFIG_OCFS2_COMPAT_JBD
-int                  ocfs2_journal_dirty_data(handle_t *handle,
-                                             struct buffer_head *bh);
-#endif
 
 /*
  *  Credit Macros:
@@ -293,6 +307,37 @@ int                  ocfs2_journal_dirty_data(handle_t *handle,
 /* extended attribute block update */
 #define OCFS2_XATTR_BLOCK_UPDATE_CREDITS 1
 
+/* global quotafile inode update, data block */
+#define OCFS2_QINFO_WRITE_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 1)
+
+/*
+ * The two writes below can accidentally see global info dirty due
+ * to set_info() quotactl so make them prepared for the writes.
+ */
+/* quota data block, global info */
+/* Write to local quota file */
+#define OCFS2_QWRITE_CREDITS (OCFS2_QINFO_WRITE_CREDITS + 1)
+
+/* global quota data block, local quota data block, global quota inode,
+ * global quota info */
+#define OCFS2_QSYNC_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 3)
+
+static inline int ocfs2_quota_trans_credits(struct super_block *sb)
+{
+       int credits = 0;
+
+       if (OCFS2_HAS_RO_COMPAT_FEATURE(sb, OCFS2_FEATURE_RO_COMPAT_USRQUOTA))
+               credits += OCFS2_QWRITE_CREDITS;
+       if (OCFS2_HAS_RO_COMPAT_FEATURE(sb, OCFS2_FEATURE_RO_COMPAT_GRPQUOTA))
+               credits += OCFS2_QWRITE_CREDITS;
+       return credits;
+}
+
+/* Number of credits needed for removing quota structure from file */
+int ocfs2_calc_qdel_credits(struct super_block *sb, int type);
+/* Number of credits needed for initialization of new quota structure */
+int ocfs2_calc_qinit_credits(struct super_block *sb, int type);
+
 /* group extend. inode update and last group update. */
 #define OCFS2_GROUP_EXTEND_CREDITS     (OCFS2_INODE_UPDATE_CREDITS + 1)
 
@@ -303,8 +348,11 @@ int                  ocfs2_journal_dirty_data(handle_t *handle,
  * prev. group desc. if we relink. */
 #define OCFS2_SUBALLOC_ALLOC (3)
 
-#define OCFS2_INLINE_TO_EXTENTS_CREDITS (OCFS2_SUBALLOC_ALLOC          \
-                                        + OCFS2_INODE_UPDATE_CREDITS)
+static inline int ocfs2_inline_to_extents_credits(struct super_block *sb)
+{
+       return OCFS2_SUBALLOC_ALLOC + OCFS2_INODE_UPDATE_CREDITS +
+              ocfs2_quota_trans_credits(sb);
+}
 
 /* dinode + group descriptor update. We don't relink on free yet. */
 #define OCFS2_SUBALLOC_FREE  (2)
@@ -313,16 +361,23 @@ int                  ocfs2_journal_dirty_data(handle_t *handle,
 #define OCFS2_TRUNCATE_LOG_FLUSH_ONE_REC (OCFS2_SUBALLOC_FREE                \
                                         + OCFS2_TRUNCATE_LOG_UPDATE)
 
-#define OCFS2_REMOVE_EXTENT_CREDITS (OCFS2_TRUNCATE_LOG_UPDATE + OCFS2_INODE_UPDATE_CREDITS)
+static inline int ocfs2_remove_extent_credits(struct super_block *sb)
+{
+       return OCFS2_TRUNCATE_LOG_UPDATE + OCFS2_INODE_UPDATE_CREDITS +
+              ocfs2_quota_trans_credits(sb);
+}
 
 /* data block for new dir/symlink, 2 for bitmap updates (bitmap fe +
  * bitmap block for the new bit) */
 #define OCFS2_DIR_LINK_ADDITIONAL_CREDITS (1 + 2)
 
 /* parent fe, parent block, new file entry, inode alloc fe, inode alloc
- * group descriptor + mkdir/symlink blocks */
-#define OCFS2_MKNOD_CREDITS (3 + OCFS2_SUBALLOC_ALLOC                         \
-                           + OCFS2_DIR_LINK_ADDITIONAL_CREDITS)
+ * group descriptor + mkdir/symlink blocks + quota update */
+static inline int ocfs2_mknod_credits(struct super_block *sb)
+{
+       return 3 + OCFS2_SUBALLOC_ALLOC + OCFS2_DIR_LINK_ADDITIONAL_CREDITS +
+              ocfs2_quota_trans_credits(sb);
+}
 
 /* local alloc metadata change + main bitmap updates */
 #define OCFS2_WINDOW_MOVE_CREDITS (OCFS2_INODE_UPDATE_CREDITS                 \
@@ -332,13 +387,21 @@ int                  ocfs2_journal_dirty_data(handle_t *handle,
  * for the dinode, one for the new block. */
 #define OCFS2_SIMPLE_DIR_EXTEND_CREDITS (2)
 
-/* file update (nlink, etc) + directory mtime/ctime + dir entry block */
-#define OCFS2_LINK_CREDITS  (2*OCFS2_INODE_UPDATE_CREDITS + 1)
+/* file update (nlink, etc) + directory mtime/ctime + dir entry block + quota
+ * update on dir */
+static inline int ocfs2_link_credits(struct super_block *sb)
+{
+       return 2*OCFS2_INODE_UPDATE_CREDITS + 1 +
+              ocfs2_quota_trans_credits(sb);
+}
 
 /* inode + dir inode (if we unlink a dir), + dir entry block + orphan
  * dir inode link */
-#define OCFS2_UNLINK_CREDITS  (2 * OCFS2_INODE_UPDATE_CREDITS + 1             \
-                             + OCFS2_LINK_CREDITS)
+static inline int ocfs2_unlink_credits(struct super_block *sb)
+{
+       /* The quota update from ocfs2_link_credits is unused here... */
+       return 2 * OCFS2_INODE_UPDATE_CREDITS + 1 + ocfs2_link_credits(sb);
+}
 
 /* dinode + orphan dir dinode + inode alloc dinode + orphan dir entry +
  * inode alloc group descriptor */
@@ -347,8 +410,10 @@ int                  ocfs2_journal_dirty_data(handle_t *handle,
 /* dinode update, old dir dinode update, new dir dinode update, old
  * dir dir entry, new dir dir entry, dir entry update for renaming
  * directory + target unlink */
-#define OCFS2_RENAME_CREDITS (3 * OCFS2_INODE_UPDATE_CREDITS + 3              \
-                            + OCFS2_UNLINK_CREDITS)
+static inline int ocfs2_rename_credits(struct super_block *sb)
+{
+       return 3 * OCFS2_INODE_UPDATE_CREDITS + 3 + ocfs2_unlink_credits(sb);
+}
 
 /* global bitmap dinode, group desc., relinked group,
  * suballocator dinode, group desc., relinked group,
@@ -386,18 +451,19 @@ static inline int ocfs2_calc_extend_credits(struct super_block *sb,
         * credit for the dinode there. */
        extent_blocks = 1 + 1 + le16_to_cpu(root_el->l_tree_depth);
 
-       return bitmap_blocks + sysfile_bitmap_blocks + extent_blocks;
+       return bitmap_blocks + sysfile_bitmap_blocks + extent_blocks +
+              ocfs2_quota_trans_credits(sb);
 }
 
 static inline int ocfs2_calc_symlink_credits(struct super_block *sb)
 {
-       int blocks = OCFS2_MKNOD_CREDITS;
+       int blocks = ocfs2_mknod_credits(sb);
 
        /* links can be longer than one block so we may update many
         * within our single allocated extent. */
        blocks += ocfs2_clusters_to_blocks(sb, 1);
 
-       return blocks;
+       return blocks + ocfs2_quota_trans_credits(sb);
 }
 
 static inline int ocfs2_calc_group_alloc_credits(struct super_block *sb,
@@ -434,6 +500,8 @@ static inline int ocfs2_calc_tree_trunc_credits(struct super_block *sb,
        /* update to the truncate log. */
        credits += OCFS2_TRUNCATE_LOG_UPDATE;
 
+       credits += ocfs2_quota_trans_credits(sb);
+
        return credits;
 }
 
index 687b28713c3253631b3588ceb41d90ca51cfa867..ec70cdbe77fcb6a360efa338ce7f832f5937965b 100644 (file)
@@ -36,6 +36,7 @@
 #include "ocfs2.h"
 
 #include "alloc.h"
+#include "blockcheck.h"
 #include "dlmglue.h"
 #include "inode.h"
 #include "journal.h"
@@ -248,8 +249,8 @@ int ocfs2_load_local_alloc(struct ocfs2_super *osb)
                goto bail;
        }
 
-       status = ocfs2_read_blocks(inode, OCFS2_I(inode)->ip_blkno, 1,
-                                  &alloc_bh, OCFS2_BH_IGNORE_CACHE);
+       status = ocfs2_read_inode_block_full(inode, &alloc_bh,
+                                            OCFS2_BH_IGNORE_CACHE);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -382,8 +383,8 @@ void ocfs2_shutdown_local_alloc(struct ocfs2_super *osb)
        }
        memcpy(alloc_copy, alloc, bh->b_size);
 
-       status = ocfs2_journal_access(handle, local_alloc_inode, bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_journal_access_di(handle, local_alloc_inode, bh,
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto out_commit;
@@ -459,8 +460,8 @@ int ocfs2_begin_local_alloc_recovery(struct ocfs2_super *osb,
 
        mutex_lock(&inode->i_mutex);
 
-       status = ocfs2_read_blocks(inode, OCFS2_I(inode)->ip_blkno, 1,
-                                  &alloc_bh, OCFS2_BH_IGNORE_CACHE);
+       status = ocfs2_read_inode_block_full(inode, &alloc_bh,
+                                            OCFS2_BH_IGNORE_CACHE);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -476,6 +477,7 @@ int ocfs2_begin_local_alloc_recovery(struct ocfs2_super *osb,
        alloc = (struct ocfs2_dinode *) alloc_bh->b_data;
        ocfs2_clear_local_alloc(alloc);
 
+       ocfs2_compute_meta_ecc(osb->sb, alloc_bh->b_data, &alloc->i_check);
        status = ocfs2_write_block(osb, alloc_bh, inode);
        if (status < 0)
                mlog_errno(status);
@@ -762,9 +764,9 @@ int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb,
         * delete bits from it! */
        *num_bits = bits_wanted;
 
-       status = ocfs2_journal_access(handle, local_alloc_inode,
-                                     osb->local_alloc_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_journal_access_di(handle, local_alloc_inode,
+                                        osb->local_alloc_bh,
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -1240,9 +1242,9 @@ static int ocfs2_local_alloc_slide_window(struct ocfs2_super *osb,
        }
        memcpy(alloc_copy, alloc, osb->local_alloc_bh->b_size);
 
-       status = ocfs2_journal_access(handle, local_alloc_inode,
-                                     osb->local_alloc_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_journal_access_di(handle, local_alloc_inode,
+                                        osb->local_alloc_bh,
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
index 2545e7402efed1453d69347c676beaf2231043e0..084aba86c3b29c145551eb12c60a44d56a6aed4f 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/highmem.h>
+#include <linux/quotaops.h>
 
 #define MLOG_MASK_PREFIX ML_NAMEI
 #include <cluster/masklog.h>
 #include "sysfile.h"
 #include "uptodate.h"
 #include "xattr.h"
+#include "acl.h"
 
 #include "buffer_head_io.h"
 
 static int ocfs2_mknod_locked(struct ocfs2_super *osb,
                              struct inode *dir,
-                             struct dentry *dentry, int mode,
+                             struct inode *inode,
+                             struct dentry *dentry,
                              dev_t dev,
                              struct buffer_head **new_fe_bh,
                              struct buffer_head *parent_fe_bh,
                              handle_t *handle,
-                             struct inode **ret_inode,
                              struct ocfs2_alloc_context *inode_ac);
 
 static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb,
@@ -186,6 +188,35 @@ bail:
        return ret;
 }
 
+static struct inode *ocfs2_get_init_inode(struct inode *dir, int mode)
+{
+       struct inode *inode;
+
+       inode = new_inode(dir->i_sb);
+       if (!inode) {
+               mlog(ML_ERROR, "new_inode failed!\n");
+               return NULL;
+       }
+
+       /* populate as many fields early on as possible - many of
+        * these are used by the support functions here and in
+        * callers. */
+       if (S_ISDIR(mode))
+               inode->i_nlink = 2;
+       else
+               inode->i_nlink = 1;
+       inode->i_uid = current_fsuid();
+       if (dir->i_mode & S_ISGID) {
+               inode->i_gid = dir->i_gid;
+               if (S_ISDIR(mode))
+                       mode |= S_ISGID;
+       } else
+               inode->i_gid = current_fsgid();
+       inode->i_mode = mode;
+       vfs_dq_init(inode);
+       return inode;
+}
+
 static int ocfs2_mknod(struct inode *dir,
                       struct dentry *dentry,
                       int mode,
@@ -201,6 +232,13 @@ static int ocfs2_mknod(struct inode *dir,
        struct inode *inode = NULL;
        struct ocfs2_alloc_context *inode_ac = NULL;
        struct ocfs2_alloc_context *data_ac = NULL;
+       struct ocfs2_alloc_context *xattr_ac = NULL;
+       int want_clusters = 0;
+       int xattr_credits = 0;
+       struct ocfs2_security_xattr_info si = {
+               .enable = 1,
+       };
+       int did_quota_inode = 0;
 
        mlog_entry("(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry, mode,
                   (unsigned long)dev, dentry->d_name.len,
@@ -250,17 +288,46 @@ static int ocfs2_mknod(struct inode *dir,
                goto leave;
        }
 
-       /* Reserve a cluster if creating an extent based directory. */
-       if (S_ISDIR(mode) && !ocfs2_supports_inline_data(osb)) {
-               status = ocfs2_reserve_clusters(osb, 1, &data_ac);
-               if (status < 0) {
-                       if (status != -ENOSPC)
-                               mlog_errno(status);
+       inode = ocfs2_get_init_inode(dir, mode);
+       if (!inode) {
+               status = -ENOMEM;
+               mlog_errno(status);
+               goto leave;
+       }
+
+       /* get security xattr */
+       status = ocfs2_init_security_get(inode, dir, &si);
+       if (status) {
+               if (status == -EOPNOTSUPP)
+                       si.enable = 0;
+               else {
+                       mlog_errno(status);
                        goto leave;
                }
        }
 
-       handle = ocfs2_start_trans(osb, OCFS2_MKNOD_CREDITS);
+       /* calculate meta data/clusters for setting security and acl xattr */
+       status = ocfs2_calc_xattr_init(dir, parent_fe_bh, mode,
+                                       &si, &want_clusters,
+                                       &xattr_credits, &xattr_ac);
+       if (status < 0) {
+               mlog_errno(status);
+               goto leave;
+       }
+
+       /* Reserve a cluster if creating an extent based directory. */
+       if (S_ISDIR(mode) && !ocfs2_supports_inline_data(osb))
+               want_clusters += 1;
+
+       status = ocfs2_reserve_clusters(osb, want_clusters, &data_ac);
+       if (status < 0) {
+               if (status != -ENOSPC)
+                       mlog_errno(status);
+               goto leave;
+       }
+
+       handle = ocfs2_start_trans(osb, ocfs2_mknod_credits(osb->sb) +
+                                  xattr_credits);
        if (IS_ERR(handle)) {
                status = PTR_ERR(handle);
                handle = NULL;
@@ -268,10 +335,19 @@ static int ocfs2_mknod(struct inode *dir,
                goto leave;
        }
 
+       /* We don't use standard VFS wrapper because we don't want vfs_dq_init
+        * to be called. */
+       if (sb_any_quota_active(osb->sb) &&
+           osb->sb->dq_op->alloc_inode(inode, 1) == NO_QUOTA) {
+               status = -EDQUOT;
+               goto leave;
+       }
+       did_quota_inode = 1;
+
        /* do the real work now. */
-       status = ocfs2_mknod_locked(osb, dir, dentry, mode, dev,
+       status = ocfs2_mknod_locked(osb, dir, inode, dentry, dev,
                                    &new_fe_bh, parent_fe_bh, handle,
-                                   &inode, inode_ac);
+                                   inode_ac);
        if (status < 0) {
                mlog_errno(status);
                goto leave;
@@ -285,8 +361,8 @@ static int ocfs2_mknod(struct inode *dir,
                        goto leave;
                }
 
-               status = ocfs2_journal_access(handle, dir, parent_fe_bh,
-                                             OCFS2_JOURNAL_ACCESS_WRITE);
+               status = ocfs2_journal_access_di(handle, dir, parent_fe_bh,
+                                                OCFS2_JOURNAL_ACCESS_WRITE);
                if (status < 0) {
                        mlog_errno(status);
                        goto leave;
@@ -300,6 +376,22 @@ static int ocfs2_mknod(struct inode *dir,
                inc_nlink(dir);
        }
 
+       status = ocfs2_init_acl(handle, inode, dir, new_fe_bh, parent_fe_bh,
+                               xattr_ac, data_ac);
+       if (status < 0) {
+               mlog_errno(status);
+               goto leave;
+       }
+
+       if (si.enable) {
+               status = ocfs2_init_security_set(handle, inode, new_fe_bh, &si,
+                                                xattr_ac, data_ac);
+               if (status < 0) {
+                       mlog_errno(status);
+                       goto leave;
+               }
+       }
+
        status = ocfs2_add_entry(handle, dentry, inode,
                                 OCFS2_I(inode)->ip_blkno, parent_fe_bh,
                                 de_bh);
@@ -320,6 +412,8 @@ static int ocfs2_mknod(struct inode *dir,
        d_instantiate(dentry, inode);
        status = 0;
 leave:
+       if (status < 0 && did_quota_inode)
+               vfs_dq_free_inode(inode);
        if (handle)
                ocfs2_commit_trans(osb, handle);
 
@@ -331,9 +425,13 @@ leave:
        brelse(new_fe_bh);
        brelse(de_bh);
        brelse(parent_fe_bh);
+       kfree(si.name);
+       kfree(si.value);
 
-       if ((status < 0) && inode)
+       if ((status < 0) && inode) {
+               clear_nlink(inode);
                iput(inode);
+       }
 
        if (inode_ac)
                ocfs2_free_alloc_context(inode_ac);
@@ -341,6 +439,9 @@ leave:
        if (data_ac)
                ocfs2_free_alloc_context(data_ac);
 
+       if (xattr_ac)
+               ocfs2_free_alloc_context(xattr_ac);
+
        mlog_exit(status);
 
        return status;
@@ -348,12 +449,12 @@ leave:
 
 static int ocfs2_mknod_locked(struct ocfs2_super *osb,
                              struct inode *dir,
-                             struct dentry *dentry, int mode,
+                             struct inode *inode,
+                             struct dentry *dentry,
                              dev_t dev,
                              struct buffer_head **new_fe_bh,
                              struct buffer_head *parent_fe_bh,
                              handle_t *handle,
-                             struct inode **ret_inode,
                              struct ocfs2_alloc_context *inode_ac)
 {
        int status = 0;
@@ -361,14 +462,12 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
        struct ocfs2_extent_list *fel;
        u64 fe_blkno = 0;
        u16 suballoc_bit;
-       struct inode *inode = NULL;
 
-       mlog_entry("(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry, mode,
-                  (unsigned long)dev, dentry->d_name.len,
+       mlog_entry("(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry,
+                  inode->i_mode, (unsigned long)dev, dentry->d_name.len,
                   dentry->d_name.name);
 
        *new_fe_bh = NULL;
-       *ret_inode = NULL;
 
        status = ocfs2_claim_new_inode(osb, handle, inode_ac, &suballoc_bit,
                                       &fe_blkno);
@@ -377,23 +476,11 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
                goto leave;
        }
 
-       inode = new_inode(dir->i_sb);
-       if (!inode) {
-               status = -ENOMEM;
-               mlog(ML_ERROR, "new_inode failed!\n");
-               goto leave;
-       }
-
        /* populate as many fields early on as possible - many of
         * these are used by the support functions here and in
         * callers. */
        inode->i_ino = ino_from_blkno(osb->sb, fe_blkno);
        OCFS2_I(inode)->ip_blkno = fe_blkno;
-       if (S_ISDIR(mode))
-               inode->i_nlink = 2;
-       else
-               inode->i_nlink = 1;
-       inode->i_mode = mode;
        spin_lock(&osb->osb_lock);
        inode->i_generation = osb->s_next_generation++;
        spin_unlock(&osb->osb_lock);
@@ -406,8 +493,8 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
        }
        ocfs2_set_new_buffer_uptodate(inode, *new_fe_bh);
 
-       status = ocfs2_journal_access(handle, inode, *new_fe_bh,
-                                     OCFS2_JOURNAL_ACCESS_CREATE);
+       status = ocfs2_journal_access_di(handle, inode, *new_fe_bh,
+                                        OCFS2_JOURNAL_ACCESS_CREATE);
        if (status < 0) {
                mlog_errno(status);
                goto leave;
@@ -421,17 +508,11 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
        fe->i_blkno = cpu_to_le64(fe_blkno);
        fe->i_suballoc_bit = cpu_to_le16(suballoc_bit);
        fe->i_suballoc_slot = cpu_to_le16(inode_ac->ac_alloc_slot);
-       fe->i_uid = cpu_to_le32(current_fsuid());
-       if (dir->i_mode & S_ISGID) {
-               fe->i_gid = cpu_to_le32(dir->i_gid);
-               if (S_ISDIR(mode))
-                       mode |= S_ISGID;
-       } else
-               fe->i_gid = cpu_to_le32(current_fsgid());
-       fe->i_mode = cpu_to_le16(mode);
-       if (S_ISCHR(mode) || S_ISBLK(mode))
+       fe->i_uid = cpu_to_le32(inode->i_uid);
+       fe->i_gid = cpu_to_le32(inode->i_gid);
+       fe->i_mode = cpu_to_le16(inode->i_mode);
+       if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
                fe->id1.dev1.i_rdev = cpu_to_le64(huge_encode_dev(dev));
-
        fe->i_links_count = cpu_to_le16(inode->i_nlink);
 
        fe->i_last_eb_blk = 0;
@@ -446,7 +527,7 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
        /*
         * If supported, directories start with inline data.
         */
-       if (S_ISDIR(mode) && ocfs2_supports_inline_data(osb)) {
+       if (S_ISDIR(inode->i_mode) && ocfs2_supports_inline_data(osb)) {
                u16 feat = le16_to_cpu(fe->i_dyn_features);
 
                fe->i_dyn_features = cpu_to_le16(feat | OCFS2_INLINE_DATA_FL);
@@ -465,15 +546,7 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
                goto leave;
        }
 
-       if (ocfs2_populate_inode(inode, fe, 1) < 0) {
-               mlog(ML_ERROR, "populate inode failed! bh->b_blocknr=%llu, "
-                    "i_blkno=%llu, i_ino=%lu\n",
-                    (unsigned long long)(*new_fe_bh)->b_blocknr,
-                    (unsigned long long)le64_to_cpu(fe->i_blkno),
-                    inode->i_ino);
-               BUG();
-       }
-
+       ocfs2_populate_inode(inode, fe, 1);
        ocfs2_inode_set_new(osb, inode);
        if (!ocfs2_mount_local(osb)) {
                status = ocfs2_create_new_inode_locks(inode);
@@ -484,17 +557,12 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
        status = 0; /* error in ocfs2_create_new_inode_locks is not
                     * critical */
 
-       *ret_inode = inode;
 leave:
        if (status < 0) {
                if (*new_fe_bh) {
                        brelse(*new_fe_bh);
                        *new_fe_bh = NULL;
                }
-               if (inode) {
-                       clear_nlink(inode);
-                       iput(inode);
-               }
        }
 
        mlog_exit(status);
@@ -588,7 +656,7 @@ static int ocfs2_link(struct dentry *old_dentry,
                goto out_unlock_inode;
        }
 
-       handle = ocfs2_start_trans(osb, OCFS2_LINK_CREDITS);
+       handle = ocfs2_start_trans(osb, ocfs2_link_credits(osb->sb));
        if (IS_ERR(handle)) {
                err = PTR_ERR(handle);
                handle = NULL;
@@ -596,8 +664,8 @@ static int ocfs2_link(struct dentry *old_dentry,
                goto out_unlock_inode;
        }
 
-       err = ocfs2_journal_access(handle, inode, fe_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       err = ocfs2_journal_access_di(handle, inode, fe_bh,
+                                     OCFS2_JOURNAL_ACCESS_WRITE);
        if (err < 0) {
                mlog_errno(err);
                goto out_commit;
@@ -775,7 +843,7 @@ static int ocfs2_unlink(struct inode *dir,
                }
        }
 
-       handle = ocfs2_start_trans(osb, OCFS2_UNLINK_CREDITS);
+       handle = ocfs2_start_trans(osb, ocfs2_unlink_credits(osb->sb));
        if (IS_ERR(handle)) {
                status = PTR_ERR(handle);
                handle = NULL;
@@ -783,8 +851,8 @@ static int ocfs2_unlink(struct inode *dir,
                goto leave;
        }
 
-       status = ocfs2_journal_access(handle, inode, fe_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_journal_access_di(handle, inode, fe_bh,
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto leave;
@@ -1181,7 +1249,7 @@ static int ocfs2_rename(struct inode *old_dir,
                }
        }
 
-       handle = ocfs2_start_trans(osb, OCFS2_RENAME_CREDITS);
+       handle = ocfs2_start_trans(osb, ocfs2_rename_credits(osb->sb));
        if (IS_ERR(handle)) {
                status = PTR_ERR(handle);
                handle = NULL;
@@ -1197,8 +1265,8 @@ static int ocfs2_rename(struct inode *old_dir,
                                goto bail;
                        }
                }
-               status = ocfs2_journal_access(handle, new_inode, newfe_bh,
-                                             OCFS2_JOURNAL_ACCESS_WRITE);
+               status = ocfs2_journal_access_di(handle, new_inode, newfe_bh,
+                                                OCFS2_JOURNAL_ACCESS_WRITE);
                if (status < 0) {
                        mlog_errno(status);
                        goto bail;
@@ -1244,8 +1312,8 @@ static int ocfs2_rename(struct inode *old_dir,
        old_inode->i_ctime = CURRENT_TIME;
        mark_inode_dirty(old_inode);
 
-       status = ocfs2_journal_access(handle, old_inode, old_inode_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_journal_access_di(handle, old_inode, old_inode_bh,
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
        if (status >= 0) {
                old_di = (struct ocfs2_dinode *) old_inode_bh->b_data;
 
@@ -1321,9 +1389,9 @@ static int ocfs2_rename(struct inode *old_dir,
                             (int)old_dir_nlink, old_dir->i_nlink);
                } else {
                        struct ocfs2_dinode *fe;
-                       status = ocfs2_journal_access(handle, old_dir,
-                                                     old_dir_bh,
-                                                     OCFS2_JOURNAL_ACCESS_WRITE);
+                       status = ocfs2_journal_access_di(handle, old_dir,
+                                                        old_dir_bh,
+                                                        OCFS2_JOURNAL_ACCESS_WRITE);
                        fe = (struct ocfs2_dinode *) old_dir_bh->b_data;
                        fe->i_links_count = cpu_to_le16(old_dir->i_nlink);
                        status = ocfs2_journal_dirty(handle, old_dir_bh);
@@ -1496,6 +1564,13 @@ static int ocfs2_symlink(struct inode *dir,
        handle_t *handle = NULL;
        struct ocfs2_alloc_context *inode_ac = NULL;
        struct ocfs2_alloc_context *data_ac = NULL;
+       struct ocfs2_alloc_context *xattr_ac = NULL;
+       int want_clusters = 0;
+       int xattr_credits = 0;
+       struct ocfs2_security_xattr_info si = {
+               .enable = 1,
+       };
+       int did_quota = 0, did_quota_inode = 0;
 
        mlog_entry("(0x%p, 0x%p, symname='%s' actual='%.*s')\n", dir,
                   dentry, symname, dentry->d_name.len, dentry->d_name.name);
@@ -1542,17 +1617,46 @@ static int ocfs2_symlink(struct inode *dir,
                goto bail;
        }
 
-       /* don't reserve bitmap space for fast symlinks. */
-       if (l > ocfs2_fast_symlink_chars(sb)) {
-               status = ocfs2_reserve_clusters(osb, 1, &data_ac);
+       inode = ocfs2_get_init_inode(dir, S_IFLNK | S_IRWXUGO);
+       if (!inode) {
+               status = -ENOMEM;
+               mlog_errno(status);
+               goto bail;
+       }
+
+       /* get security xattr */
+       status = ocfs2_init_security_get(inode, dir, &si);
+       if (status) {
+               if (status == -EOPNOTSUPP)
+                       si.enable = 0;
+               else {
+                       mlog_errno(status);
+                       goto bail;
+               }
+       }
+
+       /* calculate meta data/clusters for setting security xattr */
+       if (si.enable) {
+               status = ocfs2_calc_security_init(dir, &si, &want_clusters,
+                                                 &xattr_credits, &xattr_ac);
                if (status < 0) {
-                       if (status != -ENOSPC)
-                               mlog_errno(status);
+                       mlog_errno(status);
                        goto bail;
                }
        }
 
-       handle = ocfs2_start_trans(osb, credits);
+       /* don't reserve bitmap space for fast symlinks. */
+       if (l > ocfs2_fast_symlink_chars(sb))
+               want_clusters += 1;
+
+       status = ocfs2_reserve_clusters(osb, want_clusters, &data_ac);
+       if (status < 0) {
+               if (status != -ENOSPC)
+                       mlog_errno(status);
+               goto bail;
+       }
+
+       handle = ocfs2_start_trans(osb, credits + xattr_credits);
        if (IS_ERR(handle)) {
                status = PTR_ERR(handle);
                handle = NULL;
@@ -1560,10 +1664,18 @@ static int ocfs2_symlink(struct inode *dir,
                goto bail;
        }
 
-       status = ocfs2_mknod_locked(osb, dir, dentry,
-                                   S_IFLNK | S_IRWXUGO, 0,
-                                   &new_fe_bh, parent_fe_bh, handle,
-                                   &inode, inode_ac);
+       /* We don't use standard VFS wrapper because we don't want vfs_dq_init
+        * to be called. */
+       if (sb_any_quota_active(osb->sb) &&
+           osb->sb->dq_op->alloc_inode(inode, 1) == NO_QUOTA) {
+               status = -EDQUOT;
+               goto bail;
+       }
+       did_quota_inode = 1;
+
+       status = ocfs2_mknod_locked(osb, dir, inode, dentry,
+                                   0, &new_fe_bh, parent_fe_bh, handle,
+                                   inode_ac);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -1576,6 +1688,12 @@ static int ocfs2_symlink(struct inode *dir,
                u32 offset = 0;
 
                inode->i_op = &ocfs2_symlink_inode_operations;
+               if (vfs_dq_alloc_space_nodirty(inode,
+                   ocfs2_clusters_to_bytes(osb->sb, 1))) {
+                       status = -EDQUOT;
+                       goto bail;
+               }
+               did_quota = 1;
                status = ocfs2_add_inode_data(osb, inode, &offset, 1, 0,
                                              new_fe_bh,
                                              handle, data_ac, NULL,
@@ -1614,6 +1732,15 @@ static int ocfs2_symlink(struct inode *dir,
                }
        }
 
+       if (si.enable) {
+               status = ocfs2_init_security_set(handle, inode, new_fe_bh, &si,
+                                                xattr_ac, data_ac);
+               if (status < 0) {
+                       mlog_errno(status);
+                       goto bail;
+               }
+       }
+
        status = ocfs2_add_entry(handle, dentry, inode,
                                 le64_to_cpu(fe->i_blkno), parent_fe_bh,
                                 de_bh);
@@ -1632,6 +1759,11 @@ static int ocfs2_symlink(struct inode *dir,
        dentry->d_op = &ocfs2_dentry_ops;
        d_instantiate(dentry, inode);
 bail:
+       if (status < 0 && did_quota)
+               vfs_dq_free_space_nodirty(inode,
+                                       ocfs2_clusters_to_bytes(osb->sb, 1));
+       if (status < 0 && did_quota_inode)
+               vfs_dq_free_inode(inode);
        if (handle)
                ocfs2_commit_trans(osb, handle);
 
@@ -1640,12 +1772,18 @@ bail:
        brelse(new_fe_bh);
        brelse(parent_fe_bh);
        brelse(de_bh);
+       kfree(si.name);
+       kfree(si.value);
        if (inode_ac)
                ocfs2_free_alloc_context(inode_ac);
        if (data_ac)
                ocfs2_free_alloc_context(data_ac);
-       if ((status < 0) && inode)
+       if (xattr_ac)
+               ocfs2_free_alloc_context(xattr_ac);
+       if ((status < 0) && inode) {
+               clear_nlink(inode);
                iput(inode);
+       }
 
        mlog_exit(status);
 
@@ -1754,16 +1892,14 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
 
        mlog_entry("(inode->i_ino = %lu)\n", inode->i_ino);
 
-       status = ocfs2_read_block(orphan_dir_inode,
-                                 OCFS2_I(orphan_dir_inode)->ip_blkno,
-                                 &orphan_dir_bh);
+       status = ocfs2_read_inode_block(orphan_dir_inode, &orphan_dir_bh);
        if (status < 0) {
                mlog_errno(status);
                goto leave;
        }
 
-       status = ocfs2_journal_access(handle, orphan_dir_inode, orphan_dir_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_journal_access_di(handle, orphan_dir_inode, orphan_dir_bh,
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto leave;
@@ -1850,8 +1986,8 @@ int ocfs2_orphan_del(struct ocfs2_super *osb,
                goto leave;
        }
 
-       status = ocfs2_journal_access(handle,orphan_dir_inode,  orphan_dir_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_journal_access_di(handle,orphan_dir_inode,  orphan_dir_bh,
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto leave;
index 3fed9e3d89926a90f871a6161c4bea239b2685a7..ad5c24a29edd6d91db671390922c336651bd8d40 100644 (file)
@@ -161,6 +161,7 @@ enum ocfs2_vol_state
 {
        VOLUME_INIT = 0,
        VOLUME_MOUNTED,
+       VOLUME_MOUNTED_QUOTAS,
        VOLUME_DISMOUNTED,
        VOLUME_DISABLED
 };
@@ -195,6 +196,9 @@ enum ocfs2_mount_options
        OCFS2_MOUNT_LOCALFLOCKS = 1 << 5, /* No cluster aware user file locks */
        OCFS2_MOUNT_NOUSERXATTR = 1 << 6, /* No user xattr */
        OCFS2_MOUNT_INODE64 = 1 << 7,   /* Allow inode numbers > 2^32 */
+       OCFS2_MOUNT_POSIX_ACL = 1 << 8, /* POSIX access control lists */
+       OCFS2_MOUNT_USRQUOTA = 1 << 9, /* We support user quotas */
+       OCFS2_MOUNT_GRPQUOTA = 1 << 10, /* We support group quotas */
 };
 
 #define OCFS2_OSB_SOFT_RO      0x0001
@@ -205,6 +209,7 @@ enum ocfs2_mount_options
 struct ocfs2_journal;
 struct ocfs2_slot_info;
 struct ocfs2_recovery_map;
+struct ocfs2_quota_recovery;
 struct ocfs2_super
 {
        struct task_struct *commit_task;
@@ -286,10 +291,11 @@ struct ocfs2_super
        char *local_alloc_debug_buf;
 #endif
 
-       /* Next two fields are for local node slot recovery during
+       /* Next three fields are for local node slot recovery during
         * mount. */
        int dirty;
        struct ocfs2_dinode *local_alloc_copy;
+       struct ocfs2_quota_recovery *quota_rec;
 
        struct ocfs2_alloc_stats alloc_stats;
        char dev_str[20];               /* "major,minor" of the device */
@@ -333,6 +339,10 @@ struct ocfs2_super
 
 #define OCFS2_SB(sb)       ((struct ocfs2_super *)(sb)->s_fs_info)
 
+/* Useful typedef for passing around journal access functions */
+typedef int (*ocfs2_journal_access_func)(handle_t *handle, struct inode *inode,
+                                        struct buffer_head *bh, int type);
+
 static inline int ocfs2_should_order_data(struct inode *inode)
 {
        if (!S_ISREG(inode->i_mode))
@@ -376,6 +386,13 @@ static inline int ocfs2_supports_xattr(struct ocfs2_super *osb)
        return 0;
 }
 
+static inline int ocfs2_meta_ecc(struct ocfs2_super *osb)
+{
+       if (osb->s_feature_incompat & OCFS2_FEATURE_INCOMPAT_META_ECC)
+               return 1;
+       return 0;
+}
+
 /* set / clear functions because cluster events can make these happen
  * in parallel so we want the transitions to be atomic. this also
  * means that any future flags osb_flags must be protected by spinlock
@@ -443,39 +460,19 @@ static inline int ocfs2_uses_extended_slot_map(struct ocfs2_super *osb)
 #define OCFS2_IS_VALID_DINODE(ptr)                                     \
        (!strcmp((ptr)->i_signature, OCFS2_INODE_SIGNATURE))
 
-#define OCFS2_RO_ON_INVALID_DINODE(__sb, __di) do {                    \
-       typeof(__di) ____di = (__di);                                   \
-       ocfs2_error((__sb),                                             \
-               "Dinode # %llu has bad signature %.*s",                 \
-               (unsigned long long)le64_to_cpu((____di)->i_blkno), 7,  \
-               (____di)->i_signature);                                 \
-} while (0)
-
 #define OCFS2_IS_VALID_EXTENT_BLOCK(ptr)                               \
        (!strcmp((ptr)->h_signature, OCFS2_EXTENT_BLOCK_SIGNATURE))
 
-#define OCFS2_RO_ON_INVALID_EXTENT_BLOCK(__sb, __eb)   do {            \
-       typeof(__eb) ____eb = (__eb);                                   \
-       ocfs2_error((__sb),                                             \
-               "Extent Block # %llu has bad signature %.*s",           \
-               (unsigned long long)le64_to_cpu((____eb)->h_blkno), 7,  \
-               (____eb)->h_signature);                                 \
-} while (0)
-
 #define OCFS2_IS_VALID_GROUP_DESC(ptr)                                 \
        (!strcmp((ptr)->bg_signature, OCFS2_GROUP_DESC_SIGNATURE))
 
-#define OCFS2_RO_ON_INVALID_GROUP_DESC(__sb, __gd)     do {            \
-       typeof(__gd) ____gd = (__gd);                                   \
-               ocfs2_error((__sb),                                     \
-               "Group Descriptor # %llu has bad signature %.*s",       \
-               (unsigned long long)le64_to_cpu((____gd)->bg_blkno), 7, \
-               (____gd)->bg_signature);                                \
-} while (0)
 
 #define OCFS2_IS_VALID_XATTR_BLOCK(ptr)                                        \
        (!strcmp((ptr)->xb_signature, OCFS2_XATTR_BLOCK_SIGNATURE))
 
+#define OCFS2_IS_VALID_DIR_TRAILER(ptr)                                        \
+       (!strcmp((ptr)->db_signature, OCFS2_DIR_TRAILER_SIGNATURE))
+
 static inline unsigned long ino_from_blkno(struct super_block *sb,
                                           u64 blkno)
 {
@@ -632,5 +629,6 @@ static inline s16 ocfs2_get_inode_steal_slot(struct ocfs2_super *osb)
 #define ocfs2_clear_bit ext2_clear_bit
 #define ocfs2_test_bit ext2_test_bit
 #define ocfs2_find_next_zero_bit ext2_find_next_zero_bit
+#define ocfs2_find_next_bit ext2_find_next_bit
 #endif  /* OCFS2_H */
 
index 5e0c0d0aef7dcbcf1c9baae7b108cc47bce1f9cf..c7ae45aaa36cd5fa9bc8644dc92ab36a3d6aea55 100644 (file)
@@ -65,6 +65,7 @@
 #define OCFS2_EXTENT_BLOCK_SIGNATURE   "EXBLK01"
 #define OCFS2_GROUP_DESC_SIGNATURE      "GROUP01"
 #define OCFS2_XATTR_BLOCK_SIGNATURE    "XATTR01"
+#define OCFS2_DIR_TRAILER_SIGNATURE    "DIRTRL1"
 
 /* Compatibility flags */
 #define OCFS2_HAS_COMPAT_FEATURE(sb,mask)                      \
                                         | OCFS2_FEATURE_INCOMPAT_INLINE_DATA \
                                         | OCFS2_FEATURE_INCOMPAT_EXTENDED_SLOT_MAP \
                                         | OCFS2_FEATURE_INCOMPAT_USERSPACE_STACK \
-                                        | OCFS2_FEATURE_INCOMPAT_XATTR)
-#define OCFS2_FEATURE_RO_COMPAT_SUPP   OCFS2_FEATURE_RO_COMPAT_UNWRITTEN
+                                        | OCFS2_FEATURE_INCOMPAT_XATTR \
+                                        | OCFS2_FEATURE_INCOMPAT_META_ECC)
+#define OCFS2_FEATURE_RO_COMPAT_SUPP   (OCFS2_FEATURE_RO_COMPAT_UNWRITTEN \
+                                        | OCFS2_FEATURE_RO_COMPAT_USRQUOTA \
+                                        | OCFS2_FEATURE_RO_COMPAT_GRPQUOTA)
 
 /*
  * Heartbeat-only devices are missing journals and other files.  The
 /* Support for extended attributes */
 #define OCFS2_FEATURE_INCOMPAT_XATTR           0x0200
 
+/* Metadata checksum and error correction */
+#define OCFS2_FEATURE_INCOMPAT_META_ECC                0x0800
+
 /*
  * backup superblock flag is used to indicate that this volume
  * has backup superblocks.
  */
 #define OCFS2_FEATURE_RO_COMPAT_UNWRITTEN      0x0001
 
+/*
+ * Maintain quota information for this filesystem
+ */
+#define OCFS2_FEATURE_RO_COMPAT_USRQUOTA       0x0002
+#define OCFS2_FEATURE_RO_COMPAT_GRPQUOTA       0x0004
+
 /* The byte offset of the first backup block will be 1G.
  * The following will be 4G, 16G, 64G, 256G and 1T.
  */
 #define OCFS2_HEARTBEAT_FL     (0x00000200)    /* Heartbeat area */
 #define OCFS2_CHAIN_FL         (0x00000400)    /* Chain allocator */
 #define OCFS2_DEALLOC_FL       (0x00000800)    /* Truncate log */
+#define OCFS2_QUOTA_FL         (0x00001000)    /* Quota file */
 
 /*
  * Flags on ocfs2_dinode.i_dyn_features
@@ -329,13 +343,17 @@ enum {
 #define OCFS2_FIRST_ONLINE_SYSTEM_INODE SLOT_MAP_SYSTEM_INODE
        HEARTBEAT_SYSTEM_INODE,
        GLOBAL_BITMAP_SYSTEM_INODE,
-#define OCFS2_LAST_GLOBAL_SYSTEM_INODE GLOBAL_BITMAP_SYSTEM_INODE
+       USER_QUOTA_SYSTEM_INODE,
+       GROUP_QUOTA_SYSTEM_INODE,
+#define OCFS2_LAST_GLOBAL_SYSTEM_INODE GROUP_QUOTA_SYSTEM_INODE
        ORPHAN_DIR_SYSTEM_INODE,
        EXTENT_ALLOC_SYSTEM_INODE,
        INODE_ALLOC_SYSTEM_INODE,
        JOURNAL_SYSTEM_INODE,
        LOCAL_ALLOC_SYSTEM_INODE,
        TRUNCATE_LOG_SYSTEM_INODE,
+       LOCAL_USER_QUOTA_SYSTEM_INODE,
+       LOCAL_GROUP_QUOTA_SYSTEM_INODE,
        NUM_SYSTEM_INODES
 };
 
@@ -349,6 +367,8 @@ static struct ocfs2_system_inode_info ocfs2_system_inodes[NUM_SYSTEM_INODES] = {
        [SLOT_MAP_SYSTEM_INODE]                 = { "slot_map", 0, S_IFREG | 0644 },
        [HEARTBEAT_SYSTEM_INODE]                = { "heartbeat", OCFS2_HEARTBEAT_FL, S_IFREG | 0644 },
        [GLOBAL_BITMAP_SYSTEM_INODE]            = { "global_bitmap", 0, S_IFREG | 0644 },
+       [USER_QUOTA_SYSTEM_INODE]               = { "aquota.user", OCFS2_QUOTA_FL, S_IFREG | 0644 },
+       [GROUP_QUOTA_SYSTEM_INODE]              = { "aquota.group", OCFS2_QUOTA_FL, S_IFREG | 0644 },
 
        /* Slot-specific system inodes (one copy per slot) */
        [ORPHAN_DIR_SYSTEM_INODE]               = { "orphan_dir:%04d", 0, S_IFDIR | 0755 },
@@ -356,7 +376,9 @@ static struct ocfs2_system_inode_info ocfs2_system_inodes[NUM_SYSTEM_INODES] = {
        [INODE_ALLOC_SYSTEM_INODE]              = { "inode_alloc:%04d", OCFS2_BITMAP_FL | OCFS2_CHAIN_FL, S_IFREG | 0644 },
        [JOURNAL_SYSTEM_INODE]                  = { "journal:%04d", OCFS2_JOURNAL_FL, S_IFREG | 0644 },
        [LOCAL_ALLOC_SYSTEM_INODE]              = { "local_alloc:%04d", OCFS2_BITMAP_FL | OCFS2_LOCAL_ALLOC_FL, S_IFREG | 0644 },
-       [TRUNCATE_LOG_SYSTEM_INODE]             = { "truncate_log:%04d", OCFS2_DEALLOC_FL, S_IFREG | 0644 }
+       [TRUNCATE_LOG_SYSTEM_INODE]             = { "truncate_log:%04d", OCFS2_DEALLOC_FL, S_IFREG | 0644 },
+       [LOCAL_USER_QUOTA_SYSTEM_INODE]         = { "aquota.user:%04d", OCFS2_QUOTA_FL, S_IFREG | 0644 },
+       [LOCAL_GROUP_QUOTA_SYSTEM_INODE]        = { "aquota.group:%04d", OCFS2_QUOTA_FL, S_IFREG | 0644 },
 };
 
 /* Parameter passed from mount.ocfs2 to module */
@@ -409,6 +431,22 @@ static unsigned char ocfs2_type_by_mode[S_IFMT >> S_SHIFT] = {
  */
 #define OCFS2_RAW_SB(dinode)           (&((dinode)->id2.i_super))
 
+/*
+ * Block checking structure.  This is used in metadata to validate the
+ * contents.  If OCFS2_FEATURE_INCOMPAT_META_ECC is not set, it is all
+ * zeros.
+ */
+struct ocfs2_block_check {
+/*00*/ __le32 bc_crc32e;       /* 802.3 Ethernet II CRC32 */
+       __le16 bc_ecc;          /* Single-error-correction parity vector.
+                                  This is a simple Hamming code dependant
+                                  on the blocksize.  OCFS2's maximum
+                                  blocksize, 4K, requires 16 parity bits,
+                                  so we fit in __le16. */
+       __le16 bc_reserved1;
+/*08*/
+};
+
 /*
  * On disk extent record for OCFS2
  * It describes a range of clusters on disk.
@@ -496,7 +534,7 @@ struct ocfs2_truncate_log {
 struct ocfs2_extent_block
 {
 /*00*/ __u8 h_signature[8];            /* Signature for verification */
-       __le64 h_reserved1;
+       struct ocfs2_block_check h_check;       /* Error checking */
 /*10*/ __le16 h_suballoc_slot;         /* Slot suballocator this
                                           extent_header belongs to */
        __le16 h_suballoc_bit;          /* Bit offset in suballocator
@@ -666,7 +704,8 @@ struct ocfs2_dinode {
                                           was set in i_flags */
        __le16 i_dyn_features;
        __le64 i_xattr_loc;
-/*80*/ __le64 i_reserved2[7];
+/*80*/ struct ocfs2_block_check i_check;       /* Error checking */
+/*88*/ __le64 i_reserved2[6];
 /*B8*/ union {
                __le64 i_pad1;          /* Generic way to refer to this
                                           64bit union */
@@ -714,6 +753,34 @@ struct ocfs2_dir_entry {
 /* Actual on-disk length specified by rec_len */
 } __attribute__ ((packed));
 
+/*
+ * Per-block record for the unindexed directory btree. This is carefully
+ * crafted so that the rec_len and name_len records of an ocfs2_dir_entry are
+ * mirrored. That way, the directory manipulation code needs a minimal amount
+ * of update.
+ *
+ * NOTE: Keep this structure aligned to a multiple of 4 bytes.
+ */
+struct ocfs2_dir_block_trailer {
+/*00*/ __le64          db_compat_inode;        /* Always zero. Was inode */
+
+       __le16          db_compat_rec_len;      /* Backwards compatible with
+                                                * ocfs2_dir_entry. */
+       __u8            db_compat_name_len;     /* Always zero. Was name_len */
+       __u8            db_reserved0;
+       __le16          db_reserved1;
+       __le16          db_free_rec_len;        /* Size of largest empty hole
+                                                * in this block. (unused) */
+/*10*/ __u8            db_signature[8];        /* Signature for verification */
+       __le64          db_reserved2;
+       __le64          db_free_next;           /* Next block in list (unused) */
+/*20*/ __le64          db_blkno;               /* Offset on disk, in blocks */
+       __le64          db_parent_dinode;       /* dinode which owns me, in
+                                                  blocks */
+/*30*/ struct ocfs2_block_check db_check;      /* Error checking */
+/*40*/
+};
+
 /*
  * On disk allocator group structure for OCFS2
  */
@@ -733,7 +800,8 @@ struct ocfs2_group_desc
 /*20*/ __le64   bg_parent_dinode;       /* dinode which owns me, in
                                           blocks */
        __le64   bg_blkno;               /* Offset on disk, in blocks */
-/*30*/ __le64   bg_reserved2[2];
+/*30*/ struct ocfs2_block_check bg_check;      /* Error checking */
+       __le64   bg_reserved2;
 /*40*/ __u8    bg_bitmap[0];
 };
 
@@ -776,7 +844,12 @@ struct ocfs2_xattr_header {
                                                   in this extent record,
                                                   only valid in the first
                                                   bucket. */
-       __le64  xh_csum;
+       struct ocfs2_block_check xh_check;      /* Error checking
+                                                  (Note, this is only
+                                                   used for xattr
+                                                   buckets.  A block uses
+                                                   xb_check and sets
+                                                   this field to zero.) */
        struct ocfs2_xattr_entry xh_entries[0]; /* xattr entry list. */
 };
 
@@ -827,7 +900,7 @@ struct ocfs2_xattr_block {
                                        block group */
        __le32  xb_fs_generation;    /* Must match super block */
 /*10*/ __le64  xb_blkno;            /* Offset on disk, in blocks */
-       __le64  xb_csum;
+       struct ocfs2_block_check xb_check;      /* Error checking */
 /*20*/ __le16  xb_flags;            /* Indicates whether this block contains
                                        real xattr or a xattr tree. */
        __le16  xb_reserved0;
@@ -868,6 +941,128 @@ static inline int ocfs2_xattr_get_type(struct ocfs2_xattr_entry *xe)
        return xe->xe_type & OCFS2_XATTR_TYPE_MASK;
 }
 
+/*
+ *  On disk structures for global quota file
+ */
+
+/* Magic numbers and known versions for global quota files */
+#define OCFS2_GLOBAL_QMAGICS {\
+       0x0cf52470, /* USRQUOTA */ \
+       0x0cf52471  /* GRPQUOTA */ \
+}
+
+#define OCFS2_GLOBAL_QVERSIONS {\
+       0, \
+       0, \
+}
+
+
+/* Each block of each quota file has a certain fixed number of bytes reserved
+ * for OCFS2 internal use at its end. OCFS2 can use it for things like
+ * checksums, etc. */
+#define OCFS2_QBLK_RESERVED_SPACE 8
+
+/* Generic header of all quota files */
+struct ocfs2_disk_dqheader {
+       __le32 dqh_magic;       /* Magic number identifying file */
+       __le32 dqh_version;     /* Quota format version */
+};
+
+#define OCFS2_GLOBAL_INFO_OFF (sizeof(struct ocfs2_disk_dqheader))
+
+/* Information header of global quota file (immediately follows the generic
+ * header) */
+struct ocfs2_global_disk_dqinfo {
+/*00*/ __le32 dqi_bgrace;      /* Grace time for space softlimit excess */
+       __le32 dqi_igrace;      /* Grace time for inode softlimit excess */
+       __le32 dqi_syncms;      /* Time after which we sync local changes to
+                                * global quota file */
+       __le32 dqi_blocks;      /* Number of blocks in quota file */
+/*10*/ __le32 dqi_free_blk;    /* First free block in quota file */
+       __le32 dqi_free_entry;  /* First block with free dquot entry in quota
+                                * file */
+};
+
+/* Structure with global user / group information. We reserve some space
+ * for future use. */
+struct ocfs2_global_disk_dqblk {
+/*00*/ __le32 dqb_id;          /* ID the structure belongs to */
+       __le32 dqb_use_count;   /* Number of nodes having reference to this structure */
+       __le64 dqb_ihardlimit;  /* absolute limit on allocated inodes */
+/*10*/ __le64 dqb_isoftlimit;  /* preferred inode limit */
+       __le64 dqb_curinodes;   /* current # allocated inodes */
+/*20*/ __le64 dqb_bhardlimit;  /* absolute limit on disk space */
+       __le64 dqb_bsoftlimit;  /* preferred limit on disk space */
+/*30*/ __le64 dqb_curspace;    /* current space occupied */
+       __le64 dqb_btime;       /* time limit for excessive disk use */
+/*40*/ __le64 dqb_itime;       /* time limit for excessive inode use */
+       __le64 dqb_pad1;
+/*50*/ __le64 dqb_pad2;
+};
+
+/*
+ *  On-disk structures for local quota file
+ */
+
+/* Magic numbers and known versions for local quota files */
+#define OCFS2_LOCAL_QMAGICS {\
+       0x0cf524c0, /* USRQUOTA */ \
+       0x0cf524c1  /* GRPQUOTA */ \
+}
+
+#define OCFS2_LOCAL_QVERSIONS {\
+       0, \
+       0, \
+}
+
+/* Quota flags in dqinfo header */
+#define OLQF_CLEAN     0x0001  /* Quota file is empty (this should be after\
+                                * quota has been cleanly turned off) */
+
+#define OCFS2_LOCAL_INFO_OFF (sizeof(struct ocfs2_disk_dqheader))
+
+/* Information header of local quota file (immediately follows the generic
+ * header) */
+struct ocfs2_local_disk_dqinfo {
+       __le32 dqi_flags;       /* Flags for quota file */
+       __le32 dqi_chunks;      /* Number of chunks of quota structures
+                                * with a bitmap */
+       __le32 dqi_blocks;      /* Number of blocks allocated for quota file */
+};
+
+/* Header of one chunk of a quota file */
+struct ocfs2_local_disk_chunk {
+       __le32 dqc_free;        /* Number of free entries in the bitmap */
+       u8 dqc_bitmap[0];       /* Bitmap of entries in the corresponding
+                                * chunk of quota file */
+};
+
+/* One entry in local quota file */
+struct ocfs2_local_disk_dqblk {
+/*00*/ __le64 dqb_id;          /* id this quota applies to */
+       __le64 dqb_spacemod;    /* Change in the amount of used space */
+/*10*/ __le64 dqb_inodemod;    /* Change in the amount of used inodes */
+};
+
+
+/*
+ * The quota trailer lives at the end of each quota block.
+ */
+
+struct ocfs2_disk_dqtrailer {
+/*00*/ struct ocfs2_block_check dq_check;      /* Error checking */
+/*08*/ /* Cannot be larger than OCFS2_QBLK_RESERVED_SPACE */
+};
+
+static inline struct ocfs2_disk_dqtrailer *ocfs2_block_dqtrailer(int blocksize,
+                                                                void *buf)
+{
+       char *ptr = buf;
+       ptr += blocksize - OCFS2_QBLK_RESERVED_SPACE;
+
+       return (struct ocfs2_disk_dqtrailer *)ptr;
+}
+
 #ifdef __KERNEL__
 static inline int ocfs2_fast_symlink_chars(struct super_block *sb)
 {
diff --git a/fs/ocfs2/ocfs2_jbd_compat.h b/fs/ocfs2/ocfs2_jbd_compat.h
deleted file mode 100644 (file)
index b91c78f..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/* -*- mode: c; c-basic-offset: 8; -*-
- * vim: noexpandtab sw=8 ts=8 sts=0:
- *
- * ocfs2_jbd_compat.h
- *
- * Compatibility defines for JBD.
- *
- * Copyright (C) 2008 Oracle.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-#ifndef OCFS2_JBD_COMPAT_H
-#define OCFS2_JBD_COMPAT_H
-
-#ifndef CONFIG_OCFS2_COMPAT_JBD
-# error Should not have been included
-#endif
-
-struct jbd2_inode {
-       unsigned int dummy;
-};
-
-#define JBD2_BARRIER                   JFS_BARRIER
-#define JBD2_DEFAULT_MAX_COMMIT_AGE    JBD_DEFAULT_MAX_COMMIT_AGE
-
-#define jbd2_journal_ack_err                   journal_ack_err
-#define jbd2_journal_clear_err                 journal_clear_err
-#define jbd2_journal_destroy                   journal_destroy
-#define jbd2_journal_dirty_metadata            journal_dirty_metadata
-#define jbd2_journal_errno                     journal_errno
-#define jbd2_journal_extend                    journal_extend
-#define jbd2_journal_flush                     journal_flush
-#define jbd2_journal_force_commit              journal_force_commit
-#define jbd2_journal_get_write_access          journal_get_write_access
-#define jbd2_journal_get_undo_access           journal_get_undo_access
-#define jbd2_journal_init_inode                        journal_init_inode
-#define jbd2_journal_invalidatepage            journal_invalidatepage
-#define jbd2_journal_load                      journal_load
-#define jbd2_journal_lock_updates              journal_lock_updates
-#define jbd2_journal_restart                   journal_restart
-#define jbd2_journal_start                     journal_start
-#define jbd2_journal_start_commit              journal_start_commit
-#define jbd2_journal_stop                      journal_stop
-#define jbd2_journal_try_to_free_buffers       journal_try_to_free_buffers
-#define jbd2_journal_unlock_updates            journal_unlock_updates
-#define jbd2_journal_wipe                      journal_wipe
-#define jbd2_log_wait_commit                   log_wait_commit
-
-static inline int jbd2_journal_file_inode(handle_t *handle,
-                                         struct jbd2_inode *inode)
-{
-       return 0;
-}
-
-static inline int jbd2_journal_begin_ordered_truncate(struct jbd2_inode *inode,
-                                                     loff_t new_size)
-{
-       return 0;
-}
-
-static inline void jbd2_journal_init_jbd_inode(struct jbd2_inode *jinode,
-                                              struct inode *inode)
-{
-       return;
-}
-
-static inline void jbd2_journal_release_jbd_inode(journal_t *journal,
-                                                 struct jbd2_inode *jinode)
-{
-       return;
-}
-
-
-#endif  /* OCFS2_JBD_COMPAT_H */
index 82c200f7a8f1e327b34b065770c6758892ea70ba..eb6f50c9cecae194cab61bb88ee5a185a90a1e93 100644 (file)
@@ -46,6 +46,7 @@ enum ocfs2_lock_type {
        OCFS2_LOCK_TYPE_DENTRY,
        OCFS2_LOCK_TYPE_OPEN,
        OCFS2_LOCK_TYPE_FLOCK,
+       OCFS2_LOCK_TYPE_QINFO,
        OCFS2_NUM_LOCK_TYPES
 };
 
@@ -77,6 +78,9 @@ static inline char ocfs2_lock_type_char(enum ocfs2_lock_type type)
                case OCFS2_LOCK_TYPE_FLOCK:
                        c = 'F';
                        break;
+               case OCFS2_LOCK_TYPE_QINFO:
+                       c = 'Q';
+                       break;
                default:
                        c = '\0';
        }
@@ -95,6 +99,7 @@ static char *ocfs2_lock_type_strings[] = {
        [OCFS2_LOCK_TYPE_DENTRY] = "Dentry",
        [OCFS2_LOCK_TYPE_OPEN] = "Open",
        [OCFS2_LOCK_TYPE_FLOCK] = "Flock",
+       [OCFS2_LOCK_TYPE_QINFO] = "Quota",
 };
 
 static inline const char *ocfs2_lock_type_string(enum ocfs2_lock_type type)
diff --git a/fs/ocfs2/quota.h b/fs/ocfs2/quota.h
new file mode 100644 (file)
index 0000000..7365e2e
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * quota.h for OCFS2
+ *
+ * On disk quota structures for local and global quota file, in-memory
+ * structures.
+ *
+ */
+
+#ifndef _OCFS2_QUOTA_H
+#define _OCFS2_QUOTA_H
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/quota.h>
+#include <linux/list.h>
+#include <linux/dqblk_qtree.h>
+
+#include "ocfs2.h"
+
+/* Common stuff */
+/* id number of quota format */
+#define QFMT_OCFS2 3
+
+/*
+ * In-memory structures
+ */
+struct ocfs2_dquot {
+       struct dquot dq_dquot;  /* Generic VFS dquot */
+       loff_t dq_local_off;    /* Offset in the local quota file */
+       struct ocfs2_quota_chunk *dq_chunk;     /* Chunk dquot is in */
+       unsigned int dq_use_count;      /* Number of nodes having reference to this entry in global quota file */
+       s64 dq_origspace;       /* Last globally synced space usage */
+       s64 dq_originodes;      /* Last globally synced inode usage */
+};
+
+/* Description of one chunk to recover in memory */
+struct ocfs2_recovery_chunk {
+       struct list_head rc_list;       /* List of chunks */
+       int rc_chunk;                   /* Chunk number */
+       unsigned long *rc_bitmap;       /* Bitmap of entries to recover */
+};
+
+struct ocfs2_quota_recovery {
+       struct list_head r_list[MAXQUOTAS];     /* List of chunks to recover */
+};
+
+/* In-memory structure with quota header information */
+struct ocfs2_mem_dqinfo {
+       unsigned int dqi_type;          /* Quota type this structure describes */
+       unsigned int dqi_chunks;        /* Number of chunks in local quota file */
+       unsigned int dqi_blocks;        /* Number of blocks allocated for local quota file */
+       unsigned int dqi_syncms;        /* How often should we sync with other nodes */
+       unsigned int dqi_syncjiff;      /* Precomputed dqi_syncms in jiffies */
+       struct list_head dqi_chunk;     /* List of chunks */
+       struct inode *dqi_gqinode;      /* Global quota file inode */
+       struct ocfs2_lock_res dqi_gqlock;       /* Lock protecting quota information structure */
+       struct buffer_head *dqi_gqi_bh; /* Buffer head with global quota file inode - set only if inode lock is obtained */
+       int dqi_gqi_count;              /* Number of holders of dqi_gqi_bh */
+       struct buffer_head *dqi_lqi_bh; /* Buffer head with local quota file inode */
+       struct buffer_head *dqi_ibh;    /* Buffer with information header */
+       struct qtree_mem_dqinfo dqi_gi; /* Info about global file */
+       struct delayed_work dqi_sync_work;      /* Work for syncing dquots */
+       struct ocfs2_quota_recovery *dqi_rec;   /* Pointer to recovery
+                                                * information, in case we
+                                                * enable quotas on file
+                                                * needing it */
+};
+
+static inline struct ocfs2_dquot *OCFS2_DQUOT(struct dquot *dquot)
+{
+       return container_of(dquot, struct ocfs2_dquot, dq_dquot);
+}
+
+struct ocfs2_quota_chunk {
+       struct list_head qc_chunk;      /* List of quotafile chunks */
+       int qc_num;                     /* Number of quota chunk */
+       struct buffer_head *qc_headerbh;        /* Buffer head with chunk header */
+};
+
+extern struct kmem_cache *ocfs2_dquot_cachep;
+extern struct kmem_cache *ocfs2_qf_chunk_cachep;
+
+extern struct qtree_fmt_operations ocfs2_global_ops;
+
+struct ocfs2_quota_recovery *ocfs2_begin_quota_recovery(
+                               struct ocfs2_super *osb, int slot_num);
+int ocfs2_finish_quota_recovery(struct ocfs2_super *osb,
+                               struct ocfs2_quota_recovery *rec,
+                               int slot_num);
+void ocfs2_free_quota_recovery(struct ocfs2_quota_recovery *rec);
+ssize_t ocfs2_quota_read(struct super_block *sb, int type, char *data,
+                        size_t len, loff_t off);
+ssize_t ocfs2_quota_write(struct super_block *sb, int type,
+                         const char *data, size_t len, loff_t off);
+int ocfs2_global_read_info(struct super_block *sb, int type);
+int ocfs2_global_write_info(struct super_block *sb, int type);
+int ocfs2_global_read_dquot(struct dquot *dquot);
+int __ocfs2_sync_dquot(struct dquot *dquot, int freeing);
+static inline int ocfs2_sync_dquot(struct dquot *dquot)
+{
+       return __ocfs2_sync_dquot(dquot, 0);
+}
+static inline int ocfs2_global_release_dquot(struct dquot *dquot)
+{
+       return __ocfs2_sync_dquot(dquot, 1);
+}
+
+int ocfs2_lock_global_qf(struct ocfs2_mem_dqinfo *oinfo, int ex);
+void ocfs2_unlock_global_qf(struct ocfs2_mem_dqinfo *oinfo, int ex);
+int ocfs2_read_quota_block(struct inode *inode, u64 v_block,
+                          struct buffer_head **bh);
+
+extern struct dquot_operations ocfs2_quota_operations;
+extern struct quota_format_type ocfs2_quota_format;
+
+int ocfs2_quota_setup(void);
+void ocfs2_quota_shutdown(void);
+
+#endif /* _OCFS2_QUOTA_H */
diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c
new file mode 100644 (file)
index 0000000..6aff8f2
--- /dev/null
@@ -0,0 +1,1025 @@
+/*
+ *  Implementation of operations over global quota file
+ */
+#include <linux/spinlock.h>
+#include <linux/fs.h>
+#include <linux/quota.h>
+#include <linux/quotaops.h>
+#include <linux/dqblk_qtree.h>
+#include <linux/jiffies.h>
+#include <linux/writeback.h>
+#include <linux/workqueue.h>
+
+#define MLOG_MASK_PREFIX ML_QUOTA
+#include <cluster/masklog.h>
+
+#include "ocfs2_fs.h"
+#include "ocfs2.h"
+#include "alloc.h"
+#include "blockcheck.h"
+#include "inode.h"
+#include "journal.h"
+#include "file.h"
+#include "sysfile.h"
+#include "dlmglue.h"
+#include "uptodate.h"
+#include "quota.h"
+
+static struct workqueue_struct *ocfs2_quota_wq = NULL;
+
+static void qsync_work_fn(struct work_struct *work);
+
+static void ocfs2_global_disk2memdqb(struct dquot *dquot, void *dp)
+{
+       struct ocfs2_global_disk_dqblk *d = dp;
+       struct mem_dqblk *m = &dquot->dq_dqb;
+
+       /* Update from disk only entries not set by the admin */
+       if (!test_bit(DQ_LASTSET_B + QIF_ILIMITS_B, &dquot->dq_flags)) {
+               m->dqb_ihardlimit = le64_to_cpu(d->dqb_ihardlimit);
+               m->dqb_isoftlimit = le64_to_cpu(d->dqb_isoftlimit);
+       }
+       if (!test_bit(DQ_LASTSET_B + QIF_INODES_B, &dquot->dq_flags))
+               m->dqb_curinodes = le64_to_cpu(d->dqb_curinodes);
+       if (!test_bit(DQ_LASTSET_B + QIF_BLIMITS_B, &dquot->dq_flags)) {
+               m->dqb_bhardlimit = le64_to_cpu(d->dqb_bhardlimit);
+               m->dqb_bsoftlimit = le64_to_cpu(d->dqb_bsoftlimit);
+       }
+       if (!test_bit(DQ_LASTSET_B + QIF_SPACE_B, &dquot->dq_flags))
+               m->dqb_curspace = le64_to_cpu(d->dqb_curspace);
+       if (!test_bit(DQ_LASTSET_B + QIF_BTIME_B, &dquot->dq_flags))
+               m->dqb_btime = le64_to_cpu(d->dqb_btime);
+       if (!test_bit(DQ_LASTSET_B + QIF_ITIME_B, &dquot->dq_flags))
+               m->dqb_itime = le64_to_cpu(d->dqb_itime);
+       OCFS2_DQUOT(dquot)->dq_use_count = le32_to_cpu(d->dqb_use_count);
+}
+
+static void ocfs2_global_mem2diskdqb(void *dp, struct dquot *dquot)
+{
+       struct ocfs2_global_disk_dqblk *d = dp;
+       struct mem_dqblk *m = &dquot->dq_dqb;
+
+       d->dqb_id = cpu_to_le32(dquot->dq_id);
+       d->dqb_use_count = cpu_to_le32(OCFS2_DQUOT(dquot)->dq_use_count);
+       d->dqb_ihardlimit = cpu_to_le64(m->dqb_ihardlimit);
+       d->dqb_isoftlimit = cpu_to_le64(m->dqb_isoftlimit);
+       d->dqb_curinodes = cpu_to_le64(m->dqb_curinodes);
+       d->dqb_bhardlimit = cpu_to_le64(m->dqb_bhardlimit);
+       d->dqb_bsoftlimit = cpu_to_le64(m->dqb_bsoftlimit);
+       d->dqb_curspace = cpu_to_le64(m->dqb_curspace);
+       d->dqb_btime = cpu_to_le64(m->dqb_btime);
+       d->dqb_itime = cpu_to_le64(m->dqb_itime);
+}
+
+static int ocfs2_global_is_id(void *dp, struct dquot *dquot)
+{
+       struct ocfs2_global_disk_dqblk *d = dp;
+       struct ocfs2_mem_dqinfo *oinfo =
+                       sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
+
+       if (qtree_entry_unused(&oinfo->dqi_gi, dp))
+               return 0;
+       return le32_to_cpu(d->dqb_id) == dquot->dq_id;
+}
+
+struct qtree_fmt_operations ocfs2_global_ops = {
+       .mem2disk_dqblk = ocfs2_global_mem2diskdqb,
+       .disk2mem_dqblk = ocfs2_global_disk2memdqb,
+       .is_id = ocfs2_global_is_id,
+};
+
+static int ocfs2_validate_quota_block(struct super_block *sb,
+                                     struct buffer_head *bh)
+{
+       struct ocfs2_disk_dqtrailer *dqt =
+               ocfs2_block_dqtrailer(sb->s_blocksize, bh->b_data);
+
+       mlog(0, "Validating quota block %llu\n",
+            (unsigned long long)bh->b_blocknr);
+
+       BUG_ON(!buffer_uptodate(bh));
+
+       /*
+        * If the ecc fails, we return the error but otherwise
+        * leave the filesystem running.  We know any error is
+        * local to this block.
+        */
+       return ocfs2_validate_meta_ecc(sb, bh->b_data, &dqt->dq_check);
+}
+
+int ocfs2_read_quota_block(struct inode *inode, u64 v_block,
+                          struct buffer_head **bh)
+{
+       int rc = 0;
+       struct buffer_head *tmp = *bh;
+
+       rc = ocfs2_read_virt_blocks(inode, v_block, 1, &tmp, 0,
+                                   ocfs2_validate_quota_block);
+       if (rc)
+               mlog_errno(rc);
+
+       /* If ocfs2_read_virt_blocks() got us a new bh, pass it up. */
+       if (!rc && !*bh)
+               *bh = tmp;
+
+       return rc;
+}
+
+static int ocfs2_get_quota_block(struct inode *inode, int block,
+                                struct buffer_head **bh)
+{
+       u64 pblock, pcount;
+       int err;
+
+       down_read(&OCFS2_I(inode)->ip_alloc_sem);
+       err = ocfs2_extent_map_get_blocks(inode, block, &pblock, &pcount, NULL);
+       up_read(&OCFS2_I(inode)->ip_alloc_sem);
+       if (err) {
+               mlog_errno(err);
+               return err;
+       }
+       *bh = sb_getblk(inode->i_sb, pblock);
+       if (!*bh) {
+               err = -EIO;
+               mlog_errno(err);
+       }
+       return err;;
+}
+
+/* Read data from global quotafile - avoid pagecache and such because we cannot
+ * afford acquiring the locks... We use quota cluster lock to serialize
+ * operations. Caller is responsible for acquiring it. */
+ssize_t ocfs2_quota_read(struct super_block *sb, int type, char *data,
+                        size_t len, loff_t off)
+{
+       struct ocfs2_mem_dqinfo *oinfo = sb_dqinfo(sb, type)->dqi_priv;
+       struct inode *gqinode = oinfo->dqi_gqinode;
+       loff_t i_size = i_size_read(gqinode);
+       int offset = off & (sb->s_blocksize - 1);
+       sector_t blk = off >> sb->s_blocksize_bits;
+       int err = 0;
+       struct buffer_head *bh;
+       size_t toread, tocopy;
+
+       if (off > i_size)
+               return 0;
+       if (off + len > i_size)
+               len = i_size - off;
+       toread = len;
+       while (toread > 0) {
+               tocopy = min_t(size_t, (sb->s_blocksize - offset), toread);
+               bh = NULL;
+               err = ocfs2_read_quota_block(gqinode, blk, &bh);
+               if (err) {
+                       mlog_errno(err);
+                       return err;
+               }
+               memcpy(data, bh->b_data + offset, tocopy);
+               brelse(bh);
+               offset = 0;
+               toread -= tocopy;
+               data += tocopy;
+               blk++;
+       }
+       return len;
+}
+
+/* Write to quotafile (we know the transaction is already started and has
+ * enough credits) */
+ssize_t ocfs2_quota_write(struct super_block *sb, int type,
+                         const char *data, size_t len, loff_t off)
+{
+       struct mem_dqinfo *info = sb_dqinfo(sb, type);
+       struct ocfs2_mem_dqinfo *oinfo = info->dqi_priv;
+       struct inode *gqinode = oinfo->dqi_gqinode;
+       int offset = off & (sb->s_blocksize - 1);
+       sector_t blk = off >> sb->s_blocksize_bits;
+       int err = 0, new = 0, ja_type;
+       struct buffer_head *bh = NULL;
+       handle_t *handle = journal_current_handle();
+
+       if (!handle) {
+               mlog(ML_ERROR, "Quota write (off=%llu, len=%llu) cancelled "
+                    "because transaction was not started.\n",
+                    (unsigned long long)off, (unsigned long long)len);
+               return -EIO;
+       }
+       if (len > sb->s_blocksize - OCFS2_QBLK_RESERVED_SPACE - offset) {
+               WARN_ON(1);
+               len = sb->s_blocksize - OCFS2_QBLK_RESERVED_SPACE - offset;
+       }
+
+       mutex_lock_nested(&gqinode->i_mutex, I_MUTEX_QUOTA);
+       if (gqinode->i_size < off + len) {
+               down_write(&OCFS2_I(gqinode)->ip_alloc_sem);
+               err = ocfs2_extend_no_holes(gqinode, off + len, off);
+               up_write(&OCFS2_I(gqinode)->ip_alloc_sem);
+               if (err < 0)
+                       goto out;
+               err = ocfs2_simple_size_update(gqinode,
+                                              oinfo->dqi_gqi_bh,
+                                              off + len);
+               if (err < 0)
+                       goto out;
+               new = 1;
+       }
+       /* Not rewriting whole block? */
+       if ((offset || len < sb->s_blocksize - OCFS2_QBLK_RESERVED_SPACE) &&
+           !new) {
+               err = ocfs2_read_quota_block(gqinode, blk, &bh);
+               ja_type = OCFS2_JOURNAL_ACCESS_WRITE;
+       } else {
+               err = ocfs2_get_quota_block(gqinode, blk, &bh);
+               ja_type = OCFS2_JOURNAL_ACCESS_CREATE;
+       }
+       if (err) {
+               mlog_errno(err);
+               return err;
+       }
+       lock_buffer(bh);
+       if (new)
+               memset(bh->b_data, 0, sb->s_blocksize);
+       memcpy(bh->b_data + offset, data, len);
+       flush_dcache_page(bh->b_page);
+       set_buffer_uptodate(bh);
+       unlock_buffer(bh);
+       ocfs2_set_buffer_uptodate(gqinode, bh);
+       err = ocfs2_journal_access_dq(handle, gqinode, bh, ja_type);
+       if (err < 0) {
+               brelse(bh);
+               goto out;
+       }
+       err = ocfs2_journal_dirty(handle, bh);
+       brelse(bh);
+       if (err < 0)
+               goto out;
+out:
+       if (err) {
+               mutex_unlock(&gqinode->i_mutex);
+               mlog_errno(err);
+               return err;
+       }
+       gqinode->i_version++;
+       ocfs2_mark_inode_dirty(handle, gqinode, oinfo->dqi_gqi_bh);
+       mutex_unlock(&gqinode->i_mutex);
+       return len;
+}
+
+int ocfs2_lock_global_qf(struct ocfs2_mem_dqinfo *oinfo, int ex)
+{
+       int status;
+       struct buffer_head *bh = NULL;
+
+       status = ocfs2_inode_lock(oinfo->dqi_gqinode, &bh, ex);
+       if (status < 0)
+               return status;
+       spin_lock(&dq_data_lock);
+       if (!oinfo->dqi_gqi_count++)
+               oinfo->dqi_gqi_bh = bh;
+       else
+               WARN_ON(bh != oinfo->dqi_gqi_bh);
+       spin_unlock(&dq_data_lock);
+       return 0;
+}
+
+void ocfs2_unlock_global_qf(struct ocfs2_mem_dqinfo *oinfo, int ex)
+{
+       ocfs2_inode_unlock(oinfo->dqi_gqinode, ex);
+       brelse(oinfo->dqi_gqi_bh);
+       spin_lock(&dq_data_lock);
+       if (!--oinfo->dqi_gqi_count)
+               oinfo->dqi_gqi_bh = NULL;
+       spin_unlock(&dq_data_lock);
+}
+
+/* Read information header from global quota file */
+int ocfs2_global_read_info(struct super_block *sb, int type)
+{
+       struct inode *gqinode = NULL;
+       unsigned int ino[MAXQUOTAS] = { USER_QUOTA_SYSTEM_INODE,
+                                       GROUP_QUOTA_SYSTEM_INODE };
+       struct ocfs2_global_disk_dqinfo dinfo;
+       struct mem_dqinfo *info = sb_dqinfo(sb, type);
+       struct ocfs2_mem_dqinfo *oinfo = info->dqi_priv;
+       int status;
+
+       mlog_entry_void();
+
+       /* Read global header */
+       gqinode = ocfs2_get_system_file_inode(OCFS2_SB(sb), ino[type],
+                       OCFS2_INVALID_SLOT);
+       if (!gqinode) {
+               mlog(ML_ERROR, "failed to get global quota inode (type=%d)\n",
+                       type);
+               status = -EINVAL;
+               goto out_err;
+       }
+       oinfo->dqi_gi.dqi_sb = sb;
+       oinfo->dqi_gi.dqi_type = type;
+       ocfs2_qinfo_lock_res_init(&oinfo->dqi_gqlock, oinfo);
+       oinfo->dqi_gi.dqi_entry_size = sizeof(struct ocfs2_global_disk_dqblk);
+       oinfo->dqi_gi.dqi_ops = &ocfs2_global_ops;
+       oinfo->dqi_gqi_bh = NULL;
+       oinfo->dqi_gqi_count = 0;
+       oinfo->dqi_gqinode = gqinode;
+       status = ocfs2_lock_global_qf(oinfo, 0);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out_err;
+       }
+       status = sb->s_op->quota_read(sb, type, (char *)&dinfo,
+                                     sizeof(struct ocfs2_global_disk_dqinfo),
+                                     OCFS2_GLOBAL_INFO_OFF);
+       ocfs2_unlock_global_qf(oinfo, 0);
+       if (status != sizeof(struct ocfs2_global_disk_dqinfo)) {
+               mlog(ML_ERROR, "Cannot read global quota info (%d).\n",
+                    status);
+               if (status >= 0)
+                       status = -EIO;
+               mlog_errno(status);
+               goto out_err;
+       }
+       info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
+       info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);
+       oinfo->dqi_syncms = le32_to_cpu(dinfo.dqi_syncms);
+       oinfo->dqi_syncjiff = msecs_to_jiffies(oinfo->dqi_syncms);
+       oinfo->dqi_gi.dqi_blocks = le32_to_cpu(dinfo.dqi_blocks);
+       oinfo->dqi_gi.dqi_free_blk = le32_to_cpu(dinfo.dqi_free_blk);
+       oinfo->dqi_gi.dqi_free_entry = le32_to_cpu(dinfo.dqi_free_entry);
+       oinfo->dqi_gi.dqi_blocksize_bits = sb->s_blocksize_bits;
+       oinfo->dqi_gi.dqi_usable_bs = sb->s_blocksize -
+                                               OCFS2_QBLK_RESERVED_SPACE;
+       oinfo->dqi_gi.dqi_qtree_depth = qtree_depth(&oinfo->dqi_gi);
+       INIT_DELAYED_WORK(&oinfo->dqi_sync_work, qsync_work_fn);
+       queue_delayed_work(ocfs2_quota_wq, &oinfo->dqi_sync_work,
+                          oinfo->dqi_syncjiff);
+
+out_err:
+       mlog_exit(status);
+       return status;
+}
+
+/* Write information to global quota file. Expects exlusive lock on quota
+ * file inode and quota info */
+static int __ocfs2_global_write_info(struct super_block *sb, int type)
+{
+       struct mem_dqinfo *info = sb_dqinfo(sb, type);
+       struct ocfs2_mem_dqinfo *oinfo = info->dqi_priv;
+       struct ocfs2_global_disk_dqinfo dinfo;
+       ssize_t size;
+
+       spin_lock(&dq_data_lock);
+       info->dqi_flags &= ~DQF_INFO_DIRTY;
+       dinfo.dqi_bgrace = cpu_to_le32(info->dqi_bgrace);
+       dinfo.dqi_igrace = cpu_to_le32(info->dqi_igrace);
+       spin_unlock(&dq_data_lock);
+       dinfo.dqi_syncms = cpu_to_le32(oinfo->dqi_syncms);
+       dinfo.dqi_blocks = cpu_to_le32(oinfo->dqi_gi.dqi_blocks);
+       dinfo.dqi_free_blk = cpu_to_le32(oinfo->dqi_gi.dqi_free_blk);
+       dinfo.dqi_free_entry = cpu_to_le32(oinfo->dqi_gi.dqi_free_entry);
+       size = sb->s_op->quota_write(sb, type, (char *)&dinfo,
+                                    sizeof(struct ocfs2_global_disk_dqinfo),
+                                    OCFS2_GLOBAL_INFO_OFF);
+       if (size != sizeof(struct ocfs2_global_disk_dqinfo)) {
+               mlog(ML_ERROR, "Cannot write global quota info structure\n");
+               if (size >= 0)
+                       size = -EIO;
+               return size;
+       }
+       return 0;
+}
+
+int ocfs2_global_write_info(struct super_block *sb, int type)
+{
+       int err;
+       struct ocfs2_mem_dqinfo *info = sb_dqinfo(sb, type)->dqi_priv;
+
+       err = ocfs2_qinfo_lock(info, 1);
+       if (err < 0)
+               return err;
+       err = __ocfs2_global_write_info(sb, type);
+       ocfs2_qinfo_unlock(info, 1);
+       return err;
+}
+
+/* Read in information from global quota file and acquire a reference to it.
+ * dquot_acquire() has already started the transaction and locked quota file */
+int ocfs2_global_read_dquot(struct dquot *dquot)
+{
+       int err, err2, ex = 0;
+       struct ocfs2_mem_dqinfo *info =
+                       sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
+
+       err = ocfs2_qinfo_lock(info, 0);
+       if (err < 0)
+               goto out;
+       err = qtree_read_dquot(&info->dqi_gi, dquot);
+       if (err < 0)
+               goto out_qlock;
+       OCFS2_DQUOT(dquot)->dq_use_count++;
+       OCFS2_DQUOT(dquot)->dq_origspace = dquot->dq_dqb.dqb_curspace;
+       OCFS2_DQUOT(dquot)->dq_originodes = dquot->dq_dqb.dqb_curinodes;
+       if (!dquot->dq_off) {   /* No real quota entry? */
+               /* Upgrade to exclusive lock for allocation */
+               err = ocfs2_qinfo_lock(info, 1);
+               if (err < 0)
+                       goto out_qlock;
+               ex = 1;
+       }
+       err = qtree_write_dquot(&info->dqi_gi, dquot);
+       if (ex && info_dirty(sb_dqinfo(dquot->dq_sb, dquot->dq_type))) {
+               err2 = __ocfs2_global_write_info(dquot->dq_sb, dquot->dq_type);
+               if (!err)
+                       err = err2;
+       }
+out_qlock:
+       if (ex)
+               ocfs2_qinfo_unlock(info, 1);
+       ocfs2_qinfo_unlock(info, 0);
+out:
+       if (err < 0)
+               mlog_errno(err);
+       return err;
+}
+
+/* Sync local information about quota modifications with global quota file.
+ * Caller must have started the transaction and obtained exclusive lock for
+ * global quota file inode */
+int __ocfs2_sync_dquot(struct dquot *dquot, int freeing)
+{
+       int err, err2;
+       struct super_block *sb = dquot->dq_sb;
+       int type = dquot->dq_type;
+       struct ocfs2_mem_dqinfo *info = sb_dqinfo(sb, type)->dqi_priv;
+       struct ocfs2_global_disk_dqblk dqblk;
+       s64 spacechange, inodechange;
+       time_t olditime, oldbtime;
+
+       err = sb->s_op->quota_read(sb, type, (char *)&dqblk,
+                                  sizeof(struct ocfs2_global_disk_dqblk),
+                                  dquot->dq_off);
+       if (err != sizeof(struct ocfs2_global_disk_dqblk)) {
+               if (err >= 0) {
+                       mlog(ML_ERROR, "Short read from global quota file "
+                                      "(%u read)\n", err);
+                       err = -EIO;
+               }
+               goto out;
+       }
+
+       /* Update space and inode usage. Get also other information from
+        * global quota file so that we don't overwrite any changes there.
+        * We are */
+       spin_lock(&dq_data_lock);
+       spacechange = dquot->dq_dqb.dqb_curspace -
+                                       OCFS2_DQUOT(dquot)->dq_origspace;
+       inodechange = dquot->dq_dqb.dqb_curinodes -
+                                       OCFS2_DQUOT(dquot)->dq_originodes;
+       olditime = dquot->dq_dqb.dqb_itime;
+       oldbtime = dquot->dq_dqb.dqb_btime;
+       ocfs2_global_disk2memdqb(dquot, &dqblk);
+       mlog(0, "Syncing global dquot %u space %lld+%lld, inodes %lld+%lld\n",
+            dquot->dq_id, dquot->dq_dqb.dqb_curspace, (long long)spacechange,
+            dquot->dq_dqb.dqb_curinodes, (long long)inodechange);
+       if (!test_bit(DQ_LASTSET_B + QIF_SPACE_B, &dquot->dq_flags))
+               dquot->dq_dqb.dqb_curspace += spacechange;
+       if (!test_bit(DQ_LASTSET_B + QIF_INODES_B, &dquot->dq_flags))
+               dquot->dq_dqb.dqb_curinodes += inodechange;
+       /* Set properly space grace time... */
+       if (dquot->dq_dqb.dqb_bsoftlimit &&
+           dquot->dq_dqb.dqb_curspace > dquot->dq_dqb.dqb_bsoftlimit) {
+               if (!test_bit(DQ_LASTSET_B + QIF_BTIME_B, &dquot->dq_flags) &&
+                   oldbtime > 0) {
+                       if (dquot->dq_dqb.dqb_btime > 0)
+                               dquot->dq_dqb.dqb_btime =
+                                       min(dquot->dq_dqb.dqb_btime, oldbtime);
+                       else
+                               dquot->dq_dqb.dqb_btime = oldbtime;
+               }
+       } else {
+               dquot->dq_dqb.dqb_btime = 0;
+               clear_bit(DQ_BLKS_B, &dquot->dq_flags);
+       }
+       /* Set properly inode grace time... */
+       if (dquot->dq_dqb.dqb_isoftlimit &&
+           dquot->dq_dqb.dqb_curinodes > dquot->dq_dqb.dqb_isoftlimit) {
+               if (!test_bit(DQ_LASTSET_B + QIF_ITIME_B, &dquot->dq_flags) &&
+                   olditime > 0) {
+                       if (dquot->dq_dqb.dqb_itime > 0)
+                               dquot->dq_dqb.dqb_itime =
+                                       min(dquot->dq_dqb.dqb_itime, olditime);
+                       else
+                               dquot->dq_dqb.dqb_itime = olditime;
+               }
+       } else {
+               dquot->dq_dqb.dqb_itime = 0;
+               clear_bit(DQ_INODES_B, &dquot->dq_flags);
+       }
+       /* All information is properly updated, clear the flags */
+       __clear_bit(DQ_LASTSET_B + QIF_SPACE_B, &dquot->dq_flags);
+       __clear_bit(DQ_LASTSET_B + QIF_INODES_B, &dquot->dq_flags);
+       __clear_bit(DQ_LASTSET_B + QIF_BLIMITS_B, &dquot->dq_flags);
+       __clear_bit(DQ_LASTSET_B + QIF_ILIMITS_B, &dquot->dq_flags);
+       __clear_bit(DQ_LASTSET_B + QIF_BTIME_B, &dquot->dq_flags);
+       __clear_bit(DQ_LASTSET_B + QIF_ITIME_B, &dquot->dq_flags);
+       OCFS2_DQUOT(dquot)->dq_origspace = dquot->dq_dqb.dqb_curspace;
+       OCFS2_DQUOT(dquot)->dq_originodes = dquot->dq_dqb.dqb_curinodes;
+       spin_unlock(&dq_data_lock);
+       err = ocfs2_qinfo_lock(info, freeing);
+       if (err < 0) {
+               mlog(ML_ERROR, "Failed to lock quota info, loosing quota write"
+                              " (type=%d, id=%u)\n", dquot->dq_type,
+                              (unsigned)dquot->dq_id);
+               goto out;
+       }
+       if (freeing)
+               OCFS2_DQUOT(dquot)->dq_use_count--;
+       err = qtree_write_dquot(&info->dqi_gi, dquot);
+       if (err < 0)
+               goto out_qlock;
+       if (freeing && !OCFS2_DQUOT(dquot)->dq_use_count) {
+               err = qtree_release_dquot(&info->dqi_gi, dquot);
+               if (info_dirty(sb_dqinfo(sb, type))) {
+                       err2 = __ocfs2_global_write_info(sb, type);
+                       if (!err)
+                               err = err2;
+               }
+       }
+out_qlock:
+       ocfs2_qinfo_unlock(info, freeing);
+out:
+       if (err < 0)
+               mlog_errno(err);
+       return err;
+}
+
+/*
+ *  Functions for periodic syncing of dquots with global file
+ */
+static int ocfs2_sync_dquot_helper(struct dquot *dquot, unsigned long type)
+{
+       handle_t *handle;
+       struct super_block *sb = dquot->dq_sb;
+       struct ocfs2_mem_dqinfo *oinfo = sb_dqinfo(sb, type)->dqi_priv;
+       struct ocfs2_super *osb = OCFS2_SB(sb);
+       int status = 0;
+
+       mlog_entry("id=%u qtype=%u type=%lu device=%s\n", dquot->dq_id,
+                  dquot->dq_type, type, sb->s_id);
+       if (type != dquot->dq_type)
+               goto out;
+       status = ocfs2_lock_global_qf(oinfo, 1);
+       if (status < 0)
+               goto out;
+
+       handle = ocfs2_start_trans(osb, OCFS2_QSYNC_CREDITS);
+       if (IS_ERR(handle)) {
+               status = PTR_ERR(handle);
+               mlog_errno(status);
+               goto out_ilock;
+       }
+       mutex_lock(&sb_dqopt(sb)->dqio_mutex);
+       status = ocfs2_sync_dquot(dquot);
+       mutex_unlock(&sb_dqopt(sb)->dqio_mutex);
+       if (status < 0)
+               mlog_errno(status);
+       /* We have to write local structure as well... */
+       dquot_mark_dquot_dirty(dquot);
+       status = dquot_commit(dquot);
+       if (status < 0)
+               mlog_errno(status);
+       ocfs2_commit_trans(osb, handle);
+out_ilock:
+       ocfs2_unlock_global_qf(oinfo, 1);
+out:
+       mlog_exit(status);
+       return status;
+}
+
+static void qsync_work_fn(struct work_struct *work)
+{
+       struct ocfs2_mem_dqinfo *oinfo = container_of(work,
+                                                     struct ocfs2_mem_dqinfo,
+                                                     dqi_sync_work.work);
+       struct super_block *sb = oinfo->dqi_gqinode->i_sb;
+
+       dquot_scan_active(sb, ocfs2_sync_dquot_helper, oinfo->dqi_type);
+       queue_delayed_work(ocfs2_quota_wq, &oinfo->dqi_sync_work,
+                          oinfo->dqi_syncjiff);
+}
+
+/*
+ *  Wrappers for generic quota functions
+ */
+
+static int ocfs2_write_dquot(struct dquot *dquot)
+{
+       handle_t *handle;
+       struct ocfs2_super *osb = OCFS2_SB(dquot->dq_sb);
+       int status = 0;
+
+       mlog_entry("id=%u, type=%d", dquot->dq_id, dquot->dq_type);
+
+       handle = ocfs2_start_trans(osb, OCFS2_QWRITE_CREDITS);
+       if (IS_ERR(handle)) {
+               status = PTR_ERR(handle);
+               mlog_errno(status);
+               goto out;
+       }
+       status = dquot_commit(dquot);
+       ocfs2_commit_trans(osb, handle);
+out:
+       mlog_exit(status);
+       return status;
+}
+
+int ocfs2_calc_qdel_credits(struct super_block *sb, int type)
+{
+       struct ocfs2_mem_dqinfo *oinfo;
+       int features[MAXQUOTAS] = { OCFS2_FEATURE_RO_COMPAT_USRQUOTA,
+                                   OCFS2_FEATURE_RO_COMPAT_GRPQUOTA };
+
+       if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, features[type]))
+               return 0;
+
+       oinfo = sb_dqinfo(sb, type)->dqi_priv;
+       /* We modify tree, leaf block, global info, local chunk header,
+        * global and local inode */
+       return oinfo->dqi_gi.dqi_qtree_depth + 2 + 1 +
+              2 * OCFS2_INODE_UPDATE_CREDITS;
+}
+
+static int ocfs2_release_dquot(struct dquot *dquot)
+{
+       handle_t *handle;
+       struct ocfs2_mem_dqinfo *oinfo =
+                       sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
+       struct ocfs2_super *osb = OCFS2_SB(dquot->dq_sb);
+       int status = 0;
+
+       mlog_entry("id=%u, type=%d", dquot->dq_id, dquot->dq_type);
+
+       status = ocfs2_lock_global_qf(oinfo, 1);
+       if (status < 0)
+               goto out;
+       handle = ocfs2_start_trans(osb,
+               ocfs2_calc_qdel_credits(dquot->dq_sb, dquot->dq_type));
+       if (IS_ERR(handle)) {
+               status = PTR_ERR(handle);
+               mlog_errno(status);
+               goto out_ilock;
+       }
+       status = dquot_release(dquot);
+       ocfs2_commit_trans(osb, handle);
+out_ilock:
+       ocfs2_unlock_global_qf(oinfo, 1);
+out:
+       mlog_exit(status);
+       return status;
+}
+
+int ocfs2_calc_qinit_credits(struct super_block *sb, int type)
+{
+       struct ocfs2_mem_dqinfo *oinfo;
+       int features[MAXQUOTAS] = { OCFS2_FEATURE_RO_COMPAT_USRQUOTA,
+                                   OCFS2_FEATURE_RO_COMPAT_GRPQUOTA };
+       struct ocfs2_dinode *lfe, *gfe;
+
+       if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, features[type]))
+               return 0;
+
+       oinfo = sb_dqinfo(sb, type)->dqi_priv;
+       gfe = (struct ocfs2_dinode *)oinfo->dqi_gqi_bh->b_data;
+       lfe = (struct ocfs2_dinode *)oinfo->dqi_lqi_bh->b_data;
+       /* We can extend local file + global file. In local file we
+        * can modify info, chunk header block and dquot block. In
+        * global file we can modify info, tree and leaf block */
+       return ocfs2_calc_extend_credits(sb, &lfe->id2.i_list, 0) +
+              ocfs2_calc_extend_credits(sb, &gfe->id2.i_list, 0) +
+              3 + oinfo->dqi_gi.dqi_qtree_depth + 2;
+}
+
+static int ocfs2_acquire_dquot(struct dquot *dquot)
+{
+       handle_t *handle;
+       struct ocfs2_mem_dqinfo *oinfo =
+                       sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
+       struct ocfs2_super *osb = OCFS2_SB(dquot->dq_sb);
+       int status = 0;
+
+       mlog_entry("id=%u, type=%d", dquot->dq_id, dquot->dq_type);
+       /* We need an exclusive lock, because we're going to update use count
+        * and instantiate possibly new dquot structure */
+       status = ocfs2_lock_global_qf(oinfo, 1);
+       if (status < 0)
+               goto out;
+       handle = ocfs2_start_trans(osb,
+               ocfs2_calc_qinit_credits(dquot->dq_sb, dquot->dq_type));
+       if (IS_ERR(handle)) {
+               status = PTR_ERR(handle);
+               mlog_errno(status);
+               goto out_ilock;
+       }
+       status = dquot_acquire(dquot);
+       ocfs2_commit_trans(osb, handle);
+out_ilock:
+       ocfs2_unlock_global_qf(oinfo, 1);
+out:
+       mlog_exit(status);
+       return status;
+}
+
+static int ocfs2_mark_dquot_dirty(struct dquot *dquot)
+{
+       unsigned long mask = (1 << (DQ_LASTSET_B + QIF_ILIMITS_B)) |
+                            (1 << (DQ_LASTSET_B + QIF_BLIMITS_B)) |
+                            (1 << (DQ_LASTSET_B + QIF_INODES_B)) |
+                            (1 << (DQ_LASTSET_B + QIF_SPACE_B)) |
+                            (1 << (DQ_LASTSET_B + QIF_BTIME_B)) |
+                            (1 << (DQ_LASTSET_B + QIF_ITIME_B));
+       int sync = 0;
+       int status;
+       struct super_block *sb = dquot->dq_sb;
+       int type = dquot->dq_type;
+       struct ocfs2_mem_dqinfo *oinfo = sb_dqinfo(sb, type)->dqi_priv;
+       handle_t *handle;
+       struct ocfs2_super *osb = OCFS2_SB(sb);
+
+       mlog_entry("id=%u, type=%d", dquot->dq_id, type);
+       dquot_mark_dquot_dirty(dquot);
+
+       /* In case user set some limits, sync dquot immediately to global
+        * quota file so that information propagates quicker */
+       spin_lock(&dq_data_lock);
+       if (dquot->dq_flags & mask)
+               sync = 1;
+       spin_unlock(&dq_data_lock);
+       if (!sync) {
+               status = ocfs2_write_dquot(dquot);
+               goto out;
+       }
+       status = ocfs2_lock_global_qf(oinfo, 1);
+       if (status < 0)
+               goto out;
+       handle = ocfs2_start_trans(osb, OCFS2_QSYNC_CREDITS);
+       if (IS_ERR(handle)) {
+               status = PTR_ERR(handle);
+               mlog_errno(status);
+               goto out_ilock;
+       }
+       status = ocfs2_sync_dquot(dquot);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out_trans;
+       }
+       /* Now write updated local dquot structure */
+       status = dquot_commit(dquot);
+out_trans:
+       ocfs2_commit_trans(osb, handle);
+out_ilock:
+       ocfs2_unlock_global_qf(oinfo, 1);
+out:
+       mlog_exit(status);
+       return status;
+}
+
+/* This should happen only after set_dqinfo(). */
+static int ocfs2_write_info(struct super_block *sb, int type)
+{
+       handle_t *handle;
+       int status = 0;
+       struct ocfs2_mem_dqinfo *oinfo = sb_dqinfo(sb, type)->dqi_priv;
+
+       mlog_entry_void();
+
+       status = ocfs2_lock_global_qf(oinfo, 1);
+       if (status < 0)
+               goto out;
+       handle = ocfs2_start_trans(OCFS2_SB(sb), OCFS2_QINFO_WRITE_CREDITS);
+       if (IS_ERR(handle)) {
+               status = PTR_ERR(handle);
+               mlog_errno(status);
+               goto out_ilock;
+       }
+       status = dquot_commit_info(sb, type);
+       ocfs2_commit_trans(OCFS2_SB(sb), handle);
+out_ilock:
+       ocfs2_unlock_global_qf(oinfo, 1);
+out:
+       mlog_exit(status);
+       return status;
+}
+
+/* This is difficult. We have to lock quota inode and start transaction
+ * in this function but we don't want to take the penalty of exlusive
+ * quota file lock when we are just going to use cached structures. So
+ * we just take read lock check whether we have dquot cached and if so,
+ * we don't have to take the write lock... */
+static int ocfs2_dquot_initialize(struct inode *inode, int type)
+{
+       handle_t *handle = NULL;
+       int status = 0;
+       struct super_block *sb = inode->i_sb;
+       struct ocfs2_mem_dqinfo *oinfo;
+       int exclusive = 0;
+       int cnt;
+       qid_t id;
+
+       mlog_entry_void();
+
+       for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+               if (type != -1 && cnt != type)
+                       continue;
+               if (!sb_has_quota_active(sb, cnt))
+                       continue;
+               oinfo = sb_dqinfo(sb, cnt)->dqi_priv;
+               status = ocfs2_lock_global_qf(oinfo, 0);
+               if (status < 0)
+                       goto out;
+               /* This is just a performance optimization not a reliable test.
+                * Since we hold an inode lock, noone can actually release
+                * the structure until we are finished with initialization. */
+               if (inode->i_dquot[cnt] != NODQUOT) {
+                       ocfs2_unlock_global_qf(oinfo, 0);
+                       continue;
+               }
+               /* When we have inode lock, we know that no dquot_release() can
+                * run and thus we can safely check whether we need to
+                * read+modify global file to get quota information or whether
+                * our node already has it. */
+               if (cnt == USRQUOTA)
+                       id = inode->i_uid;
+               else if (cnt == GRPQUOTA)
+                       id = inode->i_gid;
+               else
+                       BUG();
+               /* Obtain exclusion from quota off... */
+               down_write(&sb_dqopt(sb)->dqptr_sem);
+               exclusive = !dquot_is_cached(sb, id, cnt);
+               up_write(&sb_dqopt(sb)->dqptr_sem);
+               if (exclusive) {
+                       status = ocfs2_lock_global_qf(oinfo, 1);
+                       if (status < 0) {
+                               exclusive = 0;
+                               mlog_errno(status);
+                               goto out_ilock;
+                       }
+                       handle = ocfs2_start_trans(OCFS2_SB(sb),
+                                       ocfs2_calc_qinit_credits(sb, cnt));
+                       if (IS_ERR(handle)) {
+                               status = PTR_ERR(handle);
+                               mlog_errno(status);
+                               goto out_ilock;
+                       }
+               }
+               dquot_initialize(inode, cnt);
+               if (exclusive) {
+                       ocfs2_commit_trans(OCFS2_SB(sb), handle);
+                       ocfs2_unlock_global_qf(oinfo, 1);
+               }
+               ocfs2_unlock_global_qf(oinfo, 0);
+       }
+       mlog_exit(0);
+       return 0;
+out_ilock:
+       if (exclusive)
+               ocfs2_unlock_global_qf(oinfo, 1);
+       ocfs2_unlock_global_qf(oinfo, 0);
+out:
+       mlog_exit(status);
+       return status;
+}
+
+static int ocfs2_dquot_drop_slow(struct inode *inode)
+{
+       int status = 0;
+       int cnt;
+       int got_lock[MAXQUOTAS] = {0, 0};
+       handle_t *handle;
+       struct super_block *sb = inode->i_sb;
+       struct ocfs2_mem_dqinfo *oinfo;
+
+       for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+               if (!sb_has_quota_active(sb, cnt))
+                       continue;
+               oinfo = sb_dqinfo(sb, cnt)->dqi_priv;
+               status = ocfs2_lock_global_qf(oinfo, 1);
+               if (status < 0)
+                       goto out;
+               got_lock[cnt] = 1;
+       }
+       handle = ocfs2_start_trans(OCFS2_SB(sb),
+                       ocfs2_calc_qinit_credits(sb, USRQUOTA) +
+                       ocfs2_calc_qinit_credits(sb, GRPQUOTA));
+       if (IS_ERR(handle)) {
+               status = PTR_ERR(handle);
+               mlog_errno(status);
+               goto out;
+       }
+       dquot_drop(inode);
+       ocfs2_commit_trans(OCFS2_SB(sb), handle);
+out:
+       for (cnt = 0; cnt < MAXQUOTAS; cnt++)
+               if (got_lock[cnt]) {
+                       oinfo = sb_dqinfo(sb, cnt)->dqi_priv;
+                       ocfs2_unlock_global_qf(oinfo, 1);
+               }
+       return status;
+}
+
+/* See the comment before ocfs2_dquot_initialize. */
+static int ocfs2_dquot_drop(struct inode *inode)
+{
+       int status = 0;
+       struct super_block *sb = inode->i_sb;
+       struct ocfs2_mem_dqinfo *oinfo;
+       int exclusive = 0;
+       int cnt;
+       int got_lock[MAXQUOTAS] = {0, 0};
+
+       mlog_entry_void();
+       for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+               if (!sb_has_quota_active(sb, cnt))
+                       continue;
+               oinfo = sb_dqinfo(sb, cnt)->dqi_priv;
+               status = ocfs2_lock_global_qf(oinfo, 0);
+               if (status < 0)
+                       goto out;
+               got_lock[cnt] = 1;
+       }
+       /* Lock against anyone releasing references so that when when we check
+        * we know we are not going to be last ones to release dquot */
+       down_write(&sb_dqopt(sb)->dqptr_sem);
+       /* Urgh, this is a terrible hack :( */
+       for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+               if (inode->i_dquot[cnt] != NODQUOT &&
+                   atomic_read(&inode->i_dquot[cnt]->dq_count) > 1) {
+                       exclusive = 1;
+                       break;
+               }
+       }
+       if (!exclusive)
+               dquot_drop_locked(inode);
+       up_write(&sb_dqopt(sb)->dqptr_sem);
+out:
+       for (cnt = 0; cnt < MAXQUOTAS; cnt++)
+               if (got_lock[cnt]) {
+                       oinfo = sb_dqinfo(sb, cnt)->dqi_priv;
+                       ocfs2_unlock_global_qf(oinfo, 0);
+               }
+       /* In case we bailed out because we had to do expensive locking
+        * do it now... */
+       if (exclusive)
+               status = ocfs2_dquot_drop_slow(inode);
+       mlog_exit(status);
+       return status;
+}
+
+static struct dquot *ocfs2_alloc_dquot(struct super_block *sb, int type)
+{
+       struct ocfs2_dquot *dquot =
+                               kmem_cache_zalloc(ocfs2_dquot_cachep, GFP_NOFS);
+
+       if (!dquot)
+               return NULL;
+       return &dquot->dq_dquot;
+}
+
+static void ocfs2_destroy_dquot(struct dquot *dquot)
+{
+       kmem_cache_free(ocfs2_dquot_cachep, dquot);
+}
+
+struct dquot_operations ocfs2_quota_operations = {
+       .initialize     = ocfs2_dquot_initialize,
+       .drop           = ocfs2_dquot_drop,
+       .alloc_space    = dquot_alloc_space,
+       .alloc_inode    = dquot_alloc_inode,
+       .free_space     = dquot_free_space,
+       .free_inode     = dquot_free_inode,
+       .transfer       = dquot_transfer,
+       .write_dquot    = ocfs2_write_dquot,
+       .acquire_dquot  = ocfs2_acquire_dquot,
+       .release_dquot  = ocfs2_release_dquot,
+       .mark_dirty     = ocfs2_mark_dquot_dirty,
+       .write_info     = ocfs2_write_info,
+       .alloc_dquot    = ocfs2_alloc_dquot,
+       .destroy_dquot  = ocfs2_destroy_dquot,
+};
+
+int ocfs2_quota_setup(void)
+{
+       ocfs2_quota_wq = create_workqueue("o2quot");
+       if (!ocfs2_quota_wq)
+               return -ENOMEM;
+       return 0;
+}
+
+void ocfs2_quota_shutdown(void)
+{
+       if (ocfs2_quota_wq) {
+               flush_workqueue(ocfs2_quota_wq);
+               destroy_workqueue(ocfs2_quota_wq);
+               ocfs2_quota_wq = NULL;
+       }
+}
diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c
new file mode 100644 (file)
index 0000000..07deec5
--- /dev/null
@@ -0,0 +1,1253 @@
+/*
+ *  Implementation of operations over local quota file
+ */
+
+#include <linux/fs.h>
+#include <linux/quota.h>
+#include <linux/quotaops.h>
+#include <linux/module.h>
+
+#define MLOG_MASK_PREFIX ML_QUOTA
+#include <cluster/masklog.h>
+
+#include "ocfs2_fs.h"
+#include "ocfs2.h"
+#include "inode.h"
+#include "alloc.h"
+#include "file.h"
+#include "buffer_head_io.h"
+#include "journal.h"
+#include "sysfile.h"
+#include "dlmglue.h"
+#include "quota.h"
+
+/* Number of local quota structures per block */
+static inline unsigned int ol_quota_entries_per_block(struct super_block *sb)
+{
+       return ((sb->s_blocksize - OCFS2_QBLK_RESERVED_SPACE) /
+               sizeof(struct ocfs2_local_disk_dqblk));
+}
+
+/* Number of blocks with entries in one chunk */
+static inline unsigned int ol_chunk_blocks(struct super_block *sb)
+{
+       return ((sb->s_blocksize - sizeof(struct ocfs2_local_disk_chunk) -
+                OCFS2_QBLK_RESERVED_SPACE) << 3) /
+              ol_quota_entries_per_block(sb);
+}
+
+/* Number of entries in a chunk bitmap */
+static unsigned int ol_chunk_entries(struct super_block *sb)
+{
+       return ol_chunk_blocks(sb) * ol_quota_entries_per_block(sb);
+}
+
+/* Offset of the chunk in quota file */
+static unsigned int ol_quota_chunk_block(struct super_block *sb, int c)
+{
+       /* 1 block for local quota file info, 1 block per chunk for chunk info */
+       return 1 + (ol_chunk_blocks(sb) + 1) * c;
+}
+
+static unsigned int ol_dqblk_block(struct super_block *sb, int c, int off)
+{
+       int epb = ol_quota_entries_per_block(sb);
+
+       return ol_quota_chunk_block(sb, c) + 1 + off / epb;
+}
+
+static unsigned int ol_dqblk_block_off(struct super_block *sb, int c, int off)
+{
+       int epb = ol_quota_entries_per_block(sb);
+
+       return (off % epb) * sizeof(struct ocfs2_local_disk_dqblk);
+}
+
+/* Offset of the dquot structure in the quota file */
+static loff_t ol_dqblk_off(struct super_block *sb, int c, int off)
+{
+       return (ol_dqblk_block(sb, c, off) << sb->s_blocksize_bits) +
+              ol_dqblk_block_off(sb, c, off);
+}
+
+/* Compute block number from given offset */
+static inline unsigned int ol_dqblk_file_block(struct super_block *sb, loff_t off)
+{
+       return off >> sb->s_blocksize_bits;
+}
+
+static inline unsigned int ol_dqblk_block_offset(struct super_block *sb, loff_t off)
+{
+       return off & ((1 << sb->s_blocksize_bits) - 1);
+}
+
+/* Compute offset in the chunk of a structure with the given offset */
+static int ol_dqblk_chunk_off(struct super_block *sb, int c, loff_t off)
+{
+       int epb = ol_quota_entries_per_block(sb);
+
+       return ((off >> sb->s_blocksize_bits) -
+                       ol_quota_chunk_block(sb, c) - 1) * epb
+              + ((unsigned int)(off & ((1 << sb->s_blocksize_bits) - 1))) /
+                sizeof(struct ocfs2_local_disk_dqblk);
+}
+
+/* Write bufferhead into the fs */
+static int ocfs2_modify_bh(struct inode *inode, struct buffer_head *bh,
+               void (*modify)(struct buffer_head *, void *), void *private)
+{
+       struct super_block *sb = inode->i_sb;
+       handle_t *handle;
+       int status;
+
+       handle = ocfs2_start_trans(OCFS2_SB(sb), 1);
+       if (IS_ERR(handle)) {
+               status = PTR_ERR(handle);
+               mlog_errno(status);
+               return status;
+       }
+       status = ocfs2_journal_access_dq(handle, inode, bh,
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
+       if (status < 0) {
+               mlog_errno(status);
+               ocfs2_commit_trans(OCFS2_SB(sb), handle);
+               return status;
+       }
+       lock_buffer(bh);
+       modify(bh, private);
+       unlock_buffer(bh);
+       status = ocfs2_journal_dirty(handle, bh);
+       if (status < 0) {
+               mlog_errno(status);
+               ocfs2_commit_trans(OCFS2_SB(sb), handle);
+               return status;
+       }
+       status = ocfs2_commit_trans(OCFS2_SB(sb), handle);
+       if (status < 0) {
+               mlog_errno(status);
+               return status;
+       }
+       return 0;
+}
+
+/* Check whether we understand format of quota files */
+static int ocfs2_local_check_quota_file(struct super_block *sb, int type)
+{
+       unsigned int lmagics[MAXQUOTAS] = OCFS2_LOCAL_QMAGICS;
+       unsigned int lversions[MAXQUOTAS] = OCFS2_LOCAL_QVERSIONS;
+       unsigned int gmagics[MAXQUOTAS] = OCFS2_GLOBAL_QMAGICS;
+       unsigned int gversions[MAXQUOTAS] = OCFS2_GLOBAL_QVERSIONS;
+       unsigned int ino[MAXQUOTAS] = { USER_QUOTA_SYSTEM_INODE,
+                                       GROUP_QUOTA_SYSTEM_INODE };
+       struct buffer_head *bh = NULL;
+       struct inode *linode = sb_dqopt(sb)->files[type];
+       struct inode *ginode = NULL;
+       struct ocfs2_disk_dqheader *dqhead;
+       int status, ret = 0;
+
+       /* First check whether we understand local quota file */
+       status = ocfs2_read_quota_block(linode, 0, &bh);
+       if (status) {
+               mlog_errno(status);
+               mlog(ML_ERROR, "failed to read quota file header (type=%d)\n",
+                       type);
+               goto out_err;
+       }
+       dqhead = (struct ocfs2_disk_dqheader *)(bh->b_data);
+       if (le32_to_cpu(dqhead->dqh_magic) != lmagics[type]) {
+               mlog(ML_ERROR, "quota file magic does not match (%u != %u),"
+                       " type=%d\n", le32_to_cpu(dqhead->dqh_magic),
+                       lmagics[type], type);
+               goto out_err;
+       }
+       if (le32_to_cpu(dqhead->dqh_version) != lversions[type]) {
+               mlog(ML_ERROR, "quota file version does not match (%u != %u),"
+                       " type=%d\n", le32_to_cpu(dqhead->dqh_version),
+                       lversions[type], type);
+               goto out_err;
+       }
+       brelse(bh);
+       bh = NULL;
+
+       /* Next check whether we understand global quota file */
+       ginode = ocfs2_get_system_file_inode(OCFS2_SB(sb), ino[type],
+                                               OCFS2_INVALID_SLOT);
+       if (!ginode) {
+               mlog(ML_ERROR, "cannot get global quota file inode "
+                               "(type=%d)\n", type);
+               goto out_err;
+       }
+       /* Since the header is read only, we don't care about locking */
+       status = ocfs2_read_quota_block(ginode, 0, &bh);
+       if (status) {
+               mlog_errno(status);
+               mlog(ML_ERROR, "failed to read global quota file header "
+                               "(type=%d)\n", type);
+               goto out_err;
+       }
+       dqhead = (struct ocfs2_disk_dqheader *)(bh->b_data);
+       if (le32_to_cpu(dqhead->dqh_magic) != gmagics[type]) {
+               mlog(ML_ERROR, "global quota file magic does not match "
+                       "(%u != %u), type=%d\n",
+                       le32_to_cpu(dqhead->dqh_magic), gmagics[type], type);
+               goto out_err;
+       }
+       if (le32_to_cpu(dqhead->dqh_version) != gversions[type]) {
+               mlog(ML_ERROR, "global quota file version does not match "
+                       "(%u != %u), type=%d\n",
+                       le32_to_cpu(dqhead->dqh_version), gversions[type],
+                       type);
+               goto out_err;
+       }
+
+       ret = 1;
+out_err:
+       brelse(bh);
+       iput(ginode);
+       return ret;
+}
+
+/* Release given list of quota file chunks */
+static void ocfs2_release_local_quota_bitmaps(struct list_head *head)
+{
+       struct ocfs2_quota_chunk *pos, *next;
+
+       list_for_each_entry_safe(pos, next, head, qc_chunk) {
+               list_del(&pos->qc_chunk);
+               brelse(pos->qc_headerbh);
+               kmem_cache_free(ocfs2_qf_chunk_cachep, pos);
+       }
+}
+
+/* Load quota bitmaps into memory */
+static int ocfs2_load_local_quota_bitmaps(struct inode *inode,
+                       struct ocfs2_local_disk_dqinfo *ldinfo,
+                       struct list_head *head)
+{
+       struct ocfs2_quota_chunk *newchunk;
+       int i, status;
+
+       INIT_LIST_HEAD(head);
+       for (i = 0; i < le32_to_cpu(ldinfo->dqi_chunks); i++) {
+               newchunk = kmem_cache_alloc(ocfs2_qf_chunk_cachep, GFP_NOFS);
+               if (!newchunk) {
+                       ocfs2_release_local_quota_bitmaps(head);
+                       return -ENOMEM;
+               }
+               newchunk->qc_num = i;
+               newchunk->qc_headerbh = NULL;
+               status = ocfs2_read_quota_block(inode,
+                               ol_quota_chunk_block(inode->i_sb, i),
+                               &newchunk->qc_headerbh);
+               if (status) {
+                       mlog_errno(status);
+                       kmem_cache_free(ocfs2_qf_chunk_cachep, newchunk);
+                       ocfs2_release_local_quota_bitmaps(head);
+                       return status;
+               }
+               list_add_tail(&newchunk->qc_chunk, head);
+       }
+       return 0;
+}
+
+static void olq_update_info(struct buffer_head *bh, void *private)
+{
+       struct mem_dqinfo *info = private;
+       struct ocfs2_mem_dqinfo *oinfo = info->dqi_priv;
+       struct ocfs2_local_disk_dqinfo *ldinfo;
+
+       ldinfo = (struct ocfs2_local_disk_dqinfo *)(bh->b_data +
+                                               OCFS2_LOCAL_INFO_OFF);
+       spin_lock(&dq_data_lock);
+       ldinfo->dqi_flags = cpu_to_le32(info->dqi_flags & DQF_MASK);
+       ldinfo->dqi_chunks = cpu_to_le32(oinfo->dqi_chunks);
+       ldinfo->dqi_blocks = cpu_to_le32(oinfo->dqi_blocks);
+       spin_unlock(&dq_data_lock);
+}
+
+static int ocfs2_add_recovery_chunk(struct super_block *sb,
+                                   struct ocfs2_local_disk_chunk *dchunk,
+                                   int chunk,
+                                   struct list_head *head)
+{
+       struct ocfs2_recovery_chunk *rc;
+
+       rc = kmalloc(sizeof(struct ocfs2_recovery_chunk), GFP_NOFS);
+       if (!rc)
+               return -ENOMEM;
+       rc->rc_chunk = chunk;
+       rc->rc_bitmap = kmalloc(sb->s_blocksize, GFP_NOFS);
+       if (!rc->rc_bitmap) {
+               kfree(rc);
+               return -ENOMEM;
+       }
+       memcpy(rc->rc_bitmap, dchunk->dqc_bitmap,
+              (ol_chunk_entries(sb) + 7) >> 3);
+       list_add_tail(&rc->rc_list, head);
+       return 0;
+}
+
+static void free_recovery_list(struct list_head *head)
+{
+       struct ocfs2_recovery_chunk *next;
+       struct ocfs2_recovery_chunk *rchunk;
+
+       list_for_each_entry_safe(rchunk, next, head, rc_list) {
+               list_del(&rchunk->rc_list);
+               kfree(rchunk->rc_bitmap);
+               kfree(rchunk);
+       }
+}
+
+void ocfs2_free_quota_recovery(struct ocfs2_quota_recovery *rec)
+{
+       int type;
+
+       for (type = 0; type < MAXQUOTAS; type++)
+               free_recovery_list(&(rec->r_list[type]));
+       kfree(rec);
+}
+
+/* Load entries in our quota file we have to recover*/
+static int ocfs2_recovery_load_quota(struct inode *lqinode,
+                                    struct ocfs2_local_disk_dqinfo *ldinfo,
+                                    int type,
+                                    struct list_head *head)
+{
+       struct super_block *sb = lqinode->i_sb;
+       struct buffer_head *hbh;
+       struct ocfs2_local_disk_chunk *dchunk;
+       int i, chunks = le32_to_cpu(ldinfo->dqi_chunks);
+       int status = 0;
+
+       for (i = 0; i < chunks; i++) {
+               hbh = NULL;
+               status = ocfs2_read_quota_block(lqinode,
+                                               ol_quota_chunk_block(sb, i),
+                                               &hbh);
+               if (status) {
+                       mlog_errno(status);
+                       break;
+               }
+               dchunk = (struct ocfs2_local_disk_chunk *)hbh->b_data;
+               if (le32_to_cpu(dchunk->dqc_free) < ol_chunk_entries(sb))
+                       status = ocfs2_add_recovery_chunk(sb, dchunk, i, head);
+               brelse(hbh);
+               if (status < 0)
+                       break;
+       }
+       if (status < 0)
+               free_recovery_list(head);
+       return status;
+}
+
+static struct ocfs2_quota_recovery *ocfs2_alloc_quota_recovery(void)
+{
+       int type;
+       struct ocfs2_quota_recovery *rec;
+
+       rec = kmalloc(sizeof(struct ocfs2_quota_recovery), GFP_NOFS);
+       if (!rec)
+               return NULL;
+       for (type = 0; type < MAXQUOTAS; type++)
+               INIT_LIST_HEAD(&(rec->r_list[type]));
+       return rec;
+}
+
+/* Load information we need for quota recovery into memory */
+struct ocfs2_quota_recovery *ocfs2_begin_quota_recovery(
+                                               struct ocfs2_super *osb,
+                                               int slot_num)
+{
+       unsigned int feature[MAXQUOTAS] = { OCFS2_FEATURE_RO_COMPAT_USRQUOTA,
+                                           OCFS2_FEATURE_RO_COMPAT_GRPQUOTA};
+       unsigned int ino[MAXQUOTAS] = { LOCAL_USER_QUOTA_SYSTEM_INODE,
+                                       LOCAL_GROUP_QUOTA_SYSTEM_INODE };
+       struct super_block *sb = osb->sb;
+       struct ocfs2_local_disk_dqinfo *ldinfo;
+       struct inode *lqinode;
+       struct buffer_head *bh;
+       int type;
+       int status = 0;
+       struct ocfs2_quota_recovery *rec;
+
+       mlog(ML_NOTICE, "Beginning quota recovery in slot %u\n", slot_num);
+       rec = ocfs2_alloc_quota_recovery();
+       if (!rec)
+               return ERR_PTR(-ENOMEM);
+       /* First init... */
+
+       for (type = 0; type < MAXQUOTAS; type++) {
+               if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, feature[type]))
+                       continue;
+               /* At this point, journal of the slot is already replayed so
+                * we can trust metadata and data of the quota file */
+               lqinode = ocfs2_get_system_file_inode(osb, ino[type], slot_num);
+               if (!lqinode) {
+                       status = -ENOENT;
+                       goto out;
+               }
+               status = ocfs2_inode_lock_full(lqinode, NULL, 1,
+                                              OCFS2_META_LOCK_RECOVERY);
+               if (status < 0) {
+                       mlog_errno(status);
+                       goto out_put;
+               }
+               /* Now read local header */
+               bh = NULL;
+               status = ocfs2_read_quota_block(lqinode, 0, &bh);
+               if (status) {
+                       mlog_errno(status);
+                       mlog(ML_ERROR, "failed to read quota file info header "
+                               "(slot=%d type=%d)\n", slot_num, type);
+                       goto out_lock;
+               }
+               ldinfo = (struct ocfs2_local_disk_dqinfo *)(bh->b_data +
+                                                       OCFS2_LOCAL_INFO_OFF);
+               status = ocfs2_recovery_load_quota(lqinode, ldinfo, type,
+                                                  &rec->r_list[type]);
+               brelse(bh);
+out_lock:
+               ocfs2_inode_unlock(lqinode, 1);
+out_put:
+               iput(lqinode);
+               if (status < 0)
+                       break;
+       }
+out:
+       if (status < 0) {
+               ocfs2_free_quota_recovery(rec);
+               rec = ERR_PTR(status);
+       }
+       return rec;
+}
+
+/* Sync changes in local quota file into global quota file and
+ * reinitialize local quota file.
+ * The function expects local quota file to be already locked and
+ * dqonoff_mutex locked. */
+static int ocfs2_recover_local_quota_file(struct inode *lqinode,
+                                         int type,
+                                         struct ocfs2_quota_recovery *rec)
+{
+       struct super_block *sb = lqinode->i_sb;
+       struct ocfs2_mem_dqinfo *oinfo = sb_dqinfo(sb, type)->dqi_priv;
+       struct ocfs2_local_disk_chunk *dchunk;
+       struct ocfs2_local_disk_dqblk *dqblk;
+       struct dquot *dquot;
+       handle_t *handle;
+       struct buffer_head *hbh = NULL, *qbh = NULL;
+       int status = 0;
+       int bit, chunk;
+       struct ocfs2_recovery_chunk *rchunk, *next;
+       qsize_t spacechange, inodechange;
+
+       mlog_entry("ino=%lu type=%u", (unsigned long)lqinode->i_ino, type);
+
+       status = ocfs2_lock_global_qf(oinfo, 1);
+       if (status < 0)
+               goto out;
+
+       list_for_each_entry_safe(rchunk, next, &(rec->r_list[type]), rc_list) {
+               chunk = rchunk->rc_chunk;
+               hbh = NULL;
+               status = ocfs2_read_quota_block(lqinode,
+                                               ol_quota_chunk_block(sb, chunk),
+                                               &hbh);
+               if (status) {
+                       mlog_errno(status);
+                       break;
+               }
+               dchunk = (struct ocfs2_local_disk_chunk *)hbh->b_data;
+               for_each_bit(bit, rchunk->rc_bitmap, ol_chunk_entries(sb)) {
+                       qbh = NULL;
+                       status = ocfs2_read_quota_block(lqinode,
+                                               ol_dqblk_block(sb, chunk, bit),
+                                               &qbh);
+                       if (status) {
+                               mlog_errno(status);
+                               break;
+                       }
+                       dqblk = (struct ocfs2_local_disk_dqblk *)(qbh->b_data +
+                               ol_dqblk_block_off(sb, chunk, bit));
+                       dquot = dqget(sb, le64_to_cpu(dqblk->dqb_id), type);
+                       if (!dquot) {
+                               status = -EIO;
+                               mlog(ML_ERROR, "Failed to get quota structure "
+                                    "for id %u, type %d. Cannot finish quota "
+                                    "file recovery.\n",
+                                    (unsigned)le64_to_cpu(dqblk->dqb_id),
+                                    type);
+                               goto out_put_bh;
+                       }
+                       handle = ocfs2_start_trans(OCFS2_SB(sb),
+                                                  OCFS2_QSYNC_CREDITS);
+                       if (IS_ERR(handle)) {
+                               status = PTR_ERR(handle);
+                               mlog_errno(status);
+                               goto out_put_dquot;
+                       }
+                       mutex_lock(&sb_dqopt(sb)->dqio_mutex);
+                       spin_lock(&dq_data_lock);
+                       /* Add usage from quota entry into quota changes
+                        * of our node. Auxiliary variables are important
+                        * due to signedness */
+                       spacechange = le64_to_cpu(dqblk->dqb_spacemod);
+                       inodechange = le64_to_cpu(dqblk->dqb_inodemod);
+                       dquot->dq_dqb.dqb_curspace += spacechange;
+                       dquot->dq_dqb.dqb_curinodes += inodechange;
+                       spin_unlock(&dq_data_lock);
+                       /* We want to drop reference held by the crashed
+                        * node. Since we have our own reference we know
+                        * global structure actually won't be freed. */
+                       status = ocfs2_global_release_dquot(dquot);
+                       if (status < 0) {
+                               mlog_errno(status);
+                               goto out_commit;
+                       }
+                       /* Release local quota file entry */
+                       status = ocfs2_journal_access_dq(handle, lqinode,
+                                       qbh, OCFS2_JOURNAL_ACCESS_WRITE);
+                       if (status < 0) {
+                               mlog_errno(status);
+                               goto out_commit;
+                       }
+                       lock_buffer(qbh);
+                       WARN_ON(!ocfs2_test_bit(bit, dchunk->dqc_bitmap));
+                       ocfs2_clear_bit(bit, dchunk->dqc_bitmap);
+                       le32_add_cpu(&dchunk->dqc_free, 1);
+                       unlock_buffer(qbh);
+                       status = ocfs2_journal_dirty(handle, qbh);
+                       if (status < 0)
+                               mlog_errno(status);
+out_commit:
+                       mutex_unlock(&sb_dqopt(sb)->dqio_mutex);
+                       ocfs2_commit_trans(OCFS2_SB(sb), handle);
+out_put_dquot:
+                       dqput(dquot);
+out_put_bh:
+                       brelse(qbh);
+                       if (status < 0)
+                               break;
+               }
+               brelse(hbh);
+               list_del(&rchunk->rc_list);
+               kfree(rchunk->rc_bitmap);
+               kfree(rchunk);
+               if (status < 0)
+                       break;
+       }
+       ocfs2_unlock_global_qf(oinfo, 1);
+out:
+       if (status < 0)
+               free_recovery_list(&(rec->r_list[type]));
+       mlog_exit(status);
+       return status;
+}
+
+/* Recover local quota files for given node different from us */
+int ocfs2_finish_quota_recovery(struct ocfs2_super *osb,
+                               struct ocfs2_quota_recovery *rec,
+                               int slot_num)
+{
+       unsigned int ino[MAXQUOTAS] = { LOCAL_USER_QUOTA_SYSTEM_INODE,
+                                       LOCAL_GROUP_QUOTA_SYSTEM_INODE };
+       struct super_block *sb = osb->sb;
+       struct ocfs2_local_disk_dqinfo *ldinfo;
+       struct buffer_head *bh;
+       handle_t *handle;
+       int type;
+       int status = 0;
+       struct inode *lqinode;
+       unsigned int flags;
+
+       mlog(ML_NOTICE, "Finishing quota recovery in slot %u\n", slot_num);
+       mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
+       for (type = 0; type < MAXQUOTAS; type++) {
+               if (list_empty(&(rec->r_list[type])))
+                       continue;
+               mlog(0, "Recovering quota in slot %d\n", slot_num);
+               lqinode = ocfs2_get_system_file_inode(osb, ino[type], slot_num);
+               if (!lqinode) {
+                       status = -ENOENT;
+                       goto out;
+               }
+               status = ocfs2_inode_lock_full(lqinode, NULL, 1,
+                                                      OCFS2_META_LOCK_NOQUEUE);
+               /* Someone else is holding the lock? Then he must be
+                * doing the recovery. Just skip the file... */
+               if (status == -EAGAIN) {
+                       mlog(ML_NOTICE, "skipping quota recovery for slot %d "
+                            "because quota file is locked.\n", slot_num);
+                       status = 0;
+                       goto out_put;
+               } else if (status < 0) {
+                       mlog_errno(status);
+                       goto out_put;
+               }
+               /* Now read local header */
+               bh = NULL;
+               status = ocfs2_read_quota_block(lqinode, 0, &bh);
+               if (status) {
+                       mlog_errno(status);
+                       mlog(ML_ERROR, "failed to read quota file info header "
+                               "(slot=%d type=%d)\n", slot_num, type);
+                       goto out_lock;
+               }
+               ldinfo = (struct ocfs2_local_disk_dqinfo *)(bh->b_data +
+                                                       OCFS2_LOCAL_INFO_OFF);
+               /* Is recovery still needed? */
+               flags = le32_to_cpu(ldinfo->dqi_flags);
+               if (!(flags & OLQF_CLEAN))
+                       status = ocfs2_recover_local_quota_file(lqinode,
+                                                               type,
+                                                               rec);
+               /* We don't want to mark file as clean when it is actually
+                * active */
+               if (slot_num == osb->slot_num)
+                       goto out_bh;
+               /* Mark quota file as clean if we are recovering quota file of
+                * some other node. */
+               handle = ocfs2_start_trans(osb, 1);
+               if (IS_ERR(handle)) {
+                       status = PTR_ERR(handle);
+                       mlog_errno(status);
+                       goto out_bh;
+               }
+               status = ocfs2_journal_access_dq(handle, lqinode, bh,
+                                                OCFS2_JOURNAL_ACCESS_WRITE);
+               if (status < 0) {
+                       mlog_errno(status);
+                       goto out_trans;
+               }
+               lock_buffer(bh);
+               ldinfo->dqi_flags = cpu_to_le32(flags | OLQF_CLEAN);
+               unlock_buffer(bh);
+               status = ocfs2_journal_dirty(handle, bh);
+               if (status < 0)
+                       mlog_errno(status);
+out_trans:
+               ocfs2_commit_trans(osb, handle);
+out_bh:
+               brelse(bh);
+out_lock:
+               ocfs2_inode_unlock(lqinode, 1);
+out_put:
+               iput(lqinode);
+               if (status < 0)
+                       break;
+       }
+out:
+       mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
+       kfree(rec);
+       return status;
+}
+
+/* Read information header from quota file */
+static int ocfs2_local_read_info(struct super_block *sb, int type)
+{
+       struct ocfs2_local_disk_dqinfo *ldinfo;
+       struct mem_dqinfo *info = sb_dqinfo(sb, type);
+       struct ocfs2_mem_dqinfo *oinfo;
+       struct inode *lqinode = sb_dqopt(sb)->files[type];
+       int status;
+       struct buffer_head *bh = NULL;
+       struct ocfs2_quota_recovery *rec;
+       int locked = 0;
+
+       info->dqi_maxblimit = 0x7fffffffffffffffLL;
+       info->dqi_maxilimit = 0x7fffffffffffffffLL;
+       oinfo = kmalloc(sizeof(struct ocfs2_mem_dqinfo), GFP_NOFS);
+       if (!oinfo) {
+               mlog(ML_ERROR, "failed to allocate memory for ocfs2 quota"
+                              " info.");
+               goto out_err;
+       }
+       info->dqi_priv = oinfo;
+       oinfo->dqi_type = type;
+       INIT_LIST_HEAD(&oinfo->dqi_chunk);
+       oinfo->dqi_rec = NULL;
+       oinfo->dqi_lqi_bh = NULL;
+       oinfo->dqi_ibh = NULL;
+
+       status = ocfs2_global_read_info(sb, type);
+       if (status < 0)
+               goto out_err;
+
+       status = ocfs2_inode_lock(lqinode, &oinfo->dqi_lqi_bh, 1);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out_err;
+       }
+       locked = 1;
+
+       /* Now read local header */
+       status = ocfs2_read_quota_block(lqinode, 0, &bh);
+       if (status) {
+               mlog_errno(status);
+               mlog(ML_ERROR, "failed to read quota file info header "
+                       "(type=%d)\n", type);
+               goto out_err;
+       }
+       ldinfo = (struct ocfs2_local_disk_dqinfo *)(bh->b_data +
+                                               OCFS2_LOCAL_INFO_OFF);
+       info->dqi_flags = le32_to_cpu(ldinfo->dqi_flags);
+       oinfo->dqi_chunks = le32_to_cpu(ldinfo->dqi_chunks);
+       oinfo->dqi_blocks = le32_to_cpu(ldinfo->dqi_blocks);
+       oinfo->dqi_ibh = bh;
+
+       /* We crashed when using local quota file? */
+       if (!(info->dqi_flags & OLQF_CLEAN)) {
+               rec = OCFS2_SB(sb)->quota_rec;
+               if (!rec) {
+                       rec = ocfs2_alloc_quota_recovery();
+                       if (!rec) {
+                               status = -ENOMEM;
+                               mlog_errno(status);
+                               goto out_err;
+                       }
+                       OCFS2_SB(sb)->quota_rec = rec;
+               }
+
+               status = ocfs2_recovery_load_quota(lqinode, ldinfo, type,
+                                                   &rec->r_list[type]);
+               if (status < 0) {
+                       mlog_errno(status);
+                       goto out_err;
+               }
+       }
+
+       status = ocfs2_load_local_quota_bitmaps(lqinode,
+                                               ldinfo,
+                                               &oinfo->dqi_chunk);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out_err;
+       }
+
+       /* Now mark quota file as used */
+       info->dqi_flags &= ~OLQF_CLEAN;
+       status = ocfs2_modify_bh(lqinode, bh, olq_update_info, info);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out_err;
+       }
+
+       return 0;
+out_err:
+       if (oinfo) {
+               iput(oinfo->dqi_gqinode);
+               ocfs2_simple_drop_lockres(OCFS2_SB(sb), &oinfo->dqi_gqlock);
+               ocfs2_lock_res_free(&oinfo->dqi_gqlock);
+               brelse(oinfo->dqi_lqi_bh);
+               if (locked)
+                       ocfs2_inode_unlock(lqinode, 1);
+               ocfs2_release_local_quota_bitmaps(&oinfo->dqi_chunk);
+               kfree(oinfo);
+       }
+       brelse(bh);
+       return -1;
+}
+
+/* Write local info to quota file */
+static int ocfs2_local_write_info(struct super_block *sb, int type)
+{
+       struct mem_dqinfo *info = sb_dqinfo(sb, type);
+       struct buffer_head *bh = ((struct ocfs2_mem_dqinfo *)info->dqi_priv)
+                                               ->dqi_ibh;
+       int status;
+
+       status = ocfs2_modify_bh(sb_dqopt(sb)->files[type], bh, olq_update_info,
+                                info);
+       if (status < 0) {
+               mlog_errno(status);
+               return -1;
+       }
+
+       return 0;
+}
+
+/* Release info from memory */
+static int ocfs2_local_free_info(struct super_block *sb, int type)
+{
+       struct mem_dqinfo *info = sb_dqinfo(sb, type);
+       struct ocfs2_mem_dqinfo *oinfo = info->dqi_priv;
+       struct ocfs2_quota_chunk *chunk;
+       struct ocfs2_local_disk_chunk *dchunk;
+       int mark_clean = 1, len;
+       int status;
+
+       /* At this point we know there are no more dquots and thus
+        * even if there's some sync in the pdflush queue, it won't
+        * find any dquots and return without doing anything */
+       cancel_delayed_work_sync(&oinfo->dqi_sync_work);
+       iput(oinfo->dqi_gqinode);
+       ocfs2_simple_drop_lockres(OCFS2_SB(sb), &oinfo->dqi_gqlock);
+       ocfs2_lock_res_free(&oinfo->dqi_gqlock);
+       list_for_each_entry(chunk, &oinfo->dqi_chunk, qc_chunk) {
+               dchunk = (struct ocfs2_local_disk_chunk *)
+                                       (chunk->qc_headerbh->b_data);
+               if (chunk->qc_num < oinfo->dqi_chunks - 1) {
+                       len = ol_chunk_entries(sb);
+               } else {
+                       len = (oinfo->dqi_blocks -
+                              ol_quota_chunk_block(sb, chunk->qc_num) - 1)
+                             * ol_quota_entries_per_block(sb);
+               }
+               /* Not all entries free? Bug! */
+               if (le32_to_cpu(dchunk->dqc_free) != len) {
+                       mlog(ML_ERROR, "releasing quota file with used "
+                                       "entries (type=%d)\n", type);
+                       mark_clean = 0;
+               }
+       }
+       ocfs2_release_local_quota_bitmaps(&oinfo->dqi_chunk);
+
+       /* dqonoff_mutex protects us against racing with recovery thread... */
+       if (oinfo->dqi_rec) {
+               ocfs2_free_quota_recovery(oinfo->dqi_rec);
+               mark_clean = 0;
+       }
+
+       if (!mark_clean)
+               goto out;
+
+       /* Mark local file as clean */
+       info->dqi_flags |= OLQF_CLEAN;
+       status = ocfs2_modify_bh(sb_dqopt(sb)->files[type],
+                                oinfo->dqi_ibh,
+                                olq_update_info,
+                                info);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out;
+       }
+
+out:
+       ocfs2_inode_unlock(sb_dqopt(sb)->files[type], 1);
+       brelse(oinfo->dqi_ibh);
+       brelse(oinfo->dqi_lqi_bh);
+       kfree(oinfo);
+       return 0;
+}
+
+static void olq_set_dquot(struct buffer_head *bh, void *private)
+{
+       struct ocfs2_dquot *od = private;
+       struct ocfs2_local_disk_dqblk *dqblk;
+       struct super_block *sb = od->dq_dquot.dq_sb;
+
+       dqblk = (struct ocfs2_local_disk_dqblk *)(bh->b_data
+               + ol_dqblk_block_offset(sb, od->dq_local_off));
+
+       dqblk->dqb_id = cpu_to_le64(od->dq_dquot.dq_id);
+       spin_lock(&dq_data_lock);
+       dqblk->dqb_spacemod = cpu_to_le64(od->dq_dquot.dq_dqb.dqb_curspace -
+                                         od->dq_origspace);
+       dqblk->dqb_inodemod = cpu_to_le64(od->dq_dquot.dq_dqb.dqb_curinodes -
+                                         od->dq_originodes);
+       spin_unlock(&dq_data_lock);
+       mlog(0, "Writing local dquot %u space %lld inodes %lld\n",
+            od->dq_dquot.dq_id, (long long)le64_to_cpu(dqblk->dqb_spacemod),
+            (long long)le64_to_cpu(dqblk->dqb_inodemod));
+}
+
+/* Write dquot to local quota file */
+static int ocfs2_local_write_dquot(struct dquot *dquot)
+{
+       struct super_block *sb = dquot->dq_sb;
+       struct ocfs2_dquot *od = OCFS2_DQUOT(dquot);
+       struct buffer_head *bh = NULL;
+       int status;
+
+       status = ocfs2_read_quota_block(sb_dqopt(sb)->files[dquot->dq_type],
+                                   ol_dqblk_file_block(sb, od->dq_local_off),
+                                   &bh);
+       if (status) {
+               mlog_errno(status);
+               goto out;
+       }
+       status = ocfs2_modify_bh(sb_dqopt(sb)->files[dquot->dq_type], bh,
+                                olq_set_dquot, od);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out;
+       }
+out:
+       brelse(bh);
+       return status;
+}
+
+/* Find free entry in local quota file */
+static struct ocfs2_quota_chunk *ocfs2_find_free_entry(struct super_block *sb,
+                                                      int type,
+                                                      int *offset)
+{
+       struct mem_dqinfo *info = sb_dqinfo(sb, type);
+       struct ocfs2_mem_dqinfo *oinfo = info->dqi_priv;
+       struct ocfs2_quota_chunk *chunk;
+       struct ocfs2_local_disk_chunk *dchunk;
+       int found = 0, len;
+
+       list_for_each_entry(chunk, &oinfo->dqi_chunk, qc_chunk) {
+               dchunk = (struct ocfs2_local_disk_chunk *)
+                                               chunk->qc_headerbh->b_data;
+               if (le32_to_cpu(dchunk->dqc_free) > 0) {
+                       found = 1;
+                       break;
+               }
+       }
+       if (!found)
+               return NULL;
+
+       if (chunk->qc_num < oinfo->dqi_chunks - 1) {
+               len = ol_chunk_entries(sb);
+       } else {
+               len = (oinfo->dqi_blocks -
+                      ol_quota_chunk_block(sb, chunk->qc_num) - 1)
+                     * ol_quota_entries_per_block(sb);
+       }
+
+       found = ocfs2_find_next_zero_bit(dchunk->dqc_bitmap, len, 0);
+       /* We failed? */
+       if (found == len) {
+               mlog(ML_ERROR, "Did not find empty entry in chunk %d with %u"
+                    " entries free (type=%d)\n", chunk->qc_num,
+                    le32_to_cpu(dchunk->dqc_free), type);
+               return ERR_PTR(-EIO);
+       }
+       *offset = found;
+       return chunk;
+}
+
+/* Add new chunk to the local quota file */
+static struct ocfs2_quota_chunk *ocfs2_local_quota_add_chunk(
+                                                       struct super_block *sb,
+                                                       int type,
+                                                       int *offset)
+{
+       struct mem_dqinfo *info = sb_dqinfo(sb, type);
+       struct ocfs2_mem_dqinfo *oinfo = info->dqi_priv;
+       struct inode *lqinode = sb_dqopt(sb)->files[type];
+       struct ocfs2_quota_chunk *chunk = NULL;
+       struct ocfs2_local_disk_chunk *dchunk;
+       int status;
+       handle_t *handle;
+       struct buffer_head *bh = NULL;
+       u64 p_blkno;
+
+       /* We are protected by dqio_sem so no locking needed */
+       status = ocfs2_extend_no_holes(lqinode,
+                                      lqinode->i_size + 2 * sb->s_blocksize,
+                                      lqinode->i_size);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out;
+       }
+       status = ocfs2_simple_size_update(lqinode, oinfo->dqi_lqi_bh,
+                                         lqinode->i_size + 2 * sb->s_blocksize);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out;
+       }
+
+       chunk = kmem_cache_alloc(ocfs2_qf_chunk_cachep, GFP_NOFS);
+       if (!chunk) {
+               status = -ENOMEM;
+               mlog_errno(status);
+               goto out;
+       }
+
+       down_read(&OCFS2_I(lqinode)->ip_alloc_sem);
+       status = ocfs2_extent_map_get_blocks(lqinode, oinfo->dqi_blocks,
+                                            &p_blkno, NULL, NULL);
+       up_read(&OCFS2_I(lqinode)->ip_alloc_sem);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out;
+       }
+       bh = sb_getblk(sb, p_blkno);
+       if (!bh) {
+               status = -ENOMEM;
+               mlog_errno(status);
+               goto out;
+       }
+       dchunk = (struct ocfs2_local_disk_chunk *)bh->b_data;
+
+       handle = ocfs2_start_trans(OCFS2_SB(sb), 2);
+       if (IS_ERR(handle)) {
+               status = PTR_ERR(handle);
+               mlog_errno(status);
+               goto out;
+       }
+
+       status = ocfs2_journal_access_dq(handle, lqinode, bh,
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out_trans;
+       }
+       lock_buffer(bh);
+       dchunk->dqc_free = cpu_to_le32(ol_quota_entries_per_block(sb));
+       memset(dchunk->dqc_bitmap, 0,
+              sb->s_blocksize - sizeof(struct ocfs2_local_disk_chunk) -
+              OCFS2_QBLK_RESERVED_SPACE);
+       set_buffer_uptodate(bh);
+       unlock_buffer(bh);
+       status = ocfs2_journal_dirty(handle, bh);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out_trans;
+       }
+
+       oinfo->dqi_blocks += 2;
+       oinfo->dqi_chunks++;
+       status = ocfs2_local_write_info(sb, type);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out_trans;
+       }
+       status = ocfs2_commit_trans(OCFS2_SB(sb), handle);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out;
+       }
+
+       list_add_tail(&chunk->qc_chunk, &oinfo->dqi_chunk);
+       chunk->qc_num = list_entry(chunk->qc_chunk.prev,
+                                  struct ocfs2_quota_chunk,
+                                  qc_chunk)->qc_num + 1;
+       chunk->qc_headerbh = bh;
+       *offset = 0;
+       return chunk;
+out_trans:
+       ocfs2_commit_trans(OCFS2_SB(sb), handle);
+out:
+       brelse(bh);
+       kmem_cache_free(ocfs2_qf_chunk_cachep, chunk);
+       return ERR_PTR(status);
+}
+
+/* Find free entry in local quota file */
+static struct ocfs2_quota_chunk *ocfs2_extend_local_quota_file(
+                                                      struct super_block *sb,
+                                                      int type,
+                                                      int *offset)
+{
+       struct mem_dqinfo *info = sb_dqinfo(sb, type);
+       struct ocfs2_mem_dqinfo *oinfo = info->dqi_priv;
+       struct ocfs2_quota_chunk *chunk;
+       struct inode *lqinode = sb_dqopt(sb)->files[type];
+       struct ocfs2_local_disk_chunk *dchunk;
+       int epb = ol_quota_entries_per_block(sb);
+       unsigned int chunk_blocks;
+       int status;
+       handle_t *handle;
+
+       if (list_empty(&oinfo->dqi_chunk))
+               return ocfs2_local_quota_add_chunk(sb, type, offset);
+       /* Is the last chunk full? */
+       chunk = list_entry(oinfo->dqi_chunk.prev,
+                       struct ocfs2_quota_chunk, qc_chunk);
+       chunk_blocks = oinfo->dqi_blocks -
+                       ol_quota_chunk_block(sb, chunk->qc_num) - 1;
+       if (ol_chunk_blocks(sb) == chunk_blocks)
+               return ocfs2_local_quota_add_chunk(sb, type, offset);
+
+       /* We are protected by dqio_sem so no locking needed */
+       status = ocfs2_extend_no_holes(lqinode,
+                                      lqinode->i_size + sb->s_blocksize,
+                                      lqinode->i_size);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out;
+       }
+       status = ocfs2_simple_size_update(lqinode, oinfo->dqi_lqi_bh,
+                                         lqinode->i_size + sb->s_blocksize);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out;
+       }
+       handle = ocfs2_start_trans(OCFS2_SB(sb), 2);
+       if (IS_ERR(handle)) {
+               status = PTR_ERR(handle);
+               mlog_errno(status);
+               goto out;
+       }
+       status = ocfs2_journal_access_dq(handle, lqinode, chunk->qc_headerbh,
+                                OCFS2_JOURNAL_ACCESS_WRITE);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out_trans;
+       }
+
+       dchunk = (struct ocfs2_local_disk_chunk *)chunk->qc_headerbh->b_data;
+       lock_buffer(chunk->qc_headerbh);
+       le32_add_cpu(&dchunk->dqc_free, ol_quota_entries_per_block(sb));
+       unlock_buffer(chunk->qc_headerbh);
+       status = ocfs2_journal_dirty(handle, chunk->qc_headerbh);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out_trans;
+       }
+       oinfo->dqi_blocks++;
+       status = ocfs2_local_write_info(sb, type);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out_trans;
+       }
+
+       status = ocfs2_commit_trans(OCFS2_SB(sb), handle);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out;
+       }
+       *offset = chunk_blocks * epb;
+       return chunk;
+out_trans:
+       ocfs2_commit_trans(OCFS2_SB(sb), handle);
+out:
+       return ERR_PTR(status);
+}
+
+static void olq_alloc_dquot(struct buffer_head *bh, void *private)
+{
+       int *offset = private;
+       struct ocfs2_local_disk_chunk *dchunk;
+
+       dchunk = (struct ocfs2_local_disk_chunk *)bh->b_data;
+       ocfs2_set_bit(*offset, dchunk->dqc_bitmap);
+       le32_add_cpu(&dchunk->dqc_free, -1);
+}
+
+/* Create dquot in the local file for given id */
+static int ocfs2_create_local_dquot(struct dquot *dquot)
+{
+       struct super_block *sb = dquot->dq_sb;
+       int type = dquot->dq_type;
+       struct inode *lqinode = sb_dqopt(sb)->files[type];
+       struct ocfs2_quota_chunk *chunk;
+       struct ocfs2_dquot *od = OCFS2_DQUOT(dquot);
+       int offset;
+       int status;
+
+       chunk = ocfs2_find_free_entry(sb, type, &offset);
+       if (!chunk) {
+               chunk = ocfs2_extend_local_quota_file(sb, type, &offset);
+               if (IS_ERR(chunk))
+                       return PTR_ERR(chunk);
+       } else if (IS_ERR(chunk)) {
+               return PTR_ERR(chunk);
+       }
+       od->dq_local_off = ol_dqblk_off(sb, chunk->qc_num, offset);
+       od->dq_chunk = chunk;
+
+       /* Initialize dquot structure on disk */
+       status = ocfs2_local_write_dquot(dquot);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out;
+       }
+
+       /* Mark structure as allocated */
+       status = ocfs2_modify_bh(lqinode, chunk->qc_headerbh, olq_alloc_dquot,
+                                &offset);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out;
+       }
+out:
+       return status;
+}
+
+/* Create entry in local file for dquot, load data from the global file */
+static int ocfs2_local_read_dquot(struct dquot *dquot)
+{
+       int status;
+
+       mlog_entry("id=%u, type=%d\n", dquot->dq_id, dquot->dq_type);
+
+       status = ocfs2_global_read_dquot(dquot);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out_err;
+       }
+
+       /* Now create entry in the local quota file */
+       status = ocfs2_create_local_dquot(dquot);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out_err;
+       }
+       mlog_exit(0);
+       return 0;
+out_err:
+       mlog_exit(status);
+       return status;
+}
+
+/* Release dquot structure from local quota file. ocfs2_release_dquot() has
+ * already started a transaction and obtained exclusive lock for global
+ * quota file. */
+static int ocfs2_local_release_dquot(struct dquot *dquot)
+{
+       int status;
+       int type = dquot->dq_type;
+       struct ocfs2_dquot *od = OCFS2_DQUOT(dquot);
+       struct super_block *sb = dquot->dq_sb;
+       struct ocfs2_local_disk_chunk *dchunk;
+       int offset;
+       handle_t *handle = journal_current_handle();
+
+       BUG_ON(!handle);
+       /* First write all local changes to global file */
+       status = ocfs2_global_release_dquot(dquot);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out;
+       }
+
+       status = ocfs2_journal_access_dq(handle, sb_dqopt(sb)->files[type],
+                       od->dq_chunk->qc_headerbh, OCFS2_JOURNAL_ACCESS_WRITE);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out;
+       }
+       offset = ol_dqblk_chunk_off(sb, od->dq_chunk->qc_num,
+                                            od->dq_local_off);
+       dchunk = (struct ocfs2_local_disk_chunk *)
+                       (od->dq_chunk->qc_headerbh->b_data);
+       /* Mark structure as freed */
+       lock_buffer(od->dq_chunk->qc_headerbh);
+       ocfs2_clear_bit(offset, dchunk->dqc_bitmap);
+       le32_add_cpu(&dchunk->dqc_free, 1);
+       unlock_buffer(od->dq_chunk->qc_headerbh);
+       status = ocfs2_journal_dirty(handle, od->dq_chunk->qc_headerbh);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out;
+       }
+       status = 0;
+out:
+       /* Clear the read bit so that next time someone uses this
+        * dquot he reads fresh info from disk and allocates local
+        * dquot structure */
+       clear_bit(DQ_READ_B, &dquot->dq_flags);
+       return status;
+}
+
+static struct quota_format_ops ocfs2_format_ops = {
+       .check_quota_file       = ocfs2_local_check_quota_file,
+       .read_file_info         = ocfs2_local_read_info,
+       .write_file_info        = ocfs2_global_write_info,
+       .free_file_info         = ocfs2_local_free_info,
+       .read_dqblk             = ocfs2_local_read_dquot,
+       .commit_dqblk           = ocfs2_local_write_dquot,
+       .release_dqblk          = ocfs2_local_release_dquot,
+};
+
+struct quota_format_type ocfs2_quota_format = {
+       .qf_fmt_id = QFMT_OCFS2,
+       .qf_ops = &ocfs2_format_ops,
+       .qf_owner = THIS_MODULE
+};
index ffd48db229a75323d31b250e7b5fd885fc7eff63..424adaa5f9005c9e4b0f5427de250d4925e3a95d 100644 (file)
@@ -106,8 +106,8 @@ static int ocfs2_update_last_group_and_inode(handle_t *handle,
        mlog_entry("(new_clusters=%d, first_new_cluster = %u)\n",
                   new_clusters, first_new_cluster);
 
-       ret = ocfs2_journal_access(handle, bm_inode, group_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = ocfs2_journal_access_gd(handle, bm_inode, group_bh,
+                                     OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret < 0) {
                mlog_errno(ret);
                goto out;
@@ -141,8 +141,8 @@ static int ocfs2_update_last_group_and_inode(handle_t *handle,
        }
 
        /* update the inode accordingly. */
-       ret = ocfs2_journal_access(handle, bm_inode, bm_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = ocfs2_journal_access_di(handle, bm_inode, bm_bh,
+                                     OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret < 0) {
                mlog_errno(ret);
                goto out_rollback;
@@ -314,6 +314,10 @@ int ocfs2_group_extend(struct inode * inode, int new_clusters)
 
        fe = (struct ocfs2_dinode *)main_bm_bh->b_data;
 
+       /* main_bm_bh is validated by inode read inside ocfs2_inode_lock(),
+        * so any corruption is a code bug. */
+       BUG_ON(!OCFS2_IS_VALID_DINODE(fe));
+
        if (le16_to_cpu(fe->id2.i_chain.cl_cpg) !=
                                 ocfs2_group_bitmap_size(osb->sb) * 8) {
                mlog(ML_ERROR, "The disk is too old and small. "
@@ -322,30 +326,18 @@ int ocfs2_group_extend(struct inode * inode, int new_clusters)
                goto out_unlock;
        }
 
-       if (!OCFS2_IS_VALID_DINODE(fe)) {
-               OCFS2_RO_ON_INVALID_DINODE(main_bm_inode->i_sb, fe);
-               ret = -EIO;
-               goto out_unlock;
-       }
-
        first_new_cluster = le32_to_cpu(fe->i_clusters);
        lgd_blkno = ocfs2_which_cluster_group(main_bm_inode,
                                              first_new_cluster - 1);
 
-       ret = ocfs2_read_block(main_bm_inode, lgd_blkno, &group_bh);
+       ret = ocfs2_read_group_descriptor(main_bm_inode, fe, lgd_blkno,
+                                         &group_bh);
        if (ret < 0) {
                mlog_errno(ret);
                goto out_unlock;
        }
-
        group = (struct ocfs2_group_desc *)group_bh->b_data;
 
-       ret = ocfs2_check_group_descriptor(inode->i_sb, fe, group);
-       if (ret) {
-               mlog_errno(ret);
-               goto out_unlock;
-       }
-
        cl_bpc = le16_to_cpu(fe->id2.i_chain.cl_bpc);
        if (le16_to_cpu(group->bg_bits) / cl_bpc + new_clusters >
                le16_to_cpu(fe->id2.i_chain.cl_cpg)) {
@@ -398,41 +390,16 @@ static int ocfs2_check_new_group(struct inode *inode,
                                 struct buffer_head *group_bh)
 {
        int ret;
-       struct ocfs2_group_desc *gd;
+       struct ocfs2_group_desc *gd =
+               (struct ocfs2_group_desc *)group_bh->b_data;
        u16 cl_bpc = le16_to_cpu(di->id2.i_chain.cl_bpc);
-       unsigned int max_bits = le16_to_cpu(di->id2.i_chain.cl_cpg) *
-                               le16_to_cpu(di->id2.i_chain.cl_bpc);
-
 
-       gd = (struct ocfs2_group_desc *)group_bh->b_data;
+       ret = ocfs2_check_group_descriptor(inode->i_sb, di, group_bh);
+       if (ret)
+               goto out;
 
-       ret = -EIO;
-       if (!OCFS2_IS_VALID_GROUP_DESC(gd))
-               mlog(ML_ERROR, "Group descriptor # %llu isn't valid.\n",
-                    (unsigned long long)le64_to_cpu(gd->bg_blkno));
-       else if (di->i_blkno != gd->bg_parent_dinode)
-               mlog(ML_ERROR, "Group descriptor # %llu has bad parent "
-                    "pointer (%llu, expected %llu)\n",
-                    (unsigned long long)le64_to_cpu(gd->bg_blkno),
-                    (unsigned long long)le64_to_cpu(gd->bg_parent_dinode),
-                    (unsigned long long)le64_to_cpu(di->i_blkno));
-       else if (le16_to_cpu(gd->bg_bits) > max_bits)
-               mlog(ML_ERROR, "Group descriptor # %llu has bit count of %u\n",
-                    (unsigned long long)le64_to_cpu(gd->bg_blkno),
-                    le16_to_cpu(gd->bg_bits));
-       else if (le16_to_cpu(gd->bg_free_bits_count) > le16_to_cpu(gd->bg_bits))
-               mlog(ML_ERROR, "Group descriptor # %llu has bit count %u but "
-                    "claims that %u are free\n",
-                    (unsigned long long)le64_to_cpu(gd->bg_blkno),
-                    le16_to_cpu(gd->bg_bits),
-                    le16_to_cpu(gd->bg_free_bits_count));
-       else if (le16_to_cpu(gd->bg_bits) > (8 * le16_to_cpu(gd->bg_size)))
-               mlog(ML_ERROR, "Group descriptor # %llu has bit count %u but "
-                    "max bitmap bits of %u\n",
-                    (unsigned long long)le64_to_cpu(gd->bg_blkno),
-                    le16_to_cpu(gd->bg_bits),
-                    8 * le16_to_cpu(gd->bg_size));
-       else if (le16_to_cpu(gd->bg_chain) != input->chain)
+       ret = -EINVAL;
+       if (le16_to_cpu(gd->bg_chain) != input->chain)
                mlog(ML_ERROR, "Group descriptor # %llu has bad chain %u "
                     "while input has %u set.\n",
                     (unsigned long long)le64_to_cpu(gd->bg_blkno),
@@ -451,6 +418,7 @@ static int ocfs2_check_new_group(struct inode *inode,
        else
                ret = 0;
 
+out:
        return ret;
 }
 
@@ -568,8 +536,8 @@ int ocfs2_group_add(struct inode *inode, struct ocfs2_new_group_input *input)
        cl = &fe->id2.i_chain;
        cr = &cl->cl_recs[input->chain];
 
-       ret = ocfs2_journal_access(handle, main_bm_inode, group_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = ocfs2_journal_access_gd(handle, main_bm_inode, group_bh,
+                                     OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret < 0) {
                mlog_errno(ret);
                goto out_commit;
@@ -584,8 +552,8 @@ int ocfs2_group_add(struct inode *inode, struct ocfs2_new_group_input *input)
                goto out_commit;
        }
 
-       ret = ocfs2_journal_access(handle, main_bm_inode, main_bm_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = ocfs2_journal_access_di(handle, main_bm_inode, main_bm_bh,
+                                     OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret < 0) {
                mlog_errno(ret);
                goto out_commit;
index bdda2d8f85080a5a883c1b01b4cc1fbe68d83d18..40661e7824e962d2bf36eac01b4f1f6721f88452 100644 (file)
@@ -151,7 +151,7 @@ int ocfs2_refresh_slot_info(struct ocfs2_super *osb)
         * this is not true, the read of -1 (UINT64_MAX) will fail.
         */
        ret = ocfs2_read_blocks(si->si_inode, -1, si->si_blocks, si->si_bh,
-                               OCFS2_BH_IGNORE_CACHE);
+                               OCFS2_BH_IGNORE_CACHE, NULL);
        if (ret == 0) {
                spin_lock(&osb->osb_lock);
                ocfs2_update_slot_info(si);
@@ -405,7 +405,7 @@ static int ocfs2_map_slot_buffers(struct ocfs2_super *osb,
 
                bh = NULL;  /* Acquire a fresh bh */
                status = ocfs2_read_blocks(si->si_inode, blkno, 1, &bh,
-                                          OCFS2_BH_IGNORE_CACHE);
+                                          OCFS2_BH_IGNORE_CACHE, NULL);
                if (status < 0) {
                        mlog_errno(status);
                        goto bail;
index c5ff18b46b57524884d9c4b7639f8089e7d3c532..a69628603e18273cdbc3d2b5d7e5a440623c17c8 100644 (file)
@@ -35,6 +35,7 @@
 #include "ocfs2.h"
 
 #include "alloc.h"
+#include "blockcheck.h"
 #include "dlmglue.h"
 #include "inode.h"
 #include "journal.h"
@@ -145,62 +146,183 @@ static u32 ocfs2_bits_per_group(struct ocfs2_chain_list *cl)
        return (u32)le16_to_cpu(cl->cl_cpg) * (u32)le16_to_cpu(cl->cl_bpc);
 }
 
-/* somewhat more expensive than our other checks, so use sparingly. */
-int ocfs2_check_group_descriptor(struct super_block *sb,
-                                struct ocfs2_dinode *di,
-                                struct ocfs2_group_desc *gd)
+#define do_error(fmt, ...)                                             \
+       do{                                                             \
+               if (clean_error)                                        \
+                       mlog(ML_ERROR, fmt "\n", ##__VA_ARGS__);        \
+               else                                                    \
+                       ocfs2_error(sb, fmt, ##__VA_ARGS__);            \
+       } while (0)
+
+static int ocfs2_validate_gd_self(struct super_block *sb,
+                                 struct buffer_head *bh,
+                                 int clean_error)
 {
-       unsigned int max_bits;
+       struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data;
 
        if (!OCFS2_IS_VALID_GROUP_DESC(gd)) {
-               OCFS2_RO_ON_INVALID_GROUP_DESC(sb, gd);
-               return -EIO;
+               do_error("Group descriptor #%llu has bad signature %.*s",
+                        (unsigned long long)bh->b_blocknr, 7,
+                        gd->bg_signature);
+               return -EINVAL;
        }
 
+       if (le64_to_cpu(gd->bg_blkno) != bh->b_blocknr) {
+               do_error("Group descriptor #%llu has an invalid bg_blkno "
+                        "of %llu",
+                        (unsigned long long)bh->b_blocknr,
+                        (unsigned long long)le64_to_cpu(gd->bg_blkno));
+               return -EINVAL;
+       }
+
+       if (le32_to_cpu(gd->bg_generation) != OCFS2_SB(sb)->fs_generation) {
+               do_error("Group descriptor #%llu has an invalid "
+                        "fs_generation of #%u",
+                        (unsigned long long)bh->b_blocknr,
+                        le32_to_cpu(gd->bg_generation));
+               return -EINVAL;
+       }
+
+       if (le16_to_cpu(gd->bg_free_bits_count) > le16_to_cpu(gd->bg_bits)) {
+               do_error("Group descriptor #%llu has bit count %u but "
+                        "claims that %u are free",
+                        (unsigned long long)bh->b_blocknr,
+                        le16_to_cpu(gd->bg_bits),
+                        le16_to_cpu(gd->bg_free_bits_count));
+               return -EINVAL;
+       }
+
+       if (le16_to_cpu(gd->bg_bits) > (8 * le16_to_cpu(gd->bg_size))) {
+               do_error("Group descriptor #%llu has bit count %u but "
+                        "max bitmap bits of %u",
+                        (unsigned long long)bh->b_blocknr,
+                        le16_to_cpu(gd->bg_bits),
+                        8 * le16_to_cpu(gd->bg_size));
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int ocfs2_validate_gd_parent(struct super_block *sb,
+                                   struct ocfs2_dinode *di,
+                                   struct buffer_head *bh,
+                                   int clean_error)
+{
+       unsigned int max_bits;
+       struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data;
+
        if (di->i_blkno != gd->bg_parent_dinode) {
-               ocfs2_error(sb, "Group descriptor # %llu has bad parent "
-                           "pointer (%llu, expected %llu)",
-                           (unsigned long long)le64_to_cpu(gd->bg_blkno),
-                           (unsigned long long)le64_to_cpu(gd->bg_parent_dinode),
-                           (unsigned long long)le64_to_cpu(di->i_blkno));
-               return -EIO;
+               do_error("Group descriptor #%llu has bad parent "
+                        "pointer (%llu, expected %llu)",
+                        (unsigned long long)bh->b_blocknr,
+                        (unsigned long long)le64_to_cpu(gd->bg_parent_dinode),
+                        (unsigned long long)le64_to_cpu(di->i_blkno));
+               return -EINVAL;
        }
 
        max_bits = le16_to_cpu(di->id2.i_chain.cl_cpg) * le16_to_cpu(di->id2.i_chain.cl_bpc);
        if (le16_to_cpu(gd->bg_bits) > max_bits) {
-               ocfs2_error(sb, "Group descriptor # %llu has bit count of %u",
-                           (unsigned long long)le64_to_cpu(gd->bg_blkno),
-                           le16_to_cpu(gd->bg_bits));
-               return -EIO;
+               do_error("Group descriptor #%llu has bit count of %u",
+                        (unsigned long long)bh->b_blocknr,
+                        le16_to_cpu(gd->bg_bits));
+               return -EINVAL;
        }
 
        if (le16_to_cpu(gd->bg_chain) >=
            le16_to_cpu(di->id2.i_chain.cl_next_free_rec)) {
-               ocfs2_error(sb, "Group descriptor # %llu has bad chain %u",
-                           (unsigned long long)le64_to_cpu(gd->bg_blkno),
-                           le16_to_cpu(gd->bg_chain));
-               return -EIO;
+               do_error("Group descriptor #%llu has bad chain %u",
+                        (unsigned long long)bh->b_blocknr,
+                        le16_to_cpu(gd->bg_chain));
+               return -EINVAL;
        }
 
-       if (le16_to_cpu(gd->bg_free_bits_count) > le16_to_cpu(gd->bg_bits)) {
-               ocfs2_error(sb, "Group descriptor # %llu has bit count %u but "
-                           "claims that %u are free",
-                           (unsigned long long)le64_to_cpu(gd->bg_blkno),
-                           le16_to_cpu(gd->bg_bits),
-                           le16_to_cpu(gd->bg_free_bits_count));
-               return -EIO;
-       }
+       return 0;
+}
 
-       if (le16_to_cpu(gd->bg_bits) > (8 * le16_to_cpu(gd->bg_size))) {
-               ocfs2_error(sb, "Group descriptor # %llu has bit count %u but "
-                           "max bitmap bits of %u",
-                           (unsigned long long)le64_to_cpu(gd->bg_blkno),
-                           le16_to_cpu(gd->bg_bits),
-                           8 * le16_to_cpu(gd->bg_size));
-               return -EIO;
+#undef do_error
+
+/*
+ * This version only prints errors.  It does not fail the filesystem, and
+ * exists only for resize.
+ */
+int ocfs2_check_group_descriptor(struct super_block *sb,
+                                struct ocfs2_dinode *di,
+                                struct buffer_head *bh)
+{
+       int rc;
+       struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data;
+
+       BUG_ON(!buffer_uptodate(bh));
+
+       /*
+        * If the ecc fails, we return the error but otherwise
+        * leave the filesystem running.  We know any error is
+        * local to this block.
+        */
+       rc = ocfs2_validate_meta_ecc(sb, bh->b_data, &gd->bg_check);
+       if (rc) {
+               mlog(ML_ERROR,
+                    "Checksum failed for group descriptor %llu\n",
+                    (unsigned long long)bh->b_blocknr);
+       } else
+               rc = ocfs2_validate_gd_self(sb, bh, 1);
+       if (!rc)
+               rc = ocfs2_validate_gd_parent(sb, di, bh, 1);
+
+       return rc;
+}
+
+static int ocfs2_validate_group_descriptor(struct super_block *sb,
+                                          struct buffer_head *bh)
+{
+       int rc;
+       struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data;
+
+       mlog(0, "Validating group descriptor %llu\n",
+            (unsigned long long)bh->b_blocknr);
+
+       BUG_ON(!buffer_uptodate(bh));
+
+       /*
+        * If the ecc fails, we return the error but otherwise
+        * leave the filesystem running.  We know any error is
+        * local to this block.
+        */
+       rc = ocfs2_validate_meta_ecc(sb, bh->b_data, &gd->bg_check);
+       if (rc)
+               return rc;
+
+       /*
+        * Errors after here are fatal.
+        */
+
+       return ocfs2_validate_gd_self(sb, bh, 0);
+}
+
+int ocfs2_read_group_descriptor(struct inode *inode, struct ocfs2_dinode *di,
+                               u64 gd_blkno, struct buffer_head **bh)
+{
+       int rc;
+       struct buffer_head *tmp = *bh;
+
+       rc = ocfs2_read_block(inode, gd_blkno, &tmp,
+                             ocfs2_validate_group_descriptor);
+       if (rc)
+               goto out;
+
+       rc = ocfs2_validate_gd_parent(inode->i_sb, di, tmp, 0);
+       if (rc) {
+               brelse(tmp);
+               goto out;
        }
 
-       return 0;
+       /* If ocfs2_read_block() got us a new bh, pass it up. */
+       if (!*bh)
+               *bh = tmp;
+
+out:
+       return rc;
 }
 
 static int ocfs2_block_group_fill(handle_t *handle,
@@ -225,10 +347,10 @@ static int ocfs2_block_group_fill(handle_t *handle,
                goto bail;
        }
 
-       status = ocfs2_journal_access(handle,
-                                     alloc_inode,
-                                     bg_bh,
-                                     OCFS2_JOURNAL_ACCESS_CREATE);
+       status = ocfs2_journal_access_gd(handle,
+                                        alloc_inode,
+                                        bg_bh,
+                                        OCFS2_JOURNAL_ACCESS_CREATE);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -358,8 +480,8 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb,
 
        bg = (struct ocfs2_group_desc *) bg_bh->b_data;
 
-       status = ocfs2_journal_access(handle, alloc_inode,
-                                     bh, OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_journal_access_di(handle, alloc_inode,
+                                        bh, OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -441,11 +563,11 @@ static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb,
        ac->ac_alloc_slot = slot;
 
        fe = (struct ocfs2_dinode *) bh->b_data;
-       if (!OCFS2_IS_VALID_DINODE(fe)) {
-               OCFS2_RO_ON_INVALID_DINODE(alloc_inode->i_sb, fe);
-               status = -EIO;
-               goto bail;
-       }
+
+       /* The bh was validated by the inode read inside
+        * ocfs2_inode_lock().  Any corruption is a code bug. */
+       BUG_ON(!OCFS2_IS_VALID_DINODE(fe));
+
        if (!(fe->i_flags & cpu_to_le32(OCFS2_CHAIN_FL))) {
                ocfs2_error(alloc_inode->i_sb, "Invalid chain allocator %llu",
                            (unsigned long long)le64_to_cpu(fe->i_blkno));
@@ -790,10 +912,9 @@ static int ocfs2_block_group_find_clear_bits(struct ocfs2_super *osb,
        int offset, start, found, status = 0;
        struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) bg_bh->b_data;
 
-       if (!OCFS2_IS_VALID_GROUP_DESC(bg)) {
-               OCFS2_RO_ON_INVALID_GROUP_DESC(osb->sb, bg);
-               return -EIO;
-       }
+       /* Callers got this descriptor from
+        * ocfs2_read_group_descriptor().  Any corruption is a code bug. */
+       BUG_ON(!OCFS2_IS_VALID_GROUP_DESC(bg));
 
        found = start = best_offset = best_size = 0;
        bitmap = bg->bg_bitmap;
@@ -858,11 +979,9 @@ static inline int ocfs2_block_group_set_bits(handle_t *handle,
 
        mlog_entry_void();
 
-       if (!OCFS2_IS_VALID_GROUP_DESC(bg)) {
-               OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, bg);
-               status = -EIO;
-               goto bail;
-       }
+       /* All callers get the descriptor via
+        * ocfs2_read_group_descriptor().  Any corruption is a code bug. */
+       BUG_ON(!OCFS2_IS_VALID_GROUP_DESC(bg));
        BUG_ON(le16_to_cpu(bg->bg_free_bits_count) < num_bits);
 
        mlog(0, "block_group_set_bits: off = %u, num = %u\n", bit_off,
@@ -871,10 +990,10 @@ static inline int ocfs2_block_group_set_bits(handle_t *handle,
        if (ocfs2_is_cluster_bitmap(alloc_inode))
                journal_type = OCFS2_JOURNAL_ACCESS_UNDO;
 
-       status = ocfs2_journal_access(handle,
-                                     alloc_inode,
-                                     group_bh,
-                                     journal_type);
+       status = ocfs2_journal_access_gd(handle,
+                                        alloc_inode,
+                                        group_bh,
+                                        journal_type);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -931,21 +1050,10 @@ static int ocfs2_relink_block_group(handle_t *handle,
        struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) bg_bh->b_data;
        struct ocfs2_group_desc *prev_bg = (struct ocfs2_group_desc *) prev_bg_bh->b_data;
 
-       if (!OCFS2_IS_VALID_DINODE(fe)) {
-               OCFS2_RO_ON_INVALID_DINODE(alloc_inode->i_sb, fe);
-               status = -EIO;
-               goto out;
-       }
-       if (!OCFS2_IS_VALID_GROUP_DESC(bg)) {
-               OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, bg);
-               status = -EIO;
-               goto out;
-       }
-       if (!OCFS2_IS_VALID_GROUP_DESC(prev_bg)) {
-               OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, prev_bg);
-               status = -EIO;
-               goto out;
-       }
+       /* The caller got these descriptors from
+        * ocfs2_read_group_descriptor().  Any corruption is a code bug. */
+       BUG_ON(!OCFS2_IS_VALID_GROUP_DESC(bg));
+       BUG_ON(!OCFS2_IS_VALID_GROUP_DESC(prev_bg));
 
        mlog(0, "Suballoc %llu, chain %u, move group %llu to top, prev = %llu\n",
             (unsigned long long)le64_to_cpu(fe->i_blkno), chain,
@@ -956,8 +1064,8 @@ static int ocfs2_relink_block_group(handle_t *handle,
        bg_ptr = le64_to_cpu(bg->bg_next_group);
        prev_bg_ptr = le64_to_cpu(prev_bg->bg_next_group);
 
-       status = ocfs2_journal_access(handle, alloc_inode, prev_bg_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_journal_access_gd(handle, alloc_inode, prev_bg_bh,
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto out_rollback;
@@ -971,8 +1079,8 @@ static int ocfs2_relink_block_group(handle_t *handle,
                goto out_rollback;
        }
 
-       status = ocfs2_journal_access(handle, alloc_inode, bg_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_journal_access_gd(handle, alloc_inode, bg_bh,
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto out_rollback;
@@ -986,8 +1094,8 @@ static int ocfs2_relink_block_group(handle_t *handle,
                goto out_rollback;
        }
 
-       status = ocfs2_journal_access(handle, alloc_inode, fe_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_journal_access_di(handle, alloc_inode, fe_bh,
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto out_rollback;
@@ -1008,7 +1116,7 @@ out_rollback:
                bg->bg_next_group = cpu_to_le64(bg_ptr);
                prev_bg->bg_next_group = cpu_to_le64(prev_bg_ptr);
        }
-out:
+
        mlog_exit(status);
        return status;
 }
@@ -1138,8 +1246,8 @@ static int ocfs2_alloc_dinode_update_counts(struct inode *inode,
        struct ocfs2_dinode *di = (struct ocfs2_dinode *) di_bh->b_data;
        struct ocfs2_chain_list *cl = (struct ocfs2_chain_list *) &di->id2.i_chain;
 
-       ret = ocfs2_journal_access(handle, inode, di_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = ocfs2_journal_access_di(handle, inode, di_bh,
+                                     OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret < 0) {
                mlog_errno(ret);
                goto out;
@@ -1170,21 +1278,17 @@ static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac,
        u16 found;
        struct buffer_head *group_bh = NULL;
        struct ocfs2_group_desc *gd;
+       struct ocfs2_dinode *di = (struct ocfs2_dinode *)ac->ac_bh->b_data;
        struct inode *alloc_inode = ac->ac_inode;
 
-       ret = ocfs2_read_block(alloc_inode, gd_blkno, &group_bh);
+       ret = ocfs2_read_group_descriptor(alloc_inode, di, gd_blkno,
+                                         &group_bh);
        if (ret < 0) {
                mlog_errno(ret);
                return ret;
        }
 
        gd = (struct ocfs2_group_desc *) group_bh->b_data;
-       if (!OCFS2_IS_VALID_GROUP_DESC(gd)) {
-               OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, gd);
-               ret = -EIO;
-               goto out;
-       }
-
        ret = ac->ac_group_search(alloc_inode, group_bh, bits_wanted, min_bits,
                                  ac->ac_max_block, bit_off, &found);
        if (ret < 0) {
@@ -1241,19 +1345,14 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
             bits_wanted, chain,
             (unsigned long long)OCFS2_I(alloc_inode)->ip_blkno);
 
-       status = ocfs2_read_block(alloc_inode,
-                                 le64_to_cpu(cl->cl_recs[chain].c_blkno),
-                                 &group_bh);
+       status = ocfs2_read_group_descriptor(alloc_inode, fe,
+                                            le64_to_cpu(cl->cl_recs[chain].c_blkno),
+                                            &group_bh);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
        }
        bg = (struct ocfs2_group_desc *) group_bh->b_data;
-       status = ocfs2_check_group_descriptor(alloc_inode->i_sb, fe, bg);
-       if (status) {
-               mlog_errno(status);
-               goto bail;
-       }
 
        status = -ENOSPC;
        /* for now, the chain search is a bit simplistic. We just use
@@ -1271,18 +1370,13 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
                next_group = le64_to_cpu(bg->bg_next_group);
                prev_group_bh = group_bh;
                group_bh = NULL;
-               status = ocfs2_read_block(alloc_inode,
-                                         next_group, &group_bh);
+               status = ocfs2_read_group_descriptor(alloc_inode, fe,
+                                                    next_group, &group_bh);
                if (status < 0) {
                        mlog_errno(status);
                        goto bail;
                }
                bg = (struct ocfs2_group_desc *) group_bh->b_data;
-               status = ocfs2_check_group_descriptor(alloc_inode->i_sb, fe, bg);
-               if (status) {
-                       mlog_errno(status);
-                       goto bail;
-               }
        }
        if (status < 0) {
                if (status != -ENOSPC)
@@ -1324,10 +1418,10 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
 
        /* Ok, claim our bits now: set the info on dinode, chainlist
         * and then the group */
-       status = ocfs2_journal_access(handle,
-                                     alloc_inode,
-                                     ac->ac_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_journal_access_di(handle,
+                                        alloc_inode,
+                                        ac->ac_bh,
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -1392,11 +1486,11 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb,
        BUG_ON(!ac->ac_bh);
 
        fe = (struct ocfs2_dinode *) ac->ac_bh->b_data;
-       if (!OCFS2_IS_VALID_DINODE(fe)) {
-               OCFS2_RO_ON_INVALID_DINODE(osb->sb, fe);
-               status = -EIO;
-               goto bail;
-       }
+
+       /* The bh was validated by the inode read during
+        * ocfs2_reserve_suballoc_bits().  Any corruption is a code bug. */
+       BUG_ON(!OCFS2_IS_VALID_DINODE(fe));
+
        if (le32_to_cpu(fe->id1.bitmap1.i_used) >=
            le32_to_cpu(fe->id1.bitmap1.i_total)) {
                ocfs2_error(osb->sb, "Chain allocator dinode %llu has %u used "
@@ -1725,19 +1819,17 @@ static inline int ocfs2_block_group_clear_bits(handle_t *handle,
 
        mlog_entry_void();
 
-       if (!OCFS2_IS_VALID_GROUP_DESC(bg)) {
-               OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, bg);
-               status = -EIO;
-               goto bail;
-       }
+       /* The caller got this descriptor from
+        * ocfs2_read_group_descriptor().  Any corruption is a code bug. */
+       BUG_ON(!OCFS2_IS_VALID_GROUP_DESC(bg));
 
        mlog(0, "off = %u, num = %u\n", bit_off, num_bits);
 
        if (ocfs2_is_cluster_bitmap(alloc_inode))
                journal_type = OCFS2_JOURNAL_ACCESS_UNDO;
 
-       status = ocfs2_journal_access(handle, alloc_inode, group_bh,
-                                     journal_type);
+       status = ocfs2_journal_access_gd(handle, alloc_inode, group_bh,
+                                        journal_type);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -1782,29 +1874,26 @@ int ocfs2_free_suballoc_bits(handle_t *handle,
 
        mlog_entry_void();
 
-       if (!OCFS2_IS_VALID_DINODE(fe)) {
-               OCFS2_RO_ON_INVALID_DINODE(alloc_inode->i_sb, fe);
-               status = -EIO;
-               goto bail;
-       }
+       /* The alloc_bh comes from ocfs2_free_dinode() or
+        * ocfs2_free_clusters().  The callers have all locked the
+        * allocator and gotten alloc_bh from the lock call.  This
+        * validates the dinode buffer.  Any corruption that has happended
+        * is a code bug. */
+       BUG_ON(!OCFS2_IS_VALID_DINODE(fe));
        BUG_ON((count + start_bit) > ocfs2_bits_per_group(cl));
 
        mlog(0, "%llu: freeing %u bits from group %llu, starting at %u\n",
             (unsigned long long)OCFS2_I(alloc_inode)->ip_blkno, count,
             (unsigned long long)bg_blkno, start_bit);
 
-       status = ocfs2_read_block(alloc_inode, bg_blkno, &group_bh);
+       status = ocfs2_read_group_descriptor(alloc_inode, fe, bg_blkno,
+                                            &group_bh);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
        }
-
        group = (struct ocfs2_group_desc *) group_bh->b_data;
-       status = ocfs2_check_group_descriptor(alloc_inode->i_sb, fe, group);
-       if (status) {
-               mlog_errno(status);
-               goto bail;
-       }
+
        BUG_ON((count + start_bit) > le16_to_cpu(group->bg_bits));
 
        status = ocfs2_block_group_clear_bits(handle, alloc_inode,
@@ -1815,8 +1904,8 @@ int ocfs2_free_suballoc_bits(handle_t *handle,
                goto bail;
        }
 
-       status = ocfs2_journal_access(handle, alloc_inode, alloc_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_journal_access_di(handle, alloc_inode, alloc_bh,
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
index 4df159d8f450330d2a2b7ed200dd8ef48c6a0f53..e3c13c77f9e8272baa4c0aa7651caee03ea6260f 100644 (file)
@@ -164,10 +164,24 @@ void ocfs2_free_ac_resource(struct ocfs2_alloc_context *ac);
  * and return that block offset. */
 u64 ocfs2_which_cluster_group(struct inode *inode, u32 cluster);
 
-/* somewhat more expensive than our other checks, so use sparingly. */
+/*
+ * By default, ocfs2_read_group_descriptor() calls ocfs2_error() when it
+ * finds a problem.  A caller that wants to check a group descriptor
+ * without going readonly should read the block with ocfs2_read_block[s]()
+ * and then checking it with this function.  This is only resize, really.
+ * Everyone else should be using ocfs2_read_group_descriptor().
+ */
 int ocfs2_check_group_descriptor(struct super_block *sb,
                                 struct ocfs2_dinode *di,
-                                struct ocfs2_group_desc *gd);
+                                struct buffer_head *bh);
+/*
+ * Read a group descriptor block into *bh.  If *bh is NULL, a bh will be
+ * allocated.  This is a cached read.  The descriptor will be validated with
+ * ocfs2_validate_group_descriptor().
+ */
+int ocfs2_read_group_descriptor(struct inode *inode, struct ocfs2_dinode *di,
+                               u64 gd_blkno, struct buffer_head **bh);
+
 int ocfs2_lock_allocators(struct inode *inode, struct ocfs2_extent_tree *et,
                          u32 clusters_to_add, u32 extents_to_split,
                          struct ocfs2_alloc_context **data_ac,
index 304b63ac78cfcceeef4759c66c5f72952477909d..43ed11345b59fdf7ac8c00596b14491a4e89eb20 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/debugfs.h>
 #include <linux/mount.h>
 #include <linux/seq_file.h>
+#include <linux/quotaops.h>
 
 #define MLOG_MASK_PREFIX ML_SUPER
 #include <cluster/masklog.h>
@@ -51,6 +52,7 @@
 #include "ocfs1_fs_compat.h"
 
 #include "alloc.h"
+#include "blockcheck.h"
 #include "dlmglue.h"
 #include "export.h"
 #include "extent_map.h"
 #include "uptodate.h"
 #include "ver.h"
 #include "xattr.h"
+#include "quota.h"
 
 #include "buffer_head_io.h"
 
 static struct kmem_cache *ocfs2_inode_cachep = NULL;
+struct kmem_cache *ocfs2_dquot_cachep;
+struct kmem_cache *ocfs2_qf_chunk_cachep;
 
 /* OCFS2 needs to schedule several differnt types of work which
  * require cluster locking, disk I/O, recovery waits, etc. Since these
@@ -124,6 +129,9 @@ static int ocfs2_get_sector(struct super_block *sb,
 static void ocfs2_write_super(struct super_block *sb);
 static struct inode *ocfs2_alloc_inode(struct super_block *sb);
 static void ocfs2_destroy_inode(struct inode *inode);
+static int ocfs2_susp_quotas(struct ocfs2_super *osb, int unsuspend);
+static int ocfs2_enable_quotas(struct ocfs2_super *osb);
+static void ocfs2_disable_quotas(struct ocfs2_super *osb);
 
 static const struct super_operations ocfs2_sops = {
        .statfs         = ocfs2_statfs,
@@ -137,6 +145,8 @@ static const struct super_operations ocfs2_sops = {
        .put_super      = ocfs2_put_super,
        .remount_fs     = ocfs2_remount,
        .show_options   = ocfs2_show_options,
+       .quota_read     = ocfs2_quota_read,
+       .quota_write    = ocfs2_quota_write,
 };
 
 enum {
@@ -158,6 +168,10 @@ enum {
        Opt_user_xattr,
        Opt_nouser_xattr,
        Opt_inode64,
+       Opt_acl,
+       Opt_noacl,
+       Opt_usrquota,
+       Opt_grpquota,
        Opt_err,
 };
 
@@ -180,6 +194,10 @@ static const match_table_t tokens = {
        {Opt_user_xattr, "user_xattr"},
        {Opt_nouser_xattr, "nouser_xattr"},
        {Opt_inode64, "inode64"},
+       {Opt_acl, "acl"},
+       {Opt_noacl, "noacl"},
+       {Opt_usrquota, "usrquota"},
+       {Opt_grpquota, "grpquota"},
        {Opt_err, NULL}
 };
 
@@ -221,6 +239,19 @@ static int ocfs2_sync_fs(struct super_block *sb, int wait)
        return 0;
 }
 
+static int ocfs2_need_system_inode(struct ocfs2_super *osb, int ino)
+{
+       if (!OCFS2_HAS_RO_COMPAT_FEATURE(osb->sb, OCFS2_FEATURE_RO_COMPAT_USRQUOTA)
+           && (ino == USER_QUOTA_SYSTEM_INODE
+               || ino == LOCAL_USER_QUOTA_SYSTEM_INODE))
+               return 0;
+       if (!OCFS2_HAS_RO_COMPAT_FEATURE(osb->sb, OCFS2_FEATURE_RO_COMPAT_GRPQUOTA)
+           && (ino == GROUP_QUOTA_SYSTEM_INODE
+               || ino == LOCAL_GROUP_QUOTA_SYSTEM_INODE))
+               return 0;
+       return 1;
+}
+
 static int ocfs2_init_global_system_inodes(struct ocfs2_super *osb)
 {
        struct inode *new = NULL;
@@ -247,6 +278,8 @@ static int ocfs2_init_global_system_inodes(struct ocfs2_super *osb)
 
        for (i = OCFS2_FIRST_ONLINE_SYSTEM_INODE;
             i <= OCFS2_LAST_GLOBAL_SYSTEM_INODE; i++) {
+               if (!ocfs2_need_system_inode(osb, i))
+                       continue;
                new = ocfs2_get_system_file_inode(osb, i, osb->slot_num);
                if (!new) {
                        ocfs2_release_system_inodes(osb);
@@ -277,6 +310,8 @@ static int ocfs2_init_local_system_inodes(struct ocfs2_super *osb)
        for (i = OCFS2_LAST_GLOBAL_SYSTEM_INODE + 1;
             i < NUM_SYSTEM_INODES;
             i++) {
+               if (!ocfs2_need_system_inode(osb, i))
+                       continue;
                new = ocfs2_get_system_file_inode(osb, i, osb->slot_num);
                if (!new) {
                        ocfs2_release_system_inodes(osb);
@@ -426,6 +461,12 @@ static int ocfs2_remount(struct super_block *sb, int *flags, char *data)
 
        /* We're going to/from readonly mode. */
        if ((*flags & MS_RDONLY) != (sb->s_flags & MS_RDONLY)) {
+               /* Disable quota accounting before remounting RO */
+               if (*flags & MS_RDONLY) {
+                       ret = ocfs2_susp_quotas(osb, 0);
+                       if (ret < 0)
+                               goto out;
+               }
                /* Lock here so the check of HARD_RO and the potential
                 * setting of SOFT_RO is atomic. */
                spin_lock(&osb->osb_lock);
@@ -461,11 +502,28 @@ static int ocfs2_remount(struct super_block *sb, int *flags, char *data)
                }
 unlock_osb:
                spin_unlock(&osb->osb_lock);
+               /* Enable quota accounting after remounting RW */
+               if (!ret && !(*flags & MS_RDONLY)) {
+                       if (sb_any_quota_suspended(sb))
+                               ret = ocfs2_susp_quotas(osb, 1);
+                       else
+                               ret = ocfs2_enable_quotas(osb);
+                       if (ret < 0) {
+                               /* Return back changes... */
+                               spin_lock(&osb->osb_lock);
+                               sb->s_flags |= MS_RDONLY;
+                               osb->osb_flags |= OCFS2_OSB_SOFT_RO;
+                               spin_unlock(&osb->osb_lock);
+                               goto out;
+                       }
+               }
        }
 
        if (!ret) {
                /* Only save off the new mount options in case of a successful
                 * remount. */
+               if (!(osb->s_feature_incompat & OCFS2_FEATURE_INCOMPAT_XATTR))
+                       parsed_options.mount_opt &= ~OCFS2_MOUNT_POSIX_ACL;
                osb->s_mount_opt = parsed_options.mount_opt;
                osb->s_atime_quantum = parsed_options.atime_quantum;
                osb->preferred_slot = parsed_options.slot;
@@ -619,6 +677,131 @@ static int ocfs2_verify_userspace_stack(struct ocfs2_super *osb,
        return 0;
 }
 
+static int ocfs2_susp_quotas(struct ocfs2_super *osb, int unsuspend)
+{
+       int type;
+       struct super_block *sb = osb->sb;
+       unsigned int feature[MAXQUOTAS] = { OCFS2_FEATURE_RO_COMPAT_USRQUOTA,
+                                            OCFS2_FEATURE_RO_COMPAT_GRPQUOTA};
+       int status = 0;
+
+       for (type = 0; type < MAXQUOTAS; type++) {
+               if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, feature[type]))
+                       continue;
+               if (unsuspend)
+                       status = vfs_quota_enable(
+                                       sb_dqopt(sb)->files[type],
+                                       type, QFMT_OCFS2,
+                                       DQUOT_SUSPENDED);
+               else
+                       status = vfs_quota_disable(sb, type,
+                                                  DQUOT_SUSPENDED);
+               if (status < 0)
+                       break;
+       }
+       if (status < 0)
+               mlog(ML_ERROR, "Failed to suspend/unsuspend quotas on "
+                    "remount (error = %d).\n", status);
+       return status;
+}
+
+static int ocfs2_enable_quotas(struct ocfs2_super *osb)
+{
+       struct inode *inode[MAXQUOTAS] = { NULL, NULL };
+       struct super_block *sb = osb->sb;
+       unsigned int feature[MAXQUOTAS] = { OCFS2_FEATURE_RO_COMPAT_USRQUOTA,
+                                            OCFS2_FEATURE_RO_COMPAT_GRPQUOTA};
+       unsigned int ino[MAXQUOTAS] = { LOCAL_USER_QUOTA_SYSTEM_INODE,
+                                       LOCAL_GROUP_QUOTA_SYSTEM_INODE };
+       int status;
+       int type;
+
+       sb_dqopt(sb)->flags |= DQUOT_QUOTA_SYS_FILE | DQUOT_NEGATIVE_USAGE;
+       for (type = 0; type < MAXQUOTAS; type++) {
+               if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, feature[type]))
+                       continue;
+               inode[type] = ocfs2_get_system_file_inode(osb, ino[type],
+                                                       osb->slot_num);
+               if (!inode[type]) {
+                       status = -ENOENT;
+                       goto out_quota_off;
+               }
+               status = vfs_quota_enable(inode[type], type, QFMT_OCFS2,
+                                               DQUOT_USAGE_ENABLED);
+               if (status < 0)
+                       goto out_quota_off;
+       }
+
+       for (type = 0; type < MAXQUOTAS; type++)
+               iput(inode[type]);
+       return 0;
+out_quota_off:
+       ocfs2_disable_quotas(osb);
+       for (type = 0; type < MAXQUOTAS; type++)
+               iput(inode[type]);
+       mlog_errno(status);
+       return status;
+}
+
+static void ocfs2_disable_quotas(struct ocfs2_super *osb)
+{
+       int type;
+       struct inode *inode;
+       struct super_block *sb = osb->sb;
+
+       /* We mostly ignore errors in this function because there's not much
+        * we can do when we see them */
+       for (type = 0; type < MAXQUOTAS; type++) {
+               if (!sb_has_quota_loaded(sb, type))
+                       continue;
+               inode = igrab(sb->s_dquot.files[type]);
+               /* Turn off quotas. This will remove all dquot structures from
+                * memory and so they will be automatically synced to global
+                * quota files */
+               vfs_quota_disable(sb, type, DQUOT_USAGE_ENABLED |
+                                           DQUOT_LIMITS_ENABLED);
+               if (!inode)
+                       continue;
+               iput(inode);
+       }
+}
+
+/* Handle quota on quotactl */
+static int ocfs2_quota_on(struct super_block *sb, int type, int format_id,
+                         char *path, int remount)
+{
+       unsigned int feature[MAXQUOTAS] = { OCFS2_FEATURE_RO_COMPAT_USRQUOTA,
+                                            OCFS2_FEATURE_RO_COMPAT_GRPQUOTA};
+
+       if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, feature[type]))
+               return -EINVAL;
+
+       if (remount)
+               return 0;       /* Just ignore it has been handled in
+                                * ocfs2_remount() */
+       return vfs_quota_enable(sb_dqopt(sb)->files[type], type,
+                                   format_id, DQUOT_LIMITS_ENABLED);
+}
+
+/* Handle quota off quotactl */
+static int ocfs2_quota_off(struct super_block *sb, int type, int remount)
+{
+       if (remount)
+               return 0;       /* Ignore now and handle later in
+                                * ocfs2_remount() */
+       return vfs_quota_disable(sb, type, DQUOT_LIMITS_ENABLED);
+}
+
+static struct quotactl_ops ocfs2_quotactl_ops = {
+       .quota_on       = ocfs2_quota_on,
+       .quota_off      = ocfs2_quota_off,
+       .quota_sync     = vfs_quota_sync,
+       .get_info       = vfs_get_dqinfo,
+       .set_info       = vfs_set_dqinfo,
+       .get_dqblk      = vfs_get_dqblk,
+       .set_dqblk      = vfs_set_dqblk,
+};
+
 static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
 {
        struct dentry *root;
@@ -651,12 +834,32 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
        }
        brelse(bh);
        bh = NULL;
+
+       if (!(osb->s_feature_incompat & OCFS2_FEATURE_INCOMPAT_XATTR))
+               parsed_options.mount_opt &= ~OCFS2_MOUNT_POSIX_ACL;
+
        osb->s_mount_opt = parsed_options.mount_opt;
        osb->s_atime_quantum = parsed_options.atime_quantum;
        osb->preferred_slot = parsed_options.slot;
        osb->osb_commit_interval = parsed_options.commit_interval;
        osb->local_alloc_default_bits = ocfs2_megabytes_to_clusters(sb, parsed_options.localalloc_opt);
        osb->local_alloc_bits = osb->local_alloc_default_bits;
+       if (osb->s_mount_opt & OCFS2_MOUNT_USRQUOTA &&
+           !OCFS2_HAS_RO_COMPAT_FEATURE(sb,
+                                        OCFS2_FEATURE_RO_COMPAT_USRQUOTA)) {
+               status = -EINVAL;
+               mlog(ML_ERROR, "User quotas were requested, but this "
+                    "filesystem does not have the feature enabled.\n");
+               goto read_super_error;
+       }
+       if (osb->s_mount_opt & OCFS2_MOUNT_GRPQUOTA &&
+           !OCFS2_HAS_RO_COMPAT_FEATURE(sb,
+                                        OCFS2_FEATURE_RO_COMPAT_GRPQUOTA)) {
+               status = -EINVAL;
+               mlog(ML_ERROR, "Group quotas were requested, but this "
+                    "filesystem does not have the feature enabled.\n");
+               goto read_super_error;
+       }
 
        status = ocfs2_verify_userspace_stack(osb, &parsed_options);
        if (status)
@@ -664,6 +867,9 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
 
        sb->s_magic = OCFS2_SUPER_MAGIC;
 
+       sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
+               ((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0);
+
        /* Hard readonly mode only if: bdev_read_only, MS_RDONLY,
         * heartbeat=none */
        if (bdev_read_only(sb->s_bdev)) {
@@ -758,6 +964,28 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
        atomic_set(&osb->vol_state, VOLUME_MOUNTED);
        wake_up(&osb->osb_mount_event);
 
+       /* Now we can initialize quotas because we can afford to wait
+        * for cluster locks recovery now. That also means that truncation
+        * log recovery can happen but that waits for proper quota setup */
+       if (!(sb->s_flags & MS_RDONLY)) {
+               status = ocfs2_enable_quotas(osb);
+               if (status < 0) {
+                       /* We have to err-out specially here because
+                        * s_root is already set */
+                       mlog_errno(status);
+                       atomic_set(&osb->vol_state, VOLUME_DISABLED);
+                       wake_up(&osb->osb_mount_event);
+                       mlog_exit(status);
+                       return status;
+               }
+       }
+
+       ocfs2_complete_quota_recovery(osb);
+
+       /* Now we wake up again for processes waiting for quotas */
+       atomic_set(&osb->vol_state, VOLUME_MOUNTED_QUOTAS);
+       wake_up(&osb->osb_mount_event);
+
        mlog_exit(status);
        return status;
 
@@ -945,6 +1173,41 @@ static int ocfs2_parse_options(struct super_block *sb,
                case Opt_inode64:
                        mopt->mount_opt |= OCFS2_MOUNT_INODE64;
                        break;
+               case Opt_usrquota:
+                       /* We check only on remount, otherwise features
+                        * aren't yet initialized. */
+                       if (is_remount && !OCFS2_HAS_RO_COMPAT_FEATURE(sb,
+                           OCFS2_FEATURE_RO_COMPAT_USRQUOTA)) {
+                               mlog(ML_ERROR, "User quota requested but "
+                                    "filesystem feature is not set\n");
+                               status = 0;
+                               goto bail;
+                       }
+                       mopt->mount_opt |= OCFS2_MOUNT_USRQUOTA;
+                       break;
+               case Opt_grpquota:
+                       if (is_remount && !OCFS2_HAS_RO_COMPAT_FEATURE(sb,
+                           OCFS2_FEATURE_RO_COMPAT_GRPQUOTA)) {
+                               mlog(ML_ERROR, "Group quota requested but "
+                                    "filesystem feature is not set\n");
+                               status = 0;
+                               goto bail;
+                       }
+                       mopt->mount_opt |= OCFS2_MOUNT_GRPQUOTA;
+                       break;
+#ifdef CONFIG_OCFS2_FS_POSIX_ACL
+               case Opt_acl:
+                       mopt->mount_opt |= OCFS2_MOUNT_POSIX_ACL;
+                       break;
+               case Opt_noacl:
+                       mopt->mount_opt &= ~OCFS2_MOUNT_POSIX_ACL;
+                       break;
+#else
+               case Opt_acl:
+               case Opt_noacl:
+                       printk(KERN_INFO "ocfs2 (no)acl options not supported\n");
+                       break;
+#endif
                default:
                        mlog(ML_ERROR,
                             "Unrecognized mount option \"%s\" "
@@ -1008,6 +1271,10 @@ static int ocfs2_show_options(struct seq_file *s, struct vfsmount *mnt)
        if (osb->osb_cluster_stack[0])
                seq_printf(s, ",cluster_stack=%.*s", OCFS2_STACK_LABEL_LEN,
                           osb->osb_cluster_stack);
+       if (opts & OCFS2_MOUNT_USRQUOTA)
+               seq_printf(s, ",usrquota");
+       if (opts & OCFS2_MOUNT_GRPQUOTA)
+               seq_printf(s, ",grpquota");
 
        if (opts & OCFS2_MOUNT_NOUSERXATTR)
                seq_printf(s, ",nouser_xattr");
@@ -1017,6 +1284,13 @@ static int ocfs2_show_options(struct seq_file *s, struct vfsmount *mnt)
        if (opts & OCFS2_MOUNT_INODE64)
                seq_printf(s, ",inode64");
 
+#ifdef CONFIG_OCFS2_FS_POSIX_ACL
+       if (opts & OCFS2_MOUNT_POSIX_ACL)
+               seq_printf(s, ",acl");
+       else
+               seq_printf(s, ",noacl");
+#endif
+
        return 0;
 }
 
@@ -1052,10 +1326,16 @@ static int __init ocfs2_init(void)
                mlog(ML_ERROR, "Unable to create ocfs2 debugfs root.\n");
        }
 
+       status = ocfs2_quota_setup();
+       if (status)
+               goto leave;
+
        ocfs2_set_locking_protocol();
 
+       status = register_quota_format(&ocfs2_quota_format);
 leave:
        if (status < 0) {
+               ocfs2_quota_shutdown();
                ocfs2_free_mem_caches();
                exit_ocfs2_uptodate_cache();
        }
@@ -1072,11 +1352,15 @@ static void __exit ocfs2_exit(void)
 {
        mlog_entry_void();
 
+       ocfs2_quota_shutdown();
+
        if (ocfs2_wq) {
                flush_workqueue(ocfs2_wq);
                destroy_workqueue(ocfs2_wq);
        }
 
+       unregister_quota_format(&ocfs2_quota_format);
+
        debugfs_remove(ocfs2_debugfs_root);
 
        ocfs2_free_mem_caches();
@@ -1192,8 +1476,27 @@ static int ocfs2_initialize_mem_caches(void)
                                       (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|
                                                SLAB_MEM_SPREAD),
                                       ocfs2_inode_init_once);
-       if (!ocfs2_inode_cachep)
+       ocfs2_dquot_cachep = kmem_cache_create("ocfs2_dquot_cache",
+                                       sizeof(struct ocfs2_dquot),
+                                       0,
+                                       (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|
+                                               SLAB_MEM_SPREAD),
+                                       NULL);
+       ocfs2_qf_chunk_cachep = kmem_cache_create("ocfs2_qf_chunk_cache",
+                                       sizeof(struct ocfs2_quota_chunk),
+                                       0,
+                                       (SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD),
+                                       NULL);
+       if (!ocfs2_inode_cachep || !ocfs2_dquot_cachep ||
+           !ocfs2_qf_chunk_cachep) {
+               if (ocfs2_inode_cachep)
+                       kmem_cache_destroy(ocfs2_inode_cachep);
+               if (ocfs2_dquot_cachep)
+                       kmem_cache_destroy(ocfs2_dquot_cachep);
+               if (ocfs2_qf_chunk_cachep)
+                       kmem_cache_destroy(ocfs2_qf_chunk_cachep);
                return -ENOMEM;
+       }
 
        return 0;
 }
@@ -1202,8 +1505,15 @@ static void ocfs2_free_mem_caches(void)
 {
        if (ocfs2_inode_cachep)
                kmem_cache_destroy(ocfs2_inode_cachep);
-
        ocfs2_inode_cachep = NULL;
+
+       if (ocfs2_dquot_cachep)
+               kmem_cache_destroy(ocfs2_dquot_cachep);
+       ocfs2_dquot_cachep = NULL;
+
+       if (ocfs2_qf_chunk_cachep)
+               kmem_cache_destroy(ocfs2_qf_chunk_cachep);
+       ocfs2_qf_chunk_cachep = NULL;
 }
 
 static int ocfs2_get_sector(struct super_block *sb,
@@ -1303,6 +1613,8 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err)
        osb = OCFS2_SB(sb);
        BUG_ON(!osb);
 
+       ocfs2_disable_quotas(osb);
+
        ocfs2_shutdown_local_alloc(osb);
 
        ocfs2_truncate_log_shutdown(osb);
@@ -1413,6 +1725,8 @@ static int ocfs2_initialize_super(struct super_block *sb,
        sb->s_fs_info = osb;
        sb->s_op = &ocfs2_sops;
        sb->s_export_op = &ocfs2_export_ops;
+       sb->s_qcop = &ocfs2_quotactl_ops;
+       sb->dq_op = &ocfs2_quota_operations;
        sb->s_xattr = ocfs2_xattr_handlers;
        sb->s_time_gran = 1;
        sb->s_flags |= MS_NOATIME;
@@ -1676,6 +1990,15 @@ static int ocfs2_verify_volume(struct ocfs2_dinode *di,
 
        if (memcmp(di->i_signature, OCFS2_SUPER_BLOCK_SIGNATURE,
                   strlen(OCFS2_SUPER_BLOCK_SIGNATURE)) == 0) {
+               /* We have to do a raw check of the feature here */
+               if (le32_to_cpu(di->id2.i_super.s_feature_incompat) &
+                   OCFS2_FEATURE_INCOMPAT_META_ECC) {
+                       status = ocfs2_block_check_validate(bh->b_data,
+                                                           bh->b_size,
+                                                           &di->i_check);
+                       if (status)
+                               goto out;
+               }
                status = -EINVAL;
                if ((1 << le32_to_cpu(di->id2.i_super.s_blocksize_bits)) != blksz) {
                        mlog(ML_ERROR, "found superblock with incorrect block "
@@ -1717,6 +2040,7 @@ static int ocfs2_verify_volume(struct ocfs2_dinode *di,
                }
        }
 
+out:
        mlog_exit(status);
        return status;
 }
index cbd03dfdc7b987aaef8810adfbce4590e6fdacc8..ed0a0cfd68d26b369be863d8ff70630bd8a1c5f1 100644 (file)
@@ -84,7 +84,7 @@ static char *ocfs2_fast_symlink_getlink(struct inode *inode,
 
        mlog_entry_void();
 
-       status = ocfs2_read_block(inode, OCFS2_I(inode)->ip_blkno, bh);
+       status = ocfs2_read_inode_block(inode, bh);
        if (status < 0) {
                mlog_errno(status);
                link = ERR_PTR(status);
index 74d7367ade13e1e36cb74a13327ca65573fabf86..e1d638af6ac3d00d8cb72a5b9b442c3bdfb8e3f0 100644 (file)
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/string.h>
+#include <linux/security.h>
 
 #define MLOG_MASK_PREFIX ML_XATTR
 #include <cluster/masklog.h>
 
 #include "ocfs2.h"
 #include "alloc.h"
+#include "blockcheck.h"
 #include "dlmglue.h"
 #include "file.h"
 #include "symlink.h"
@@ -61,12 +63,32 @@ struct ocfs2_xattr_def_value_root {
 };
 
 struct ocfs2_xattr_bucket {
-       struct buffer_head *bhs[OCFS2_XATTR_MAX_BLOCKS_PER_BUCKET];
-       struct ocfs2_xattr_header *xh;
+       /* The inode these xattrs are associated with */
+       struct inode *bu_inode;
+
+       /* The actual buffers that make up the bucket */
+       struct buffer_head *bu_bhs[OCFS2_XATTR_MAX_BLOCKS_PER_BUCKET];
+
+       /* How many blocks make up one bucket for this filesystem */
+       int bu_blocks;
+};
+
+struct ocfs2_xattr_set_ctxt {
+       handle_t *handle;
+       struct ocfs2_alloc_context *meta_ac;
+       struct ocfs2_alloc_context *data_ac;
+       struct ocfs2_cached_dealloc_ctxt dealloc;
 };
 
 #define OCFS2_XATTR_ROOT_SIZE  (sizeof(struct ocfs2_xattr_def_value_root))
 #define OCFS2_XATTR_INLINE_SIZE        80
+#define OCFS2_XATTR_FREE_IN_IBODY      (OCFS2_MIN_XATTR_INLINE_SIZE \
+                                        - sizeof(struct ocfs2_xattr_header) \
+                                        - sizeof(__u32))
+#define OCFS2_XATTR_FREE_IN_BLOCK(ptr) ((ptr)->i_sb->s_blocksize \
+                                        - sizeof(struct ocfs2_xattr_block) \
+                                        - sizeof(struct ocfs2_xattr_header) \
+                                        - sizeof(__u32))
 
 static struct ocfs2_xattr_def_value_root def_xv = {
        .xv.xr_list.l_count = cpu_to_le16(1),
@@ -74,13 +96,25 @@ static struct ocfs2_xattr_def_value_root def_xv = {
 
 struct xattr_handler *ocfs2_xattr_handlers[] = {
        &ocfs2_xattr_user_handler,
+#ifdef CONFIG_OCFS2_FS_POSIX_ACL
+       &ocfs2_xattr_acl_access_handler,
+       &ocfs2_xattr_acl_default_handler,
+#endif
        &ocfs2_xattr_trusted_handler,
+       &ocfs2_xattr_security_handler,
        NULL
 };
 
 static struct xattr_handler *ocfs2_xattr_handler_map[OCFS2_XATTR_MAX] = {
        [OCFS2_XATTR_INDEX_USER]        = &ocfs2_xattr_user_handler,
+#ifdef CONFIG_OCFS2_FS_POSIX_ACL
+       [OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS]
+                                       = &ocfs2_xattr_acl_access_handler,
+       [OCFS2_XATTR_INDEX_POSIX_ACL_DEFAULT]
+                                       = &ocfs2_xattr_acl_default_handler,
+#endif
        [OCFS2_XATTR_INDEX_TRUSTED]     = &ocfs2_xattr_trusted_handler,
+       [OCFS2_XATTR_INDEX_SECURITY]    = &ocfs2_xattr_security_handler,
 };
 
 struct ocfs2_xattr_info {
@@ -98,7 +132,7 @@ struct ocfs2_xattr_search {
         */
        struct buffer_head *xattr_bh;
        struct ocfs2_xattr_header *header;
-       struct ocfs2_xattr_bucket bucket;
+       struct ocfs2_xattr_bucket *bucket;
        void *base;
        void *end;
        struct ocfs2_xattr_entry *here;
@@ -127,14 +161,20 @@ static int ocfs2_xattr_tree_list_index_block(struct inode *inode,
                                        size_t buffer_size);
 
 static int ocfs2_xattr_create_index_block(struct inode *inode,
-                                         struct ocfs2_xattr_search *xs);
+                                         struct ocfs2_xattr_search *xs,
+                                         struct ocfs2_xattr_set_ctxt *ctxt);
 
 static int ocfs2_xattr_set_entry_index_block(struct inode *inode,
                                             struct ocfs2_xattr_info *xi,
-                                            struct ocfs2_xattr_search *xs);
+                                            struct ocfs2_xattr_search *xs,
+                                            struct ocfs2_xattr_set_ctxt *ctxt);
 
 static int ocfs2_delete_xattr_index_block(struct inode *inode,
                                          struct buffer_head *xb_bh);
+static int ocfs2_mv_xattr_buckets(struct inode *inode, handle_t *handle,
+                                 u64 src_blk, u64 last_blk, u64 to_blk,
+                                 unsigned int start_bucket,
+                                 u32 *first_hash);
 
 static inline u16 ocfs2_xattr_buckets_per_cluster(struct ocfs2_super *osb)
 {
@@ -154,6 +194,216 @@ static inline u16 ocfs2_xattr_max_xe_in_bucket(struct super_block *sb)
        return len / sizeof(struct ocfs2_xattr_entry);
 }
 
+#define bucket_blkno(_b) ((_b)->bu_bhs[0]->b_blocknr)
+#define bucket_block(_b, _n) ((_b)->bu_bhs[(_n)]->b_data)
+#define bucket_xh(_b) ((struct ocfs2_xattr_header *)bucket_block((_b), 0))
+
+static struct ocfs2_xattr_bucket *ocfs2_xattr_bucket_new(struct inode *inode)
+{
+       struct ocfs2_xattr_bucket *bucket;
+       int blks = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
+
+       BUG_ON(blks > OCFS2_XATTR_MAX_BLOCKS_PER_BUCKET);
+
+       bucket = kzalloc(sizeof(struct ocfs2_xattr_bucket), GFP_NOFS);
+       if (bucket) {
+               bucket->bu_inode = inode;
+               bucket->bu_blocks = blks;
+       }
+
+       return bucket;
+}
+
+static void ocfs2_xattr_bucket_relse(struct ocfs2_xattr_bucket *bucket)
+{
+       int i;
+
+       for (i = 0; i < bucket->bu_blocks; i++) {
+               brelse(bucket->bu_bhs[i]);
+               bucket->bu_bhs[i] = NULL;
+       }
+}
+
+static void ocfs2_xattr_bucket_free(struct ocfs2_xattr_bucket *bucket)
+{
+       if (bucket) {
+               ocfs2_xattr_bucket_relse(bucket);
+               bucket->bu_inode = NULL;
+               kfree(bucket);
+       }
+}
+
+/*
+ * A bucket that has never been written to disk doesn't need to be
+ * read.  We just need the buffer_heads.  Don't call this for
+ * buckets that are already on disk.  ocfs2_read_xattr_bucket() initializes
+ * them fully.
+ */
+static int ocfs2_init_xattr_bucket(struct ocfs2_xattr_bucket *bucket,
+                                  u64 xb_blkno)
+{
+       int i, rc = 0;
+
+       for (i = 0; i < bucket->bu_blocks; i++) {
+               bucket->bu_bhs[i] = sb_getblk(bucket->bu_inode->i_sb,
+                                             xb_blkno + i);
+               if (!bucket->bu_bhs[i]) {
+                       rc = -EIO;
+                       mlog_errno(rc);
+                       break;
+               }
+
+               if (!ocfs2_buffer_uptodate(bucket->bu_inode,
+                                          bucket->bu_bhs[i]))
+                       ocfs2_set_new_buffer_uptodate(bucket->bu_inode,
+                                                     bucket->bu_bhs[i]);
+       }
+
+       if (rc)
+               ocfs2_xattr_bucket_relse(bucket);
+       return rc;
+}
+
+/* Read the xattr bucket at xb_blkno */
+static int ocfs2_read_xattr_bucket(struct ocfs2_xattr_bucket *bucket,
+                                  u64 xb_blkno)
+{
+       int rc;
+
+       rc = ocfs2_read_blocks(bucket->bu_inode, xb_blkno,
+                              bucket->bu_blocks, bucket->bu_bhs, 0,
+                              NULL);
+       if (!rc) {
+               rc = ocfs2_validate_meta_ecc_bhs(bucket->bu_inode->i_sb,
+                                                bucket->bu_bhs,
+                                                bucket->bu_blocks,
+                                                &bucket_xh(bucket)->xh_check);
+               if (rc)
+                       mlog_errno(rc);
+       }
+
+       if (rc)
+               ocfs2_xattr_bucket_relse(bucket);
+       return rc;
+}
+
+static int ocfs2_xattr_bucket_journal_access(handle_t *handle,
+                                            struct ocfs2_xattr_bucket *bucket,
+                                            int type)
+{
+       int i, rc = 0;
+
+       for (i = 0; i < bucket->bu_blocks; i++) {
+               rc = ocfs2_journal_access(handle, bucket->bu_inode,
+                                         bucket->bu_bhs[i], type);
+               if (rc) {
+                       mlog_errno(rc);
+                       break;
+               }
+       }
+
+       return rc;
+}
+
+static void ocfs2_xattr_bucket_journal_dirty(handle_t *handle,
+                                            struct ocfs2_xattr_bucket *bucket)
+{
+       int i;
+
+       ocfs2_compute_meta_ecc_bhs(bucket->bu_inode->i_sb,
+                                  bucket->bu_bhs, bucket->bu_blocks,
+                                  &bucket_xh(bucket)->xh_check);
+
+       for (i = 0; i < bucket->bu_blocks; i++)
+               ocfs2_journal_dirty(handle, bucket->bu_bhs[i]);
+}
+
+static void ocfs2_xattr_bucket_copy_data(struct ocfs2_xattr_bucket *dest,
+                                        struct ocfs2_xattr_bucket *src)
+{
+       int i;
+       int blocksize = src->bu_inode->i_sb->s_blocksize;
+
+       BUG_ON(dest->bu_blocks != src->bu_blocks);
+       BUG_ON(dest->bu_inode != src->bu_inode);
+
+       for (i = 0; i < src->bu_blocks; i++) {
+               memcpy(bucket_block(dest, i), bucket_block(src, i),
+                      blocksize);
+       }
+}
+
+static int ocfs2_validate_xattr_block(struct super_block *sb,
+                                     struct buffer_head *bh)
+{
+       int rc;
+       struct ocfs2_xattr_block *xb =
+               (struct ocfs2_xattr_block *)bh->b_data;
+
+       mlog(0, "Validating xattr block %llu\n",
+            (unsigned long long)bh->b_blocknr);
+
+       BUG_ON(!buffer_uptodate(bh));
+
+       /*
+        * If the ecc fails, we return the error but otherwise
+        * leave the filesystem running.  We know any error is
+        * local to this block.
+        */
+       rc = ocfs2_validate_meta_ecc(sb, bh->b_data, &xb->xb_check);
+       if (rc)
+               return rc;
+
+       /*
+        * Errors after here are fatal
+        */
+
+       if (!OCFS2_IS_VALID_XATTR_BLOCK(xb)) {
+               ocfs2_error(sb,
+                           "Extended attribute block #%llu has bad "
+                           "signature %.*s",
+                           (unsigned long long)bh->b_blocknr, 7,
+                           xb->xb_signature);
+               return -EINVAL;
+       }
+
+       if (le64_to_cpu(xb->xb_blkno) != bh->b_blocknr) {
+               ocfs2_error(sb,
+                           "Extended attribute block #%llu has an "
+                           "invalid xb_blkno of %llu",
+                           (unsigned long long)bh->b_blocknr,
+                           (unsigned long long)le64_to_cpu(xb->xb_blkno));
+               return -EINVAL;
+       }
+
+       if (le32_to_cpu(xb->xb_fs_generation) != OCFS2_SB(sb)->fs_generation) {
+               ocfs2_error(sb,
+                           "Extended attribute block #%llu has an invalid "
+                           "xb_fs_generation of #%u",
+                           (unsigned long long)bh->b_blocknr,
+                           le32_to_cpu(xb->xb_fs_generation));
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int ocfs2_read_xattr_block(struct inode *inode, u64 xb_blkno,
+                                 struct buffer_head **bh)
+{
+       int rc;
+       struct buffer_head *tmp = *bh;
+
+       rc = ocfs2_read_block(inode, xb_blkno, &tmp,
+                             ocfs2_validate_xattr_block);
+
+       /* If ocfs2_read_block() got us a new bh, pass it up. */
+       if (!rc && !*bh)
+               *bh = tmp;
+
+       return rc;
+}
+
 static inline const char *ocfs2_xattr_prefix(int name_index)
 {
        struct xattr_handler *handler = NULL;
@@ -200,54 +450,163 @@ static void ocfs2_xattr_hash_entry(struct inode *inode,
        return;
 }
 
+static int ocfs2_xattr_entry_real_size(int name_len, size_t value_len)
+{
+       int size = 0;
+
+       if (value_len <= OCFS2_XATTR_INLINE_SIZE)
+               size = OCFS2_XATTR_SIZE(name_len) + OCFS2_XATTR_SIZE(value_len);
+       else
+               size = OCFS2_XATTR_SIZE(name_len) + OCFS2_XATTR_ROOT_SIZE;
+       size += sizeof(struct ocfs2_xattr_entry);
+
+       return size;
+}
+
+int ocfs2_calc_security_init(struct inode *dir,
+                            struct ocfs2_security_xattr_info *si,
+                            int *want_clusters,
+                            int *xattr_credits,
+                            struct ocfs2_alloc_context **xattr_ac)
+{
+       int ret = 0;
+       struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
+       int s_size = ocfs2_xattr_entry_real_size(strlen(si->name),
+                                                si->value_len);
+
+       /*
+        * The max space of security xattr taken inline is
+        * 256(name) + 80(value) + 16(entry) = 352 bytes,
+        * So reserve one metadata block for it is ok.
+        */
+       if (dir->i_sb->s_blocksize == OCFS2_MIN_BLOCKSIZE ||
+           s_size > OCFS2_XATTR_FREE_IN_IBODY) {
+               ret = ocfs2_reserve_new_metadata_blocks(osb, 1, xattr_ac);
+               if (ret) {
+                       mlog_errno(ret);
+                       return ret;
+               }
+               *xattr_credits += OCFS2_XATTR_BLOCK_CREATE_CREDITS;
+       }
+
+       /* reserve clusters for xattr value which will be set in B tree*/
+       if (si->value_len > OCFS2_XATTR_INLINE_SIZE) {
+               int new_clusters = ocfs2_clusters_for_bytes(dir->i_sb,
+                                                           si->value_len);
+
+               *xattr_credits += ocfs2_clusters_to_blocks(dir->i_sb,
+                                                          new_clusters);
+               *want_clusters += new_clusters;
+       }
+       return ret;
+}
+
+int ocfs2_calc_xattr_init(struct inode *dir,
+                         struct buffer_head *dir_bh,
+                         int mode,
+                         struct ocfs2_security_xattr_info *si,
+                         int *want_clusters,
+                         int *xattr_credits,
+                         struct ocfs2_alloc_context **xattr_ac)
+{
+       int ret = 0;
+       struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
+       int s_size = 0, a_size = 0, acl_len = 0, new_clusters;
+
+       if (si->enable)
+               s_size = ocfs2_xattr_entry_real_size(strlen(si->name),
+                                                    si->value_len);
+
+       if (osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) {
+               acl_len = ocfs2_xattr_get_nolock(dir, dir_bh,
+                                       OCFS2_XATTR_INDEX_POSIX_ACL_DEFAULT,
+                                       "", NULL, 0);
+               if (acl_len > 0) {
+                       a_size = ocfs2_xattr_entry_real_size(0, acl_len);
+                       if (S_ISDIR(mode))
+                               a_size <<= 1;
+               } else if (acl_len != 0 && acl_len != -ENODATA) {
+                       mlog_errno(ret);
+                       return ret;
+               }
+       }
+
+       if (!(s_size + a_size))
+               return ret;
+
+       /*
+        * The max space of security xattr taken inline is
+        * 256(name) + 80(value) + 16(entry) = 352 bytes,
+        * The max space of acl xattr taken inline is
+        * 80(value) + 16(entry) * 2(if directory) = 192 bytes,
+        * when blocksize = 512, may reserve one more cluser for
+        * xattr bucket, otherwise reserve one metadata block
+        * for them is ok.
+        */
+       if (dir->i_sb->s_blocksize == OCFS2_MIN_BLOCKSIZE ||
+           (s_size + a_size) > OCFS2_XATTR_FREE_IN_IBODY) {
+               ret = ocfs2_reserve_new_metadata_blocks(osb, 1, xattr_ac);
+               if (ret) {
+                       mlog_errno(ret);
+                       return ret;
+               }
+               *xattr_credits += OCFS2_XATTR_BLOCK_CREATE_CREDITS;
+       }
+
+       if (dir->i_sb->s_blocksize == OCFS2_MIN_BLOCKSIZE &&
+           (s_size + a_size) > OCFS2_XATTR_FREE_IN_BLOCK(dir)) {
+               *want_clusters += 1;
+               *xattr_credits += ocfs2_blocks_per_xattr_bucket(dir->i_sb);
+       }
+
+       /*
+        * reserve credits and clusters for xattrs which has large value
+        * and have to be set outside
+        */
+       if (si->enable && si->value_len > OCFS2_XATTR_INLINE_SIZE) {
+               new_clusters = ocfs2_clusters_for_bytes(dir->i_sb,
+                                                       si->value_len);
+               *xattr_credits += ocfs2_clusters_to_blocks(dir->i_sb,
+                                                          new_clusters);
+               *want_clusters += new_clusters;
+       }
+       if (osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL &&
+           acl_len > OCFS2_XATTR_INLINE_SIZE) {
+               /* for directory, it has DEFAULT and ACCESS two types of acls */
+               new_clusters = (S_ISDIR(mode) ? 2 : 1) *
+                               ocfs2_clusters_for_bytes(dir->i_sb, acl_len);
+               *xattr_credits += ocfs2_clusters_to_blocks(dir->i_sb,
+                                                          new_clusters);
+               *want_clusters += new_clusters;
+       }
+
+       return ret;
+}
+
 static int ocfs2_xattr_extend_allocation(struct inode *inode,
                                         u32 clusters_to_add,
-                                        struct buffer_head *xattr_bh,
-                                        struct ocfs2_xattr_value_root *xv)
+                                        struct ocfs2_xattr_value_buf *vb,
+                                        struct ocfs2_xattr_set_ctxt *ctxt)
 {
        int status = 0;
-       int restart_func = 0;
-       int credits = 0;
-       handle_t *handle = NULL;
-       struct ocfs2_alloc_context *data_ac = NULL;
-       struct ocfs2_alloc_context *meta_ac = NULL;
+       handle_t *handle = ctxt->handle;
        enum ocfs2_alloc_restarted why;
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
-       u32 prev_clusters, logical_start = le32_to_cpu(xv->xr_clusters);
+       u32 prev_clusters, logical_start = le32_to_cpu(vb->vb_xv->xr_clusters);
        struct ocfs2_extent_tree et;
 
        mlog(0, "(clusters_to_add for xattr= %u)\n", clusters_to_add);
 
-       ocfs2_init_xattr_value_extent_tree(&et, inode, xattr_bh, xv);
-
-restart_all:
-
-       status = ocfs2_lock_allocators(inode, &et, clusters_to_add, 0,
-                                      &data_ac, &meta_ac);
-       if (status) {
-               mlog_errno(status);
-               goto leave;
-       }
-
-       credits = ocfs2_calc_extend_credits(osb->sb, et.et_root_el,
-                                           clusters_to_add);
-       handle = ocfs2_start_trans(osb, credits);
-       if (IS_ERR(handle)) {
-               status = PTR_ERR(handle);
-               handle = NULL;
-               mlog_errno(status);
-               goto leave;
-       }
+       ocfs2_init_xattr_value_extent_tree(&et, inode, vb);
 
-restarted_transaction:
-       status = ocfs2_journal_access(handle, inode, xattr_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = vb->vb_access(handle, inode, vb->vb_bh,
+                             OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto leave;
        }
 
-       prev_clusters = le32_to_cpu(xv->xr_clusters);
+       prev_clusters = le32_to_cpu(vb->vb_xv->xr_clusters);
        status = ocfs2_add_clusters_in_btree(osb,
                                             inode,
                                             &logical_start,
@@ -255,157 +614,84 @@ restarted_transaction:
                                             0,
                                             &et,
                                             handle,
-                                            data_ac,
-                                            meta_ac,
+                                            ctxt->data_ac,
+                                            ctxt->meta_ac,
                                             &why);
-       if ((status < 0) && (status != -EAGAIN)) {
-               if (status != -ENOSPC)
-                       mlog_errno(status);
+       if (status < 0) {
+               mlog_errno(status);
                goto leave;
        }
 
-       status = ocfs2_journal_dirty(handle, xattr_bh);
+       status = ocfs2_journal_dirty(handle, vb->vb_bh);
        if (status < 0) {
                mlog_errno(status);
                goto leave;
        }
 
-       clusters_to_add -= le32_to_cpu(xv->xr_clusters) - prev_clusters;
+       clusters_to_add -= le32_to_cpu(vb->vb_xv->xr_clusters) - prev_clusters;
 
-       if (why != RESTART_NONE && clusters_to_add) {
-               if (why == RESTART_META) {
-                       mlog(0, "restarting function.\n");
-                       restart_func = 1;
-               } else {
-                       BUG_ON(why != RESTART_TRANS);
-
-                       mlog(0, "restarting transaction.\n");
-                       /* TODO: This can be more intelligent. */
-                       credits = ocfs2_calc_extend_credits(osb->sb,
-                                                           et.et_root_el,
-                                                           clusters_to_add);
-                       status = ocfs2_extend_trans(handle, credits);
-                       if (status < 0) {
-                               /* handle still has to be committed at
-                                * this point. */
-                               status = -ENOMEM;
-                               mlog_errno(status);
-                               goto leave;
-                       }
-                       goto restarted_transaction;
-               }
-       }
+       /*
+        * We should have already allocated enough space before the transaction,
+        * so no need to restart.
+        */
+       BUG_ON(why != RESTART_NONE || clusters_to_add);
 
 leave:
-       if (handle) {
-               ocfs2_commit_trans(osb, handle);
-               handle = NULL;
-       }
-       if (data_ac) {
-               ocfs2_free_alloc_context(data_ac);
-               data_ac = NULL;
-       }
-       if (meta_ac) {
-               ocfs2_free_alloc_context(meta_ac);
-               meta_ac = NULL;
-       }
-       if ((!status) && restart_func) {
-               restart_func = 0;
-               goto restart_all;
-       }
 
        return status;
 }
 
 static int __ocfs2_remove_xattr_range(struct inode *inode,
-                                     struct buffer_head *root_bh,
-                                     struct ocfs2_xattr_value_root *xv,
+                                     struct ocfs2_xattr_value_buf *vb,
                                      u32 cpos, u32 phys_cpos, u32 len,
-                                     struct ocfs2_cached_dealloc_ctxt *dealloc)
+                                     struct ocfs2_xattr_set_ctxt *ctxt)
 {
        int ret;
        u64 phys_blkno = ocfs2_clusters_to_blocks(inode->i_sb, phys_cpos);
-       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
-       struct inode *tl_inode = osb->osb_tl_inode;
-       handle_t *handle;
-       struct ocfs2_alloc_context *meta_ac = NULL;
+       handle_t *handle = ctxt->handle;
        struct ocfs2_extent_tree et;
 
-       ocfs2_init_xattr_value_extent_tree(&et, inode, root_bh, xv);
+       ocfs2_init_xattr_value_extent_tree(&et, inode, vb);
 
-       ret = ocfs2_lock_allocators(inode, &et, 0, 1, NULL, &meta_ac);
+       ret = vb->vb_access(handle, inode, vb->vb_bh,
+                           OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
-               mlog_errno(ret);
-               return ret;
-       }
-
-       mutex_lock(&tl_inode->i_mutex);
-
-       if (ocfs2_truncate_log_needs_flush(osb)) {
-               ret = __ocfs2_flush_truncate_log(osb);
-               if (ret < 0) {
-                       mlog_errno(ret);
-                       goto out;
-               }
-       }
-
-       handle = ocfs2_start_trans(osb, OCFS2_REMOVE_EXTENT_CREDITS);
-       if (IS_ERR(handle)) {
-               ret = PTR_ERR(handle);
                mlog_errno(ret);
                goto out;
        }
 
-       ret = ocfs2_journal_access(handle, inode, root_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
-       if (ret) {
-               mlog_errno(ret);
-               goto out_commit;
-       }
-
-       ret = ocfs2_remove_extent(inode, &et, cpos, len, handle, meta_ac,
-                                 dealloc);
+       ret = ocfs2_remove_extent(inode, &et, cpos, len, handle, ctxt->meta_ac,
+                                 &ctxt->dealloc);
        if (ret) {
                mlog_errno(ret);
-               goto out_commit;
+               goto out;
        }
 
-       le32_add_cpu(&xv->xr_clusters, -len);
+       le32_add_cpu(&vb->vb_xv->xr_clusters, -len);
 
-       ret = ocfs2_journal_dirty(handle, root_bh);
+       ret = ocfs2_journal_dirty(handle, vb->vb_bh);
        if (ret) {
                mlog_errno(ret);
-               goto out_commit;
+               goto out;
        }
 
-       ret = ocfs2_truncate_log_append(osb, handle, phys_blkno, len);
+       ret = ocfs2_cache_cluster_dealloc(&ctxt->dealloc, phys_blkno, len);
        if (ret)
                mlog_errno(ret);
 
-out_commit:
-       ocfs2_commit_trans(osb, handle);
 out:
-       mutex_unlock(&tl_inode->i_mutex);
-
-       if (meta_ac)
-               ocfs2_free_alloc_context(meta_ac);
-
        return ret;
 }
 
 static int ocfs2_xattr_shrink_size(struct inode *inode,
                                   u32 old_clusters,
                                   u32 new_clusters,
-                                  struct buffer_head *root_bh,
-                                  struct ocfs2_xattr_value_root *xv)
+                                  struct ocfs2_xattr_value_buf *vb,
+                                  struct ocfs2_xattr_set_ctxt *ctxt)
 {
        int ret = 0;
        u32 trunc_len, cpos, phys_cpos, alloc_size;
        u64 block;
-       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
-       struct ocfs2_cached_dealloc_ctxt dealloc;
-
-       ocfs2_init_dealloc_ctxt(&dealloc);
 
        if (old_clusters <= new_clusters)
                return 0;
@@ -414,7 +700,8 @@ static int ocfs2_xattr_shrink_size(struct inode *inode,
        trunc_len = old_clusters - new_clusters;
        while (trunc_len) {
                ret = ocfs2_xattr_get_clusters(inode, cpos, &phys_cpos,
-                                              &alloc_size, &xv->xr_list);
+                                              &alloc_size,
+                                              &vb->vb_xv->xr_list);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -423,9 +710,9 @@ static int ocfs2_xattr_shrink_size(struct inode *inode,
                if (alloc_size > trunc_len)
                        alloc_size = trunc_len;
 
-               ret = __ocfs2_remove_xattr_range(inode, root_bh, xv, cpos,
+               ret = __ocfs2_remove_xattr_range(inode, vb, cpos,
                                                 phys_cpos, alloc_size,
-                                                &dealloc);
+                                                ctxt);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -439,20 +726,17 @@ static int ocfs2_xattr_shrink_size(struct inode *inode,
        }
 
 out:
-       ocfs2_schedule_truncate_log_flush(osb, 1);
-       ocfs2_run_deallocs(osb, &dealloc);
-
        return ret;
 }
 
 static int ocfs2_xattr_value_truncate(struct inode *inode,
-                                     struct buffer_head *root_bh,
-                                     struct ocfs2_xattr_value_root *xv,
-                                     int len)
+                                     struct ocfs2_xattr_value_buf *vb,
+                                     int len,
+                                     struct ocfs2_xattr_set_ctxt *ctxt)
 {
        int ret;
        u32 new_clusters = ocfs2_clusters_for_bytes(inode->i_sb, len);
-       u32 old_clusters = le32_to_cpu(xv->xr_clusters);
+       u32 old_clusters = le32_to_cpu(vb->vb_xv->xr_clusters);
 
        if (new_clusters == old_clusters)
                return 0;
@@ -460,11 +744,11 @@ static int ocfs2_xattr_value_truncate(struct inode *inode,
        if (new_clusters > old_clusters)
                ret = ocfs2_xattr_extend_allocation(inode,
                                                    new_clusters - old_clusters,
-                                                   root_bh, xv);
+                                                   vb, ctxt);
        else
                ret = ocfs2_xattr_shrink_size(inode,
                                              old_clusters, new_clusters,
-                                             root_bh, xv);
+                                             vb, ctxt);
 
        return ret;
 }
@@ -554,18 +838,14 @@ static int ocfs2_xattr_block_list(struct inode *inode,
        if (!di->i_xattr_loc)
                return ret;
 
-       ret = ocfs2_read_block(inode, le64_to_cpu(di->i_xattr_loc), &blk_bh);
+       ret = ocfs2_read_xattr_block(inode, le64_to_cpu(di->i_xattr_loc),
+                                    &blk_bh);
        if (ret < 0) {
                mlog_errno(ret);
                return ret;
        }
 
        xb = (struct ocfs2_xattr_block *)blk_bh->b_data;
-       if (!OCFS2_IS_VALID_XATTR_BLOCK(xb)) {
-               ret = -EIO;
-               goto cleanup;
-       }
-
        if (!(le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED)) {
                struct ocfs2_xattr_header *header = &xb->xb_attrs.xb_header;
                ret = ocfs2_xattr_list_entries(inode, header,
@@ -575,7 +855,7 @@ static int ocfs2_xattr_block_list(struct inode *inode,
                ret = ocfs2_xattr_tree_list_index_block(inode, xt,
                                                   buffer, buffer_size);
        }
-cleanup:
+
        brelse(blk_bh);
 
        return ret;
@@ -685,7 +965,7 @@ static int ocfs2_xattr_get_value_outside(struct inode *inode,
                blkno = ocfs2_clusters_to_blocks(inode->i_sb, p_cluster);
                /* Copy ocfs2_xattr_value */
                for (i = 0; i < num_clusters * bpc; i++, blkno++) {
-                       ret = ocfs2_read_block(inode, blkno, &bh);
+                       ret = ocfs2_read_block(inode, blkno, &bh, NULL);
                        if (ret) {
                                mlog_errno(ret);
                                goto out;
@@ -769,7 +1049,12 @@ static int ocfs2_xattr_block_get(struct inode *inode,
        size_t size;
        int ret = -ENODATA, name_offset, name_len, block_off, i;
 
-       memset(&xs->bucket, 0, sizeof(xs->bucket));
+       xs->bucket = ocfs2_xattr_bucket_new(inode);
+       if (!xs->bucket) {
+               ret = -ENOMEM;
+               mlog_errno(ret);
+               goto cleanup;
+       }
 
        ret = ocfs2_xattr_block_find(inode, name_index, name, xs);
        if (ret) {
@@ -795,11 +1080,11 @@ static int ocfs2_xattr_block_get(struct inode *inode,
 
                if (le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED) {
                        ret = ocfs2_xattr_bucket_get_name_value(inode,
-                                                               xs->bucket.xh,
+                                                               bucket_xh(xs->bucket),
                                                                i,
                                                                &block_off,
                                                                &name_offset);
-                       xs->base = xs->bucket.bhs[block_off]->b_data;
+                       xs->base = bucket_block(xs->bucket, block_off);
                }
                if (ocfs2_xattr_is_local(xs->here)) {
                        memcpy(buffer, (void *)xs->base +
@@ -817,21 +1102,15 @@ static int ocfs2_xattr_block_get(struct inode *inode,
        }
        ret = size;
 cleanup:
-       for (i = 0; i < OCFS2_XATTR_MAX_BLOCKS_PER_BUCKET; i++)
-               brelse(xs->bucket.bhs[i]);
-       memset(&xs->bucket, 0, sizeof(xs->bucket));
+       ocfs2_xattr_bucket_free(xs->bucket);
 
        brelse(xs->xattr_bh);
        xs->xattr_bh = NULL;
        return ret;
 }
 
-/* ocfs2_xattr_get()
- *
- * Copy an extended attribute into the buffer provided.
- * Buffer is NULL to compute the size of buffer required.
- */
-static int ocfs2_xattr_get(struct inode *inode,
+int ocfs2_xattr_get_nolock(struct inode *inode,
+                          struct buffer_head *di_bh,
                           int name_index,
                           const char *name,
                           void *buffer,
@@ -839,7 +1118,6 @@ static int ocfs2_xattr_get(struct inode *inode,
 {
        int ret;
        struct ocfs2_dinode *di = NULL;
-       struct buffer_head *di_bh = NULL;
        struct ocfs2_inode_info *oi = OCFS2_I(inode);
        struct ocfs2_xattr_search xis = {
                .not_found = -ENODATA,
@@ -854,11 +1132,6 @@ static int ocfs2_xattr_get(struct inode *inode,
        if (!(oi->ip_dyn_features & OCFS2_HAS_XATTR_FL))
                ret = -ENODATA;
 
-       ret = ocfs2_inode_lock(inode, &di_bh, 0);
-       if (ret < 0) {
-               mlog_errno(ret);
-               return ret;
-       }
        xis.inode_bh = xbs.inode_bh = di_bh;
        di = (struct ocfs2_dinode *)di_bh->b_data;
 
@@ -869,52 +1142,70 @@ static int ocfs2_xattr_get(struct inode *inode,
                ret = ocfs2_xattr_block_get(inode, name_index, name, buffer,
                                            buffer_size, &xbs);
        up_read(&oi->ip_xattr_sem);
-       ocfs2_inode_unlock(inode, 0);
-
-       brelse(di_bh);
 
        return ret;
 }
 
-static int __ocfs2_xattr_set_value_outside(struct inode *inode,
-                                          struct ocfs2_xattr_value_root *xv,
-                                          const void *value,
-                                          int value_len)
+/* ocfs2_xattr_get()
+ *
+ * Copy an extended attribute into the buffer provided.
+ * Buffer is NULL to compute the size of buffer required.
+ */
+static int ocfs2_xattr_get(struct inode *inode,
+                          int name_index,
+                          const char *name,
+                          void *buffer,
+                          size_t buffer_size)
 {
-       int ret = 0, i, cp_len, credits;
-       u16 blocksize = inode->i_sb->s_blocksize;
-       u32 p_cluster, num_clusters;
-       u32 cpos = 0, bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1);
+       int ret;
+       struct buffer_head *di_bh = NULL;
+
+       ret = ocfs2_inode_lock(inode, &di_bh, 0);
+       if (ret < 0) {
+               mlog_errno(ret);
+               return ret;
+       }
+       ret = ocfs2_xattr_get_nolock(inode, di_bh, name_index,
+                                    name, buffer, buffer_size);
+
+       ocfs2_inode_unlock(inode, 0);
+
+       brelse(di_bh);
+
+       return ret;
+}
+
+static int __ocfs2_xattr_set_value_outside(struct inode *inode,
+                                          handle_t *handle,
+                                          struct ocfs2_xattr_value_root *xv,
+                                          const void *value,
+                                          int value_len)
+{
+       int ret = 0, i, cp_len;
+       u16 blocksize = inode->i_sb->s_blocksize;
+       u32 p_cluster, num_clusters;
+       u32 cpos = 0, bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1);
        u32 clusters = ocfs2_clusters_for_bytes(inode->i_sb, value_len);
        u64 blkno;
        struct buffer_head *bh = NULL;
-       handle_t *handle;
 
        BUG_ON(clusters > le32_to_cpu(xv->xr_clusters));
 
-       credits = clusters * bpc;
-       handle = ocfs2_start_trans(OCFS2_SB(inode->i_sb), credits);
-       if (IS_ERR(handle)) {
-               ret = PTR_ERR(handle);
-               mlog_errno(ret);
-               goto out;
-       }
-
        while (cpos < clusters) {
                ret = ocfs2_xattr_get_clusters(inode, cpos, &p_cluster,
                                               &num_clusters, &xv->xr_list);
                if (ret) {
                        mlog_errno(ret);
-                       goto out_commit;
+                       goto out;
                }
 
                blkno = ocfs2_clusters_to_blocks(inode->i_sb, p_cluster);
 
                for (i = 0; i < num_clusters * bpc; i++, blkno++) {
-                       ret = ocfs2_read_block(inode, blkno, &bh);
+                       ret = ocfs2_read_block(inode, blkno, &bh, NULL);
                        if (ret) {
                                mlog_errno(ret);
-                               goto out_commit;
+                               goto out;
                        }
 
                        ret = ocfs2_journal_access(handle,
@@ -923,7 +1214,7 @@ static int __ocfs2_xattr_set_value_outside(struct inode *inode,
                                                   OCFS2_JOURNAL_ACCESS_WRITE);
                        if (ret < 0) {
                                mlog_errno(ret);
-                               goto out_commit;
+                               goto out;
                        }
 
                        cp_len = value_len > blocksize ? blocksize : value_len;
@@ -937,7 +1228,7 @@ static int __ocfs2_xattr_set_value_outside(struct inode *inode,
                        ret = ocfs2_journal_dirty(handle, bh);
                        if (ret < 0) {
                                mlog_errno(ret);
-                               goto out_commit;
+                               goto out;
                        }
                        brelse(bh);
                        bh = NULL;
@@ -951,8 +1242,6 @@ static int __ocfs2_xattr_set_value_outside(struct inode *inode,
                }
                cpos += num_clusters;
        }
-out_commit:
-       ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle);
 out:
        brelse(bh);
 
@@ -960,28 +1249,22 @@ out:
 }
 
 static int ocfs2_xattr_cleanup(struct inode *inode,
+                              handle_t *handle,
                               struct ocfs2_xattr_info *xi,
                               struct ocfs2_xattr_search *xs,
+                              struct ocfs2_xattr_value_buf *vb,
                               size_t offs)
 {
-       handle_t *handle = NULL;
        int ret = 0;
        size_t name_len = strlen(xi->name);
        void *val = xs->base + offs;
        size_t size = OCFS2_XATTR_SIZE(name_len) + OCFS2_XATTR_ROOT_SIZE;
 
-       handle = ocfs2_start_trans((OCFS2_SB(inode->i_sb)),
-                                  OCFS2_XATTR_BLOCK_UPDATE_CREDITS);
-       if (IS_ERR(handle)) {
-               ret = PTR_ERR(handle);
-               mlog_errno(ret);
-               goto out;
-       }
-       ret = ocfs2_journal_access(handle, inode, xs->xattr_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = vb->vb_access(handle, inode, vb->vb_bh,
+                           OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
-               goto out_commit;
+               goto out;
        }
        /* Decrease xattr count */
        le16_add_cpu(&xs->header->xh_count, -1);
@@ -989,35 +1272,27 @@ static int ocfs2_xattr_cleanup(struct inode *inode,
        memset((void *)xs->here, 0, sizeof(struct ocfs2_xattr_entry));
        memset(val, 0, size);
 
-       ret = ocfs2_journal_dirty(handle, xs->xattr_bh);
+       ret = ocfs2_journal_dirty(handle, vb->vb_bh);
        if (ret < 0)
                mlog_errno(ret);
-out_commit:
-       ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle);
 out:
        return ret;
 }
 
 static int ocfs2_xattr_update_entry(struct inode *inode,
+                                   handle_t *handle,
                                    struct ocfs2_xattr_info *xi,
                                    struct ocfs2_xattr_search *xs,
+                                   struct ocfs2_xattr_value_buf *vb,
                                    size_t offs)
 {
-       handle_t *handle = NULL;
-       int ret = 0;
+       int ret;
 
-       handle = ocfs2_start_trans((OCFS2_SB(inode->i_sb)),
-                                  OCFS2_XATTR_BLOCK_UPDATE_CREDITS);
-       if (IS_ERR(handle)) {
-               ret = PTR_ERR(handle);
-               mlog_errno(ret);
-               goto out;
-       }
-       ret = ocfs2_journal_access(handle, inode, xs->xattr_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = vb->vb_access(handle, inode, vb->vb_bh,
+                           OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
-               goto out_commit;
+               goto out;
        }
 
        xs->here->xe_name_offset = cpu_to_le16(offs);
@@ -1028,11 +1303,9 @@ static int ocfs2_xattr_update_entry(struct inode *inode,
                ocfs2_xattr_set_local(xs->here, 0);
        ocfs2_xattr_hash_entry(inode, xs->header, xs->here);
 
-       ret = ocfs2_journal_dirty(handle, xs->xattr_bh);
+       ret = ocfs2_journal_dirty(handle, vb->vb_bh);
        if (ret < 0)
                mlog_errno(ret);
-out_commit:
-       ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle);
 out:
        return ret;
 }
@@ -1045,6 +1318,8 @@ out:
 static int ocfs2_xattr_set_value_outside(struct inode *inode,
                                         struct ocfs2_xattr_info *xi,
                                         struct ocfs2_xattr_search *xs,
+                                        struct ocfs2_xattr_set_ctxt *ctxt,
+                                        struct ocfs2_xattr_value_buf *vb,
                                         size_t offs)
 {
        size_t name_len = strlen(xi->name);
@@ -1062,20 +1337,20 @@ static int ocfs2_xattr_set_value_outside(struct inode *inode,
        xv->xr_list.l_tree_depth = 0;
        xv->xr_list.l_count = cpu_to_le16(1);
        xv->xr_list.l_next_free_rec = 0;
+       vb->vb_xv = xv;
 
-       ret = ocfs2_xattr_value_truncate(inode, xs->xattr_bh, xv,
-                                        xi->value_len);
+       ret = ocfs2_xattr_value_truncate(inode, vb, xi->value_len, ctxt);
        if (ret < 0) {
                mlog_errno(ret);
                return ret;
        }
-       ret = __ocfs2_xattr_set_value_outside(inode, xv, xi->value,
-                                             xi->value_len);
+       ret = ocfs2_xattr_update_entry(inode, ctxt->handle, xi, xs, vb, offs);
        if (ret < 0) {
                mlog_errno(ret);
                return ret;
        }
-       ret = ocfs2_xattr_update_entry(inode, xi, xs, offs);
+       ret = __ocfs2_xattr_set_value_outside(inode, ctxt->handle, vb->vb_xv,
+                                             xi->value, xi->value_len);
        if (ret < 0)
                mlog_errno(ret);
 
@@ -1195,6 +1470,7 @@ static void ocfs2_xattr_set_entry_local(struct inode *inode,
 static int ocfs2_xattr_set_entry(struct inode *inode,
                                 struct ocfs2_xattr_info *xi,
                                 struct ocfs2_xattr_search *xs,
+                                struct ocfs2_xattr_set_ctxt *ctxt,
                                 int flag)
 {
        struct ocfs2_xattr_entry *last;
@@ -1202,7 +1478,7 @@ static int ocfs2_xattr_set_entry(struct inode *inode,
        struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data;
        size_t min_offs = xs->end - xs->base, name_len = strlen(xi->name);
        size_t size_l = 0;
-       handle_t *handle = NULL;
+       handle_t *handle = ctxt->handle;
        int free, i, ret;
        struct ocfs2_xattr_info xi_l = {
                .name_index = xi->name_index,
@@ -1210,6 +1486,16 @@ static int ocfs2_xattr_set_entry(struct inode *inode,
                .value = xi->value,
                .value_len = xi->value_len,
        };
+       struct ocfs2_xattr_value_buf vb = {
+               .vb_bh = xs->xattr_bh,
+               .vb_access = ocfs2_journal_access_di,
+       };
+
+       if (!(flag & OCFS2_INLINE_XATTR_FL)) {
+               BUG_ON(xs->xattr_bh == xs->inode_bh);
+               vb.vb_access = ocfs2_journal_access_xb;
+       } else
+               BUG_ON(xs->xattr_bh != xs->inode_bh);
 
        /* Compute min_offs, last and free space. */
        last = xs->header->xh_entries;
@@ -1265,15 +1551,14 @@ static int ocfs2_xattr_set_entry(struct inode *inode,
                if (ocfs2_xattr_is_local(xs->here) && size == size_l) {
                        /* Replace existing local xattr with tree root */
                        ret = ocfs2_xattr_set_value_outside(inode, xi, xs,
-                                                           offs);
+                                                           ctxt, &vb, offs);
                        if (ret < 0)
                                mlog_errno(ret);
                        goto out;
                } else if (!ocfs2_xattr_is_local(xs->here)) {
                        /* For existing xattr which has value outside */
-                       struct ocfs2_xattr_value_root *xv = NULL;
-                       xv = (struct ocfs2_xattr_value_root *)(val +
-                               OCFS2_XATTR_SIZE(name_len));
+                       vb.vb_xv = (struct ocfs2_xattr_value_root *)
+                               (val + OCFS2_XATTR_SIZE(name_len));
 
                        if (xi->value_len > OCFS2_XATTR_INLINE_SIZE) {
                                /*
@@ -1282,27 +1567,30 @@ static int ocfs2_xattr_set_entry(struct inode *inode,
                                 * then set new value with set_value_outside().
                                 */
                                ret = ocfs2_xattr_value_truncate(inode,
-                                                                xs->xattr_bh,
-                                                                xv,
-                                                                xi->value_len);
+                                                                &vb,
+                                                                xi->value_len,
+                                                                ctxt);
                                if (ret < 0) {
                                        mlog_errno(ret);
                                        goto out;
                                }
 
-                               ret = __ocfs2_xattr_set_value_outside(inode,
-                                                               xv,
-                                                               xi->value,
-                                                               xi->value_len);
+                               ret = ocfs2_xattr_update_entry(inode,
+                                                              handle,
+                                                              xi,
+                                                              xs,
+                                                              &vb,
+                                                              offs);
                                if (ret < 0) {
                                        mlog_errno(ret);
                                        goto out;
                                }
 
-                               ret = ocfs2_xattr_update_entry(inode,
-                                                              xi,
-                                                              xs,
-                                                              offs);
+                               ret = __ocfs2_xattr_set_value_outside(inode,
+                                                               handle,
+                                                               vb.vb_xv,
+                                                               xi->value,
+                                                               xi->value_len);
                                if (ret < 0)
                                        mlog_errno(ret);
                                goto out;
@@ -1312,44 +1600,28 @@ static int ocfs2_xattr_set_entry(struct inode *inode,
                                 * just trucate old value to zero.
                                 */
                                 ret = ocfs2_xattr_value_truncate(inode,
-                                                                xs->xattr_bh,
-                                                                xv,
-                                                                0);
+                                                                 &vb,
+                                                                 0,
+                                                                 ctxt);
                                if (ret < 0)
                                        mlog_errno(ret);
                        }
                }
        }
 
-       handle = ocfs2_start_trans((OCFS2_SB(inode->i_sb)),
-                                  OCFS2_INODE_UPDATE_CREDITS);
-       if (IS_ERR(handle)) {
-               ret = PTR_ERR(handle);
-               mlog_errno(ret);
-               goto out;
-       }
-
-       ret = ocfs2_journal_access(handle, inode, xs->inode_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = ocfs2_journal_access_di(handle, inode, xs->inode_bh,
+                                     OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
-               goto out_commit;
+               goto out;
        }
 
        if (!(flag & OCFS2_INLINE_XATTR_FL)) {
-               /* set extended attribute in external block. */
-               ret = ocfs2_extend_trans(handle,
-                                        OCFS2_INODE_UPDATE_CREDITS +
-                                        OCFS2_XATTR_BLOCK_UPDATE_CREDITS);
-               if (ret) {
-                       mlog_errno(ret);
-                       goto out_commit;
-               }
-               ret = ocfs2_journal_access(handle, inode, xs->xattr_bh,
-                                          OCFS2_JOURNAL_ACCESS_WRITE);
+               ret = vb.vb_access(handle, inode, vb.vb_bh,
+                                  OCFS2_JOURNAL_ACCESS_WRITE);
                if (ret) {
                        mlog_errno(ret);
-                       goto out_commit;
+                       goto out;
                }
        }
 
@@ -1363,7 +1635,7 @@ static int ocfs2_xattr_set_entry(struct inode *inode,
                ret = ocfs2_journal_dirty(handle, xs->xattr_bh);
                if (ret < 0) {
                        mlog_errno(ret);
-                       goto out_commit;
+                       goto out;
                }
        }
 
@@ -1391,25 +1663,19 @@ static int ocfs2_xattr_set_entry(struct inode *inode,
        oi->ip_dyn_features |= flag;
        di->i_dyn_features = cpu_to_le16(oi->ip_dyn_features);
        spin_unlock(&oi->ip_lock);
-       /* Update inode ctime */
-       inode->i_ctime = CURRENT_TIME;
-       di->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec);
-       di->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec);
 
        ret = ocfs2_journal_dirty(handle, xs->inode_bh);
        if (ret < 0)
                mlog_errno(ret);
 
-out_commit:
-       ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle);
-
        if (!ret && xi->value_len > OCFS2_XATTR_INLINE_SIZE) {
                /*
                 * Set value outside in B tree.
                 * This is the second step for value size > INLINE_SIZE.
                 */
                size_t offs = le16_to_cpu(xs->here->xe_name_offset);
-               ret = ocfs2_xattr_set_value_outside(inode, xi, xs, offs);
+               ret = ocfs2_xattr_set_value_outside(inode, xi, xs, ctxt,
+                                                   &vb, offs);
                if (ret < 0) {
                        int ret2;
 
@@ -1418,41 +1684,56 @@ out_commit:
                         * If set value outside failed, we have to clean
                         * the junk tree root we have already set in local.
                         */
-                       ret2 = ocfs2_xattr_cleanup(inode, xi, xs, offs);
+                       ret2 = ocfs2_xattr_cleanup(inode, ctxt->handle,
+                                                  xi, xs, &vb, offs);
                        if (ret2 < 0)
                                mlog_errno(ret2);
                }
        }
 out:
        return ret;
-
 }
 
 static int ocfs2_remove_value_outside(struct inode*inode,
-                                     struct buffer_head *bh,
+                                     struct ocfs2_xattr_value_buf *vb,
                                      struct ocfs2_xattr_header *header)
 {
        int ret = 0, i;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       struct ocfs2_xattr_set_ctxt ctxt = { NULL, NULL, };
+
+       ocfs2_init_dealloc_ctxt(&ctxt.dealloc);
+
+       ctxt.handle = ocfs2_start_trans(osb,
+                                       ocfs2_remove_extent_credits(osb->sb));
+       if (IS_ERR(ctxt.handle)) {
+               ret = PTR_ERR(ctxt.handle);
+               mlog_errno(ret);
+               goto out;
+       }
 
        for (i = 0; i < le16_to_cpu(header->xh_count); i++) {
                struct ocfs2_xattr_entry *entry = &header->xh_entries[i];
 
                if (!ocfs2_xattr_is_local(entry)) {
-                       struct ocfs2_xattr_value_root *xv;
                        void *val;
 
                        val = (void *)header +
                                le16_to_cpu(entry->xe_name_offset);
-                       xv = (struct ocfs2_xattr_value_root *)
+                       vb->vb_xv = (struct ocfs2_xattr_value_root *)
                                (val + OCFS2_XATTR_SIZE(entry->xe_name_len));
-                       ret = ocfs2_xattr_value_truncate(inode, bh, xv, 0);
+                       ret = ocfs2_xattr_value_truncate(inode, vb, 0, &ctxt);
                        if (ret < 0) {
                                mlog_errno(ret);
-                               return ret;
+                               break;
                        }
                }
        }
 
+       ocfs2_commit_trans(osb, ctxt.handle);
+       ocfs2_schedule_truncate_log_flush(osb, 1);
+       ocfs2_run_deallocs(osb, &ctxt.dealloc);
+out:
        return ret;
 }
 
@@ -1463,12 +1744,16 @@ static int ocfs2_xattr_ibody_remove(struct inode *inode,
        struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
        struct ocfs2_xattr_header *header;
        int ret;
+       struct ocfs2_xattr_value_buf vb = {
+               .vb_bh = di_bh,
+               .vb_access = ocfs2_journal_access_di,
+       };
 
        header = (struct ocfs2_xattr_header *)
                 ((void *)di + inode->i_sb->s_blocksize -
                 le16_to_cpu(di->i_xattr_inline_size));
 
-       ret = ocfs2_remove_value_outside(inode, di_bh, header);
+       ret = ocfs2_remove_value_outside(inode, &vb, header);
 
        return ret;
 }
@@ -1478,11 +1763,15 @@ static int ocfs2_xattr_block_remove(struct inode *inode,
 {
        struct ocfs2_xattr_block *xb;
        int ret = 0;
+       struct ocfs2_xattr_value_buf vb = {
+               .vb_bh = blk_bh,
+               .vb_access = ocfs2_journal_access_xb,
+       };
 
        xb = (struct ocfs2_xattr_block *)blk_bh->b_data;
        if (!(le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED)) {
                struct ocfs2_xattr_header *header = &(xb->xb_attrs.xb_header);
-               ret = ocfs2_remove_value_outside(inode, blk_bh, header);
+               ret = ocfs2_remove_value_outside(inode, &vb, header);
        } else
                ret = ocfs2_delete_xattr_index_block(inode, blk_bh);
 
@@ -1502,24 +1791,19 @@ static int ocfs2_xattr_free_block(struct inode *inode,
        u64 blk, bg_blkno;
        u16 bit;
 
-       ret = ocfs2_read_block(inode, block, &blk_bh);
+       ret = ocfs2_read_xattr_block(inode, block, &blk_bh);
        if (ret < 0) {
                mlog_errno(ret);
                goto out;
        }
 
-       xb = (struct ocfs2_xattr_block *)blk_bh->b_data;
-       if (!OCFS2_IS_VALID_XATTR_BLOCK(xb)) {
-               ret = -EIO;
-               goto out;
-       }
-
        ret = ocfs2_xattr_block_remove(inode, blk_bh);
        if (ret < 0) {
                mlog_errno(ret);
                goto out;
        }
 
+       xb = (struct ocfs2_xattr_block *)blk_bh->b_data;
        blk = le64_to_cpu(xb->xb_blkno);
        bit = le16_to_cpu(xb->xb_suballoc_bit);
        bg_blkno = ocfs2_which_suballoc_group(blk, bit);
@@ -1606,8 +1890,8 @@ int ocfs2_xattr_remove(struct inode *inode, struct buffer_head *di_bh)
                mlog_errno(ret);
                goto out;
        }
-       ret = ocfs2_journal_access(handle, inode, di_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = ocfs2_journal_access_di(handle, inode, di_bh,
+                                     OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
                goto out_commit;
@@ -1714,7 +1998,8 @@ static int ocfs2_xattr_ibody_find(struct inode *inode,
  */
 static int ocfs2_xattr_ibody_set(struct inode *inode,
                                 struct ocfs2_xattr_info *xi,
-                                struct ocfs2_xattr_search *xs)
+                                struct ocfs2_xattr_search *xs,
+                                struct ocfs2_xattr_set_ctxt *ctxt)
 {
        struct ocfs2_inode_info *oi = OCFS2_I(inode);
        struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data;
@@ -1731,7 +2016,7 @@ static int ocfs2_xattr_ibody_set(struct inode *inode,
                }
        }
 
-       ret = ocfs2_xattr_set_entry(inode, xi, xs,
+       ret = ocfs2_xattr_set_entry(inode, xi, xs, ctxt,
                                (OCFS2_INLINE_XATTR_FL | OCFS2_HAS_XATTR_FL));
 out:
        up_write(&oi->ip_alloc_sem);
@@ -1758,19 +2043,15 @@ static int ocfs2_xattr_block_find(struct inode *inode,
        if (!di->i_xattr_loc)
                return ret;
 
-       ret = ocfs2_read_block(inode, le64_to_cpu(di->i_xattr_loc), &blk_bh);
+       ret = ocfs2_read_xattr_block(inode, le64_to_cpu(di->i_xattr_loc),
+                                    &blk_bh);
        if (ret < 0) {
                mlog_errno(ret);
                return ret;
        }
 
-       xb = (struct ocfs2_xattr_block *)blk_bh->b_data;
-       if (!OCFS2_IS_VALID_XATTR_BLOCK(xb)) {
-               ret = -EIO;
-               goto cleanup;
-       }
-
        xs->xattr_bh = blk_bh;
+       xb = (struct ocfs2_xattr_block *)blk_bh->b_data;
 
        if (!(le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED)) {
                xs->header = &xb->xb_attrs.xb_header;
@@ -1804,13 +2085,13 @@ cleanup:
  */
 static int ocfs2_xattr_block_set(struct inode *inode,
                                 struct ocfs2_xattr_info *xi,
-                                struct ocfs2_xattr_search *xs)
+                                struct ocfs2_xattr_search *xs,
+                                struct ocfs2_xattr_set_ctxt *ctxt)
 {
        struct buffer_head *new_bh = NULL;
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
        struct ocfs2_dinode *di =  (struct ocfs2_dinode *)xs->inode_bh->b_data;
-       struct ocfs2_alloc_context *meta_ac = NULL;
-       handle_t *handle = NULL;
+       handle_t *handle = ctxt->handle;
        struct ocfs2_xattr_block *xblk = NULL;
        u16 suballoc_bit_start;
        u32 num_got;
@@ -1818,45 +2099,29 @@ static int ocfs2_xattr_block_set(struct inode *inode,
        int ret;
 
        if (!xs->xattr_bh) {
-               /*
-                * Alloc one external block for extended attribute
-                * outside of inode.
-                */
-               ret = ocfs2_reserve_new_metadata_blocks(osb, 1, &meta_ac);
+               ret = ocfs2_journal_access_di(handle, inode, xs->inode_bh,
+                                             OCFS2_JOURNAL_ACCESS_CREATE);
                if (ret < 0) {
                        mlog_errno(ret);
-                       goto out;
-               }
-               handle = ocfs2_start_trans(osb,
-                                          OCFS2_XATTR_BLOCK_CREATE_CREDITS);
-               if (IS_ERR(handle)) {
-                       ret = PTR_ERR(handle);
-                       mlog_errno(ret);
-                       goto out;
-               }
-               ret = ocfs2_journal_access(handle, inode, xs->inode_bh,
-                                          OCFS2_JOURNAL_ACCESS_CREATE);
-               if (ret < 0) {
-                       mlog_errno(ret);
-                       goto out_commit;
+                       goto end;
                }
 
-               ret = ocfs2_claim_metadata(osb, handle, meta_ac, 1,
+               ret = ocfs2_claim_metadata(osb, handle, ctxt->meta_ac, 1,
                                           &suballoc_bit_start, &num_got,
                                           &first_blkno);
                if (ret < 0) {
                        mlog_errno(ret);
-                       goto out_commit;
+                       goto end;
                }
 
                new_bh = sb_getblk(inode->i_sb, first_blkno);
                ocfs2_set_new_buffer_uptodate(inode, new_bh);
 
-               ret = ocfs2_journal_access(handle, inode, new_bh,
-                                          OCFS2_JOURNAL_ACCESS_CREATE);
+               ret = ocfs2_journal_access_xb(handle, inode, new_bh,
+                                             OCFS2_JOURNAL_ACCESS_CREATE);
                if (ret < 0) {
                        mlog_errno(ret);
-                       goto out_commit;
+                       goto end;
                }
 
                /* Initialize ocfs2_xattr_block */
@@ -1874,44 +2139,555 @@ static int ocfs2_xattr_block_set(struct inode *inode,
                xs->end = (void *)xblk + inode->i_sb->s_blocksize;
                xs->here = xs->header->xh_entries;
 
-
                ret = ocfs2_journal_dirty(handle, new_bh);
                if (ret < 0) {
                        mlog_errno(ret);
-                       goto out_commit;
+                       goto end;
                }
                di->i_xattr_loc = cpu_to_le64(first_blkno);
-               ret = ocfs2_journal_dirty(handle, xs->inode_bh);
-               if (ret < 0)
-                       mlog_errno(ret);
-out_commit:
-               ocfs2_commit_trans(osb, handle);
-out:
-               if (meta_ac)
-                       ocfs2_free_alloc_context(meta_ac);
-               if (ret < 0)
-                       return ret;
+               ocfs2_journal_dirty(handle, xs->inode_bh);
        } else
                xblk = (struct ocfs2_xattr_block *)xs->xattr_bh->b_data;
 
        if (!(le16_to_cpu(xblk->xb_flags) & OCFS2_XATTR_INDEXED)) {
                /* Set extended attribute into external block */
-               ret = ocfs2_xattr_set_entry(inode, xi, xs, OCFS2_HAS_XATTR_FL);
+               ret = ocfs2_xattr_set_entry(inode, xi, xs, ctxt,
+                                           OCFS2_HAS_XATTR_FL);
                if (!ret || ret != -ENOSPC)
                        goto end;
 
-               ret = ocfs2_xattr_create_index_block(inode, xs);
+               ret = ocfs2_xattr_create_index_block(inode, xs, ctxt);
                if (ret)
                        goto end;
        }
 
-       ret = ocfs2_xattr_set_entry_index_block(inode, xi, xs);
+       ret = ocfs2_xattr_set_entry_index_block(inode, xi, xs, ctxt);
 
 end:
 
        return ret;
 }
 
+/* Check whether the new xattr can be inserted into the inode. */
+static int ocfs2_xattr_can_be_in_inode(struct inode *inode,
+                                      struct ocfs2_xattr_info *xi,
+                                      struct ocfs2_xattr_search *xs)
+{
+       u64 value_size;
+       struct ocfs2_xattr_entry *last;
+       int free, i;
+       size_t min_offs = xs->end - xs->base;
+
+       if (!xs->header)
+               return 0;
+
+       last = xs->header->xh_entries;
+
+       for (i = 0; i < le16_to_cpu(xs->header->xh_count); i++) {
+               size_t offs = le16_to_cpu(last->xe_name_offset);
+               if (offs < min_offs)
+                       min_offs = offs;
+               last += 1;
+       }
+
+       free = min_offs - ((void *)last - xs->base) - sizeof(__u32);
+       if (free < 0)
+               return 0;
+
+       BUG_ON(!xs->not_found);
+
+       if (xi->value_len > OCFS2_XATTR_INLINE_SIZE)
+               value_size = OCFS2_XATTR_ROOT_SIZE;
+       else
+               value_size = OCFS2_XATTR_SIZE(xi->value_len);
+
+       if (free >= sizeof(struct ocfs2_xattr_entry) +
+                  OCFS2_XATTR_SIZE(strlen(xi->name)) + value_size)
+               return 1;
+
+       return 0;
+}
+
+static int ocfs2_calc_xattr_set_need(struct inode *inode,
+                                    struct ocfs2_dinode *di,
+                                    struct ocfs2_xattr_info *xi,
+                                    struct ocfs2_xattr_search *xis,
+                                    struct ocfs2_xattr_search *xbs,
+                                    int *clusters_need,
+                                    int *meta_need,
+                                    int *credits_need)
+{
+       int ret = 0, old_in_xb = 0;
+       int clusters_add = 0, meta_add = 0, credits = 0;
+       struct buffer_head *bh = NULL;
+       struct ocfs2_xattr_block *xb = NULL;
+       struct ocfs2_xattr_entry *xe = NULL;
+       struct ocfs2_xattr_value_root *xv = NULL;
+       char *base = NULL;
+       int name_offset, name_len = 0;
+       u32 new_clusters = ocfs2_clusters_for_bytes(inode->i_sb,
+                                                   xi->value_len);
+       u64 value_size;
+
+       /*
+        * Calculate the clusters we need to write.
+        * No matter whether we replace an old one or add a new one,
+        * we need this for writing.
+        */
+       if (xi->value_len > OCFS2_XATTR_INLINE_SIZE)
+               credits += new_clusters *
+                          ocfs2_clusters_to_blocks(inode->i_sb, 1);
+
+       if (xis->not_found && xbs->not_found) {
+               credits += ocfs2_blocks_per_xattr_bucket(inode->i_sb);
+
+               if (xi->value_len > OCFS2_XATTR_INLINE_SIZE) {
+                       clusters_add += new_clusters;
+                       credits += ocfs2_calc_extend_credits(inode->i_sb,
+                                                       &def_xv.xv.xr_list,
+                                                       new_clusters);
+               }
+
+               goto meta_guess;
+       }
+
+       if (!xis->not_found) {
+               xe = xis->here;
+               name_offset = le16_to_cpu(xe->xe_name_offset);
+               name_len = OCFS2_XATTR_SIZE(xe->xe_name_len);
+               base = xis->base;
+               credits += OCFS2_INODE_UPDATE_CREDITS;
+       } else {
+               int i, block_off = 0;
+               xb = (struct ocfs2_xattr_block *)xbs->xattr_bh->b_data;
+               xe = xbs->here;
+               name_offset = le16_to_cpu(xe->xe_name_offset);
+               name_len = OCFS2_XATTR_SIZE(xe->xe_name_len);
+               i = xbs->here - xbs->header->xh_entries;
+               old_in_xb = 1;
+
+               if (le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED) {
+                       ret = ocfs2_xattr_bucket_get_name_value(inode,
+                                                       bucket_xh(xbs->bucket),
+                                                       i, &block_off,
+                                                       &name_offset);
+                       base = bucket_block(xbs->bucket, block_off);
+                       credits += ocfs2_blocks_per_xattr_bucket(inode->i_sb);
+               } else {
+                       base = xbs->base;
+                       credits += OCFS2_XATTR_BLOCK_UPDATE_CREDITS;
+               }
+       }
+
+       /*
+        * delete a xattr doesn't need metadata and cluster allocation.
+        * so just calculate the credits and return.
+        *
+        * The credits for removing the value tree will be extended
+        * by ocfs2_remove_extent itself.
+        */
+       if (!xi->value) {
+               if (!ocfs2_xattr_is_local(xe))
+                       credits += ocfs2_remove_extent_credits(inode->i_sb);
+
+               goto out;
+       }
+
+       /* do cluster allocation guess first. */
+       value_size = le64_to_cpu(xe->xe_value_size);
+
+       if (old_in_xb) {
+               /*
+                * In xattr set, we always try to set the xe in inode first,
+                * so if it can be inserted into inode successfully, the old
+                * one will be removed from the xattr block, and this xattr
+                * will be inserted into inode as a new xattr in inode.
+                */
+               if (ocfs2_xattr_can_be_in_inode(inode, xi, xis)) {
+                       clusters_add += new_clusters;
+                       credits += ocfs2_remove_extent_credits(inode->i_sb) +
+                                   OCFS2_INODE_UPDATE_CREDITS;
+                       if (!ocfs2_xattr_is_local(xe))
+                               credits += ocfs2_calc_extend_credits(
+                                                       inode->i_sb,
+                                                       &def_xv.xv.xr_list,
+                                                       new_clusters);
+                       goto out;
+               }
+       }
+
+       if (xi->value_len > OCFS2_XATTR_INLINE_SIZE) {
+               /* the new values will be stored outside. */
+               u32 old_clusters = 0;
+
+               if (!ocfs2_xattr_is_local(xe)) {
+                       old_clusters =  ocfs2_clusters_for_bytes(inode->i_sb,
+                                                                value_size);
+                       xv = (struct ocfs2_xattr_value_root *)
+                            (base + name_offset + name_len);
+                       value_size = OCFS2_XATTR_ROOT_SIZE;
+               } else
+                       xv = &def_xv.xv;
+
+               if (old_clusters >= new_clusters) {
+                       credits += ocfs2_remove_extent_credits(inode->i_sb);
+                       goto out;
+               } else {
+                       meta_add += ocfs2_extend_meta_needed(&xv->xr_list);
+                       clusters_add += new_clusters - old_clusters;
+                       credits += ocfs2_calc_extend_credits(inode->i_sb,
+                                                            &xv->xr_list,
+                                                            new_clusters -
+                                                            old_clusters);
+                       if (value_size >= OCFS2_XATTR_ROOT_SIZE)
+                               goto out;
+               }
+       } else {
+               /*
+                * Now the new value will be stored inside. So if the new
+                * value is smaller than the size of value root or the old
+                * value, we don't need any allocation, otherwise we have
+                * to guess metadata allocation.
+                */
+               if ((ocfs2_xattr_is_local(xe) && value_size >= xi->value_len) ||
+                   (!ocfs2_xattr_is_local(xe) &&
+                    OCFS2_XATTR_ROOT_SIZE >= xi->value_len))
+                       goto out;
+       }
+
+meta_guess:
+       /* calculate metadata allocation. */
+       if (di->i_xattr_loc) {
+               if (!xbs->xattr_bh) {
+                       ret = ocfs2_read_xattr_block(inode,
+                                                    le64_to_cpu(di->i_xattr_loc),
+                                                    &bh);
+                       if (ret) {
+                               mlog_errno(ret);
+                               goto out;
+                       }
+
+                       xb = (struct ocfs2_xattr_block *)bh->b_data;
+               } else
+                       xb = (struct ocfs2_xattr_block *)xbs->xattr_bh->b_data;
+
+               /*
+                * If there is already an xattr tree, good, we can calculate
+                * like other b-trees. Otherwise we may have the chance of
+                * create a tree, the credit calculation is borrowed from
+                * ocfs2_calc_extend_credits with root_el = NULL. And the
+                * new tree will be cluster based, so no meta is needed.
+                */
+               if (le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED) {
+                       struct ocfs2_extent_list *el =
+                                &xb->xb_attrs.xb_root.xt_list;
+                       meta_add += ocfs2_extend_meta_needed(el);
+                       credits += ocfs2_calc_extend_credits(inode->i_sb,
+                                                            el, 1);
+               } else
+                       credits += OCFS2_SUBALLOC_ALLOC + 1;
+
+               /*
+                * This cluster will be used either for new bucket or for
+                * new xattr block.
+                * If the cluster size is the same as the bucket size, one
+                * more is needed since we may need to extend the bucket
+                * also.
+                */
+               clusters_add += 1;
+               credits += ocfs2_blocks_per_xattr_bucket(inode->i_sb);
+               if (OCFS2_XATTR_BUCKET_SIZE ==
+                       OCFS2_SB(inode->i_sb)->s_clustersize) {
+                       credits += ocfs2_blocks_per_xattr_bucket(inode->i_sb);
+                       clusters_add += 1;
+               }
+       } else {
+               meta_add += 1;
+               credits += OCFS2_XATTR_BLOCK_CREATE_CREDITS;
+       }
+out:
+       if (clusters_need)
+               *clusters_need = clusters_add;
+       if (meta_need)
+               *meta_need = meta_add;
+       if (credits_need)
+               *credits_need = credits;
+       brelse(bh);
+       return ret;
+}
+
+static int ocfs2_init_xattr_set_ctxt(struct inode *inode,
+                                    struct ocfs2_dinode *di,
+                                    struct ocfs2_xattr_info *xi,
+                                    struct ocfs2_xattr_search *xis,
+                                    struct ocfs2_xattr_search *xbs,
+                                    struct ocfs2_xattr_set_ctxt *ctxt,
+                                    int *credits)
+{
+       int clusters_add, meta_add, ret;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+       memset(ctxt, 0, sizeof(struct ocfs2_xattr_set_ctxt));
+
+       ocfs2_init_dealloc_ctxt(&ctxt->dealloc);
+
+       ret = ocfs2_calc_xattr_set_need(inode, di, xi, xis, xbs,
+                                       &clusters_add, &meta_add, credits);
+       if (ret) {
+               mlog_errno(ret);
+               return ret;
+       }
+
+       mlog(0, "Set xattr %s, reserve meta blocks = %d, clusters = %d, "
+            "credits = %d\n", xi->name, meta_add, clusters_add, *credits);
+
+       if (meta_add) {
+               ret = ocfs2_reserve_new_metadata_blocks(osb, meta_add,
+                                                       &ctxt->meta_ac);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+       }
+
+       if (clusters_add) {
+               ret = ocfs2_reserve_clusters(osb, clusters_add, &ctxt->data_ac);
+               if (ret)
+                       mlog_errno(ret);
+       }
+out:
+       if (ret) {
+               if (ctxt->meta_ac) {
+                       ocfs2_free_alloc_context(ctxt->meta_ac);
+                       ctxt->meta_ac = NULL;
+               }
+
+               /*
+                * We cannot have an error and a non null ctxt->data_ac.
+                */
+       }
+
+       return ret;
+}
+
+static int __ocfs2_xattr_set_handle(struct inode *inode,
+                                   struct ocfs2_dinode *di,
+                                   struct ocfs2_xattr_info *xi,
+                                   struct ocfs2_xattr_search *xis,
+                                   struct ocfs2_xattr_search *xbs,
+                                   struct ocfs2_xattr_set_ctxt *ctxt)
+{
+       int ret = 0, credits, old_found;
+
+       if (!xi->value) {
+               /* Remove existing extended attribute */
+               if (!xis->not_found)
+                       ret = ocfs2_xattr_ibody_set(inode, xi, xis, ctxt);
+               else if (!xbs->not_found)
+                       ret = ocfs2_xattr_block_set(inode, xi, xbs, ctxt);
+       } else {
+               /* We always try to set extended attribute into inode first*/
+               ret = ocfs2_xattr_ibody_set(inode, xi, xis, ctxt);
+               if (!ret && !xbs->not_found) {
+                       /*
+                        * If succeed and that extended attribute existing in
+                        * external block, then we will remove it.
+                        */
+                       xi->value = NULL;
+                       xi->value_len = 0;
+
+                       old_found = xis->not_found;
+                       xis->not_found = -ENODATA;
+                       ret = ocfs2_calc_xattr_set_need(inode,
+                                                       di,
+                                                       xi,
+                                                       xis,
+                                                       xbs,
+                                                       NULL,
+                                                       NULL,
+                                                       &credits);
+                       xis->not_found = old_found;
+                       if (ret) {
+                               mlog_errno(ret);
+                               goto out;
+                       }
+
+                       ret = ocfs2_extend_trans(ctxt->handle, credits +
+                                       ctxt->handle->h_buffer_credits);
+                       if (ret) {
+                               mlog_errno(ret);
+                               goto out;
+                       }
+                       ret = ocfs2_xattr_block_set(inode, xi, xbs, ctxt);
+               } else if (ret == -ENOSPC) {
+                       if (di->i_xattr_loc && !xbs->xattr_bh) {
+                               ret = ocfs2_xattr_block_find(inode,
+                                                            xi->name_index,
+                                                            xi->name, xbs);
+                               if (ret)
+                                       goto out;
+
+                               old_found = xis->not_found;
+                               xis->not_found = -ENODATA;
+                               ret = ocfs2_calc_xattr_set_need(inode,
+                                                               di,
+                                                               xi,
+                                                               xis,
+                                                               xbs,
+                                                               NULL,
+                                                               NULL,
+                                                               &credits);
+                               xis->not_found = old_found;
+                               if (ret) {
+                                       mlog_errno(ret);
+                                       goto out;
+                               }
+
+                               ret = ocfs2_extend_trans(ctxt->handle, credits +
+                                       ctxt->handle->h_buffer_credits);
+                               if (ret) {
+                                       mlog_errno(ret);
+                                       goto out;
+                               }
+                       }
+                       /*
+                        * If no space in inode, we will set extended attribute
+                        * into external block.
+                        */
+                       ret = ocfs2_xattr_block_set(inode, xi, xbs, ctxt);
+                       if (ret)
+                               goto out;
+                       if (!xis->not_found) {
+                               /*
+                                * If succeed and that extended attribute
+                                * existing in inode, we will remove it.
+                                */
+                               xi->value = NULL;
+                               xi->value_len = 0;
+                               xbs->not_found = -ENODATA;
+                               ret = ocfs2_calc_xattr_set_need(inode,
+                                                               di,
+                                                               xi,
+                                                               xis,
+                                                               xbs,
+                                                               NULL,
+                                                               NULL,
+                                                               &credits);
+                               if (ret) {
+                                       mlog_errno(ret);
+                                       goto out;
+                               }
+
+                               ret = ocfs2_extend_trans(ctxt->handle, credits +
+                                               ctxt->handle->h_buffer_credits);
+                               if (ret) {
+                                       mlog_errno(ret);
+                                       goto out;
+                               }
+                               ret = ocfs2_xattr_ibody_set(inode, xi,
+                                                           xis, ctxt);
+                       }
+               }
+       }
+
+       if (!ret) {
+               /* Update inode ctime. */
+               ret = ocfs2_journal_access(ctxt->handle, inode, xis->inode_bh,
+                                          OCFS2_JOURNAL_ACCESS_WRITE);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+
+               inode->i_ctime = CURRENT_TIME;
+               di->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec);
+               di->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec);
+               ocfs2_journal_dirty(ctxt->handle, xis->inode_bh);
+       }
+out:
+       return ret;
+}
+
+/*
+ * This function only called duing creating inode
+ * for init security/acl xattrs of the new inode.
+ * All transanction credits have been reserved in mknod.
+ */
+int ocfs2_xattr_set_handle(handle_t *handle,
+                          struct inode *inode,
+                          struct buffer_head *di_bh,
+                          int name_index,
+                          const char *name,
+                          const void *value,
+                          size_t value_len,
+                          int flags,
+                          struct ocfs2_alloc_context *meta_ac,
+                          struct ocfs2_alloc_context *data_ac)
+{
+       struct ocfs2_dinode *di;
+       int ret;
+
+       struct ocfs2_xattr_info xi = {
+               .name_index = name_index,
+               .name = name,
+               .value = value,
+               .value_len = value_len,
+       };
+
+       struct ocfs2_xattr_search xis = {
+               .not_found = -ENODATA,
+       };
+
+       struct ocfs2_xattr_search xbs = {
+               .not_found = -ENODATA,
+       };
+
+       struct ocfs2_xattr_set_ctxt ctxt = {
+               .handle = handle,
+               .meta_ac = meta_ac,
+               .data_ac = data_ac,
+       };
+
+       if (!ocfs2_supports_xattr(OCFS2_SB(inode->i_sb)))
+               return -EOPNOTSUPP;
+
+       /*
+        * In extreme situation, may need xattr bucket when
+        * block size is too small. And we have already reserved
+        * the credits for bucket in mknod.
+        */
+       if (inode->i_sb->s_blocksize == OCFS2_MIN_BLOCKSIZE) {
+               xbs.bucket = ocfs2_xattr_bucket_new(inode);
+               if (!xbs.bucket) {
+                       mlog_errno(-ENOMEM);
+                       return -ENOMEM;
+               }
+       }
+
+       xis.inode_bh = xbs.inode_bh = di_bh;
+       di = (struct ocfs2_dinode *)di_bh->b_data;
+
+       down_write(&OCFS2_I(inode)->ip_xattr_sem);
+
+       ret = ocfs2_xattr_ibody_find(inode, name_index, name, &xis);
+       if (ret)
+               goto cleanup;
+       if (xis.not_found) {
+               ret = ocfs2_xattr_block_find(inode, name_index, name, &xbs);
+               if (ret)
+                       goto cleanup;
+       }
+
+       ret = __ocfs2_xattr_set_handle(inode, di, &xi, &xis, &xbs, &ctxt);
+
+cleanup:
+       up_write(&OCFS2_I(inode)->ip_xattr_sem);
+       brelse(xbs.xattr_bh);
+       ocfs2_xattr_bucket_free(xbs.bucket);
+
+       return ret;
+}
+
 /*
  * ocfs2_xattr_set()
  *
@@ -1928,8 +2704,10 @@ int ocfs2_xattr_set(struct inode *inode,
 {
        struct buffer_head *di_bh = NULL;
        struct ocfs2_dinode *di;
-       int ret;
-       u16 i, blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
+       int ret, credits;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       struct inode *tl_inode = osb->osb_tl_inode;
+       struct ocfs2_xattr_set_ctxt ctxt = { NULL, NULL, };
 
        struct ocfs2_xattr_info xi = {
                .name_index = name_index,
@@ -1949,10 +2727,20 @@ int ocfs2_xattr_set(struct inode *inode,
        if (!ocfs2_supports_xattr(OCFS2_SB(inode->i_sb)))
                return -EOPNOTSUPP;
 
+       /*
+        * Only xbs will be used on indexed trees.  xis doesn't need a
+        * bucket.
+        */
+       xbs.bucket = ocfs2_xattr_bucket_new(inode);
+       if (!xbs.bucket) {
+               mlog_errno(-ENOMEM);
+               return -ENOMEM;
+       }
+
        ret = ocfs2_inode_lock(inode, &di_bh, 1);
        if (ret < 0) {
                mlog_errno(ret);
-               return ret;
+               goto cleanup_nolock;
        }
        xis.inode_bh = xbs.inode_bh = di_bh;
        di = (struct ocfs2_dinode *)di_bh->b_data;
@@ -1984,55 +2772,53 @@ int ocfs2_xattr_set(struct inode *inode,
                        goto cleanup;
        }
 
-       if (!value) {
-               /* Remove existing extended attribute */
-               if (!xis.not_found)
-                       ret = ocfs2_xattr_ibody_set(inode, &xi, &xis);
-               else if (!xbs.not_found)
-                       ret = ocfs2_xattr_block_set(inode, &xi, &xbs);
-       } else {
-               /* We always try to set extended attribute into inode first*/
-               ret = ocfs2_xattr_ibody_set(inode, &xi, &xis);
-               if (!ret && !xbs.not_found) {
-                       /*
-                        * If succeed and that extended attribute existing in
-                        * external block, then we will remove it.
-                        */
-                       xi.value = NULL;
-                       xi.value_len = 0;
-                       ret = ocfs2_xattr_block_set(inode, &xi, &xbs);
-               } else if (ret == -ENOSPC) {
-                       if (di->i_xattr_loc && !xbs.xattr_bh) {
-                               ret = ocfs2_xattr_block_find(inode, name_index,
-                                                            name, &xbs);
-                               if (ret)
-                                       goto cleanup;
-                       }
-                       /*
-                        * If no space in inode, we will set extended attribute
-                        * into external block.
-                        */
-                       ret = ocfs2_xattr_block_set(inode, &xi, &xbs);
-                       if (ret)
-                               goto cleanup;
-                       if (!xis.not_found) {
-                               /*
-                                * If succeed and that extended attribute
-                                * existing in inode, we will remove it.
-                                */
-                               xi.value = NULL;
-                               xi.value_len = 0;
-                               ret = ocfs2_xattr_ibody_set(inode, &xi, &xis);
-                       }
-               }
+
+       mutex_lock(&tl_inode->i_mutex);
+
+       if (ocfs2_truncate_log_needs_flush(osb)) {
+               ret = __ocfs2_flush_truncate_log(osb);
+               if (ret < 0) {
+                       mutex_unlock(&tl_inode->i_mutex);
+                       mlog_errno(ret);
+                       goto cleanup;
+               }
+       }
+       mutex_unlock(&tl_inode->i_mutex);
+
+       ret = ocfs2_init_xattr_set_ctxt(inode, di, &xi, &xis,
+                                       &xbs, &ctxt, &credits);
+       if (ret) {
+               mlog_errno(ret);
+               goto cleanup;
+       }
+
+       /* we need to update inode's ctime field, so add credit for it. */
+       credits += OCFS2_INODE_UPDATE_CREDITS;
+       ctxt.handle = ocfs2_start_trans(osb, credits);
+       if (IS_ERR(ctxt.handle)) {
+               ret = PTR_ERR(ctxt.handle);
+               mlog_errno(ret);
+               goto cleanup;
        }
+
+       ret = __ocfs2_xattr_set_handle(inode, di, &xi, &xis, &xbs, &ctxt);
+
+       ocfs2_commit_trans(osb, ctxt.handle);
+
+       if (ctxt.data_ac)
+               ocfs2_free_alloc_context(ctxt.data_ac);
+       if (ctxt.meta_ac)
+               ocfs2_free_alloc_context(ctxt.meta_ac);
+       if (ocfs2_dealloc_has_cluster(&ctxt.dealloc))
+               ocfs2_schedule_truncate_log_flush(osb, 1);
+       ocfs2_run_deallocs(osb, &ctxt.dealloc);
 cleanup:
        up_write(&OCFS2_I(inode)->ip_xattr_sem);
        ocfs2_inode_unlock(inode, 1);
+cleanup_nolock:
        brelse(di_bh);
        brelse(xbs.xattr_bh);
-       for (i = 0; i < blk_per_bucket; i++)
-               brelse(xbs.bucket.bhs[i]);
+       ocfs2_xattr_bucket_free(xbs.bucket);
 
        return ret;
 }
@@ -2107,7 +2893,7 @@ typedef int (xattr_bucket_func)(struct inode *inode,
                                void *para);
 
 static int ocfs2_find_xe_in_bucket(struct inode *inode,
-                                  struct buffer_head *header_bh,
+                                  struct ocfs2_xattr_bucket *bucket,
                                   int name_index,
                                   const char *name,
                                   u32 name_hash,
@@ -2115,11 +2901,9 @@ static int ocfs2_find_xe_in_bucket(struct inode *inode,
                                   int *found)
 {
        int i, ret = 0, cmp = 1, block_off, new_offset;
-       struct ocfs2_xattr_header *xh =
-                       (struct ocfs2_xattr_header *)header_bh->b_data;
+       struct ocfs2_xattr_header *xh = bucket_xh(bucket);
        size_t name_len = strlen(name);
        struct ocfs2_xattr_entry *xe = NULL;
-       struct buffer_head *name_bh = NULL;
        char *xe_name;
 
        /*
@@ -2150,19 +2934,9 @@ static int ocfs2_find_xe_in_bucket(struct inode *inode,
                        break;
                }
 
-               ret = ocfs2_read_block(inode, header_bh->b_blocknr + block_off,
-                                      &name_bh);
-               if (ret) {
-                       mlog_errno(ret);
-                       break;
-               }
-               xe_name = name_bh->b_data + new_offset;
-
-               cmp = memcmp(name, xe_name, name_len);
-               brelse(name_bh);
-               name_bh = NULL;
 
-               if (cmp == 0) {
+               xe_name = bucket_block(bucket, block_off) + new_offset;
+               if (!memcmp(name, xe_name, name_len)) {
                        *xe_index = i;
                        *found = 1;
                        ret = 0;
@@ -2192,39 +2966,42 @@ static int ocfs2_xattr_bucket_find(struct inode *inode,
                                   struct ocfs2_xattr_search *xs)
 {
        int ret, found = 0;
-       struct buffer_head *bh = NULL;
-       struct buffer_head *lower_bh = NULL;
        struct ocfs2_xattr_header *xh = NULL;
        struct ocfs2_xattr_entry *xe = NULL;
        u16 index = 0;
        u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
        int low_bucket = 0, bucket, high_bucket;
+       struct ocfs2_xattr_bucket *search;
        u32 last_hash;
-       u64 blkno;
+       u64 blkno, lower_blkno = 0;
+
+       search = ocfs2_xattr_bucket_new(inode);
+       if (!search) {
+               ret = -ENOMEM;
+               mlog_errno(ret);
+               goto out;
+       }
 
-       ret = ocfs2_read_block(inode, p_blkno, &bh);
+       ret = ocfs2_read_xattr_bucket(search, p_blkno);
        if (ret) {
                mlog_errno(ret);
                goto out;
        }
 
-       xh = (struct ocfs2_xattr_header *)bh->b_data;
+       xh = bucket_xh(search);
        high_bucket = le16_to_cpu(xh->xh_num_buckets) - 1;
-
        while (low_bucket <= high_bucket) {
-               brelse(bh);
-               bh = NULL;
-               bucket = (low_bucket + high_bucket) / 2;
+               ocfs2_xattr_bucket_relse(search);
 
+               bucket = (low_bucket + high_bucket) / 2;
                blkno = p_blkno + bucket * blk_per_bucket;
-
-               ret = ocfs2_read_block(inode, blkno, &bh);
+               ret = ocfs2_read_xattr_bucket(search, blkno);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
                }
 
-               xh = (struct ocfs2_xattr_header *)bh->b_data;
+               xh = bucket_xh(search);
                xe = &xh->xh_entries[0];
                if (name_hash < le32_to_cpu(xe->xe_name_hash)) {
                        high_bucket = bucket - 1;
@@ -2241,10 +3018,8 @@ static int ocfs2_xattr_bucket_find(struct inode *inode,
 
                last_hash = le32_to_cpu(xe->xe_name_hash);
 
-               /* record lower_bh which may be the insert place. */
-               brelse(lower_bh);
-               lower_bh = bh;
-               bh = NULL;
+               /* record lower_blkno which may be the insert place. */
+               lower_blkno = blkno;
 
                if (name_hash > le32_to_cpu(xe->xe_name_hash)) {
                        low_bucket = bucket + 1;
@@ -2252,7 +3027,7 @@ static int ocfs2_xattr_bucket_find(struct inode *inode,
                }
 
                /* the searched xattr should reside in this bucket if exists. */
-               ret = ocfs2_find_xe_in_bucket(inode, lower_bh,
+               ret = ocfs2_find_xe_in_bucket(inode, search,
                                              name_index, name, name_hash,
                                              &index, &found);
                if (ret) {
@@ -2267,46 +3042,29 @@ static int ocfs2_xattr_bucket_find(struct inode *inode,
         * When the xattr's hash value is in the gap of 2 buckets, we will
         * always set it to the previous bucket.
         */
-       if (!lower_bh) {
-               /*
-                * We can't find any bucket whose first name_hash is less
-                * than the find name_hash.
-                */
-               BUG_ON(bh->b_blocknr != p_blkno);
-               lower_bh = bh;
-               bh = NULL;
+       if (!lower_blkno)
+               lower_blkno = p_blkno;
+
+       /* This should be in cache - we just read it during the search */
+       ret = ocfs2_read_xattr_bucket(xs->bucket, lower_blkno);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
        }
-       xs->bucket.bhs[0] = lower_bh;
-       xs->bucket.xh = (struct ocfs2_xattr_header *)
-                                       xs->bucket.bhs[0]->b_data;
-       lower_bh = NULL;
 
-       xs->header = xs->bucket.xh;
-       xs->base = xs->bucket.bhs[0]->b_data;
+       xs->header = bucket_xh(xs->bucket);
+       xs->base = bucket_block(xs->bucket, 0);
        xs->end = xs->base + inode->i_sb->s_blocksize;
 
        if (found) {
-               /*
-                * If we have found the xattr enty, read all the blocks in
-                * this bucket.
-                */
-               ret = ocfs2_read_blocks(inode, xs->bucket.bhs[0]->b_blocknr + 1,
-                                       blk_per_bucket - 1, &xs->bucket.bhs[1],
-                                       0);
-               if (ret) {
-                       mlog_errno(ret);
-                       goto out;
-               }
-
                xs->here = &xs->header->xh_entries[index];
                mlog(0, "find xattr %s in bucket %llu, entry = %u\n", name,
-                    (unsigned long long)xs->bucket.bhs[0]->b_blocknr, index);
+                    (unsigned long long)bucket_blkno(xs->bucket), index);
        } else
                ret = -ENODATA;
 
 out:
-       brelse(bh);
-       brelse(lower_bh);
+       ocfs2_xattr_bucket_free(search);
        return ret;
 }
 
@@ -2357,53 +3115,50 @@ static int ocfs2_iterate_xattr_buckets(struct inode *inode,
                                       xattr_bucket_func *func,
                                       void *para)
 {
-       int i, j, ret = 0;
-       int blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
+       int i, ret = 0;
        u32 bpc = ocfs2_xattr_buckets_per_cluster(OCFS2_SB(inode->i_sb));
        u32 num_buckets = clusters * bpc;
-       struct ocfs2_xattr_bucket bucket;
+       struct ocfs2_xattr_bucket *bucket;
 
-       memset(&bucket, 0, sizeof(bucket));
+       bucket = ocfs2_xattr_bucket_new(inode);
+       if (!bucket) {
+               mlog_errno(-ENOMEM);
+               return -ENOMEM;
+       }
 
        mlog(0, "iterating xattr buckets in %u clusters starting from %llu\n",
             clusters, (unsigned long long)blkno);
 
-       for (i = 0; i < num_buckets; i++, blkno += blk_per_bucket) {
-               ret = ocfs2_read_blocks(inode, blkno, blk_per_bucket,
-                                       bucket.bhs, 0);
+       for (i = 0; i < num_buckets; i++, blkno += bucket->bu_blocks) {
+               ret = ocfs2_read_xattr_bucket(bucket, blkno);
                if (ret) {
                        mlog_errno(ret);
-                       goto out;
+                       break;
                }
 
-               bucket.xh = (struct ocfs2_xattr_header *)bucket.bhs[0]->b_data;
                /*
                 * The real bucket num in this series of blocks is stored
                 * in the 1st bucket.
                 */
                if (i == 0)
-                       num_buckets = le16_to_cpu(bucket.xh->xh_num_buckets);
+                       num_buckets = le16_to_cpu(bucket_xh(bucket)->xh_num_buckets);
 
                mlog(0, "iterating xattr bucket %llu, first hash %u\n",
                     (unsigned long long)blkno,
-                    le32_to_cpu(bucket.xh->xh_entries[0].xe_name_hash));
+                    le32_to_cpu(bucket_xh(bucket)->xh_entries[0].xe_name_hash));
                if (func) {
-                       ret = func(inode, &bucket, para);
-                       if (ret) {
+                       ret = func(inode, bucket, para);
+                       if (ret)
                                mlog_errno(ret);
-                               break;
-                       }
+                       /* Fall through to bucket_relse() */
                }
 
-               for (j = 0; j < blk_per_bucket; j++)
-                       brelse(bucket.bhs[j]);
-               memset(&bucket, 0, sizeof(bucket));
+               ocfs2_xattr_bucket_relse(bucket);
+               if (ret)
+                       break;
        }
 
-out:
-       for (j = 0; j < blk_per_bucket; j++)
-               brelse(bucket.bhs[j]);
-
+       ocfs2_xattr_bucket_free(bucket);
        return ret;
 }
 
@@ -2441,21 +3196,21 @@ static int ocfs2_list_xattr_bucket(struct inode *inode,
        int i, block_off, new_offset;
        const char *prefix, *name;
 
-       for (i = 0 ; i < le16_to_cpu(bucket->xh->xh_count); i++) {
-               struct ocfs2_xattr_entry *entry = &bucket->xh->xh_entries[i];
+       for (i = 0 ; i < le16_to_cpu(bucket_xh(bucket)->xh_count); i++) {
+               struct ocfs2_xattr_entry *entry = &bucket_xh(bucket)->xh_entries[i];
                type = ocfs2_xattr_get_type(entry);
                prefix = ocfs2_xattr_prefix(type);
 
                if (prefix) {
                        ret = ocfs2_xattr_bucket_get_name_value(inode,
-                                                               bucket->xh,
+                                                               bucket_xh(bucket),
                                                                i,
                                                                &block_off,
                                                                &new_offset);
                        if (ret)
                                break;
 
-                       name = (const char *)bucket->bhs[block_off]->b_data +
+                       name = (const char *)bucket_block(bucket, block_off) +
                                new_offset;
                        ret = ocfs2_xattr_list_entry(xl->buffer,
                                                     xl->buffer_size,
@@ -2540,32 +3295,34 @@ static void swap_xe(void *a, void *b, int size)
 /*
  * When the ocfs2_xattr_block is filled up, new bucket will be created
  * and all the xattr entries will be moved to the new bucket.
+ * The header goes at the start of the bucket, and the names+values are
+ * filled from the end.  This is why *target starts as the last buffer.
  * Note: we need to sort the entries since they are not saved in order
  * in the ocfs2_xattr_block.
  */
 static void ocfs2_cp_xattr_block_to_bucket(struct inode *inode,
                                           struct buffer_head *xb_bh,
-                                          struct buffer_head *xh_bh,
-                                          struct buffer_head *data_bh)
+                                          struct ocfs2_xattr_bucket *bucket)
 {
        int i, blocksize = inode->i_sb->s_blocksize;
+       int blks = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
        u16 offset, size, off_change;
        struct ocfs2_xattr_entry *xe;
        struct ocfs2_xattr_block *xb =
                                (struct ocfs2_xattr_block *)xb_bh->b_data;
        struct ocfs2_xattr_header *xb_xh = &xb->xb_attrs.xb_header;
-       struct ocfs2_xattr_header *xh =
-                               (struct ocfs2_xattr_header *)xh_bh->b_data;
+       struct ocfs2_xattr_header *xh = bucket_xh(bucket);
        u16 count = le16_to_cpu(xb_xh->xh_count);
-       char *target = xh_bh->b_data, *src = xb_bh->b_data;
+       char *src = xb_bh->b_data;
+       char *target = bucket_block(bucket, blks - 1);
 
        mlog(0, "cp xattr from block %llu to bucket %llu\n",
             (unsigned long long)xb_bh->b_blocknr,
-            (unsigned long long)xh_bh->b_blocknr);
+            (unsigned long long)bucket_blkno(bucket));
+
+       for (i = 0; i < blks; i++)
+               memset(bucket_block(bucket, i), 0, blocksize);
 
-       memset(xh_bh->b_data, 0, blocksize);
-       if (data_bh)
-               memset(data_bh->b_data, 0, blocksize);
        /*
         * Since the xe_name_offset is based on ocfs2_xattr_header,
         * there is a offset change corresponding to the change of
@@ -2577,8 +3334,6 @@ static void ocfs2_cp_xattr_block_to_bucket(struct inode *inode,
        size = blocksize - offset;
 
        /* copy all the names and values. */
-       if (data_bh)
-               target = data_bh->b_data;
        memcpy(target + offset, src + offset, size);
 
        /* Init new header now. */
@@ -2588,7 +3343,7 @@ static void ocfs2_cp_xattr_block_to_bucket(struct inode *inode,
        xh->xh_free_start = cpu_to_le16(OCFS2_XATTR_BUCKET_SIZE - size);
 
        /* copy all the entries. */
-       target = xh_bh->b_data;
+       target = bucket_block(bucket, 0);
        offset = offsetof(struct ocfs2_xattr_header, xh_entries);
        size = count * sizeof(struct ocfs2_xattr_entry);
        memcpy(target + offset, (char *)xb_xh + offset, size);
@@ -2614,73 +3369,47 @@ static void ocfs2_cp_xattr_block_to_bucket(struct inode *inode,
  * While if the entry is in index b-tree, "bucket" indicates the
  * real place of the xattr.
  */
-static int ocfs2_xattr_update_xattr_search(struct inode *inode,
-                                          struct ocfs2_xattr_search *xs,
-                                          struct buffer_head *old_bh,
-                                          struct buffer_head *new_bh)
+static void ocfs2_xattr_update_xattr_search(struct inode *inode,
+                                           struct ocfs2_xattr_search *xs,
+                                           struct buffer_head *old_bh)
 {
-       int ret = 0;
        char *buf = old_bh->b_data;
        struct ocfs2_xattr_block *old_xb = (struct ocfs2_xattr_block *)buf;
        struct ocfs2_xattr_header *old_xh = &old_xb->xb_attrs.xb_header;
-       int i, blocksize = inode->i_sb->s_blocksize;
-       u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
-
-       xs->bucket.bhs[0] = new_bh;
-       get_bh(new_bh);
-       xs->bucket.xh = (struct ocfs2_xattr_header *)xs->bucket.bhs[0]->b_data;
-       xs->header = xs->bucket.xh;
+       int i;
 
-       xs->base = new_bh->b_data;
+       xs->header = bucket_xh(xs->bucket);
+       xs->base = bucket_block(xs->bucket, 0);
        xs->end = xs->base + inode->i_sb->s_blocksize;
 
-       if (!xs->not_found) {
-               if (OCFS2_XATTR_BUCKET_SIZE != blocksize) {
-                       ret = ocfs2_read_blocks(inode,
-                                       xs->bucket.bhs[0]->b_blocknr + 1,
-                                       blk_per_bucket - 1, &xs->bucket.bhs[1],
-                                       0);
-                       if (ret) {
-                               mlog_errno(ret);
-                               return ret;
-                       }
-
-               }
-               i = xs->here - old_xh->xh_entries;
-               xs->here = &xs->header->xh_entries[i];
-       }
+       if (xs->not_found)
+               return;
 
-       return ret;
+       i = xs->here - old_xh->xh_entries;
+       xs->here = &xs->header->xh_entries[i];
 }
 
 static int ocfs2_xattr_create_index_block(struct inode *inode,
-                                         struct ocfs2_xattr_search *xs)
+                                         struct ocfs2_xattr_search *xs,
+                                         struct ocfs2_xattr_set_ctxt *ctxt)
 {
-       int ret, credits = OCFS2_SUBALLOC_ALLOC;
+       int ret;
        u32 bit_off, len;
        u64 blkno;
-       handle_t *handle;
+       handle_t *handle = ctxt->handle;
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
        struct ocfs2_inode_info *oi = OCFS2_I(inode);
-       struct ocfs2_alloc_context *data_ac;
-       struct buffer_head *xh_bh = NULL, *data_bh = NULL;
        struct buffer_head *xb_bh = xs->xattr_bh;
        struct ocfs2_xattr_block *xb =
                        (struct ocfs2_xattr_block *)xb_bh->b_data;
        struct ocfs2_xattr_tree_root *xr;
        u16 xb_flags = le16_to_cpu(xb->xb_flags);
-       u16 bpb = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
 
        mlog(0, "create xattr index block for %llu\n",
             (unsigned long long)xb_bh->b_blocknr);
 
        BUG_ON(xb_flags & OCFS2_XATTR_INDEXED);
-
-       ret = ocfs2_reserve_clusters(osb, 1, &data_ac);
-       if (ret) {
-               mlog_errno(ret);
-               goto out;
-       }
+       BUG_ON(!xs->bucket);
 
        /*
         * XXX:
@@ -2689,29 +3418,18 @@ static int ocfs2_xattr_create_index_block(struct inode *inode,
         */
        down_write(&oi->ip_alloc_sem);
 
-       /*
-        * 3 more credits, one for xattr block update, one for the 1st block
-        * of the new xattr bucket and one for the value/data.
-        */
-       credits += 3;
-       handle = ocfs2_start_trans(osb, credits);
-       if (IS_ERR(handle)) {
-               ret = PTR_ERR(handle);
-               mlog_errno(ret);
-               goto out_sem;
-       }
-
-       ret = ocfs2_journal_access(handle, inode, xb_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = ocfs2_journal_access_xb(handle, inode, xb_bh,
+                                     OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
-               goto out_commit;
+               goto out;
        }
 
-       ret = ocfs2_claim_clusters(osb, handle, data_ac, 1, &bit_off, &len);
+       ret = __ocfs2_claim_clusters(osb, handle, ctxt->data_ac,
+                                    1, 1, &bit_off, &len);
        if (ret) {
                mlog_errno(ret);
-               goto out_commit;
+               goto out;
        }
 
        /*
@@ -2724,51 +3442,23 @@ static int ocfs2_xattr_create_index_block(struct inode *inode,
        mlog(0, "allocate 1 cluster from %llu to xattr block\n",
             (unsigned long long)blkno);
 
-       xh_bh = sb_getblk(inode->i_sb, blkno);
-       if (!xh_bh) {
-               ret = -EIO;
+       ret = ocfs2_init_xattr_bucket(xs->bucket, blkno);
+       if (ret) {
                mlog_errno(ret);
-               goto out_commit;
+               goto out;
        }
 
-       ocfs2_set_new_buffer_uptodate(inode, xh_bh);
-
-       ret = ocfs2_journal_access(handle, inode, xh_bh,
-                                  OCFS2_JOURNAL_ACCESS_CREATE);
+       ret = ocfs2_xattr_bucket_journal_access(handle, xs->bucket,
+                                               OCFS2_JOURNAL_ACCESS_CREATE);
        if (ret) {
                mlog_errno(ret);
-               goto out_commit;
-       }
-
-       if (bpb > 1) {
-               data_bh = sb_getblk(inode->i_sb, blkno + bpb - 1);
-               if (!data_bh) {
-                       ret = -EIO;
-                       mlog_errno(ret);
-                       goto out_commit;
-               }
-
-               ocfs2_set_new_buffer_uptodate(inode, data_bh);
-
-               ret = ocfs2_journal_access(handle, inode, data_bh,
-                                          OCFS2_JOURNAL_ACCESS_CREATE);
-               if (ret) {
-                       mlog_errno(ret);
-                       goto out_commit;
-               }
+               goto out;
        }
 
-       ocfs2_cp_xattr_block_to_bucket(inode, xb_bh, xh_bh, data_bh);
+       ocfs2_cp_xattr_block_to_bucket(inode, xb_bh, xs->bucket);
+       ocfs2_xattr_bucket_journal_dirty(handle, xs->bucket);
 
-       ocfs2_journal_dirty(handle, xh_bh);
-       if (data_bh)
-               ocfs2_journal_dirty(handle, data_bh);
-
-       ret = ocfs2_xattr_update_xattr_search(inode, xs, xb_bh, xh_bh);
-       if (ret) {
-               mlog_errno(ret);
-               goto out_commit;
-       }
+       ocfs2_xattr_update_xattr_search(inode, xs, xb_bh);
 
        /* Change from ocfs2_xattr_header to ocfs2_xattr_tree_root */
        memset(&xb->xb_attrs, 0, inode->i_sb->s_blocksize -
@@ -2787,24 +3477,10 @@ static int ocfs2_xattr_create_index_block(struct inode *inode,
 
        xb->xb_flags = cpu_to_le16(xb_flags | OCFS2_XATTR_INDEXED);
 
-       ret = ocfs2_journal_dirty(handle, xb_bh);
-       if (ret) {
-               mlog_errno(ret);
-               goto out_commit;
-       }
-
-out_commit:
-       ocfs2_commit_trans(osb, handle);
-
-out_sem:
-       up_write(&oi->ip_alloc_sem);
+       ocfs2_journal_dirty(handle, xb_bh);
 
 out:
-       if (data_ac)
-               ocfs2_free_alloc_context(data_ac);
-
-       brelse(xh_bh);
-       brelse(data_bh);
+       up_write(&oi->ip_alloc_sem);
 
        return ret;
 }
@@ -2829,29 +3505,18 @@ static int cmp_xe_offset(const void *a, const void *b)
  * so that we can spare some space for insertion.
  */
 static int ocfs2_defrag_xattr_bucket(struct inode *inode,
+                                    handle_t *handle,
                                     struct ocfs2_xattr_bucket *bucket)
 {
        int ret, i;
        size_t end, offset, len, value_len;
        struct ocfs2_xattr_header *xh;
        char *entries, *buf, *bucket_buf = NULL;
-       u64 blkno = bucket->bhs[0]->b_blocknr;
-       u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
+       u64 blkno = bucket_blkno(bucket);
        u16 xh_free_start;
        size_t blocksize = inode->i_sb->s_blocksize;
-       handle_t *handle;
-       struct buffer_head **bhs;
        struct ocfs2_xattr_entry *xe;
 
-       bhs = kzalloc(sizeof(struct buffer_head *) * blk_per_bucket,
-                       GFP_NOFS);
-       if (!bhs)
-               return -ENOMEM;
-
-       ret = ocfs2_read_blocks(inode, blkno, blk_per_bucket, bhs, 0);
-       if (ret)
-               goto out;
-
        /*
         * In order to make the operation more efficient and generic,
         * we copy all the blocks into a contiguous memory and do the
@@ -2865,26 +3530,16 @@ static int ocfs2_defrag_xattr_bucket(struct inode *inode,
        }
 
        buf = bucket_buf;
-       for (i = 0; i < blk_per_bucket; i++, buf += blocksize)
-               memcpy(buf, bhs[i]->b_data, blocksize);
+       for (i = 0; i < bucket->bu_blocks; i++, buf += blocksize)
+               memcpy(buf, bucket_block(bucket, i), blocksize);
 
-       handle = ocfs2_start_trans((OCFS2_SB(inode->i_sb)), blk_per_bucket);
-       if (IS_ERR(handle)) {
-               ret = PTR_ERR(handle);
-               handle = NULL;
+       ret = ocfs2_xattr_bucket_journal_access(handle, bucket,
+                                               OCFS2_JOURNAL_ACCESS_WRITE);
+       if (ret < 0) {
                mlog_errno(ret);
                goto out;
        }
 
-       for (i = 0; i < blk_per_bucket; i++) {
-               ret = ocfs2_journal_access(handle, inode, bhs[i],
-                                          OCFS2_JOURNAL_ACCESS_WRITE);
-               if (ret < 0) {
-                       mlog_errno(ret);
-                       goto commit;
-               }
-       }
-
        xh = (struct ocfs2_xattr_header *)bucket_buf;
        entries = (char *)xh->xh_entries;
        xh_free_start = le16_to_cpu(xh->xh_free_start);
@@ -2940,7 +3595,7 @@ static int ocfs2_defrag_xattr_bucket(struct inode *inode,
                        "bucket %llu\n", (unsigned long long)blkno);
 
        if (xh_free_start == end)
-               goto commit;
+               goto out;
 
        memset(bucket_buf + xh_free_start, 0, end - xh_free_start);
        xh->xh_free_start = cpu_to_le16(end);
@@ -2951,169 +3606,94 @@ static int ocfs2_defrag_xattr_bucket(struct inode *inode,
             cmp_xe, swap_xe);
 
        buf = bucket_buf;
-       for (i = 0; i < blk_per_bucket; i++, buf += blocksize) {
-               memcpy(bhs[i]->b_data, buf, blocksize);
-               ocfs2_journal_dirty(handle, bhs[i]);
-       }
+       for (i = 0; i < bucket->bu_blocks; i++, buf += blocksize)
+               memcpy(bucket_block(bucket, i), buf, blocksize);
+       ocfs2_xattr_bucket_journal_dirty(handle, bucket);
 
-commit:
-       ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle);
 out:
-
-       if (bhs) {
-               for (i = 0; i < blk_per_bucket; i++)
-                       brelse(bhs[i]);
-       }
-       kfree(bhs);
-
        kfree(bucket_buf);
        return ret;
 }
 
 /*
- * Move half nums of the xattr bucket in the previous cluster to this new
- * cluster. We only touch the last cluster of the previous extend record.
+ * prev_blkno points to the start of an existing extent.  new_blkno
+ * points to a newly allocated extent.  Because we know each of our
+ * clusters contains more than bucket, we can easily split one cluster
+ * at a bucket boundary.  So we take the last cluster of the existing
+ * extent and split it down the middle.  We move the last half of the
+ * buckets in the last cluster of the existing extent over to the new
+ * extent.
  *
- * first_bh is the first buffer_head of a series of bucket in the same
- * extent rec and header_bh is the header of one bucket in this cluster.
- * They will be updated if we move the data header_bh contains to the new
- * cluster. first_hash will be set as the 1st xe's name_hash of the new cluster.
+ * first_bh is the buffer at prev_blkno so we can update the existing
+ * extent's bucket count.  header_bh is the bucket were we were hoping
+ * to insert our xattr.  If the bucket move places the target in the new
+ * extent, we'll update first_bh and header_bh after modifying the old
+ * extent.
+ *
+ * first_hash will be set as the 1st xe's name_hash in the new extent.
  */
 static int ocfs2_mv_xattr_bucket_cross_cluster(struct inode *inode,
                                               handle_t *handle,
-                                              struct buffer_head **first_bh,
-                                              struct buffer_head **header_bh,
+                                              struct ocfs2_xattr_bucket *first,
+                                              struct ocfs2_xattr_bucket *target,
                                               u64 new_blkno,
-                                              u64 prev_blkno,
                                               u32 num_clusters,
                                               u32 *first_hash)
 {
-       int i, ret, credits;
-       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
-       int bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1);
-       int num_buckets = ocfs2_xattr_buckets_per_cluster(osb);
-       int blocksize = inode->i_sb->s_blocksize;
-       struct buffer_head *old_bh, *new_bh, *prev_bh, *new_first_bh = NULL;
-       struct ocfs2_xattr_header *new_xh;
-       struct ocfs2_xattr_header *xh =
-                       (struct ocfs2_xattr_header *)((*first_bh)->b_data);
-
-       BUG_ON(le16_to_cpu(xh->xh_num_buckets) < num_buckets);
-       BUG_ON(OCFS2_XATTR_BUCKET_SIZE == osb->s_clustersize);
-
-       prev_bh = *first_bh;
-       get_bh(prev_bh);
-       xh = (struct ocfs2_xattr_header *)prev_bh->b_data;
+       int ret;
+       struct super_block *sb = inode->i_sb;
+       int blks_per_bucket = ocfs2_blocks_per_xattr_bucket(sb);
+       int num_buckets = ocfs2_xattr_buckets_per_cluster(OCFS2_SB(sb));
+       int to_move = num_buckets / 2;
+       u64 src_blkno;
+       u64 last_cluster_blkno = bucket_blkno(first) +
+               ((num_clusters - 1) * ocfs2_clusters_to_blocks(sb, 1));
 
-       prev_blkno += (num_clusters - 1) * bpc + bpc / 2;
+       BUG_ON(le16_to_cpu(bucket_xh(first)->xh_num_buckets) < num_buckets);
+       BUG_ON(OCFS2_XATTR_BUCKET_SIZE == OCFS2_SB(sb)->s_clustersize);
 
        mlog(0, "move half of xattrs in cluster %llu to %llu\n",
-            (unsigned long long)prev_blkno, (unsigned long long)new_blkno);
+            (unsigned long long)last_cluster_blkno, (unsigned long long)new_blkno);
 
-       /*
-        * We need to update the 1st half of the new cluster and
-        * 1 more for the update of the 1st bucket of the previous
-        * extent record.
-        */
-       credits = bpc / 2 + 1;
-       ret = ocfs2_extend_trans(handle, credits);
+       ret = ocfs2_mv_xattr_buckets(inode, handle, bucket_blkno(first),
+                                    last_cluster_blkno, new_blkno,
+                                    to_move, first_hash);
        if (ret) {
                mlog_errno(ret);
                goto out;
        }
 
-       ret = ocfs2_journal_access(handle, inode, prev_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
-       if (ret) {
-               mlog_errno(ret);
-               goto out;
-       }
+       /* This is the first bucket that got moved */
+       src_blkno = last_cluster_blkno + (to_move * blks_per_bucket);
 
-       for (i = 0; i < bpc / 2; i++, prev_blkno++, new_blkno++) {
-               old_bh = new_bh = NULL;
-               new_bh = sb_getblk(inode->i_sb, new_blkno);
-               if (!new_bh) {
-                       ret = -EIO;
-                       mlog_errno(ret);
-                       goto out;
-               }
+       /*
+        * If the target bucket was part of the moved buckets, we need to
+        * update first and target.
+        */
+       if (bucket_blkno(target) >= src_blkno) {
+               /* Find the block for the new target bucket */
+               src_blkno = new_blkno +
+                       (bucket_blkno(target) - src_blkno);
 
-               ocfs2_set_new_buffer_uptodate(inode, new_bh);
+               ocfs2_xattr_bucket_relse(first);
+               ocfs2_xattr_bucket_relse(target);
 
-               ret = ocfs2_journal_access(handle, inode, new_bh,
-                                          OCFS2_JOURNAL_ACCESS_CREATE);
-               if (ret < 0) {
+               /*
+                * These shouldn't fail - the buffers are in the
+                * journal from ocfs2_cp_xattr_bucket().
+                */
+               ret = ocfs2_read_xattr_bucket(first, new_blkno);
+               if (ret) {
                        mlog_errno(ret);
-                       brelse(new_bh);
                        goto out;
                }
-
-               ret = ocfs2_read_block(inode, prev_blkno, &old_bh);
-               if (ret < 0) {
+               ret = ocfs2_read_xattr_bucket(target, src_blkno);
+               if (ret)
                        mlog_errno(ret);
-                       brelse(new_bh);
-                       goto out;
-               }
-
-               memcpy(new_bh->b_data, old_bh->b_data, blocksize);
-
-               if (i == 0) {
-                       new_xh = (struct ocfs2_xattr_header *)new_bh->b_data;
-                       new_xh->xh_num_buckets = cpu_to_le16(num_buckets / 2);
 
-                       if (first_hash)
-                               *first_hash = le32_to_cpu(
-                                       new_xh->xh_entries[0].xe_name_hash);
-                       new_first_bh = new_bh;
-                       get_bh(new_first_bh);
-               }
-
-               ocfs2_journal_dirty(handle, new_bh);
-
-               if (*header_bh == old_bh) {
-                       brelse(*header_bh);
-                       *header_bh = new_bh;
-                       get_bh(*header_bh);
-
-                       brelse(*first_bh);
-                       *first_bh = new_first_bh;
-                       get_bh(*first_bh);
-               }
-               brelse(new_bh);
-               brelse(old_bh);
        }
 
-       le16_add_cpu(&xh->xh_num_buckets, -(num_buckets / 2));
-
-       ocfs2_journal_dirty(handle, prev_bh);
 out:
-       brelse(prev_bh);
-       brelse(new_first_bh);
-       return ret;
-}
-
-static int ocfs2_read_xattr_bucket(struct inode *inode,
-                                  u64 blkno,
-                                  struct buffer_head **bhs,
-                                  int new)
-{
-       int ret = 0;
-       u16 i, blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
-
-       if (!new)
-               return ocfs2_read_blocks(inode, blkno,
-                                        blk_per_bucket, bhs, 0);
-
-       for (i = 0; i < blk_per_bucket; i++) {
-               bhs[i] = sb_getblk(inode->i_sb, blkno + i);
-               if (bhs[i] == NULL) {
-                       ret = -EIO;
-                       mlog_errno(ret);
-                       break;
-               }
-               ocfs2_set_new_buffer_uptodate(inode, bhs[i]);
-       }
-
        return ret;
 }
 
@@ -3178,8 +3758,7 @@ static int ocfs2_divide_xattr_bucket(struct inode *inode,
 {
        int ret, i;
        int count, start, len, name_value_len = 0, xe_len, name_offset = 0;
-       u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
-       struct buffer_head **s_bhs, **t_bhs = NULL;
+       struct ocfs2_xattr_bucket *s_bucket = NULL, *t_bucket = NULL;
        struct ocfs2_xattr_header *xh;
        struct ocfs2_xattr_entry *xe;
        int blocksize = inode->i_sb->s_blocksize;
@@ -3187,47 +3766,52 @@ static int ocfs2_divide_xattr_bucket(struct inode *inode,
        mlog(0, "move some of xattrs from bucket %llu to %llu\n",
             (unsigned long long)blk, (unsigned long long)new_blk);
 
-       s_bhs = kcalloc(blk_per_bucket, sizeof(struct buffer_head *), GFP_NOFS);
-       if (!s_bhs)
-               return -ENOMEM;
-
-       ret = ocfs2_read_xattr_bucket(inode, blk, s_bhs, 0);
-       if (ret) {
+       s_bucket = ocfs2_xattr_bucket_new(inode);
+       t_bucket = ocfs2_xattr_bucket_new(inode);
+       if (!s_bucket || !t_bucket) {
+               ret = -ENOMEM;
                mlog_errno(ret);
                goto out;
        }
 
-       ret = ocfs2_journal_access(handle, inode, s_bhs[0],
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = ocfs2_read_xattr_bucket(s_bucket, blk);
        if (ret) {
                mlog_errno(ret);
                goto out;
        }
 
-       t_bhs = kcalloc(blk_per_bucket, sizeof(struct buffer_head *), GFP_NOFS);
-       if (!t_bhs) {
-               ret = -ENOMEM;
+       ret = ocfs2_xattr_bucket_journal_access(handle, s_bucket,
+                                               OCFS2_JOURNAL_ACCESS_WRITE);
+       if (ret) {
+               mlog_errno(ret);
                goto out;
        }
 
-       ret = ocfs2_read_xattr_bucket(inode, new_blk, t_bhs, new_bucket_head);
+       /*
+        * Even if !new_bucket_head, we're overwriting t_bucket.  Thus,
+        * there's no need to read it.
+        */
+       ret = ocfs2_init_xattr_bucket(t_bucket, new_blk);
        if (ret) {
                mlog_errno(ret);
                goto out;
        }
 
-       for (i = 0; i < blk_per_bucket; i++) {
-               ret = ocfs2_journal_access(handle, inode, t_bhs[i],
-                                          new_bucket_head ?
-                                          OCFS2_JOURNAL_ACCESS_CREATE :
-                                          OCFS2_JOURNAL_ACCESS_WRITE);
-               if (ret) {
-                       mlog_errno(ret);
-                       goto out;
-               }
+       /*
+        * Hey, if we're overwriting t_bucket, what difference does
+        * ACCESS_CREATE vs ACCESS_WRITE make?  See the comment in the
+        * same part of ocfs2_cp_xattr_bucket().
+        */
+       ret = ocfs2_xattr_bucket_journal_access(handle, t_bucket,
+                                               new_bucket_head ?
+                                               OCFS2_JOURNAL_ACCESS_CREATE :
+                                               OCFS2_JOURNAL_ACCESS_WRITE);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
        }
 
-       xh = (struct ocfs2_xattr_header *)s_bhs[0]->b_data;
+       xh = bucket_xh(s_bucket);
        count = le16_to_cpu(xh->xh_count);
        start = ocfs2_xattr_find_divide_pos(xh);
 
@@ -3239,10 +3823,10 @@ static int ocfs2_divide_xattr_bucket(struct inode *inode,
                 * The hash value is set as one larger than
                 * that of the last entry in the previous bucket.
                 */
-               for (i = 0; i < blk_per_bucket; i++)
-                       memset(t_bhs[i]->b_data, 0, blocksize);
+               for (i = 0; i < t_bucket->bu_blocks; i++)
+                       memset(bucket_block(t_bucket, i), 0, blocksize);
 
-               xh = (struct ocfs2_xattr_header *)t_bhs[0]->b_data;
+               xh = bucket_xh(t_bucket);
                xh->xh_free_start = cpu_to_le16(blocksize);
                xh->xh_entries[0].xe_name_hash = xe->xe_name_hash;
                le32_add_cpu(&xh->xh_entries[0].xe_name_hash, 1);
@@ -3251,11 +3835,10 @@ static int ocfs2_divide_xattr_bucket(struct inode *inode,
        }
 
        /* copy the whole bucket to the new first. */
-       for (i = 0; i < blk_per_bucket; i++)
-               memcpy(t_bhs[i]->b_data, s_bhs[i]->b_data, blocksize);
+       ocfs2_xattr_bucket_copy_data(t_bucket, s_bucket);
 
        /* update the new bucket. */
-       xh = (struct ocfs2_xattr_header *)t_bhs[0]->b_data;
+       xh = bucket_xh(t_bucket);
 
        /*
         * Calculate the total name/value len and xh_free_start for
@@ -3319,11 +3902,7 @@ set_num_buckets:
        else
                xh->xh_num_buckets = 0;
 
-       for (i = 0; i < blk_per_bucket; i++) {
-               ocfs2_journal_dirty(handle, t_bhs[i]);
-               if (ret)
-                       mlog_errno(ret);
-       }
+       ocfs2_xattr_bucket_journal_dirty(handle, t_bucket);
 
        /* store the first_hash of the new bucket. */
        if (first_hash)
@@ -3337,29 +3916,18 @@ set_num_buckets:
        if (start == count)
                goto out;
 
-       xh = (struct ocfs2_xattr_header *)s_bhs[0]->b_data;
+       xh = bucket_xh(s_bucket);
        memset(&xh->xh_entries[start], 0,
               sizeof(struct ocfs2_xattr_entry) * (count - start));
        xh->xh_count = cpu_to_le16(start);
        xh->xh_free_start = cpu_to_le16(name_offset);
        xh->xh_name_value_len = cpu_to_le16(name_value_len);
 
-       ocfs2_journal_dirty(handle, s_bhs[0]);
-       if (ret)
-               mlog_errno(ret);
+       ocfs2_xattr_bucket_journal_dirty(handle, s_bucket);
 
 out:
-       if (s_bhs) {
-               for (i = 0; i < blk_per_bucket; i++)
-                       brelse(s_bhs[i]);
-       }
-       kfree(s_bhs);
-
-       if (t_bhs) {
-               for (i = 0; i < blk_per_bucket; i++)
-                       brelse(t_bhs[i]);
-       }
-       kfree(t_bhs);
+       ocfs2_xattr_bucket_free(s_bucket);
+       ocfs2_xattr_bucket_free(t_bucket);
 
        return ret;
 }
@@ -3376,103 +3944,124 @@ static int ocfs2_cp_xattr_bucket(struct inode *inode,
                                 u64 t_blkno,
                                 int t_is_new)
 {
-       int ret, i;
-       int blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
-       int blocksize = inode->i_sb->s_blocksize;
-       struct buffer_head **s_bhs, **t_bhs = NULL;
+       int ret;
+       struct ocfs2_xattr_bucket *s_bucket = NULL, *t_bucket = NULL;
 
        BUG_ON(s_blkno == t_blkno);
 
        mlog(0, "cp bucket %llu to %llu, target is %d\n",
             (unsigned long long)s_blkno, (unsigned long long)t_blkno,
-            t_is_new);
-
-       s_bhs = kzalloc(sizeof(struct buffer_head *) * blk_per_bucket,
-                       GFP_NOFS);
-       if (!s_bhs)
-               return -ENOMEM;
-
-       ret = ocfs2_read_xattr_bucket(inode, s_blkno, s_bhs, 0);
-       if (ret)
-               goto out;
+            t_is_new);
 
-       t_bhs = kzalloc(sizeof(struct buffer_head *) * blk_per_bucket,
-                       GFP_NOFS);
-       if (!t_bhs) {
+       s_bucket = ocfs2_xattr_bucket_new(inode);
+       t_bucket = ocfs2_xattr_bucket_new(inode);
+       if (!s_bucket || !t_bucket) {
                ret = -ENOMEM;
+               mlog_errno(ret);
                goto out;
        }
 
-       ret = ocfs2_read_xattr_bucket(inode, t_blkno, t_bhs, t_is_new);
+       ret = ocfs2_read_xattr_bucket(s_bucket, s_blkno);
        if (ret)
                goto out;
 
-       for (i = 0; i < blk_per_bucket; i++) {
-               ret = ocfs2_journal_access(handle, inode, t_bhs[i],
-                                          t_is_new ?
-                                          OCFS2_JOURNAL_ACCESS_CREATE :
-                                          OCFS2_JOURNAL_ACCESS_WRITE);
-               if (ret)
-                       goto out;
-       }
+       /*
+        * Even if !t_is_new, we're overwriting t_bucket.  Thus,
+        * there's no need to read it.
+        */
+       ret = ocfs2_init_xattr_bucket(t_bucket, t_blkno);
+       if (ret)
+               goto out;
 
-       for (i = 0; i < blk_per_bucket; i++) {
-               memcpy(t_bhs[i]->b_data, s_bhs[i]->b_data, blocksize);
-               ocfs2_journal_dirty(handle, t_bhs[i]);
-       }
+       /*
+        * Hey, if we're overwriting t_bucket, what difference does
+        * ACCESS_CREATE vs ACCESS_WRITE make?  Well, if we allocated a new
+        * cluster to fill, we came here from
+        * ocfs2_mv_xattr_buckets(), and it is really new -
+        * ACCESS_CREATE is required.  But we also might have moved data
+        * out of t_bucket before extending back into it.
+        * ocfs2_add_new_xattr_bucket() can do this - its call to
+        * ocfs2_add_new_xattr_cluster() may have created a new extent
+        * and copied out the end of the old extent.  Then it re-extends
+        * the old extent back to create space for new xattrs.  That's
+        * how we get here, and the bucket isn't really new.
+        */
+       ret = ocfs2_xattr_bucket_journal_access(handle, t_bucket,
+                                               t_is_new ?
+                                               OCFS2_JOURNAL_ACCESS_CREATE :
+                                               OCFS2_JOURNAL_ACCESS_WRITE);
+       if (ret)
+               goto out;
 
-out:
-       if (s_bhs) {
-               for (i = 0; i < blk_per_bucket; i++)
-                       brelse(s_bhs[i]);
-       }
-       kfree(s_bhs);
+       ocfs2_xattr_bucket_copy_data(t_bucket, s_bucket);
+       ocfs2_xattr_bucket_journal_dirty(handle, t_bucket);
 
-       if (t_bhs) {
-               for (i = 0; i < blk_per_bucket; i++)
-                       brelse(t_bhs[i]);
-       }
-       kfree(t_bhs);
+out:
+       ocfs2_xattr_bucket_free(t_bucket);
+       ocfs2_xattr_bucket_free(s_bucket);
 
        return ret;
 }
 
 /*
- * Copy one xattr cluster from src_blk to to_blk.
- * The to_blk will become the first bucket header of the cluster, so its
- * xh_num_buckets will be initialized as the bucket num in the cluster.
+ * src_blk points to the start of an existing extent.  last_blk points to
+ * last cluster in that extent.  to_blk points to a newly allocated
+ * extent.  We copy the buckets from the cluster at last_blk to the new
+ * extent.  If start_bucket is non-zero, we skip that many buckets before
+ * we start copying.  The new extent's xh_num_buckets gets set to the
+ * number of buckets we copied.  The old extent's xh_num_buckets shrinks
+ * by the same amount.
  */
-static int ocfs2_cp_xattr_cluster(struct inode *inode,
-                                 handle_t *handle,
-                                 struct buffer_head *first_bh,
-                                 u64 src_blk,
-                                 u64 to_blk,
+static int ocfs2_mv_xattr_buckets(struct inode *inode, handle_t *handle,
+                                 u64 src_blk, u64 last_blk, u64 to_blk,
+                                 unsigned int start_bucket,
                                  u32 *first_hash)
 {
        int i, ret, credits;
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
-       int bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1);
+       int blks_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
        int num_buckets = ocfs2_xattr_buckets_per_cluster(osb);
-       struct buffer_head *bh = NULL;
-       struct ocfs2_xattr_header *xh;
-       u64 to_blk_start = to_blk;
+       struct ocfs2_xattr_bucket *old_first, *new_first;
+
+       mlog(0, "mv xattrs from cluster %llu to %llu\n",
+            (unsigned long long)last_blk, (unsigned long long)to_blk);
+
+       BUG_ON(start_bucket >= num_buckets);
+       if (start_bucket) {
+               num_buckets -= start_bucket;
+               last_blk += (start_bucket * blks_per_bucket);
+       }
 
-       mlog(0, "cp xattrs from cluster %llu to %llu\n",
-            (unsigned long long)src_blk, (unsigned long long)to_blk);
+       /* The first bucket of the original extent */
+       old_first = ocfs2_xattr_bucket_new(inode);
+       /* The first bucket of the new extent */
+       new_first = ocfs2_xattr_bucket_new(inode);
+       if (!old_first || !new_first) {
+               ret = -ENOMEM;
+               mlog_errno(ret);
+               goto out;
+       }
+
+       ret = ocfs2_read_xattr_bucket(old_first, src_blk);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
+       }
 
        /*
-        * We need to update the new cluster and 1 more for the update of
-        * the 1st bucket of the previous extent rec.
+        * We need to update the first bucket of the old extent and all
+        * the buckets going to the new extent.
         */
-       credits = bpc + 1;
+       credits = ((num_buckets + 1) * blks_per_bucket) +
+               handle->h_buffer_credits;
        ret = ocfs2_extend_trans(handle, credits);
        if (ret) {
                mlog_errno(ret);
                goto out;
        }
 
-       ret = ocfs2_journal_access(handle, inode, first_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = ocfs2_xattr_bucket_journal_access(handle, old_first,
+                                               OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -3480,45 +4069,45 @@ static int ocfs2_cp_xattr_cluster(struct inode *inode,
 
        for (i = 0; i < num_buckets; i++) {
                ret = ocfs2_cp_xattr_bucket(inode, handle,
-                                           src_blk, to_blk, 1);
+                                           last_blk + (i * blks_per_bucket),
+                                           to_blk + (i * blks_per_bucket),
+                                           1);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
                }
-
-               src_blk += ocfs2_blocks_per_xattr_bucket(inode->i_sb);
-               to_blk += ocfs2_blocks_per_xattr_bucket(inode->i_sb);
        }
 
-       /* update the old bucket header. */
-       xh = (struct ocfs2_xattr_header *)first_bh->b_data;
-       le16_add_cpu(&xh->xh_num_buckets, -num_buckets);
-
-       ocfs2_journal_dirty(handle, first_bh);
-
-       /* update the new bucket header. */
-       ret = ocfs2_read_block(inode, to_blk_start, &bh);
-       if (ret < 0) {
+       /*
+        * Get the new bucket ready before we dirty anything
+        * (This actually shouldn't fail, because we already dirtied
+        * it once in ocfs2_cp_xattr_bucket()).
+        */
+       ret = ocfs2_read_xattr_bucket(new_first, to_blk);
+       if (ret) {
                mlog_errno(ret);
                goto out;
        }
-
-       ret = ocfs2_journal_access(handle, inode, bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = ocfs2_xattr_bucket_journal_access(handle, new_first,
+                                               OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
                goto out;
        }
 
-       xh = (struct ocfs2_xattr_header *)bh->b_data;
-       xh->xh_num_buckets = cpu_to_le16(num_buckets);
+       /* Now update the headers */
+       le16_add_cpu(&bucket_xh(old_first)->xh_num_buckets, -num_buckets);
+       ocfs2_xattr_bucket_journal_dirty(handle, old_first);
 
-       ocfs2_journal_dirty(handle, bh);
+       bucket_xh(new_first)->xh_num_buckets = cpu_to_le16(num_buckets);
+       ocfs2_xattr_bucket_journal_dirty(handle, new_first);
 
        if (first_hash)
-               *first_hash = le32_to_cpu(xh->xh_entries[0].xe_name_hash);
+               *first_hash = le32_to_cpu(bucket_xh(new_first)->xh_entries[0].xe_name_hash);
+
 out:
-       brelse(bh);
+       ocfs2_xattr_bucket_free(new_first);
+       ocfs2_xattr_bucket_free(old_first);
        return ret;
 }
 
@@ -3534,7 +4123,7 @@ static int ocfs2_divide_xattr_cluster(struct inode *inode,
                                      u32 *first_hash)
 {
        u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
-       int ret, credits = 2 * blk_per_bucket;
+       int ret, credits = 2 * blk_per_bucket + handle->h_buffer_credits;
 
        BUG_ON(OCFS2_XATTR_BUCKET_SIZE < OCFS2_SB(inode->i_sb)->s_clustersize);
 
@@ -3577,43 +4166,49 @@ static int ocfs2_divide_xattr_cluster(struct inode *inode,
  */
 static int ocfs2_adjust_xattr_cross_cluster(struct inode *inode,
                                            handle_t *handle,
-                                           struct buffer_head **first_bh,
-                                           struct buffer_head **header_bh,
+                                           struct ocfs2_xattr_bucket *first,
+                                           struct ocfs2_xattr_bucket *target,
                                            u64 new_blk,
-                                           u64 prev_blk,
                                            u32 prev_clusters,
                                            u32 *v_start,
                                            int *extend)
 {
-       int ret = 0;
-       int bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1);
+       int ret;
 
        mlog(0, "adjust xattrs from cluster %llu len %u to %llu\n",
-            (unsigned long long)prev_blk, prev_clusters,
+            (unsigned long long)bucket_blkno(first), prev_clusters,
             (unsigned long long)new_blk);
 
-       if (ocfs2_xattr_buckets_per_cluster(OCFS2_SB(inode->i_sb)) > 1)
+       if (ocfs2_xattr_buckets_per_cluster(OCFS2_SB(inode->i_sb)) > 1) {
                ret = ocfs2_mv_xattr_bucket_cross_cluster(inode,
                                                          handle,
-                                                         first_bh,
-                                                         header_bh,
+                                                         first, target,
                                                          new_blk,
-                                                         prev_blk,
                                                          prev_clusters,
                                                          v_start);
-       else {
-               u64 last_blk = prev_blk + bpc * (prev_clusters - 1);
-
-               if (prev_clusters > 1 && (*header_bh)->b_blocknr != last_blk)
-                       ret = ocfs2_cp_xattr_cluster(inode, handle, *first_bh,
-                                                    last_blk, new_blk,
+               if (ret)
+                       mlog_errno(ret);
+       } else {
+               /* The start of the last cluster in the first extent */
+               u64 last_blk = bucket_blkno(first) +
+                       ((prev_clusters - 1) *
+                        ocfs2_clusters_to_blocks(inode->i_sb, 1));
+
+               if (prev_clusters > 1 && bucket_blkno(target) != last_blk) {
+                       ret = ocfs2_mv_xattr_buckets(inode, handle,
+                                                    bucket_blkno(first),
+                                                    last_blk, new_blk, 0,
                                                     v_start);
-               else {
+                       if (ret)
+                               mlog_errno(ret);
+               } else {
                        ret = ocfs2_divide_xattr_cluster(inode, handle,
                                                         last_blk, new_blk,
                                                         v_start);
+                       if (ret)
+                               mlog_errno(ret);
 
-                       if ((*header_bh)->b_blocknr == last_blk && extend)
+                       if ((bucket_blkno(target) == last_blk) && extend)
                                *extend = 0;
                }
        }
@@ -3639,56 +4234,37 @@ static int ocfs2_adjust_xattr_cross_cluster(struct inode *inode,
  */
 static int ocfs2_add_new_xattr_cluster(struct inode *inode,
                                       struct buffer_head *root_bh,
-                                      struct buffer_head **first_bh,
-                                      struct buffer_head **header_bh,
+                                      struct ocfs2_xattr_bucket *first,
+                                      struct ocfs2_xattr_bucket *target,
                                       u32 *num_clusters,
                                       u32 prev_cpos,
-                                      u64 prev_blkno,
-                                      int *extend)
+                                      int *extend,
+                                      struct ocfs2_xattr_set_ctxt *ctxt)
 {
-       int ret, credits;
+       int ret;
        u16 bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1);
        u32 prev_clusters = *num_clusters;
        u32 clusters_to_add = 1, bit_off, num_bits, v_start = 0;
        u64 block;
-       handle_t *handle = NULL;
-       struct ocfs2_alloc_context *data_ac = NULL;
-       struct ocfs2_alloc_context *meta_ac = NULL;
+       handle_t *handle = ctxt->handle;
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
        struct ocfs2_extent_tree et;
 
        mlog(0, "Add new xattr cluster for %llu, previous xattr hash = %u, "
             "previous xattr blkno = %llu\n",
             (unsigned long long)OCFS2_I(inode)->ip_blkno,
-            prev_cpos, (unsigned long long)prev_blkno);
+            prev_cpos, (unsigned long long)bucket_blkno(first));
 
        ocfs2_init_xattr_tree_extent_tree(&et, inode, root_bh);
 
-       ret = ocfs2_lock_allocators(inode, &et, clusters_to_add, 0,
-                                   &data_ac, &meta_ac);
-       if (ret) {
-               mlog_errno(ret);
-               goto leave;
-       }
-
-       credits = ocfs2_calc_extend_credits(osb->sb, et.et_root_el,
-                                           clusters_to_add);
-       handle = ocfs2_start_trans(osb, credits);
-       if (IS_ERR(handle)) {
-               ret = PTR_ERR(handle);
-               handle = NULL;
-               mlog_errno(ret);
-               goto leave;
-       }
-
-       ret = ocfs2_journal_access(handle, inode, root_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = ocfs2_journal_access_xb(handle, inode, root_bh,
+                                     OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret < 0) {
                mlog_errno(ret);
                goto leave;
        }
 
-       ret = __ocfs2_claim_clusters(osb, handle, data_ac, 1,
+       ret = __ocfs2_claim_clusters(osb, handle, ctxt->data_ac, 1,
                                     clusters_to_add, &bit_off, &num_bits);
        if (ret < 0) {
                if (ret != -ENOSPC)
@@ -3702,7 +4278,7 @@ static int ocfs2_add_new_xattr_cluster(struct inode *inode,
        mlog(0, "Allocating %u clusters at block %u for xattr in inode %llu\n",
             num_bits, bit_off, (unsigned long long)OCFS2_I(inode)->ip_blkno);
 
-       if (prev_blkno + prev_clusters * bpc == block &&
+       if (bucket_blkno(first) + (prev_clusters * bpc) == block &&
            (prev_clusters + num_bits) << osb->s_clustersize_bits <=
             OCFS2_MAX_XATTR_TREE_LEAF_SIZE) {
                /*
@@ -3721,10 +4297,9 @@ static int ocfs2_add_new_xattr_cluster(struct inode *inode,
        } else {
                ret = ocfs2_adjust_xattr_cross_cluster(inode,
                                                       handle,
-                                                      first_bh,
-                                                      header_bh,
+                                                      first,
+                                                      target,
                                                       block,
-                                                      prev_blkno,
                                                       prev_clusters,
                                                       &v_start,
                                                       extend);
@@ -3734,149 +4309,137 @@ static int ocfs2_add_new_xattr_cluster(struct inode *inode,
                }
        }
 
-       if (handle->h_buffer_credits < credits) {
-               /*
-                * The journal has been restarted before, and don't
-                * have enough space for the insertion, so extend it
-                * here.
-                */
-               ret = ocfs2_extend_trans(handle, credits);
-               if (ret) {
-                       mlog_errno(ret);
-                       goto leave;
-               }
-       }
        mlog(0, "Insert %u clusters at block %llu for xattr at %u\n",
             num_bits, (unsigned long long)block, v_start);
        ret = ocfs2_insert_extent(osb, handle, inode, &et, v_start, block,
-                                 num_bits, 0, meta_ac);
+                                 num_bits, 0, ctxt->meta_ac);
        if (ret < 0) {
                mlog_errno(ret);
                goto leave;
        }
 
        ret = ocfs2_journal_dirty(handle, root_bh);
-       if (ret < 0) {
+       if (ret < 0)
                mlog_errno(ret);
-               goto leave;
-       }
 
 leave:
-       if (handle)
-               ocfs2_commit_trans(osb, handle);
-       if (data_ac)
-               ocfs2_free_alloc_context(data_ac);
-       if (meta_ac)
-               ocfs2_free_alloc_context(meta_ac);
-
        return ret;
 }
 
 /*
- * Extend a new xattr bucket and move xattrs to the end one by one until
- * We meet with start_bh. Only move half of the xattrs to the bucket after it.
+ * We are given an extent.  'first' is the bucket at the very front of
+ * the extent.  The extent has space for an additional bucket past
+ * bucket_xh(first)->xh_num_buckets.  'target_blkno' is the block number
+ * of the target bucket.  We wish to shift every bucket past the target
+ * down one, filling in that additional space.  When we get back to the
+ * target, we split the target between itself and the now-empty bucket
+ * at target+1 (aka, target_blkno + blks_per_bucket).
  */
 static int ocfs2_extend_xattr_bucket(struct inode *inode,
-                                    struct buffer_head *first_bh,
-                                    struct buffer_head *start_bh,
+                                    handle_t *handle,
+                                    struct ocfs2_xattr_bucket *first,
+                                    u64 target_blk,
                                     u32 num_clusters)
 {
        int ret, credits;
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
        u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
-       u64 start_blk = start_bh->b_blocknr, end_blk;
-       u32 num_buckets = num_clusters * ocfs2_xattr_buckets_per_cluster(osb);
-       handle_t *handle;
-       struct ocfs2_xattr_header *first_xh =
-                               (struct ocfs2_xattr_header *)first_bh->b_data;
-       u16 bucket = le16_to_cpu(first_xh->xh_num_buckets);
+       u64 end_blk;
+       u16 new_bucket = le16_to_cpu(bucket_xh(first)->xh_num_buckets);
 
        mlog(0, "extend xattr bucket in %llu, xattr extend rec starting "
-            "from %llu, len = %u\n", (unsigned long long)start_blk,
-            (unsigned long long)first_bh->b_blocknr, num_clusters);
+            "from %llu, len = %u\n", (unsigned long long)target_blk,
+            (unsigned long long)bucket_blkno(first), num_clusters);
 
-       BUG_ON(bucket >= num_buckets);
+       /* The extent must have room for an additional bucket */
+       BUG_ON(new_bucket >=
+              (num_clusters * ocfs2_xattr_buckets_per_cluster(osb)));
 
-       end_blk = first_bh->b_blocknr + (bucket - 1) * blk_per_bucket;
+       /* end_blk points to the last existing bucket */
+       end_blk = bucket_blkno(first) + ((new_bucket - 1) * blk_per_bucket);
 
        /*
-        * We will touch all the buckets after the start_bh(include it).
-        * Add one more bucket and modify the first_bh.
+        * end_blk is the start of the last existing bucket.
+        * Thus, (end_blk - target_blk) covers the target bucket and
+        * every bucket after it up to, but not including, the last
+        * existing bucket.  Then we add the last existing bucket, the
+        * new bucket, and the first bucket (3 * blk_per_bucket).
         */
-       credits = end_blk - start_blk + 2 * blk_per_bucket + 1;
-       handle = ocfs2_start_trans(osb, credits);
-       if (IS_ERR(handle)) {
-               ret = PTR_ERR(handle);
-               handle = NULL;
+       credits = (end_blk - target_blk) + (3 * blk_per_bucket) +
+                 handle->h_buffer_credits;
+       ret = ocfs2_extend_trans(handle, credits);
+       if (ret) {
                mlog_errno(ret);
                goto out;
        }
 
-       ret = ocfs2_journal_access(handle, inode, first_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = ocfs2_xattr_bucket_journal_access(handle, first,
+                                               OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
-               goto commit;
+               goto out;
        }
 
-       while (end_blk != start_blk) {
+       while (end_blk != target_blk) {
                ret = ocfs2_cp_xattr_bucket(inode, handle, end_blk,
                                            end_blk + blk_per_bucket, 0);
                if (ret)
-                       goto commit;
+                       goto out;
                end_blk -= blk_per_bucket;
        }
 
-       /* Move half of the xattr in start_blk to the next bucket. */
-       ret = ocfs2_divide_xattr_bucket(inode, handle, start_blk,
-                                       start_blk + blk_per_bucket, NULL, 0);
+       /* Move half of the xattr in target_blkno to the next bucket. */
+       ret = ocfs2_divide_xattr_bucket(inode, handle, target_blk,
+                                       target_blk + blk_per_bucket, NULL, 0);
 
-       le16_add_cpu(&first_xh->xh_num_buckets, 1);
-       ocfs2_journal_dirty(handle, first_bh);
+       le16_add_cpu(&bucket_xh(first)->xh_num_buckets, 1);
+       ocfs2_xattr_bucket_journal_dirty(handle, first);
 
-commit:
-       ocfs2_commit_trans(osb, handle);
 out:
        return ret;
 }
 
 /*
- * Add new xattr bucket in an extent record and adjust the buckets accordingly.
- * xb_bh is the ocfs2_xattr_block.
- * We will move all the buckets starting from header_bh to the next place. As
- * for this one, half num of its xattrs will be moved to the next one.
+ * Add new xattr bucket in an extent record and adjust the buckets
+ * accordingly.  xb_bh is the ocfs2_xattr_block, and target is the
+ * bucket we want to insert into.
  *
- * We will allocate a new cluster if current cluster is full and adjust
- * header_bh and first_bh if the insert place is moved to the new cluster.
+ * In the easy case, we will move all the buckets after target down by
+ * one. Half of target's xattrs will be moved to the next bucket.
+ *
+ * If current cluster is full, we'll allocate a new one.  This may not
+ * be contiguous.  The underlying calls will make sure that there is
+ * space for the insert, shifting buckets around if necessary.
+ * 'target' may be moved by those calls.
  */
 static int ocfs2_add_new_xattr_bucket(struct inode *inode,
                                      struct buffer_head *xb_bh,
-                                     struct buffer_head *header_bh)
+                                     struct ocfs2_xattr_bucket *target,
+                                     struct ocfs2_xattr_set_ctxt *ctxt)
 {
-       struct ocfs2_xattr_header *first_xh = NULL;
-       struct buffer_head *first_bh = NULL;
        struct ocfs2_xattr_block *xb =
                        (struct ocfs2_xattr_block *)xb_bh->b_data;
        struct ocfs2_xattr_tree_root *xb_root = &xb->xb_attrs.xb_root;
        struct ocfs2_extent_list *el = &xb_root->xt_list;
-       struct ocfs2_xattr_header *xh =
-                       (struct ocfs2_xattr_header *)header_bh->b_data;
-       u32 name_hash = le32_to_cpu(xh->xh_entries[0].xe_name_hash);
-       struct super_block *sb = inode->i_sb;
-       struct ocfs2_super *osb = OCFS2_SB(sb);
+       u32 name_hash =
+               le32_to_cpu(bucket_xh(target)->xh_entries[0].xe_name_hash);
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
        int ret, num_buckets, extend = 1;
        u64 p_blkno;
        u32 e_cpos, num_clusters;
+       /* The bucket at the front of the extent */
+       struct ocfs2_xattr_bucket *first;
 
-       mlog(0, "Add new xattr bucket starting form %llu\n",
-            (unsigned long long)header_bh->b_blocknr);
+       mlog(0, "Add new xattr bucket starting from %llu\n",
+            (unsigned long long)bucket_blkno(target));
 
-       /*
-        * Add refrence for header_bh here because it may be
-        * changed in ocfs2_add_new_xattr_cluster and we need
-        * to free it in the end.
-        */
-       get_bh(header_bh);
+       /* The first bucket of the original extent */
+       first = ocfs2_xattr_bucket_new(inode);
+       if (!first) {
+               ret = -ENOMEM;
+               mlog_errno(ret);
+               goto out;
+       }
 
        ret = ocfs2_xattr_get_rec(inode, name_hash, &p_blkno, &e_cpos,
                                  &num_clusters, el);
@@ -3885,40 +4448,45 @@ static int ocfs2_add_new_xattr_bucket(struct inode *inode,
                goto out;
        }
 
-       ret = ocfs2_read_block(inode, p_blkno, &first_bh);
+       ret = ocfs2_read_xattr_bucket(first, p_blkno);
        if (ret) {
                mlog_errno(ret);
                goto out;
        }
 
        num_buckets = ocfs2_xattr_buckets_per_cluster(osb) * num_clusters;
-       first_xh = (struct ocfs2_xattr_header *)first_bh->b_data;
-
-       if (num_buckets == le16_to_cpu(first_xh->xh_num_buckets)) {
+       if (num_buckets == le16_to_cpu(bucket_xh(first)->xh_num_buckets)) {
+               /*
+                * This can move first+target if the target bucket moves
+                * to the new extent.
+                */
                ret = ocfs2_add_new_xattr_cluster(inode,
                                                  xb_bh,
-                                                 &first_bh,
-                                                 &header_bh,
+                                                 first,
+                                                 target,
                                                  &num_clusters,
                                                  e_cpos,
-                                                 p_blkno,
-                                                 &extend);
+                                                 &extend,
+                                                 ctxt);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
                }
        }
 
-       if (extend)
+       if (extend) {
                ret = ocfs2_extend_xattr_bucket(inode,
-                                               first_bh,
-                                               header_bh,
+                                               ctxt->handle,
+                                               first,
+                                               bucket_blkno(target),
                                                num_clusters);
-       if (ret)
-               mlog_errno(ret);
+               if (ret)
+                       mlog_errno(ret);
+       }
+
 out:
-       brelse(first_bh);
-       brelse(header_bh);
+       ocfs2_xattr_bucket_free(first);
+
        return ret;
 }
 
@@ -3929,7 +4497,7 @@ static inline char *ocfs2_xattr_bucket_get_val(struct inode *inode,
        int block_off = offs >> inode->i_sb->s_blocksize_bits;
 
        offs = offs % inode->i_sb->s_blocksize;
-       return bucket->bhs[block_off]->b_data + offs;
+       return bucket_block(bucket, block_off) + offs;
 }
 
 /*
@@ -3984,7 +4552,7 @@ static void ocfs2_xattr_set_entry_normal(struct inode *inode,
                                xe->xe_value_size = 0;
 
                        val = ocfs2_xattr_bucket_get_val(inode,
-                                                        &xs->bucket, offs);
+                                                        xs->bucket, offs);
                        memset(val + OCFS2_XATTR_SIZE(name_len), 0,
                               size - OCFS2_XATTR_SIZE(name_len));
                        if (OCFS2_XATTR_SIZE(xi->value_len) > 0)
@@ -4062,8 +4630,7 @@ set_new_name_value:
                xh->xh_free_start = cpu_to_le16(offs);
        }
 
-       val = ocfs2_xattr_bucket_get_val(inode,
-                                        &xs->bucket, offs - size);
+       val = ocfs2_xattr_bucket_get_val(inode, xs->bucket, offs - size);
        xe->xe_name_offset = cpu_to_le16(offs - size);
 
        memset(val, 0, size);
@@ -4079,125 +4646,45 @@ set_new_name_value:
        return;
 }
 
-static int ocfs2_xattr_bucket_handle_journal(struct inode *inode,
-                                            handle_t *handle,
-                                            struct ocfs2_xattr_search *xs,
-                                            struct buffer_head **bhs,
-                                            u16 bh_num)
-{
-       int ret = 0, off, block_off;
-       struct ocfs2_xattr_entry *xe = xs->here;
-
-       /*
-        * First calculate all the blocks we should journal_access
-        * and journal_dirty. The first block should always be touched.
-        */
-       ret = ocfs2_journal_dirty(handle, bhs[0]);
-       if (ret)
-               mlog_errno(ret);
-
-       /* calc the data. */
-       off = le16_to_cpu(xe->xe_name_offset);
-       block_off = off >> inode->i_sb->s_blocksize_bits;
-       ret = ocfs2_journal_dirty(handle, bhs[block_off]);
-       if (ret)
-               mlog_errno(ret);
-
-       return ret;
-}
-
 /*
  * Set the xattr entry in the specified bucket.
  * The bucket is indicated by xs->bucket and it should have the enough
  * space for the xattr insertion.
  */
 static int ocfs2_xattr_set_entry_in_bucket(struct inode *inode,
+                                          handle_t *handle,
                                           struct ocfs2_xattr_info *xi,
                                           struct ocfs2_xattr_search *xs,
                                           u32 name_hash,
                                           int local)
 {
-       int i, ret;
-       handle_t *handle = NULL;
-       u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
-       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       int ret;
+       u64 blkno;
 
        mlog(0, "Set xattr entry len = %lu index = %d in bucket %llu\n",
             (unsigned long)xi->value_len, xi->name_index,
-            (unsigned long long)xs->bucket.bhs[0]->b_blocknr);
+            (unsigned long long)bucket_blkno(xs->bucket));
 
-       if (!xs->bucket.bhs[1]) {
-               ret = ocfs2_read_blocks(inode,
-                                       xs->bucket.bhs[0]->b_blocknr + 1,
-                                       blk_per_bucket - 1, &xs->bucket.bhs[1],
-                                       0);
+       if (!xs->bucket->bu_bhs[1]) {
+               blkno = bucket_blkno(xs->bucket);
+               ocfs2_xattr_bucket_relse(xs->bucket);
+               ret = ocfs2_read_xattr_bucket(xs->bucket, blkno);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
                }
        }
 
-       handle = ocfs2_start_trans(osb, blk_per_bucket);
-       if (IS_ERR(handle)) {
-               ret = PTR_ERR(handle);
-               handle = NULL;
+       ret = ocfs2_xattr_bucket_journal_access(handle, xs->bucket,
+                                               OCFS2_JOURNAL_ACCESS_WRITE);
+       if (ret < 0) {
                mlog_errno(ret);
                goto out;
        }
 
-       for (i = 0; i < blk_per_bucket; i++) {
-               ret = ocfs2_journal_access(handle, inode, xs->bucket.bhs[i],
-                                          OCFS2_JOURNAL_ACCESS_WRITE);
-               if (ret < 0) {
-                       mlog_errno(ret);
-                       goto out;
-               }
-       }
-
        ocfs2_xattr_set_entry_normal(inode, xi, xs, name_hash, local);
+       ocfs2_xattr_bucket_journal_dirty(handle, xs->bucket);
 
-       /*Only dirty the blocks we have touched in set xattr. */
-       ret = ocfs2_xattr_bucket_handle_journal(inode, handle, xs,
-                                               xs->bucket.bhs, blk_per_bucket);
-       if (ret)
-               mlog_errno(ret);
-out:
-       ocfs2_commit_trans(osb, handle);
-
-       return ret;
-}
-
-static int ocfs2_xattr_value_update_size(struct inode *inode,
-                                        struct buffer_head *xe_bh,
-                                        struct ocfs2_xattr_entry *xe,
-                                        u64 new_size)
-{
-       int ret;
-       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
-       handle_t *handle = NULL;
-
-       handle = ocfs2_start_trans(osb, 1);
-       if (IS_ERR(handle)) {
-               ret = -ENOMEM;
-               mlog_errno(ret);
-               goto out;
-       }
-
-       ret = ocfs2_journal_access(handle, inode, xe_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
-       if (ret < 0) {
-               mlog_errno(ret);
-               goto out_commit;
-       }
-
-       xe->xe_value_size = cpu_to_le64(new_size);
-
-       ret = ocfs2_journal_dirty(handle, xe_bh);
-       if (ret < 0)
-               mlog_errno(ret);
-
-out_commit:
-       ocfs2_commit_trans(osb, handle);
 out:
        return ret;
 }
@@ -4210,18 +4697,19 @@ out:
  * Copy the new updated xe and xe_value_root to new_xe and new_xv if needed.
  */
 static int ocfs2_xattr_bucket_value_truncate(struct inode *inode,
-                                            struct buffer_head *header_bh,
+                                            struct ocfs2_xattr_bucket *bucket,
                                             int xe_off,
-                                            int len)
+                                            int len,
+                                            struct ocfs2_xattr_set_ctxt *ctxt)
 {
        int ret, offset;
        u64 value_blk;
-       struct buffer_head *value_bh = NULL;
-       struct ocfs2_xattr_value_root *xv;
        struct ocfs2_xattr_entry *xe;
-       struct ocfs2_xattr_header *xh =
-                       (struct ocfs2_xattr_header *)header_bh->b_data;
+       struct ocfs2_xattr_header *xh = bucket_xh(bucket);
        size_t blocksize = inode->i_sb->s_blocksize;
+       struct ocfs2_xattr_value_buf vb = {
+               .vb_access = ocfs2_journal_access,
+       };
 
        xe = &xh->xh_entries[xe_off];
 
@@ -4234,49 +4722,58 @@ static int ocfs2_xattr_bucket_value_truncate(struct inode *inode,
 
        /* We don't allow ocfs2_xattr_value to be stored in different block. */
        BUG_ON(value_blk != (offset + OCFS2_XATTR_ROOT_SIZE - 1) / blocksize);
-       value_blk += header_bh->b_blocknr;
 
-       ret = ocfs2_read_block(inode, value_blk, &value_bh);
-       if (ret) {
-               mlog_errno(ret);
-               goto out;
-       }
+       vb.vb_bh = bucket->bu_bhs[value_blk];
+       BUG_ON(!vb.vb_bh);
 
-       xv = (struct ocfs2_xattr_value_root *)
-               (value_bh->b_data + offset % blocksize);
+       vb.vb_xv = (struct ocfs2_xattr_value_root *)
+               (vb.vb_bh->b_data + offset % blocksize);
 
-       mlog(0, "truncate %u in xattr bucket %llu to %d bytes.\n",
-            xe_off, (unsigned long long)header_bh->b_blocknr, len);
-       ret = ocfs2_xattr_value_truncate(inode, value_bh, xv, len);
+       ret = ocfs2_xattr_bucket_journal_access(ctxt->handle, bucket,
+                                               OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
                goto out;
        }
 
-       ret = ocfs2_xattr_value_update_size(inode, header_bh, xe, len);
+       /*
+        * From here on out we have to dirty the bucket.  The generic
+        * value calls only modify one of the bucket's bhs, but we need
+        * to send the bucket at once.  So if they error, they *could* have
+        * modified something.  We have to assume they did, and dirty
+        * the whole bucket.  This leaves us in a consistent state.
+        */
+       mlog(0, "truncate %u in xattr bucket %llu to %d bytes.\n",
+            xe_off, (unsigned long long)bucket_blkno(bucket), len);
+       ret = ocfs2_xattr_value_truncate(inode, &vb, len, ctxt);
        if (ret) {
                mlog_errno(ret);
-               goto out;
+               goto out_dirty;
        }
 
+       xe->xe_value_size = cpu_to_le64(len);
+
+out_dirty:
+       ocfs2_xattr_bucket_journal_dirty(ctxt->handle, bucket);
+
 out:
-       brelse(value_bh);
        return ret;
 }
 
 static int ocfs2_xattr_bucket_value_truncate_xs(struct inode *inode,
-                                               struct ocfs2_xattr_search *xs,
-                                               int len)
+                                       struct ocfs2_xattr_search *xs,
+                                       int len,
+                                       struct ocfs2_xattr_set_ctxt *ctxt)
 {
        int ret, offset;
        struct ocfs2_xattr_entry *xe = xs->here;
        struct ocfs2_xattr_header *xh = (struct ocfs2_xattr_header *)xs->base;
 
-       BUG_ON(!xs->bucket.bhs[0] || !xe || ocfs2_xattr_is_local(xe));
+       BUG_ON(!xs->bucket->bu_bhs[0] || !xe || ocfs2_xattr_is_local(xe));
 
        offset = xe - xh->xh_entries;
-       ret = ocfs2_xattr_bucket_value_truncate(inode, xs->bucket.bhs[0],
-                                               offset, len);
+       ret = ocfs2_xattr_bucket_value_truncate(inode, xs->bucket,
+                                               offset, len, ctxt);
        if (ret)
                mlog_errno(ret);
 
@@ -4284,6 +4781,7 @@ static int ocfs2_xattr_bucket_value_truncate_xs(struct inode *inode,
 }
 
 static int ocfs2_xattr_bucket_set_value_outside(struct inode *inode,
+                                               handle_t *handle,
                                                struct ocfs2_xattr_search *xs,
                                                char *val,
                                                int value_len)
@@ -4299,7 +4797,8 @@ static int ocfs2_xattr_bucket_set_value_outside(struct inode *inode,
 
        xv = (struct ocfs2_xattr_value_root *)(xs->base + offset);
 
-       return __ocfs2_xattr_set_value_outside(inode, xv, val, value_len);
+       return __ocfs2_xattr_set_value_outside(inode, handle,
+                                              xv, val, value_len);
 }
 
 static int ocfs2_rm_xattr_cluster(struct inode *inode,
@@ -4343,15 +4842,15 @@ static int ocfs2_rm_xattr_cluster(struct inode *inode,
                }
        }
 
-       handle = ocfs2_start_trans(osb, OCFS2_REMOVE_EXTENT_CREDITS);
+       handle = ocfs2_start_trans(osb, ocfs2_remove_extent_credits(osb->sb));
        if (IS_ERR(handle)) {
                ret = -ENOMEM;
                mlog_errno(ret);
                goto out;
        }
 
-       ret = ocfs2_journal_access(handle, inode, root_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = ocfs2_journal_access_xb(handle, inode, root_bh,
+                                     OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
                goto out_commit;
@@ -4392,26 +4891,19 @@ out:
 }
 
 static void ocfs2_xattr_bucket_remove_xs(struct inode *inode,
+                                        handle_t *handle,
                                         struct ocfs2_xattr_search *xs)
 {
-       handle_t *handle = NULL;
-       struct ocfs2_xattr_header *xh = xs->bucket.xh;
+       struct ocfs2_xattr_header *xh = bucket_xh(xs->bucket);
        struct ocfs2_xattr_entry *last = &xh->xh_entries[
                                                le16_to_cpu(xh->xh_count) - 1];
        int ret = 0;
 
-       handle = ocfs2_start_trans((OCFS2_SB(inode->i_sb)), 1);
-       if (IS_ERR(handle)) {
-               ret = PTR_ERR(handle);
-               mlog_errno(ret);
-               return;
-       }
-
-       ret = ocfs2_journal_access(handle, inode, xs->bucket.bhs[0],
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = ocfs2_xattr_bucket_journal_access(handle, xs->bucket,
+                                               OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
-               goto out_commit;
+               return;
        }
 
        /* Remove the old entry. */
@@ -4420,11 +4912,7 @@ static void ocfs2_xattr_bucket_remove_xs(struct inode *inode,
        memset(last, 0, sizeof(struct ocfs2_xattr_entry));
        le16_add_cpu(&xh->xh_count, -1);
 
-       ret = ocfs2_journal_dirty(handle, xs->bucket.bhs[0]);
-       if (ret < 0)
-               mlog_errno(ret);
-out_commit:
-       ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle);
+       ocfs2_xattr_bucket_journal_dirty(handle, xs->bucket);
 }
 
 /*
@@ -4440,7 +4928,8 @@ out_commit:
  */
 static int ocfs2_xattr_set_in_bucket(struct inode *inode,
                                     struct ocfs2_xattr_info *xi,
-                                    struct ocfs2_xattr_search *xs)
+                                    struct ocfs2_xattr_search *xs,
+                                    struct ocfs2_xattr_set_ctxt *ctxt)
 {
        int ret, local = 1;
        size_t value_len;
@@ -4468,7 +4957,8 @@ static int ocfs2_xattr_set_in_bucket(struct inode *inode,
                        value_len = 0;
 
                ret = ocfs2_xattr_bucket_value_truncate_xs(inode, xs,
-                                                          value_len);
+                                                          value_len,
+                                                          ctxt);
                if (ret)
                        goto out;
 
@@ -4488,7 +4978,8 @@ static int ocfs2_xattr_set_in_bucket(struct inode *inode,
                xi->value_len = OCFS2_XATTR_ROOT_SIZE;
        }
 
-       ret = ocfs2_xattr_set_entry_in_bucket(inode, xi, xs, name_hash, local);
+       ret = ocfs2_xattr_set_entry_in_bucket(inode, ctxt->handle, xi, xs,
+                                             name_hash, local);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -4499,7 +4990,7 @@ static int ocfs2_xattr_set_in_bucket(struct inode *inode,
 
        /* allocate the space now for the outside block storage. */
        ret = ocfs2_xattr_bucket_value_truncate_xs(inode, xs,
-                                                  value_len);
+                                                  value_len, ctxt);
        if (ret) {
                mlog_errno(ret);
 
@@ -4509,13 +5000,14 @@ static int ocfs2_xattr_set_in_bucket(struct inode *inode,
                         * storage and we have allocated xattr already,
                         * so need to remove it.
                         */
-                       ocfs2_xattr_bucket_remove_xs(inode, xs);
+                       ocfs2_xattr_bucket_remove_xs(inode, ctxt->handle, xs);
                }
                goto out;
        }
 
 set_value_outside:
-       ret = ocfs2_xattr_bucket_set_value_outside(inode, xs, val, value_len);
+       ret = ocfs2_xattr_bucket_set_value_outside(inode, ctxt->handle,
+                                                  xs, val, value_len);
 out:
        return ret;
 }
@@ -4530,7 +5022,7 @@ static int ocfs2_check_xattr_bucket_collision(struct inode *inode,
                                              struct ocfs2_xattr_bucket *bucket,
                                              const char *name)
 {
-       struct ocfs2_xattr_header *xh = bucket->xh;
+       struct ocfs2_xattr_header *xh = bucket_xh(bucket);
        u32 name_hash = ocfs2_xattr_name_hash(inode, name, strlen(name));
 
        if (name_hash != le32_to_cpu(xh->xh_entries[0].xe_name_hash))
@@ -4540,7 +5032,7 @@ static int ocfs2_check_xattr_bucket_collision(struct inode *inode,
            xh->xh_entries[0].xe_name_hash) {
                mlog(ML_ERROR, "Too much hash collision in xattr bucket %llu, "
                     "hash = %u\n",
-                    (unsigned long long)bucket->bhs[0]->b_blocknr,
+                    (unsigned long long)bucket_blkno(bucket),
                     le32_to_cpu(xh->xh_entries[0].xe_name_hash));
                return -ENOSPC;
        }
@@ -4550,16 +5042,16 @@ static int ocfs2_check_xattr_bucket_collision(struct inode *inode,
 
 static int ocfs2_xattr_set_entry_index_block(struct inode *inode,
                                             struct ocfs2_xattr_info *xi,
-                                            struct ocfs2_xattr_search *xs)
+                                            struct ocfs2_xattr_search *xs,
+                                            struct ocfs2_xattr_set_ctxt *ctxt)
 {
        struct ocfs2_xattr_header *xh;
        struct ocfs2_xattr_entry *xe;
        u16 count, header_size, xh_free_start;
-       int i, free, max_free, need, old;
+       int free, max_free, need, old;
        size_t value_size = 0, name_len = strlen(xi->name);
        size_t blocksize = inode->i_sb->s_blocksize;
        int ret, allocation = 0;
-       u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
 
        mlog_entry("Set xattr %s in xattr index block\n", xi->name);
 
@@ -4574,7 +5066,7 @@ try_again:
 
        mlog_bug_on_msg(header_size > blocksize, "bucket %llu has header size "
                        "of %u which exceed block size\n",
-                       (unsigned long long)xs->bucket.bhs[0]->b_blocknr,
+                       (unsigned long long)bucket_blkno(xs->bucket),
                        header_size);
 
        if (xi->value && xi->value_len > OCFS2_XATTR_INLINE_SIZE)
@@ -4614,11 +5106,13 @@ try_again:
        mlog(0, "xs->not_found = %d, in xattr bucket %llu: free = %d, "
             "need = %d, max_free = %d, xh_free_start = %u, xh_name_value_len ="
             " %u\n", xs->not_found,
-            (unsigned long long)xs->bucket.bhs[0]->b_blocknr,
+            (unsigned long long)bucket_blkno(xs->bucket),
             free, need, max_free, le16_to_cpu(xh->xh_free_start),
             le16_to_cpu(xh->xh_name_value_len));
 
-       if (free < need || count == ocfs2_xattr_max_xe_in_bucket(inode->i_sb)) {
+       if (free < need ||
+           (xs->not_found &&
+            count == ocfs2_xattr_max_xe_in_bucket(inode->i_sb))) {
                if (need <= max_free &&
                    count < ocfs2_xattr_max_xe_in_bucket(inode->i_sb)) {
                        /*
@@ -4626,7 +5120,8 @@ try_again:
                         * name/value will be moved, the xe shouldn't be changed
                         * in xs.
                         */
-                       ret = ocfs2_defrag_xattr_bucket(inode, &xs->bucket);
+                       ret = ocfs2_defrag_xattr_bucket(inode, ctxt->handle,
+                                                       xs->bucket);
                        if (ret) {
                                mlog_errno(ret);
                                goto out;
@@ -4658,7 +5153,7 @@ try_again:
                 * add a new bucket for the insert.
                 */
                ret = ocfs2_check_xattr_bucket_collision(inode,
-                                                        &xs->bucket,
+                                                        xs->bucket,
                                                         xi->name);
                if (ret) {
                        mlog_errno(ret);
@@ -4667,17 +5162,21 @@ try_again:
 
                ret = ocfs2_add_new_xattr_bucket(inode,
                                                 xs->xattr_bh,
-                                                xs->bucket.bhs[0]);
+                                                xs->bucket,
+                                                ctxt);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
                }
 
-               for (i = 0; i < blk_per_bucket; i++)
-                       brelse(xs->bucket.bhs[i]);
-
-               memset(&xs->bucket, 0, sizeof(xs->bucket));
-
+               /*
+                * ocfs2_add_new_xattr_bucket() will have updated
+                * xs->bucket if it moved, but it will not have updated
+                * any of the other search fields.  Thus, we drop it and
+                * re-search.  Everything should be cached, so it'll be
+                * quick.
+                */
+               ocfs2_xattr_bucket_relse(xs->bucket);
                ret = ocfs2_xattr_index_block_find(inode, xs->xattr_bh,
                                                   xi->name_index,
                                                   xi->name, xs);
@@ -4689,7 +5188,7 @@ try_again:
        }
 
 xattr_set:
-       ret = ocfs2_xattr_set_in_bucket(inode, xi, xs);
+       ret = ocfs2_xattr_set_in_bucket(inode, xi, xs, ctxt);
 out:
        mlog_exit(ret);
        return ret;
@@ -4700,24 +5199,41 @@ static int ocfs2_delete_xattr_in_bucket(struct inode *inode,
                                        void *para)
 {
        int ret = 0;
-       struct ocfs2_xattr_header *xh = bucket->xh;
+       struct ocfs2_xattr_header *xh = bucket_xh(bucket);
        u16 i;
        struct ocfs2_xattr_entry *xe;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       struct ocfs2_xattr_set_ctxt ctxt = {NULL, NULL,};
+       int credits = ocfs2_remove_extent_credits(osb->sb) +
+               ocfs2_blocks_per_xattr_bucket(inode->i_sb);
+
+
+       ocfs2_init_dealloc_ctxt(&ctxt.dealloc);
 
        for (i = 0; i < le16_to_cpu(xh->xh_count); i++) {
                xe = &xh->xh_entries[i];
                if (ocfs2_xattr_is_local(xe))
                        continue;
 
-               ret = ocfs2_xattr_bucket_value_truncate(inode,
-                                                       bucket->bhs[0],
-                                                       i, 0);
+               ctxt.handle = ocfs2_start_trans(osb, credits);
+               if (IS_ERR(ctxt.handle)) {
+                       ret = PTR_ERR(ctxt.handle);
+                       mlog_errno(ret);
+                       break;
+               }
+
+               ret = ocfs2_xattr_bucket_value_truncate(inode, bucket,
+                                                       i, 0, &ctxt);
+
+               ocfs2_commit_trans(osb, ctxt.handle);
                if (ret) {
                        mlog_errno(ret);
                        break;
                }
        }
 
+       ocfs2_schedule_truncate_log_flush(osb, 1);
+       ocfs2_run_deallocs(osb, &ctxt.dealloc);
        return ret;
 }
 
@@ -4767,6 +5283,74 @@ out:
        return ret;
 }
 
+/*
+ * 'security' attributes support
+ */
+static size_t ocfs2_xattr_security_list(struct inode *inode, char *list,
+                                       size_t list_size, const char *name,
+                                       size_t name_len)
+{
+       const size_t prefix_len = XATTR_SECURITY_PREFIX_LEN;
+       const size_t total_len = prefix_len + name_len + 1;
+
+       if (list && total_len <= list_size) {
+               memcpy(list, XATTR_SECURITY_PREFIX, prefix_len);
+               memcpy(list + prefix_len, name, name_len);
+               list[prefix_len + name_len] = '\0';
+       }
+       return total_len;
+}
+
+static int ocfs2_xattr_security_get(struct inode *inode, const char *name,
+                                   void *buffer, size_t size)
+{
+       if (strcmp(name, "") == 0)
+               return -EINVAL;
+       return ocfs2_xattr_get(inode, OCFS2_XATTR_INDEX_SECURITY, name,
+                              buffer, size);
+}
+
+static int ocfs2_xattr_security_set(struct inode *inode, const char *name,
+                                   const void *value, size_t size, int flags)
+{
+       if (strcmp(name, "") == 0)
+               return -EINVAL;
+
+       return ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_SECURITY, name, value,
+                              size, flags);
+}
+
+int ocfs2_init_security_get(struct inode *inode,
+                           struct inode *dir,
+                           struct ocfs2_security_xattr_info *si)
+{
+       /* check whether ocfs2 support feature xattr */
+       if (!ocfs2_supports_xattr(OCFS2_SB(dir->i_sb)))
+               return -EOPNOTSUPP;
+       return security_inode_init_security(inode, dir, &si->name, &si->value,
+                                           &si->value_len);
+}
+
+int ocfs2_init_security_set(handle_t *handle,
+                           struct inode *inode,
+                           struct buffer_head *di_bh,
+                           struct ocfs2_security_xattr_info *si,
+                           struct ocfs2_alloc_context *xattr_ac,
+                           struct ocfs2_alloc_context *data_ac)
+{
+       return ocfs2_xattr_set_handle(handle, inode, di_bh,
+                                    OCFS2_XATTR_INDEX_SECURITY,
+                                    si->name, si->value, si->value_len, 0,
+                                    xattr_ac, data_ac);
+}
+
+struct xattr_handler ocfs2_xattr_security_handler = {
+       .prefix = XATTR_SECURITY_PREFIX,
+       .list   = ocfs2_xattr_security_list,
+       .get    = ocfs2_xattr_security_get,
+       .set    = ocfs2_xattr_security_set,
+};
+
 /*
  * 'trusted' attributes support
  */
index 1d8314c7656d78e1dfa4b091821c80dd4b460996..5a1ebc789f7eff51d8e364217171c3b0188983a8 100644 (file)
@@ -30,13 +30,58 @@ enum ocfs2_xattr_type {
        OCFS2_XATTR_MAX
 };
 
+struct ocfs2_security_xattr_info {
+       int enable;
+       char *name;
+       void *value;
+       size_t value_len;
+};
+
 extern struct xattr_handler ocfs2_xattr_user_handler;
 extern struct xattr_handler ocfs2_xattr_trusted_handler;
+extern struct xattr_handler ocfs2_xattr_security_handler;
+#ifdef CONFIG_OCFS2_FS_POSIX_ACL
+extern struct xattr_handler ocfs2_xattr_acl_access_handler;
+extern struct xattr_handler ocfs2_xattr_acl_default_handler;
+#endif
 extern struct xattr_handler *ocfs2_xattr_handlers[];
 
 ssize_t ocfs2_listxattr(struct dentry *, char *, size_t);
+int ocfs2_xattr_get_nolock(struct inode *, struct buffer_head *, int,
+                          const char *, void *, size_t);
 int ocfs2_xattr_set(struct inode *, int, const char *, const void *,
                    size_t, int);
+int ocfs2_xattr_set_handle(handle_t *, struct inode *, struct buffer_head *,
+                          int, const char *, const void *, size_t, int,
+                          struct ocfs2_alloc_context *,
+                          struct ocfs2_alloc_context *);
 int ocfs2_xattr_remove(struct inode *, struct buffer_head *);
+int ocfs2_init_security_get(struct inode *, struct inode *,
+                           struct ocfs2_security_xattr_info *);
+int ocfs2_init_security_set(handle_t *, struct inode *,
+                           struct buffer_head *,
+                           struct ocfs2_security_xattr_info *,
+                           struct ocfs2_alloc_context *,
+                           struct ocfs2_alloc_context *);
+int ocfs2_calc_security_init(struct inode *,
+                            struct ocfs2_security_xattr_info *,
+                            int *, int *, struct ocfs2_alloc_context **);
+int ocfs2_calc_xattr_init(struct inode *, struct buffer_head *,
+                         int, struct ocfs2_security_xattr_info *,
+                         int *, int *, struct ocfs2_alloc_context **);
+
+/*
+ * xattrs can live inside an inode, as part of an external xattr block,
+ * or inside an xattr bucket, which is the leaf of a tree rooted in an
+ * xattr block.  Some of the xattr calls, especially the value setting
+ * functions, want to treat each of these locations as equal.  Let's wrap
+ * them in a structure that we can pass around instead of raw buffer_heads.
+ */
+struct ocfs2_xattr_value_buf {
+       struct buffer_head              *vb_bh;
+       ocfs2_journal_access_func       vb_access;
+       struct ocfs2_xattr_value_root   *vb_xv;
+};
+
 
 #endif /* OCFS2_XATTR_H */
index 6afe57c84f849f33560981ed87f9d5a3b2c96afd..633e9dc972bbc63edb052e89cd924aad8e25e8c3 100644 (file)
@@ -39,7 +39,6 @@ struct inode *omfs_new_inode(struct inode *dir, int mode)
        inode->i_mode = mode;
        inode->i_uid = current_fsuid();
        inode->i_gid = current_fsgid();
-       inode->i_blocks = 0;
        inode->i_mapping->a_ops = &omfs_aops;
 
        inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
index 1cd7d40e99915df06a996f4b738401f663544442..d882fd2351d625fef025292c07403bbf89da57d3 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -412,7 +412,7 @@ asmlinkage long sys_fallocate(int fd, int mode, loff_t offset, loff_t len)
        if (((offset + len) > inode->i_sb->s_maxbytes) || ((offset + len) < 0))
                goto out_fput;
 
-       if (inode->i_op && inode->i_op->fallocate)
+       if (inode->i_op->fallocate)
                ret = inode->i_op->fallocate(inode, mode, offset, len);
        else
                ret = -EOPNOTSUPP;
index d41bdc784de4e920c2966fe0d18d27228df95aed..ffcd04f0012c6aa67dcf2fa5990d4d162f835f5a 100644 (file)
@@ -256,9 +256,6 @@ found:
                break;
        }
 
-       inode->i_gid = 0;
-       inode->i_uid = 0;
-
        d_add(dentry, inode);
        return NULL;
 }
index aaf797bd57b9f1a29d4fef90bcd2367dbe9cd32b..891697112f6620c9d25f4c080f2654962b45d1b9 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -1016,10 +1016,7 @@ int do_pipe_flags(int *fd, int flags)
                goto err_fdr;
        fdw = error;
 
-       error = audit_fd_pair(fdr, fdw);
-       if (error < 0)
-               goto err_fdw;
-
+       audit_fd_pair(fdr, fdw);
        fd_install(fdr, fr);
        fd_install(fdw, fw);
        fd[0] = fdr;
@@ -1027,8 +1024,6 @@ int do_pipe_flags(int *fd, int flags)
 
        return 0;
 
- err_fdw:
-       put_unused_fd(fdw);
  err_fdr:
        put_unused_fd(fdr);
  err_read_pipe:
index cad92c1ac2b389c17ac84cbc841bf646592542aa..10fd5223d600aec609a2adb1ea8e1693dd923562 100644 (file)
@@ -1426,8 +1426,6 @@ static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_st
        if (!ei->pid)
                goto out_unlock;
 
-       inode->i_uid = 0;
-       inode->i_gid = 0;
        if (task_dumpable(task)) {
                rcu_read_lock();
                cred = __task_cred(task);
@@ -2349,8 +2347,6 @@ static struct dentry *proc_base_instantiate(struct inode *dir,
        if (!ei->pid)
                goto out_iput;
 
-       inode->i_uid = 0;
-       inode->i_gid = 0;
        inode->i_mode = p->mode;
        if (S_ISDIR(inode->i_mode))
                inode->i_nlink = 2;
index 06ed10b7da9ee17e9dae1d63ec2b09435aefa551..94fcfff6863a5976965b8d4253ff3ad1ac45386b 100644 (file)
@@ -31,7 +31,6 @@ static struct inode *proc_sys_make_inode(struct super_block *sb,
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
        inode->i_flags |= S_PRIVATE; /* tell selinux to ignore this inode */
        inode->i_mode = table->mode;
-       inode->i_uid = inode->i_gid = 0;
        if (!table->child) {
                inode->i_mode |= S_IFREG;
                inode->i_op = &proc_sys_inode_operations;
index b7fe44e01618ed8b67dbae7814bc3a5ee8927b26..4a8c94f05f76b29cce8c0b811e09a33a6ea3a2da 100644 (file)
@@ -73,7 +73,7 @@ static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, qid
                case Q_SETQUOTA:
                case Q_GETQUOTA:
                        /* This is just informative test so we are satisfied without a lock */
-                       if (!sb_has_quota_enabled(sb, type))
+                       if (!sb_has_quota_active(sb, type))
                                return -ESRCH;
        }
 
@@ -160,6 +160,9 @@ static void quota_sync_sb(struct super_block *sb, int type)
        int cnt;
 
        sb->s_qcop->quota_sync(sb, type);
+
+       if (sb_dqopt(sb)->flags & DQUOT_QUOTA_SYS_FILE)
+               return;
        /* This is not very clever (and fast) but currently I don't know about
         * any other simple way of getting quota data to disk and we must get
         * them there for userspace to be visible... */
@@ -175,7 +178,7 @@ static void quota_sync_sb(struct super_block *sb, int type)
        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
                if (type != -1 && cnt != type)
                        continue;
-               if (!sb_has_quota_enabled(sb, cnt))
+               if (!sb_has_quota_active(sb, cnt))
                        continue;
                mutex_lock_nested(&sb_dqopt(sb)->files[cnt]->i_mutex, I_MUTEX_QUOTA);
                truncate_inode_pages(&sb_dqopt(sb)->files[cnt]->i_data, 0);
@@ -201,7 +204,7 @@ restart:
                for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
                        if (type != -1 && type != cnt)
                                continue;
-                       if (!sb_has_quota_enabled(sb, cnt))
+                       if (!sb_has_quota_active(sb, cnt))
                                continue;
                        if (!info_dirty(&sb_dqopt(sb)->info[cnt]) &&
                            list_empty(&sb_dqopt(sb)->info[cnt].dqi_dirty_list))
@@ -245,7 +248,7 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, void
                        __u32 fmt;
 
                        down_read(&sb_dqopt(sb)->dqptr_sem);
-                       if (!sb_has_quota_enabled(sb, type)) {
+                       if (!sb_has_quota_active(sb, type)) {
                                up_read(&sb_dqopt(sb)->dqptr_sem);
                                return -ESRCH;
                        }
diff --git a/fs/quota_tree.c b/fs/quota_tree.c
new file mode 100644 (file)
index 0000000..953404c
--- /dev/null
@@ -0,0 +1,645 @@
+/*
+ *     vfsv0 quota IO operations on file
+ */
+
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/mount.h>
+#include <linux/dqblk_v2.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/quotaops.h>
+
+#include <asm/byteorder.h>
+
+#include "quota_tree.h"
+
+MODULE_AUTHOR("Jan Kara");
+MODULE_DESCRIPTION("Quota trie support");
+MODULE_LICENSE("GPL");
+
+#define __QUOTA_QT_PARANOIA
+
+typedef char *dqbuf_t;
+
+static int get_index(struct qtree_mem_dqinfo *info, qid_t id, int depth)
+{
+       unsigned int epb = info->dqi_usable_bs >> 2;
+
+       depth = info->dqi_qtree_depth - depth - 1;
+       while (depth--)
+               id /= epb;
+       return id % epb;
+}
+
+/* Number of entries in one blocks */
+static inline int qtree_dqstr_in_blk(struct qtree_mem_dqinfo *info)
+{
+       return (info->dqi_usable_bs - sizeof(struct qt_disk_dqdbheader))
+              / info->dqi_entry_size;
+}
+
+static dqbuf_t getdqbuf(size_t size)
+{
+       dqbuf_t buf = kmalloc(size, GFP_NOFS);
+       if (!buf)
+               printk(KERN_WARNING "VFS: Not enough memory for quota buffers.\n");
+       return buf;
+}
+
+static inline void freedqbuf(dqbuf_t buf)
+{
+       kfree(buf);
+}
+
+static inline ssize_t read_blk(struct qtree_mem_dqinfo *info, uint blk, dqbuf_t buf)
+{
+       struct super_block *sb = info->dqi_sb;
+
+       memset(buf, 0, info->dqi_usable_bs);
+       return sb->s_op->quota_read(sb, info->dqi_type, (char *)buf,
+              info->dqi_usable_bs, blk << info->dqi_blocksize_bits);
+}
+
+static inline ssize_t write_blk(struct qtree_mem_dqinfo *info, uint blk, dqbuf_t buf)
+{
+       struct super_block *sb = info->dqi_sb;
+
+       return sb->s_op->quota_write(sb, info->dqi_type, (char *)buf,
+              info->dqi_usable_bs, blk << info->dqi_blocksize_bits);
+}
+
+/* Remove empty block from list and return it */
+static int get_free_dqblk(struct qtree_mem_dqinfo *info)
+{
+       dqbuf_t buf = getdqbuf(info->dqi_usable_bs);
+       struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf;
+       int ret, blk;
+
+       if (!buf)
+               return -ENOMEM;
+       if (info->dqi_free_blk) {
+               blk = info->dqi_free_blk;
+               ret = read_blk(info, blk, buf);
+               if (ret < 0)
+                       goto out_buf;
+               info->dqi_free_blk = le32_to_cpu(dh->dqdh_next_free);
+       }
+       else {
+               memset(buf, 0, info->dqi_usable_bs);
+               /* Assure block allocation... */
+               ret = write_blk(info, info->dqi_blocks, buf);
+               if (ret < 0)
+                       goto out_buf;
+               blk = info->dqi_blocks++;
+       }
+       mark_info_dirty(info->dqi_sb, info->dqi_type);
+       ret = blk;
+out_buf:
+       freedqbuf(buf);
+       return ret;
+}
+
+/* Insert empty block to the list */
+static int put_free_dqblk(struct qtree_mem_dqinfo *info, dqbuf_t buf, uint blk)
+{
+       struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf;
+       int err;
+
+       dh->dqdh_next_free = cpu_to_le32(info->dqi_free_blk);
+       dh->dqdh_prev_free = cpu_to_le32(0);
+       dh->dqdh_entries = cpu_to_le16(0);
+       err = write_blk(info, blk, buf);
+       if (err < 0)
+               return err;
+       info->dqi_free_blk = blk;
+       mark_info_dirty(info->dqi_sb, info->dqi_type);
+       return 0;
+}
+
+/* Remove given block from the list of blocks with free entries */
+static int remove_free_dqentry(struct qtree_mem_dqinfo *info, dqbuf_t buf, uint blk)
+{
+       dqbuf_t tmpbuf = getdqbuf(info->dqi_usable_bs);
+       struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf;
+       uint nextblk = le32_to_cpu(dh->dqdh_next_free);
+       uint prevblk = le32_to_cpu(dh->dqdh_prev_free);
+       int err;
+
+       if (!tmpbuf)
+               return -ENOMEM;
+       if (nextblk) {
+               err = read_blk(info, nextblk, tmpbuf);
+               if (err < 0)
+                       goto out_buf;
+               ((struct qt_disk_dqdbheader *)tmpbuf)->dqdh_prev_free =
+                                                       dh->dqdh_prev_free;
+               err = write_blk(info, nextblk, tmpbuf);
+               if (err < 0)
+                       goto out_buf;
+       }
+       if (prevblk) {
+               err = read_blk(info, prevblk, tmpbuf);
+               if (err < 0)
+                       goto out_buf;
+               ((struct qt_disk_dqdbheader *)tmpbuf)->dqdh_next_free =
+                                                       dh->dqdh_next_free;
+               err = write_blk(info, prevblk, tmpbuf);
+               if (err < 0)
+                       goto out_buf;
+       } else {
+               info->dqi_free_entry = nextblk;
+               mark_info_dirty(info->dqi_sb, info->dqi_type);
+       }
+       freedqbuf(tmpbuf);
+       dh->dqdh_next_free = dh->dqdh_prev_free = cpu_to_le32(0);
+       /* No matter whether write succeeds block is out of list */
+       if (write_blk(info, blk, buf) < 0)
+               printk(KERN_ERR "VFS: Can't write block (%u) with free entries.\n", blk);
+       return 0;
+out_buf:
+       freedqbuf(tmpbuf);
+       return err;
+}
+
+/* Insert given block to the beginning of list with free entries */
+static int insert_free_dqentry(struct qtree_mem_dqinfo *info, dqbuf_t buf, uint blk)
+{
+       dqbuf_t tmpbuf = getdqbuf(info->dqi_usable_bs);
+       struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf;
+       int err;
+
+       if (!tmpbuf)
+               return -ENOMEM;
+       dh->dqdh_next_free = cpu_to_le32(info->dqi_free_entry);
+       dh->dqdh_prev_free = cpu_to_le32(0);
+       err = write_blk(info, blk, buf);
+       if (err < 0)
+               goto out_buf;
+       if (info->dqi_free_entry) {
+               err = read_blk(info, info->dqi_free_entry, tmpbuf);
+               if (err < 0)
+                       goto out_buf;
+               ((struct qt_disk_dqdbheader *)tmpbuf)->dqdh_prev_free =
+                                                       cpu_to_le32(blk);
+               err = write_blk(info, info->dqi_free_entry, tmpbuf);
+               if (err < 0)
+                       goto out_buf;
+       }
+       freedqbuf(tmpbuf);
+       info->dqi_free_entry = blk;
+       mark_info_dirty(info->dqi_sb, info->dqi_type);
+       return 0;
+out_buf:
+       freedqbuf(tmpbuf);
+       return err;
+}
+
+/* Is the entry in the block free? */
+int qtree_entry_unused(struct qtree_mem_dqinfo *info, char *disk)
+{
+       int i;
+
+       for (i = 0; i < info->dqi_entry_size; i++)
+               if (disk[i])
+                       return 0;
+       return 1;
+}
+EXPORT_SYMBOL(qtree_entry_unused);
+
+/* Find space for dquot */
+static uint find_free_dqentry(struct qtree_mem_dqinfo *info,
+                             struct dquot *dquot, int *err)
+{
+       uint blk, i;
+       struct qt_disk_dqdbheader *dh;
+       dqbuf_t buf = getdqbuf(info->dqi_usable_bs);
+       char *ddquot;
+
+       *err = 0;
+       if (!buf) {
+               *err = -ENOMEM;
+               return 0;
+       }
+       dh = (struct qt_disk_dqdbheader *)buf;
+       if (info->dqi_free_entry) {
+               blk = info->dqi_free_entry;
+               *err = read_blk(info, blk, buf);
+               if (*err < 0)
+                       goto out_buf;
+       } else {
+               blk = get_free_dqblk(info);
+               if ((int)blk < 0) {
+                       *err = blk;
+                       freedqbuf(buf);
+                       return 0;
+               }
+               memset(buf, 0, info->dqi_usable_bs);
+               /* This is enough as block is already zeroed and entry list is empty... */
+               info->dqi_free_entry = blk;
+               mark_info_dirty(dquot->dq_sb, dquot->dq_type);
+       }
+       /* Block will be full? */
+       if (le16_to_cpu(dh->dqdh_entries) + 1 >= qtree_dqstr_in_blk(info)) {
+               *err = remove_free_dqentry(info, buf, blk);
+               if (*err < 0) {
+                       printk(KERN_ERR "VFS: find_free_dqentry(): Can't "
+                              "remove block (%u) from entry free list.\n",
+                              blk);
+                       goto out_buf;
+               }
+       }
+       le16_add_cpu(&dh->dqdh_entries, 1);
+       /* Find free structure in block */
+       for (i = 0, ddquot = ((char *)buf) + sizeof(struct qt_disk_dqdbheader);
+            i < qtree_dqstr_in_blk(info) && !qtree_entry_unused(info, ddquot);
+            i++, ddquot += info->dqi_entry_size);
+#ifdef __QUOTA_QT_PARANOIA
+       if (i == qtree_dqstr_in_blk(info)) {
+               printk(KERN_ERR "VFS: find_free_dqentry(): Data block full "
+                               "but it shouldn't.\n");
+               *err = -EIO;
+               goto out_buf;
+       }
+#endif
+       *err = write_blk(info, blk, buf);
+       if (*err < 0) {
+               printk(KERN_ERR "VFS: find_free_dqentry(): Can't write quota "
+                               "data block %u.\n", blk);
+               goto out_buf;
+       }
+       dquot->dq_off = (blk << info->dqi_blocksize_bits) +
+                       sizeof(struct qt_disk_dqdbheader) +
+                       i * info->dqi_entry_size;
+       freedqbuf(buf);
+       return blk;
+out_buf:
+       freedqbuf(buf);
+       return 0;
+}
+
+/* Insert reference to structure into the trie */
+static int do_insert_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot,
+                         uint *treeblk, int depth)
+{
+       dqbuf_t buf = getdqbuf(info->dqi_usable_bs);
+       int ret = 0, newson = 0, newact = 0;
+       __le32 *ref;
+       uint newblk;
+
+       if (!buf)
+               return -ENOMEM;
+       if (!*treeblk) {
+               ret = get_free_dqblk(info);
+               if (ret < 0)
+                       goto out_buf;
+               *treeblk = ret;
+               memset(buf, 0, info->dqi_usable_bs);
+               newact = 1;
+       } else {
+               ret = read_blk(info, *treeblk, buf);
+               if (ret < 0) {
+                       printk(KERN_ERR "VFS: Can't read tree quota block "
+                                       "%u.\n", *treeblk);
+                       goto out_buf;
+               }
+       }
+       ref = (__le32 *)buf;
+       newblk = le32_to_cpu(ref[get_index(info, dquot->dq_id, depth)]);
+       if (!newblk)
+               newson = 1;
+       if (depth == info->dqi_qtree_depth - 1) {
+#ifdef __QUOTA_QT_PARANOIA
+               if (newblk) {
+                       printk(KERN_ERR "VFS: Inserting already present quota "
+                                       "entry (block %u).\n",
+                              le32_to_cpu(ref[get_index(info,
+                                               dquot->dq_id, depth)]));
+                       ret = -EIO;
+                       goto out_buf;
+               }
+#endif
+               newblk = find_free_dqentry(info, dquot, &ret);
+       } else {
+               ret = do_insert_tree(info, dquot, &newblk, depth+1);
+       }
+       if (newson && ret >= 0) {
+               ref[get_index(info, dquot->dq_id, depth)] =
+                                                       cpu_to_le32(newblk);
+               ret = write_blk(info, *treeblk, buf);
+       } else if (newact && ret < 0) {
+               put_free_dqblk(info, buf, *treeblk);
+       }
+out_buf:
+       freedqbuf(buf);
+       return ret;
+}
+
+/* Wrapper for inserting quota structure into tree */
+static inline int dq_insert_tree(struct qtree_mem_dqinfo *info,
+                                struct dquot *dquot)
+{
+       int tmp = QT_TREEOFF;
+       return do_insert_tree(info, dquot, &tmp, 0);
+}
+
+/*
+ *     We don't have to be afraid of deadlocks as we never have quotas on quota files...
+ */
+int qtree_write_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot)
+{
+       int type = dquot->dq_type;
+       struct super_block *sb = dquot->dq_sb;
+       ssize_t ret;
+       dqbuf_t ddquot = getdqbuf(info->dqi_entry_size);
+
+       if (!ddquot)
+               return -ENOMEM;
+
+       /* dq_off is guarded by dqio_mutex */
+       if (!dquot->dq_off) {
+               ret = dq_insert_tree(info, dquot);
+               if (ret < 0) {
+                       printk(KERN_ERR "VFS: Error %zd occurred while "
+                                       "creating quota.\n", ret);
+                       freedqbuf(ddquot);
+                       return ret;
+               }
+       }
+       spin_lock(&dq_data_lock);
+       info->dqi_ops->mem2disk_dqblk(ddquot, dquot);
+       spin_unlock(&dq_data_lock);
+       ret = sb->s_op->quota_write(sb, type, (char *)ddquot,
+                                       info->dqi_entry_size, dquot->dq_off);
+       if (ret != info->dqi_entry_size) {
+               printk(KERN_WARNING "VFS: dquota write failed on dev %s\n",
+                      sb->s_id);
+               if (ret >= 0)
+                       ret = -ENOSPC;
+       } else {
+               ret = 0;
+       }
+       dqstats.writes++;
+       freedqbuf(ddquot);
+
+       return ret;
+}
+EXPORT_SYMBOL(qtree_write_dquot);
+
+/* Free dquot entry in data block */
+static int free_dqentry(struct qtree_mem_dqinfo *info, struct dquot *dquot,
+                       uint blk)
+{
+       struct qt_disk_dqdbheader *dh;
+       dqbuf_t buf = getdqbuf(info->dqi_usable_bs);
+       int ret = 0;
+
+       if (!buf)
+               return -ENOMEM;
+       if (dquot->dq_off >> info->dqi_blocksize_bits != blk) {
+               printk(KERN_ERR "VFS: Quota structure has offset to other "
+                 "block (%u) than it should (%u).\n", blk,
+                 (uint)(dquot->dq_off >> info->dqi_blocksize_bits));
+               goto out_buf;
+       }
+       ret = read_blk(info, blk, buf);
+       if (ret < 0) {
+               printk(KERN_ERR "VFS: Can't read quota data block %u\n", blk);
+               goto out_buf;
+       }
+       dh = (struct qt_disk_dqdbheader *)buf;
+       le16_add_cpu(&dh->dqdh_entries, -1);
+       if (!le16_to_cpu(dh->dqdh_entries)) {   /* Block got free? */
+               ret = remove_free_dqentry(info, buf, blk);
+               if (ret >= 0)
+                       ret = put_free_dqblk(info, buf, blk);
+               if (ret < 0) {
+                       printk(KERN_ERR "VFS: Can't move quota data block (%u) "
+                         "to free list.\n", blk);
+                       goto out_buf;
+               }
+       } else {
+               memset(buf +
+                      (dquot->dq_off & ((1 << info->dqi_blocksize_bits) - 1)),
+                      0, info->dqi_entry_size);
+               if (le16_to_cpu(dh->dqdh_entries) ==
+                   qtree_dqstr_in_blk(info) - 1) {
+                       /* Insert will write block itself */
+                       ret = insert_free_dqentry(info, buf, blk);
+                       if (ret < 0) {
+                               printk(KERN_ERR "VFS: Can't insert quota data "
+                                      "block (%u) to free entry list.\n", blk);
+                               goto out_buf;
+                       }
+               } else {
+                       ret = write_blk(info, blk, buf);
+                       if (ret < 0) {
+                               printk(KERN_ERR "VFS: Can't write quota data "
+                                 "block %u\n", blk);
+                               goto out_buf;
+                       }
+               }
+       }
+       dquot->dq_off = 0;      /* Quota is now unattached */
+out_buf:
+       freedqbuf(buf);
+       return ret;
+}
+
+/* Remove reference to dquot from tree */
+static int remove_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot,
+                      uint *blk, int depth)
+{
+       dqbuf_t buf = getdqbuf(info->dqi_usable_bs);
+       int ret = 0;
+       uint newblk;
+       __le32 *ref = (__le32 *)buf;
+
+       if (!buf)
+               return -ENOMEM;
+       ret = read_blk(info, *blk, buf);
+       if (ret < 0) {
+               printk(KERN_ERR "VFS: Can't read quota data block %u\n", *blk);
+               goto out_buf;
+       }
+       newblk = le32_to_cpu(ref[get_index(info, dquot->dq_id, depth)]);
+       if (depth == info->dqi_qtree_depth - 1) {
+               ret = free_dqentry(info, dquot, newblk);
+               newblk = 0;
+       } else {
+               ret = remove_tree(info, dquot, &newblk, depth+1);
+       }
+       if (ret >= 0 && !newblk) {
+               int i;
+               ref[get_index(info, dquot->dq_id, depth)] = cpu_to_le32(0);
+               /* Block got empty? */
+               for (i = 0;
+                    i < (info->dqi_usable_bs >> 2) && !ref[i];
+                    i++);
+               /* Don't put the root block into the free block list */
+               if (i == (info->dqi_usable_bs >> 2)
+                   && *blk != QT_TREEOFF) {
+                       put_free_dqblk(info, buf, *blk);
+                       *blk = 0;
+               } else {
+                       ret = write_blk(info, *blk, buf);
+                       if (ret < 0)
+                               printk(KERN_ERR "VFS: Can't write quota tree "
+                                 "block %u.\n", *blk);
+               }
+       }
+out_buf:
+       freedqbuf(buf);
+       return ret;
+}
+
+/* Delete dquot from tree */
+int qtree_delete_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot)
+{
+       uint tmp = QT_TREEOFF;
+
+       if (!dquot->dq_off)     /* Even not allocated? */
+               return 0;
+       return remove_tree(info, dquot, &tmp, 0);
+}
+EXPORT_SYMBOL(qtree_delete_dquot);
+
+/* Find entry in block */
+static loff_t find_block_dqentry(struct qtree_mem_dqinfo *info,
+                                struct dquot *dquot, uint blk)
+{
+       dqbuf_t buf = getdqbuf(info->dqi_usable_bs);
+       loff_t ret = 0;
+       int i;
+       char *ddquot;
+
+       if (!buf)
+               return -ENOMEM;
+       ret = read_blk(info, blk, buf);
+       if (ret < 0) {
+               printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
+               goto out_buf;
+       }
+       for (i = 0, ddquot = ((char *)buf) + sizeof(struct qt_disk_dqdbheader);
+            i < qtree_dqstr_in_blk(info) && !info->dqi_ops->is_id(ddquot, dquot);
+            i++, ddquot += info->dqi_entry_size);
+       if (i == qtree_dqstr_in_blk(info)) {
+               printk(KERN_ERR "VFS: Quota for id %u referenced "
+                 "but not present.\n", dquot->dq_id);
+               ret = -EIO;
+               goto out_buf;
+       } else {
+               ret = (blk << info->dqi_blocksize_bits) + sizeof(struct
+                 qt_disk_dqdbheader) + i * info->dqi_entry_size;
+       }
+out_buf:
+       freedqbuf(buf);
+       return ret;
+}
+
+/* Find entry for given id in the tree */
+static loff_t find_tree_dqentry(struct qtree_mem_dqinfo *info,
+                               struct dquot *dquot, uint blk, int depth)
+{
+       dqbuf_t buf = getdqbuf(info->dqi_usable_bs);
+       loff_t ret = 0;
+       __le32 *ref = (__le32 *)buf;
+
+       if (!buf)
+               return -ENOMEM;
+       ret = read_blk(info, blk, buf);
+       if (ret < 0) {
+               printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
+               goto out_buf;
+       }
+       ret = 0;
+       blk = le32_to_cpu(ref[get_index(info, dquot->dq_id, depth)]);
+       if (!blk)       /* No reference? */
+               goto out_buf;
+       if (depth < info->dqi_qtree_depth - 1)
+               ret = find_tree_dqentry(info, dquot, blk, depth+1);
+       else
+               ret = find_block_dqentry(info, dquot, blk);
+out_buf:
+       freedqbuf(buf);
+       return ret;
+}
+
+/* Find entry for given id in the tree - wrapper function */
+static inline loff_t find_dqentry(struct qtree_mem_dqinfo *info,
+                                 struct dquot *dquot)
+{
+       return find_tree_dqentry(info, dquot, QT_TREEOFF, 0);
+}
+
+int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot)
+{
+       int type = dquot->dq_type;
+       struct super_block *sb = dquot->dq_sb;
+       loff_t offset;
+       dqbuf_t ddquot;
+       int ret = 0;
+
+#ifdef __QUOTA_QT_PARANOIA
+       /* Invalidated quota? */
+       if (!sb_dqopt(dquot->dq_sb)->files[type]) {
+               printk(KERN_ERR "VFS: Quota invalidated while reading!\n");
+               return -EIO;
+       }
+#endif
+       /* Do we know offset of the dquot entry in the quota file? */
+       if (!dquot->dq_off) {
+               offset = find_dqentry(info, dquot);
+               if (offset <= 0) {      /* Entry not present? */
+                       if (offset < 0)
+                               printk(KERN_ERR "VFS: Can't read quota "
+                                 "structure for id %u.\n", dquot->dq_id);
+                       dquot->dq_off = 0;
+                       set_bit(DQ_FAKE_B, &dquot->dq_flags);
+                       memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk));
+                       ret = offset;
+                       goto out;
+               }
+               dquot->dq_off = offset;
+       }
+       ddquot = getdqbuf(info->dqi_entry_size);
+       if (!ddquot)
+               return -ENOMEM;
+       ret = sb->s_op->quota_read(sb, type, (char *)ddquot,
+                                  info->dqi_entry_size, dquot->dq_off);
+       if (ret != info->dqi_entry_size) {
+               if (ret >= 0)
+                       ret = -EIO;
+               printk(KERN_ERR "VFS: Error while reading quota "
+                               "structure for id %u.\n", dquot->dq_id);
+               set_bit(DQ_FAKE_B, &dquot->dq_flags);
+               memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk));
+               freedqbuf(ddquot);
+               goto out;
+       }
+       spin_lock(&dq_data_lock);
+       info->dqi_ops->disk2mem_dqblk(dquot, ddquot);
+       if (!dquot->dq_dqb.dqb_bhardlimit &&
+           !dquot->dq_dqb.dqb_bsoftlimit &&
+           !dquot->dq_dqb.dqb_ihardlimit &&
+           !dquot->dq_dqb.dqb_isoftlimit)
+               set_bit(DQ_FAKE_B, &dquot->dq_flags);
+       spin_unlock(&dq_data_lock);
+       freedqbuf(ddquot);
+out:
+       dqstats.reads++;
+       return ret;
+}
+EXPORT_SYMBOL(qtree_read_dquot);
+
+/* Check whether dquot should not be deleted. We know we are
+ * the only one operating on dquot (thanks to dq_lock) */
+int qtree_release_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot)
+{
+       if (test_bit(DQ_FAKE_B, &dquot->dq_flags) && !(dquot->dq_dqb.dqb_curinodes | dquot->dq_dqb.dqb_curspace))
+               return qtree_delete_dquot(info, dquot);
+       return 0;
+}
+EXPORT_SYMBOL(qtree_release_dquot);
diff --git a/fs/quota_tree.h b/fs/quota_tree.h
new file mode 100644 (file)
index 0000000..a1ab8db
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ *     Definitions of structures for vfsv0 quota format
+ */
+
+#ifndef _LINUX_QUOTA_TREE_H
+#define _LINUX_QUOTA_TREE_H
+
+#include <linux/types.h>
+#include <linux/quota.h>
+
+/*
+ *  Structure of header of block with quota structures. It is padded to 16 bytes so
+ *  there will be space for exactly 21 quota-entries in a block
+ */
+struct qt_disk_dqdbheader {
+       __le32 dqdh_next_free;  /* Number of next block with free entry */
+       __le32 dqdh_prev_free;  /* Number of previous block with free entry */
+       __le16 dqdh_entries;    /* Number of valid entries in block */
+       __le16 dqdh_pad1;
+       __le32 dqdh_pad2;
+};
+
+#define QT_TREEOFF     1               /* Offset of tree in file in blocks */
+
+#endif /* _LINUX_QUOTAIO_TREE_H */
index 5ae15b13eeb00217b529b336349736604377c472..b4af1c69ad16fb1522d14a06f5810a5b75c350d4 100644 (file)
@@ -3,25 +3,39 @@
 #include <linux/quota.h>
 #include <linux/quotaops.h>
 #include <linux/dqblk_v1.h>
-#include <linux/quotaio_v1.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
 
 #include <asm/byteorder.h>
 
+#include "quotaio_v1.h"
+
 MODULE_AUTHOR("Jan Kara");
 MODULE_DESCRIPTION("Old quota format support");
 MODULE_LICENSE("GPL");
 
+#define QUOTABLOCK_BITS 10
+#define QUOTABLOCK_SIZE (1 << QUOTABLOCK_BITS)
+
+static inline qsize_t v1_stoqb(qsize_t space)
+{
+       return (space + QUOTABLOCK_SIZE - 1) >> QUOTABLOCK_BITS;
+}
+
+static inline qsize_t v1_qbtos(qsize_t blocks)
+{
+       return blocks << QUOTABLOCK_BITS;
+}
+
 static void v1_disk2mem_dqblk(struct mem_dqblk *m, struct v1_disk_dqblk *d)
 {
        m->dqb_ihardlimit = d->dqb_ihardlimit;
        m->dqb_isoftlimit = d->dqb_isoftlimit;
        m->dqb_curinodes = d->dqb_curinodes;
-       m->dqb_bhardlimit = d->dqb_bhardlimit;
-       m->dqb_bsoftlimit = d->dqb_bsoftlimit;
-       m->dqb_curspace = ((qsize_t)d->dqb_curblocks) << QUOTABLOCK_BITS;
+       m->dqb_bhardlimit = v1_qbtos(d->dqb_bhardlimit);
+       m->dqb_bsoftlimit = v1_qbtos(d->dqb_bsoftlimit);
+       m->dqb_curspace = v1_qbtos(d->dqb_curblocks);
        m->dqb_itime = d->dqb_itime;
        m->dqb_btime = d->dqb_btime;
 }
@@ -31,9 +45,9 @@ static void v1_mem2disk_dqblk(struct v1_disk_dqblk *d, struct mem_dqblk *m)
        d->dqb_ihardlimit = m->dqb_ihardlimit;
        d->dqb_isoftlimit = m->dqb_isoftlimit;
        d->dqb_curinodes = m->dqb_curinodes;
-       d->dqb_bhardlimit = m->dqb_bhardlimit;
-       d->dqb_bsoftlimit = m->dqb_bsoftlimit;
-       d->dqb_curblocks = toqb(m->dqb_curspace);
+       d->dqb_bhardlimit = v1_stoqb(m->dqb_bhardlimit);
+       d->dqb_bsoftlimit = v1_stoqb(m->dqb_bsoftlimit);
+       d->dqb_curblocks = v1_stoqb(m->dqb_curspace);
        d->dqb_itime = m->dqb_itime;
        d->dqb_btime = m->dqb_btime;
 }
index b53827dc02d9081c50e0d0ed0acb971c2ad931b8..b618b563635c6322e63be9fa00c70d0d0ad7f5b6 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/fs.h>
 #include <linux/mount.h>
 #include <linux/dqblk_v2.h>
-#include <linux/quotaio_v2.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
 
 #include <asm/byteorder.h>
 
+#include "quota_tree.h"
+#include "quotaio_v2.h"
+
 MODULE_AUTHOR("Jan Kara");
 MODULE_DESCRIPTION("Quota format v2 support");
 MODULE_LICENSE("GPL");
 
 #define __QUOTA_V2_PARANOIA
 
-typedef char *dqbuf_t;
+static void v2_mem2diskdqb(void *dp, struct dquot *dquot);
+static void v2_disk2memdqb(struct dquot *dquot, void *dp);
+static int v2_is_id(void *dp, struct dquot *dquot);
+
+static struct qtree_fmt_operations v2_qtree_ops = {
+       .mem2disk_dqblk = v2_mem2diskdqb,
+       .disk2mem_dqblk = v2_disk2memdqb,
+       .is_id = v2_is_id,
+};
+
+#define QUOTABLOCK_BITS 10
+#define QUOTABLOCK_SIZE (1 << QUOTABLOCK_BITS)
 
-#define GETIDINDEX(id, depth) (((id) >> ((V2_DQTREEDEPTH-(depth)-1)*8)) & 0xff)
-#define GETENTRIES(buf) ((struct v2_disk_dqblk *)(((char *)buf)+sizeof(struct v2_disk_dqdbheader)))
+static inline qsize_t v2_stoqb(qsize_t space)
+{
+       return (space + QUOTABLOCK_SIZE - 1) >> QUOTABLOCK_BITS;
+}
+
+static inline qsize_t v2_qbtos(qsize_t blocks)
+{
+       return blocks << QUOTABLOCK_BITS;
+}
 
 /* Check whether given file is really vfsv0 quotafile */
 static int v2_check_quota_file(struct super_block *sb, int type)
@@ -50,7 +70,8 @@ static int v2_check_quota_file(struct super_block *sb, int type)
 static int v2_read_file_info(struct super_block *sb, int type)
 {
        struct v2_disk_dqinfo dinfo;
-       struct mem_dqinfo *info = sb_dqopt(sb)->info+type;
+       struct mem_dqinfo *info = sb_dqinfo(sb, type);
+       struct qtree_mem_dqinfo *qinfo;
        ssize_t size;
 
        size = sb->s_op->quota_read(sb, type, (char *)&dinfo,
@@ -60,15 +81,29 @@ static int v2_read_file_info(struct super_block *sb, int type)
                        sb->s_id);
                return -1;
        }
+       info->dqi_priv = kmalloc(sizeof(struct qtree_mem_dqinfo), GFP_NOFS);
+       if (!info->dqi_priv) {
+               printk(KERN_WARNING
+                      "Not enough memory for quota information structure.\n");
+               return -1;
+       }
+       qinfo = info->dqi_priv;
        /* limits are stored as unsigned 32-bit data */
        info->dqi_maxblimit = 0xffffffff;
        info->dqi_maxilimit = 0xffffffff;
        info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
        info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);
        info->dqi_flags = le32_to_cpu(dinfo.dqi_flags);
-       info->u.v2_i.dqi_blocks = le32_to_cpu(dinfo.dqi_blocks);
-       info->u.v2_i.dqi_free_blk = le32_to_cpu(dinfo.dqi_free_blk);
-       info->u.v2_i.dqi_free_entry = le32_to_cpu(dinfo.dqi_free_entry);
+       qinfo->dqi_sb = sb;
+       qinfo->dqi_type = type;
+       qinfo->dqi_blocks = le32_to_cpu(dinfo.dqi_blocks);
+       qinfo->dqi_free_blk = le32_to_cpu(dinfo.dqi_free_blk);
+       qinfo->dqi_free_entry = le32_to_cpu(dinfo.dqi_free_entry);
+       qinfo->dqi_blocksize_bits = V2_DQBLKSIZE_BITS;
+       qinfo->dqi_usable_bs = 1 << V2_DQBLKSIZE_BITS;
+       qinfo->dqi_qtree_depth = qtree_depth(qinfo);
+       qinfo->dqi_entry_size = sizeof(struct v2_disk_dqblk);
+       qinfo->dqi_ops = &v2_qtree_ops;
        return 0;
 }
 
@@ -76,7 +111,8 @@ static int v2_read_file_info(struct super_block *sb, int type)
 static int v2_write_file_info(struct super_block *sb, int type)
 {
        struct v2_disk_dqinfo dinfo;
-       struct mem_dqinfo *info = sb_dqopt(sb)->info+type;
+       struct mem_dqinfo *info = sb_dqinfo(sb, type);
+       struct qtree_mem_dqinfo *qinfo = info->dqi_priv;
        ssize_t size;
 
        spin_lock(&dq_data_lock);
@@ -85,9 +121,9 @@ static int v2_write_file_info(struct super_block *sb, int type)
        dinfo.dqi_igrace = cpu_to_le32(info->dqi_igrace);
        dinfo.dqi_flags = cpu_to_le32(info->dqi_flags & DQF_MASK);
        spin_unlock(&dq_data_lock);
-       dinfo.dqi_blocks = cpu_to_le32(info->u.v2_i.dqi_blocks);
-       dinfo.dqi_free_blk = cpu_to_le32(info->u.v2_i.dqi_free_blk);
-       dinfo.dqi_free_entry = cpu_to_le32(info->u.v2_i.dqi_free_entry);
+       dinfo.dqi_blocks = cpu_to_le32(qinfo->dqi_blocks);
+       dinfo.dqi_free_blk = cpu_to_le32(qinfo->dqi_free_blk);
+       dinfo.dqi_free_entry = cpu_to_le32(qinfo->dqi_free_entry);
        size = sb->s_op->quota_write(sb, type, (char *)&dinfo,
               sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF);
        if (size != sizeof(struct v2_disk_dqinfo)) {
@@ -98,574 +134,75 @@ static int v2_write_file_info(struct super_block *sb, int type)
        return 0;
 }
 
-static void disk2memdqb(struct mem_dqblk *m, struct v2_disk_dqblk *d)
+static void v2_disk2memdqb(struct dquot *dquot, void *dp)
 {
+       struct v2_disk_dqblk *d = dp, empty;
+       struct mem_dqblk *m = &dquot->dq_dqb;
+
        m->dqb_ihardlimit = le32_to_cpu(d->dqb_ihardlimit);
        m->dqb_isoftlimit = le32_to_cpu(d->dqb_isoftlimit);
        m->dqb_curinodes = le32_to_cpu(d->dqb_curinodes);
        m->dqb_itime = le64_to_cpu(d->dqb_itime);
-       m->dqb_bhardlimit = le32_to_cpu(d->dqb_bhardlimit);
-       m->dqb_bsoftlimit = le32_to_cpu(d->dqb_bsoftlimit);
+       m->dqb_bhardlimit = v2_qbtos(le32_to_cpu(d->dqb_bhardlimit));
+       m->dqb_bsoftlimit = v2_qbtos(le32_to_cpu(d->dqb_bsoftlimit));
        m->dqb_curspace = le64_to_cpu(d->dqb_curspace);
        m->dqb_btime = le64_to_cpu(d->dqb_btime);
+       /* We need to escape back all-zero structure */
+       memset(&empty, 0, sizeof(struct v2_disk_dqblk));
+       empty.dqb_itime = cpu_to_le64(1);
+       if (!memcmp(&empty, dp, sizeof(struct v2_disk_dqblk)))
+               m->dqb_itime = 0;
 }
 
-static void mem2diskdqb(struct v2_disk_dqblk *d, struct mem_dqblk *m, qid_t id)
+static void v2_mem2diskdqb(void *dp, struct dquot *dquot)
 {
+       struct v2_disk_dqblk *d = dp;
+       struct mem_dqblk *m = &dquot->dq_dqb;
+       struct qtree_mem_dqinfo *info =
+                       sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
+
        d->dqb_ihardlimit = cpu_to_le32(m->dqb_ihardlimit);
        d->dqb_isoftlimit = cpu_to_le32(m->dqb_isoftlimit);
        d->dqb_curinodes = cpu_to_le32(m->dqb_curinodes);
        d->dqb_itime = cpu_to_le64(m->dqb_itime);
-       d->dqb_bhardlimit = cpu_to_le32(m->dqb_bhardlimit);
-       d->dqb_bsoftlimit = cpu_to_le32(m->dqb_bsoftlimit);
+       d->dqb_bhardlimit = cpu_to_le32(v2_stoqb(m->dqb_bhardlimit));
+       d->dqb_bsoftlimit = cpu_to_le32(v2_stoqb(m->dqb_bsoftlimit));
        d->dqb_curspace = cpu_to_le64(m->dqb_curspace);
        d->dqb_btime = cpu_to_le64(m->dqb_btime);
-       d->dqb_id = cpu_to_le32(id);
-}
-
-static dqbuf_t getdqbuf(void)
-{
-       dqbuf_t buf = kmalloc(V2_DQBLKSIZE, GFP_NOFS);
-       if (!buf)
-               printk(KERN_WARNING "VFS: Not enough memory for quota buffers.\n");
-       return buf;
-}
-
-static inline void freedqbuf(dqbuf_t buf)
-{
-       kfree(buf);
-}
-
-static inline ssize_t read_blk(struct super_block *sb, int type, uint blk, dqbuf_t buf)
-{
-       memset(buf, 0, V2_DQBLKSIZE);
-       return sb->s_op->quota_read(sb, type, (char *)buf,
-              V2_DQBLKSIZE, blk << V2_DQBLKSIZE_BITS);
-}
-
-static inline ssize_t write_blk(struct super_block *sb, int type, uint blk, dqbuf_t buf)
-{
-       return sb->s_op->quota_write(sb, type, (char *)buf,
-              V2_DQBLKSIZE, blk << V2_DQBLKSIZE_BITS);
-}
-
-/* Remove empty block from list and return it */
-static int get_free_dqblk(struct super_block *sb, int type)
-{
-       dqbuf_t buf = getdqbuf();
-       struct mem_dqinfo *info = sb_dqinfo(sb, type);
-       struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
-       int ret, blk;
-
-       if (!buf)
-               return -ENOMEM;
-       if (info->u.v2_i.dqi_free_blk) {
-               blk = info->u.v2_i.dqi_free_blk;
-               if ((ret = read_blk(sb, type, blk, buf)) < 0)
-                       goto out_buf;
-               info->u.v2_i.dqi_free_blk = le32_to_cpu(dh->dqdh_next_free);
-       }
-       else {
-               memset(buf, 0, V2_DQBLKSIZE);
-               /* Assure block allocation... */
-               if ((ret = write_blk(sb, type, info->u.v2_i.dqi_blocks, buf)) < 0)
-                       goto out_buf;
-               blk = info->u.v2_i.dqi_blocks++;
-       }
-       mark_info_dirty(sb, type);
-       ret = blk;
-out_buf:
-       freedqbuf(buf);
-       return ret;
-}
-
-/* Insert empty block to the list */
-static int put_free_dqblk(struct super_block *sb, int type, dqbuf_t buf, uint blk)
-{
-       struct mem_dqinfo *info = sb_dqinfo(sb, type);
-       struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
-       int err;
-
-       dh->dqdh_next_free = cpu_to_le32(info->u.v2_i.dqi_free_blk);
-       dh->dqdh_prev_free = cpu_to_le32(0);
-       dh->dqdh_entries = cpu_to_le16(0);
-       info->u.v2_i.dqi_free_blk = blk;
-       mark_info_dirty(sb, type);
-       /* Some strange block. We had better leave it... */
-       if ((err = write_blk(sb, type, blk, buf)) < 0)
-               return err;
-       return 0;
+       d->dqb_id = cpu_to_le32(dquot->dq_id);
+       if (qtree_entry_unused(info, dp))
+               d->dqb_itime = cpu_to_le64(1);
 }
 
-/* Remove given block from the list of blocks with free entries */
-static int remove_free_dqentry(struct super_block *sb, int type, dqbuf_t buf, uint blk)
+static int v2_is_id(void *dp, struct dquot *dquot)
 {
-       dqbuf_t tmpbuf = getdqbuf();
-       struct mem_dqinfo *info = sb_dqinfo(sb, type);
-       struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
-       uint nextblk = le32_to_cpu(dh->dqdh_next_free), prevblk = le32_to_cpu(dh->dqdh_prev_free);
-       int err;
+       struct v2_disk_dqblk *d = dp;
+       struct qtree_mem_dqinfo *info =
+                       sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
 
-       if (!tmpbuf)
-               return -ENOMEM;
-       if (nextblk) {
-               if ((err = read_blk(sb, type, nextblk, tmpbuf)) < 0)
-                       goto out_buf;
-               ((struct v2_disk_dqdbheader *)tmpbuf)->dqdh_prev_free = dh->dqdh_prev_free;
-               if ((err = write_blk(sb, type, nextblk, tmpbuf)) < 0)
-                       goto out_buf;
-       }
-       if (prevblk) {
-               if ((err = read_blk(sb, type, prevblk, tmpbuf)) < 0)
-                       goto out_buf;
-               ((struct v2_disk_dqdbheader *)tmpbuf)->dqdh_next_free = dh->dqdh_next_free;
-               if ((err = write_blk(sb, type, prevblk, tmpbuf)) < 0)
-                       goto out_buf;
-       }
-       else {
-               info->u.v2_i.dqi_free_entry = nextblk;
-               mark_info_dirty(sb, type);
-       }
-       freedqbuf(tmpbuf);
-       dh->dqdh_next_free = dh->dqdh_prev_free = cpu_to_le32(0);
-       /* No matter whether write succeeds block is out of list */
-       if (write_blk(sb, type, blk, buf) < 0)
-               printk(KERN_ERR "VFS: Can't write block (%u) with free entries.\n", blk);
-       return 0;
-out_buf:
-       freedqbuf(tmpbuf);
-       return err;
-}
-
-/* Insert given block to the beginning of list with free entries */
-static int insert_free_dqentry(struct super_block *sb, int type, dqbuf_t buf, uint blk)
-{
-       dqbuf_t tmpbuf = getdqbuf();
-       struct mem_dqinfo *info = sb_dqinfo(sb, type);
-       struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
-       int err;
-
-       if (!tmpbuf)
-               return -ENOMEM;
-       dh->dqdh_next_free = cpu_to_le32(info->u.v2_i.dqi_free_entry);
-       dh->dqdh_prev_free = cpu_to_le32(0);
-       if ((err = write_blk(sb, type, blk, buf)) < 0)
-               goto out_buf;
-       if (info->u.v2_i.dqi_free_entry) {
-               if ((err = read_blk(sb, type, info->u.v2_i.dqi_free_entry, tmpbuf)) < 0)
-                       goto out_buf;
-               ((struct v2_disk_dqdbheader *)tmpbuf)->dqdh_prev_free = cpu_to_le32(blk);
-               if ((err = write_blk(sb, type, info->u.v2_i.dqi_free_entry, tmpbuf)) < 0)
-                       goto out_buf;
-       }
-       freedqbuf(tmpbuf);
-       info->u.v2_i.dqi_free_entry = blk;
-       mark_info_dirty(sb, type);
-       return 0;
-out_buf:
-       freedqbuf(tmpbuf);
-       return err;
-}
-
-/* Find space for dquot */
-static uint find_free_dqentry(struct dquot *dquot, int *err)
-{
-       struct super_block *sb = dquot->dq_sb;
-       struct mem_dqinfo *info = sb_dqopt(sb)->info+dquot->dq_type;
-       uint blk, i;
-       struct v2_disk_dqdbheader *dh;
-       struct v2_disk_dqblk *ddquot;
-       struct v2_disk_dqblk fakedquot;
-       dqbuf_t buf;
-
-       *err = 0;
-       if (!(buf = getdqbuf())) {
-               *err = -ENOMEM;
+       if (qtree_entry_unused(info, dp))
                return 0;
-       }
-       dh = (struct v2_disk_dqdbheader *)buf;
-       ddquot = GETENTRIES(buf);
-       if (info->u.v2_i.dqi_free_entry) {
-               blk = info->u.v2_i.dqi_free_entry;
-               if ((*err = read_blk(sb, dquot->dq_type, blk, buf)) < 0)
-                       goto out_buf;
-       }
-       else {
-               blk = get_free_dqblk(sb, dquot->dq_type);
-               if ((int)blk < 0) {
-                       *err = blk;
-                       freedqbuf(buf);
-                       return 0;
-               }
-               memset(buf, 0, V2_DQBLKSIZE);
-               /* This is enough as block is already zeroed and entry list is empty... */
-               info->u.v2_i.dqi_free_entry = blk;
-               mark_info_dirty(sb, dquot->dq_type);
-       }
-       if (le16_to_cpu(dh->dqdh_entries)+1 >= V2_DQSTRINBLK)   /* Block will be full? */
-               if ((*err = remove_free_dqentry(sb, dquot->dq_type, buf, blk)) < 0) {
-                       printk(KERN_ERR "VFS: find_free_dqentry(): Can't remove block (%u) from entry free list.\n", blk);
-                       goto out_buf;
-               }
-       le16_add_cpu(&dh->dqdh_entries, 1);
-       memset(&fakedquot, 0, sizeof(struct v2_disk_dqblk));
-       /* Find free structure in block */
-       for (i = 0; i < V2_DQSTRINBLK && memcmp(&fakedquot, ddquot+i, sizeof(struct v2_disk_dqblk)); i++);
-#ifdef __QUOTA_V2_PARANOIA
-       if (i == V2_DQSTRINBLK) {
-               printk(KERN_ERR "VFS: find_free_dqentry(): Data block full but it shouldn't.\n");
-               *err = -EIO;
-               goto out_buf;
-       }
-#endif
-       if ((*err = write_blk(sb, dquot->dq_type, blk, buf)) < 0) {
-               printk(KERN_ERR "VFS: find_free_dqentry(): Can't write quota data block %u.\n", blk);
-               goto out_buf;
-       }
-       dquot->dq_off = (blk<<V2_DQBLKSIZE_BITS)+sizeof(struct v2_disk_dqdbheader)+i*sizeof(struct v2_disk_dqblk);
-       freedqbuf(buf);
-       return blk;
-out_buf:
-       freedqbuf(buf);
-       return 0;
-}
-
-/* Insert reference to structure into the trie */
-static int do_insert_tree(struct dquot *dquot, uint *treeblk, int depth)
-{
-       struct super_block *sb = dquot->dq_sb;
-       dqbuf_t buf;
-       int ret = 0, newson = 0, newact = 0;
-       __le32 *ref;
-       uint newblk;
-
-       if (!(buf = getdqbuf()))
-               return -ENOMEM;
-       if (!*treeblk) {
-               ret = get_free_dqblk(sb, dquot->dq_type);
-               if (ret < 0)
-                       goto out_buf;
-               *treeblk = ret;
-               memset(buf, 0, V2_DQBLKSIZE);
-               newact = 1;
-       }
-       else {
-               if ((ret = read_blk(sb, dquot->dq_type, *treeblk, buf)) < 0) {
-                       printk(KERN_ERR "VFS: Can't read tree quota block %u.\n", *treeblk);
-                       goto out_buf;
-               }
-       }
-       ref = (__le32 *)buf;
-       newblk = le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]);
-       if (!newblk)
-               newson = 1;
-       if (depth == V2_DQTREEDEPTH-1) {
-#ifdef __QUOTA_V2_PARANOIA
-               if (newblk) {
-                       printk(KERN_ERR "VFS: Inserting already present quota entry (block %u).\n", le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]));
-                       ret = -EIO;
-                       goto out_buf;
-               }
-#endif
-               newblk = find_free_dqentry(dquot, &ret);
-       }
-       else
-               ret = do_insert_tree(dquot, &newblk, depth+1);
-       if (newson && ret >= 0) {
-               ref[GETIDINDEX(dquot->dq_id, depth)] = cpu_to_le32(newblk);
-               ret = write_blk(sb, dquot->dq_type, *treeblk, buf);
-       }
-       else if (newact && ret < 0)
-               put_free_dqblk(sb, dquot->dq_type, buf, *treeblk);
-out_buf:
-       freedqbuf(buf);
-       return ret;
+       return le32_to_cpu(d->dqb_id) == dquot->dq_id;
 }
 
-/* Wrapper for inserting quota structure into tree */
-static inline int dq_insert_tree(struct dquot *dquot)
+static int v2_read_dquot(struct dquot *dquot)
 {
-       int tmp = V2_DQTREEOFF;
-       return do_insert_tree(dquot, &tmp, 0);
+       return qtree_read_dquot(sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv, dquot);
 }
 
-/*
- *     We don't have to be afraid of deadlocks as we never have quotas on quota files...
- */
 static int v2_write_dquot(struct dquot *dquot)
 {
-       int type = dquot->dq_type;
-       ssize_t ret;
-       struct v2_disk_dqblk ddquot, empty;
-
-       /* dq_off is guarded by dqio_mutex */
-       if (!dquot->dq_off)
-               if ((ret = dq_insert_tree(dquot)) < 0) {
-                       printk(KERN_ERR "VFS: Error %zd occurred while creating quota.\n", ret);
-                       return ret;
-               }
-       spin_lock(&dq_data_lock);
-       mem2diskdqb(&ddquot, &dquot->dq_dqb, dquot->dq_id);
-       /* Argh... We may need to write structure full of zeroes but that would be
-        * treated as an empty place by the rest of the code. Format change would
-        * be definitely cleaner but the problems probably are not worth it */
-       memset(&empty, 0, sizeof(struct v2_disk_dqblk));
-       if (!memcmp(&empty, &ddquot, sizeof(struct v2_disk_dqblk)))
-               ddquot.dqb_itime = cpu_to_le64(1);
-       spin_unlock(&dq_data_lock);
-       ret = dquot->dq_sb->s_op->quota_write(dquot->dq_sb, type,
-             (char *)&ddquot, sizeof(struct v2_disk_dqblk), dquot->dq_off);
-       if (ret != sizeof(struct v2_disk_dqblk)) {
-               printk(KERN_WARNING "VFS: dquota write failed on dev %s\n", dquot->dq_sb->s_id);
-               if (ret >= 0)
-                       ret = -ENOSPC;
-       }
-       else
-               ret = 0;
-       dqstats.writes++;
-
-       return ret;
+       return qtree_write_dquot(sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv, dquot);
 }
 
-/* Free dquot entry in data block */
-static int free_dqentry(struct dquot *dquot, uint blk)
-{
-       struct super_block *sb = dquot->dq_sb;
-       int type = dquot->dq_type;
-       struct v2_disk_dqdbheader *dh;
-       dqbuf_t buf = getdqbuf();
-       int ret = 0;
-
-       if (!buf)
-               return -ENOMEM;
-       if (dquot->dq_off >> V2_DQBLKSIZE_BITS != blk) {
-               printk(KERN_ERR "VFS: Quota structure has offset to other "
-                 "block (%u) than it should (%u).\n", blk,
-                 (uint)(dquot->dq_off >> V2_DQBLKSIZE_BITS));
-               goto out_buf;
-       }
-       if ((ret = read_blk(sb, type, blk, buf)) < 0) {
-               printk(KERN_ERR "VFS: Can't read quota data block %u\n", blk);
-               goto out_buf;
-       }
-       dh = (struct v2_disk_dqdbheader *)buf;
-       le16_add_cpu(&dh->dqdh_entries, -1);
-       if (!le16_to_cpu(dh->dqdh_entries)) {   /* Block got free? */
-               if ((ret = remove_free_dqentry(sb, type, buf, blk)) < 0 ||
-                   (ret = put_free_dqblk(sb, type, buf, blk)) < 0) {
-                       printk(KERN_ERR "VFS: Can't move quota data block (%u) "
-                         "to free list.\n", blk);
-                       goto out_buf;
-               }
-       }
-       else {
-               memset(buf+(dquot->dq_off & ((1 << V2_DQBLKSIZE_BITS)-1)), 0,
-                 sizeof(struct v2_disk_dqblk));
-               if (le16_to_cpu(dh->dqdh_entries) == V2_DQSTRINBLK-1) {
-                       /* Insert will write block itself */
-                       if ((ret = insert_free_dqentry(sb, type, buf, blk)) < 0) {
-                               printk(KERN_ERR "VFS: Can't insert quota data block (%u) to free entry list.\n", blk);
-                               goto out_buf;
-                       }
-               }
-               else
-                       if ((ret = write_blk(sb, type, blk, buf)) < 0) {
-                               printk(KERN_ERR "VFS: Can't write quota data "
-                                 "block %u\n", blk);
-                               goto out_buf;
-                       }
-       }
-       dquot->dq_off = 0;      /* Quota is now unattached */
-out_buf:
-       freedqbuf(buf);
-       return ret;
-}
-
-/* Remove reference to dquot from tree */
-static int remove_tree(struct dquot *dquot, uint *blk, int depth)
-{
-       struct super_block *sb = dquot->dq_sb;
-       int type = dquot->dq_type;
-       dqbuf_t buf = getdqbuf();
-       int ret = 0;
-       uint newblk;
-       __le32 *ref = (__le32 *)buf;
-       
-       if (!buf)
-               return -ENOMEM;
-       if ((ret = read_blk(sb, type, *blk, buf)) < 0) {
-               printk(KERN_ERR "VFS: Can't read quota data block %u\n", *blk);
-               goto out_buf;
-       }
-       newblk = le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]);
-       if (depth == V2_DQTREEDEPTH-1) {
-               ret = free_dqentry(dquot, newblk);
-               newblk = 0;
-       }
-       else
-               ret = remove_tree(dquot, &newblk, depth+1);
-       if (ret >= 0 && !newblk) {
-               int i;
-               ref[GETIDINDEX(dquot->dq_id, depth)] = cpu_to_le32(0);
-               for (i = 0; i < V2_DQBLKSIZE && !buf[i]; i++);  /* Block got empty? */
-               /* Don't put the root block into the free block list */
-               if (i == V2_DQBLKSIZE && *blk != V2_DQTREEOFF) {
-                       put_free_dqblk(sb, type, buf, *blk);
-                       *blk = 0;
-               }
-               else
-                       if ((ret = write_blk(sb, type, *blk, buf)) < 0)
-                               printk(KERN_ERR "VFS: Can't write quota tree "
-                                 "block %u.\n", *blk);
-       }
-out_buf:
-       freedqbuf(buf);
-       return ret;     
-}
-
-/* Delete dquot from tree */
-static int v2_delete_dquot(struct dquot *dquot)
-{
-       uint tmp = V2_DQTREEOFF;
-
-       if (!dquot->dq_off)     /* Even not allocated? */
-               return 0;
-       return remove_tree(dquot, &tmp, 0);
-}
-
-/* Find entry in block */
-static loff_t find_block_dqentry(struct dquot *dquot, uint blk)
-{
-       dqbuf_t buf = getdqbuf();
-       loff_t ret = 0;
-       int i;
-       struct v2_disk_dqblk *ddquot = GETENTRIES(buf);
-
-       if (!buf)
-               return -ENOMEM;
-       if ((ret = read_blk(dquot->dq_sb, dquot->dq_type, blk, buf)) < 0) {
-               printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
-               goto out_buf;
-       }
-       if (dquot->dq_id)
-               for (i = 0; i < V2_DQSTRINBLK &&
-                    le32_to_cpu(ddquot[i].dqb_id) != dquot->dq_id; i++);
-       else {  /* ID 0 as a bit more complicated searching... */
-               struct v2_disk_dqblk fakedquot;
-
-               memset(&fakedquot, 0, sizeof(struct v2_disk_dqblk));
-               for (i = 0; i < V2_DQSTRINBLK; i++)
-                       if (!le32_to_cpu(ddquot[i].dqb_id) &&
-                           memcmp(&fakedquot, ddquot+i, sizeof(struct v2_disk_dqblk)))
-                               break;
-       }
-       if (i == V2_DQSTRINBLK) {
-               printk(KERN_ERR "VFS: Quota for id %u referenced "
-                 "but not present.\n", dquot->dq_id);
-               ret = -EIO;
-               goto out_buf;
-       }
-       else
-               ret = (blk << V2_DQBLKSIZE_BITS) + sizeof(struct
-                 v2_disk_dqdbheader) + i * sizeof(struct v2_disk_dqblk);
-out_buf:
-       freedqbuf(buf);
-       return ret;
-}
-
-/* Find entry for given id in the tree */
-static loff_t find_tree_dqentry(struct dquot *dquot, uint blk, int depth)
-{
-       dqbuf_t buf = getdqbuf();
-       loff_t ret = 0;
-       __le32 *ref = (__le32 *)buf;
-
-       if (!buf)
-               return -ENOMEM;
-       if ((ret = read_blk(dquot->dq_sb, dquot->dq_type, blk, buf)) < 0) {
-               printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
-               goto out_buf;
-       }
-       ret = 0;
-       blk = le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]);
-       if (!blk)       /* No reference? */
-               goto out_buf;
-       if (depth < V2_DQTREEDEPTH-1)
-               ret = find_tree_dqentry(dquot, blk, depth+1);
-       else
-               ret = find_block_dqentry(dquot, blk);
-out_buf:
-       freedqbuf(buf);
-       return ret;
-}
-
-/* Find entry for given id in the tree - wrapper function */
-static inline loff_t find_dqentry(struct dquot *dquot)
-{
-       return find_tree_dqentry(dquot, V2_DQTREEOFF, 0);
-}
-
-static int v2_read_dquot(struct dquot *dquot)
+static int v2_release_dquot(struct dquot *dquot)
 {
-       int type = dquot->dq_type;
-       loff_t offset;
-       struct v2_disk_dqblk ddquot, empty;
-       int ret = 0;
-
-#ifdef __QUOTA_V2_PARANOIA
-       /* Invalidated quota? */
-       if (!dquot->dq_sb || !sb_dqopt(dquot->dq_sb)->files[type]) {
-               printk(KERN_ERR "VFS: Quota invalidated while reading!\n");
-               return -EIO;
-       }
-#endif
-       offset = find_dqentry(dquot);
-       if (offset <= 0) {      /* Entry not present? */
-               if (offset < 0)
-                       printk(KERN_ERR "VFS: Can't read quota "
-                         "structure for id %u.\n", dquot->dq_id);
-               dquot->dq_off = 0;
-               set_bit(DQ_FAKE_B, &dquot->dq_flags);
-               memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk));
-               ret = offset;
-       }
-       else {
-               dquot->dq_off = offset;
-               if ((ret = dquot->dq_sb->s_op->quota_read(dquot->dq_sb, type,
-                   (char *)&ddquot, sizeof(struct v2_disk_dqblk), offset))
-                   != sizeof(struct v2_disk_dqblk)) {
-                       if (ret >= 0)
-                               ret = -EIO;
-                       printk(KERN_ERR "VFS: Error while reading quota "
-                         "structure for id %u.\n", dquot->dq_id);
-                       memset(&ddquot, 0, sizeof(struct v2_disk_dqblk));
-               }
-               else {
-                       ret = 0;
-                       /* We need to escape back all-zero structure */
-                       memset(&empty, 0, sizeof(struct v2_disk_dqblk));
-                       empty.dqb_itime = cpu_to_le64(1);
-                       if (!memcmp(&empty, &ddquot, sizeof(struct v2_disk_dqblk)))
-                               ddquot.dqb_itime = 0;
-               }
-               disk2memdqb(&dquot->dq_dqb, &ddquot);
-               if (!dquot->dq_dqb.dqb_bhardlimit &&
-                       !dquot->dq_dqb.dqb_bsoftlimit &&
-                       !dquot->dq_dqb.dqb_ihardlimit &&
-                       !dquot->dq_dqb.dqb_isoftlimit)
-                       set_bit(DQ_FAKE_B, &dquot->dq_flags);
-       }
-       dqstats.reads++;
-
-       return ret;
+       return qtree_release_dquot(sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv, dquot);
 }
 
-/* Check whether dquot should not be deleted. We know we are
- * the only one operating on dquot (thanks to dq_lock) */
-static int v2_release_dquot(struct dquot *dquot)
+static int v2_free_file_info(struct super_block *sb, int type)
 {
-       if (test_bit(DQ_FAKE_B, &dquot->dq_flags) && !(dquot->dq_dqb.dqb_curinodes | dquot->dq_dqb.dqb_curspace))
-               return v2_delete_dquot(dquot);
+       kfree(sb_dqinfo(sb, type)->dqi_priv);
        return 0;
 }
 
@@ -673,7 +210,7 @@ static struct quota_format_ops v2_format_ops = {
        .check_quota_file       = v2_check_quota_file,
        .read_file_info         = v2_read_file_info,
        .write_file_info        = v2_write_file_info,
-       .free_file_info         = NULL,
+       .free_file_info         = v2_free_file_info,
        .read_dqblk             = v2_read_dquot,
        .commit_dqblk           = v2_write_dquot,
        .release_dqblk          = v2_release_dquot,
similarity index 100%
rename from include/linux/quotaio_v1.h
rename to fs/quotaio_v1.h
similarity index 68%
rename from include/linux/quotaio_v2.h
rename to fs/quotaio_v2.h
index 303d7cbe30d43530d3a2ee4a16bae4ac2f66b4cc..530fe580685c64abb2576f637f61454ee601c81c 100644 (file)
        0               /* GRPQUOTA */\
 }
 
+/* First generic header */
+struct v2_disk_dqheader {
+       __le32 dqh_magic;       /* Magic number identifying file */
+       __le32 dqh_version;     /* File version */
+};
+
 /*
  * The following structure defines the format of the disk quota file
  * (as it appears on disk) - the file is a radix tree whose leaves point
@@ -38,15 +44,6 @@ struct v2_disk_dqblk {
        __le64 dqb_itime;       /* time limit for excessive inode use */
 };
 
-/*
- * Here are header structures as written on disk and their in-memory copies
- */
-/* First generic header */
-struct v2_disk_dqheader {
-       __le32 dqh_magic;       /* Magic number identifying file */
-       __le32 dqh_version;     /* File version */
-};
-
 /* Header with type and version specific information */
 struct v2_disk_dqinfo {
        __le32 dqi_bgrace;      /* Time before block soft limit becomes hard limit */
@@ -57,23 +54,7 @@ struct v2_disk_dqinfo {
        __le32 dqi_free_entry;  /* Number of block with at least one free entry */
 };
 
-/*
- *  Structure of header of block with quota structures. It is padded to 16 bytes so
- *  there will be space for exactly 21 quota-entries in a block
- */
-struct v2_disk_dqdbheader {
-       __le32 dqdh_next_free;  /* Number of next block with free entry */
-       __le32 dqdh_prev_free;  /* Number of previous block with free entry */
-       __le16 dqdh_entries;    /* Number of valid entries in block */
-       __le16 dqdh_pad1;
-       __le32 dqdh_pad2;
-};
-
 #define V2_DQINFOOFF   sizeof(struct v2_disk_dqheader) /* Offset of info header in file */
-#define V2_DQBLKSIZE_BITS      10
-#define V2_DQBLKSIZE   (1 << V2_DQBLKSIZE_BITS)        /* Size of block with quota structures */
-#define V2_DQTREEOFF   1               /* Offset of tree in file in blocks */
-#define V2_DQTREEDEPTH 4               /* Depth of quota tree */
-#define V2_DQSTRINBLK  ((V2_DQBLKSIZE - sizeof(struct v2_disk_dqdbheader)) / sizeof(struct v2_disk_dqblk))     /* Number of entries in one blocks */
+#define V2_DQBLKSIZE_BITS 10                           /* Size of leaf block in tree */
 
 #endif /* _LINUX_QUOTAIO_V2_H */
index a83a3518ae331134458a72df0208249a90b8ee09..b7e6ac706b87b30ba96701b3bb7820e47f319218 100644 (file)
@@ -57,7 +57,6 @@ struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev)
                inode->i_mode = mode;
                inode->i_uid = current_fsuid();
                inode->i_gid = current_fsgid();
-               inode->i_blocks = 0;
                inode->i_mapping->a_ops = &ramfs_aops;
                inode->i_mapping->backing_dev_info = &ramfs_backing_dev_info;
                mapping_set_gfp_mask(inode->i_mapping, GFP_HIGHUSER);
index 969a6d9c020ba01644578b04c86043b15e98b53a..5cc6924eb158f14b47fdc82c96500ef090f4c738 100644 (file)
@@ -50,6 +50,14 @@ generic_file_llseek_unlocked(struct file *file, loff_t offset, int origin)
                offset += inode->i_size;
                break;
        case SEEK_CUR:
+               /*
+                * Here we special-case the lseek(fd, 0, SEEK_CUR)
+                * position-querying operation.  Avoid rewriting the "same"
+                * f_pos value back to the file because a concurrent read(),
+                * write() or lseek() might have altered it
+                */
+               if (offset == 0)
+                       return file->f_pos;
                offset += file->f_pos;
                break;
        }
@@ -105,6 +113,10 @@ loff_t default_llseek(struct file *file, loff_t offset, int origin)
                        offset += i_size_read(file->f_path.dentry->d_inode);
                        break;
                case SEEK_CUR:
+                       if (offset == 0) {
+                               retval = file->f_pos;
+                               goto out;
+                       }
                        offset += file->f_pos;
        }
        retval = -EINVAL;
@@ -115,6 +127,7 @@ loff_t default_llseek(struct file *file, loff_t offset, int origin)
                }
                retval = offset;
        }
+out:
        unlock_kernel();
        return retval;
 }
index 145c2d3e5e0107a911e0127ba4f65a1a75d2c903..55fce92cdf18f4cfc58241d3c48ef76fa04f340e 100644 (file)
@@ -1782,6 +1782,12 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
                goto out_bad_inode;
        }
        args.objectid = inode->i_ino = le32_to_cpu(ih.ih_key.k_objectid);
+       if (old_format_only(sb))
+               make_le_item_head(&ih, NULL, KEY_FORMAT_3_5, SD_OFFSET,
+                                 TYPE_STAT_DATA, SD_V1_SIZE, MAX_US_INT);
+       else
+               make_le_item_head(&ih, NULL, KEY_FORMAT_3_6, SD_OFFSET,
+                                 TYPE_STAT_DATA, SD_SIZE, MAX_US_INT);
        memcpy(INODE_PKEY(inode), &(ih.ih_key), KEY_SIZE);
        args.dirid = le32_to_cpu(ih.ih_key.k_dir_id);
        if (insert_inode_locked4(inode, args.objectid,
@@ -1834,13 +1840,6 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
        reiserfs_init_acl_default(inode);
        reiserfs_init_xattr_rwsem(inode);
 
-       if (old_format_only(sb))
-               make_le_item_head(&ih, NULL, KEY_FORMAT_3_5, SD_OFFSET,
-                                 TYPE_STAT_DATA, SD_V1_SIZE, MAX_US_INT);
-       else
-               make_le_item_head(&ih, NULL, KEY_FORMAT_3_6, SD_OFFSET,
-                                 TYPE_STAT_DATA, SD_SIZE, MAX_US_INT);
-
        /* key to search for correct place for new stat data */
        _make_cpu_key(&key, KEY_FORMAT_3_6, le32_to_cpu(ih.ih_key.k_dir_id),
                      le32_to_cpu(ih.ih_key.k_objectid), SD_OFFSET,
@@ -2561,7 +2560,7 @@ static int reiserfs_write_begin(struct file *file,
        }
 
        index = pos >> PAGE_CACHE_SHIFT;
-       page = __grab_cache_page(mapping, index);
+       page = grab_cache_page_write_begin(mapping, index, flags);
        if (!page)
                return -ENOMEM;
        *pagep = page;
index 663a91f5dce8a33d4f12c85658122a62da216bc8..c55651f1407ce9b19966bb6fadc3d881e98525b7 100644 (file)
@@ -649,6 +649,8 @@ static struct dquot_operations reiserfs_quota_operations = {
        .release_dquot = reiserfs_release_dquot,
        .mark_dirty = reiserfs_mark_dquot_dirty,
        .write_info = reiserfs_write_info,
+       .alloc_dquot    = dquot_alloc,
+       .destroy_dquot  = dquot_destroy,
 };
 
 static struct quotactl_ops reiserfs_qctl_operations = {
@@ -994,8 +996,7 @@ static int reiserfs_parse_options(struct super_block *s, char *options,     /* strin
                if (c == 'u' || c == 'g') {
                        int qtype = c == 'u' ? USRQUOTA : GRPQUOTA;
 
-                       if ((sb_any_quota_enabled(s) ||
-                            sb_any_quota_suspended(s)) &&
+                       if (sb_any_quota_loaded(s) &&
                            (!*arg != !REISERFS_SB(s)->s_qf_names[qtype])) {
                                reiserfs_warning(s,
                                                 "reiserfs_parse_options: cannot change journaled quota options when quota turned on.");
@@ -1041,8 +1042,7 @@ static int reiserfs_parse_options(struct super_block *s, char *options,   /* strin
                                                 "reiserfs_parse_options: unknown quota format specified.");
                                return 0;
                        }
-                       if ((sb_any_quota_enabled(s) ||
-                            sb_any_quota_suspended(s)) &&
+                       if (sb_any_quota_loaded(s) &&
                            *qfmt != REISERFS_SB(s)->s_jquota_fmt) {
                                reiserfs_warning(s,
                                                 "reiserfs_parse_options: cannot change journaled quota options when quota turned on.");
@@ -1067,7 +1067,7 @@ static int reiserfs_parse_options(struct super_block *s, char *options,   /* strin
        }
        /* This checking is not precise wrt the quota type but for our purposes it is sufficient */
        if (!(*mount_options & (1 << REISERFS_QUOTA))
-           && sb_any_quota_enabled(s)) {
+           && sb_any_quota_loaded(s)) {
                reiserfs_warning(s,
                                 "reiserfs_parse_options: quota options must be present when quota is turned on.");
                return 0;
index 60d2f822e87befa396bb31f78ca53b13a378e7ef..c97d4c931715767bff385ece2600f1504d2483af 100644 (file)
@@ -524,7 +524,6 @@ romfs_iget(struct super_block *sb, unsigned long ino)
        i->i_size = be32_to_cpu(ri.size);
        i->i_mtime.tv_sec = i->i_atime.tv_sec = i->i_ctime.tv_sec = 0;
        i->i_mtime.tv_nsec = i->i_atime.tv_nsec = i->i_ctime.tv_nsec = 0;
-       i->i_uid = i->i_gid = 0;
 
         /* Precalculate the data offset */
         ino = romfs_strnlen(i, ino+ROMFH_SIZE, ROMFS_MAXFN);
index 99d8b8cfc9b78673e1040d0e690f33cf43361bdf..b569ff1c4dc81570bec822be5df54069af18a162 100644 (file)
@@ -468,7 +468,8 @@ int seq_dentry(struct seq_file *m, struct dentry *dentry, char *esc)
        return -1;
 }
 
-int seq_bitmap(struct seq_file *m, unsigned long *bits, unsigned int nr_bits)
+int seq_bitmap(struct seq_file *m, const unsigned long *bits,
+                                  unsigned int nr_bits)
 {
        if (m->count < m->size) {
                int len = bitmap_scnprintf(m->buf + m->count,
index e4f8d51a5553651bd0235b2d4310ac9c44f32fb6..92d5e8ffb63923062680d09906f8baa7ad53d8c8 100644 (file)
@@ -297,7 +297,7 @@ static int smb_write_begin(struct file *file, struct address_space *mapping,
                        struct page **pagep, void **fsdata)
 {
        pgoff_t index = pos >> PAGE_CACHE_SHIFT;
-       *pagep = __grab_cache_page(mapping, index);
+       *pagep = grab_cache_page_write_begin(mapping, index, flags);
        if (!*pagep)
                return -ENOMEM;
        return 0;
index 7c46fbeb8b762e0f125a594a6fd27747ff160c55..7e12a6f827954bbd5fcdd7c1be9d02918ccef75a 100644 (file)
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -305,7 +305,7 @@ asmlinkage long sys_readlinkat(int dfd, const char __user *pathname,
                struct inode *inode = path.dentry->d_inode;
 
                error = -EINVAL;
-               if (inode->i_op && inode->i_op->readlink) {
+               if (inode->i_op->readlink) {
                        error = security_inode_readlink(path.dentry);
                        if (!error) {
                                touch_atime(path.mnt, path.dentry);
index 2967562d416fb52e54a1af5840d0dc63c0d25cfb..0921d6d4b5e6d27b6fe471128da5b07cf699f137 100644 (file)
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -75,14 +75,39 @@ int file_fsync(struct file *filp, struct dentry *dentry, int datasync)
        return ret;
 }
 
-long do_fsync(struct file *file, int datasync)
+/**
+ * vfs_fsync - perform a fsync or fdatasync on a file
+ * @file:              file to sync
+ * @dentry:            dentry of @file
+ * @data:              only perform a fdatasync operation
+ *
+ * Write back data and metadata for @file to disk.  If @datasync is
+ * set only metadata needed to access modified file data is written.
+ *
+ * In case this function is called from nfsd @file may be %NULL and
+ * only @dentry is set.  This can only happen when the filesystem
+ * implements the export_operations API.
+ */
+int vfs_fsync(struct file *file, struct dentry *dentry, int datasync)
 {
-       int ret;
-       int err;
-       struct address_space *mapping = file->f_mapping;
+       const struct file_operations *fop;
+       struct address_space *mapping;
+       int err, ret;
+
+       /*
+        * Get mapping and operations from the file in case we have
+        * as file, or get the default values for them in case we
+        * don't have a struct file available.  Damn nfsd..
+        */
+       if (file) {
+               mapping = file->f_mapping;
+               fop = file->f_op;
+       } else {
+               mapping = dentry->d_inode->i_mapping;
+               fop = dentry->d_inode->i_fop;
+       }
 
-       if (!file->f_op || !file->f_op->fsync) {
-               /* Why?  We can still call filemap_fdatawrite */
+       if (!fop || !fop->fsync) {
                ret = -EINVAL;
                goto out;
        }
@@ -94,7 +119,7 @@ long do_fsync(struct file *file, int datasync)
         * livelocks in fsync_buffers_list().
         */
        mutex_lock(&mapping->host->i_mutex);
-       err = file->f_op->fsync(file, file->f_path.dentry, datasync);
+       err = fop->fsync(file, dentry, datasync);
        if (!ret)
                ret = err;
        mutex_unlock(&mapping->host->i_mutex);
@@ -104,15 +129,16 @@ long do_fsync(struct file *file, int datasync)
 out:
        return ret;
 }
+EXPORT_SYMBOL(vfs_fsync);
 
-static long __do_fsync(unsigned int fd, int datasync)
+static int do_fsync(unsigned int fd, int datasync)
 {
        struct file *file;
        int ret = -EBADF;
 
        file = fget(fd);
        if (file) {
-               ret = do_fsync(file, datasync);
+               ret = vfs_fsync(file, file->f_path.dentry, datasync);
                fput(file);
        }
        return ret;
@@ -120,12 +146,12 @@ static long __do_fsync(unsigned int fd, int datasync)
 
 asmlinkage long sys_fsync(unsigned int fd)
 {
-       return __do_fsync(fd, 0);
+       return do_fsync(fd, 0);
 }
 
 asmlinkage long sys_fdatasync(unsigned int fd)
 {
-       return __do_fsync(fd, 1);
+       return do_fsync(fd, 1);
 }
 
 /*
index eb53c632f8564a100d92e4670b8c6764776a3514..dfa3d94cfc74a33b5bf342ea1a5e7c9ad346109c 100644 (file)
@@ -107,8 +107,6 @@ int sysfs_setattr(struct dentry * dentry, struct iattr * iattr)
 static inline void set_default_inode_attr(struct inode * inode, mode_t mode)
 {
        inode->i_mode = mode;
-       inode->i_uid = 0;
-       inode->i_gid = 0;
        inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 }
 
@@ -149,7 +147,6 @@ static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
 {
        struct bin_attribute *bin_attr;
 
-       inode->i_blocks = 0;
        inode->i_mapping->a_ops = &sysfs_aops;
        inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
        inode->i_op = &sysfs_inode_operations;
index 4a18f084cc427a7df83214055d9efa023a549444..0e5e54d829243afba459b97a72a303aad6654e00 100644 (file)
 
 #include "ubifs.h"
 #include <linux/writeback.h>
-#include <asm/div64.h>
+#include <linux/math64.h>
 
 /*
  * When pessimistic budget calculations say that there is no enough space,
  * UBIFS starts writing back dirty inodes and pages, doing garbage collection,
- * or committing. The below constants define maximum number of times UBIFS
+ * or committing. The below constant defines maximum number of times UBIFS
  * repeats the operations.
  */
-#define MAX_SHRINK_RETRIES 8
-#define MAX_GC_RETRIES     4
-#define MAX_CMT_RETRIES    2
-#define MAX_NOSPC_RETRIES  1
+#define MAX_MKSPC_RETRIES 3
 
 /*
  * The below constant defines amount of dirty pages which should be written
  */
 #define NR_TO_WRITE 16
 
-/**
- * struct retries_info - information about re-tries while making free space.
- * @prev_liability: previous liability
- * @shrink_cnt: how many times the liability was shrinked
- * @shrink_retries: count of liability shrink re-tries (increased when
- *                  liability does not shrink)
- * @try_gc: GC should be tried first
- * @gc_retries: how many times GC was run
- * @cmt_retries: how many times commit has been done
- * @nospc_retries: how many times GC returned %-ENOSPC
- *
- * Since we consider budgeting to be the fast-path, and this structure has to
- * be allocated on stack and zeroed out, we make it smaller using bit-fields.
- */
-struct retries_info {
-       long long prev_liability;
-       unsigned int shrink_cnt;
-       unsigned int shrink_retries:5;
-       unsigned int try_gc:1;
-       unsigned int gc_retries:4;
-       unsigned int cmt_retries:3;
-       unsigned int nospc_retries:1;
-};
-
 /**
  * shrink_liability - write-back some dirty pages/inodes.
  * @c: UBIFS file-system description object
@@ -146,10 +119,26 @@ static int run_gc(struct ubifs_info *c)
        return 0;
 }
 
+/**
+ * get_liability - calculate current liability.
+ * @c: UBIFS file-system description object
+ *
+ * This function calculates and returns current UBIFS liability, i.e. the
+ * amount of bytes UBIFS has "promised" to write to the media.
+ */
+static long long get_liability(struct ubifs_info *c)
+{
+       long long liab;
+
+       spin_lock(&c->space_lock);
+       liab = c->budg_idx_growth + c->budg_data_growth + c->budg_dd_growth;
+       spin_unlock(&c->space_lock);
+       return liab;
+}
+
 /**
  * make_free_space - make more free space on the file-system.
  * @c: UBIFS file-system description object
- * @ri: information about previous invocations of this function
  *
  * This function is called when an operation cannot be budgeted because there
  * is supposedly no free space. But in most cases there is some free space:
@@ -165,87 +154,42 @@ static int run_gc(struct ubifs_info *c)
  * Returns %-ENOSPC if it couldn't do more free space, and other negative error
  * codes on failures.
  */
-static int make_free_space(struct ubifs_info *c, struct retries_info *ri)
+static int make_free_space(struct ubifs_info *c)
 {
-       int err;
-
-       /*
-        * If we have some dirty pages and inodes (liability), try to write
-        * them back unless this was tried too many times without effect
-        * already.
-        */
-       if (ri->shrink_retries < MAX_SHRINK_RETRIES && !ri->try_gc) {
-               long long liability;
-
-               spin_lock(&c->space_lock);
-               liability = c->budg_idx_growth + c->budg_data_growth +
-                           c->budg_dd_growth;
-               spin_unlock(&c->space_lock);
+       int err, retries = 0;
+       long long liab1, liab2;
 
-               if (ri->prev_liability >= liability) {
-                       /* Liability does not shrink, next time try GC then */
-                       ri->shrink_retries += 1;
-                       if (ri->gc_retries < MAX_GC_RETRIES)
-                               ri->try_gc = 1;
-                       dbg_budg("liability did not shrink: retries %d of %d",
-                                ri->shrink_retries, MAX_SHRINK_RETRIES);
-               }
+       do {
+               liab1 = get_liability(c);
+               /*
+                * We probably have some dirty pages or inodes (liability), try
+                * to write them back.
+                */
+               dbg_budg("liability %lld, run write-back", liab1);
+               shrink_liability(c, NR_TO_WRITE);
 
-               dbg_budg("force write-back (count %d)", ri->shrink_cnt);
-               shrink_liability(c, NR_TO_WRITE + ri->shrink_cnt);
+               liab2 = get_liability(c);
+               if (liab2 < liab1)
+                       return -EAGAIN;
 
-               ri->prev_liability = liability;
-               ri->shrink_cnt += 1;
-               return -EAGAIN;
-       }
+               dbg_budg("new liability %lld (not shrinked)", liab2);
 
-       /*
-        * Try to run garbage collector unless it was already tried too many
-        * times.
-        */
-       if (ri->gc_retries < MAX_GC_RETRIES) {
-               ri->gc_retries += 1;
-               dbg_budg("run GC, retries %d of %d",
-                        ri->gc_retries, MAX_GC_RETRIES);
-
-               ri->try_gc = 0;
+               /* Liability did not shrink again, try GC */
+               dbg_budg("Run GC");
                err = run_gc(c);
                if (!err)
                        return -EAGAIN;
 
-               if (err == -EAGAIN) {
-                       dbg_budg("GC asked to commit");
-                       err = ubifs_run_commit(c);
-                       if (err)
-                               return err;
-                       return -EAGAIN;
-               }
-
-               if (err != -ENOSPC)
-                       return err;
-
-               /*
-                * GC could not make any progress. If this is the first time,
-                * then it makes sense to try to commit, because it might make
-                * some dirty space.
-                */
-               dbg_budg("GC returned -ENOSPC, retries %d",
-                        ri->nospc_retries);
-               if (ri->nospc_retries >= MAX_NOSPC_RETRIES)
+               if (err != -EAGAIN && err != -ENOSPC)
+                       /* Some real error happened */
                        return err;
-               ri->nospc_retries += 1;
-       }
 
-       /* Neither GC nor write-back helped, try to commit */
-       if (ri->cmt_retries < MAX_CMT_RETRIES) {
-               ri->cmt_retries += 1;
-               dbg_budg("run commit, retries %d of %d",
-                        ri->cmt_retries, MAX_CMT_RETRIES);
+               dbg_budg("Run commit (retries %d)", retries);
                err = ubifs_run_commit(c);
                if (err)
                        return err;
-               return -EAGAIN;
-       }
+       } while (retries++ < MAX_MKSPC_RETRIES);
+
        return -ENOSPC;
 }
 
@@ -258,8 +202,8 @@ static int make_free_space(struct ubifs_info *c, struct retries_info *ri)
  */
 int ubifs_calc_min_idx_lebs(struct ubifs_info *c)
 {
-       int ret;
-       uint64_t idx_size;
+       int idx_lebs, eff_leb_size = c->leb_size - c->max_idx_node_sz;
+       long long idx_size;
 
        idx_size = c->old_idx_sz + c->budg_idx_growth + c->budg_uncommitted_idx;
 
@@ -271,23 +215,16 @@ int ubifs_calc_min_idx_lebs(struct ubifs_info *c)
         * pair, nor similarly the two variables for the new index size, so we
         * have to do this costly 64-bit division on fast-path.
         */
-       if (do_div(idx_size, c->leb_size - c->max_idx_node_sz))
-               ret = idx_size + 1;
-       else
-               ret = idx_size;
+       idx_size += eff_leb_size - 1;
+       idx_lebs = div_u64(idx_size, eff_leb_size);
        /*
         * The index head is not available for the in-the-gaps method, so add an
         * extra LEB to compensate.
         */
-       ret += 1;
-       /*
-        * At present the index needs at least 2 LEBs: one for the index head
-        * and one for in-the-gaps method (which currently does not cater for
-        * the index head and so excludes it from consideration).
-        */
-       if (ret < 2)
-               ret = 2;
-       return ret;
+       idx_lebs += 1;
+       if (idx_lebs < MIN_INDEX_LEBS)
+               idx_lebs = MIN_INDEX_LEBS;
+       return idx_lebs;
 }
 
 /**
@@ -530,8 +467,7 @@ static int calc_dd_growth(const struct ubifs_info *c,
 int ubifs_budget_space(struct ubifs_info *c, struct ubifs_budget_req *req)
 {
        int uninitialized_var(cmt_retries), uninitialized_var(wb_retries);
-       int err, idx_growth, data_growth, dd_growth;
-       struct retries_info ri;
+       int err, idx_growth, data_growth, dd_growth, retried = 0;
 
        ubifs_assert(req->new_page <= 1);
        ubifs_assert(req->dirtied_page <= 1);
@@ -549,7 +485,6 @@ int ubifs_budget_space(struct ubifs_info *c, struct ubifs_budget_req *req)
        if (!data_growth && !dd_growth)
                return 0;
        idx_growth = calc_idx_growth(c, req);
-       memset(&ri, 0, sizeof(struct retries_info));
 
 again:
        spin_lock(&c->space_lock);
@@ -587,12 +522,17 @@ again:
                return err;
        }
 
-       err = make_free_space(c, &ri);
+       err = make_free_space(c);
+       cond_resched();
        if (err == -EAGAIN) {
                dbg_budg("try again");
-               cond_resched();
                goto again;
        } else if (err == -ENOSPC) {
+               if (!retried) {
+                       retried = 1;
+                       dbg_budg("-ENOSPC, but anyway try once again");
+                       goto again;
+               }
                dbg_budg("FS is full, -ENOSPC");
                c->nospace = 1;
                if (can_use_rp(c) || c->rp_size == 0)
@@ -712,9 +652,9 @@ void ubifs_release_dirty_inode_budget(struct ubifs_info *c,
  * user-space. User-space application tend to expect that if the file-system
  * (e.g., via the 'statfs()' call) reports that it has N bytes available, they
  * are able to write a file of size N. UBIFS attaches node headers to each data
- * node and it has to write indexind nodes as well. This introduces additional
- * overhead, and UBIFS it has to report sligtly less free space to meet the
- * above expectetion.
+ * node and it has to write indexing nodes as well. This introduces additional
+ * overhead, and UBIFS has to report slightly less free space to meet the above
+ * expectations.
  *
  * This function assumes free space is made up of uncompressed data nodes and
  * full index nodes (one per data node, tripled because we always allow enough
@@ -723,7 +663,7 @@ void ubifs_release_dirty_inode_budget(struct ubifs_info *c,
  * Note, the calculation is pessimistic, which means that most of the time
  * UBIFS reports less space than it actually has.
  */
-long long ubifs_reported_space(const struct ubifs_info *c, uint64_t free)
+long long ubifs_reported_space(const struct ubifs_info *c, long long free)
 {
        int divisor, factor, f;
 
@@ -737,7 +677,7 @@ long long ubifs_reported_space(const struct ubifs_info *c, uint64_t free)
         * of data nodes, f - fanout. Because effective UBIFS fanout is twice
         * as less than maximum fanout, we assume that each data node
         * introduces 3 * @c->max_idx_node_sz / (@c->fanout/2 - 1) bytes.
-        * Note, the multiplier 3 is because UBIFS reseves thrice as more space
+        * Note, the multiplier 3 is because UBIFS reserves thrice as more space
         * for the index.
         */
        f = c->fanout > 3 ? c->fanout >> 1 : 2;
@@ -745,8 +685,7 @@ long long ubifs_reported_space(const struct ubifs_info *c, uint64_t free)
        divisor = UBIFS_MAX_DATA_NODE_SZ;
        divisor += (c->max_idx_node_sz * 3) / (f - 1);
        free *= factor;
-       do_div(free, divisor);
-       return free;
+       return div_u64(free, divisor);
 }
 
 /**
@@ -756,10 +695,10 @@ long long ubifs_reported_space(const struct ubifs_info *c, uint64_t free)
  * This function calculates amount of free space to report to user-space.
  *
  * Because UBIFS may introduce substantial overhead (the index, node headers,
- * alighment, wastage at the end of eraseblocks, etc), it cannot report real
+ * alignment, wastage at the end of eraseblocks, etc), it cannot report real
  * amount of free flash space it has (well, because not all dirty space is
- * reclamable, UBIFS does not actually know the real amount). If UBIFS did so,
- * it would bread user expectetion about what free space is. Users seem to
+ * reclaimable, UBIFS does not actually know the real amount). If UBIFS did so,
+ * it would bread user expectations about what free space is. Users seem to
  * accustomed to assume that if the file-system reports N bytes of free space,
  * they would be able to fit a file of N bytes to the FS. This almost works for
  * traditional file-systems, because they have way less overhead than UBIFS.
@@ -771,18 +710,9 @@ long long ubifs_get_free_space(struct ubifs_info *c)
        long long available, outstanding, free;
 
        spin_lock(&c->space_lock);
-       min_idx_lebs = ubifs_calc_min_idx_lebs(c);
+       min_idx_lebs = c->min_idx_lebs;
+       ubifs_assert(min_idx_lebs == ubifs_calc_min_idx_lebs(c));
        outstanding = c->budg_data_growth + c->budg_dd_growth;
-
-       /*
-        * Force the amount available to the total size reported if the used
-        * space is zero.
-        */
-       if (c->lst.total_used <= UBIFS_INO_NODE_SZ && !outstanding) {
-               spin_unlock(&c->space_lock);
-               return (long long)c->block_cnt << UBIFS_BLOCK_SHIFT;
-       }
-
        available = ubifs_calc_available(c, min_idx_lebs);
 
        /*
index b49884c8c10e823cbe484e9d5c1fadddf16b5008..f3a7945527fb694b9902143763deebc15231b3aa 100644 (file)
@@ -470,12 +470,12 @@ int dbg_old_index_check_init(struct ubifs_info *c, struct ubifs_zbranch *zroot)
 {
        struct ubifs_idx_node *idx;
        int lnum, offs, len, err = 0;
+       struct ubifs_debug_info *d = c->dbg;
 
-       c->old_zroot = *zroot;
-
-       lnum = c->old_zroot.lnum;
-       offs = c->old_zroot.offs;
-       len = c->old_zroot.len;
+       d->old_zroot = *zroot;
+       lnum = d->old_zroot.lnum;
+       offs = d->old_zroot.offs;
+       len = d->old_zroot.len;
 
        idx = kmalloc(c->max_idx_node_sz, GFP_NOFS);
        if (!idx)
@@ -485,8 +485,8 @@ int dbg_old_index_check_init(struct ubifs_info *c, struct ubifs_zbranch *zroot)
        if (err)
                goto out;
 
-       c->old_zroot_level = le16_to_cpu(idx->level);
-       c->old_zroot_sqnum = le64_to_cpu(idx->ch.sqnum);
+       d->old_zroot_level = le16_to_cpu(idx->level);
+       d->old_zroot_sqnum = le64_to_cpu(idx->ch.sqnum);
 out:
        kfree(idx);
        return err;
@@ -509,6 +509,7 @@ int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot)
 {
        int lnum, offs, len, err = 0, uninitialized_var(last_level), child_cnt;
        int first = 1, iip;
+       struct ubifs_debug_info *d = c->dbg;
        union ubifs_key lower_key, upper_key, l_key, u_key;
        unsigned long long uninitialized_var(last_sqnum);
        struct ubifs_idx_node *idx;
@@ -525,9 +526,9 @@ int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot)
             UBIFS_IDX_NODE_SZ;
 
        /* Start at the old zroot */
-       lnum = c->old_zroot.lnum;
-       offs = c->old_zroot.offs;
-       len = c->old_zroot.len;
+       lnum = d->old_zroot.lnum;
+       offs = d->old_zroot.offs;
+       len = d->old_zroot.len;
        iip = 0;
 
        /*
@@ -560,11 +561,11 @@ int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot)
                if (first) {
                        first = 0;
                        /* Check root level and sqnum */
-                       if (le16_to_cpu(idx->level) != c->old_zroot_level) {
+                       if (le16_to_cpu(idx->level) != d->old_zroot_level) {
                                err = 2;
                                goto out_dump;
                        }
-                       if (le64_to_cpu(idx->ch.sqnum) != c->old_zroot_sqnum) {
+                       if (le64_to_cpu(idx->ch.sqnum) != d->old_zroot_sqnum) {
                                err = 3;
                                goto out_dump;
                        }
index a0ada596b17c4a5d9180b515e5fd7e524b72a642..11e4132f314acfcabc610cf97f4c4dd9e52b768d 100644 (file)
@@ -33,7 +33,7 @@
 /* Fake description object for the "none" compressor */
 static struct ubifs_compressor none_compr = {
        .compr_type = UBIFS_COMPR_NONE,
-       .name = "no compression",
+       .name = "none",
        .capi_name = "",
 };
 
@@ -43,13 +43,13 @@ static DEFINE_MUTEX(lzo_mutex);
 static struct ubifs_compressor lzo_compr = {
        .compr_type = UBIFS_COMPR_LZO,
        .comp_mutex = &lzo_mutex,
-       .name = "LZO",
+       .name = "lzo",
        .capi_name = "lzo",
 };
 #else
 static struct ubifs_compressor lzo_compr = {
        .compr_type = UBIFS_COMPR_LZO,
-       .name = "LZO",
+       .name = "lzo",
 };
 #endif
 
@@ -108,7 +108,7 @@ void ubifs_compress(const void *in_buf, int in_len, void *out_buf, int *out_len,
        if (compr->comp_mutex)
                mutex_lock(compr->comp_mutex);
        err = crypto_comp_compress(compr->cc, in_buf, in_len, out_buf,
-                                  out_len);
+                                  (unsigned int *)out_len);
        if (compr->comp_mutex)
                mutex_unlock(compr->comp_mutex);
        if (unlikely(err)) {
@@ -119,10 +119,10 @@ void ubifs_compress(const void *in_buf, int in_len, void *out_buf, int *out_len,
        }
 
        /*
-        * Presently, we just require that compression results in less data,
-        * rather than any defined minimum compression ratio or amount.
+        * If the data compressed only slightly, it is better to leave it
+        * uncompressed to improve read speed.
         */
-       if (ALIGN(*out_len, 8) >= ALIGN(in_len, 8))
+       if (in_len - *out_len < UBIFS_MIN_COMPRESS_DIFF)
                goto no_compr;
 
        return;
@@ -172,7 +172,7 @@ int ubifs_decompress(const void *in_buf, int in_len, void *out_buf,
        if (compr->decomp_mutex)
                mutex_lock(compr->decomp_mutex);
        err = crypto_comp_decompress(compr->cc, in_buf, in_len, out_buf,
-                                    out_len);
+                                    (unsigned int *)out_len);
        if (compr->decomp_mutex)
                mutex_unlock(compr->decomp_mutex);
        if (err)
@@ -244,7 +244,7 @@ out_lzo:
 /**
  * ubifs_compressors_exit - de-initialize UBIFS compressors.
  */
-void __exit ubifs_compressors_exit(void)
+void ubifs_compressors_exit(void)
 {
        compr_exit(&lzo_compr);
        compr_exit(&zlib_compr);
index 510ffa0bbda4658559cf682a01145d4ff7f9231e..792c5a16c182e6b4f501e85041c7144e444370e8 100644 (file)
@@ -32,6 +32,8 @@
 #include "ubifs.h"
 #include <linux/module.h>
 #include <linux/moduleparam.h>
+#include <linux/debugfs.h>
+#include <linux/math64.h>
 
 #ifdef CONFIG_UBIFS_FS_DEBUG
 
@@ -596,7 +598,9 @@ void dbg_dump_budg(struct ubifs_info *c)
        struct rb_node *rb;
        struct ubifs_bud *bud;
        struct ubifs_gced_idx_leb *idx_gc;
+       long long available, outstanding, free;
 
+       ubifs_assert(spin_is_locked(&c->space_lock));
        spin_lock(&dbg_lock);
        printk(KERN_DEBUG "(pid %d) Budgeting info: budg_data_growth %lld, "
               "budg_dd_growth %lld, budg_idx_growth %lld\n", current->pid,
@@ -629,6 +633,17 @@ void dbg_dump_budg(struct ubifs_info *c)
                printk(KERN_DEBUG "\tGC'ed idx LEB %d unmap %d\n",
                       idx_gc->lnum, idx_gc->unmap);
        printk(KERN_DEBUG "\tcommit state %d\n", c->cmt_state);
+
+       /* Print budgeting predictions */
+       available = ubifs_calc_available(c, c->min_idx_lebs);
+       outstanding = c->budg_data_growth + c->budg_dd_growth;
+       if (available > outstanding)
+               free = ubifs_reported_space(c, available - outstanding);
+       else
+               free = 0;
+       printk(KERN_DEBUG "Budgeting predictions:\n");
+       printk(KERN_DEBUG "\tavailable: %lld, outstanding %lld, free %lld\n",
+              available, outstanding, free);
        spin_unlock(&dbg_lock);
 }
 
@@ -645,7 +660,8 @@ void dbg_dump_lprops(struct ubifs_info *c)
        struct ubifs_lprops lp;
        struct ubifs_lp_stats lst;
 
-       printk(KERN_DEBUG "(pid %d) Dumping LEB properties\n", current->pid);
+       printk(KERN_DEBUG "(pid %d) start dumping LEB properties\n",
+              current->pid);
        ubifs_get_lp_stats(c, &lst);
        dbg_dump_lstats(&lst);
 
@@ -656,6 +672,8 @@ void dbg_dump_lprops(struct ubifs_info *c)
 
                dbg_dump_lprop(c, &lp);
        }
+       printk(KERN_DEBUG "(pid %d) finish dumping LEB properties\n",
+              current->pid);
 }
 
 void dbg_dump_lpt_info(struct ubifs_info *c)
@@ -663,6 +681,7 @@ void dbg_dump_lpt_info(struct ubifs_info *c)
        int i;
 
        spin_lock(&dbg_lock);
+       printk(KERN_DEBUG "(pid %d) dumping LPT information\n", current->pid);
        printk(KERN_DEBUG "\tlpt_sz:        %lld\n", c->lpt_sz);
        printk(KERN_DEBUG "\tpnode_sz:      %d\n", c->pnode_sz);
        printk(KERN_DEBUG "\tnnode_sz:      %d\n", c->nnode_sz);
@@ -684,7 +703,8 @@ void dbg_dump_lpt_info(struct ubifs_info *c)
        printk(KERN_DEBUG "\tLPT root is at %d:%d\n", c->lpt_lnum, c->lpt_offs);
        printk(KERN_DEBUG "\tLPT head is at %d:%d\n",
               c->nhead_lnum, c->nhead_offs);
-       printk(KERN_DEBUG "\tLPT ltab is at %d:%d\n", c->ltab_lnum, c->ltab_offs);
+       printk(KERN_DEBUG "\tLPT ltab is at %d:%d\n",
+              c->ltab_lnum, c->ltab_offs);
        if (c->big_lpt)
                printk(KERN_DEBUG "\tLPT lsave is at %d:%d\n",
                       c->lsave_lnum, c->lsave_offs);
@@ -703,9 +723,9 @@ void dbg_dump_leb(const struct ubifs_info *c, int lnum)
        if (dbg_failure_mode)
                return;
 
-       printk(KERN_DEBUG "(pid %d) Dumping LEB %d\n", current->pid, lnum);
-
-       sleb = ubifs_scan(c, lnum, 0, c->dbg_buf);
+       printk(KERN_DEBUG "(pid %d) start dumping LEB %d\n",
+              current->pid, lnum);
+       sleb = ubifs_scan(c, lnum, 0, c->dbg->buf);
        if (IS_ERR(sleb)) {
                ubifs_err("scan error %d", (int)PTR_ERR(sleb));
                return;
@@ -721,6 +741,8 @@ void dbg_dump_leb(const struct ubifs_info *c, int lnum)
                dbg_dump_node(c, snod->node);
        }
 
+       printk(KERN_DEBUG "(pid %d) finish dumping LEB %d\n",
+              current->pid, lnum);
        ubifs_scan_destroy(sleb);
        return;
 }
@@ -768,7 +790,7 @@ void dbg_dump_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat)
 {
        int i;
 
-       printk(KERN_DEBUG "(pid %d) Dumping heap cat %d (%d elements)\n",
+       printk(KERN_DEBUG "(pid %d) start dumping heap cat %d (%d elements)\n",
               current->pid, cat, heap->cnt);
        for (i = 0; i < heap->cnt; i++) {
                struct ubifs_lprops *lprops = heap->arr[i];
@@ -777,6 +799,7 @@ void dbg_dump_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat)
                       "flags %d\n", i, lprops->lnum, lprops->hpos,
                       lprops->free, lprops->dirty, lprops->flags);
        }
+       printk(KERN_DEBUG "(pid %d) finish dumping heap\n", current->pid);
 }
 
 void dbg_dump_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
@@ -784,7 +807,7 @@ void dbg_dump_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
 {
        int i;
 
-       printk(KERN_DEBUG "(pid %d) Dumping pnode:\n", current->pid);
+       printk(KERN_DEBUG "(pid %d) dumping pnode:\n", current->pid);
        printk(KERN_DEBUG "\taddress %zx parent %zx cnext %zx\n",
               (size_t)pnode, (size_t)parent, (size_t)pnode->cnext);
        printk(KERN_DEBUG "\tflags %lu iip %d level %d num %d\n",
@@ -803,7 +826,7 @@ void dbg_dump_tnc(struct ubifs_info *c)
        int level;
 
        printk(KERN_DEBUG "\n");
-       printk(KERN_DEBUG "(pid %d) Dumping the TNC tree\n", current->pid);
+       printk(KERN_DEBUG "(pid %d) start dumping TNC tree\n", current->pid);
        znode = ubifs_tnc_levelorder_next(c->zroot.znode, NULL);
        level = znode->level;
        printk(KERN_DEBUG "== Level %d ==\n", level);
@@ -815,8 +838,7 @@ void dbg_dump_tnc(struct ubifs_info *c)
                dbg_dump_znode(c, znode);
                znode = ubifs_tnc_levelorder_next(c->zroot.znode, znode);
        }
-
-       printk(KERN_DEBUG "\n");
+       printk(KERN_DEBUG "(pid %d) finish dumping TNC tree\n", current->pid);
 }
 
 static int dump_znode(struct ubifs_info *c, struct ubifs_znode *znode,
@@ -992,8 +1014,8 @@ static int dbg_check_key_order(struct ubifs_info *c, struct ubifs_zbranch *zbr1,
                        zbr1->offs, DBGKEY(&key));
                dbg_err("but it should have key %s according to tnc",
                        DBGKEY(&zbr1->key));
-                       dbg_dump_node(c, dent1);
-                       goto out_free;
+               dbg_dump_node(c, dent1);
+               goto out_free;
        }
 
        key_read(c, &dent2->key, &key);
@@ -1002,8 +1024,8 @@ static int dbg_check_key_order(struct ubifs_info *c, struct ubifs_zbranch *zbr1,
                        zbr1->offs, DBGKEY(&key));
                dbg_err("but it should have key %s according to tnc",
                        DBGKEY(&zbr2->key));
-                       dbg_dump_node(c, dent2);
-                       goto out_free;
+               dbg_dump_node(c, dent2);
+               goto out_free;
        }
 
        nlen1 = le16_to_cpu(dent1->nlen);
@@ -1020,9 +1042,9 @@ static int dbg_check_key_order(struct ubifs_info *c, struct ubifs_zbranch *zbr1,
                dbg_err("bad order of colliding key %s",
                        DBGKEY(&key));
 
-       dbg_msg("first node at %d:%d\n", zbr1->lnum, zbr1->offs);
+       ubifs_msg("first node at %d:%d\n", zbr1->lnum, zbr1->offs);
        dbg_dump_node(c, dent1);
-       dbg_msg("second node at %d:%d\n", zbr2->lnum, zbr2->offs);
+       ubifs_msg("second node at %d:%d\n", zbr2->lnum, zbr2->offs);
        dbg_dump_node(c, dent2);
 
 out_free:
@@ -2097,13 +2119,13 @@ static int simple_rand(void)
        return (next >> 16) & 32767;
 }
 
-void dbg_failure_mode_registration(struct ubifs_info *c)
+static void failure_mode_init(struct ubifs_info *c)
 {
        struct failure_mode_info *fmi;
 
        fmi = kmalloc(sizeof(struct failure_mode_info), GFP_NOFS);
        if (!fmi) {
-               dbg_err("Failed to register failure mode - no memory");
+               ubifs_err("Failed to register failure mode - no memory");
                return;
        }
        fmi->c = c;
@@ -2112,7 +2134,7 @@ void dbg_failure_mode_registration(struct ubifs_info *c)
        spin_unlock(&fmi_lock);
 }
 
-void dbg_failure_mode_deregistration(struct ubifs_info *c)
+static void failure_mode_exit(struct ubifs_info *c)
 {
        struct failure_mode_info *fmi, *tmp;
 
@@ -2146,42 +2168,44 @@ static int in_failure_mode(struct ubi_volume_desc *desc)
        struct ubifs_info *c = dbg_find_info(desc);
 
        if (c && dbg_failure_mode)
-               return c->failure_mode;
+               return c->dbg->failure_mode;
        return 0;
 }
 
 static int do_fail(struct ubi_volume_desc *desc, int lnum, int write)
 {
        struct ubifs_info *c = dbg_find_info(desc);
+       struct ubifs_debug_info *d;
 
        if (!c || !dbg_failure_mode)
                return 0;
-       if (c->failure_mode)
+       d = c->dbg;
+       if (d->failure_mode)
                return 1;
-       if (!c->fail_cnt) {
+       if (!d->fail_cnt) {
                /* First call - decide delay to failure */
                if (chance(1, 2)) {
                        unsigned int delay = 1 << (simple_rand() >> 11);
 
                        if (chance(1, 2)) {
-                               c->fail_delay = 1;
-                               c->fail_timeout = jiffies +
+                               d->fail_delay = 1;
+                               d->fail_timeout = jiffies +
                                                  msecs_to_jiffies(delay);
                                dbg_rcvry("failing after %ums", delay);
                        } else {
-                               c->fail_delay = 2;
-                               c->fail_cnt_max = delay;
+                               d->fail_delay = 2;
+                               d->fail_cnt_max = delay;
                                dbg_rcvry("failing after %u calls", delay);
                        }
                }
-               c->fail_cnt += 1;
+               d->fail_cnt += 1;
        }
        /* Determine if failure delay has expired */
-       if (c->fail_delay == 1) {
-               if (time_before(jiffies, c->fail_timeout))
+       if (d->fail_delay == 1) {
+               if (time_before(jiffies, d->fail_timeout))
                        return 0;
-       } else if (c->fail_delay == 2)
-               if (c->fail_cnt++ < c->fail_cnt_max)
+       } else if (d->fail_delay == 2)
+               if (d->fail_cnt++ < d->fail_cnt_max)
                        return 0;
        if (lnum == UBIFS_SB_LNUM) {
                if (write) {
@@ -2239,7 +2263,7 @@ static int do_fail(struct ubi_volume_desc *desc, int lnum, int write)
                dbg_rcvry("failing in bud LEB %d commit not running", lnum);
        }
        ubifs_err("*** SETTING FAILURE MODE ON (LEB %d) ***", lnum);
-       c->failure_mode = 1;
+       d->failure_mode = 1;
        dump_stack();
        return 1;
 }
@@ -2344,4 +2368,181 @@ int dbg_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype)
        return 0;
 }
 
+/**
+ * ubifs_debugging_init - initialize UBIFS debugging.
+ * @c: UBIFS file-system description object
+ *
+ * This function initializes debugging-related data for the file system.
+ * Returns zero in case of success and a negative error code in case of
+ * failure.
+ */
+int ubifs_debugging_init(struct ubifs_info *c)
+{
+       c->dbg = kzalloc(sizeof(struct ubifs_debug_info), GFP_KERNEL);
+       if (!c->dbg)
+               return -ENOMEM;
+
+       c->dbg->buf = vmalloc(c->leb_size);
+       if (!c->dbg->buf)
+               goto out;
+
+       failure_mode_init(c);
+       return 0;
+
+out:
+       kfree(c->dbg);
+       return -ENOMEM;
+}
+
+/**
+ * ubifs_debugging_exit - free debugging data.
+ * @c: UBIFS file-system description object
+ */
+void ubifs_debugging_exit(struct ubifs_info *c)
+{
+       failure_mode_exit(c);
+       vfree(c->dbg->buf);
+       kfree(c->dbg);
+}
+
+/*
+ * Root directory for UBIFS stuff in debugfs. Contains sub-directories which
+ * contain the stuff specific to particular file-system mounts.
+ */
+static struct dentry *debugfs_rootdir;
+
+/**
+ * dbg_debugfs_init - initialize debugfs file-system.
+ *
+ * UBIFS uses debugfs file-system to expose various debugging knobs to
+ * user-space. This function creates "ubifs" directory in the debugfs
+ * file-system. Returns zero in case of success and a negative error code in
+ * case of failure.
+ */
+int dbg_debugfs_init(void)
+{
+       debugfs_rootdir = debugfs_create_dir("ubifs", NULL);
+       if (IS_ERR(debugfs_rootdir)) {
+               int err = PTR_ERR(debugfs_rootdir);
+               ubifs_err("cannot create \"ubifs\" debugfs directory, "
+                         "error %d\n", err);
+               return err;
+       }
+
+       return 0;
+}
+
+/**
+ * dbg_debugfs_exit - remove the "ubifs" directory from debugfs file-system.
+ */
+void dbg_debugfs_exit(void)
+{
+       debugfs_remove(debugfs_rootdir);
+}
+
+static int open_debugfs_file(struct inode *inode, struct file *file)
+{
+       file->private_data = inode->i_private;
+       return 0;
+}
+
+static ssize_t write_debugfs_file(struct file *file, const char __user *buf,
+                                 size_t count, loff_t *ppos)
+{
+       struct ubifs_info *c = file->private_data;
+       struct ubifs_debug_info *d = c->dbg;
+
+       if (file->f_path.dentry == d->dump_lprops)
+               dbg_dump_lprops(c);
+       else if (file->f_path.dentry == d->dump_budg) {
+               spin_lock(&c->space_lock);
+               dbg_dump_budg(c);
+               spin_unlock(&c->space_lock);
+       } else if (file->f_path.dentry == d->dump_tnc) {
+               mutex_lock(&c->tnc_mutex);
+               dbg_dump_tnc(c);
+               mutex_unlock(&c->tnc_mutex);
+       } else
+               return -EINVAL;
+
+       *ppos += count;
+       return count;
+}
+
+static const struct file_operations debugfs_fops = {
+       .open = open_debugfs_file,
+       .write = write_debugfs_file,
+       .owner = THIS_MODULE,
+};
+
+/**
+ * dbg_debugfs_init_fs - initialize debugfs for UBIFS instance.
+ * @c: UBIFS file-system description object
+ *
+ * This function creates all debugfs files for this instance of UBIFS. Returns
+ * zero in case of success and a negative error code in case of failure.
+ *
+ * Note, the only reason we have not merged this function with the
+ * 'ubifs_debugging_init()' function is because it is better to initialize
+ * debugfs interfaces at the very end of the mount process, and remove them at
+ * the very beginning of the mount process.
+ */
+int dbg_debugfs_init_fs(struct ubifs_info *c)
+{
+       int err;
+       const char *fname;
+       struct dentry *dent;
+       struct ubifs_debug_info *d = c->dbg;
+
+       sprintf(d->debugfs_dir_name, "ubi%d_%d", c->vi.ubi_num, c->vi.vol_id);
+       d->debugfs_dir = debugfs_create_dir(d->debugfs_dir_name,
+                                             debugfs_rootdir);
+       if (IS_ERR(d->debugfs_dir)) {
+               err = PTR_ERR(d->debugfs_dir);
+               ubifs_err("cannot create \"%s\" debugfs directory, error %d\n",
+                         d->debugfs_dir_name, err);
+               goto out;
+       }
+
+       fname = "dump_lprops";
+       dent = debugfs_create_file(fname, S_IWUGO, d->debugfs_dir, c,
+                                  &debugfs_fops);
+       if (IS_ERR(dent))
+               goto out_remove;
+       d->dump_lprops = dent;
+
+       fname = "dump_budg";
+       dent = debugfs_create_file(fname, S_IWUGO, d->debugfs_dir, c,
+                                  &debugfs_fops);
+       if (IS_ERR(dent))
+               goto out_remove;
+       d->dump_budg = dent;
+
+       fname = "dump_tnc";
+       dent = debugfs_create_file(fname, S_IWUGO, d->debugfs_dir, c,
+                                  &debugfs_fops);
+       if (IS_ERR(dent))
+               goto out_remove;
+       d->dump_tnc = dent;
+
+       return 0;
+
+out_remove:
+       err = PTR_ERR(dent);
+       ubifs_err("cannot create \"%s\" debugfs directory, error %d\n",
+                 fname, err);
+       debugfs_remove_recursive(d->debugfs_dir);
+out:
+       return err;
+}
+
+/**
+ * dbg_debugfs_exit_fs - remove all debugfs files.
+ * @c: UBIFS file-system description object
+ */
+void dbg_debugfs_exit_fs(struct ubifs_info *c)
+{
+       debugfs_remove_recursive(c->dbg->debugfs_dir);
+}
+
 #endif /* CONFIG_UBIFS_FS_DEBUG */
index 33d6b95071e4589f94c17530d0d14320920c47af..9820d6999f7e0b2704325713cba2150a7c4b0cef 100644 (file)
 
 #ifdef CONFIG_UBIFS_FS_DEBUG
 
-#define UBIFS_DBG(op) op
+/**
+ * ubifs_debug_info - per-FS debugging information.
+ * @buf: a buffer of LEB size, used for various purposes
+ * @old_zroot: old index root - used by 'dbg_check_old_index()'
+ * @old_zroot_level: old index root level - used by 'dbg_check_old_index()'
+ * @old_zroot_sqnum: old index root sqnum - used by 'dbg_check_old_index()'
+ * @failure_mode: failure mode for recovery testing
+ * @fail_delay: 0=>don't delay, 1=>delay a time, 2=>delay a number of calls
+ * @fail_timeout: time in jiffies when delay of failure mode expires
+ * @fail_cnt: current number of calls to failure mode I/O functions
+ * @fail_cnt_max: number of calls by which to delay failure mode
+ * @chk_lpt_sz: used by LPT tree size checker
+ * @chk_lpt_sz2: used by LPT tree size checker
+ * @chk_lpt_wastage: used by LPT tree size checker
+ * @chk_lpt_lebs: used by LPT tree size checker
+ * @new_nhead_offs: used by LPT tree size checker
+ * @new_ihead_lnum: used by debugging to check ihead_lnum
+ * @new_ihead_offs: used by debugging to check ihead_offs
+ *
+ * debugfs_dir_name: name of debugfs directory containing this file-system's
+ *                   files
+ * debugfs_dir: direntry object of the file-system debugfs directory
+ * dump_lprops: "dump lprops" debugfs knob
+ * dump_budg: "dump budgeting information" debugfs knob
+ * dump_tnc: "dump TNC" debugfs knob
+ */
+struct ubifs_debug_info {
+       void *buf;
+       struct ubifs_zbranch old_zroot;
+       int old_zroot_level;
+       unsigned long long old_zroot_sqnum;
+       int failure_mode;
+       int fail_delay;
+       unsigned long fail_timeout;
+       unsigned int fail_cnt;
+       unsigned int fail_cnt_max;
+       long long chk_lpt_sz;
+       long long chk_lpt_sz2;
+       long long chk_lpt_wastage;
+       int chk_lpt_lebs;
+       int new_nhead_offs;
+       int new_ihead_lnum;
+       int new_ihead_offs;
+
+       char debugfs_dir_name[100];
+       struct dentry *debugfs_dir;
+       struct dentry *dump_lprops;
+       struct dentry *dump_budg;
+       struct dentry *dump_tnc;
+};
 
 #define ubifs_assert(expr) do {                                                \
        if (unlikely(!(expr))) {                                               \
@@ -211,14 +260,18 @@ extern unsigned int ubifs_msg_flags;
 extern unsigned int ubifs_chk_flags;
 extern unsigned int ubifs_tst_flags;
 
-/* Dump functions */
+int ubifs_debugging_init(struct ubifs_info *c);
+void ubifs_debugging_exit(struct ubifs_info *c);
 
+/* Dump functions */
 const char *dbg_ntype(int type);
 const char *dbg_cstate(int cmt_state);
 const char *dbg_get_key_dump(const struct ubifs_info *c,
                             const union ubifs_key *key);
 void dbg_dump_inode(const struct ubifs_info *c, const struct inode *inode);
 void dbg_dump_node(const struct ubifs_info *c, const void *node);
+void dbg_dump_lpt_node(const struct ubifs_info *c, void *node, int lnum,
+                      int offs);
 void dbg_dump_budget_req(const struct ubifs_budget_req *req);
 void dbg_dump_lstats(const struct ubifs_lp_stats *lst);
 void dbg_dump_budg(struct ubifs_info *c);
@@ -233,9 +286,9 @@ void dbg_dump_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
                    struct ubifs_nnode *parent, int iip);
 void dbg_dump_tnc(struct ubifs_info *c);
 void dbg_dump_index(struct ubifs_info *c);
+void dbg_dump_lpt_lebs(const struct ubifs_info *c);
 
 /* Checking helper functions */
-
 typedef int (*dbg_leaf_callback)(struct ubifs_info *c,
                                 struct ubifs_zbranch *zbr, void *priv);
 typedef int (*dbg_znode_callback)(struct ubifs_info *c,
@@ -274,9 +327,6 @@ int dbg_force_in_the_gaps(void);
 
 #define dbg_failure_mode (ubifs_tst_flags & UBIFS_TST_RCVRY)
 
-void dbg_failure_mode_registration(struct ubifs_info *c);
-void dbg_failure_mode_deregistration(struct ubifs_info *c);
-
 #ifndef UBIFS_DBG_PRESERVE_UBI
 
 #define ubi_leb_read   dbg_leb_read
@@ -318,9 +368,13 @@ static inline int dbg_change(struct ubi_volume_desc *desc, int lnum,
        return dbg_leb_change(desc, lnum, buf, len, UBI_UNKNOWN);
 }
 
-#else /* !CONFIG_UBIFS_FS_DEBUG */
+/* Debugfs-related stuff */
+int dbg_debugfs_init(void);
+void dbg_debugfs_exit(void);
+int dbg_debugfs_init_fs(struct ubifs_info *c);
+void dbg_debugfs_exit_fs(struct ubifs_info *c);
 
-#define UBIFS_DBG(op)
+#else /* !CONFIG_UBIFS_FS_DEBUG */
 
 /* Use "if (0)" to make compiler check arguments even if debugging is off */
 #define ubifs_assert(expr)  do {                                               \
@@ -360,23 +414,28 @@ static inline int dbg_change(struct ubi_volume_desc *desc, int lnum,
 #define DBGKEY(key)  ((char *)(key))
 #define DBGKEY1(key) ((char *)(key))
 
-#define dbg_ntype(type)                       ""
-#define dbg_cstate(cmt_state)                 ""
-#define dbg_get_key_dump(c, key)              ({})
-#define dbg_dump_inode(c, inode)              ({})
-#define dbg_dump_node(c, node)                ({})
-#define dbg_dump_budget_req(req)              ({})
-#define dbg_dump_lstats(lst)                  ({})
-#define dbg_dump_budg(c)                      ({})
-#define dbg_dump_lprop(c, lp)                 ({})
-#define dbg_dump_lprops(c)                    ({})
-#define dbg_dump_lpt_info(c)                  ({})
-#define dbg_dump_leb(c, lnum)                 ({})
-#define dbg_dump_znode(c, znode)              ({})
-#define dbg_dump_heap(c, heap, cat)           ({})
-#define dbg_dump_pnode(c, pnode, parent, iip) ({})
-#define dbg_dump_tnc(c)                       ({})
-#define dbg_dump_index(c)                     ({})
+#define ubifs_debugging_init(c)                0
+#define ubifs_debugging_exit(c)                ({})
+
+#define dbg_ntype(type)                        ""
+#define dbg_cstate(cmt_state)                  ""
+#define dbg_get_key_dump(c, key)               ({})
+#define dbg_dump_inode(c, inode)               ({})
+#define dbg_dump_node(c, node)                 ({})
+#define dbg_dump_lpt_node(c, node, lnum, offs) ({})
+#define dbg_dump_budget_req(req)               ({})
+#define dbg_dump_lstats(lst)                   ({})
+#define dbg_dump_budg(c)                       ({})
+#define dbg_dump_lprop(c, lp)                  ({})
+#define dbg_dump_lprops(c)                     ({})
+#define dbg_dump_lpt_info(c)                   ({})
+#define dbg_dump_leb(c, lnum)                  ({})
+#define dbg_dump_znode(c, znode)               ({})
+#define dbg_dump_heap(c, heap, cat)            ({})
+#define dbg_dump_pnode(c, pnode, parent, iip)  ({})
+#define dbg_dump_tnc(c)                        ({})
+#define dbg_dump_index(c)                      ({})
+#define dbg_dump_lpt_lebs(c)                   ({})
 
 #define dbg_walk_index(c, leaf_cb, znode_cb, priv) 0
 #define dbg_old_index_check_init(c, zroot)         0
@@ -396,9 +455,11 @@ static inline int dbg_change(struct ubi_volume_desc *desc, int lnum,
 #define dbg_force_in_the_gaps_enabled              0
 #define dbg_force_in_the_gaps()                    0
 #define dbg_failure_mode                           0
-#define dbg_failure_mode_registration(c)           ({})
-#define dbg_failure_mode_deregistration(c)         ({})
 
-#endif /* !CONFIG_UBIFS_FS_DEBUG */
+#define dbg_debugfs_init()                         0
+#define dbg_debugfs_exit()
+#define dbg_debugfs_init_fs(c)                     0
+#define dbg_debugfs_exit_fs(c)                     0
 
+#endif /* !CONFIG_UBIFS_FS_DEBUG */
 #endif /* !__UBIFS_DEBUG_H__ */
index 2624411d9758d11023c938418f8a6a7938066ff5..bf37374567fa745c63c9f4698d929811544af0e3 100644 (file)
@@ -72,8 +72,8 @@ static int read_block(struct inode *inode, void *addr, unsigned int block,
                return err;
        }
 
-       ubifs_assert(le64_to_cpu(dn->ch.sqnum) > ubifs_inode(inode)->creat_sqnum);
-
+       ubifs_assert(le64_to_cpu(dn->ch.sqnum) >
+                    ubifs_inode(inode)->creat_sqnum);
        len = le32_to_cpu(dn->size);
        if (len <= 0 || len > UBIFS_BLOCK_SIZE)
                goto dump;
@@ -219,7 +219,8 @@ static void release_existing_page_budget(struct ubifs_info *c)
 }
 
 static int write_begin_slow(struct address_space *mapping,
-                           loff_t pos, unsigned len, struct page **pagep)
+                           loff_t pos, unsigned len, struct page **pagep,
+                           unsigned flags)
 {
        struct inode *inode = mapping->host;
        struct ubifs_info *c = inode->i_sb->s_fs_info;
@@ -247,14 +248,14 @@ static int write_begin_slow(struct address_space *mapping,
        if (unlikely(err))
                return err;
 
-       page = __grab_cache_page(mapping, index);
+       page = grab_cache_page_write_begin(mapping, index, flags);
        if (unlikely(!page)) {
                ubifs_release_budget(c, &req);
                return -ENOMEM;
        }
 
        if (!PageUptodate(page)) {
-               if (!(pos & PAGE_CACHE_MASK) && len == PAGE_CACHE_SIZE)
+               if (!(pos & ~PAGE_CACHE_MASK) && len == PAGE_CACHE_SIZE)
                        SetPageChecked(page);
                else {
                        err = do_readpage(page);
@@ -438,13 +439,13 @@ static int ubifs_write_begin(struct file *file, struct address_space *mapping,
                return -EROFS;
 
        /* Try out the fast-path part first */
-       page = __grab_cache_page(mapping, index);
+       page = grab_cache_page_write_begin(mapping, index, flags);
        if (unlikely(!page))
                return -ENOMEM;
 
        if (!PageUptodate(page)) {
                /* The page is not loaded from the flash */
-               if (!(pos & PAGE_CACHE_MASK) && len == PAGE_CACHE_SIZE)
+               if (!(pos & ~PAGE_CACHE_MASK) && len == PAGE_CACHE_SIZE)
                        /*
                         * We change whole page so no need to load it. But we
                         * have to set the @PG_checked flag to make the further
@@ -483,7 +484,7 @@ static int ubifs_write_begin(struct file *file, struct address_space *mapping,
                unlock_page(page);
                page_cache_release(page);
 
-               return write_begin_slow(mapping, pos, len, pagep);
+               return write_begin_slow(mapping, pos, len, pagep, flags);
        }
 
        /*
index 5e82cffe969503594101c9f5e418d3d77ce6064c..6db7a6be6c9732a8a14cecc8ea60683522493442 100644 (file)
@@ -154,6 +154,7 @@ long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        case FS_IOC_GETFLAGS:
                flags = ubifs2ioctl(ubifs_inode(inode)->flags);
 
+               dbg_gen("get flags: %#x, i_flags %#x", flags, inode->i_flags);
                return put_user(flags, (int __user *) arg);
 
        case FS_IOC_SETFLAGS: {
@@ -176,6 +177,7 @@ long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                err = mnt_want_write(file->f_path.mnt);
                if (err)
                        return err;
+               dbg_gen("set flags: %#x, i_flags %#x", flags, inode->i_flags);
                err = setflags(inode, flags);
                mnt_drop_write(file->f_path.mnt);
                return err;
index f91b745908ea595ac94bd25b86368d5515149be0..10ae25b7d1dbe4e4ed84c8d6f4d835a3cd40f37c 100644 (file)
@@ -704,7 +704,7 @@ int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode,
        data->size = cpu_to_le32(len);
        zero_data_node_unused(data);
 
-       if (!(ui->flags && UBIFS_COMPR_FL))
+       if (!(ui->flags & UBIFS_COMPR_FL))
                /* Compression is disabled for this inode */
                compr_type = UBIFS_COMPR_NONE;
        else
@@ -1220,7 +1220,7 @@ int ubifs_jnl_truncate(struct ubifs_info *c, const struct inode *inode,
        data_key_init(c, &key, inum, blk);
 
        bit = old_size & (UBIFS_BLOCK_SIZE - 1);
-       blk = (old_size >> UBIFS_BLOCK_SHIFT) - (bit ? 0: 1);
+       blk = (old_size >> UBIFS_BLOCK_SHIFT) - (bit ? 0 : 1);
        data_key_init(c, &to_key, inum, blk);
 
        err = ubifs_tnc_remove_range(c, &key, &to_key);
index 3f1f16bc25c99ba1e019c940030c1fa48b7217fa..efb3430a2581c4b723cafc6f846ed7b5841ed933 100644 (file)
 #ifndef __UBIFS_KEY_H__
 #define __UBIFS_KEY_H__
 
+/**
+ * key_mask_hash - mask a valid hash value.
+ * @val: value to be masked
+ *
+ * We use hash values as offset in directories, so values %0 and %1 are
+ * reserved for "." and "..". %2 is reserved for "end of readdir" marker. This
+ * function makes sure the reserved values are not used.
+ */
+static inline uint32_t key_mask_hash(uint32_t hash)
+{
+       hash &= UBIFS_S_KEY_HASH_MASK;
+       if (unlikely(hash <= 2))
+               hash += 3;
+       return hash;
+}
+
 /**
  * key_r5_hash - R5 hash function (borrowed from reiserfs).
  * @s: direntry name
@@ -54,16 +70,7 @@ static inline uint32_t key_r5_hash(const char *s, int len)
                str++;
        }
 
-       a &= UBIFS_S_KEY_HASH_MASK;
-
-       /*
-        * We use hash values as offset in directories, so values %0 and %1 are
-        * reserved for "." and "..". %2 is reserved for "end of readdir"
-        * marker.
-        */
-       if (unlikely(a >= 0 && a <= 2))
-               a += 3;
-       return a;
+       return key_mask_hash(a);
 }
 
 /**
@@ -77,10 +84,7 @@ static inline uint32_t key_test_hash(const char *str, int len)
 
        len = min_t(uint32_t, len, 4);
        memcpy(&a, str, len);
-       a &= UBIFS_S_KEY_HASH_MASK;
-       if (unlikely(a >= 0 && a <= 2))
-               a += 3;
-       return a;
+       return key_mask_hash(a);
 }
 
 /**
index f27176e9b70d7208074e0825065f3a79618f9940..dfd2bcece27a865de970f3d4333468c5ebb5db66 100644 (file)
@@ -520,13 +520,13 @@ static int is_lprops_dirty(struct ubifs_info *c, struct ubifs_lprops *lprops)
  * @flags: new flags
  * @idx_gc_cnt: change to the count of idx_gc list
  *
- * This function changes LEB properties. This function does not change a LEB
- * property (@free, @dirty or @flag) if the value passed is %LPROPS_NC.
+ * This function changes LEB properties (@free, @dirty or @flag). However, the
+ * property which has the %LPROPS_NC value is not changed. Returns a pointer to
+ * the updated LEB properties on success and a negative error code on failure.
  *
- * This function returns a pointer to the updated LEB properties on success
- * and a negative error code on failure. N.B. the LEB properties may have had to
- * be copied (due to COW) and consequently the pointer returned may not be the
- * same as the pointer passed.
+ * Note, the LEB properties may have had to be copied (due to COW) and
+ * consequently the pointer returned may not be the same as the pointer
+ * passed.
  */
 const struct ubifs_lprops *ubifs_change_lp(struct ubifs_info *c,
                                           const struct ubifs_lprops *lp,
@@ -1088,7 +1088,7 @@ static int scan_check_cb(struct ubifs_info *c,
                }
        }
 
-       sleb = ubifs_scan(c, lnum, 0, c->dbg_buf);
+       sleb = ubifs_scan(c, lnum, 0, c->dbg->buf);
        if (IS_ERR(sleb)) {
                /*
                 * After an unclean unmount, empty and freeable LEBs
index db8bd0e518b21151c5d6f11eff7d40bac62fc9ff..b2792e84d2452fd37e27991b42c1ab5754044de4 100644 (file)
  * can be written into a single eraseblock. In that case, garbage collection
  * consists of just writing the whole table, which therefore makes all other
  * eraseblocks reusable. In the case of the big model, dirty eraseblocks are
- * selected for garbage collection, which consists are marking the nodes in
+ * selected for garbage collection, which consists of marking the clean nodes in
  * that LEB as dirty, and then only the dirty nodes are written out. Also, in
  * the case of the big model, a table of LEB numbers is saved so that the entire
  * LPT does not to be scanned looking for empty eraseblocks when UBIFS is first
  * mounted.
  */
 
-#include <linux/crc16.h>
 #include "ubifs.h"
+#include <linux/crc16.h>
+#include <linux/math64.h>
 
 /**
  * do_calc_lpt_geom - calculate sizes for the LPT area.
@@ -135,15 +136,13 @@ static void do_calc_lpt_geom(struct ubifs_info *c)
 int ubifs_calc_lpt_geom(struct ubifs_info *c)
 {
        int lebs_needed;
-       uint64_t sz;
+       long long sz;
 
        do_calc_lpt_geom(c);
 
        /* Verify that lpt_lebs is big enough */
        sz = c->lpt_sz * 2; /* Must have at least 2 times the size */
-       sz += c->leb_size - 1;
-       do_div(sz, c->leb_size);
-       lebs_needed = sz;
+       lebs_needed = div_u64(sz + c->leb_size - 1, c->leb_size);
        if (lebs_needed > c->lpt_lebs) {
                ubifs_err("too few LPT LEBs");
                return -EINVAL;
@@ -156,7 +155,6 @@ int ubifs_calc_lpt_geom(struct ubifs_info *c)
        }
 
        c->check_lpt_free = c->big_lpt;
-
        return 0;
 }
 
@@ -176,7 +174,7 @@ static int calc_dflt_lpt_geom(struct ubifs_info *c, int *main_lebs,
                              int *big_lpt)
 {
        int i, lebs_needed;
-       uint64_t sz;
+       long long sz;
 
        /* Start by assuming the minimum number of LPT LEBs */
        c->lpt_lebs = UBIFS_MIN_LPT_LEBS;
@@ -203,9 +201,7 @@ static int calc_dflt_lpt_geom(struct ubifs_info *c, int *main_lebs,
        /* Now check there are enough LPT LEBs */
        for (i = 0; i < 64 ; i++) {
                sz = c->lpt_sz * 4; /* Allow 4 times the size */
-               sz += c->leb_size - 1;
-               do_div(sz, c->leb_size);
-               lebs_needed = sz;
+               lebs_needed = div_u64(sz + c->leb_size - 1, c->leb_size);
                if (lebs_needed > c->lpt_lebs) {
                        /* Not enough LPT LEBs so try again with more */
                        c->lpt_lebs = lebs_needed;
@@ -558,7 +554,7 @@ static int calc_nnode_num(int row, int col)
  * This function calculates and returns the nnode number based on the parent's
  * nnode number and the index in parent.
  */
-static int calc_nnode_num_from_parent(struct ubifs_info *c,
+static int calc_nnode_num_from_parent(const struct ubifs_info *c,
                                      struct ubifs_nnode *parent, int iip)
 {
        int num, shft;
@@ -583,7 +579,7 @@ static int calc_nnode_num_from_parent(struct ubifs_info *c,
  * This function calculates and returns the pnode number based on the parent's
  * nnode number and the index in parent.
  */
-static int calc_pnode_num_from_parent(struct ubifs_info *c,
+static int calc_pnode_num_from_parent(const struct ubifs_info *c,
                                      struct ubifs_nnode *parent, int iip)
 {
        int i, n = c->lpt_hght - 1, pnum = parent->num, num = 0;
@@ -966,7 +962,7 @@ static int check_lpt_type(uint8_t **addr, int *pos, int type)
  *
  * This function returns %0 on success and a negative error code on failure.
  */
-static int unpack_pnode(struct ubifs_info *c, void *buf,
+static int unpack_pnode(const struct ubifs_info *c, void *buf,
                        struct ubifs_pnode *pnode)
 {
        uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
@@ -996,15 +992,15 @@ static int unpack_pnode(struct ubifs_info *c, void *buf,
 }
 
 /**
- * unpack_nnode - unpack a nnode.
+ * ubifs_unpack_nnode - unpack a nnode.
  * @c: UBIFS file-system description object
  * @buf: buffer containing packed nnode to unpack
  * @nnode: nnode structure to fill
  *
  * This function returns %0 on success and a negative error code on failure.
  */
-static int unpack_nnode(struct ubifs_info *c, void *buf,
-                       struct ubifs_nnode *nnode)
+int ubifs_unpack_nnode(const struct ubifs_info *c, void *buf,
+                      struct ubifs_nnode *nnode)
 {
        uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
        int i, pos = 0, err;
@@ -1036,7 +1032,7 @@ static int unpack_nnode(struct ubifs_info *c, void *buf,
  *
  * This function returns %0 on success and a negative error code on failure.
  */
-static int unpack_ltab(struct ubifs_info *c, void *buf)
+static int unpack_ltab(const struct ubifs_info *c, void *buf)
 {
        uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
        int i, pos = 0, err;
@@ -1068,7 +1064,7 @@ static int unpack_ltab(struct ubifs_info *c, void *buf)
  *
  * This function returns %0 on success and a negative error code on failure.
  */
-static int unpack_lsave(struct ubifs_info *c, void *buf)
+static int unpack_lsave(const struct ubifs_info *c, void *buf)
 {
        uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
        int i, pos = 0, err;
@@ -1096,7 +1092,7 @@ static int unpack_lsave(struct ubifs_info *c, void *buf)
  *
  * This function returns %0 on success and a negative error code on failure.
  */
-static int validate_nnode(struct ubifs_info *c, struct ubifs_nnode *nnode,
+static int validate_nnode(const struct ubifs_info *c, struct ubifs_nnode *nnode,
                          struct ubifs_nnode *parent, int iip)
 {
        int i, lvl, max_offs;
@@ -1140,7 +1136,7 @@ static int validate_nnode(struct ubifs_info *c, struct ubifs_nnode *nnode,
  *
  * This function returns %0 on success and a negative error code on failure.
  */
-static int validate_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
+static int validate_pnode(const struct ubifs_info *c, struct ubifs_pnode *pnode,
                          struct ubifs_nnode *parent, int iip)
 {
        int i;
@@ -1174,7 +1170,8 @@ static int validate_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
  * This function calculates the LEB numbers for the LEB properties it contains
  * based on the pnode number.
  */
-static void set_pnode_lnum(struct ubifs_info *c, struct ubifs_pnode *pnode)
+static void set_pnode_lnum(const struct ubifs_info *c,
+                          struct ubifs_pnode *pnode)
 {
        int i, lnum;
 
@@ -1227,7 +1224,7 @@ int ubifs_read_nnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip)
                err = ubi_read(c->ubi, lnum, buf, offs, c->nnode_sz);
                if (err)
                        goto out;
-               err = unpack_nnode(c, buf, nnode);
+               err = ubifs_unpack_nnode(c, buf, nnode);
                if (err)
                        goto out;
        }
@@ -1816,7 +1813,7 @@ static struct ubifs_nnode *scan_get_nnode(struct ubifs_info *c,
                               c->nnode_sz);
                if (err)
                        return ERR_PTR(err);
-               err = unpack_nnode(c, buf, nnode);
+               err = ubifs_unpack_nnode(c, buf, nnode);
                if (err)
                        return ERR_PTR(err);
        }
index a41434b427854e66527775ca3e6fdfcb89a332bd..96ca957071754067f7aeddf5dcecc2b0a2b12116 100644 (file)
@@ -320,6 +320,8 @@ no_space:
        dbg_err("LPT out of space at LEB %d:%d needing %d, done_ltab %d, "
                "done_lsave %d", lnum, offs, len, done_ltab, done_lsave);
        dbg_dump_lpt_info(c);
+       dbg_dump_lpt_lebs(c);
+       dump_stack();
        return err;
 }
 
@@ -546,8 +548,10 @@ static int write_cnodes(struct ubifs_info *c)
 no_space:
        ubifs_err("LPT out of space mismatch");
        dbg_err("LPT out of space mismatch at LEB %d:%d needing %d, done_ltab "
-               "%d, done_lsave %d", lnum, offs, len, done_ltab, done_lsave);
+               "%d, done_lsave %d", lnum, offs, len, done_ltab, done_lsave);
        dbg_dump_lpt_info(c);
+       dbg_dump_lpt_lebs(c);
+       dump_stack();
        return err;
 }
 
@@ -749,7 +753,7 @@ static void lpt_tgc_start(struct ubifs_info *c)
  * LPT trivial garbage collection is where a LPT LEB contains only dirty and
  * free space and so may be reused as soon as the next commit is completed.
  * This function is called after the commit is completed (master node has been
- * written) and unmaps LPT LEBs that were marked for trivial GC.
+ * written) and un-maps LPT LEBs that were marked for trivial GC.
  */
 static int lpt_tgc_end(struct ubifs_info *c)
 {
@@ -1025,7 +1029,7 @@ static int make_node_dirty(struct ubifs_info *c, int node_type, int node_num,
  * @c: UBIFS file-system description object
  * @node_type: LPT node type
  */
-static int get_lpt_node_len(struct ubifs_info *c, int node_type)
+static int get_lpt_node_len(const struct ubifs_info *c, int node_type)
 {
        switch (node_type) {
        case UBIFS_LPT_NNODE:
@@ -1046,7 +1050,7 @@ static int get_lpt_node_len(struct ubifs_info *c, int node_type)
  * @buf: buffer
  * @len: length of buffer
  */
-static int get_pad_len(struct ubifs_info *c, uint8_t *buf, int len)
+static int get_pad_len(const struct ubifs_info *c, uint8_t *buf, int len)
 {
        int offs, pad_len;
 
@@ -1063,7 +1067,8 @@ static int get_pad_len(struct ubifs_info *c, uint8_t *buf, int len)
  * @buf: buffer
  * @node_num: node number is returned here
  */
-static int get_lpt_node_type(struct ubifs_info *c, uint8_t *buf, int *node_num)
+static int get_lpt_node_type(const struct ubifs_info *c, uint8_t *buf,
+                            int *node_num)
 {
        uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
        int pos = 0, node_type;
@@ -1081,7 +1086,7 @@ static int get_lpt_node_type(struct ubifs_info *c, uint8_t *buf, int *node_num)
  *
  * This function returns %1 if the buffer contains a node or %0 if it does not.
  */
-static int is_a_node(struct ubifs_info *c, uint8_t *buf, int len)
+static int is_a_node(const struct ubifs_info *c, uint8_t *buf, int len)
 {
        uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
        int pos = 0, node_type, node_len;
@@ -1105,7 +1110,6 @@ static int is_a_node(struct ubifs_info *c, uint8_t *buf, int len)
        return 1;
 }
 
-
 /**
  * lpt_gc_lnum - garbage collect a LPT LEB.
  * @c: UBIFS file-system description object
@@ -1463,7 +1467,7 @@ void ubifs_lpt_free(struct ubifs_info *c, int wr_only)
 #ifdef CONFIG_UBIFS_FS_DEBUG
 
 /**
- * dbg_is_all_ff - determine if a buffer contains only 0xff bytes.
+ * dbg_is_all_ff - determine if a buffer contains only 0xFF bytes.
  * @buf: buffer
  * @len: buffer length
  */
@@ -1488,7 +1492,7 @@ static int dbg_is_nnode_dirty(struct ubifs_info *c, int lnum, int offs)
        struct ubifs_nnode *nnode;
        int hght;
 
-       /* Entire tree is in memory so first_nnode / next_nnode are ok */
+       /* Entire tree is in memory so first_nnode / next_nnode are OK */
        nnode = first_nnode(c, &hght);
        for (; nnode; nnode = next_nnode(c, nnode, &hght)) {
                struct ubifs_nbranch *branch;
@@ -1602,7 +1606,10 @@ static int dbg_check_ltab_lnum(struct ubifs_info *c, int lnum)
 {
        int err, len = c->leb_size, dirty = 0, node_type, node_num, node_len;
        int ret;
-       void *buf = c->dbg_buf;
+       void *buf = c->dbg->buf;
+
+       if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS))
+               return 0;
 
        dbg_lp("LEB %d", lnum);
        err = ubi_read(c->ubi, lnum, buf, 0, c->leb_size);
@@ -1704,6 +1711,9 @@ int dbg_chk_lpt_free_spc(struct ubifs_info *c)
        long long free = 0;
        int i;
 
+       if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS))
+               return 0;
+
        for (i = 0; i < c->lpt_lebs; i++) {
                if (c->ltab[i].tgc || c->ltab[i].cmt)
                        continue;
@@ -1716,6 +1726,8 @@ int dbg_chk_lpt_free_spc(struct ubifs_info *c)
                dbg_err("LPT space error: free %lld lpt_sz %lld",
                        free, c->lpt_sz);
                dbg_dump_lpt_info(c);
+               dbg_dump_lpt_lebs(c);
+               dump_stack();
                return -EINVAL;
        }
        return 0;
@@ -1731,15 +1743,19 @@ int dbg_chk_lpt_free_spc(struct ubifs_info *c)
  */
 int dbg_chk_lpt_sz(struct ubifs_info *c, int action, int len)
 {
+       struct ubifs_debug_info *d = c->dbg;
        long long chk_lpt_sz, lpt_sz;
        int err = 0;
 
+       if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS))
+               return 0;
+
        switch (action) {
        case 0:
-               c->chk_lpt_sz = 0;
-               c->chk_lpt_sz2 = 0;
-               c->chk_lpt_lebs = 0;
-               c->chk_lpt_wastage = 0;
+               d->chk_lpt_sz = 0;
+               d->chk_lpt_sz2 = 0;
+               d->chk_lpt_lebs = 0;
+               d->chk_lpt_wastage = 0;
                if (c->dirty_pn_cnt > c->pnode_cnt) {
                        dbg_err("dirty pnodes %d exceed max %d",
                                c->dirty_pn_cnt, c->pnode_cnt);
@@ -1752,35 +1768,35 @@ int dbg_chk_lpt_sz(struct ubifs_info *c, int action, int len)
                }
                return err;
        case 1:
-               c->chk_lpt_sz += len;
+               d->chk_lpt_sz += len;
                return 0;
        case 2:
-               c->chk_lpt_sz += len;
-               c->chk_lpt_wastage += len;
-               c->chk_lpt_lebs += 1;
+               d->chk_lpt_sz += len;
+               d->chk_lpt_wastage += len;
+               d->chk_lpt_lebs += 1;
                return 0;
        case 3:
                chk_lpt_sz = c->leb_size;
-               chk_lpt_sz *= c->chk_lpt_lebs;
+               chk_lpt_sz *= d->chk_lpt_lebs;
                chk_lpt_sz += len - c->nhead_offs;
-               if (c->chk_lpt_sz != chk_lpt_sz) {
+               if (d->chk_lpt_sz != chk_lpt_sz) {
                        dbg_err("LPT wrote %lld but space used was %lld",
-                               c->chk_lpt_sz, chk_lpt_sz);
+                               d->chk_lpt_sz, chk_lpt_sz);
                        err = -EINVAL;
                }
-               if (c->chk_lpt_sz > c->lpt_sz) {
+               if (d->chk_lpt_sz > c->lpt_sz) {
                        dbg_err("LPT wrote %lld but lpt_sz is %lld",
-                               c->chk_lpt_sz, c->lpt_sz);
+                               d->chk_lpt_sz, c->lpt_sz);
                        err = -EINVAL;
                }
-               if (c->chk_lpt_sz2 && c->chk_lpt_sz != c->chk_lpt_sz2) {
+               if (d->chk_lpt_sz2 && d->chk_lpt_sz != d->chk_lpt_sz2) {
                        dbg_err("LPT layout size %lld but wrote %lld",
-                               c->chk_lpt_sz, c->chk_lpt_sz2);
+                               d->chk_lpt_sz, d->chk_lpt_sz2);
                        err = -EINVAL;
                }
-               if (c->chk_lpt_sz2 && c->new_nhead_offs != len) {
+               if (d->chk_lpt_sz2 && d->new_nhead_offs != len) {
                        dbg_err("LPT new nhead offs: expected %d was %d",
-                               c->new_nhead_offs, len);
+                               d->new_nhead_offs, len);
                        err = -EINVAL;
                }
                lpt_sz = (long long)c->pnode_cnt * c->pnode_sz;
@@ -1788,26 +1804,146 @@ int dbg_chk_lpt_sz(struct ubifs_info *c, int action, int len)
                lpt_sz += c->ltab_sz;
                if (c->big_lpt)
                        lpt_sz += c->lsave_sz;
-               if (c->chk_lpt_sz - c->chk_lpt_wastage > lpt_sz) {
+               if (d->chk_lpt_sz - d->chk_lpt_wastage > lpt_sz) {
                        dbg_err("LPT chk_lpt_sz %lld + waste %lld exceeds %lld",
-                               c->chk_lpt_sz, c->chk_lpt_wastage, lpt_sz);
+                               d->chk_lpt_sz, d->chk_lpt_wastage, lpt_sz);
                        err = -EINVAL;
                }
-               if (err)
+               if (err) {
                        dbg_dump_lpt_info(c);
-               c->chk_lpt_sz2 = c->chk_lpt_sz;
-               c->chk_lpt_sz = 0;
-               c->chk_lpt_wastage = 0;
-               c->chk_lpt_lebs = 0;
-               c->new_nhead_offs = len;
+                       dbg_dump_lpt_lebs(c);
+                       dump_stack();
+               }
+               d->chk_lpt_sz2 = d->chk_lpt_sz;
+               d->chk_lpt_sz = 0;
+               d->chk_lpt_wastage = 0;
+               d->chk_lpt_lebs = 0;
+               d->new_nhead_offs = len;
                return err;
        case 4:
-               c->chk_lpt_sz += len;
-               c->chk_lpt_wastage += len;
+               d->chk_lpt_sz += len;
+               d->chk_lpt_wastage += len;
                return 0;
        default:
                return -EINVAL;
        }
 }
 
+/**
+ * dbg_dump_lpt_leb - dump an LPT LEB.
+ * @c: UBIFS file-system description object
+ * @lnum: LEB number to dump
+ *
+ * This function dumps an LEB from LPT area. Nodes in this area are very
+ * different to nodes in the main area (e.g., they do not have common headers,
+ * they do not have 8-byte alignments, etc), so we have a separate function to
+ * dump LPT area LEBs. Note, LPT has to be locked by the caller.
+ */
+static void dump_lpt_leb(const struct ubifs_info *c, int lnum)
+{
+       int err, len = c->leb_size, node_type, node_num, node_len, offs;
+       void *buf = c->dbg->buf;
+
+       printk(KERN_DEBUG "(pid %d) start dumping LEB %d\n",
+              current->pid, lnum);
+       err = ubi_read(c->ubi, lnum, buf, 0, c->leb_size);
+       if (err) {
+               ubifs_err("cannot read LEB %d, error %d", lnum, err);
+               return;
+       }
+       while (1) {
+               offs = c->leb_size - len;
+               if (!is_a_node(c, buf, len)) {
+                       int pad_len;
+
+                       pad_len = get_pad_len(c, buf, len);
+                       if (pad_len) {
+                               printk(KERN_DEBUG "LEB %d:%d, pad %d bytes\n",
+                                      lnum, offs, pad_len);
+                               buf += pad_len;
+                               len -= pad_len;
+                               continue;
+                       }
+                       if (len)
+                               printk(KERN_DEBUG "LEB %d:%d, free %d bytes\n",
+                                      lnum, offs, len);
+                       break;
+               }
+
+               node_type = get_lpt_node_type(c, buf, &node_num);
+               switch (node_type) {
+               case UBIFS_LPT_PNODE:
+               {
+                       node_len = c->pnode_sz;
+                       if (c->big_lpt)
+                               printk(KERN_DEBUG "LEB %d:%d, pnode num %d\n",
+                                      lnum, offs, node_num);
+                       else
+                               printk(KERN_DEBUG "LEB %d:%d, pnode\n",
+                                      lnum, offs);
+                       break;
+               }
+               case UBIFS_LPT_NNODE:
+               {
+                       int i;
+                       struct ubifs_nnode nnode;
+
+                       node_len = c->nnode_sz;
+                       if (c->big_lpt)
+                               printk(KERN_DEBUG "LEB %d:%d, nnode num %d, ",
+                                      lnum, offs, node_num);
+                       else
+                               printk(KERN_DEBUG "LEB %d:%d, nnode, ",
+                                      lnum, offs);
+                       err = ubifs_unpack_nnode(c, buf, &nnode);
+                       for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
+                               printk("%d:%d", nnode.nbranch[i].lnum,
+                                      nnode.nbranch[i].offs);
+                               if (i != UBIFS_LPT_FANOUT - 1)
+                                       printk(", ");
+                       }
+                       printk("\n");
+                       break;
+               }
+               case UBIFS_LPT_LTAB:
+                       node_len = c->ltab_sz;
+                       printk(KERN_DEBUG "LEB %d:%d, ltab\n",
+                              lnum, offs);
+                       break;
+               case UBIFS_LPT_LSAVE:
+                       node_len = c->lsave_sz;
+                       printk(KERN_DEBUG "LEB %d:%d, lsave len\n", lnum, offs);
+                       break;
+               default:
+                       ubifs_err("LPT node type %d not recognized", node_type);
+                       return;
+               }
+
+               buf += node_len;
+               len -= node_len;
+       }
+
+       printk(KERN_DEBUG "(pid %d) finish dumping LEB %d\n",
+              current->pid, lnum);
+}
+
+/**
+ * dbg_dump_lpt_lebs - dump LPT lebs.
+ * @c: UBIFS file-system description object
+ *
+ * This function dumps all LPT LEBs. The caller has to make sure the LPT is
+ * locked.
+ */
+void dbg_dump_lpt_lebs(const struct ubifs_info *c)
+{
+       int i;
+
+       printk(KERN_DEBUG "(pid %d) start dumping all LPT LEBs\n",
+              current->pid);
+       for (i = 0; i < c->lpt_lebs; i++)
+               dump_lpt_leb(c, i + c->lpt_first);
+       printk(KERN_DEBUG "(pid %d) finish dumping all LPT LEBs\n",
+              current->pid);
+}
+
 #endif /* CONFIG_UBIFS_FS_DEBUG */
index 9bd5a43d4526c8d7a55d0ae2a1fb4fa37a3fd922..9e6f403f170e4425641c5db8b833db9f63c3ce7b 100644 (file)
@@ -899,7 +899,7 @@ static int dbg_scan_orphans(struct ubifs_info *c, struct check_info *ci)
        for (lnum = c->orph_first; lnum <= c->orph_last; lnum++) {
                struct ubifs_scan_leb *sleb;
 
-               sleb = ubifs_scan(c, lnum, 0, c->dbg_buf);
+               sleb = ubifs_scan(c, lnum, 0, c->dbg->buf);
                if (IS_ERR(sleb)) {
                        err = PTR_ERR(sleb);
                        break;
index 21f7d047c306be4cc3761deed76ea0de2ff8ea3f..ce42a7b0ca5a3113b92495ed67a2970a36292a49 100644 (file)
@@ -144,7 +144,7 @@ static int set_bud_lprops(struct ubifs_info *c, struct replay_entry *r)
                /*
                 * If the replay order was perfect the dirty space would now be
                 * zero. The order is not perfect because the the journal heads
-                * race with eachother. This is not a problem but is does mean
+                * race with each other. This is not a problem but is does mean
                 * that the dirty space may temporarily exceed c->leb_size
                 * during the replay.
                 */
@@ -656,7 +656,7 @@ out_dump:
  * @dirty: amount of dirty space from padding and deletion nodes
  *
  * This function inserts a reference node to the replay tree and returns zero
- * in case of success ort a negative error code in case of failure.
+ * in case of success or a negative error code in case of failure.
  */
 static int insert_ref_node(struct ubifs_info *c, int lnum, int offs,
                           unsigned long long sqnum, int free, int dirty)
@@ -883,7 +883,7 @@ static int replay_log_leb(struct ubifs_info *c, int lnum, int offs, void *sbuf)
                 * This means that we reached end of log and now
                 * look to the older log data, which was already
                 * committed but the eraseblock was not erased (UBIFS
-                * only unmaps it). So this basically means we have to
+                * only un-maps it). So this basically means we have to
                 * exit with "end of log" code.
                 */
                err = 1;
@@ -1062,6 +1062,15 @@ int ubifs_replay_journal(struct ubifs_info *c)
        if (err)
                goto out;
 
+       /*
+        * UBIFS budgeting calculations use @c->budg_uncommitted_idx variable
+        * to roughly estimate index growth. Things like @c->min_idx_lebs
+        * depend on it. This means we have to initialize it to make sure
+        * budgeting works properly.
+        */
+       c->budg_uncommitted_idx = atomic_long_read(&c->dirty_zn_cnt);
+       c->budg_uncommitted_idx *= c->max_idx_node_sz;
+
        ubifs_assert(c->bud_bytes <= c->max_bud_bytes || c->need_recovery);
        dbg_mnt("finished, log head LEB %d:%d, max_sqnum %llu, "
                "highest_inum %lu", c->lhead_lnum, c->lhead_offs, c->max_sqnum,
index 0f392351dc5a57232c776ccf7577c7d759d5da85..e070c643d1bb180b0099c7674f9703d4be0870ce 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "ubifs.h"
 #include <linux/random.h>
+#include <linux/math64.h>
 
 /*
  * Default journal size in logical eraseblocks as a percent of total
@@ -80,7 +81,7 @@ static int create_default_filesystem(struct ubifs_info *c)
        int err, tmp, jnl_lebs, log_lebs, max_buds, main_lebs, main_first;
        int lpt_lebs, lpt_first, orph_lebs, big_lpt, ino_waste, sup_flags = 0;
        int min_leb_cnt = UBIFS_MIN_LEB_CNT;
-       uint64_t tmp64, main_bytes;
+       long long tmp64, main_bytes;
        __le64 tmp_le64;
 
        /* Some functions called from here depend on the @c->key_len filed */
@@ -160,7 +161,7 @@ static int create_default_filesystem(struct ubifs_info *c)
        if (!sup)
                return -ENOMEM;
 
-       tmp64 = (uint64_t)max_buds * c->leb_size;
+       tmp64 = (long long)max_buds * c->leb_size;
        if (big_lpt)
                sup_flags |= UBIFS_FLG_BIGLPT;
 
@@ -179,14 +180,16 @@ static int create_default_filesystem(struct ubifs_info *c)
        sup->fanout        = cpu_to_le32(DEFAULT_FANOUT);
        sup->lsave_cnt     = cpu_to_le32(c->lsave_cnt);
        sup->fmt_version   = cpu_to_le32(UBIFS_FORMAT_VERSION);
-       sup->default_compr = cpu_to_le16(UBIFS_COMPR_LZO);
        sup->time_gran     = cpu_to_le32(DEFAULT_TIME_GRAN);
+       if (c->mount_opts.override_compr)
+               sup->default_compr = cpu_to_le16(c->mount_opts.compr_type);
+       else
+               sup->default_compr = cpu_to_le16(UBIFS_COMPR_LZO);
 
        generate_random_uuid(sup->uuid);
 
-       main_bytes = (uint64_t)main_lebs * c->leb_size;
-       tmp64 = main_bytes * DEFAULT_RP_PERCENT;
-       do_div(tmp64, 100);
+       main_bytes = (long long)main_lebs * c->leb_size;
+       tmp64 = div_u64(main_bytes * DEFAULT_RP_PERCENT, 100);
        if (tmp64 > DEFAULT_MAX_RP_SIZE)
                tmp64 = DEFAULT_MAX_RP_SIZE;
        sup->rp_size = cpu_to_le64(tmp64);
@@ -582,16 +585,15 @@ int ubifs_read_superblock(struct ubifs_info *c)
        c->jhead_cnt     = le32_to_cpu(sup->jhead_cnt) + NONDATA_JHEADS_CNT;
        c->fanout        = le32_to_cpu(sup->fanout);
        c->lsave_cnt     = le32_to_cpu(sup->lsave_cnt);
-       c->default_compr = le16_to_cpu(sup->default_compr);
        c->rp_size       = le64_to_cpu(sup->rp_size);
        c->rp_uid        = le32_to_cpu(sup->rp_uid);
        c->rp_gid        = le32_to_cpu(sup->rp_gid);
        sup_flags        = le32_to_cpu(sup->flags);
+       if (!c->mount_opts.override_compr)
+               c->default_compr = le16_to_cpu(sup->default_compr);
 
        c->vfs_sb->s_time_gran = le32_to_cpu(sup->time_gran);
-
        memcpy(&c->uuid, &sup->uuid, 16);
-
        c->big_lpt = !!(sup_flags & UBIFS_FLG_BIGLPT);
 
        /* Automatically increase file system size to the maximum size */
index d80b2aef42b661001b2c87ac645f9a8ac29fbfd7..0d7564b95f8e2572ff47e661e7616fce7354a440 100644 (file)
@@ -34,6 +34,8 @@
 #include <linux/parser.h>
 #include <linux/seq_file.h>
 #include <linux/mount.h>
+#include <linux/math64.h>
+#include <linux/writeback.h>
 #include "ubifs.h"
 
 /*
@@ -417,39 +419,54 @@ static int ubifs_show_options(struct seq_file *s, struct vfsmount *mnt)
        else if (c->mount_opts.chk_data_crc == 1)
                seq_printf(s, ",no_chk_data_crc");
 
+       if (c->mount_opts.override_compr) {
+               seq_printf(s, ",compr=");
+               seq_printf(s, ubifs_compr_name(c->mount_opts.compr_type));
+       }
+
        return 0;
 }
 
 static int ubifs_sync_fs(struct super_block *sb, int wait)
 {
+       int i, err;
        struct ubifs_info *c = sb->s_fs_info;
-       int i, ret = 0, err;
-       long long bud_bytes;
-
-       if (c->jheads) {
-               for (i = 0; i < c->jhead_cnt; i++) {
-                       err = ubifs_wbuf_sync(&c->jheads[i].wbuf);
-                       if (err && !ret)
-                               ret = err;
-               }
+       struct writeback_control wbc = {
+               .sync_mode   = wait ? WB_SYNC_ALL : WB_SYNC_HOLD,
+               .range_start = 0,
+               .range_end   = LLONG_MAX,
+               .nr_to_write = LONG_MAX,
+       };
+
+       if (sb->s_flags & MS_RDONLY)
+               return 0;
 
-               /* Commit the journal unless it has too little data */
-               spin_lock(&c->buds_lock);
-               bud_bytes = c->bud_bytes;
-               spin_unlock(&c->buds_lock);
-               if (bud_bytes > c->leb_size) {
-                       err = ubifs_run_commit(c);
-                       if (err)
-                               return err;
-               }
+       /*
+        * Synchronize write buffers, because 'ubifs_run_commit()' does not
+        * do this if it waits for an already running commit.
+        */
+       for (i = 0; i < c->jhead_cnt; i++) {
+               err = ubifs_wbuf_sync(&c->jheads[i].wbuf);
+               if (err)
+                       return err;
        }
 
        /*
-        * We ought to call sync for c->ubi but it does not have one. If it had
-        * it would in turn call mtd->sync, however mtd operations are
-        * synchronous anyway, so we don't lose any sleep here.
+        * VFS calls '->sync_fs()' before synchronizing all dirty inodes and
+        * pages, so synchronize them first, then commit the journal. Strictly
+        * speaking, it is not necessary to commit the journal here,
+        * synchronizing write-buffers would be enough. But committing makes
+        * UBIFS free space predictions much more accurate, so we want to let
+        * the user be able to get more accurate results of 'statfs()' after
+        * they synchronize the file system.
         */
-       return ret;
+       generic_sync_sb_inodes(sb, &wbc);
+
+       err = ubifs_run_commit(c);
+       if (err)
+               return err;
+
+       return ubi_sync(c->vi.ubi_num);
 }
 
 /**
@@ -596,7 +613,7 @@ static int bud_wbuf_callback(struct ubifs_info *c, int lnum, int free, int pad)
 }
 
 /*
- * init_constants_late - initialize UBIFS constants.
+ * init_constants_sb - initialize UBIFS constants.
  * @c: UBIFS file-system description object
  *
  * This is a helper function which initializes various UBIFS constants after
@@ -604,10 +621,10 @@ static int bud_wbuf_callback(struct ubifs_info *c, int lnum, int free, int pad)
  * makes sure they are all right. Returns zero in case of success and a
  * negative error code in case of failure.
  */
-static int init_constants_late(struct ubifs_info *c)
+static int init_constants_sb(struct ubifs_info *c)
 {
        int tmp, err;
-       uint64_t tmp64;
+       long long tmp64;
 
        c->main_bytes = (long long)c->main_lebs * c->leb_size;
        c->max_znode_sz = sizeof(struct ubifs_znode) +
@@ -634,9 +651,8 @@ static int init_constants_late(struct ubifs_info *c)
         * Make sure that the log is large enough to fit reference nodes for
         * all buds plus one reserved LEB.
         */
-       tmp64 = c->max_bud_bytes;
-       tmp = do_div(tmp64, c->leb_size);
-       c->max_bud_cnt = tmp64 + !!tmp;
+       tmp64 = c->max_bud_bytes + c->leb_size - 1;
+       c->max_bud_cnt = div_u64(tmp64, c->leb_size);
        tmp = (c->ref_node_alsz * c->max_bud_cnt + c->leb_size - 1);
        tmp /= c->leb_size;
        tmp += 1;
@@ -672,7 +688,7 @@ static int init_constants_late(struct ubifs_info *c)
         * Consequently, if the journal is too small, UBIFS will treat it as
         * always full.
         */
-       tmp64 = (uint64_t)(c->jhead_cnt + 1) * c->leb_size + 1;
+       tmp64 = (long long)(c->jhead_cnt + 1) * c->leb_size + 1;
        if (c->bg_bud_bytes < tmp64)
                c->bg_bud_bytes = tmp64;
        if (c->max_bud_bytes < tmp64 + c->leb_size)
@@ -682,6 +698,21 @@ static int init_constants_late(struct ubifs_info *c)
        if (err)
                return err;
 
+       return 0;
+}
+
+/*
+ * init_constants_master - initialize UBIFS constants.
+ * @c: UBIFS file-system description object
+ *
+ * This is a helper function which initializes various UBIFS constants after
+ * the master node has been read. It also checks various UBIFS parameters and
+ * makes sure they are all right.
+ */
+static void init_constants_master(struct ubifs_info *c)
+{
+       long long tmp64;
+
        c->min_idx_lebs = ubifs_calc_min_idx_lebs(c);
 
        /*
@@ -690,14 +721,13 @@ static int init_constants_late(struct ubifs_info *c)
         * necessary to report something for the 'statfs()' call.
         *
         * Subtract the LEB reserved for GC, the LEB which is reserved for
-        * deletions, and assume only one journal head is available.
+        * deletions, minimum LEBs for the index, and assume only one journal
+        * head is available.
         */
-       tmp64 = c->main_lebs - 2 - c->jhead_cnt + 1;
-       tmp64 *= (uint64_t)c->leb_size - c->leb_overhead;
+       tmp64 = c->main_lebs - 1 - 1 - MIN_INDEX_LEBS - c->jhead_cnt + 1;
+       tmp64 *= (long long)c->leb_size - c->leb_overhead;
        tmp64 = ubifs_reported_space(c, tmp64);
        c->block_cnt = tmp64 >> UBIFS_BLOCK_SHIFT;
-
-       return 0;
 }
 
 /**
@@ -878,6 +908,7 @@ static int check_volume_empty(struct ubifs_info *c)
  * Opt_no_bulk_read: disable bulk-reads
  * Opt_chk_data_crc: check CRCs when reading data nodes
  * Opt_no_chk_data_crc: do not check CRCs when reading data nodes
+ * Opt_override_compr: override default compressor
  * Opt_err: just end of array marker
  */
 enum {
@@ -887,6 +918,7 @@ enum {
        Opt_no_bulk_read,
        Opt_chk_data_crc,
        Opt_no_chk_data_crc,
+       Opt_override_compr,
        Opt_err,
 };
 
@@ -897,6 +929,7 @@ static const match_table_t tokens = {
        {Opt_no_bulk_read, "no_bulk_read"},
        {Opt_chk_data_crc, "chk_data_crc"},
        {Opt_no_chk_data_crc, "no_chk_data_crc"},
+       {Opt_override_compr, "compr=%s"},
        {Opt_err, NULL},
 };
 
@@ -950,6 +983,28 @@ static int ubifs_parse_options(struct ubifs_info *c, char *options,
                        c->mount_opts.chk_data_crc = 1;
                        c->no_chk_data_crc = 1;
                        break;
+               case Opt_override_compr:
+               {
+                       char *name = match_strdup(&args[0]);
+
+                       if (!name)
+                               return -ENOMEM;
+                       if (!strcmp(name, "none"))
+                               c->mount_opts.compr_type = UBIFS_COMPR_NONE;
+                       else if (!strcmp(name, "lzo"))
+                               c->mount_opts.compr_type = UBIFS_COMPR_LZO;
+                       else if (!strcmp(name, "zlib"))
+                               c->mount_opts.compr_type = UBIFS_COMPR_ZLIB;
+                       else {
+                               ubifs_err("unknown compressor \"%s\"", name);
+                               kfree(name);
+                               return -EINVAL;
+                       }
+                       kfree(name);
+                       c->mount_opts.override_compr = 1;
+                       c->default_compr = c->mount_opts.compr_type;
+                       break;
+               }
                default:
                        ubifs_err("unrecognized mount option \"%s\" "
                                  "or missing value", p);
@@ -1018,6 +1073,30 @@ again:
        }
 }
 
+/**
+ * check_free_space - check if there is enough free space to mount.
+ * @c: UBIFS file-system description object
+ *
+ * This function makes sure UBIFS has enough free space to be mounted in
+ * read/write mode. UBIFS must always have some free space to allow deletions.
+ */
+static int check_free_space(struct ubifs_info *c)
+{
+       ubifs_assert(c->dark_wm > 0);
+       if (c->lst.total_free + c->lst.total_dirty < c->dark_wm) {
+               ubifs_err("insufficient free space to mount in read/write mode");
+               dbg_dump_budg(c);
+               dbg_dump_lprops(c);
+               /*
+                * We return %-EINVAL instead of %-ENOSPC because it seems to
+                * be the closest error code mentioned in the mount function
+                * documentation.
+                */
+               return -EINVAL;
+       }
+       return 0;
+}
+
 /**
  * mount_ubifs - mount UBIFS file-system.
  * @c: UBIFS file-system description object
@@ -1039,11 +1118,9 @@ static int mount_ubifs(struct ubifs_info *c)
        if (err)
                return err;
 
-#ifdef CONFIG_UBIFS_FS_DEBUG
-       c->dbg_buf = vmalloc(c->leb_size);
-       if (!c->dbg_buf)
-               return -ENOMEM;
-#endif
+       err = ubifs_debugging_init(c);
+       if (err)
+               return err;
 
        err = check_volume_empty(c);
        if (err)
@@ -1100,27 +1177,25 @@ static int mount_ubifs(struct ubifs_info *c)
                goto out_free;
 
        /*
-        * Make sure the compressor which is set as the default on in the
-        * superblock was actually compiled in.
+        * Make sure the compressor which is set as default in the superblock
+        * or overridden by mount options is actually compiled in.
         */
        if (!ubifs_compr_present(c->default_compr)) {
-               ubifs_warn("'%s' compressor is set by superblock, but not "
-                          "compiled in", ubifs_compr_name(c->default_compr));
-               c->default_compr = UBIFS_COMPR_NONE;
+               ubifs_err("'compressor \"%s\" is not compiled in",
+                         ubifs_compr_name(c->default_compr));
+               goto out_free;
        }
 
-       dbg_failure_mode_registration(c);
-
-       err = init_constants_late(c);
+       err = init_constants_sb(c);
        if (err)
-               goto out_dereg;
+               goto out_free;
 
        sz = ALIGN(c->max_idx_node_sz, c->min_io_size);
        sz = ALIGN(sz + c->max_idx_node_sz, c->min_io_size);
        c->cbuf = kmalloc(sz, GFP_NOFS);
        if (!c->cbuf) {
                err = -ENOMEM;
-               goto out_dereg;
+               goto out_free;
        }
 
        sprintf(c->bgt_name, BGT_NAME_PATTERN, c->vi.ubi_num, c->vi.vol_id);
@@ -1145,6 +1220,8 @@ static int mount_ubifs(struct ubifs_info *c)
        if (err)
                goto out_master;
 
+       init_constants_master(c);
+
        if ((c->mst_node->flags & cpu_to_le32(UBIFS_MST_DIRTY)) != 0) {
                ubifs_msg("recovery needed");
                c->need_recovery = 1;
@@ -1183,12 +1260,9 @@ static int mount_ubifs(struct ubifs_info *c)
        if (!mounted_read_only) {
                int lnum;
 
-               /* Check for enough free space */
-               if (ubifs_calc_available(c, c->min_idx_lebs) <= 0) {
-                       ubifs_err("insufficient available space");
-                       err = -EINVAL;
+               err = check_free_space(c);
+               if (err)
                        goto out_orphans;
-               }
 
                /* Check for enough log space */
                lnum = c->lhead_lnum + 1;
@@ -1232,6 +1306,10 @@ static int mount_ubifs(struct ubifs_info *c)
                }
        }
 
+       err = dbg_debugfs_init_fs(c);
+       if (err)
+               goto out_infos;
+
        err = dbg_check_filesystem(c);
        if (err)
                goto out_infos;
@@ -1283,8 +1361,20 @@ static int mount_ubifs(struct ubifs_info *c)
        dbg_msg("tree fanout:         %d", c->fanout);
        dbg_msg("reserved GC LEB:     %d", c->gc_lnum);
        dbg_msg("first main LEB:      %d", c->main_first);
+       dbg_msg("max. znode size      %d", c->max_znode_sz);
+       dbg_msg("max. index node size %d", c->max_idx_node_sz);
+       dbg_msg("node sizes:          data %zu, inode %zu, dentry %zu",
+               UBIFS_DATA_NODE_SZ, UBIFS_INO_NODE_SZ, UBIFS_DENT_NODE_SZ);
+       dbg_msg("node sizes:          trun %zu, sb %zu, master %zu",
+               UBIFS_TRUN_NODE_SZ, UBIFS_SB_NODE_SZ, UBIFS_MST_NODE_SZ);
+       dbg_msg("node sizes:          ref %zu, cmt. start %zu, orph %zu",
+               UBIFS_REF_NODE_SZ, UBIFS_CS_NODE_SZ, UBIFS_ORPH_NODE_SZ);
+       dbg_msg("max. node sizes:     data %zu, inode %zu dentry %zu",
+               UBIFS_MAX_DATA_NODE_SZ, UBIFS_MAX_INO_NODE_SZ,
+               UBIFS_MAX_DENT_NODE_SZ);
        dbg_msg("dead watermark:      %d", c->dead_wm);
        dbg_msg("dark watermark:      %d", c->dark_wm);
+       dbg_msg("LEB overhead:        %d", c->leb_overhead);
        x = (long long)c->main_lebs * c->dark_wm;
        dbg_msg("max. dark space:     %lld (%lld KiB, %lld MiB)",
                x, x >> 10, x >> 20);
@@ -1320,14 +1410,12 @@ out_wbufs:
        free_wbufs(c);
 out_cbuf:
        kfree(c->cbuf);
-out_dereg:
-       dbg_failure_mode_deregistration(c);
 out_free:
        kfree(c->bu.buf);
        vfree(c->ileb_buf);
        vfree(c->sbuf);
        kfree(c->bottom_up_buf);
-       UBIFS_DBG(vfree(c->dbg_buf));
+       ubifs_debugging_exit(c);
        return err;
 }
 
@@ -1345,6 +1433,7 @@ static void ubifs_umount(struct ubifs_info *c)
        dbg_gen("un-mounting UBI device %d, volume %d", c->vi.ubi_num,
                c->vi.vol_id);
 
+       dbg_debugfs_exit_fs(c);
        spin_lock(&ubifs_infos_lock);
        list_del(&c->infos_list);
        spin_unlock(&ubifs_infos_lock);
@@ -1364,8 +1453,7 @@ static void ubifs_umount(struct ubifs_info *c)
        vfree(c->ileb_buf);
        vfree(c->sbuf);
        kfree(c->bottom_up_buf);
-       UBIFS_DBG(vfree(c->dbg_buf));
-       dbg_failure_mode_deregistration(c);
+       ubifs_debugging_exit(c);
 }
 
 /**
@@ -1387,12 +1475,9 @@ static int ubifs_remount_rw(struct ubifs_info *c)
        c->remounting_rw = 1;
        c->always_chk_crc = 1;
 
-       /* Check for enough free space */
-       if (ubifs_calc_available(c, c->min_idx_lebs) <= 0) {
-               ubifs_err("insufficient available space");
-               err = -EINVAL;
+       err = check_free_space(c);
+       if (err)
                goto out;
-       }
 
        if (c->old_leb_cnt != c->leb_cnt) {
                struct ubifs_sb_node *sup;
@@ -1515,20 +1600,24 @@ out:
  * @c: UBIFS file-system description object
  *
  * This function is called during un-mounting and re-mounting, and it commits
- * the journal unless the "fast unmount" mode is enabled. It also avoids
- * committing the journal if it contains too few data.
+ * the journal unless the "fast unmount" mode is enabled.
  */
 static void commit_on_unmount(struct ubifs_info *c)
 {
-       if (!c->fast_unmount) {
-               long long bud_bytes;
+       struct super_block *sb = c->vfs_sb;
+       long long bud_bytes;
 
-               spin_lock(&c->buds_lock);
-               bud_bytes = c->bud_bytes;
-               spin_unlock(&c->buds_lock);
-               if (bud_bytes > c->leb_size)
-                       ubifs_run_commit(c);
-       }
+       /*
+        * This function is called before the background thread is stopped, so
+        * we may race with ongoing commit, which means we have to take
+        * @c->bud_lock to access @c->bud_bytes.
+        */
+       spin_lock(&c->buds_lock);
+       bud_bytes = c->bud_bytes;
+       spin_unlock(&c->buds_lock);
+
+       if (!c->fast_unmount && !(sb->s_flags & MS_RDONLY) && bud_bytes)
+               ubifs_run_commit(c);
 }
 
 /**
@@ -1849,7 +1938,6 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent)
                goto out_iput;
 
        mutex_unlock(&c->umount_mutex);
-
        return 0;
 
 out_iput:
@@ -1955,7 +2043,7 @@ static void ubifs_kill_sb(struct super_block *sb)
         * We do 'commit_on_unmount()' here instead of 'ubifs_put_super()'
         * in order to be outside BKL.
         */
-       if (sb->s_root && !(sb->s_flags & MS_RDONLY))
+       if (sb->s_root)
                commit_on_unmount(c);
        /* The un-mount routine is actually done in put_super() */
        generic_shutdown_super(sb);
@@ -2020,6 +2108,14 @@ static int __init ubifs_init(void)
        BUILD_BUG_ON(UBIFS_INO_NODE_SZ != 160);
        BUILD_BUG_ON(UBIFS_REF_NODE_SZ != 64);
 
+       /*
+        * We use 2 bit wide bit-fields to store compression type, which should
+        * be amended if more compressors are added. The bit-fields are:
+        * @compr_type in 'struct ubifs_inode', @default_compr in
+        * 'struct ubifs_info' and @compr_type in 'struct ubifs_mount_opts'.
+        */
+       BUILD_BUG_ON(UBIFS_COMPR_TYPES_CNT > 4);
+
        /*
         * We require that PAGE_CACHE_SIZE is greater-than-or-equal-to
         * UBIFS_BLOCK_SIZE. It is assumed that both are powers of 2.
@@ -2048,12 +2144,18 @@ static int __init ubifs_init(void)
        register_shrinker(&ubifs_shrinker_info);
 
        err = ubifs_compressors_init();
+       if (err)
+               goto out_shrinker;
+
+       err = dbg_debugfs_init();
        if (err)
                goto out_compr;
 
        return 0;
 
 out_compr:
+       ubifs_compressors_exit();
+out_shrinker:
        unregister_shrinker(&ubifs_shrinker_info);
        kmem_cache_destroy(ubifs_inode_slab);
 out_reg:
@@ -2068,6 +2170,7 @@ static void __exit ubifs_exit(void)
        ubifs_assert(list_empty(&ubifs_infos));
        ubifs_assert(atomic_long_read(&ubifs_clean_zn_cnt) == 0);
 
+       dbg_debugfs_exit();
        ubifs_compressors_exit();
        unregister_shrinker(&ubifs_shrinker_info);
        kmem_cache_destroy(ubifs_inode_slab);
index 6eef5344a145ec845ee17791567ea41ad4db2fa9..f7e36f5455275e3e125b551b49b32448dd6f9188 100644 (file)
@@ -2245,12 +2245,11 @@ int ubifs_tnc_replace(struct ubifs_info *c, const union ubifs_key *key,
                        if (found) {
                                /* Ensure the znode is dirtied */
                                if (znode->cnext || !ubifs_zn_dirty(znode)) {
-                                           znode = dirty_cow_bottom_up(c,
-                                                                       znode);
-                                           if (IS_ERR(znode)) {
-                                                   err = PTR_ERR(znode);
-                                                   goto out_unlock;
-                                           }
+                                       znode = dirty_cow_bottom_up(c, znode);
+                                       if (IS_ERR(znode)) {
+                                               err = PTR_ERR(znode);
+                                               goto out_unlock;
+                                       }
                                }
                                zbr = &znode->zbranch[n];
                                lnc_free(zbr);
@@ -2317,11 +2316,11 @@ int ubifs_tnc_add_nm(struct ubifs_info *c, const union ubifs_key *key,
 
                /* Ensure the znode is dirtied */
                if (znode->cnext || !ubifs_zn_dirty(znode)) {
-                           znode = dirty_cow_bottom_up(c, znode);
-                           if (IS_ERR(znode)) {
-                                   err = PTR_ERR(znode);
-                                   goto out_unlock;
-                           }
+                       znode = dirty_cow_bottom_up(c, znode);
+                       if (IS_ERR(znode)) {
+                               err = PTR_ERR(znode);
+                               goto out_unlock;
+                       }
                }
 
                if (found == 1) {
@@ -2627,11 +2626,11 @@ int ubifs_tnc_remove_range(struct ubifs_info *c, union ubifs_key *from_key,
 
                /* Ensure the znode is dirtied */
                if (znode->cnext || !ubifs_zn_dirty(znode)) {
-                           znode = dirty_cow_bottom_up(c, znode);
-                           if (IS_ERR(znode)) {
-                                   err = PTR_ERR(znode);
-                                   goto out_unlock;
-                           }
+                       znode = dirty_cow_bottom_up(c, znode);
+                       if (IS_ERR(znode)) {
+                               err = PTR_ERR(znode);
+                               goto out_unlock;
+                       }
                }
 
                /* Remove all keys in range except the first */
index 8ac76b1c2d552eb5d8c94e765e2e4a1a2f747358..fde8d127c768d11c6b16087f4a2a6437b729c1d1 100644 (file)
@@ -553,8 +553,8 @@ static int layout_in_empty_space(struct ubifs_info *c)
        }
 
 #ifdef CONFIG_UBIFS_FS_DEBUG
-       c->new_ihead_lnum = lnum;
-       c->new_ihead_offs = buf_offs;
+       c->dbg->new_ihead_lnum = lnum;
+       c->dbg->new_ihead_offs = buf_offs;
 #endif
 
        return 0;
@@ -802,8 +802,10 @@ int ubifs_tnc_start_commit(struct ubifs_info *c, struct ubifs_zbranch *zroot)
         * budgeting subsystem to assume the index is already committed,
         * even though it is not.
         */
+       ubifs_assert(c->min_idx_lebs == ubifs_calc_min_idx_lebs(c));
        c->old_idx_sz = c->calc_idx_sz;
        c->budg_uncommitted_idx = 0;
+       c->min_idx_lebs = ubifs_calc_min_idx_lebs(c);
        spin_unlock(&c->space_lock);
        mutex_unlock(&c->tnc_mutex);
 
@@ -1002,7 +1004,8 @@ static int write_index(struct ubifs_info *c)
        }
 
 #ifdef CONFIG_UBIFS_FS_DEBUG
-       if (lnum != c->new_ihead_lnum || buf_offs != c->new_ihead_offs) {
+       if (lnum != c->dbg->new_ihead_lnum ||
+           buf_offs != c->dbg->new_ihead_offs) {
                ubifs_err("inconsistent ihead");
                return -EINVAL;
        }
index 0b378042a3a28dd18737f6211e29dafbe7c5410b..b25fc36cf72f1fa70889dc3749f892e604673e75 100644 (file)
  */
 #define UBIFS_MIN_COMPR_LEN 128
 
+/*
+ * If compressed data length is less than %UBIFS_MIN_COMPRESS_DIFF bytes
+ * shorter than uncompressed data length, UBIFS preferes to leave this data
+ * node uncompress, because it'll be read faster.
+ */
+#define UBIFS_MIN_COMPRESS_DIFF 64
+
 /* Root inode number */
 #define UBIFS_ROOT_INO 1
 
index 46b172560a064eb7b4d541359aa9b02e7dd39380..fc2a4cc66d03c75429a14de807c4fcf8d48a7cce 100644 (file)
 #define SQNUM_WARN_WATERMARK 0xFFFFFFFF00000000ULL
 #define SQNUM_WATERMARK      0xFFFFFFFFFF000000ULL
 
+/*
+ * Minimum amount of LEBs reserved for the index. At present the index needs at
+ * least 2 LEBs: one for the index head and one for in-the-gaps method (which
+ * currently does not cater for the index head and so excludes it from
+ * consideration).
+ */
+#define MIN_INDEX_LEBS 2
+
 /* Minimum amount of data UBIFS writes to the flash */
 #define MIN_WRITE_SZ (UBIFS_DATA_NODE_SZ + 8)
 
@@ -386,12 +394,12 @@ struct ubifs_inode {
        unsigned int dirty:1;
        unsigned int xattr:1;
        unsigned int bulk_read:1;
+       unsigned int compr_type:2;
        struct mutex ui_mutex;
        spinlock_t ui_lock;
        loff_t synced_i_size;
        loff_t ui_size;
        int flags;
-       int compr_type;
        pgoff_t last_page_read;
        pgoff_t read_in_a_row;
        int data_len;
@@ -419,7 +427,7 @@ struct ubifs_unclean_leb {
  *
  * LPROPS_UNCAT: not categorized
  * LPROPS_DIRTY: dirty > 0, not index
- * LPROPS_DIRTY_IDX: dirty + free > UBIFS_CH_SZ and index
+ * LPROPS_DIRTY_IDX: dirty + free > @c->min_idx_node_sze and index
  * LPROPS_FREE: free > 0, not empty, not index
  * LPROPS_HEAP_CNT: number of heaps used for storing categorized LEBs
  * LPROPS_EMPTY: LEB is empty, not taken
@@ -473,8 +481,8 @@ struct ubifs_lprops {
 struct ubifs_lpt_lprops {
        int free;
        int dirty;
-       unsigned tgc : 1;
-       unsigned cmt : 1;
+       unsigned tgc:1;
+       unsigned cmt:1;
 };
 
 /**
@@ -482,24 +490,26 @@ struct ubifs_lpt_lprops {
  * @empty_lebs: number of empty LEBs
  * @taken_empty_lebs: number of taken LEBs
  * @idx_lebs: number of indexing LEBs
- * @total_free: total free space in bytes
- * @total_dirty: total dirty space in bytes
- * @total_used: total used space in bytes (includes only data LEBs)
- * @total_dead: total dead space in bytes (includes only data LEBs)
- * @total_dark: total dark space in bytes (includes only data LEBs)
+ * @total_free: total free space in bytes (includes all LEBs)
+ * @total_dirty: total dirty space in bytes (includes all LEBs)
+ * @total_used: total used space in bytes (does not include index LEBs)
+ * @total_dead: total dead space in bytes (does not include index LEBs)
+ * @total_dark: total dark space in bytes (does not include index LEBs)
+ *
+ * The @taken_empty_lebs field counts the LEBs that are in the transient state
+ * of having been "taken" for use but not yet written to. @taken_empty_lebs is
+ * needed to account correctly for @gc_lnum, otherwise @empty_lebs could be
+ * used by itself (in which case 'unused_lebs' would be a better name). In the
+ * case of @gc_lnum, it is "taken" at mount time or whenever a LEB is retained
+ * by GC, but unlike other empty LEBs that are "taken", it may not be written
+ * straight away (i.e. before the next commit start or unmount), so either
+ * @gc_lnum must be specially accounted for, or the current approach followed
+ * i.e. count it under @taken_empty_lebs.
  *
- * N.B. total_dirty and total_used are different to other total_* fields,
- * because they account _all_ LEBs, not just data LEBs.
+ * @empty_lebs includes @taken_empty_lebs.
  *
- * 'taken_empty_lebs' counts the LEBs that are in the transient state of having
- * been 'taken' for use but not yet written to. 'taken_empty_lebs' is needed
- * to account correctly for gc_lnum, otherwise 'empty_lebs' could be used
- * by itself (in which case 'unused_lebs' would be a better name). In the case
- * of gc_lnum, it is 'taken' at mount time or whenever a LEB is retained by GC,
- * but unlike other empty LEBs that are 'taken', it may not be written straight
- * away (i.e. before the next commit start or unmount), so either gc_lnum must
- * be specially accounted for, or the current approach followed i.e. count it
- * under 'taken_empty_lebs'.
+ * @total_used, @total_dead and @total_dark fields do not account indexing
+ * LEBs.
  */
 struct ubifs_lp_stats {
        int empty_lebs;
@@ -893,15 +903,25 @@ struct ubifs_orphan {
 /**
  * struct ubifs_mount_opts - UBIFS-specific mount options information.
  * @unmount_mode: selected unmount mode (%0 default, %1 normal, %2 fast)
- * @bulk_read: enable bulk-reads
- * @chk_data_crc: check CRCs when reading data nodes
+ * @bulk_read: enable/disable bulk-reads (%0 default, %1 disabe, %2 enable)
+ * @chk_data_crc: enable/disable CRC data checking when reading data nodes
+ *                (%0 default, %1 disabe, %2 enable)
+ * @override_compr: override default compressor (%0 - do not override and use
+ *                  superblock compressor, %1 - override and use compressor
+ *                  specified in @compr_type)
+ * @compr_type: compressor type to override the superblock compressor with
+ *              (%UBIFS_COMPR_NONE, etc)
  */
 struct ubifs_mount_opts {
        unsigned int unmount_mode:2;
        unsigned int bulk_read:2;
        unsigned int chk_data_crc:2;
+       unsigned int override_compr:1;
+       unsigned int compr_type:2;
 };
 
+struct ubifs_debug_info;
+
 /**
  * struct ubifs_info - UBIFS file-system description data structure
  * (per-superblock).
@@ -946,6 +966,7 @@ struct ubifs_mount_opts {
  * @no_chk_data_crc: do not check CRCs when reading data nodes (except during
  *                   recovery)
  * @bulk_read: enable bulk-reads
+ * @default_compr: default compression algorithm (%UBIFS_COMPR_LZO, etc)
  *
  * @tnc_mutex: protects the Tree Node Cache (TNC), @zroot, @cnext, @enext, and
  *             @calc_idx_sz
@@ -963,8 +984,6 @@ struct ubifs_mount_opts {
  * @ileb_nxt: next pre-allocated index LEBs
  * @old_idx: tree of index nodes obsoleted since the last commit start
  * @bottom_up_buf: a buffer which is used by 'dirty_cow_bottom_up()' in tnc.c
- * @new_ihead_lnum: used by debugging to check ihead_lnum
- * @new_ihead_offs: used by debugging to check ihead_offs
  *
  * @mst_node: master node
  * @mst_offs: offset of valid master node
@@ -986,7 +1005,6 @@ struct ubifs_mount_opts {
  * @main_lebs: count of LEBs in the main area
  * @main_first: first LEB of the main area
  * @main_bytes: main area size in bytes
- * @default_compr: default compression algorithm (%UBIFS_COMPR_LZO, etc)
  *
  * @key_hash_type: type of the key hash
  * @key_hash: direntry key hash function
@@ -1149,15 +1167,7 @@ struct ubifs_mount_opts {
  * @always_chk_crc: always check CRCs (while mounting and remounting rw)
  * @mount_opts: UBIFS-specific mount options
  *
- * @dbg_buf: a buffer of LEB size used for debugging purposes
- * @old_zroot: old index root - used by 'dbg_check_old_index()'
- * @old_zroot_level: old index root level - used by 'dbg_check_old_index()'
- * @old_zroot_sqnum: old index root sqnum - used by 'dbg_check_old_index()'
- * @failure_mode: failure mode for recovery testing
- * @fail_delay: 0=>don't delay, 1=>delay a time, 2=>delay a number of calls
- * @fail_timeout: time in jiffies when delay of failure mode expires
- * @fail_cnt: current number of calls to failure mode I/O functions
- * @fail_cnt_max: number of calls by which to delay failure mode
+ * @dbg: debugging-related information
  */
 struct ubifs_info {
        struct super_block *vfs_sb;
@@ -1196,6 +1206,7 @@ struct ubifs_info {
        unsigned int big_lpt:1;
        unsigned int no_chk_data_crc:1;
        unsigned int bulk_read:1;
+       unsigned int default_compr:2;
 
        struct mutex tnc_mutex;
        struct ubifs_zbranch zroot;
@@ -1212,10 +1223,6 @@ struct ubifs_info {
        int ileb_nxt;
        struct rb_root old_idx;
        int *bottom_up_buf;
-#ifdef CONFIG_UBIFS_FS_DEBUG
-       int new_ihead_lnum;
-       int new_ihead_offs;
-#endif
 
        struct ubifs_mst_node *mst_node;
        int mst_offs;
@@ -1237,7 +1244,6 @@ struct ubifs_info {
        int main_lebs;
        int main_first;
        long long main_bytes;
-       int default_compr;
 
        uint8_t key_hash_type;
        uint32_t (*key_hash)(const char *str, int len);
@@ -1315,8 +1321,8 @@ struct ubifs_info {
        void *sbuf;
        struct list_head idx_gc;
        int idx_gc_cnt;
-       volatile int gc_seq;
-       volatile int gced_lnum;
+       int gc_seq;
+       int gced_lnum;
 
        struct list_head infos_list;
        struct mutex umount_mutex;
@@ -1391,21 +1397,7 @@ struct ubifs_info {
        struct ubifs_mount_opts mount_opts;
 
 #ifdef CONFIG_UBIFS_FS_DEBUG
-       void *dbg_buf;
-       struct ubifs_zbranch old_zroot;
-       int old_zroot_level;
-       unsigned long long old_zroot_sqnum;
-       int failure_mode;
-       int fail_delay;
-       unsigned long fail_timeout;
-       unsigned int fail_cnt;
-       unsigned int fail_cnt_max;
-       long long chk_lpt_sz;
-       long long chk_lpt_sz2;
-       long long chk_lpt_wastage;
-       int chk_lpt_lebs;
-       int new_nhead_lnum;
-       int new_nhead_offs;
+       struct ubifs_debug_info *dbg;
 #endif
 };
 
@@ -1505,7 +1497,7 @@ void ubifs_cancel_ino_op(struct ubifs_info *c, struct inode *inode,
 long long ubifs_get_free_space(struct ubifs_info *c);
 int ubifs_calc_min_idx_lebs(struct ubifs_info *c);
 void ubifs_convert_page_budget(struct ubifs_info *c);
-long long ubifs_reported_space(const struct ubifs_info *c, uint64_t free);
+long long ubifs_reported_space(const struct ubifs_info *c, long long free);
 long long ubifs_calc_available(const struct ubifs_info *c, int min_idx_lebs);
 
 /* find.c */
@@ -1639,6 +1631,9 @@ void ubifs_add_lpt_dirt(struct ubifs_info *c, int lnum, int dirty);
 void ubifs_add_nnode_dirt(struct ubifs_info *c, struct ubifs_nnode *nnode);
 uint32_t ubifs_unpack_bits(uint8_t **addr, int *pos, int nrbits);
 struct ubifs_nnode *ubifs_first_nnode(struct ubifs_info *c, int *hght);
+/* Needed only in debugging code in lpt_commit.c */
+int ubifs_unpack_nnode(const struct ubifs_info *c, void *buf,
+                      struct ubifs_nnode *nnode);
 
 /* lpt_commit.c */
 int ubifs_lpt_start_commit(struct ubifs_info *c);
@@ -1714,7 +1709,7 @@ long ubifs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
 
 /* compressor.c */
 int __init ubifs_compressors_init(void);
-void __exit ubifs_compressors_exit(void);
+void ubifs_compressors_exit(void);
 void ubifs_compress(const void *in_buf, int in_len, void *out_buf, int *out_len,
                    int *compr_type);
 int ubifs_decompress(const void *buf, int len, void *out, int *out_len,
index 468377e665314434fd4f5aa6fe407f50a68096fc..237804cd6b566572177b60b05d68307b7cc207b2 100644 (file)
@@ -175,7 +175,7 @@ vfs_listxattr(struct dentry *d, char *list, size_t size)
        if (error)
                return error;
        error = -EOPNOTSUPP;
-       if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
+       if (d->d_inode->i_op->listxattr) {
                error = d->d_inode->i_op->listxattr(d, list, size);
        } else {
                error = security_inode_listsecurity(d->d_inode, list, size);
index 3795590e152abbc54209e71b7688d4ed7639339f..0574add2a1e3ad24938f3cd090893f5bc178d227 100644 (file)
@@ -127,7 +127,7 @@ struct acpi_processor_performance {
        unsigned int state_count;
        struct acpi_processor_px *states;
        struct acpi_psd_package domain_info;
-       cpumask_t shared_cpu_map;
+       cpumask_var_t shared_cpu_map;
        unsigned int shared_type;
 };
 
@@ -172,7 +172,7 @@ struct acpi_processor_throttling {
        unsigned int state_count;
        struct acpi_processor_tx_tss *states_tss;
        struct acpi_tsd_package domain_info;
-       cpumask_t shared_cpu_map;
+       cpumask_var_t shared_cpu_map;
        int (*acpi_processor_get_throttling) (struct acpi_processor * pr);
        int (*acpi_processor_set_throttling) (struct acpi_processor * pr,
                                              int state);
index 39456ba0ec17c7156c5a7fef5baed6cbf60f74e2..287f6f697ce276d55b498cea168a67e402e6b5bf 100644 (file)
@@ -339,6 +339,19 @@ int __ffs(unsigned long x)
        return 31 - bit;
 }
 
+/**
+ * __fls - find last (most-significant) set bit in a long word
+ * @word: the word to search
+ *
+ * Undefined if no set bit exists, so code should check against 0 first.
+ */
+static inline unsigned long __fls(unsigned long word)
+{
+       unsigned long bit;
+       asm("scan %1,gr0,%0" : "=r"(bit) : "r"(word));
+       return bit;
+}
+
 /*
  * special slimline version of fls() for calculating ilog2_u32()
  * - note: no protection against n == 0
index 6dc9b81bf9f36544eeacfee071866629f220ce5c..aaddf0d5760326626616ecfdf3c884c196f924bb 100644 (file)
@@ -251,6 +251,7 @@ static __inline__ int test_and_change_bit(int nr, volatile void * addr)
 #include <asm-generic/bitops/ffz.h>
 #include <asm-generic/bitops/__ffs.h>
 #include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/__fls.h>
 #include <asm-generic/bitops/fls64.h>
 
 #ifdef __KERNEL__
index 3e8106442d5af6e7953b887ebdb8a35203e5f029..9bde784e7bad038a41d471a22af238587a998aad 100644 (file)
@@ -315,6 +315,11 @@ static inline int fls(int x)
        return 32 - cnt;
 }
 
+static inline int __fls(int x)
+{
+       return fls(x) - 1;
+}
+
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
index cc6d40c05cf3a369951ed8571f7bf226c844405f..0b610f482abb9fbe0622e9b6758cbc758e046de3 100644 (file)
@@ -195,6 +195,17 @@ int fls(int x)
        return (x != 0) ? __ilog2_u32(x) + 1 : 0;
 }
 
+/**
+ * __fls - find last (most-significant) set bit in a long word
+ * @word: the word to search
+ *
+ * Undefined if no set bit exists, so code should check against 0 first.
+ */
+static inline unsigned long __fls(unsigned long word)
+{
+       return __ilog2_u32(word);
+}
+
 /**
  * ffs - find first bit set
  * @x: the word to search
index 23261e8f2e5ac4c15cf36a23921f3cd9cb654b5f..6c3930397bd32539716f51c0cd23a290efa74cdd 100644 (file)
@@ -82,6 +82,16 @@ static inline int fls (unsigned int x)
        return 32 - __cntlz(x);
 }
 
+/**
+ * __fls - find last (most-significant) set bit in a long word
+ * @word: the word to search
+ *
+ * Undefined if no set bit exists, so code should check against 0 first.
+ */
+static inline unsigned long __fls(unsigned long word)
+{
+       return 31 - __cntlz(word);
+}
 #else
 
 /* Use the generic implementation if we don't have the nsa/nsau instructions. */
@@ -90,6 +100,7 @@ static inline int fls (unsigned int x)
 # include <asm-generic/bitops/__ffs.h>
 # include <asm-generic/bitops/ffz.h>
 # include <asm-generic/bitops/fls.h>
+# include <asm-generic/bitops/__fls.h>
 
 #endif
 
index 95ac82340c3bc0914ad08e02bc337a17b0416e39..39da666067b9cb14d6301005618f42ddb57c3ef6 100644 (file)
@@ -56,8 +56,6 @@ header-y += dlm_device.h
 header-y += dlm_netlink.h
 header-y += dm-ioctl.h
 header-y += dn.h
-header-y += dqblk_v1.h
-header-y += dqblk_v2.h
 header-y += dqblk_xfs.h
 header-y += efs_fs_sb.h
 header-y += elf-fdpic.h
@@ -134,8 +132,6 @@ header-y += posix_types.h
 header-y += ppdev.h
 header-y += prctl.h
 header-y += qnxtypes.h
-header-y += quotaio_v1.h
-header-y += quotaio_v2.h
 header-y += radeonfb.h
 header-y += raw.h
 header-y += resource.h
index 26c4f6f65a46f5a18a1db4066045aa294109111f..67e5dbfc296140fe4825490ac952773921516c3b 100644 (file)
 #define AUDIT_GREATER_THAN_OR_EQUAL    (AUDIT_GREATER_THAN|AUDIT_EQUAL)
 #define AUDIT_OPERATORS                        (AUDIT_EQUAL|AUDIT_NOT_EQUAL|AUDIT_BIT_MASK)
 
+enum {
+       Audit_equal,
+       Audit_not_equal,
+       Audit_bitmask,
+       Audit_bittest,
+       Audit_lt,
+       Audit_gt,
+       Audit_le,
+       Audit_ge,
+       Audit_bad
+};
+
 /* Status symbols */
                                /* Mask values */
 #define AUDIT_STATUS_ENABLED           0x0001
@@ -373,6 +385,8 @@ struct audit_krule {
        struct audit_watch      *watch; /* associated watch */
        struct audit_tree       *tree;  /* associated watched tree */
        struct list_head        rlist;  /* entry in audit_{watch,tree}.rules list */
+       struct list_head        list;   /* for AUDIT_LIST* purposes only */
+       u64                     prio;
 };
 
 struct audit_field {
@@ -443,70 +457,56 @@ extern int  audit_set_loginuid(struct task_struct *task, uid_t loginuid);
 #define audit_get_loginuid(t) ((t)->loginuid)
 #define audit_get_sessionid(t) ((t)->sessionid)
 extern void audit_log_task_context(struct audit_buffer *ab);
-extern int __audit_ipc_obj(struct kern_ipc_perm *ipcp);
-extern int __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode);
+extern void __audit_ipc_obj(struct kern_ipc_perm *ipcp);
+extern void __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode);
 extern int audit_bprm(struct linux_binprm *bprm);
-extern int audit_socketcall(int nargs, unsigned long *args);
+extern void audit_socketcall(int nargs, unsigned long *args);
 extern int audit_sockaddr(int len, void *addr);
-extern int __audit_fd_pair(int fd1, int fd2);
+extern void __audit_fd_pair(int fd1, int fd2);
 extern int audit_set_macxattr(const char *name);
-extern int __audit_mq_open(int oflag, mode_t mode, struct mq_attr __user *u_attr);
-extern int __audit_mq_timedsend(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec __user *u_abs_timeout);
-extern int __audit_mq_timedreceive(mqd_t mqdes, size_t msg_len, unsigned int __user *u_msg_prio, const struct timespec __user *u_abs_timeout);
-extern int __audit_mq_notify(mqd_t mqdes, const struct sigevent __user *u_notification);
-extern int __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat);
+extern void __audit_mq_open(int oflag, mode_t mode, struct mq_attr *attr);
+extern void __audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec *abs_timeout);
+extern void __audit_mq_notify(mqd_t mqdes, const struct sigevent *notification);
+extern void __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat);
 extern int __audit_log_bprm_fcaps(struct linux_binprm *bprm,
                                  const struct cred *new,
                                  const struct cred *old);
-extern int __audit_log_capset(pid_t pid, const struct cred *new, const struct cred *old);
+extern void __audit_log_capset(pid_t pid, const struct cred *new, const struct cred *old);
 
-static inline int audit_ipc_obj(struct kern_ipc_perm *ipcp)
+static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp)
 {
        if (unlikely(!audit_dummy_context()))
-               return __audit_ipc_obj(ipcp);
-       return 0;
-}
-static inline int audit_fd_pair(int fd1, int fd2)
-{
-       if (unlikely(!audit_dummy_context()))
-               return __audit_fd_pair(fd1, fd2);
-       return 0;
+               __audit_ipc_obj(ipcp);
 }
-static inline int audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode)
+static inline void audit_fd_pair(int fd1, int fd2)
 {
        if (unlikely(!audit_dummy_context()))
-               return __audit_ipc_set_perm(qbytes, uid, gid, mode);
-       return 0;
+               __audit_fd_pair(fd1, fd2);
 }
-static inline int audit_mq_open(int oflag, mode_t mode, struct mq_attr __user *u_attr)
+static inline void audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode)
 {
        if (unlikely(!audit_dummy_context()))
-               return __audit_mq_open(oflag, mode, u_attr);
-       return 0;
+               __audit_ipc_set_perm(qbytes, uid, gid, mode);
 }
-static inline int audit_mq_timedsend(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec __user *u_abs_timeout)
+static inline void audit_mq_open(int oflag, mode_t mode, struct mq_attr *attr)
 {
        if (unlikely(!audit_dummy_context()))
-               return __audit_mq_timedsend(mqdes, msg_len, msg_prio, u_abs_timeout);
-       return 0;
+               __audit_mq_open(oflag, mode, attr);
 }
-static inline int audit_mq_timedreceive(mqd_t mqdes, size_t msg_len, unsigned int __user *u_msg_prio, const struct timespec __user *u_abs_timeout)
+static inline void audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec *abs_timeout)
 {
        if (unlikely(!audit_dummy_context()))
-               return __audit_mq_timedreceive(mqdes, msg_len, u_msg_prio, u_abs_timeout);
-       return 0;
+               __audit_mq_sendrecv(mqdes, msg_len, msg_prio, abs_timeout);
 }
-static inline int audit_mq_notify(mqd_t mqdes, const struct sigevent __user *u_notification)
+static inline void audit_mq_notify(mqd_t mqdes, const struct sigevent *notification)
 {
        if (unlikely(!audit_dummy_context()))
-               return __audit_mq_notify(mqdes, u_notification);
-       return 0;
+               __audit_mq_notify(mqdes, notification);
 }
-static inline int audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat)
+static inline void audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat)
 {
        if (unlikely(!audit_dummy_context()))
-               return __audit_mq_getsetattr(mqdes, mqstat);
-       return 0;
+               __audit_mq_getsetattr(mqdes, mqstat);
 }
 
 static inline int audit_log_bprm_fcaps(struct linux_binprm *bprm,
@@ -518,12 +518,11 @@ static inline int audit_log_bprm_fcaps(struct linux_binprm *bprm,
        return 0;
 }
 
-static inline int audit_log_capset(pid_t pid, const struct cred *new,
+static inline void audit_log_capset(pid_t pid, const struct cred *new,
                                   const struct cred *old)
 {
        if (unlikely(!audit_dummy_context()))
-               return __audit_log_capset(pid, new, old);
-       return 0;
+               __audit_log_capset(pid, new, old);
 }
 
 extern int audit_n_rules;
@@ -546,20 +545,19 @@ extern int audit_signals;
 #define audit_get_loginuid(t) (-1)
 #define audit_get_sessionid(t) (-1)
 #define audit_log_task_context(b) do { ; } while (0)
-#define audit_ipc_obj(i) ({ 0; })
-#define audit_ipc_set_perm(q,u,g,m) ({ 0; })
+#define audit_ipc_obj(i) ((void)0)
+#define audit_ipc_set_perm(q,u,g,m) ((void)0)
 #define audit_bprm(p) ({ 0; })
-#define audit_socketcall(n,a) ({ 0; })
-#define audit_fd_pair(n,a) ({ 0; })
+#define audit_socketcall(n,a) ((void)0)
+#define audit_fd_pair(n,a) ((void)0)
 #define audit_sockaddr(len, addr) ({ 0; })
 #define audit_set_macxattr(n) do { ; } while (0)
-#define audit_mq_open(o,m,a) ({ 0; })
-#define audit_mq_timedsend(d,l,p,t) ({ 0; })
-#define audit_mq_timedreceive(d,l,p,t) ({ 0; })
-#define audit_mq_notify(d,n) ({ 0; })
-#define audit_mq_getsetattr(d,s) ({ 0; })
+#define audit_mq_open(o,m,a) ((void)0)
+#define audit_mq_sendrecv(d,l,p,t) ((void)0)
+#define audit_mq_notify(d,n) ((void)0)
+#define audit_mq_getsetattr(d,s) ((void)0)
 #define audit_log_bprm_fcaps(b, ncr, ocr) ({ 0; })
-#define audit_log_capset(pid, ncr, ocr) ({ 0; })
+#define audit_log_capset(pid, ncr, ocr) ((void)0)
 #define audit_ptrace(t) ((void)0)
 #define audit_n_rules 0
 #define audit_signals 0
index a08c33a26ca938eeb7835a3e568f3a94fc0de70b..2878811c61346f09520ffdc086742c77943e91ea 100644 (file)
@@ -137,9 +137,12 @@ extern void bitmap_copy_le(void *dst, const unsigned long *src, int nbits);
                (1UL<<((nbits) % BITS_PER_LONG))-1 : ~0UL               \
 )
 
+#define small_const_nbits(nbits) \
+       (__builtin_constant_p(nbits) && (nbits) <= BITS_PER_LONG)
+
 static inline void bitmap_zero(unsigned long *dst, int nbits)
 {
-       if (nbits <= BITS_PER_LONG)
+       if (small_const_nbits(nbits))
                *dst = 0UL;
        else {
                int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
@@ -150,7 +153,7 @@ static inline void bitmap_zero(unsigned long *dst, int nbits)
 static inline void bitmap_fill(unsigned long *dst, int nbits)
 {
        size_t nlongs = BITS_TO_LONGS(nbits);
-       if (nlongs > 1) {
+       if (!small_const_nbits(nbits)) {
                int len = (nlongs - 1) * sizeof(unsigned long);
                memset(dst, 0xff,  len);
        }
@@ -160,7 +163,7 @@ static inline void bitmap_fill(unsigned long *dst, int nbits)
 static inline void bitmap_copy(unsigned long *dst, const unsigned long *src,
                        int nbits)
 {
-       if (nbits <= BITS_PER_LONG)
+       if (small_const_nbits(nbits))
                *dst = *src;
        else {
                int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
@@ -171,7 +174,7 @@ static inline void bitmap_copy(unsigned long *dst, const unsigned long *src,
 static inline void bitmap_and(unsigned long *dst, const unsigned long *src1,
                        const unsigned long *src2, int nbits)
 {
-       if (nbits <= BITS_PER_LONG)
+       if (small_const_nbits(nbits))
                *dst = *src1 & *src2;
        else
                __bitmap_and(dst, src1, src2, nbits);
@@ -180,7 +183,7 @@ static inline void bitmap_and(unsigned long *dst, const unsigned long *src1,
 static inline void bitmap_or(unsigned long *dst, const unsigned long *src1,
                        const unsigned long *src2, int nbits)
 {
-       if (nbits <= BITS_PER_LONG)
+       if (small_const_nbits(nbits))
                *dst = *src1 | *src2;
        else
                __bitmap_or(dst, src1, src2, nbits);
@@ -189,7 +192,7 @@ static inline void bitmap_or(unsigned long *dst, const unsigned long *src1,
 static inline void bitmap_xor(unsigned long *dst, const unsigned long *src1,
                        const unsigned long *src2, int nbits)
 {
-       if (nbits <= BITS_PER_LONG)
+       if (small_const_nbits(nbits))
                *dst = *src1 ^ *src2;
        else
                __bitmap_xor(dst, src1, src2, nbits);
@@ -198,7 +201,7 @@ static inline void bitmap_xor(unsigned long *dst, const unsigned long *src1,
 static inline void bitmap_andnot(unsigned long *dst, const unsigned long *src1,
                        const unsigned long *src2, int nbits)
 {
-       if (nbits <= BITS_PER_LONG)
+       if (small_const_nbits(nbits))
                *dst = *src1 & ~(*src2);
        else
                __bitmap_andnot(dst, src1, src2, nbits);
@@ -207,7 +210,7 @@ static inline void bitmap_andnot(unsigned long *dst, const unsigned long *src1,
 static inline void bitmap_complement(unsigned long *dst, const unsigned long *src,
                        int nbits)
 {
-       if (nbits <= BITS_PER_LONG)
+       if (small_const_nbits(nbits))
                *dst = ~(*src) & BITMAP_LAST_WORD_MASK(nbits);
        else
                __bitmap_complement(dst, src, nbits);
@@ -216,7 +219,7 @@ static inline void bitmap_complement(unsigned long *dst, const unsigned long *sr
 static inline int bitmap_equal(const unsigned long *src1,
                        const unsigned long *src2, int nbits)
 {
-       if (nbits <= BITS_PER_LONG)
+       if (small_const_nbits(nbits))
                return ! ((*src1 ^ *src2) & BITMAP_LAST_WORD_MASK(nbits));
        else
                return __bitmap_equal(src1, src2, nbits);
@@ -225,7 +228,7 @@ static inline int bitmap_equal(const unsigned long *src1,
 static inline int bitmap_intersects(const unsigned long *src1,
                        const unsigned long *src2, int nbits)
 {
-       if (nbits <= BITS_PER_LONG)
+       if (small_const_nbits(nbits))
                return ((*src1 & *src2) & BITMAP_LAST_WORD_MASK(nbits)) != 0;
        else
                return __bitmap_intersects(src1, src2, nbits);
@@ -234,7 +237,7 @@ static inline int bitmap_intersects(const unsigned long *src1,
 static inline int bitmap_subset(const unsigned long *src1,
                        const unsigned long *src2, int nbits)
 {
-       if (nbits <= BITS_PER_LONG)
+       if (small_const_nbits(nbits))
                return ! ((*src1 & ~(*src2)) & BITMAP_LAST_WORD_MASK(nbits));
        else
                return __bitmap_subset(src1, src2, nbits);
@@ -242,7 +245,7 @@ static inline int bitmap_subset(const unsigned long *src1,
 
 static inline int bitmap_empty(const unsigned long *src, int nbits)
 {
-       if (nbits <= BITS_PER_LONG)
+       if (small_const_nbits(nbits))
                return ! (*src & BITMAP_LAST_WORD_MASK(nbits));
        else
                return __bitmap_empty(src, nbits);
@@ -250,7 +253,7 @@ static inline int bitmap_empty(const unsigned long *src, int nbits)
 
 static inline int bitmap_full(const unsigned long *src, int nbits)
 {
-       if (nbits <= BITS_PER_LONG)
+       if (small_const_nbits(nbits))
                return ! (~(*src) & BITMAP_LAST_WORD_MASK(nbits));
        else
                return __bitmap_full(src, nbits);
@@ -258,7 +261,7 @@ static inline int bitmap_full(const unsigned long *src, int nbits)
 
 static inline int bitmap_weight(const unsigned long *src, int nbits)
 {
-       if (nbits <= BITS_PER_LONG)
+       if (small_const_nbits(nbits))
                return hweight_long(*src & BITMAP_LAST_WORD_MASK(nbits));
        return __bitmap_weight(src, nbits);
 }
@@ -266,7 +269,7 @@ static inline int bitmap_weight(const unsigned long *src, int nbits)
 static inline void bitmap_shift_right(unsigned long *dst,
                        const unsigned long *src, int n, int nbits)
 {
-       if (nbits <= BITS_PER_LONG)
+       if (small_const_nbits(nbits))
                *dst = *src >> n;
        else
                __bitmap_shift_right(dst, src, n, nbits);
@@ -275,7 +278,7 @@ static inline void bitmap_shift_right(unsigned long *dst,
 static inline void bitmap_shift_left(unsigned long *dst,
                        const unsigned long *src, int n, int nbits)
 {
-       if (nbits <= BITS_PER_LONG)
+       if (small_const_nbits(nbits))
                *dst = (*src << n) & BITMAP_LAST_WORD_MASK(nbits);
        else
                __bitmap_shift_left(dst, src, n, nbits);
index 024f2b027244aa8fd8ce35cb4aaa6ee1c9e57fbb..61829139795af07cdcb11f5623ebb0aabbcc608b 100644 (file)
@@ -134,9 +134,20 @@ extern unsigned long find_first_bit(const unsigned long *addr,
  */
 extern unsigned long find_first_zero_bit(const unsigned long *addr,
                                         unsigned long size);
-
 #endif /* CONFIG_GENERIC_FIND_FIRST_BIT */
 
+#ifdef CONFIG_GENERIC_FIND_LAST_BIT
+/**
+ * find_last_bit - find the last set bit in a memory region
+ * @addr: The address to start the search at
+ * @size: The maximum size to search
+ *
+ * Returns the bit number of the first set bit, or size.
+ */
+extern unsigned long find_last_bit(const unsigned long *addr,
+                                  unsigned long size);
+#endif /* CONFIG_GENERIC_FIND_LAST_BIT */
+
 #ifdef CONFIG_GENERIC_FIND_NEXT_BIT
 
 /**
index 8607312983bd8045c24a402335b30ee034c4505c..e44b88ba552b87c45ffc947c3afa9364b10afc7c 100644 (file)
@@ -53,7 +53,10 @@ static inline void bgl_lock_init(struct blockgroup_lock *bgl)
  * The accessor is a macro so we can embed a blockgroup_lock into different
  * superblock types
  */
-#define sb_bgl_lock(sb, block_group) \
-       (&(sb)->s_blockgroup_lock.locks[(block_group) & (NR_BG_LOCKS-1)].lock)
+static inline spinlock_t *
+bgl_lock_ptr(struct blockgroup_lock *bgl, unsigned int block_group)
+{
+       return &bgl->locks[(block_group) & (NR_BG_LOCKS-1)].lock;
+}
 
 #endif
index 1ee608fd7b77c35bee3639c449f6f6483de2bc7c..484b3abf61bb09235d30fba0ee83214c300e8ae7 100644 (file)
@@ -234,6 +234,7 @@ struct cpufreq_driver {
        int     (*suspend)      (struct cpufreq_policy *policy, pm_message_t pmsg);
        int     (*resume)       (struct cpufreq_policy *policy);
        struct freq_attr        **attr;
+       bool                    hide_interface;
 };
 
 /* flags */
index d4bf52603e6bfbdab95eb81b65bad0dce510356c..9f315382610b579e91da6677483ea75d7ce1ab4b 100644 (file)
 typedef struct cpumask { DECLARE_BITMAP(bits, NR_CPUS); } cpumask_t;
 extern cpumask_t _unused_cpumask_arg_;
 
+#ifndef CONFIG_DISABLE_OBSOLETE_CPUMASK_FUNCTIONS
 #define cpu_set(cpu, dst) __cpu_set((cpu), &(dst))
 static inline void __cpu_set(int cpu, volatile cpumask_t *dstp)
 {
@@ -267,6 +268,26 @@ static inline void __cpus_shift_left(cpumask_t *dstp,
 {
        bitmap_shift_left(dstp->bits, srcp->bits, n, nbits);
 }
+#endif /* !CONFIG_DISABLE_OBSOLETE_CPUMASK_FUNCTIONS */
+
+/**
+ * to_cpumask - convert an NR_CPUS bitmap to a struct cpumask *
+ * @bitmap: the bitmap
+ *
+ * There are a few places where cpumask_var_t isn't appropriate and
+ * static cpumasks must be used (eg. very early boot), yet we don't
+ * expose the definition of 'struct cpumask'.
+ *
+ * This does the conversion, and can be used as a constant initializer.
+ */
+#define to_cpumask(bitmap)                                             \
+       ((struct cpumask *)(1 ? (bitmap)                                \
+                           : (void *)sizeof(__check_is_bitmap(bitmap))))
+
+static inline int __check_is_bitmap(const unsigned long *bitmap)
+{
+       return 1;
+}
 
 /*
  * Special-case data structure for "single bit set only" constant CPU masks.
@@ -278,13 +299,14 @@ static inline void __cpus_shift_left(cpumask_t *dstp,
 extern const unsigned long
        cpu_bit_bitmap[BITS_PER_LONG+1][BITS_TO_LONGS(NR_CPUS)];
 
-static inline const cpumask_t *get_cpu_mask(unsigned int cpu)
+static inline const struct cpumask *get_cpu_mask(unsigned int cpu)
 {
        const unsigned long *p = cpu_bit_bitmap[1 + cpu % BITS_PER_LONG];
        p -= cpu / BITS_PER_LONG;
-       return (const cpumask_t *)p;
+       return to_cpumask(p);
 }
 
+#ifndef CONFIG_DISABLE_OBSOLETE_CPUMASK_FUNCTIONS
 /*
  * In cases where we take the address of the cpumask immediately,
  * gcc optimizes it out (it's a constant) and there's no huge stack
@@ -370,19 +392,22 @@ static inline void __cpus_fold(cpumask_t *dstp, const cpumask_t *origp,
 {
        bitmap_fold(dstp->bits, origp->bits, sz, nbits);
 }
+#endif /* !CONFIG_DISABLE_OBSOLETE_CPUMASK_FUNCTIONS */
 
 #if NR_CPUS == 1
 
 #define nr_cpu_ids             1
+#ifndef CONFIG_DISABLE_OBSOLETE_CPUMASK_FUNCTIONS
 #define first_cpu(src)         ({ (void)(src); 0; })
 #define next_cpu(n, src)       ({ (void)(src); 1; })
 #define any_online_cpu(mask)   0
 #define for_each_cpu_mask(cpu, mask)   \
        for ((cpu) = 0; (cpu) < 1; (cpu)++, (void)mask)
-
+#endif /* !CONFIG_DISABLE_OBSOLETE_CPUMASK_FUNCTIONS */
 #else /* NR_CPUS > 1 */
 
 extern int nr_cpu_ids;
+#ifndef CONFIG_DISABLE_OBSOLETE_CPUMASK_FUNCTIONS
 int __first_cpu(const cpumask_t *srcp);
 int __next_cpu(int n, const cpumask_t *srcp);
 int __any_online_cpu(const cpumask_t *mask);
@@ -394,8 +419,10 @@ int __any_online_cpu(const cpumask_t *mask);
        for ((cpu) = -1;                                \
                (cpu) = next_cpu((cpu), (mask)),        \
                (cpu) < NR_CPUS; )
+#endif /* !CONFIG_DISABLE_OBSOLETE_CPUMASK_FUNCTIONS */
 #endif
 
+#ifndef CONFIG_DISABLE_OBSOLETE_CPUMASK_FUNCTIONS
 #if NR_CPUS <= 64
 
 #define next_cpu_nr(n, src)            next_cpu(n, src)
@@ -413,77 +440,67 @@ int __next_cpu_nr(int n, const cpumask_t *srcp);
                (cpu) < nr_cpu_ids; )
 
 #endif /* NR_CPUS > 64 */
+#endif /* !CONFIG_DISABLE_OBSOLETE_CPUMASK_FUNCTIONS */
 
 /*
  * The following particular system cpumasks and operations manage
- * possible, present, active and online cpus.  Each of them is a fixed size
- * bitmap of size NR_CPUS.
+ * possible, present, active and online cpus.
  *
- *  #ifdef CONFIG_HOTPLUG_CPU
- *     cpu_possible_map - has bit 'cpu' set iff cpu is populatable
- *     cpu_present_map  - has bit 'cpu' set iff cpu is populated
- *     cpu_online_map   - has bit 'cpu' set iff cpu available to scheduler
- *     cpu_active_map   - has bit 'cpu' set iff cpu available to migration
- *  #else
- *     cpu_possible_map - has bit 'cpu' set iff cpu is populated
- *     cpu_present_map  - copy of cpu_possible_map
- *     cpu_online_map   - has bit 'cpu' set iff cpu available to scheduler
- *  #endif
+ *     cpu_possible_mask- has bit 'cpu' set iff cpu is populatable
+ *     cpu_present_mask - has bit 'cpu' set iff cpu is populated
+ *     cpu_online_mask  - has bit 'cpu' set iff cpu available to scheduler
+ *     cpu_active_mask  - has bit 'cpu' set iff cpu available to migration
  *
- *  In either case, NR_CPUS is fixed at compile time, as the static
- *  size of these bitmaps.  The cpu_possible_map is fixed at boot
- *  time, as the set of CPU id's that it is possible might ever
- *  be plugged in at anytime during the life of that system boot.
- *  The cpu_present_map is dynamic(*), representing which CPUs
- *  are currently plugged in.  And cpu_online_map is the dynamic
- *  subset of cpu_present_map, indicating those CPUs available
- *  for scheduling.
+ *  If !CONFIG_HOTPLUG_CPU, present == possible, and active == online.
  *
- *  If HOTPLUG is enabled, then cpu_possible_map is forced to have
+ *  The cpu_possible_mask is fixed at boot time, as the set of CPU id's
+ *  that it is possible might ever be plugged in at anytime during the
+ *  life of that system boot.  The cpu_present_mask is dynamic(*),
+ *  representing which CPUs are currently plugged in.  And
+ *  cpu_online_mask is the dynamic subset of cpu_present_mask,
+ *  indicating those CPUs available for scheduling.
+ *
+ *  If HOTPLUG is enabled, then cpu_possible_mask is forced to have
  *  all NR_CPUS bits set, otherwise it is just the set of CPUs that
  *  ACPI reports present at boot.
  *
- *  If HOTPLUG is enabled, then cpu_present_map varies dynamically,
+ *  If HOTPLUG is enabled, then cpu_present_mask varies dynamically,
  *  depending on what ACPI reports as currently plugged in, otherwise
- *  cpu_present_map is just a copy of cpu_possible_map.
+ *  cpu_present_mask is just a copy of cpu_possible_mask.
  *
- *  (*) Well, cpu_present_map is dynamic in the hotplug case.  If not
- *      hotplug, it's a copy of cpu_possible_map, hence fixed at boot.
+ *  (*) Well, cpu_present_mask is dynamic in the hotplug case.  If not
+ *      hotplug, it's a copy of cpu_possible_mask, hence fixed at boot.
  *
  * Subtleties:
  * 1) UP arch's (NR_CPUS == 1, CONFIG_SMP not defined) hardcode
  *    assumption that their single CPU is online.  The UP
- *    cpu_{online,possible,present}_maps are placebos.  Changing them
+ *    cpu_{online,possible,present}_masks are placebos.  Changing them
  *    will have no useful affect on the following num_*_cpus()
  *    and cpu_*() macros in the UP case.  This ugliness is a UP
  *    optimization - don't waste any instructions or memory references
  *    asking if you're online or how many CPUs there are if there is
  *    only one CPU.
- * 2) Most SMP arch's #define some of these maps to be some
- *    other map specific to that arch.  Therefore, the following
- *    must be #define macros, not inlines.  To see why, examine
- *    the assembly code produced by the following.  Note that
- *    set1() writes phys_x_map, but set2() writes x_map:
- *        int x_map, phys_x_map;
- *        #define set1(a) x_map = a
- *        inline void set2(int a) { x_map = a; }
- *        #define x_map phys_x_map
- *        main(){ set1(3); set2(5); }
  */
 
-extern cpumask_t cpu_possible_map;
-extern cpumask_t cpu_online_map;
-extern cpumask_t cpu_present_map;
-extern cpumask_t cpu_active_map;
+extern const struct cpumask *const cpu_possible_mask;
+extern const struct cpumask *const cpu_online_mask;
+extern const struct cpumask *const cpu_present_mask;
+extern const struct cpumask *const cpu_active_mask;
+
+/* These strip const, as traditionally they weren't const. */
+#define cpu_possible_map       (*(cpumask_t *)cpu_possible_mask)
+#define cpu_online_map         (*(cpumask_t *)cpu_online_mask)
+#define cpu_present_map                (*(cpumask_t *)cpu_present_mask)
+#define cpu_active_map         (*(cpumask_t *)cpu_active_mask)
 
 #if NR_CPUS > 1
-#define num_online_cpus()      cpus_weight_nr(cpu_online_map)
-#define num_possible_cpus()    cpus_weight_nr(cpu_possible_map)
-#define num_present_cpus()     cpus_weight_nr(cpu_present_map)
-#define cpu_online(cpu)                cpu_isset((cpu), cpu_online_map)
-#define cpu_possible(cpu)      cpu_isset((cpu), cpu_possible_map)
-#define cpu_present(cpu)       cpu_isset((cpu), cpu_present_map)
-#define cpu_active(cpu)                cpu_isset((cpu), cpu_active_map)
+#define num_online_cpus()      cpumask_weight(cpu_online_mask)
+#define num_possible_cpus()    cpumask_weight(cpu_possible_mask)
+#define num_present_cpus()     cpumask_weight(cpu_present_mask)
+#define cpu_online(cpu)                cpumask_test_cpu((cpu), cpu_online_mask)
+#define cpu_possible(cpu)      cpumask_test_cpu((cpu), cpu_possible_mask)
+#define cpu_present(cpu)       cpumask_test_cpu((cpu), cpu_present_mask)
+#define cpu_active(cpu)                cpumask_test_cpu((cpu), cpu_active_mask)
 #else
 #define num_online_cpus()      1
 #define num_possible_cpus()    1
@@ -496,10 +513,6 @@ extern cpumask_t cpu_active_map;
 
 #define cpu_is_offline(cpu)    unlikely(!cpu_online(cpu))
 
-#define for_each_possible_cpu(cpu) for_each_cpu_mask_nr((cpu), cpu_possible_map)
-#define for_each_online_cpu(cpu)   for_each_cpu_mask_nr((cpu), cpu_online_map)
-#define for_each_present_cpu(cpu)  for_each_cpu_mask_nr((cpu), cpu_present_map)
-
 /* These are the new versions of the cpumask operators: passed by pointer.
  * The older versions will be implemented in terms of these, then deleted. */
 #define cpumask_bits(maskp) ((maskp)->bits)
@@ -687,7 +700,7 @@ static inline void cpumask_clear_cpu(int cpu, struct cpumask *dstp)
  * No static inline type checking - see Subtlety (1) above.
  */
 #define cpumask_test_cpu(cpu, cpumask) \
-       test_bit(cpumask_check(cpu), (cpumask)->bits)
+       test_bit(cpumask_check(cpu), cpumask_bits((cpumask)))
 
 /**
  * cpumask_test_and_set_cpu - atomically test and set a cpu in a cpumask
@@ -930,7 +943,7 @@ static inline void cpumask_copy(struct cpumask *dstp,
 static inline int cpumask_scnprintf(char *buf, int len,
                                    const struct cpumask *srcp)
 {
-       return bitmap_scnprintf(buf, len, srcp->bits, nr_cpumask_bits);
+       return bitmap_scnprintf(buf, len, cpumask_bits(srcp), nr_cpumask_bits);
 }
 
 /**
@@ -944,7 +957,7 @@ static inline int cpumask_scnprintf(char *buf, int len,
 static inline int cpumask_parse_user(const char __user *buf, int len,
                                     struct cpumask *dstp)
 {
-       return bitmap_parse_user(buf, len, dstp->bits, nr_cpumask_bits);
+       return bitmap_parse_user(buf, len, cpumask_bits(dstp), nr_cpumask_bits);
 }
 
 /**
@@ -959,7 +972,8 @@ static inline int cpumask_parse_user(const char __user *buf, int len,
 static inline int cpulist_scnprintf(char *buf, int len,
                                    const struct cpumask *srcp)
 {
-       return bitmap_scnlistprintf(buf, len, srcp->bits, nr_cpumask_bits);
+       return bitmap_scnlistprintf(buf, len, cpumask_bits(srcp),
+                                   nr_cpumask_bits);
 }
 
 /**
@@ -972,26 +986,7 @@ static inline int cpulist_scnprintf(char *buf, int len,
  */
 static inline int cpulist_parse(const char *buf, struct cpumask *dstp)
 {
-       return bitmap_parselist(buf, dstp->bits, nr_cpumask_bits);
-}
-
-/**
- * to_cpumask - convert an NR_CPUS bitmap to a struct cpumask *
- * @bitmap: the bitmap
- *
- * There are a few places where cpumask_var_t isn't appropriate and
- * static cpumasks must be used (eg. very early boot), yet we don't
- * expose the definition of 'struct cpumask'.
- *
- * This does the conversion, and can be used as a constant initializer.
- */
-#define to_cpumask(bitmap)                                             \
-       ((struct cpumask *)(1 ? (bitmap)                                \
-                           : (void *)sizeof(__check_is_bitmap(bitmap))))
-
-static inline int __check_is_bitmap(const unsigned long *bitmap)
-{
-       return 1;
+       return bitmap_parselist(buf, cpumask_bits(dstp), nr_cpumask_bits);
 }
 
 /**
@@ -1025,6 +1020,7 @@ static inline size_t cpumask_size(void)
 #ifdef CONFIG_CPUMASK_OFFSTACK
 typedef struct cpumask *cpumask_var_t;
 
+bool alloc_cpumask_var_node(cpumask_var_t *mask, gfp_t flags, int node);
 bool alloc_cpumask_var(cpumask_var_t *mask, gfp_t flags);
 void alloc_bootmem_cpumask_var(cpumask_var_t *mask);
 void free_cpumask_var(cpumask_var_t mask);
@@ -1038,6 +1034,12 @@ static inline bool alloc_cpumask_var(cpumask_var_t *mask, gfp_t flags)
        return true;
 }
 
+static inline bool alloc_cpumask_var_node(cpumask_var_t *mask, gfp_t flags,
+                                         int node)
+{
+       return true;
+}
+
 static inline void alloc_bootmem_cpumask_var(cpumask_var_t *mask)
 {
 }
@@ -1051,12 +1053,6 @@ static inline void free_bootmem_cpumask_var(cpumask_var_t mask)
 }
 #endif /* CONFIG_CPUMASK_OFFSTACK */
 
-/* The pointer versions of the maps, these will become the primary versions. */
-#define cpu_possible_mask ((const struct cpumask *)&cpu_possible_map)
-#define cpu_online_mask ((const struct cpumask *)&cpu_online_map)
-#define cpu_present_mask ((const struct cpumask *)&cpu_present_map)
-#define cpu_active_mask ((const struct cpumask *)&cpu_active_map)
-
 /* It's common to want to use cpu_all_mask in struct member initializers,
  * so it has to refer to an address rather than a pointer. */
 extern const DECLARE_BITMAP(cpu_all_bits, NR_CPUS);
@@ -1065,51 +1061,16 @@ extern const DECLARE_BITMAP(cpu_all_bits, NR_CPUS);
 /* First bits of cpu_bit_bitmap are in fact unset. */
 #define cpu_none_mask to_cpumask(cpu_bit_bitmap[0])
 
-/* Wrappers for arch boot code to manipulate normally-constant masks */
-static inline void set_cpu_possible(unsigned int cpu, bool possible)
-{
-       if (possible)
-               cpumask_set_cpu(cpu, &cpu_possible_map);
-       else
-               cpumask_clear_cpu(cpu, &cpu_possible_map);
-}
-
-static inline void set_cpu_present(unsigned int cpu, bool present)
-{
-       if (present)
-               cpumask_set_cpu(cpu, &cpu_present_map);
-       else
-               cpumask_clear_cpu(cpu, &cpu_present_map);
-}
-
-static inline void set_cpu_online(unsigned int cpu, bool online)
-{
-       if (online)
-               cpumask_set_cpu(cpu, &cpu_online_map);
-       else
-               cpumask_clear_cpu(cpu, &cpu_online_map);
-}
+#define for_each_possible_cpu(cpu) for_each_cpu((cpu), cpu_possible_mask)
+#define for_each_online_cpu(cpu)   for_each_cpu((cpu), cpu_online_mask)
+#define for_each_present_cpu(cpu)  for_each_cpu((cpu), cpu_present_mask)
 
-static inline void set_cpu_active(unsigned int cpu, bool active)
-{
-       if (active)
-               cpumask_set_cpu(cpu, &cpu_active_map);
-       else
-               cpumask_clear_cpu(cpu, &cpu_active_map);
-}
-
-static inline void init_cpu_present(const struct cpumask *src)
-{
-       cpumask_copy(&cpu_present_map, src);
-}
-
-static inline void init_cpu_possible(const struct cpumask *src)
-{
-       cpumask_copy(&cpu_possible_map, src);
-}
-
-static inline void init_cpu_online(const struct cpumask *src)
-{
-       cpumask_copy(&cpu_online_map, src);
-}
+/* Wrappers for arch boot code to manipulate normally-constant masks */
+void set_cpu_possible(unsigned int cpu, bool possible);
+void set_cpu_present(unsigned int cpu, bool present);
+void set_cpu_online(unsigned int cpu, bool online);
+void set_cpu_active(unsigned int cpu, bool active);
+void init_cpu_present(const struct cpumask *src);
+void init_cpu_possible(const struct cpumask *src);
+void init_cpu_online(const struct cpumask *src);
 #endif /* __LINUX_CPUMASK_H */
index 952df39c989d6bcb4624537c256b4c264c7345f5..136f170cecc294bd1c2b5b792bb93d89c025c021 100644 (file)
 #define VTD_PAGE_MASK          (((u64)-1) << VTD_PAGE_SHIFT)
 #define VTD_PAGE_ALIGN(addr)   (((addr) + VTD_PAGE_SIZE - 1) & VTD_PAGE_MASK)
 
-#define IOVA_PFN(addr)         ((addr) >> PAGE_SHIFT)
-#define DMA_32BIT_PFN          IOVA_PFN(DMA_32BIT_MASK)
-#define DMA_64BIT_PFN          IOVA_PFN(DMA_64BIT_MASK)
-
-
-/*
- * 0: Present
- * 1-11: Reserved
- * 12-63: Context Ptr (12 - (haw-1))
- * 64-127: Reserved
- */
-struct root_entry {
-       u64     val;
-       u64     rsvd1;
-};
-#define ROOT_ENTRY_NR (VTD_PAGE_SIZE/sizeof(struct root_entry))
-static inline bool root_present(struct root_entry *root)
-{
-       return (root->val & 1);
-}
-static inline void set_root_present(struct root_entry *root)
-{
-       root->val |= 1;
-}
-static inline void set_root_value(struct root_entry *root, unsigned long value)
-{
-       root->val |= value & VTD_PAGE_MASK;
-}
-
-struct context_entry;
-static inline struct context_entry *
-get_context_addr_from_root(struct root_entry *root)
-{
-       return (struct context_entry *)
-               (root_present(root)?phys_to_virt(
-               root->val & VTD_PAGE_MASK) :
-               NULL);
-}
-
-/*
- * low 64 bits:
- * 0: present
- * 1: fault processing disable
- * 2-3: translation type
- * 12-63: address space root
- * high 64 bits:
- * 0-2: address width
- * 3-6: aval
- * 8-23: domain id
- */
-struct context_entry {
-       u64 lo;
-       u64 hi;
-};
-#define context_present(c) ((c).lo & 1)
-#define context_fault_disable(c) (((c).lo >> 1) & 1)
-#define context_translation_type(c) (((c).lo >> 2) & 3)
-#define context_address_root(c) ((c).lo & VTD_PAGE_MASK)
-#define context_address_width(c) ((c).hi &  7)
-#define context_domain_id(c) (((c).hi >> 8) & ((1 << 16) - 1))
-
-#define context_set_present(c) do {(c).lo |= 1;} while (0)
-#define context_set_fault_enable(c) \
-       do {(c).lo &= (((u64)-1) << 2) | 1;} while (0)
-#define context_set_translation_type(c, val) \
-       do { \
-               (c).lo &= (((u64)-1) << 4) | 3; \
-               (c).lo |= ((val) & 3) << 2; \
-       } while (0)
-#define CONTEXT_TT_MULTI_LEVEL 0
-#define context_set_address_root(c, val) \
-       do {(c).lo |= (val) & VTD_PAGE_MASK; } while (0)
-#define context_set_address_width(c, val) do {(c).hi |= (val) & 7;} while (0)
-#define context_set_domain_id(c, val) \
-       do {(c).hi |= ((val) & ((1 << 16) - 1)) << 8;} while (0)
-#define context_clear_entry(c) do {(c).lo = 0; (c).hi = 0;} while (0)
-
-/*
- * 0: readable
- * 1: writable
- * 2-6: reserved
- * 7: super page
- * 8-11: available
- * 12-63: Host physcial address
- */
-struct dma_pte {
-       u64 val;
-};
-#define dma_clear_pte(p)       do {(p).val = 0;} while (0)
-
 #define DMA_PTE_READ (1)
 #define DMA_PTE_WRITE (2)
 
-#define dma_set_pte_readable(p) do {(p).val |= DMA_PTE_READ;} while (0)
-#define dma_set_pte_writable(p) do {(p).val |= DMA_PTE_WRITE;} while (0)
-#define dma_set_pte_prot(p, prot) \
-               do {(p).val = ((p).val & ~3) | ((prot) & 3); } while (0)
-#define dma_pte_addr(p) ((p).val & VTD_PAGE_MASK)
-#define dma_set_pte_addr(p, addr) do {\
-               (p).val |= ((addr) & VTD_PAGE_MASK); } while (0)
-#define dma_pte_present(p) (((p).val & 3) != 0)
-
 struct intel_iommu;
+struct dmar_domain;
+struct root_entry;
 
-struct dmar_domain {
-       int     id;                     /* domain id */
-       struct intel_iommu *iommu;      /* back pointer to owning iommu */
-
-       struct list_head devices;       /* all devices' list */
-       struct iova_domain iovad;       /* iova's that belong to this domain */
-
-       struct dma_pte  *pgd;           /* virtual address */
-       spinlock_t      mapping_lock;   /* page table lock */
-       int             gaw;            /* max guest address width */
-
-       /* adjusted guest address width, 0 is level 2 30-bit */
-       int             agaw;
-
-#define DOMAIN_FLAG_MULTIPLE_DEVICES 1
-       int             flags;
-};
-
-/* PCI domain-device relationship */
-struct device_domain_info {
-       struct list_head link;  /* link to domain siblings */
-       struct list_head global; /* link to global list */
-       u8 bus;                 /* PCI bus numer */
-       u8 devfn;               /* PCI devfn number */
-       struct pci_dev *dev; /* it's NULL for PCIE-to-PCI bridge */
-       struct dmar_domain *domain; /* pointer to domain */
-};
-
-extern int init_dmars(void);
 extern void free_dmar_iommu(struct intel_iommu *iommu);
+extern int iommu_calculate_agaw(struct intel_iommu *iommu);
 
 extern int dmar_disabled;
 
-#ifndef CONFIG_DMAR_GFX_WA
-static inline void iommu_prepare_gfx_mapping(void)
-{
-       return;
-}
-#endif /* !CONFIG_DMAR_GFX_WA */
-
 #endif
index f1984fc3e06d54e21646c79c591169c5a3f84aeb..f28440784cf0861eed96d57dada953f8d3113bae 100644 (file)
@@ -144,7 +144,6 @@ struct dmar_rmrr_unit {
        list_for_each_entry(rmrr, &dmar_rmrr_units, list)
 /* Intel DMAR  initialization functions */
 extern int intel_iommu_init(void);
-extern int dmar_disabled;
 #else
 static inline int intel_iommu_init(void)
 {
diff --git a/include/linux/dqblk_qtree.h b/include/linux/dqblk_qtree.h
new file mode 100644 (file)
index 0000000..82a1652
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ *     Definitions of structures and functions for quota formats using trie
+ */
+
+#ifndef _LINUX_DQBLK_QTREE_H
+#define _LINUX_DQBLK_QTREE_H
+
+#include <linux/types.h>
+
+/* Numbers of blocks needed for updates - we count with the smallest
+ * possible block size (1024) */
+#define QTREE_INIT_ALLOC 4
+#define QTREE_INIT_REWRITE 2
+#define QTREE_DEL_ALLOC 0
+#define QTREE_DEL_REWRITE 6
+
+struct dquot;
+
+/* Operations */
+struct qtree_fmt_operations {
+       void (*mem2disk_dqblk)(void *disk, struct dquot *dquot);        /* Convert given entry from in memory format to disk one */
+       void (*disk2mem_dqblk)(struct dquot *dquot, void *disk);        /* Convert given entry from disk format to in memory one */
+       int (*is_id)(void *disk, struct dquot *dquot);  /* Is this structure for given id? */
+};
+
+/* Inmemory copy of version specific information */
+struct qtree_mem_dqinfo {
+       struct super_block *dqi_sb;     /* Sb quota is on */
+       int dqi_type;                   /* Quota type */
+       unsigned int dqi_blocks;        /* # of blocks in quota file */
+       unsigned int dqi_free_blk;      /* First block in list of free blocks */
+       unsigned int dqi_free_entry;    /* First block with free entry */
+       unsigned int dqi_blocksize_bits;        /* Block size of quota file */
+       unsigned int dqi_entry_size;    /* Size of quota entry in quota file */
+       unsigned int dqi_usable_bs;     /* Space usable in block for quota data */
+       unsigned int dqi_qtree_depth;   /* Precomputed depth of quota tree */
+       struct qtree_fmt_operations *dqi_ops;   /* Operations for entry manipulation */
+};
+
+int qtree_write_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot);
+int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot);
+int qtree_delete_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot);
+int qtree_release_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot);
+int qtree_entry_unused(struct qtree_mem_dqinfo *info, char *disk);
+static inline int qtree_depth(struct qtree_mem_dqinfo *info)
+{
+       unsigned int epb = info->dqi_usable_bs >> 2;
+       unsigned long long entries = epb;
+       int i;
+
+       for (i = 1; entries < (1ULL << 32); i++)
+               entries *= epb;
+       return i;
+}
+
+#endif /* _LINUX_DQBLK_QTREE_H */
index 57f1250d5a526c88e8d30ebbd277c878b60c6e6c..3713a7232dd8e5d267f40aa1d1498e5947589301 100644 (file)
@@ -5,9 +5,6 @@
 #ifndef _LINUX_DQBLK_V1_H
 #define _LINUX_DQBLK_V1_H
 
-/* Id of quota format */
-#define QFMT_VFS_OLD 1
-
 /* Root squash turned on */
 #define V1_DQF_RSQUASH 1
 
@@ -17,8 +14,4 @@
 #define V1_DEL_ALLOC 0
 #define V1_DEL_REWRITE 2
 
-/* Special information about quotafile */
-struct v1_mem_dqinfo {
-};
-
 #endif /* _LINUX_DQBLK_V1_H */
index 4f853322cb7fa0db9a6a73f266b01b825b6f37c7..18000a5426772382cac9f927585b15add4a22c4c 100644 (file)
@@ -1,26 +1,16 @@
 /*
- *     Definitions of structures for vfsv0 quota format
+ *  Definitions for vfsv0 quota format
  */
 
 #ifndef _LINUX_DQBLK_V2_H
 #define _LINUX_DQBLK_V2_H
 
-#include <linux/types.h>
-
-/* id numbers of quota format */
-#define QFMT_VFS_V0 2
+#include <linux/dqblk_qtree.h>
 
 /* Numbers of blocks needed for updates */
-#define V2_INIT_ALLOC 4
-#define V2_INIT_REWRITE 2
-#define V2_DEL_ALLOC 0
-#define V2_DEL_REWRITE 6
-
-/* Inmemory copy of version specific information */
-struct v2_mem_dqinfo {
-       unsigned int dqi_blocks;
-       unsigned int dqi_free_blk;
-       unsigned int dqi_free_entry;
-};
+#define V2_INIT_ALLOC QTREE_INIT_ALLOC
+#define V2_INIT_REWRITE QTREE_INIT_REWRITE
+#define V2_DEL_ALLOC QTREE_DEL_ALLOC
+#define V2_DEL_REWRITE QTREE_DEL_REWRITE
 
 #endif /* _LINUX_DQBLK_V2_H */
index 79a8ed8e6a7d6c02517c7407019b0302806035c1..55026b1a40bd8ee17fdfca344311d28f2bae3a6a 100644 (file)
@@ -62,10 +62,11 @@ typedef enum fe_caps {
        FE_CAN_HIERARCHY_AUTO           = 0x100000,
        FE_CAN_8VSB                     = 0x200000,
        FE_CAN_16VSB                    = 0x400000,
-       FE_HAS_EXTENDED_CAPS            = 0x800000,   // We need more bitspace for newer APIs, indicate this.
-       FE_NEEDS_BENDING                = 0x20000000, // not supported anymore, don't use (frontend requires frequency bending)
-       FE_CAN_RECOVER                  = 0x40000000, // frontend can recover from a cable unplug automatically
-       FE_CAN_MUTE_TS                  = 0x80000000  // frontend can stop spurious TS data output
+       FE_HAS_EXTENDED_CAPS            = 0x800000,   /* We need more bitspace for newer APIs, indicate this. */
+       FE_CAN_2G_MODULATION            = 0x10000000, /* frontend supports "2nd generation modulation" (DVB-S2) */
+       FE_NEEDS_BENDING                = 0x20000000, /* not supported anymore, don't use (frontend requires frequency bending) */
+       FE_CAN_RECOVER                  = 0x40000000, /* frontend can recover from a cable unplug automatically */
+       FE_CAN_MUTE_TS                  = 0x80000000  /* frontend can stop spurious TS data output */
 } fe_caps_t;
 
 
@@ -121,15 +122,15 @@ typedef enum fe_sec_mini_cmd {
 
 
 typedef enum fe_status {
-       FE_HAS_SIGNAL   = 0x01,   /*  found something above the noise level */
-       FE_HAS_CARRIER  = 0x02,   /*  found a DVB signal  */
-       FE_HAS_VITERBI  = 0x04,   /*  FEC is stable  */
-       FE_HAS_SYNC     = 0x08,   /*  found sync bytes  */
-       FE_HAS_LOCK     = 0x10,   /*  everything's working... */
-       FE_TIMEDOUT     = 0x20,   /*  no lock within the last ~2 seconds */
-       FE_REINIT       = 0x40    /*  frontend was reinitialized,  */
-} fe_status_t;                   /*  application is recommended to reset */
-                                 /*  DiSEqC, tone and parameters */
+       FE_HAS_SIGNAL   = 0x01,   /* found something above the noise level */
+       FE_HAS_CARRIER  = 0x02,   /* found a DVB signal  */
+       FE_HAS_VITERBI  = 0x04,   /* FEC is stable  */
+       FE_HAS_SYNC     = 0x08,   /* found sync bytes  */
+       FE_HAS_LOCK     = 0x10,   /* everything's working... */
+       FE_TIMEDOUT     = 0x20,   /* no lock within the last ~2 seconds */
+       FE_REINIT       = 0x40    /* frontend was reinitialized,  */
+} fe_status_t;                   /* application is recommended to reset */
+                                 /* DiSEqC, tone and parameters */
 
 typedef enum fe_spectral_inversion {
        INVERSION_OFF,
index f273415ab6f1afab257883b2b00d4f9cd6d1512b..dc541f3653d173fe45cbd9ba1e7a89192432d6bc 100644 (file)
@@ -108,4 +108,10 @@ struct ext2_sb_info {
        struct ext2_reserve_window_node s_rsv_window_head;
 };
 
+static inline spinlock_t *
+sb_bgl_lock(struct ext2_sb_info *sbi, unsigned int block_group)
+{
+       return bgl_lock_ptr(&sbi->s_blockgroup_lock, block_group);
+}
+
 #endif /* _LINUX_EXT2_FS_SB */
index b65f0288b842202866b878e5bae6889d2b763576..e024e38248ffc83e0bfc77bdb3713674d2188118 100644 (file)
@@ -83,4 +83,10 @@ struct ext3_sb_info {
 #endif
 };
 
+static inline spinlock_t *
+sb_bgl_lock(struct ext3_sb_info *sbi, unsigned int block_group)
+{
+       return bgl_lock_ptr(&sbi->s_blockgroup_lock, block_group);
+}
+
 #endif /* _LINUX_EXT3_FS_SB */
index e2170ee21e185bbfe6d4a7c4b3605402e634eca2..8b916ce92e73f96acb83d902c89131b34ac4042f 100644 (file)
@@ -423,6 +423,9 @@ enum positive_aop_returns {
 
 #define AOP_FLAG_UNINTERRUPTIBLE       0x0001 /* will not do a short write */
 #define AOP_FLAG_CONT_EXPAND           0x0002 /* called from cont_expand */
+#define AOP_FLAG_NOFS                  0x0004 /* used by filesystem to direct
+                                               * helper code (eg buffer layer)
+                                               * to clear GFP_FS from alloc */
 
 /*
  * oh the beauties of C type declarations.
@@ -1827,7 +1830,7 @@ extern int __filemap_fdatawrite_range(struct address_space *mapping,
 extern int filemap_fdatawrite_range(struct address_space *mapping,
                                loff_t start, loff_t end);
 
-extern long do_fsync(struct file *file, int datasync);
+extern int vfs_fsync(struct file *file, struct dentry *dentry, int datasync);
 extern void sync_supers(void);
 extern void sync_filesystems(int wait);
 extern void __fsync_super(struct super_block *sb);
@@ -2035,7 +2038,7 @@ extern int page_readlink(struct dentry *, char __user *, int);
 extern void *page_follow_link_light(struct dentry *, struct nameidata *);
 extern void page_put_link(struct dentry *, struct nameidata *, void *);
 extern int __page_symlink(struct inode *inode, const char *symname, int len,
-               gfp_t gfp_mask);
+               int nofs);
 extern int page_symlink(struct inode *inode, const char *symname, int len);
 extern const struct inode_operations page_symlink_inode_operations;
 extern int generic_readlink(struct dentry *, char __user *, int);
index 3d017cfd245b6a2ad690cd4579fd6413f6c22a42..c4f6c101dbcddd91e0b7d045a345a4d6fba28777 100644 (file)
@@ -23,8 +23,6 @@
 #define _INTEL_IOMMU_H_
 
 #include <linux/types.h>
-#include <linux/msi.h>
-#include <linux/sysdev.h>
 #include <linux/iova.h>
 #include <linux/io.h>
 #include <linux/dma_remapping.h>
@@ -289,10 +287,10 @@ struct intel_iommu {
        void __iomem    *reg; /* Pointer to hardware regs, virtual addr */
        u64             cap;
        u64             ecap;
-       int             seg;
        u32             gcmd; /* Holds TE, EAFL. Don't need SRTP, SFL, WBF */
        spinlock_t      register_lock; /* protect register handling */
        int             seq_id; /* sequence id of the iommu */
+       int             agaw; /* agaw of this iommu */
 
 #ifdef CONFIG_DMAR
        unsigned long   *domain_ids; /* bitmap of domains */
@@ -302,8 +300,6 @@ struct intel_iommu {
 
        unsigned int irq;
        unsigned char name[7];    /* Device Name */
-       struct msi_msg saved_msg;
-       struct sys_device sysdev;
        struct iommu_flush flush;
 #endif
        struct q_inval  *qi;            /* Queued invalidation info */
@@ -334,25 +330,6 @@ extern int qi_flush_iotlb(struct intel_iommu *iommu, u16 did, u64 addr,
 
 extern void qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu);
 
-void intel_iommu_domain_exit(struct dmar_domain *domain);
-struct dmar_domain *intel_iommu_domain_alloc(struct pci_dev *pdev);
-int intel_iommu_context_mapping(struct dmar_domain *domain,
-                               struct pci_dev *pdev);
-int intel_iommu_page_mapping(struct dmar_domain *domain, dma_addr_t iova,
-                            u64 hpa, size_t size, int prot);
-void intel_iommu_detach_dev(struct dmar_domain *domain, u8 bus, u8 devfn);
-struct dmar_domain *intel_iommu_find_domain(struct pci_dev *pdev);
-u64 intel_iommu_iova_to_pfn(struct dmar_domain *domain, u64 iova);
-
-#ifdef CONFIG_DMAR
-int intel_iommu_found(void);
-#else /* CONFIG_DMAR */
-static inline int intel_iommu_found(void)
-{
-       return 0;
-}
-#endif /* CONFIG_DMAR */
-
 extern void *intel_alloc_coherent(struct device *, size_t, dma_addr_t *, gfp_t);
 extern void intel_free_coherent(struct device *, size_t, void *, dma_addr_t);
 extern dma_addr_t intel_map_single(struct device *, phys_addr_t, size_t, int);
index 990355fbc54ee64004f7a2150552b2db2d1e6682..0702c4d7bdf01f17f34aaa4e91c077bcec1b15ec 100644 (file)
@@ -109,7 +109,7 @@ extern void enable_irq(unsigned int irq);
 
 #if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_HARDIRQS)
 
-extern cpumask_t irq_default_affinity;
+extern cpumask_var_t irq_default_affinity;
 
 extern int irq_set_affinity(unsigned int irq, const struct cpumask *cpumask);
 extern int irq_can_set_affinity(unsigned int irq);
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
new file mode 100644 (file)
index 0000000..8a7bfb1
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2007-2008 Advanced Micro Devices, Inc.
+ * Author: Joerg Roedel <joerg.roedel@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#ifndef __LINUX_IOMMU_H
+#define __LINUX_IOMMU_H
+
+#define IOMMU_READ     (1)
+#define IOMMU_WRITE    (2)
+
+struct device;
+
+struct iommu_domain {
+       void *priv;
+};
+
+struct iommu_ops {
+       int (*domain_init)(struct iommu_domain *domain);
+       void (*domain_destroy)(struct iommu_domain *domain);
+       int (*attach_dev)(struct iommu_domain *domain, struct device *dev);
+       void (*detach_dev)(struct iommu_domain *domain, struct device *dev);
+       int (*map)(struct iommu_domain *domain, unsigned long iova,
+                  phys_addr_t paddr, size_t size, int prot);
+       void (*unmap)(struct iommu_domain *domain, unsigned long iova,
+                     size_t size);
+       phys_addr_t (*iova_to_phys)(struct iommu_domain *domain,
+                                   unsigned long iova);
+};
+
+#ifdef CONFIG_IOMMU_API
+
+extern void register_iommu(struct iommu_ops *ops);
+extern bool iommu_found(void);
+extern struct iommu_domain *iommu_domain_alloc(void);
+extern void iommu_domain_free(struct iommu_domain *domain);
+extern int iommu_attach_device(struct iommu_domain *domain,
+                              struct device *dev);
+extern void iommu_detach_device(struct iommu_domain *domain,
+                               struct device *dev);
+extern int iommu_map_range(struct iommu_domain *domain, unsigned long iova,
+                          phys_addr_t paddr, size_t size, int prot);
+extern void iommu_unmap_range(struct iommu_domain *domain, unsigned long iova,
+                             size_t size);
+extern phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain,
+                                     unsigned long iova);
+
+#else /* CONFIG_IOMMU_API */
+
+static inline void register_iommu(struct iommu_ops *ops)
+{
+}
+
+static inline bool iommu_found(void)
+{
+       return false;
+}
+
+static inline struct iommu_domain *iommu_domain_alloc(void)
+{
+       return NULL;
+}
+
+static inline void iommu_domain_free(struct iommu_domain *domain)
+{
+}
+
+static inline int iommu_attach_device(struct iommu_domain *domain,
+                                     struct device *dev)
+{
+       return -ENODEV;
+}
+
+static inline void iommu_detach_device(struct iommu_domain *domain,
+                                      struct device *dev)
+{
+}
+
+static inline int iommu_map_range(struct iommu_domain *domain,
+                                 unsigned long iova, phys_addr_t paddr,
+                                 size_t size, int prot)
+{
+       return -ENODEV;
+}
+
+static inline void iommu_unmap_range(struct iommu_domain *domain,
+                                    unsigned long iova, size_t size)
+{
+}
+
+static inline phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain,
+                                            unsigned long iova)
+{
+       return 0;
+}
+
+#endif /* CONFIG_IOMMU_API */
+
+#endif /* __LINUX_IOMMU_H */
index c7d106ef22e2f535f2c78f470a300b5fb7e8b930..34456476e761330686a4e6d6afa98cf570fc94de 100644 (file)
@@ -329,6 +329,7 @@ enum jbd_state_bits {
        BH_State,               /* Pins most journal_head state */
        BH_JournalHead,         /* Pins bh->b_private and jh->b_bh */
        BH_Unshadow,            /* Dummy bit, for BJ_Shadow wakeup filtering */
+       BH_JBDPrivateStart,     /* First bit available for private use by FS */
 };
 
 BUFFER_FNS(JBD, jbd)
@@ -1007,6 +1008,35 @@ int __jbd2_journal_clean_checkpoint_list(journal_t *journal);
 int __jbd2_journal_remove_checkpoint(struct journal_head *);
 void __jbd2_journal_insert_checkpoint(struct journal_head *, transaction_t *);
 
+
+/*
+ * Triggers
+ */
+
+struct jbd2_buffer_trigger_type {
+       /*
+        * Fired just before a buffer is written to the journal.
+        * mapped_data is a mapped buffer that is the frozen data for
+        * commit.
+        */
+       void (*t_commit)(struct jbd2_buffer_trigger_type *type,
+                        struct buffer_head *bh, void *mapped_data,
+                        size_t size);
+
+       /*
+        * Fired during journal abort for dirty buffers that will not be
+        * committed.
+        */
+       void (*t_abort)(struct jbd2_buffer_trigger_type *type,
+                       struct buffer_head *bh);
+};
+
+extern void jbd2_buffer_commit_trigger(struct journal_head *jh,
+                                      void *mapped_data,
+                                      struct jbd2_buffer_trigger_type *triggers);
+extern void jbd2_buffer_abort_trigger(struct journal_head *jh,
+                                     struct jbd2_buffer_trigger_type *triggers);
+
 /* Buffer IO */
 extern int
 jbd2_journal_write_metadata_buffer(transaction_t         *transaction,
@@ -1045,6 +1075,8 @@ extern int         jbd2_journal_extend (handle_t *, int nblocks);
 extern int      jbd2_journal_get_write_access(handle_t *, struct buffer_head *);
 extern int      jbd2_journal_get_create_access (handle_t *, struct buffer_head *);
 extern int      jbd2_journal_get_undo_access(handle_t *, struct buffer_head *);
+void            jbd2_journal_set_triggers(struct buffer_head *,
+                                          struct jbd2_buffer_trigger_type *type);
 extern int      jbd2_journal_dirty_metadata (handle_t *, struct buffer_head *);
 extern void     jbd2_journal_release_buffer (handle_t *, struct buffer_head *);
 extern int      jbd2_journal_forget (handle_t *, struct buffer_head *);
index bb70ebb6a2d5bd9f7435387bb2eb4fa91cbce166..525aac3c97dfeca86b1a6801d07aec59c9e8599d 100644 (file)
@@ -12,6 +12,8 @@
 
 typedef unsigned int           tid_t;          /* Unique transaction ID */
 typedef struct transaction_s   transaction_t;  /* Compound transaction type */
+
+
 struct buffer_head;
 
 struct journal_head {
@@ -87,6 +89,12 @@ struct journal_head {
         * [j_list_lock]
         */
        struct journal_head *b_cpnext, *b_cpprev;
+
+       /* Trigger type */
+       struct jbd2_buffer_trigger_type *b_triggers;
+
+       /* Trigger type for the committing transaction's frozen data */
+       struct jbd2_buffer_trigger_type *b_frozen_triggers;
 };
 
 #endif         /* JOURNAL_HEAD_H_INCLUDED */
index 4ee4b3d2316ffc78495e7bfa0dd3017f220c05c9..570d2041311911352da76c830073f7c9aa314457 100644 (file)
@@ -79,10 +79,13 @@ static inline unsigned int kstat_irqs(unsigned int irq)
 }
 
 extern unsigned long long task_delta_exec(struct task_struct *);
-extern void account_user_time(struct task_struct *, cputime_t);
-extern void account_user_time_scaled(struct task_struct *, cputime_t);
-extern void account_system_time(struct task_struct *, int, cputime_t);
-extern void account_system_time_scaled(struct task_struct *, cputime_t);
-extern void account_steal_time(struct task_struct *, cputime_t);
+extern void account_user_time(struct task_struct *, cputime_t, cputime_t);
+extern void account_system_time(struct task_struct *, int, cputime_t, cputime_t);
+extern void account_steal_time(cputime_t);
+extern void account_idle_time(cputime_t);
+
+extern void account_process_tick(struct task_struct *, int user);
+extern void account_steal_ticks(unsigned long ticks);
+extern void account_idle_ticks(unsigned long ticks);
 
 #endif /* _LINUX_KERNEL_STAT_H */
index eafabd5c66b2951234d8d157520771514e9e83f0..ec49d0be7f5245614c00e566a5f3702bccd6fa5e 100644 (file)
@@ -316,6 +316,7 @@ struct kvm_assigned_dev_kernel {
 #define KVM_ASSIGNED_DEV_HOST_MSI      (1 << 9)
        unsigned long irq_requested_type;
        int irq_source_id;
+       int flags;
        struct pci_dev *dev;
        struct kvm *kvm;
 };
@@ -327,13 +328,16 @@ void kvm_unregister_irq_ack_notifier(struct kvm_irq_ack_notifier *kian);
 int kvm_request_irq_source_id(struct kvm *kvm);
 void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id);
 
-#ifdef CONFIG_DMAR
+#ifdef CONFIG_IOMMU_API
 int kvm_iommu_map_pages(struct kvm *kvm, gfn_t base_gfn,
                        unsigned long npages);
-int kvm_iommu_map_guest(struct kvm *kvm,
-                       struct kvm_assigned_dev_kernel *assigned_dev);
+int kvm_iommu_map_guest(struct kvm *kvm);
 int kvm_iommu_unmap_guest(struct kvm *kvm);
-#else /* CONFIG_DMAR */
+int kvm_assign_device(struct kvm *kvm,
+                     struct kvm_assigned_dev_kernel *assigned_dev);
+int kvm_deassign_device(struct kvm *kvm,
+                       struct kvm_assigned_dev_kernel *assigned_dev);
+#else /* CONFIG_IOMMU_API */
 static inline int kvm_iommu_map_pages(struct kvm *kvm,
                                      gfn_t base_gfn,
                                      unsigned long npages)
@@ -341,9 +345,7 @@ static inline int kvm_iommu_map_pages(struct kvm *kvm,
        return 0;
 }
 
-static inline int kvm_iommu_map_guest(struct kvm *kvm,
-                                     struct kvm_assigned_dev_kernel
-                                     *assigned_dev)
+static inline int kvm_iommu_map_guest(struct kvm *kvm)
 {
        return -ENODEV;
 }
@@ -352,7 +354,19 @@ static inline int kvm_iommu_unmap_guest(struct kvm *kvm)
 {
        return 0;
 }
-#endif /* CONFIG_DMAR */
+
+static inline int kvm_assign_device(struct kvm *kvm,
+               struct kvm_assigned_dev_kernel *assigned_dev)
+{
+       return 0;
+}
+
+static inline int kvm_deassign_device(struct kvm *kvm,
+               struct kvm_assigned_dev_kernel *assigned_dev)
+{
+       return 0;
+}
+#endif /* CONFIG_IOMMU_API */
 
 static inline void kvm_guest_enter(void)
 {
index 143cebf0586f140fd267bf360d69654281584d11..7ac8b500d55c3bf8d2202878348b8b0115579f43 100644 (file)
@@ -151,4 +151,6 @@ static inline void mmc_claim_host(struct mmc_host *host)
        __mmc_claim_host(host, NULL);
 }
 
+extern u32 mmc_vddrange_to_ocrmask(int vdd_min, int vdd_max);
+
 #endif
index f842f234e44f6eea4d64ff4df793e3e4da0a3c11..4e457256bd33dd18734a0f292c23d2404ee0b60f 100644 (file)
@@ -41,6 +41,7 @@ struct mmc_ios {
 
 #define MMC_BUS_WIDTH_1                0
 #define MMC_BUS_WIDTH_4                2
+#define MMC_BUS_WIDTH_8                3
 
        unsigned char   timing;                 /* timing specification used */
 
@@ -116,6 +117,7 @@ struct mmc_host {
 #define MMC_CAP_SDIO_IRQ       (1 << 3)        /* Can signal pending SDIO IRQs */
 #define MMC_CAP_SPI            (1 << 4)        /* Talks only SPI protocols */
 #define MMC_CAP_NEEDS_POLL     (1 << 5)        /* Needs polling for card-detection */
+#define MMC_CAP_8_BIT_DATA     (1 << 6)        /* Can the host do 8 bit transfers */
 
        /* host specific block data */
        unsigned int            max_seg_size;   /* see blk_queue_max_segment_size */
index 41e1224651cf98dacc97acf74d999a7c89233ec4..c28bbba3c23d8b720c7207df010798020f361d2b 100644 (file)
@@ -313,10 +313,11 @@ struct napi_struct {
 #ifdef CONFIG_NETPOLL
        spinlock_t              poll_lock;
        int                     poll_owner;
-       struct net_device       *dev;
 #endif
+       struct net_device       *dev;
        struct list_head        dev_list;
        struct sk_buff          *gro_list;
+       struct sk_buff          *skb;
 };
 
 enum
@@ -990,6 +991,9 @@ struct napi_gro_cb {
 
        /* Number of segments aggregated. */
        int count;
+
+       /* Free the skb? */
+       int free;
 };
 
 #define NAPI_GRO_CB(skb) ((struct napi_gro_cb *)(skb)->cb)
@@ -1011,6 +1015,14 @@ struct packet_type {
        struct list_head        list;
 };
 
+struct napi_gro_fraginfo {
+       skb_frag_t frags[MAX_SKB_FRAGS];
+       unsigned int nr_frags;
+       unsigned int ip_summed;
+       unsigned int len;
+       __wsum csum;
+};
+
 #include <linux/interrupt.h>
 #include <linux/notifier.h>
 
@@ -1363,6 +1375,8 @@ extern int                netif_receive_skb(struct sk_buff *skb);
 extern void            napi_gro_flush(struct napi_struct *napi);
 extern int             napi_gro_receive(struct napi_struct *napi,
                                         struct sk_buff *skb);
+extern int             napi_gro_frags(struct napi_struct *napi,
+                                      struct napi_gro_fraginfo *info);
 extern void            netif_nit_deliver(struct sk_buff *skb);
 extern int             dev_valid_name(const char *name);
 extern int             dev_ioctl(struct net *net, unsigned int cmd, void __user *);
index 709742be02f0a1bac5336d5e38b172a2b7d9f2b7..01ca0856caff38a8d910df0915e4bb6cc93be536 100644 (file)
@@ -241,7 +241,8 @@ unsigned find_get_pages_contig(struct address_space *mapping, pgoff_t start,
 unsigned find_get_pages_tag(struct address_space *mapping, pgoff_t *index,
                        int tag, unsigned int nr_pages, struct page **pages);
 
-struct page *__grab_cache_page(struct address_space *mapping, pgoff_t index);
+struct page *grab_cache_page_write_begin(struct address_space *mapping,
+                       pgoff_t index, unsigned flags);
 
 /*
  * Returns locked page at given index in given cache, creating it if needed.
index 40401b554484ceeafec0ca395097424f99acc2e9..d72d5d84fde54a02d54e8b7dbd580638ab1f67ff 100644 (file)
 #include <linux/errno.h>
 #include <linux/types.h>
 
-#define __DQUOT_VERSION__      "dquot_6.5.1"
-#define __DQUOT_NUM_VERSION__  6*10000+5*100+1
-
-/* Size of blocks in which are counted size limits */
-#define QUOTABLOCK_BITS 10
-#define QUOTABLOCK_SIZE (1 << QUOTABLOCK_BITS)
-
-/* Conversion routines from and to quota blocks */
-#define qb2kb(x) ((x) << (QUOTABLOCK_BITS-10))
-#define kb2qb(x) ((x) >> (QUOTABLOCK_BITS-10))
-#define toqb(x) (((x) + QUOTABLOCK_SIZE - 1) >> QUOTABLOCK_BITS)
+#define __DQUOT_VERSION__      "dquot_6.5.2"
 
 #define MAXQUOTAS 2
 #define USRQUOTA  0            /* element used for user quotas */
 #define Q_GETQUOTA 0x800007    /* get user quota structure */
 #define Q_SETQUOTA 0x800008    /* set user quota structure */
 
+/* Quota format type IDs */
+#define        QFMT_VFS_OLD 1
+#define        QFMT_VFS_V0 2
+
+/* Size of block in which space limits are passed through the quota
+ * interface */
+#define QIF_DQBLKSIZE_BITS 10
+#define QIF_DQBLKSIZE (1 << QIF_DQBLKSIZE_BITS)
+
 /*
  * Quota structure used for communication with userspace via quotactl
  * Following flags are used to specify which fields are valid
  */
-#define QIF_BLIMITS    1
-#define QIF_SPACE      2
-#define QIF_ILIMITS    4
-#define QIF_INODES     8
-#define QIF_BTIME      16
-#define QIF_ITIME      32
+enum {
+       QIF_BLIMITS_B = 0,
+       QIF_SPACE_B,
+       QIF_ILIMITS_B,
+       QIF_INODES_B,
+       QIF_BTIME_B,
+       QIF_ITIME_B,
+};
+
+#define QIF_BLIMITS    (1 << QIF_BLIMITS_B)
+#define QIF_SPACE      (1 << QIF_SPACE_B)
+#define QIF_ILIMITS    (1 << QIF_ILIMITS_B)
+#define QIF_INODES     (1 << QIF_INODES_B)
+#define QIF_BTIME      (1 << QIF_BTIME_B)
+#define QIF_ITIME      (1 << QIF_ITIME_B)
 #define QIF_LIMITS     (QIF_BLIMITS | QIF_ILIMITS)
 #define QIF_USAGE      (QIF_SPACE | QIF_INODES)
 #define QIF_TIMES      (QIF_BTIME | QIF_ITIME)
@@ -172,7 +180,7 @@ enum {
 #include <asm/atomic.h>
 
 typedef __kernel_uid32_t qid_t; /* Type in which we store ids in memory */
-typedef __u64 qsize_t;          /* Type in which we store sizes */
+typedef long long qsize_t;     /* Type in which we store sizes */
 
 extern spinlock_t dq_data_lock;
 
@@ -187,12 +195,12 @@ extern spinlock_t dq_data_lock;
  * Data for one user/group kept in memory
  */
 struct mem_dqblk {
-       __u32 dqb_bhardlimit;   /* absolute limit on disk blks alloc */
-       __u32 dqb_bsoftlimit;   /* preferred limit on disk blks */
+       qsize_t dqb_bhardlimit; /* absolute limit on disk blks alloc */
+       qsize_t dqb_bsoftlimit; /* preferred limit on disk blks */
        qsize_t dqb_curspace;   /* current used space */
-       __u32 dqb_ihardlimit;   /* absolute limit on allocated inodes */
-       __u32 dqb_isoftlimit;   /* preferred inode limit */
-       __u32 dqb_curinodes;    /* current # allocated inodes */
+       qsize_t dqb_ihardlimit; /* absolute limit on allocated inodes */
+       qsize_t dqb_isoftlimit; /* preferred inode limit */
+       qsize_t dqb_curinodes;  /* current # allocated inodes */
        time_t dqb_btime;       /* time limit for excessive disk use */
        time_t dqb_itime;       /* time limit for excessive inode use */
 };
@@ -212,10 +220,7 @@ struct mem_dqinfo {
        unsigned int dqi_igrace;
        qsize_t dqi_maxblimit;
        qsize_t dqi_maxilimit;
-       union {
-               struct v1_mem_dqinfo v1_i;
-               struct v2_mem_dqinfo v2_i;
-       } u;
+       void *dqi_priv;
 };
 
 struct super_block;
@@ -249,6 +254,11 @@ extern struct dqstats dqstats;
 #define DQ_FAKE_B      3       /* no limits only usage */
 #define DQ_READ_B      4       /* dquot was read into memory */
 #define DQ_ACTIVE_B    5       /* dquot is active (dquot_release not called) */
+#define DQ_LASTSET_B   6       /* Following 6 bits (see QIF_) are reserved\
+                                * for the mask of entries set via SETQUOTA\
+                                * quotactl. They are set under dq_data_lock\
+                                * and the quota format handling dquot can\
+                                * clear them when it sees fit. */
 
 struct dquot {
        struct hlist_node dq_hash;      /* Hash list in memory */
@@ -287,11 +297,13 @@ struct dquot_operations {
        int (*initialize) (struct inode *, int);
        int (*drop) (struct inode *);
        int (*alloc_space) (struct inode *, qsize_t, int);
-       int (*alloc_inode) (const struct inode *, unsigned long);
+       int (*alloc_inode) (const struct inode *, qsize_t);
        int (*free_space) (struct inode *, qsize_t);
-       int (*free_inode) (const struct inode *, unsigned long);
+       int (*free_inode) (const struct inode *, qsize_t);
        int (*transfer) (struct inode *, struct iattr *);
        int (*write_dquot) (struct dquot *);            /* Ordinary dquot write */
+       struct dquot *(*alloc_dquot)(struct super_block *, int);        /* Allocate memory for new dquot */
+       void (*destroy_dquot)(struct dquot *);          /* Free memory for dquot */
        int (*acquire_dquot) (struct dquot *);          /* Quota is going to be created on disk */
        int (*release_dquot) (struct dquot *);          /* Quota is going to be deleted from disk */
        int (*mark_dirty) (struct dquot *);             /* Dquot is marked dirty */
@@ -320,12 +332,42 @@ struct quota_format_type {
        struct quota_format_type *qf_next;
 };
 
-#define DQUOT_USR_ENABLED      0x01            /* User diskquotas enabled */
-#define DQUOT_GRP_ENABLED      0x02            /* Group diskquotas enabled */
-#define DQUOT_USR_SUSPENDED    0x04            /* User diskquotas are off, but
+/* Quota state flags - they actually come in two flavors - for users and groups */
+enum {
+       _DQUOT_USAGE_ENABLED = 0,               /* Track disk usage for users */
+       _DQUOT_LIMITS_ENABLED,                  /* Enforce quota limits for users */
+       _DQUOT_SUSPENDED,                       /* User diskquotas are off, but
                                                 * we have necessary info in
                                                 * memory to turn them on */
-#define DQUOT_GRP_SUSPENDED    0x08            /* The same for group quotas */
+       _DQUOT_STATE_FLAGS
+};
+#define DQUOT_USAGE_ENABLED    (1 << _DQUOT_USAGE_ENABLED)
+#define DQUOT_LIMITS_ENABLED   (1 << _DQUOT_LIMITS_ENABLED)
+#define DQUOT_SUSPENDED                (1 << _DQUOT_SUSPENDED)
+#define DQUOT_STATE_FLAGS      (DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED | \
+                                DQUOT_SUSPENDED)
+/* Other quota flags */
+#define DQUOT_QUOTA_SYS_FILE   (1 << 6)        /* Quota file is a special
+                                                * system file and user cannot
+                                                * touch it. Filesystem is
+                                                * responsible for setting
+                                                * S_NOQUOTA, S_NOATIME flags
+                                                */
+#define DQUOT_NEGATIVE_USAGE   (1 << 7)        /* Allow negative quota usage */
+
+static inline unsigned int dquot_state_flag(unsigned int flags, int type)
+{
+       if (type == USRQUOTA)
+               return flags;
+       return flags << _DQUOT_STATE_FLAGS;
+}
+
+static inline unsigned int dquot_generic_flag(unsigned int flags, int type)
+{
+       if (type == USRQUOTA)
+               return flags;
+       return flags >> _DQUOT_STATE_FLAGS;
+}
 
 struct quota_info {
        unsigned int flags;                     /* Flags for diskquotas on this device */
index a558a4c1d35a2a10eea7d0017fc5326133b8faf4..21b781a3350f6cb939ae53510095341603edc99d 100644 (file)
@@ -24,12 +24,21 @@ void sync_dquots(struct super_block *sb, int type);
 
 int dquot_initialize(struct inode *inode, int type);
 int dquot_drop(struct inode *inode);
+int dquot_drop_locked(struct inode *inode);
+struct dquot *dqget(struct super_block *sb, unsigned int id, int type);
+void dqput(struct dquot *dquot);
+int dquot_is_cached(struct super_block *sb, unsigned int id, int type);
+int dquot_scan_active(struct super_block *sb,
+                     int (*fn)(struct dquot *dquot, unsigned long priv),
+                     unsigned long priv);
+struct dquot *dquot_alloc(struct super_block *sb, int type);
+void dquot_destroy(struct dquot *dquot);
 
 int dquot_alloc_space(struct inode *inode, qsize_t number, int prealloc);
-int dquot_alloc_inode(const struct inode *inode, unsigned long number);
+int dquot_alloc_inode(const struct inode *inode, qsize_t number);
 
 int dquot_free_space(struct inode *inode, qsize_t number);
-int dquot_free_inode(const struct inode *inode, unsigned long number);
+int dquot_free_inode(const struct inode *inode, qsize_t number);
 
 int dquot_transfer(struct inode *inode, struct iattr *iattr);
 int dquot_commit(struct dquot *dquot);
@@ -40,11 +49,14 @@ int dquot_mark_dquot_dirty(struct dquot *dquot);
 
 int vfs_quota_on(struct super_block *sb, int type, int format_id,
        char *path, int remount);
+int vfs_quota_enable(struct inode *inode, int type, int format_id,
+       unsigned int flags);
 int vfs_quota_on_path(struct super_block *sb, int type, int format_id,
        struct path *path);
 int vfs_quota_on_mount(struct super_block *sb, char *qf_name,
        int format_id, int type);
 int vfs_quota_off(struct super_block *sb, int type, int remount);
+int vfs_quota_disable(struct super_block *sb, int type, unsigned int flags);
 int vfs_quota_sync(struct super_block *sb, int type);
 int vfs_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
 int vfs_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
@@ -64,24 +76,22 @@ static inline struct mem_dqinfo *sb_dqinfo(struct super_block *sb, int type)
  * Functions for checking status of quota
  */
 
-static inline int sb_has_quota_enabled(struct super_block *sb, int type)
+static inline int sb_has_quota_usage_enabled(struct super_block *sb, int type)
 {
-       if (type == USRQUOTA)
-               return sb_dqopt(sb)->flags & DQUOT_USR_ENABLED;
-       return sb_dqopt(sb)->flags & DQUOT_GRP_ENABLED;
+       return sb_dqopt(sb)->flags &
+                               dquot_state_flag(DQUOT_USAGE_ENABLED, type);
 }
 
-static inline int sb_any_quota_enabled(struct super_block *sb)
+static inline int sb_has_quota_limits_enabled(struct super_block *sb, int type)
 {
-       return sb_has_quota_enabled(sb, USRQUOTA) ||
-               sb_has_quota_enabled(sb, GRPQUOTA);
+       return sb_dqopt(sb)->flags &
+                               dquot_state_flag(DQUOT_LIMITS_ENABLED, type);
 }
 
 static inline int sb_has_quota_suspended(struct super_block *sb, int type)
 {
-       if (type == USRQUOTA)
-               return sb_dqopt(sb)->flags & DQUOT_USR_SUSPENDED;
-       return sb_dqopt(sb)->flags & DQUOT_GRP_SUSPENDED;
+       return sb_dqopt(sb)->flags &
+                               dquot_state_flag(DQUOT_SUSPENDED, type);
 }
 
 static inline int sb_any_quota_suspended(struct super_block *sb)
@@ -90,6 +100,31 @@ static inline int sb_any_quota_suspended(struct super_block *sb)
                sb_has_quota_suspended(sb, GRPQUOTA);
 }
 
+/* Does kernel know about any quota information for given sb + type? */
+static inline int sb_has_quota_loaded(struct super_block *sb, int type)
+{
+       /* Currently if anything is on, then quota usage is on as well */
+       return sb_has_quota_usage_enabled(sb, type);
+}
+
+static inline int sb_any_quota_loaded(struct super_block *sb)
+{
+       return sb_has_quota_loaded(sb, USRQUOTA) ||
+               sb_has_quota_loaded(sb, GRPQUOTA);
+}
+
+static inline int sb_has_quota_active(struct super_block *sb, int type)
+{
+       return sb_has_quota_loaded(sb, type) &&
+              !sb_has_quota_suspended(sb, type);
+}
+
+static inline int sb_any_quota_active(struct super_block *sb)
+{
+       return sb_has_quota_active(sb, USRQUOTA) ||
+              sb_has_quota_active(sb, GRPQUOTA);
+}
+
 /*
  * Operations supported for diskquotas.
  */
@@ -104,7 +139,7 @@ extern struct quotactl_ops vfs_quotactl_ops;
 static inline void vfs_dq_init(struct inode *inode)
 {
        BUG_ON(!inode->i_sb);
-       if (sb_any_quota_enabled(inode->i_sb) && !IS_NOQUOTA(inode))
+       if (sb_any_quota_active(inode->i_sb) && !IS_NOQUOTA(inode))
                inode->i_sb->dq_op->initialize(inode, -1);
 }
 
@@ -112,7 +147,7 @@ static inline void vfs_dq_init(struct inode *inode)
  * a transaction (deadlocks possible otherwise) */
 static inline int vfs_dq_prealloc_space_nodirty(struct inode *inode, qsize_t nr)
 {
-       if (sb_any_quota_enabled(inode->i_sb)) {
+       if (sb_any_quota_active(inode->i_sb)) {
                /* Used space is updated in alloc_space() */
                if (inode->i_sb->dq_op->alloc_space(inode, nr, 1) == NO_QUOTA)
                        return 1;
@@ -132,7 +167,7 @@ static inline int vfs_dq_prealloc_space(struct inode *inode, qsize_t nr)
 
 static inline int vfs_dq_alloc_space_nodirty(struct inode *inode, qsize_t nr)
 {
-       if (sb_any_quota_enabled(inode->i_sb)) {
+       if (sb_any_quota_active(inode->i_sb)) {
                /* Used space is updated in alloc_space() */
                if (inode->i_sb->dq_op->alloc_space(inode, nr, 0) == NO_QUOTA)
                        return 1;
@@ -152,7 +187,7 @@ static inline int vfs_dq_alloc_space(struct inode *inode, qsize_t nr)
 
 static inline int vfs_dq_alloc_inode(struct inode *inode)
 {
-       if (sb_any_quota_enabled(inode->i_sb)) {
+       if (sb_any_quota_active(inode->i_sb)) {
                vfs_dq_init(inode);
                if (inode->i_sb->dq_op->alloc_inode(inode, 1) == NO_QUOTA)
                        return 1;
@@ -162,7 +197,7 @@ static inline int vfs_dq_alloc_inode(struct inode *inode)
 
 static inline void vfs_dq_free_space_nodirty(struct inode *inode, qsize_t nr)
 {
-       if (sb_any_quota_enabled(inode->i_sb))
+       if (sb_any_quota_active(inode->i_sb))
                inode->i_sb->dq_op->free_space(inode, nr);
        else
                inode_sub_bytes(inode, nr);
@@ -176,7 +211,7 @@ static inline void vfs_dq_free_space(struct inode *inode, qsize_t nr)
 
 static inline void vfs_dq_free_inode(struct inode *inode)
 {
-       if (sb_any_quota_enabled(inode->i_sb))
+       if (sb_any_quota_active(inode->i_sb))
                inode->i_sb->dq_op->free_inode(inode, 1);
 }
 
@@ -197,12 +232,12 @@ static inline int vfs_dq_off(struct super_block *sb, int remount)
 
 #else
 
-static inline int sb_has_quota_enabled(struct super_block *sb, int type)
+static inline int sb_has_quota_usage_enabled(struct super_block *sb, int type)
 {
        return 0;
 }
 
-static inline int sb_any_quota_enabled(struct super_block *sb)
+static inline int sb_has_quota_limits_enabled(struct super_block *sb, int type)
 {
        return 0;
 }
@@ -217,6 +252,27 @@ static inline int sb_any_quota_suspended(struct super_block *sb)
        return 0;
 }
 
+/* Does kernel know about any quota information for given sb + type? */
+static inline int sb_has_quota_loaded(struct super_block *sb, int type)
+{
+       return 0;
+}
+
+static inline int sb_any_quota_loaded(struct super_block *sb)
+{
+       return 0;
+}
+
+static inline int sb_has_quota_active(struct super_block *sb, int type)
+{
+       return 0;
+}
+
+static inline int sb_any_quota_active(struct super_block *sb)
+{
+       return 0;
+}
+
 /*
  * NO-OP when quota not configured.
  */
index a916c6660dfa0ac94d9c08768b9b627470985247..355f6e80db0d3e8afd4de9d4bcf447ec4e637ea3 100644 (file)
@@ -136,7 +136,7 @@ do {                                                                        \
  */
 static inline void *radix_tree_deref_slot(void **pslot)
 {
-       void *ret = *pslot;
+       void *ret = rcu_dereference(*pslot);
        if (unlikely(radix_tree_is_indirect_ptr(ret)))
                ret = RADIX_TREE_RETRY;
        return ret;
index adbf3bd3c6b3c8edea3e313a4abce0a736d02ebf..407ea3646f8f12f05a0410166f3ff2e6fa4a447e 100644 (file)
@@ -45,56 +45,6 @@ struct rand_pool_info {
 
 extern void rand_initialize_irq(int irq);
 
-struct timer_rand_state;
-#ifndef CONFIG_SPARSE_IRQ
-
-extern struct timer_rand_state *irq_timer_state[];
-
-static inline struct timer_rand_state *get_timer_rand_state(unsigned int irq)
-{
-       if (irq >= nr_irqs)
-               return NULL;
-
-       return irq_timer_state[irq];
-}
-
-static inline void set_timer_rand_state(unsigned int irq, struct timer_rand_state *state)
-{
-       if (irq >= nr_irqs)
-               return;
-
-       irq_timer_state[irq] = state;
-}
-
-#else
-
-#include <linux/irq.h>
-static inline struct timer_rand_state *get_timer_rand_state(unsigned int irq)
-{
-       struct irq_desc *desc;
-
-       desc = irq_to_desc(irq);
-
-       if (!desc)
-               return NULL;
-
-       return desc->timer_rand_state;
-}
-
-static inline void set_timer_rand_state(unsigned int irq, struct timer_rand_state *state)
-{
-       struct irq_desc *desc;
-
-       desc = irq_to_desc(irq);
-
-       if (!desc)
-               return;
-
-       desc->timer_rand_state = state;
-}
-#endif
-
-
 extern void add_input_randomness(unsigned int type, unsigned int code,
                                 unsigned int value);
 extern void add_interrupt_randomness(int irq);
index 301dda829e37499f5cdaa0950e3a11f0c4ed3b74..f3f697df1d71b439b677efbc0da952ae6d25d066 100644 (file)
@@ -59,8 +59,8 @@ struct rcu_ctrlblk {
        int     signaled;
 
        spinlock_t      lock    ____cacheline_internodealigned_in_smp;
-       cpumask_t       cpumask; /* CPUs that need to switch in order    */
-                                /* for current batch to proceed.        */
+       DECLARE_BITMAP(cpumask, NR_CPUS); /* CPUs that need to switch for */
+                                         /* current batch to proceed.     */
 } ____cacheline_internodealigned_in_smp;
 
 /* Is batch a before batch b ? */
index 91f597ad6acc5d1659f66f90039408b01b23e8b5..4046b75563c1c26dc8d11352b77c73139d1b99ce 100644 (file)
@@ -145,6 +145,8 @@ struct rtc_class_ops {
        int (*irq_set_state)(struct device *, int enabled);
        int (*irq_set_freq)(struct device *, int freq);
        int (*read_callback)(struct device *, int data);
+       int (*alarm_irq_enable)(struct device *, unsigned int enabled);
+       int (*update_irq_enable)(struct device *, unsigned int enabled);
 };
 
 #define RTC_DEVICE_NAME_SIZE 20
@@ -181,7 +183,7 @@ struct rtc_device
        struct timer_list uie_timer;
        /* Those fields are protected by rtc->irq_lock */
        unsigned int oldsecs;
-       unsigned int irq_active:1;
+       unsigned int uie_irq_active:1;
        unsigned int stop_uie_polling:1;
        unsigned int uie_task_active:1;
        unsigned int uie_timer_active:1;
@@ -216,6 +218,10 @@ extern int rtc_irq_set_state(struct rtc_device *rtc,
                                struct rtc_task *task, int enabled);
 extern int rtc_irq_set_freq(struct rtc_device *rtc,
                                struct rtc_task *task, int freq);
+extern int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled);
+extern int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled);
+extern int rtc_dev_update_irq_enable_emul(struct rtc_device *rtc,
+                                               unsigned int enabled);
 
 typedef struct rtc_task {
        void (*func)(void *private_data);
index 158d53d07765888af5c2e7bdc4515373983d930e..38a3f4b1539466cb1bd483c1b2daa6d1e2dc42ab 100644 (file)
@@ -284,7 +284,6 @@ long io_schedule_timeout(long timeout);
 
 extern void cpu_init (void);
 extern void trap_init(void);
-extern void account_process_tick(struct task_struct *task, int user);
 extern void update_process_times(int user);
 extern void scheduler_tick(void);
 
index b3dfa72f13b902bd48275ac923b551f0375d7e0f..40ea5058c2ec0ced97079290c08cd5bac08d1dca 100644 (file)
@@ -50,10 +50,11 @@ int seq_path(struct seq_file *, struct path *, char *);
 int seq_dentry(struct seq_file *, struct dentry *, char *);
 int seq_path_root(struct seq_file *m, struct path *path, struct path *root,
                  char *esc);
-int seq_bitmap(struct seq_file *m, unsigned long *bits, unsigned int nr_bits);
-static inline int seq_cpumask(struct seq_file *m, cpumask_t *mask)
+int seq_bitmap(struct seq_file *m, const unsigned long *bits,
+                                  unsigned int nr_bits);
+static inline int seq_cpumask(struct seq_file *m, const struct cpumask *mask)
 {
-       return seq_bitmap(m, mask->bits, NR_CPUS);
+       return seq_bitmap(m, mask->bits, nr_cpu_ids);
 }
 
 static inline int seq_nodemask(struct seq_file *m, nodemask_t *mask)
index 6e7ba16ff454f878d28315c02f66572b9734bd09..b824669681014502e1f1d0972ad5d9f775d274cb 100644 (file)
@@ -21,6 +21,9 @@ struct call_single_data {
        u16 priv;
 };
 
+/* total number of cpus in this system (may exceed NR_CPUS) */
+extern unsigned int total_cpus;
+
 #ifdef CONFIG_SMP
 
 #include <linux/preempt.h>
@@ -64,15 +67,16 @@ extern void smp_cpus_done(unsigned int max_cpus);
  * Call a function on all other processors
  */
 int smp_call_function(void(*func)(void *info), void *info, int wait);
-/* Deprecated: use smp_call_function_many() which uses a cpumask ptr. */
-int smp_call_function_mask(cpumask_t mask, void(*func)(void *info), void *info,
-                               int wait);
+void smp_call_function_many(const struct cpumask *mask,
+                           void (*func)(void *info), void *info, bool wait);
 
-static inline void smp_call_function_many(const struct cpumask *mask,
-                                         void (*func)(void *info), void *info,
-                                         int wait)
+/* Deprecated: Use smp_call_function_many which takes a pointer to the mask. */
+static inline int
+smp_call_function_mask(cpumask_t mask, void(*func)(void *info), void *info,
+                      int wait)
 {
-       smp_call_function_mask(*mask, func, info, wait);
+       smp_call_function_many(&mask, func, info, wait);
+       return 0;
 }
 
 int smp_call_function_single(int cpuid, void (*func) (void *info), void *info,
index a3626aedaec9350f9f17b19a12a6ade89a561b5c..0f4eb165f2542fbafcfe6433c0fa0ef8f8396260 100644 (file)
@@ -1,9 +1,10 @@
 #ifndef __LINUX_SPI_MMC_SPI_H
 #define __LINUX_SPI_MMC_SPI_H
 
+#include <linux/device.h>
+#include <linux/spi/spi.h>
 #include <linux/interrupt.h>
 
-struct device;
 struct mmc_host;
 
 /* Put this in platform_data of a device being used to manage an MMC/SD
@@ -41,4 +42,16 @@ struct mmc_spi_platform_data {
        void (*setpower)(struct device *, unsigned int maskval);
 };
 
+#ifdef CONFIG_OF
+extern struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi);
+extern void mmc_spi_put_pdata(struct spi_device *spi);
+#else
+static inline struct mmc_spi_platform_data *
+mmc_spi_get_pdata(struct spi_device *spi)
+{
+       return spi->dev.platform_data;
+}
+static inline void mmc_spi_put_pdata(struct spi_device *spi) {}
+#endif /* CONFIG_OF */
+
 #endif /* __LINUX_SPI_MMC_SPI_H */
index 4be01bb4437748c27f80aa79733c3a1360ca13e0..82229317753d53286df8843eeb86f88d50cb7457 100644 (file)
@@ -19,6 +19,8 @@
 #ifndef __LINUX_SPI_H
 #define __LINUX_SPI_H
 
+#include <linux/device.h>
+
 /*
  * INTERFACES between SPI master-side drivers and SPI infrastructure.
  * (There's no SPI slave support for Linux yet...)
index faf1519b5adc5235aab952baeb6876083e21c5ab..74d59a641362ea758911b0f647ca10f4e059ea79 100644 (file)
@@ -23,7 +23,7 @@
  *
  * This can be thought of as a very heavy write lock, equivalent to
  * grabbing every spinlock in the kernel. */
-int stop_machine(int (*fn)(void *), void *data, const cpumask_t *cpus);
+int stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus);
 
 /**
  * __stop_machine: freeze the machine on all CPUs and run this function
@@ -34,11 +34,11 @@ int stop_machine(int (*fn)(void *), void *data, const cpumask_t *cpus);
  * Description: This is a special version of the above, which assumes cpus
  * won't come or go while it's being called.  Used by hotplug cpu.
  */
-int __stop_machine(int (*fn)(void *), void *data, const cpumask_t *cpus);
+int __stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus);
 #else
 
 static inline int stop_machine(int (*fn)(void *), void *data,
-                              const cpumask_t *cpus)
+                              const struct cpumask *cpus)
 {
        int ret;
        local_irq_disable();
index 04fb47bfb920d317c4b5217ebfbb1602e7606d90..18d0a243a7b3a8cd98e05386c10ac697258bbb56 100644 (file)
@@ -549,7 +549,7 @@ asmlinkage long sys_inotify_init(void);
 asmlinkage long sys_inotify_init1(int flags);
 asmlinkage long sys_inotify_add_watch(int fd, const char __user *path,
                                        u32 mask);
-asmlinkage long sys_inotify_rm_watch(int fd, u32 wd);
+asmlinkage long sys_inotify_rm_watch(int fd, __s32 wd);
 
 asmlinkage long sys_spu_run(int fd, __u32 __user *unpc,
                                 __u32 __user *ustatus);
index 38d1a5d6568e8dece38c80cb279f1c4fbbed41a1..052b12bec8bdabf7a4c8b7af652eb83550c01a93 100644 (file)
@@ -8,17 +8,17 @@
  */
 
 /*
- * Maximum supported processors that can run under SMP.  This value is
- * set via configure setting.  The maximum is equal to the size of the
- * bitmasks used on that platform, i.e. 32 or 64.  Setting this smaller
- * saves quite a bit of memory.
+ * Maximum supported processors.  Setting this smaller saves quite a
+ * bit of memory.  Use nr_cpu_ids instead of this except for static bitmaps.
  */
-#ifdef CONFIG_SMP
-#define NR_CPUS                CONFIG_NR_CPUS
-#else
-#define NR_CPUS                1
+#ifndef CONFIG_NR_CPUS
+/* FIXME: This should be fixed in the arch's Kconfig */
+#define CONFIG_NR_CPUS 1
 #endif
 
+/* Places which use this should consider cpumask_var_t. */
+#define NR_CPUS                CONFIG_NR_CPUS
+
 #define MIN_THREADS_LEFT_FOR_ROOT 4
 
 /*
index b6ec8189ac0c16673689f5327cde1d78b3ab49d6..469b82d88b3b133b5bbadf5b72304f5657f2b961 100644 (file)
@@ -84,10 +84,10 @@ static inline void tick_cancel_sched_timer(int cpu) { }
 
 # ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
 extern struct tick_device *tick_get_broadcast_device(void);
-extern cpumask_t *tick_get_broadcast_mask(void);
+extern struct cpumask *tick_get_broadcast_mask(void);
 
 #  ifdef CONFIG_TICK_ONESHOT
-extern cpumask_t *tick_get_broadcast_oneshot_mask(void);
+extern struct cpumask *tick_get_broadcast_oneshot_mask(void);
 #  endif
 
 # endif /* BROADCAST */
index 1f126e30766cbb42d41557bf2a4aed6192f354ba..5571dbe1c0addb74d48809925f2b09ff7bd144f3 100644 (file)
@@ -1370,25 +1370,41 @@ struct v4l2_streamparm {
 /*
  *     A D V A N C E D   D E B U G G I N G
  *
- *     NOTE: EXPERIMENTAL API
+ *     NOTE: EXPERIMENTAL API, NEVER RELY ON THIS IN APPLICATIONS!
+ *     FOR DEBUGGING, TESTING AND INTERNAL USE ONLY!
  */
 
 /* VIDIOC_DBG_G_REGISTER and VIDIOC_DBG_S_REGISTER */
 
 #define V4L2_CHIP_MATCH_HOST       0  /* Match against chip ID on host (0 for the host) */
-#define V4L2_CHIP_MATCH_I2C_DRIVER 1  /* Match against I2C driver ID */
+#define V4L2_CHIP_MATCH_I2C_DRIVER 1  /* Match against I2C driver name */
 #define V4L2_CHIP_MATCH_I2C_ADDR   2  /* Match against I2C 7-bit address */
 #define V4L2_CHIP_MATCH_AC97       3  /* Match against anciliary AC97 chip */
 
-struct v4l2_register {
-       __u32 match_type; /* Match type */
-       __u32 match_chip; /* Match this chip, meaning determined by match_type */
+struct v4l2_dbg_match {
+       __u32 type; /* Match type */
+       union {     /* Match this chip, meaning determined by type */
+               __u32 addr;
+               char name[32];
+       };
+} __attribute__ ((packed));
+
+struct v4l2_dbg_register {
+       struct v4l2_dbg_match match;
+       __u32 size;     /* register size in bytes */
        __u64 reg;
        __u64 val;
-};
+} __attribute__ ((packed));
+
+/* VIDIOC_DBG_G_CHIP_IDENT */
+struct v4l2_dbg_chip_ident {
+       struct v4l2_dbg_match match;
+       __u32 ident;       /* chip identifier as specified in <media/v4l2-chip-ident.h> */
+       __u32 revision;    /* chip revision, chip specific */
+} __attribute__ ((packed));
 
-/* VIDIOC_G_CHIP_IDENT */
-struct v4l2_chip_ident {
+/* VIDIOC_G_CHIP_IDENT_OLD: Deprecated, do not use */
+struct v4l2_chip_ident_old {
        __u32 match_type;  /* Match type */
        __u32 match_chip;  /* Match this chip, meaning determined by match_type */
        __u32 ident;       /* chip identifier as specified in <media/v4l2-chip-ident.h> */
@@ -1460,13 +1476,22 @@ struct v4l2_chip_ident {
 #define VIDIOC_G_ENC_INDEX       _IOR('V', 76, struct v4l2_enc_idx)
 #define VIDIOC_ENCODER_CMD      _IOWR('V', 77, struct v4l2_encoder_cmd)
 #define VIDIOC_TRY_ENCODER_CMD  _IOWR('V', 78, struct v4l2_encoder_cmd)
+#endif
 
-/* Experimental, only implemented if CONFIG_VIDEO_ADV_DEBUG is defined */
-#define        VIDIOC_DBG_S_REGISTER    _IOW('V', 79, struct v4l2_register)
-#define        VIDIOC_DBG_G_REGISTER   _IOWR('V', 80, struct v4l2_register)
-
-#define VIDIOC_G_CHIP_IDENT     _IOWR('V', 81, struct v4l2_chip_ident)
+#if 1
+/* Experimental, meant for debugging, testing and internal use.
+   Only implemented if CONFIG_VIDEO_ADV_DEBUG is defined.
+   You must be root to use these ioctls. Never use these in applications! */
+#define        VIDIOC_DBG_S_REGISTER    _IOW('V', 79, struct v4l2_dbg_register)
+#define        VIDIOC_DBG_G_REGISTER   _IOWR('V', 80, struct v4l2_dbg_register)
+
+/* Experimental, meant for debugging, testing and internal use.
+   Never use this ioctl in applications! */
+#define VIDIOC_DBG_G_CHIP_IDENT _IOWR('V', 81, struct v4l2_dbg_chip_ident)
+/* This is deprecated and will go away in 2.6.30 */
+#define VIDIOC_G_CHIP_IDENT_OLD _IOWR('V', 81, struct v4l2_chip_ident_old)
 #endif
+
 #define VIDIOC_S_HW_FREQ_SEEK   _IOW('V', 82, struct v4l2_hw_freq_seek)
 /* Reminder: when adding new ioctls please add support for them to
    drivers/media/video/v4l2-compat-ioctl32.c as well! */
index 6bbb0d93bb5f39b34a368a450b73caae2eeccd66..c8d0b23fde295542d02c86421cdfc6e305383bd2 100644 (file)
@@ -177,9 +177,9 @@ struct saa7146_ext_vv
        int (*std_callback)(struct saa7146_dev*, struct saa7146_standard *);
 
        struct saa7146_extension_ioctls *ioctls;
-       int (*ioctl)(struct saa7146_fh*, unsigned int cmd, void *arg);
+       long (*ioctl)(struct saa7146_fh *, unsigned int cmd, void *arg);
 
-       struct file_operations vbi_fops;
+       struct v4l2_file_operations vbi_fops;
 };
 
 struct saa7146_use_ops  {
@@ -216,7 +216,7 @@ void saa7146_set_gpio(struct saa7146_dev *saa, u8 pin, u8 data);
 extern struct saa7146_use_ops saa7146_video_uops;
 int saa7146_start_preview(struct saa7146_fh *fh);
 int saa7146_stop_preview(struct saa7146_fh *fh);
-int saa7146_video_do_ioctl(struct file *file, unsigned int cmd, void *arg);
+long saa7146_video_do_ioctl(struct file *file, unsigned int cmd, void *arg);
 
 /* from saa7146_vbi.c */
 extern struct saa7146_use_ops saa7146_vbi_uops;
index 425b6a98c95c220e703cb98a5b2eb32a04bb2f08..7440d9250665489f2699fc1557bc1a7ae655b337 100644 (file)
@@ -164,12 +164,12 @@ struct soc_camera_ops {
        unsigned long (*query_bus_param)(struct soc_camera_device *);
        int (*set_bus_param)(struct soc_camera_device *, unsigned long);
        int (*get_chip_id)(struct soc_camera_device *,
-                          struct v4l2_chip_ident *);
+                          struct v4l2_dbg_chip_ident *);
        int (*set_std)(struct soc_camera_device *, v4l2_std_id *);
        int (*enum_input)(struct soc_camera_device *, struct v4l2_input *);
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-       int (*get_register)(struct soc_camera_device *, struct v4l2_register *);
-       int (*set_register)(struct soc_camera_device *, struct v4l2_register *);
+       int (*get_register)(struct soc_camera_device *, struct v4l2_dbg_register *);
+       int (*set_register)(struct soc_camera_device *, struct v4l2_dbg_register *);
 #endif
        int (*get_control)(struct soc_camera_device *, struct v4l2_control *);
        int (*set_control)(struct soc_camera_device *, struct v4l2_control *);
index 43dbb659f1f57533f6cba2bd8df37ff5d47591c5..9aaf652b20ef7a3ff638e171906f60231de68161 100644 (file)
@@ -2,7 +2,7 @@
     v4l2 chip identifiers header
 
     This header provides a list of chip identifiers that can be returned
-    through the VIDIOC_G_CHIP_IDENT ioctl.
+    through the VIDIOC_DBG_G_CHIP_IDENT ioctl.
 
     Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
 
@@ -24,7 +24,7 @@
 #ifndef V4L2_CHIP_IDENT_H_
 #define V4L2_CHIP_IDENT_H_
 
-/* VIDIOC_G_CHIP_IDENT: identifies the actual chip installed on the board */
+/* VIDIOC_DBG_G_CHIP_IDENT: identifies the actual chip installed on the board */
 enum {
        /* general idents: reserved range 0-49 */
        V4L2_IDENT_NONE      = 0,       /* No chip matched */
index f99c866d8c37f0cd4506e8f28b6d2911bb7a71ab..95e74f1874e1cc53b24b6ac11af0d47149e99b9c 100644 (file)
@@ -114,10 +114,10 @@ u32 v4l2_ctrl_next(const u32 * const *ctrl_classes, u32 id);
 /* Register/chip ident helper function */
 
 struct i2c_client; /* forward reference */
-int v4l2_chip_match_i2c_client(struct i2c_client *c, u32 id_type, u32 chip_id);
-int v4l2_chip_ident_i2c_client(struct i2c_client *c, struct v4l2_chip_ident *chip,
+int v4l2_chip_match_i2c_client(struct i2c_client *c, const struct v4l2_dbg_match *match);
+int v4l2_chip_ident_i2c_client(struct i2c_client *c, struct v4l2_dbg_chip_ident *chip,
                u32 ident, u32 revision);
-int v4l2_chip_match_host(u32 id_type, u32 chip_id);
+int v4l2_chip_match_host(const struct v4l2_dbg_match *match);
 
 /* ------------------------------------------------------------------------- */
 
index 0a88d1d17d30accc82ec89aff84313dc04d81821..e36faab8459b873f7ec07147abbcb834a12861cf 100644 (file)
@@ -25,6 +25,7 @@
 #define VFL_TYPE_MAX           4
 
 struct v4l2_ioctl_callbacks;
+struct video_device;
 struct v4l2_device;
 
 /* Flag to mark the video_device struct as unregistered.
@@ -32,6 +33,18 @@ struct v4l2_device;
    device access. It is set by video_unregister_device. */
 #define V4L2_FL_UNREGISTERED   (0)
 
+struct v4l2_file_operations {
+       struct module *owner;
+       ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
+       ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
+       unsigned int (*poll) (struct file *, struct poll_table_struct *);
+       long (*ioctl) (struct file *, unsigned int, unsigned long);
+       long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
+       int (*mmap) (struct file *, struct vm_area_struct *);
+       int (*open) (struct file *);
+       int (*release) (struct file *);
+};
+
 /*
  * Newer version of video_device, handled by videodev2.c
  *     This version moves redundant code from video device code to
@@ -41,7 +54,7 @@ struct v4l2_device;
 struct video_device
 {
        /* device ops */
-       const struct file_operations *fops;
+       const struct v4l2_file_operations *fops;
 
        /* sysfs */
        struct device dev;              /* v4l device */
index 97b283a0428903dcf093952bc0fcd9ca9449e828..9bf4ccc93dbf9ff591df4eecc6f4358d527d14fe 100644 (file)
@@ -80,7 +80,7 @@ void v4l2_device_unregister_subdev(struct v4l2_subdev *sd);
 #define __v4l2_device_call_subdevs_until_err(dev, cond, o, f, args...)  \
 ({                                                                     \
        struct v4l2_subdev *sd;                                         \
-       int err = 0;                                                    \
+       long err = 0;                                                   \
                                                                        \
        list_for_each_entry(sd, &(dev)->subdevs, list) {                \
                if ((cond) && sd->ops->o && sd->ops->o->f)              \
index ecda3c72583705cc2dda3422c83b8deba7031b28..fbf585561570bc7fbc43859fd9aa70a4bfdc68f6 100644 (file)
@@ -219,7 +219,7 @@ enum v4l2_int_ioctl_num {
        vidioc_int_reset_num,
        /* VIDIOC_INT_INIT */
        vidioc_int_init_num,
-       /* VIDIOC_INT_G_CHIP_IDENT */
+       /* VIDIOC_DBG_G_CHIP_IDENT */
        vidioc_int_g_chip_ident_num,
 
        /*
index fcdb58c4ce07b6872a3cbe57d72abdbb6e080a35..b01c044868d060e8c33fff3bf59d226b94ff33eb 100644 (file)
@@ -225,12 +225,12 @@ struct v4l2_ioctl_ops {
        /* Debugging ioctls */
 #ifdef CONFIG_VIDEO_ADV_DEBUG
        int (*vidioc_g_register)       (struct file *file, void *fh,
-                                       struct v4l2_register *reg);
+                                       struct v4l2_dbg_register *reg);
        int (*vidioc_s_register)       (struct file *file, void *fh,
-                                       struct v4l2_register *reg);
+                                       struct v4l2_dbg_register *reg);
 #endif
        int (*vidioc_g_chip_ident)     (struct file *file, void *fh,
-                                       struct v4l2_chip_ident *chip);
+                                       struct v4l2_dbg_chip_ident *chip);
 
        int (*vidioc_enum_framesizes)   (struct file *file, void *fh,
                                         struct v4l2_frmsizeenum *fsize);
@@ -239,7 +239,7 @@ struct v4l2_ioctl_ops {
                                           struct v4l2_frmivalenum *fival);
 
        /* For other private ioctls */
-       int (*vidioc_default)          (struct file *file, void *fh,
+       long (*vidioc_default)         (struct file *file, void *fh,
                                        int cmd, void *arg);
 };
 
@@ -277,36 +277,27 @@ extern const char *v4l2_field_names[];
 extern const char *v4l2_type_names[];
 
 /*  Compatibility layer interface  --  v4l1-compat module */
-typedef int (*v4l2_kioctl)(struct file *file,
+typedef long (*v4l2_kioctl)(struct file *file,
                           unsigned int cmd, void *arg);
 #ifdef CONFIG_VIDEO_V4L1_COMPAT
-int v4l_compat_translate_ioctl(struct file *file,
+long v4l_compat_translate_ioctl(struct file *file,
                               int cmd, void *arg, v4l2_kioctl driver_ioctl);
 #else
 #define v4l_compat_translate_ioctl(file, cmd, arg, ioctl) (-EINVAL)
 #endif
 
+#ifdef CONFIG_COMPAT
 /* 32 Bits compatibility layer for 64 bits processors */
-extern long v4l_compat_ioctl32(struct file *file, unsigned int cmd,
+extern long v4l2_compat_ioctl32(struct file *file, unsigned int cmd,
                                unsigned long arg);
+#endif
 
 /* Include support for obsoleted stuff */
-extern int video_usercopy(struct file *file, unsigned int cmd,
+extern long video_usercopy(struct file *file, unsigned int cmd,
                                unsigned long arg, v4l2_kioctl func);
 
 /* Standard handlers for V4L ioctl's */
-
-/* This prototype is used on fops.unlocked_ioctl */
-extern long __video_ioctl2(struct file *file,
-                       unsigned int cmd, unsigned long arg);
-
-/* This prototype is used on fops.ioctl
- * Since fops.ioctl enables Kernel Big Lock, it is preferred
- * to use __video_ioctl2 instead.
- * It should be noticed that there's no lock code inside
- * video_ioctl2().
- */
-extern int video_ioctl2(struct inode *inode, struct file *file,
+extern long video_ioctl2(struct file *file,
                        unsigned int cmd, unsigned long arg);
 
 #endif /* _V4L2_IOCTL_H */
index ceef016bb0b7a24ef7ef6397d5b893bbf355e3f3..37b09e56e943ecf0938c175c3a9e83df8b171a7f 100644 (file)
@@ -69,7 +69,7 @@ struct tuner_setup;
    not yet implemented) since ops provide proper type-checking.
  */
 struct v4l2_subdev_core_ops {
-       int (*g_chip_ident)(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip);
+       int (*g_chip_ident)(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip);
        int (*log_status)(struct v4l2_subdev *sd);
        int (*init)(struct v4l2_subdev *sd, u32 val);
        int (*s_standby)(struct v4l2_subdev *sd, u32 standby);
@@ -79,10 +79,10 @@ struct v4l2_subdev_core_ops {
        int (*g_ctrl)(struct v4l2_subdev *sd, struct v4l2_control *ctrl);
        int (*s_ctrl)(struct v4l2_subdev *sd, struct v4l2_control *ctrl);
        int (*querymenu)(struct v4l2_subdev *sd, struct v4l2_querymenu *qm);
-       int (*ioctl)(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
+       long (*ioctl)(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-       int (*g_register)(struct v4l2_subdev *sd, struct v4l2_register *reg);
-       int (*s_register)(struct v4l2_subdev *sd, struct v4l2_register *reg);
+       int (*g_register)(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg);
+       int (*s_register)(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg);
 #endif
 };
 
index ce532f2222ce723daf21eaea7429bcbb5a26b4a8..1459ed3e2697b495bb37226c8190b7f81d428c3c 100644 (file)
@@ -155,9 +155,9 @@ static inline struct neighbour * ndisc_get_neigh(struct net_device *dev, const s
 {
 
        if (dev)
-               return __neigh_lookup(&nd_tbl, addr, dev, 1);
+               return __neigh_lookup_errno(&nd_tbl, addr, dev);
 
-       return NULL;
+       return ERR_PTR(-ENODEV);
 }
 
 
index b6870cbaf2b38812e6bc77c24ce7a7e416eadd3f..426899e529c55313ee2aa35374e01f6c4fd74de5 100644 (file)
@@ -36,7 +36,7 @@ struct snd_tea575x_ops {
 struct snd_tea575x {
        struct snd_card *card;
        struct video_device vd;         /* video device */
-       struct file_operations fops;
+       struct v4l2_file_operations fops;
        int dev_nr;                     /* requested device number + 1 */
        int vd_registered;              /* video device is registered */
        int tea5759;                    /* 5759 chip is present */
index ad8f9f53f8d1e7180353b9f07429fdd86dee4015..cd168ebc592439b650042916ab26efd913f7ef42 100644 (file)
@@ -371,12 +371,7 @@ EXPORT_SYMBOL(nr_cpu_ids);
 /* An arch may set nr_cpu_ids earlier if needed, so this would be redundant */
 static void __init setup_nr_cpu_ids(void)
 {
-       int cpu, highest_cpu = 0;
-
-       for_each_possible_cpu(cpu)
-               highest_cpu = cpu;
-
-       nr_cpu_ids = highest_cpu + 1;
+       nr_cpu_ids = find_last_bit(cpumask_bits(cpu_possible_mask),NR_CPUS) + 1;
 }
 
 #ifndef CONFIG_HAVE_SETUP_PER_CPU_AREA
@@ -518,9 +513,9 @@ static void __init boot_cpu_init(void)
 {
        int cpu = smp_processor_id();
        /* Mark the boot cpu "present", "online" etc for SMP and UP case */
-       cpu_set(cpu, cpu_online_map);
-       cpu_set(cpu, cpu_present_map);
-       cpu_set(cpu, cpu_possible_map);
+       set_cpu_online(cpu, true);
+       set_cpu_present(cpu, true);
+       set_cpu_possible(cpu, true);
 }
 
 void __init __weak smp_setup_processor_id(void)
index d9393f8e4c3ebb2ec4a63cd64290f237e45a4f83..eddb6247a55322be4e021083ef96ea279be8f07f 100644 (file)
@@ -120,7 +120,6 @@ static struct inode *mqueue_get_inode(struct super_block *sb, int mode,
                inode->i_mode = mode;
                inode->i_uid = current_fsuid();
                inode->i_gid = current_fsgid();
-               inode->i_blocks = 0;
                inode->i_mtime = inode->i_ctime = inode->i_atime =
                                CURRENT_TIME;
 
@@ -524,31 +523,27 @@ static void __do_notify(struct mqueue_inode_info *info)
        wake_up(&info->wait_q);
 }
 
-static long prepare_timeout(const struct timespec __user *u_arg)
+static long prepare_timeout(struct timespec *p)
 {
-       struct timespec ts, nowts;
+       struct timespec nowts;
        long timeout;
 
-       if (u_arg) {
-               if (unlikely(copy_from_user(&ts, u_arg,
-                                       sizeof(struct timespec))))
-                       return -EFAULT;
-
-               if (unlikely(ts.tv_nsec < 0 || ts.tv_sec < 0
-                       || ts.tv_nsec >= NSEC_PER_SEC))
+       if (p) {
+               if (unlikely(p->tv_nsec < 0 || p->tv_sec < 0
+                       || p->tv_nsec >= NSEC_PER_SEC))
                        return -EINVAL;
                nowts = CURRENT_TIME;
                /* first subtract as jiffies can't be too big */
-               ts.tv_sec -= nowts.tv_sec;
-               if (ts.tv_nsec < nowts.tv_nsec) {
-                       ts.tv_nsec += NSEC_PER_SEC;
-                       ts.tv_sec--;
+               p->tv_sec -= nowts.tv_sec;
+               if (p->tv_nsec < nowts.tv_nsec) {
+                       p->tv_nsec += NSEC_PER_SEC;
+                       p->tv_sec--;
                }
-               ts.tv_nsec -= nowts.tv_nsec;
-               if (ts.tv_sec < 0)
+               p->tv_nsec -= nowts.tv_nsec;
+               if (p->tv_sec < 0)
                        return 0;
 
-               timeout = timespec_to_jiffies(&ts) + 1;
+               timeout = timespec_to_jiffies(p) + 1;
        } else
                return MAX_SCHEDULE_TIMEOUT;
 
@@ -592,22 +587,18 @@ static int mq_attr_ok(struct mq_attr *attr)
  * Invoked when creating a new queue via sys_mq_open
  */
 static struct file *do_create(struct dentry *dir, struct dentry *dentry,
-                       int oflag, mode_t mode, struct mq_attr __user *u_attr)
+                       int oflag, mode_t mode, struct mq_attr *attr)
 {
        const struct cred *cred = current_cred();
-       struct mq_attr attr;
        struct file *result;
        int ret;
 
-       if (u_attr) {
-               ret = -EFAULT;
-               if (copy_from_user(&attr, u_attr, sizeof(attr)))
-                       goto out;
+       if (attr) {
                ret = -EINVAL;
-               if (!mq_attr_ok(&attr))
+               if (!mq_attr_ok(attr))
                        goto out;
                /* store for use during create */
-               dentry->d_fsdata = &attr;
+               dentry->d_fsdata = attr;
        }
 
        mode &= ~current->fs->umask;
@@ -664,11 +655,13 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
        struct dentry *dentry;
        struct file *filp;
        char *name;
+       struct mq_attr attr;
        int fd, error;
 
-       error = audit_mq_open(oflag, mode, u_attr);
-       if (error != 0)
-               return error;
+       if (u_attr && copy_from_user(&attr, u_attr, sizeof(struct mq_attr)))
+               return -EFAULT;
+
+       audit_mq_open(oflag, mode, u_attr ? &attr : NULL);
 
        if (IS_ERR(name = getname(u_name)))
                return PTR_ERR(name);
@@ -694,7 +687,8 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
                        filp = do_open(dentry, oflag);
                } else {
                        filp = do_create(mqueue_mnt->mnt_root, dentry,
-                                               oflag, mode, u_attr);
+                                               oflag, mode,
+                                               u_attr ? &attr : NULL);
                }
        } else {
                error = -ENOENT;
@@ -829,17 +823,22 @@ asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr,
        struct ext_wait_queue *receiver;
        struct msg_msg *msg_ptr;
        struct mqueue_inode_info *info;
+       struct timespec ts, *p = NULL;
        long timeout;
        int ret;
 
-       ret = audit_mq_timedsend(mqdes, msg_len, msg_prio, u_abs_timeout);
-       if (ret != 0)
-               return ret;
+       if (u_abs_timeout) {
+               if (copy_from_user(&ts, u_abs_timeout, 
+                                       sizeof(struct timespec)))
+                       return -EFAULT;
+               p = &ts;
+       }
 
        if (unlikely(msg_prio >= (unsigned long) MQ_PRIO_MAX))
                return -EINVAL;
 
-       timeout = prepare_timeout(u_abs_timeout);
+       audit_mq_sendrecv(mqdes, msg_len, msg_prio, p);
+       timeout = prepare_timeout(p);
 
        ret = -EBADF;
        filp = fget(mqdes);
@@ -918,12 +917,17 @@ asmlinkage ssize_t sys_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr,
        struct inode *inode;
        struct mqueue_inode_info *info;
        struct ext_wait_queue wait;
+       struct timespec ts, *p = NULL;
 
-       ret = audit_mq_timedreceive(mqdes, msg_len, u_msg_prio, u_abs_timeout);
-       if (ret != 0)
-               return ret;
+       if (u_abs_timeout) {
+               if (copy_from_user(&ts, u_abs_timeout, 
+                                       sizeof(struct timespec)))
+                       return -EFAULT;
+               p = &ts;
+       }
 
-       timeout = prepare_timeout(u_abs_timeout);
+       audit_mq_sendrecv(mqdes, msg_len, 0, p);
+       timeout = prepare_timeout(p);
 
        ret = -EBADF;
        filp = fget(mqdes);
@@ -1003,17 +1007,17 @@ asmlinkage long sys_mq_notify(mqd_t mqdes,
        struct mqueue_inode_info *info;
        struct sk_buff *nc;
 
-       ret = audit_mq_notify(mqdes, u_notification);
-       if (ret != 0)
-               return ret;
-
-       nc = NULL;
-       sock = NULL;
-       if (u_notification != NULL) {
+       if (u_notification) {
                if (copy_from_user(&notification, u_notification,
                                        sizeof(struct sigevent)))
                        return -EFAULT;
+       }
 
+       audit_mq_notify(mqdes, u_notification ? &notification : NULL);
+
+       nc = NULL;
+       sock = NULL;
+       if (u_notification != NULL) {
                if (unlikely(notification.sigev_notify != SIGEV_NONE &&
                             notification.sigev_notify != SIGEV_SIGNAL &&
                             notification.sigev_notify != SIGEV_THREAD))
@@ -1150,11 +1154,7 @@ asmlinkage long sys_mq_getsetattr(mqd_t mqdes,
        omqstat = info->attr;
        omqstat.mq_flags = filp->f_flags & O_NONBLOCK;
        if (u_mqstat) {
-               ret = audit_mq_getsetattr(mqdes, &mqstat);
-               if (ret != 0) {
-                       spin_unlock(&info->lock);
-                       goto out_fput;
-               }
+               audit_mq_getsetattr(mqdes, &mqstat);
                if (mqstat.mq_flags & O_NONBLOCK)
                        filp->f_flags |= O_NONBLOCK;
                else
index 082122469b17490c1d0a1b634055efc079be81c1..fea0ad3aed7b36775efccce0914e0eaa1f343e2c 100644 (file)
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -58,7 +58,7 @@
  * SMP-threaded, sysctl's added
  * (c) 1999 Manfred Spraul <manfred@colorfullife.com>
  * Enforced range limit on SEM_UNDO
- * (c) 2001 Red Hat Inc <alan@redhat.com>
+ * (c) 2001 Red Hat Inc
  * Lockless wakeup
  * (c) 2003 Manfred Spraul <manfred@colorfullife.com>
  *
index 38a055758a9b212638775f19e60452350f62d482..57dd50046cefc0a4202ae7981c3eece60ee59c16 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -747,9 +747,7 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf)
                        goto out;
                }
 
-               err = audit_ipc_obj(&(shp->shm_perm));
-               if (err)
-                       goto out_unlock;
+               audit_ipc_obj(&(shp->shm_perm));
 
                if (!capable(CAP_IPC_LOCK)) {
                        uid_t euid = current_euid();
index 5a1808c774a2f238746c9234ca40822eaff47fd9..7585a72e259b7de40ecebcabb5d5c6c0040ad024 100644 (file)
@@ -624,10 +624,9 @@ void ipc_rcu_putref(void *ptr)
 int ipcperms (struct kern_ipc_perm *ipcp, short flag)
 {      /* flag will most probably be 0 or S_...UGO from <linux/stat.h> */
        uid_t euid = current_euid();
-       int requested_mode, granted_mode, err;
+       int requested_mode, granted_mode;
 
-       if (unlikely((err = audit_ipc_obj(ipcp))))
-               return err;
+       audit_ipc_obj(ipcp);
        requested_mode = (flag >> 6) | (flag >> 3) | flag;
        granted_mode = ipcp->mode;
        if (euid == ipcp->cuid ||
@@ -803,16 +802,10 @@ struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd,
                goto out_up;
        }
 
-       err = audit_ipc_obj(ipcp);
-       if (err)
-               goto out_unlock;
-
-       if (cmd == IPC_SET) {
-               err = audit_ipc_set_perm(extra_perm, perm->uid,
+       audit_ipc_obj(ipcp);
+       if (cmd == IPC_SET)
+               audit_ipc_set_perm(extra_perm, perm->uid,
                                         perm->gid, perm->mode);
-               if (err)
-                       goto out_unlock;
-       }
 
        euid = current_euid();
        if (euid == ipcp->cuid ||
@@ -820,7 +813,6 @@ struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd,
                return ipcp;
 
        err = -EPERM;
-out_unlock:
        ipc_unlock(ipcp);
 out_up:
        up_write(&ids->rw_mutex);
index 9d6717412fecd75eb36029b1c65d84228602b723..16f18cac661b68261c20c551caa3a94333df3da0 100644 (file)
@@ -159,11 +159,8 @@ static inline int audit_signal_info(int sig, struct task_struct *t)
                return __audit_signal_info(sig, t);
        return 0;
 }
-extern enum audit_state audit_filter_inodes(struct task_struct *,
-                                           struct audit_context *);
-extern void audit_set_auditable(struct audit_context *);
+extern void audit_filter_inodes(struct task_struct *, struct audit_context *);
 #else
 #define audit_signal_info(s,t) AUDIT_DISABLED
 #define audit_filter_inodes(t,c) AUDIT_DISABLED
-#define audit_set_auditable(c)
 #endif
index 8b509441f49a2f740a2d709c66cecc73d9896f1c..8ad9545b8db9e67203c49f37ece0a3da30f42b28 100644 (file)
@@ -450,6 +450,7 @@ static void kill_rules(struct audit_tree *tree)
                        audit_log_end(ab);
                        rule->tree = NULL;
                        list_del_rcu(&entry->list);
+                       list_del(&entry->rule.list);
                        call_rcu(&entry->rcu, audit_free_rule_rcu);
                }
        }
@@ -617,7 +618,7 @@ int audit_make_tree(struct audit_krule *rule, char *pathname, u32 op)
 
        if (pathname[0] != '/' ||
            rule->listnr != AUDIT_FILTER_EXIT ||
-           op & ~AUDIT_EQUAL ||
+           op != Audit_equal ||
            rule->inode_f || rule->watch || rule->tree)
                return -EINVAL;
        rule->tree = alloc_tree(pathname);
index 9fd85a4640a096eab72312d33a090e417e013548..fbf24d121d97dea5167920a2dbae673b978c6b82 100644 (file)
@@ -86,6 +86,14 @@ struct list_head audit_filter_list[AUDIT_NR_FILTERS] = {
 #error Fix audit_filter_list initialiser
 #endif
 };
+static struct list_head audit_rules_list[AUDIT_NR_FILTERS] = {
+       LIST_HEAD_INIT(audit_rules_list[0]),
+       LIST_HEAD_INIT(audit_rules_list[1]),
+       LIST_HEAD_INIT(audit_rules_list[2]),
+       LIST_HEAD_INIT(audit_rules_list[3]),
+       LIST_HEAD_INIT(audit_rules_list[4]),
+       LIST_HEAD_INIT(audit_rules_list[5]),
+};
 
 DEFINE_MUTEX(audit_filter_mutex);
 
@@ -244,7 +252,8 @@ static inline int audit_to_inode(struct audit_krule *krule,
                                 struct audit_field *f)
 {
        if (krule->listnr != AUDIT_FILTER_EXIT ||
-           krule->watch || krule->inode_f || krule->tree)
+           krule->watch || krule->inode_f || krule->tree ||
+           (f->op != Audit_equal && f->op != Audit_not_equal))
                return -EINVAL;
 
        krule->inode_f = f;
@@ -262,7 +271,7 @@ static int audit_to_watch(struct audit_krule *krule, char *path, int len,
 
        if (path[0] != '/' || path[len-1] == '/' ||
            krule->listnr != AUDIT_FILTER_EXIT ||
-           op & ~AUDIT_EQUAL ||
+           op != Audit_equal ||
            krule->inode_f || krule->watch || krule->tree)
                return -EINVAL;
 
@@ -412,12 +421,32 @@ exit_err:
        return ERR_PTR(err);
 }
 
+static u32 audit_ops[] =
+{
+       [Audit_equal] = AUDIT_EQUAL,
+       [Audit_not_equal] = AUDIT_NOT_EQUAL,
+       [Audit_bitmask] = AUDIT_BIT_MASK,
+       [Audit_bittest] = AUDIT_BIT_TEST,
+       [Audit_lt] = AUDIT_LESS_THAN,
+       [Audit_gt] = AUDIT_GREATER_THAN,
+       [Audit_le] = AUDIT_LESS_THAN_OR_EQUAL,
+       [Audit_ge] = AUDIT_GREATER_THAN_OR_EQUAL,
+};
+
+static u32 audit_to_op(u32 op)
+{
+       u32 n;
+       for (n = Audit_equal; n < Audit_bad && audit_ops[n] != op; n++)
+               ;
+       return n;
+}
+
+
 /* Translate struct audit_rule to kernel's rule respresentation.
  * Exists for backward compatibility with userspace. */
 static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
 {
        struct audit_entry *entry;
-       struct audit_field *ino_f;
        int err = 0;
        int i;
 
@@ -427,12 +456,28 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
 
        for (i = 0; i < rule->field_count; i++) {
                struct audit_field *f = &entry->rule.fields[i];
+               u32 n;
+
+               n = rule->fields[i] & (AUDIT_NEGATE|AUDIT_OPERATORS);
+
+               /* Support for legacy operators where
+                * AUDIT_NEGATE bit signifies != and otherwise assumes == */
+               if (n & AUDIT_NEGATE)
+                       f->op = Audit_not_equal;
+               else if (!n)
+                       f->op = Audit_equal;
+               else
+                       f->op = audit_to_op(n);
+
+               entry->rule.vers_ops = (n & AUDIT_OPERATORS) ? 2 : 1;
 
-               f->op = rule->fields[i] & (AUDIT_NEGATE|AUDIT_OPERATORS);
                f->type = rule->fields[i] & ~(AUDIT_NEGATE|AUDIT_OPERATORS);
                f->val = rule->values[i];
 
                err = -EINVAL;
+               if (f->op == Audit_bad)
+                       goto exit_free;
+
                switch(f->type) {
                default:
                        goto exit_free;
@@ -454,11 +499,8 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
                case AUDIT_EXIT:
                case AUDIT_SUCCESS:
                        /* bit ops are only useful on syscall args */
-                       if (f->op == AUDIT_BIT_MASK ||
-                                               f->op == AUDIT_BIT_TEST) {
-                               err = -EINVAL;
+                       if (f->op == Audit_bitmask || f->op == Audit_bittest)
                                goto exit_free;
-                       }
                        break;
                case AUDIT_ARG0:
                case AUDIT_ARG1:
@@ -467,11 +509,8 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
                        break;
                /* arch is only allowed to be = or != */
                case AUDIT_ARCH:
-                       if ((f->op != AUDIT_NOT_EQUAL) && (f->op != AUDIT_EQUAL)
-                                       && (f->op != AUDIT_NEGATE) && (f->op)) {
-                               err = -EINVAL;
+                       if (f->op != Audit_not_equal && f->op != Audit_equal)
                                goto exit_free;
-                       }
                        entry->rule.arch_f = f;
                        break;
                case AUDIT_PERM:
@@ -488,33 +527,10 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
                                goto exit_free;
                        break;
                }
-
-               entry->rule.vers_ops = (f->op & AUDIT_OPERATORS) ? 2 : 1;
-
-               /* Support for legacy operators where
-                * AUDIT_NEGATE bit signifies != and otherwise assumes == */
-               if (f->op & AUDIT_NEGATE)
-                       f->op = AUDIT_NOT_EQUAL;
-               else if (!f->op)
-                       f->op = AUDIT_EQUAL;
-               else if (f->op == AUDIT_OPERATORS) {
-                       err = -EINVAL;
-                       goto exit_free;
-               }
        }
 
-       ino_f = entry->rule.inode_f;
-       if (ino_f) {
-               switch(ino_f->op) {
-               case AUDIT_NOT_EQUAL:
-                       entry->rule.inode_f = NULL;
-               case AUDIT_EQUAL:
-                       break;
-               default:
-                       err = -EINVAL;
-                       goto exit_free;
-               }
-       }
+       if (entry->rule.inode_f && entry->rule.inode_f->op == Audit_not_equal)
+               entry->rule.inode_f = NULL;
 
 exit_nofree:
        return entry;
@@ -530,7 +546,6 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
 {
        int err = 0;
        struct audit_entry *entry;
-       struct audit_field *ino_f;
        void *bufp;
        size_t remain = datasz - sizeof(struct audit_rule_data);
        int i;
@@ -546,11 +561,11 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
                struct audit_field *f = &entry->rule.fields[i];
 
                err = -EINVAL;
-               if (!(data->fieldflags[i] & AUDIT_OPERATORS) ||
-                   data->fieldflags[i] & ~AUDIT_OPERATORS)
+
+               f->op = audit_to_op(data->fieldflags[i]);
+               if (f->op == Audit_bad)
                        goto exit_free;
 
-               f->op = data->fieldflags[i] & AUDIT_OPERATORS;
                f->type = data->fields[i];
                f->val = data->values[i];
                f->lsm_str = NULL;
@@ -662,18 +677,8 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
                }
        }
 
-       ino_f = entry->rule.inode_f;
-       if (ino_f) {
-               switch(ino_f->op) {
-               case AUDIT_NOT_EQUAL:
-                       entry->rule.inode_f = NULL;
-               case AUDIT_EQUAL:
-                       break;
-               default:
-                       err = -EINVAL;
-                       goto exit_free;
-               }
-       }
+       if (entry->rule.inode_f && entry->rule.inode_f->op == Audit_not_equal)
+               entry->rule.inode_f = NULL;
 
 exit_nofree:
        return entry;
@@ -713,10 +718,10 @@ static struct audit_rule *audit_krule_to_rule(struct audit_krule *krule)
                rule->fields[i] = krule->fields[i].type;
 
                if (krule->vers_ops == 1) {
-                       if (krule->fields[i].op & AUDIT_NOT_EQUAL)
+                       if (krule->fields[i].op == Audit_not_equal)
                                rule->fields[i] |= AUDIT_NEGATE;
                } else {
-                       rule->fields[i] |= krule->fields[i].op;
+                       rule->fields[i] |= audit_ops[krule->fields[i].op];
                }
        }
        for (i = 0; i < AUDIT_BITMASK_SIZE; i++) rule->mask[i] = krule->mask[i];
@@ -744,7 +749,7 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule)
                struct audit_field *f = &krule->fields[i];
 
                data->fields[i] = f->type;
-               data->fieldflags[i] = f->op;
+               data->fieldflags[i] = audit_ops[f->op];
                switch(f->type) {
                case AUDIT_SUBJ_USER:
                case AUDIT_SUBJ_ROLE:
@@ -919,6 +924,7 @@ static struct audit_entry *audit_dupe_rule(struct audit_krule *old,
        new->action = old->action;
        for (i = 0; i < AUDIT_BITMASK_SIZE; i++)
                new->mask[i] = old->mask[i];
+       new->prio = old->prio;
        new->buflen = old->buflen;
        new->inode_f = old->inode_f;
        new->watch = NULL;
@@ -987,9 +993,8 @@ static void audit_update_watch(struct audit_parent *parent,
 
                /* If the update involves invalidating rules, do the inode-based
                 * filtering now, so we don't omit records. */
-               if (invalidating && current->audit_context &&
-                   audit_filter_inodes(current, current->audit_context) == AUDIT_RECORD_CONTEXT)
-                       audit_set_auditable(current->audit_context);
+               if (invalidating && current->audit_context)
+                       audit_filter_inodes(current, current->audit_context);
 
                nwatch = audit_dupe_watch(owatch);
                if (IS_ERR(nwatch)) {
@@ -1007,12 +1012,15 @@ static void audit_update_watch(struct audit_parent *parent,
                        list_del_rcu(&oentry->list);
 
                        nentry = audit_dupe_rule(&oentry->rule, nwatch);
-                       if (IS_ERR(nentry))
+                       if (IS_ERR(nentry)) {
+                               list_del(&oentry->rule.list);
                                audit_panic("error updating watch, removing");
-                       else {
+                       else {
                                int h = audit_hash_ino((u32)ino);
                                list_add(&nentry->rule.rlist, &nwatch->rules);
                                list_add_rcu(&nentry->list, &audit_inode_hash[h]);
+                               list_replace(&oentry->rule.list,
+                                            &nentry->rule.list);
                        }
 
                        call_rcu(&oentry->rcu, audit_free_rule_rcu);
@@ -1077,6 +1085,7 @@ static void audit_remove_parent_watches(struct audit_parent *parent)
                                audit_log_end(ab);
                        }
                        list_del(&r->rlist);
+                       list_del(&r->list);
                        list_del_rcu(&e->list);
                        call_rcu(&e->rcu, audit_free_rule_rcu);
                }
@@ -1102,12 +1111,16 @@ static void audit_inotify_unregister(struct list_head *in_list)
 /* Find an existing audit rule.
  * Caller must hold audit_filter_mutex to prevent stale rule data. */
 static struct audit_entry *audit_find_rule(struct audit_entry *entry,
-                                          struct list_head *list)
+                                          struct list_head **p)
 {
        struct audit_entry *e, *found = NULL;
+       struct list_head *list;
        int h;
 
-       if (entry->rule.watch) {
+       if (entry->rule.inode_f) {
+               h = audit_hash_ino(entry->rule.inode_f->val);
+               *p = list = &audit_inode_hash[h];
+       } else if (entry->rule.watch) {
                /* we don't know the inode number, so must walk entire hash */
                for (h = 0; h < AUDIT_INODE_BUCKETS; h++) {
                        list = &audit_inode_hash[h];
@@ -1118,6 +1131,8 @@ static struct audit_entry *audit_find_rule(struct audit_entry *entry,
                                }
                }
                goto out;
+       } else {
+               *p = list = &audit_filter_list[entry->rule.listnr];
        }
 
        list_for_each_entry(e, list, list)
@@ -1258,15 +1273,17 @@ static int audit_add_watch(struct audit_krule *krule, struct nameidata *ndp,
        return ret;
 }
 
+static u64 prio_low = ~0ULL/2;
+static u64 prio_high = ~0ULL/2 - 1;
+
 /* Add rule to given filterlist if not a duplicate. */
-static inline int audit_add_rule(struct audit_entry *entry,
-                                struct list_head *list)
+static inline int audit_add_rule(struct audit_entry *entry)
 {
        struct audit_entry *e;
-       struct audit_field *inode_f = entry->rule.inode_f;
        struct audit_watch *watch = entry->rule.watch;
        struct audit_tree *tree = entry->rule.tree;
        struct nameidata *ndp = NULL, *ndw = NULL;
+       struct list_head *list;
        int h, err;
 #ifdef CONFIG_AUDITSYSCALL
        int dont_count = 0;
@@ -1277,13 +1294,8 @@ static inline int audit_add_rule(struct audit_entry *entry,
                dont_count = 1;
 #endif
 
-       if (inode_f) {
-               h = audit_hash_ino(inode_f->val);
-               list = &audit_inode_hash[h];
-       }
-
        mutex_lock(&audit_filter_mutex);
-       e = audit_find_rule(entry, list);
+       e = audit_find_rule(entry, &list);
        mutex_unlock(&audit_filter_mutex);
        if (e) {
                err = -EEXIST;
@@ -1319,10 +1331,22 @@ static inline int audit_add_rule(struct audit_entry *entry,
                }
        }
 
+       entry->rule.prio = ~0ULL;
+       if (entry->rule.listnr == AUDIT_FILTER_EXIT) {
+               if (entry->rule.flags & AUDIT_FILTER_PREPEND)
+                       entry->rule.prio = ++prio_high;
+               else
+                       entry->rule.prio = --prio_low;
+       }
+
        if (entry->rule.flags & AUDIT_FILTER_PREPEND) {
+               list_add(&entry->rule.list,
+                        &audit_rules_list[entry->rule.listnr]);
                list_add_rcu(&entry->list, list);
                entry->rule.flags &= ~AUDIT_FILTER_PREPEND;
        } else {
+               list_add_tail(&entry->rule.list,
+                             &audit_rules_list[entry->rule.listnr]);
                list_add_tail_rcu(&entry->list, list);
        }
 #ifdef CONFIG_AUDITSYSCALL
@@ -1345,15 +1369,14 @@ error:
 }
 
 /* Remove an existing rule from filterlist. */
-static inline int audit_del_rule(struct audit_entry *entry,
-                                struct list_head *list)
+static inline int audit_del_rule(struct audit_entry *entry)
 {
        struct audit_entry  *e;
-       struct audit_field *inode_f = entry->rule.inode_f;
        struct audit_watch *watch, *tmp_watch = entry->rule.watch;
        struct audit_tree *tree = entry->rule.tree;
+       struct list_head *list;
        LIST_HEAD(inotify_list);
-       int h, ret = 0;
+       int ret = 0;
 #ifdef CONFIG_AUDITSYSCALL
        int dont_count = 0;
 
@@ -1363,13 +1386,8 @@ static inline int audit_del_rule(struct audit_entry *entry,
                dont_count = 1;
 #endif
 
-       if (inode_f) {
-               h = audit_hash_ino(inode_f->val);
-               list = &audit_inode_hash[h];
-       }
-
        mutex_lock(&audit_filter_mutex);
-       e = audit_find_rule(entry, list);
+       e = audit_find_rule(entry, &list);
        if (!e) {
                mutex_unlock(&audit_filter_mutex);
                ret = -ENOENT;
@@ -1404,6 +1422,7 @@ static inline int audit_del_rule(struct audit_entry *entry,
                audit_remove_tree_rule(&e->rule);
 
        list_del_rcu(&e->list);
+       list_del(&e->rule.list);
        call_rcu(&e->rcu, audit_free_rule_rcu);
 
 #ifdef CONFIG_AUDITSYSCALL
@@ -1432,30 +1451,16 @@ out:
 static void audit_list(int pid, int seq, struct sk_buff_head *q)
 {
        struct sk_buff *skb;
-       struct audit_entry *entry;
+       struct audit_krule *r;
        int i;
 
        /* This is a blocking read, so use audit_filter_mutex instead of rcu
         * iterator to sync with list writers. */
        for (i=0; i<AUDIT_NR_FILTERS; i++) {
-               list_for_each_entry(entry, &audit_filter_list[i], list) {
-                       struct audit_rule *rule;
-
-                       rule = audit_krule_to_rule(&entry->rule);
-                       if (unlikely(!rule))
-                               break;
-                       skb = audit_make_reply(pid, seq, AUDIT_LIST, 0, 1,
-                                        rule, sizeof(*rule));
-                       if (skb)
-                               skb_queue_tail(q, skb);
-                       kfree(rule);
-               }
-       }
-       for (i = 0; i < AUDIT_INODE_BUCKETS; i++) {
-               list_for_each_entry(entry, &audit_inode_hash[i], list) {
+               list_for_each_entry(r, &audit_rules_list[i], list) {
                        struct audit_rule *rule;
 
-                       rule = audit_krule_to_rule(&entry->rule);
+                       rule = audit_krule_to_rule(r);
                        if (unlikely(!rule))
                                break;
                        skb = audit_make_reply(pid, seq, AUDIT_LIST, 0, 1,
@@ -1474,30 +1479,16 @@ static void audit_list(int pid, int seq, struct sk_buff_head *q)
 static void audit_list_rules(int pid, int seq, struct sk_buff_head *q)
 {
        struct sk_buff *skb;
-       struct audit_entry *e;
+       struct audit_krule *r;
        int i;
 
        /* This is a blocking read, so use audit_filter_mutex instead of rcu
         * iterator to sync with list writers. */
        for (i=0; i<AUDIT_NR_FILTERS; i++) {
-               list_for_each_entry(e, &audit_filter_list[i], list) {
-                       struct audit_rule_data *data;
-
-                       data = audit_krule_to_data(&e->rule);
-                       if (unlikely(!data))
-                               break;
-                       skb = audit_make_reply(pid, seq, AUDIT_LIST_RULES, 0, 1,
-                                        data, sizeof(*data) + data->buflen);
-                       if (skb)
-                               skb_queue_tail(q, skb);
-                       kfree(data);
-               }
-       }
-       for (i=0; i< AUDIT_INODE_BUCKETS; i++) {
-               list_for_each_entry(e, &audit_inode_hash[i], list) {
+               list_for_each_entry(r, &audit_rules_list[i], list) {
                        struct audit_rule_data *data;
 
-                       data = audit_krule_to_data(&e->rule);
+                       data = audit_krule_to_data(r);
                        if (unlikely(!data))
                                break;
                        skb = audit_make_reply(pid, seq, AUDIT_LIST_RULES, 0, 1,
@@ -1603,8 +1594,7 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
                if (IS_ERR(entry))
                        return PTR_ERR(entry);
 
-               err = audit_add_rule(entry,
-                                    &audit_filter_list[entry->rule.listnr]);
+               err = audit_add_rule(entry);
                audit_log_rule_change(loginuid, sessionid, sid, "add",
                                      &entry->rule, !err);
 
@@ -1620,8 +1610,7 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
                if (IS_ERR(entry))
                        return PTR_ERR(entry);
 
-               err = audit_del_rule(entry,
-                                    &audit_filter_list[entry->rule.listnr]);
+               err = audit_del_rule(entry);
                audit_log_rule_change(loginuid, sessionid, sid, "remove",
                                      &entry->rule, !err);
 
@@ -1634,28 +1623,29 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
        return err;
 }
 
-int audit_comparator(const u32 left, const u32 op, const u32 right)
+int audit_comparator(u32 left, u32 op, u32 right)
 {
        switch (op) {
-       case AUDIT_EQUAL:
+       case Audit_equal:
                return (left == right);
-       case AUDIT_NOT_EQUAL:
+       case Audit_not_equal:
                return (left != right);
-       case AUDIT_LESS_THAN:
+       case Audit_lt:
                return (left < right);
-       case AUDIT_LESS_THAN_OR_EQUAL:
+       case Audit_le:
                return (left <= right);
-       case AUDIT_GREATER_THAN:
+       case Audit_gt:
                return (left > right);
-       case AUDIT_GREATER_THAN_OR_EQUAL:
+       case Audit_ge:
                return (left >= right);
-       case AUDIT_BIT_MASK:
+       case Audit_bitmask:
                return (left & right);
-       case AUDIT_BIT_TEST:
+       case Audit_bittest:
                return ((left & right) == right);
+       default:
+               BUG();
+               return 0;
        }
-       BUG();
-       return 0;
 }
 
 /* Compare given dentry name with last component in given path,
@@ -1778,6 +1768,43 @@ unlock_and_return:
        return result;
 }
 
+static int update_lsm_rule(struct audit_krule *r)
+{
+       struct audit_entry *entry = container_of(r, struct audit_entry, rule);
+       struct audit_entry *nentry;
+       struct audit_watch *watch;
+       struct audit_tree *tree;
+       int err = 0;
+
+       if (!security_audit_rule_known(r))
+               return 0;
+
+       watch = r->watch;
+       tree = r->tree;
+       nentry = audit_dupe_rule(r, watch);
+       if (IS_ERR(nentry)) {
+               /* save the first error encountered for the
+                * return value */
+               err = PTR_ERR(nentry);
+               audit_panic("error updating LSM filters");
+               if (watch)
+                       list_del(&r->rlist);
+               list_del_rcu(&entry->list);
+               list_del(&r->list);
+       } else {
+               if (watch) {
+                       list_add(&nentry->rule.rlist, &watch->rules);
+                       list_del(&r->rlist);
+               } else if (tree)
+                       list_replace_init(&r->rlist, &nentry->rule.rlist);
+               list_replace_rcu(&entry->list, &nentry->list);
+               list_replace(&r->list, &nentry->rule.list);
+       }
+       call_rcu(&entry->rcu, audit_free_rule_rcu);
+
+       return err;
+}
+
 /* This function will re-initialize the lsm_rule field of all applicable rules.
  * It will traverse the filter lists serarching for rules that contain LSM
  * specific filter fields.  When such a rule is found, it is copied, the
@@ -1785,45 +1812,19 @@ unlock_and_return:
  * updated rule. */
 int audit_update_lsm_rules(void)
 {
-       struct audit_entry *entry, *n, *nentry;
-       struct audit_watch *watch;
-       struct audit_tree *tree;
+       struct audit_krule *r, *n;
        int i, err = 0;
 
        /* audit_filter_mutex synchronizes the writers */
        mutex_lock(&audit_filter_mutex);
 
        for (i = 0; i < AUDIT_NR_FILTERS; i++) {
-               list_for_each_entry_safe(entry, n, &audit_filter_list[i], list) {
-                       if (!security_audit_rule_known(&entry->rule))
-                               continue;
-
-                       watch = entry->rule.watch;
-                       tree = entry->rule.tree;
-                       nentry = audit_dupe_rule(&entry->rule, watch);
-                       if (IS_ERR(nentry)) {
-                               /* save the first error encountered for the
-                                * return value */
-                               if (!err)
-                                       err = PTR_ERR(nentry);
-                               audit_panic("error updating LSM filters");
-                               if (watch)
-                                       list_del(&entry->rule.rlist);
-                               list_del_rcu(&entry->list);
-                       } else {
-                               if (watch) {
-                                       list_add(&nentry->rule.rlist,
-                                                &watch->rules);
-                                       list_del(&entry->rule.rlist);
-                               } else if (tree)
-                                       list_replace_init(&entry->rule.rlist,
-                                                    &nentry->rule.rlist);
-                               list_replace_rcu(&entry->list, &nentry->list);
-                       }
-                       call_rcu(&entry->rcu, audit_free_rule_rcu);
+               list_for_each_entry_safe(r, n, &audit_rules_list[i], list) {
+                       int res = update_lsm_rule(r);
+                       if (!err)
+                               err = res;
                }
        }
-
        mutex_unlock(&audit_filter_mutex);
 
        return err;
index 4819f3711973f746207aa15a60b45126546ffc9e..8cbddff6c283a569acb2b1c707b2448f67771e44 100644 (file)
@@ -124,43 +124,6 @@ struct audit_aux_data {
 /* Number of target pids per aux struct. */
 #define AUDIT_AUX_PIDS 16
 
-struct audit_aux_data_mq_open {
-       struct audit_aux_data   d;
-       int                     oflag;
-       mode_t                  mode;
-       struct mq_attr          attr;
-};
-
-struct audit_aux_data_mq_sendrecv {
-       struct audit_aux_data   d;
-       mqd_t                   mqdes;
-       size_t                  msg_len;
-       unsigned int            msg_prio;
-       struct timespec         abs_timeout;
-};
-
-struct audit_aux_data_mq_notify {
-       struct audit_aux_data   d;
-       mqd_t                   mqdes;
-       struct sigevent         notification;
-};
-
-struct audit_aux_data_mq_getsetattr {
-       struct audit_aux_data   d;
-       mqd_t                   mqdes;
-       struct mq_attr          mqstat;
-};
-
-struct audit_aux_data_ipcctl {
-       struct audit_aux_data   d;
-       struct ipc_perm         p;
-       unsigned long           qbytes;
-       uid_t                   uid;
-       gid_t                   gid;
-       mode_t                  mode;
-       u32                     osid;
-};
-
 struct audit_aux_data_execve {
        struct audit_aux_data   d;
        int argc;
@@ -168,23 +131,6 @@ struct audit_aux_data_execve {
        struct mm_struct *mm;
 };
 
-struct audit_aux_data_socketcall {
-       struct audit_aux_data   d;
-       int                     nargs;
-       unsigned long           args[0];
-};
-
-struct audit_aux_data_sockaddr {
-       struct audit_aux_data   d;
-       int                     len;
-       char                    a[0];
-};
-
-struct audit_aux_data_fd_pair {
-       struct  audit_aux_data d;
-       int     fd[2];
-};
-
 struct audit_aux_data_pids {
        struct audit_aux_data   d;
        pid_t                   target_pid[AUDIT_AUX_PIDS];
@@ -219,14 +165,14 @@ struct audit_tree_refs {
 struct audit_context {
        int                 dummy;      /* must be the first element */
        int                 in_syscall; /* 1 if task is in a syscall */
-       enum audit_state    state;
+       enum audit_state    state, current_state;
        unsigned int        serial;     /* serial number for record */
        struct timespec     ctime;      /* time of syscall entry */
        int                 major;      /* syscall number */
        unsigned long       argv[4];    /* syscall arguments */
        int                 return_valid; /* return code is valid */
        long                return_code;/* syscall return code */
-       int                 auditable;  /* 1 if record should be written */
+       u64                 prio;
        int                 name_count;
        struct audit_names  names[AUDIT_NAMES];
        char *              filterkey;  /* key for rule that triggered record */
@@ -234,7 +180,8 @@ struct audit_context {
        struct audit_context *previous; /* For nested syscalls */
        struct audit_aux_data *aux;
        struct audit_aux_data *aux_pids;
-
+       struct sockaddr_storage *sockaddr;
+       size_t sockaddr_len;
                                /* Save things to print about task_struct */
        pid_t               pid, ppid;
        uid_t               uid, euid, suid, fsuid;
@@ -252,6 +199,49 @@ struct audit_context {
        struct audit_tree_refs *trees, *first_trees;
        int tree_count;
 
+       int type;
+       union {
+               struct {
+                       int nargs;
+                       long args[6];
+               } socketcall;
+               struct {
+                       uid_t                   uid;
+                       gid_t                   gid;
+                       mode_t                  mode;
+                       u32                     osid;
+                       int                     has_perm;
+                       uid_t                   perm_uid;
+                       gid_t                   perm_gid;
+                       mode_t                  perm_mode;
+                       unsigned long           qbytes;
+               } ipc;
+               struct {
+                       mqd_t                   mqdes;
+                       struct mq_attr          mqstat;
+               } mq_getsetattr;
+               struct {
+                       mqd_t                   mqdes;
+                       int                     sigev_signo;
+               } mq_notify;
+               struct {
+                       mqd_t                   mqdes;
+                       size_t                  msg_len;
+                       unsigned int            msg_prio;
+                       struct timespec         abs_timeout;
+               } mq_sendrecv;
+               struct {
+                       int                     oflag;
+                       mode_t                  mode;
+                       struct mq_attr          attr;
+               } mq_open;
+               struct {
+                       pid_t                   pid;
+                       struct audit_cap_data   cap;
+               } capset;
+       };
+       int fds[2];
+
 #if AUDIT_DEBUG
        int                 put_count;
        int                 ino_count;
@@ -608,19 +598,12 @@ static int audit_filter_rules(struct task_struct *tsk,
                                        }
                                }
                                /* Find ipc objects that match */
-                               if (ctx) {
-                                       struct audit_aux_data *aux;
-                                       for (aux = ctx->aux; aux;
-                                            aux = aux->next) {
-                                               if (aux->type == AUDIT_IPC) {
-                                                       struct audit_aux_data_ipcctl *axi = (void *)aux;
-                                                       if (security_audit_rule_match(axi->osid, f->type, f->op, f->lsm_rule, ctx)) {
-                                                               ++result;
-                                                               break;
-                                                       }
-                                               }
-                                       }
-                               }
+                               if (!ctx || ctx->type != AUDIT_IPC)
+                                       break;
+                               if (security_audit_rule_match(ctx->ipc.osid,
+                                                             f->type, f->op,
+                                                             f->lsm_rule, ctx))
+                                       ++result;
                        }
                        break;
                case AUDIT_ARG0:
@@ -647,8 +630,16 @@ static int audit_filter_rules(struct task_struct *tsk,
                        return 0;
                }
        }
-       if (rule->filterkey && ctx)
-               ctx->filterkey = kstrdup(rule->filterkey, GFP_ATOMIC);
+
+       if (ctx) {
+               if (rule->prio <= ctx->prio)
+                       return 0;
+               if (rule->filterkey) {
+                       kfree(ctx->filterkey);
+                       ctx->filterkey = kstrdup(rule->filterkey, GFP_ATOMIC);
+               }
+               ctx->prio = rule->prio;
+       }
        switch (rule->action) {
        case AUDIT_NEVER:    *state = AUDIT_DISABLED;       break;
        case AUDIT_ALWAYS:   *state = AUDIT_RECORD_CONTEXT; break;
@@ -661,7 +652,7 @@ static int audit_filter_rules(struct task_struct *tsk,
  * completely disabled for this task.  Since we only have the task
  * structure at this point, we can only check uid and gid.
  */
-static enum audit_state audit_filter_task(struct task_struct *tsk)
+static enum audit_state audit_filter_task(struct task_struct *tsk, char **key)
 {
        struct audit_entry *e;
        enum audit_state   state;
@@ -669,6 +660,8 @@ static enum audit_state audit_filter_task(struct task_struct *tsk)
        rcu_read_lock();
        list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_TASK], list) {
                if (audit_filter_rules(tsk, &e->rule, NULL, NULL, &state)) {
+                       if (state == AUDIT_RECORD_CONTEXT)
+                               *key = kstrdup(e->rule.filterkey, GFP_ATOMIC);
                        rcu_read_unlock();
                        return state;
                }
@@ -702,6 +695,7 @@ static enum audit_state audit_filter_syscall(struct task_struct *tsk,
                            audit_filter_rules(tsk, &e->rule, ctx, NULL,
                                               &state)) {
                                rcu_read_unlock();
+                               ctx->current_state = state;
                                return state;
                        }
                }
@@ -715,15 +709,14 @@ static enum audit_state audit_filter_syscall(struct task_struct *tsk,
  * buckets applicable to the inode numbers in audit_names[].
  * Regarding audit_state, same rules apply as for audit_filter_syscall().
  */
-enum audit_state audit_filter_inodes(struct task_struct *tsk,
-                                    struct audit_context *ctx)
+void audit_filter_inodes(struct task_struct *tsk, struct audit_context *ctx)
 {
        int i;
        struct audit_entry *e;
        enum audit_state state;
 
        if (audit_pid && tsk->tgid == audit_pid)
-               return AUDIT_DISABLED;
+               return;
 
        rcu_read_lock();
        for (i = 0; i < ctx->name_count; i++) {
@@ -740,17 +733,20 @@ enum audit_state audit_filter_inodes(struct task_struct *tsk,
                        if ((e->rule.mask[word] & bit) == bit &&
                            audit_filter_rules(tsk, &e->rule, ctx, n, &state)) {
                                rcu_read_unlock();
-                               return state;
+                               ctx->current_state = state;
+                               return;
                        }
                }
        }
        rcu_read_unlock();
-       return AUDIT_BUILD_CONTEXT;
 }
 
-void audit_set_auditable(struct audit_context *ctx)
+static void audit_set_auditable(struct audit_context *ctx)
 {
-       ctx->auditable = 1;
+       if (!ctx->prio) {
+               ctx->prio = 1;
+               ctx->current_state = AUDIT_RECORD_CONTEXT;
+       }
 }
 
 static inline struct audit_context *audit_get_context(struct task_struct *tsk,
@@ -781,23 +777,11 @@ static inline struct audit_context *audit_get_context(struct task_struct *tsk,
        else
                context->return_code  = return_code;
 
-       if (context->in_syscall && !context->dummy && !context->auditable) {
-               enum audit_state state;
-
-               state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_EXIT]);
-               if (state == AUDIT_RECORD_CONTEXT) {
-                       context->auditable = 1;
-                       goto get_context;
-               }
-
-               state = audit_filter_inodes(tsk, context);
-               if (state == AUDIT_RECORD_CONTEXT)
-                       context->auditable = 1;
-
+       if (context->in_syscall && !context->dummy) {
+               audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_EXIT]);
+               audit_filter_inodes(tsk, context);
        }
 
-get_context:
-
        tsk->audit_context = NULL;
        return context;
 }
@@ -807,8 +791,7 @@ static inline void audit_free_names(struct audit_context *context)
        int i;
 
 #if AUDIT_DEBUG == 2
-       if (context->auditable
-           ||context->put_count + context->ino_count != context->name_count) {
+       if (context->put_count + context->ino_count != context->name_count) {
                printk(KERN_ERR "%s:%d(:%d): major=%d in_syscall=%d"
                       " name_count=%d put_count=%d"
                       " ino_count=%d [NOT freeing]\n",
@@ -859,6 +842,7 @@ static inline void audit_zero_context(struct audit_context *context,
 {
        memset(context, 0, sizeof(*context));
        context->state      = state;
+       context->prio = state == AUDIT_RECORD_CONTEXT ? ~0ULL : 0;
 }
 
 static inline struct audit_context *audit_alloc_context(enum audit_state state)
@@ -884,18 +868,21 @@ int audit_alloc(struct task_struct *tsk)
 {
        struct audit_context *context;
        enum audit_state     state;
+       char *key = NULL;
 
        if (likely(!audit_ever_enabled))
                return 0; /* Return if not auditing. */
 
-       state = audit_filter_task(tsk);
+       state = audit_filter_task(tsk, &key);
        if (likely(state == AUDIT_DISABLED))
                return 0;
 
        if (!(context = audit_alloc_context(state))) {
+               kfree(key);
                audit_log_lost("out of memory in audit_alloc");
                return -ENOMEM;
        }
+       context->filterkey = key;
 
        tsk->audit_context  = context;
        set_tsk_thread_flag(tsk, TIF_SYSCALL_AUDIT);
@@ -921,6 +908,7 @@ static inline void audit_free_context(struct audit_context *context)
                free_tree_refs(context);
                audit_free_aux(context);
                kfree(context->filterkey);
+               kfree(context->sockaddr);
                kfree(context);
                context  = previous;
        } while (context);
@@ -1230,6 +1218,97 @@ static void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name)
                audit_log_format(ab, " cap_fe=%d cap_fver=%x", name->fcap.fE, name->fcap_ver);
 }
 
+static void show_special(struct audit_context *context, int *call_panic)
+{
+       struct audit_buffer *ab;
+       int i;
+
+       ab = audit_log_start(context, GFP_KERNEL, context->type);
+       if (!ab)
+               return;
+
+       switch (context->type) {
+       case AUDIT_SOCKETCALL: {
+               int nargs = context->socketcall.nargs;
+               audit_log_format(ab, "nargs=%d", nargs);
+               for (i = 0; i < nargs; i++)
+                       audit_log_format(ab, " a%d=%lx", i,
+                               context->socketcall.args[i]);
+               break; }
+       case AUDIT_IPC: {
+               u32 osid = context->ipc.osid;
+
+               audit_log_format(ab, "ouid=%u ogid=%u mode=%#o",
+                        context->ipc.uid, context->ipc.gid, context->ipc.mode);
+               if (osid) {
+                       char *ctx = NULL;
+                       u32 len;
+                       if (security_secid_to_secctx(osid, &ctx, &len)) {
+                               audit_log_format(ab, " osid=%u", osid);
+                               *call_panic = 1;
+                       } else {
+                               audit_log_format(ab, " obj=%s", ctx);
+                               security_release_secctx(ctx, len);
+                       }
+               }
+               if (context->ipc.has_perm) {
+                       audit_log_end(ab);
+                       ab = audit_log_start(context, GFP_KERNEL,
+                                            AUDIT_IPC_SET_PERM);
+                       audit_log_format(ab,
+                               "qbytes=%lx ouid=%u ogid=%u mode=%#o",
+                               context->ipc.qbytes,
+                               context->ipc.perm_uid,
+                               context->ipc.perm_gid,
+                               context->ipc.perm_mode);
+                       if (!ab)
+                               return;
+               }
+               break; }
+       case AUDIT_MQ_OPEN: {
+               audit_log_format(ab,
+                       "oflag=0x%x mode=%#o mq_flags=0x%lx mq_maxmsg=%ld "
+                       "mq_msgsize=%ld mq_curmsgs=%ld",
+                       context->mq_open.oflag, context->mq_open.mode,
+                       context->mq_open.attr.mq_flags,
+                       context->mq_open.attr.mq_maxmsg,
+                       context->mq_open.attr.mq_msgsize,
+                       context->mq_open.attr.mq_curmsgs);
+               break; }
+       case AUDIT_MQ_SENDRECV: {
+               audit_log_format(ab,
+                       "mqdes=%d msg_len=%zd msg_prio=%u "
+                       "abs_timeout_sec=%ld abs_timeout_nsec=%ld",
+                       context->mq_sendrecv.mqdes,
+                       context->mq_sendrecv.msg_len,
+                       context->mq_sendrecv.msg_prio,
+                       context->mq_sendrecv.abs_timeout.tv_sec,
+                       context->mq_sendrecv.abs_timeout.tv_nsec);
+               break; }
+       case AUDIT_MQ_NOTIFY: {
+               audit_log_format(ab, "mqdes=%d sigev_signo=%d",
+                               context->mq_notify.mqdes,
+                               context->mq_notify.sigev_signo);
+               break; }
+       case AUDIT_MQ_GETSETATTR: {
+               struct mq_attr *attr = &context->mq_getsetattr.mqstat;
+               audit_log_format(ab,
+                       "mqdes=%d mq_flags=0x%lx mq_maxmsg=%ld mq_msgsize=%ld "
+                       "mq_curmsgs=%ld ",
+                       context->mq_getsetattr.mqdes,
+                       attr->mq_flags, attr->mq_maxmsg,
+                       attr->mq_msgsize, attr->mq_curmsgs);
+               break; }
+       case AUDIT_CAPSET: {
+               audit_log_format(ab, "pid=%d", context->capset.pid);
+               audit_log_cap(ab, "cap_pi", &context->capset.cap.inheritable);
+               audit_log_cap(ab, "cap_pp", &context->capset.cap.permitted);
+               audit_log_cap(ab, "cap_pe", &context->capset.cap.effective);
+               break; }
+       }
+       audit_log_end(ab);
+}
+
 static void audit_log_exit(struct audit_context *context, struct task_struct *tsk)
 {
        const struct cred *cred;
@@ -1307,94 +1386,12 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
                        continue; /* audit_panic has been called */
 
                switch (aux->type) {
-               case AUDIT_MQ_OPEN: {
-                       struct audit_aux_data_mq_open *axi = (void *)aux;
-                       audit_log_format(ab,
-                               "oflag=0x%x mode=%#o mq_flags=0x%lx mq_maxmsg=%ld "
-                               "mq_msgsize=%ld mq_curmsgs=%ld",
-                               axi->oflag, axi->mode, axi->attr.mq_flags,
-                               axi->attr.mq_maxmsg, axi->attr.mq_msgsize,
-                               axi->attr.mq_curmsgs);
-                       break; }
-
-               case AUDIT_MQ_SENDRECV: {
-                       struct audit_aux_data_mq_sendrecv *axi = (void *)aux;
-                       audit_log_format(ab,
-                               "mqdes=%d msg_len=%zd msg_prio=%u "
-                               "abs_timeout_sec=%ld abs_timeout_nsec=%ld",
-                               axi->mqdes, axi->msg_len, axi->msg_prio,
-                               axi->abs_timeout.tv_sec, axi->abs_timeout.tv_nsec);
-                       break; }
-
-               case AUDIT_MQ_NOTIFY: {
-                       struct audit_aux_data_mq_notify *axi = (void *)aux;
-                       audit_log_format(ab,
-                               "mqdes=%d sigev_signo=%d",
-                               axi->mqdes,
-                               axi->notification.sigev_signo);
-                       break; }
-
-               case AUDIT_MQ_GETSETATTR: {
-                       struct audit_aux_data_mq_getsetattr *axi = (void *)aux;
-                       audit_log_format(ab,
-                               "mqdes=%d mq_flags=0x%lx mq_maxmsg=%ld mq_msgsize=%ld "
-                               "mq_curmsgs=%ld ",
-                               axi->mqdes,
-                               axi->mqstat.mq_flags, axi->mqstat.mq_maxmsg,
-                               axi->mqstat.mq_msgsize, axi->mqstat.mq_curmsgs);
-                       break; }
-
-               case AUDIT_IPC: {
-                       struct audit_aux_data_ipcctl *axi = (void *)aux;
-                       audit_log_format(ab, 
-                                "ouid=%u ogid=%u mode=%#o",
-                                axi->uid, axi->gid, axi->mode);
-                       if (axi->osid != 0) {
-                               char *ctx = NULL;
-                               u32 len;
-                               if (security_secid_to_secctx(
-                                               axi->osid, &ctx, &len)) {
-                                       audit_log_format(ab, " osid=%u",
-                                                       axi->osid);
-                                       call_panic = 1;
-                               } else {
-                                       audit_log_format(ab, " obj=%s", ctx);
-                                       security_release_secctx(ctx, len);
-                               }
-                       }
-                       break; }
-
-               case AUDIT_IPC_SET_PERM: {
-                       struct audit_aux_data_ipcctl *axi = (void *)aux;
-                       audit_log_format(ab,
-                               "qbytes=%lx ouid=%u ogid=%u mode=%#o",
-                               axi->qbytes, axi->uid, axi->gid, axi->mode);
-                       break; }
 
                case AUDIT_EXECVE: {
                        struct audit_aux_data_execve *axi = (void *)aux;
                        audit_log_execve_info(context, &ab, axi);
                        break; }
 
-               case AUDIT_SOCKETCALL: {
-                       struct audit_aux_data_socketcall *axs = (void *)aux;
-                       audit_log_format(ab, "nargs=%d", axs->nargs);
-                       for (i=0; i<axs->nargs; i++)
-                               audit_log_format(ab, " a%d=%lx", i, axs->args[i]);
-                       break; }
-
-               case AUDIT_SOCKADDR: {
-                       struct audit_aux_data_sockaddr *axs = (void *)aux;
-
-                       audit_log_format(ab, "saddr=");
-                       audit_log_n_hex(ab, axs->a, axs->len);
-                       break; }
-
-               case AUDIT_FD_PAIR: {
-                       struct audit_aux_data_fd_pair *axs = (void *)aux;
-                       audit_log_format(ab, "fd0=%d fd1=%d", axs->fd[0], axs->fd[1]);
-                       break; }
-
                case AUDIT_BPRM_FCAPS: {
                        struct audit_aux_data_bprm_fcaps *axs = (void *)aux;
                        audit_log_format(ab, "fver=%x", axs->fcap_ver);
@@ -1409,18 +1406,32 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
                        audit_log_cap(ab, "new_pe", &axs->new_pcap.effective);
                        break; }
 
-               case AUDIT_CAPSET: {
-                       struct audit_aux_data_capset *axs = (void *)aux;
-                       audit_log_format(ab, "pid=%d", axs->pid);
-                       audit_log_cap(ab, "cap_pi", &axs->cap.inheritable);
-                       audit_log_cap(ab, "cap_pp", &axs->cap.permitted);
-                       audit_log_cap(ab, "cap_pe", &axs->cap.effective);
-                       break; }
-
                }
                audit_log_end(ab);
        }
 
+       if (context->type)
+               show_special(context, &call_panic);
+
+       if (context->fds[0] >= 0) {
+               ab = audit_log_start(context, GFP_KERNEL, AUDIT_FD_PAIR);
+               if (ab) {
+                       audit_log_format(ab, "fd0=%d fd1=%d",
+                                       context->fds[0], context->fds[1]);
+                       audit_log_end(ab);
+               }
+       }
+
+       if (context->sockaddr_len) {
+               ab = audit_log_start(context, GFP_KERNEL, AUDIT_SOCKADDR);
+               if (ab) {
+                       audit_log_format(ab, "saddr=");
+                       audit_log_n_hex(ab, (void *)context->sockaddr,
+                                       context->sockaddr_len);
+                       audit_log_end(ab);
+               }
+       }
+
        for (aux = context->aux_pids; aux; aux = aux->next) {
                struct audit_aux_data_pids *axs = (void *)aux;
 
@@ -1536,7 +1547,7 @@ void audit_free(struct task_struct *tsk)
         * We use GFP_ATOMIC here because we might be doing this
         * in the context of the idle thread */
        /* that can happen only if we are called from do_exit() */
-       if (context->in_syscall && context->auditable)
+       if (context->in_syscall && context->current_state == AUDIT_RECORD_CONTEXT)
                audit_log_exit(context, tsk);
 
        audit_free_context(context);
@@ -1620,15 +1631,17 @@ void audit_syscall_entry(int arch, int major,
 
        state = context->state;
        context->dummy = !audit_n_rules;
-       if (!context->dummy && (state == AUDIT_SETUP_CONTEXT || state == AUDIT_BUILD_CONTEXT))
+       if (!context->dummy && state == AUDIT_BUILD_CONTEXT) {
+               context->prio = 0;
                state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_ENTRY]);
+       }
        if (likely(state == AUDIT_DISABLED))
                return;
 
        context->serial     = 0;
        context->ctime      = CURRENT_TIME;
        context->in_syscall = 1;
-       context->auditable  = !!(state == AUDIT_RECORD_CONTEXT);
+       context->current_state  = state;
        context->ppid       = 0;
 }
 
@@ -1636,17 +1649,20 @@ void audit_finish_fork(struct task_struct *child)
 {
        struct audit_context *ctx = current->audit_context;
        struct audit_context *p = child->audit_context;
-       if (!p || !ctx || !ctx->auditable)
+       if (!p || !ctx)
+               return;
+       if (!ctx->in_syscall || ctx->current_state != AUDIT_RECORD_CONTEXT)
                return;
        p->arch = ctx->arch;
        p->major = ctx->major;
        memcpy(p->argv, ctx->argv, sizeof(ctx->argv));
        p->ctime = ctx->ctime;
        p->dummy = ctx->dummy;
-       p->auditable = ctx->auditable;
        p->in_syscall = ctx->in_syscall;
        p->filterkey = kstrdup(ctx->filterkey, GFP_KERNEL);
        p->ppid = current->pid;
+       p->prio = ctx->prio;
+       p->current_state = ctx->current_state;
 }
 
 /**
@@ -1670,11 +1686,11 @@ void audit_syscall_exit(int valid, long return_code)
        if (likely(!context))
                return;
 
-       if (context->in_syscall && context->auditable)
+       if (context->in_syscall && context->current_state == AUDIT_RECORD_CONTEXT)
                audit_log_exit(context, tsk);
 
        context->in_syscall = 0;
-       context->auditable  = 0;
+       context->prio = context->state == AUDIT_RECORD_CONTEXT ? ~0ULL : 0;
 
        if (context->previous) {
                struct audit_context *new_context = context->previous;
@@ -1689,8 +1705,13 @@ void audit_syscall_exit(int valid, long return_code)
                context->aux_pids = NULL;
                context->target_pid = 0;
                context->target_sid = 0;
-               kfree(context->filterkey);
-               context->filterkey = NULL;
+               context->sockaddr_len = 0;
+               context->type = 0;
+               context->fds[0] = -1;
+               if (context->state != AUDIT_RECORD_CONTEXT) {
+                       kfree(context->filterkey);
+                       context->filterkey = NULL;
+               }
                tsk->audit_context = context;
        }
 }
@@ -2081,7 +2102,10 @@ int auditsc_get_stamp(struct audit_context *ctx,
        t->tv_sec  = ctx->ctime.tv_sec;
        t->tv_nsec = ctx->ctime.tv_nsec;
        *serial    = ctx->serial;
-       ctx->auditable = 1;
+       if (!ctx->prio) {
+               ctx->prio = 1;
+               ctx->current_state = AUDIT_RECORD_CONTEXT;
+       }
        return 1;
 }
 
@@ -2127,132 +2151,46 @@ int audit_set_loginuid(struct task_struct *task, uid_t loginuid)
  * @mode: mode bits
  * @u_attr: queue attributes
  *
- * Returns 0 for success or NULL context or < 0 on error.
  */
-int __audit_mq_open(int oflag, mode_t mode, struct mq_attr __user *u_attr)
+void __audit_mq_open(int oflag, mode_t mode, struct mq_attr *attr)
 {
-       struct audit_aux_data_mq_open *ax;
        struct audit_context *context = current->audit_context;
 
-       if (!audit_enabled)
-               return 0;
-
-       if (likely(!context))
-               return 0;
-
-       ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
-       if (!ax)
-               return -ENOMEM;
-
-       if (u_attr != NULL) {
-               if (copy_from_user(&ax->attr, u_attr, sizeof(ax->attr))) {
-                       kfree(ax);
-                       return -EFAULT;
-               }
-       } else
-               memset(&ax->attr, 0, sizeof(ax->attr));
+       if (attr)
+               memcpy(&context->mq_open.attr, attr, sizeof(struct mq_attr));
+       else
+               memset(&context->mq_open.attr, 0, sizeof(struct mq_attr));
 
-       ax->oflag = oflag;
-       ax->mode = mode;
+       context->mq_open.oflag = oflag;
+       context->mq_open.mode = mode;
 
-       ax->d.type = AUDIT_MQ_OPEN;
-       ax->d.next = context->aux;
-       context->aux = (void *)ax;
-       return 0;
+       context->type = AUDIT_MQ_OPEN;
 }
 
 /**
- * __audit_mq_timedsend - record audit data for a POSIX MQ timed send
+ * __audit_mq_sendrecv - record audit data for a POSIX MQ timed send/receive
  * @mqdes: MQ descriptor
  * @msg_len: Message length
  * @msg_prio: Message priority
- * @u_abs_timeout: Message timeout in absolute time
+ * @abs_timeout: Message timeout in absolute time
  *
- * Returns 0 for success or NULL context or < 0 on error.
  */
-int __audit_mq_timedsend(mqd_t mqdes, size_t msg_len, unsigned int msg_prio,
-                       const struct timespec __user *u_abs_timeout)
+void __audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio,
+                       const struct timespec *abs_timeout)
 {
-       struct audit_aux_data_mq_sendrecv *ax;
        struct audit_context *context = current->audit_context;
+       struct timespec *p = &context->mq_sendrecv.abs_timeout;
 
-       if (!audit_enabled)
-               return 0;
-
-       if (likely(!context))
-               return 0;
-
-       ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
-       if (!ax)
-               return -ENOMEM;
-
-       if (u_abs_timeout != NULL) {
-               if (copy_from_user(&ax->abs_timeout, u_abs_timeout, sizeof(ax->abs_timeout))) {
-                       kfree(ax);
-                       return -EFAULT;
-               }
-       } else
-               memset(&ax->abs_timeout, 0, sizeof(ax->abs_timeout));
-
-       ax->mqdes = mqdes;
-       ax->msg_len = msg_len;
-       ax->msg_prio = msg_prio;
-
-       ax->d.type = AUDIT_MQ_SENDRECV;
-       ax->d.next = context->aux;
-       context->aux = (void *)ax;
-       return 0;
-}
-
-/**
- * __audit_mq_timedreceive - record audit data for a POSIX MQ timed receive
- * @mqdes: MQ descriptor
- * @msg_len: Message length
- * @u_msg_prio: Message priority
- * @u_abs_timeout: Message timeout in absolute time
- *
- * Returns 0 for success or NULL context or < 0 on error.
- */
-int __audit_mq_timedreceive(mqd_t mqdes, size_t msg_len,
-                               unsigned int __user *u_msg_prio,
-                               const struct timespec __user *u_abs_timeout)
-{
-       struct audit_aux_data_mq_sendrecv *ax;
-       struct audit_context *context = current->audit_context;
-
-       if (!audit_enabled)
-               return 0;
-
-       if (likely(!context))
-               return 0;
-
-       ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
-       if (!ax)
-               return -ENOMEM;
-
-       if (u_msg_prio != NULL) {
-               if (get_user(ax->msg_prio, u_msg_prio)) {
-                       kfree(ax);
-                       return -EFAULT;
-               }
-       } else
-               ax->msg_prio = 0;
-
-       if (u_abs_timeout != NULL) {
-               if (copy_from_user(&ax->abs_timeout, u_abs_timeout, sizeof(ax->abs_timeout))) {
-                       kfree(ax);
-                       return -EFAULT;
-               }
-       } else
-               memset(&ax->abs_timeout, 0, sizeof(ax->abs_timeout));
+       if (abs_timeout)
+               memcpy(p, abs_timeout, sizeof(struct timespec));
+       else
+               memset(p, 0, sizeof(struct timespec));
 
-       ax->mqdes = mqdes;
-       ax->msg_len = msg_len;
+       context->mq_sendrecv.mqdes = mqdes;
+       context->mq_sendrecv.msg_len = msg_len;
+       context->mq_sendrecv.msg_prio = msg_prio;
 
-       ax->d.type = AUDIT_MQ_SENDRECV;
-       ax->d.next = context->aux;
-       context->aux = (void *)ax;
-       return 0;
+       context->type = AUDIT_MQ_SENDRECV;
 }
 
 /**
@@ -2260,38 +2198,19 @@ int __audit_mq_timedreceive(mqd_t mqdes, size_t msg_len,
  * @mqdes: MQ descriptor
  * @u_notification: Notification event
  *
- * Returns 0 for success or NULL context or < 0 on error.
  */
 
-int __audit_mq_notify(mqd_t mqdes, const struct sigevent __user *u_notification)
+void __audit_mq_notify(mqd_t mqdes, const struct sigevent *notification)
 {
-       struct audit_aux_data_mq_notify *ax;
        struct audit_context *context = current->audit_context;
 
-       if (!audit_enabled)
-               return 0;
-
-       if (likely(!context))
-               return 0;
-
-       ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
-       if (!ax)
-               return -ENOMEM;
-
-       if (u_notification != NULL) {
-               if (copy_from_user(&ax->notification, u_notification, sizeof(ax->notification))) {
-                       kfree(ax);
-                       return -EFAULT;
-               }
-       } else
-               memset(&ax->notification, 0, sizeof(ax->notification));
-
-       ax->mqdes = mqdes;
+       if (notification)
+               context->mq_notify.sigev_signo = notification->sigev_signo;
+       else
+               context->mq_notify.sigev_signo = 0;
 
-       ax->d.type = AUDIT_MQ_NOTIFY;
-       ax->d.next = context->aux;
-       context->aux = (void *)ax;
-       return 0;
+       context->mq_notify.mqdes = mqdes;
+       context->type = AUDIT_MQ_NOTIFY;
 }
 
 /**
@@ -2299,55 +2218,29 @@ int __audit_mq_notify(mqd_t mqdes, const struct sigevent __user *u_notification)
  * @mqdes: MQ descriptor
  * @mqstat: MQ flags
  *
- * Returns 0 for success or NULL context or < 0 on error.
  */
-int __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat)
+void __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat)
 {
-       struct audit_aux_data_mq_getsetattr *ax;
        struct audit_context *context = current->audit_context;
-
-       if (!audit_enabled)
-               return 0;
-
-       if (likely(!context))
-               return 0;
-
-       ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
-       if (!ax)
-               return -ENOMEM;
-
-       ax->mqdes = mqdes;
-       ax->mqstat = *mqstat;
-
-       ax->d.type = AUDIT_MQ_GETSETATTR;
-       ax->d.next = context->aux;
-       context->aux = (void *)ax;
-       return 0;
+       context->mq_getsetattr.mqdes = mqdes;
+       context->mq_getsetattr.mqstat = *mqstat;
+       context->type = AUDIT_MQ_GETSETATTR;
 }
 
 /**
  * audit_ipc_obj - record audit data for ipc object
  * @ipcp: ipc permissions
  *
- * Returns 0 for success or NULL context or < 0 on error.
  */
-int __audit_ipc_obj(struct kern_ipc_perm *ipcp)
+void __audit_ipc_obj(struct kern_ipc_perm *ipcp)
 {
-       struct audit_aux_data_ipcctl *ax;
        struct audit_context *context = current->audit_context;
-
-       ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
-       if (!ax)
-               return -ENOMEM;
-
-       ax->uid = ipcp->uid;
-       ax->gid = ipcp->gid;
-       ax->mode = ipcp->mode;
-       security_ipc_getsecid(ipcp, &ax->osid);
-       ax->d.type = AUDIT_IPC;
-       ax->d.next = context->aux;
-       context->aux = (void *)ax;
-       return 0;
+       context->ipc.uid = ipcp->uid;
+       context->ipc.gid = ipcp->gid;
+       context->ipc.mode = ipcp->mode;
+       context->ipc.has_perm = 0;
+       security_ipc_getsecid(ipcp, &context->ipc.osid);
+       context->type = AUDIT_IPC;
 }
 
 /**
@@ -2357,26 +2250,17 @@ int __audit_ipc_obj(struct kern_ipc_perm *ipcp)
  * @gid: msgq group id
  * @mode: msgq mode (permissions)
  *
- * Returns 0 for success or NULL context or < 0 on error.
+ * Called only after audit_ipc_obj().
  */
-int __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode)
+void __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode)
 {
-       struct audit_aux_data_ipcctl *ax;
        struct audit_context *context = current->audit_context;
 
-       ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
-       if (!ax)
-               return -ENOMEM;
-
-       ax->qbytes = qbytes;
-       ax->uid = uid;
-       ax->gid = gid;
-       ax->mode = mode;
-
-       ax->d.type = AUDIT_IPC_SET_PERM;
-       ax->d.next = context->aux;
-       context->aux = (void *)ax;
-       return 0;
+       context->ipc.qbytes = qbytes;
+       context->ipc.perm_uid = uid;
+       context->ipc.perm_gid = gid;
+       context->ipc.perm_mode = mode;
+       context->ipc.has_perm = 1;
 }
 
 int audit_bprm(struct linux_binprm *bprm)
@@ -2406,27 +2290,17 @@ int audit_bprm(struct linux_binprm *bprm)
  * @nargs: number of args
  * @args: args array
  *
- * Returns 0 for success or NULL context or < 0 on error.
  */
-int audit_socketcall(int nargs, unsigned long *args)
+void audit_socketcall(int nargs, unsigned long *args)
 {
-       struct audit_aux_data_socketcall *ax;
        struct audit_context *context = current->audit_context;
 
        if (likely(!context || context->dummy))
-               return 0;
-
-       ax = kmalloc(sizeof(*ax) + nargs * sizeof(unsigned long), GFP_KERNEL);
-       if (!ax)
-               return -ENOMEM;
-
-       ax->nargs = nargs;
-       memcpy(ax->args, args, nargs * sizeof(unsigned long));
+               return;
 
-       ax->d.type = AUDIT_SOCKETCALL;
-       ax->d.next = context->aux;
-       context->aux = (void *)ax;
-       return 0;
+       context->type = AUDIT_SOCKETCALL;
+       context->socketcall.nargs = nargs;
+       memcpy(context->socketcall.args, args, nargs * sizeof(unsigned long));
 }
 
 /**
@@ -2434,29 +2308,12 @@ int audit_socketcall(int nargs, unsigned long *args)
  * @fd1: the first file descriptor
  * @fd2: the second file descriptor
  *
- * Returns 0 for success or NULL context or < 0 on error.
  */
-int __audit_fd_pair(int fd1, int fd2)
+void __audit_fd_pair(int fd1, int fd2)
 {
        struct audit_context *context = current->audit_context;
-       struct audit_aux_data_fd_pair *ax;
-
-       if (likely(!context)) {
-               return 0;
-       }
-
-       ax = kmalloc(sizeof(*ax), GFP_KERNEL);
-       if (!ax) {
-               return -ENOMEM;
-       }
-
-       ax->fd[0] = fd1;
-       ax->fd[1] = fd2;
-
-       ax->d.type = AUDIT_FD_PAIR;
-       ax->d.next = context->aux;
-       context->aux = (void *)ax;
-       return 0;
+       context->fds[0] = fd1;
+       context->fds[1] = fd2;
 }
 
 /**
@@ -2468,22 +2325,20 @@ int __audit_fd_pair(int fd1, int fd2)
  */
 int audit_sockaddr(int len, void *a)
 {
-       struct audit_aux_data_sockaddr *ax;
        struct audit_context *context = current->audit_context;
 
        if (likely(!context || context->dummy))
                return 0;
 
-       ax = kmalloc(sizeof(*ax) + len, GFP_KERNEL);
-       if (!ax)
-               return -ENOMEM;
-
-       ax->len = len;
-       memcpy(ax->a, a, len);
+       if (!context->sockaddr) {
+               void *p = kmalloc(sizeof(struct sockaddr_storage), GFP_KERNEL);
+               if (!p)
+                       return -ENOMEM;
+               context->sockaddr = p;
+       }
 
-       ax->d.type = AUDIT_SOCKADDR;
-       ax->d.next = context->aux;
-       context->aux = (void *)ax;
+       context->sockaddr_len = len;
+       memcpy(context->sockaddr, a, len);
        return 0;
 }
 
@@ -2617,29 +2472,15 @@ int __audit_log_bprm_fcaps(struct linux_binprm *bprm,
  * Record the aguments userspace sent to sys_capset for later printing by the
  * audit system if applicable
  */
-int __audit_log_capset(pid_t pid,
+void __audit_log_capset(pid_t pid,
                       const struct cred *new, const struct cred *old)
 {
-       struct audit_aux_data_capset *ax;
        struct audit_context *context = current->audit_context;
-
-       if (likely(!audit_enabled || !context || context->dummy))
-               return 0;
-
-       ax = kmalloc(sizeof(*ax), GFP_KERNEL);
-       if (!ax)
-               return -ENOMEM;
-
-       ax->d.type = AUDIT_CAPSET;
-       ax->d.next = context->aux;
-       context->aux = (void *)ax;
-
-       ax->pid = pid;
-       ax->cap.effective   = new->cap_effective;
-       ax->cap.inheritable = new->cap_effective;
-       ax->cap.permitted   = new->cap_permitted;
-
-       return 0;
+       context->capset.pid = pid;
+       context->capset.cap.effective   = new->cap_effective;
+       context->capset.cap.inheritable = new->cap_effective;
+       context->capset.cap.permitted   = new->cap_permitted;
+       context->type = AUDIT_CAPSET;
 }
 
 /**
index 36b4b4daebec0a465fb8490c9531ed71d694ae59..c598d9d5be4fd6d325286ddab316ff8ae0e22651 100644 (file)
@@ -280,9 +280,7 @@ asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data)
        if (ret < 0)
                goto error;
 
-       ret = audit_log_capset(pid, new, current_cred());
-       if (ret < 0)
-               return ret;
+       audit_log_capset(pid, new, current_cred());
 
        return commit_creds(new);
 
index 48348dde6d814ea52270edee180c3db89da5d0c4..87bb0258fd27a781d8fe8bbe5519a389f27a70b1 100644 (file)
@@ -573,7 +573,6 @@ static struct inode *cgroup_new_inode(mode_t mode, struct super_block *sb)
                inode->i_mode = mode;
                inode->i_uid = current_fsuid();
                inode->i_gid = current_fsgid();
-               inode->i_blocks = 0;
                inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
                inode->i_mapping->backing_dev_info = &cgroup_backing_dev_info;
        }
@@ -2945,7 +2944,11 @@ int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *subsys,
        parent = task_cgroup(tsk, subsys->subsys_id);
 
        /* Pin the hierarchy */
-       atomic_inc(&parent->root->sb->s_active);
+       if (!atomic_inc_not_zero(&parent->root->sb->s_active)) {
+               /* We race with the final deactivate_super() */
+               mutex_unlock(&cgroup_mutex);
+               return 0;
+       }
 
        /* Keep the cgroup alive */
        get_css_set(cg);
index 8eafe3eb50d9feb76dce5b289a4a7278321e4d8a..d52e2ec1deb59d521d3a8c89c230a68d41c33d3e 100644 (file)
@@ -454,16 +454,16 @@ asmlinkage long compat_sys_waitid(int which, compat_pid_t pid,
 }
 
 static int compat_get_user_cpu_mask(compat_ulong_t __user *user_mask_ptr,
-                                   unsigned len, cpumask_t *new_mask)
+                                   unsigned len, struct cpumask *new_mask)
 {
        unsigned long *k;
 
-       if (len < sizeof(cpumask_t))
-               memset(new_mask, 0, sizeof(cpumask_t));
-       else if (len > sizeof(cpumask_t))
-               len = sizeof(cpumask_t);
+       if (len < cpumask_size())
+               memset(new_mask, 0, cpumask_size());
+       else if (len > cpumask_size())
+               len = cpumask_size();
 
-       k = cpus_addr(*new_mask);
+       k = cpumask_bits(new_mask);
        return compat_get_bitmap(k, user_mask_ptr, len * 8);
 }
 
@@ -471,40 +471,51 @@ asmlinkage long compat_sys_sched_setaffinity(compat_pid_t pid,
                                             unsigned int len,
                                             compat_ulong_t __user *user_mask_ptr)
 {
-       cpumask_t new_mask;
+       cpumask_var_t new_mask;
        int retval;
 
-       retval = compat_get_user_cpu_mask(user_mask_ptr, len, &new_mask);
+       if (!alloc_cpumask_var(&new_mask, GFP_KERNEL))
+               return -ENOMEM;
+
+       retval = compat_get_user_cpu_mask(user_mask_ptr, len, new_mask);
        if (retval)
-               return retval;
+               goto out;
 
-       return sched_setaffinity(pid, &new_mask);
+       retval = sched_setaffinity(pid, new_mask);
+out:
+       free_cpumask_var(new_mask);
+       return retval;
 }
 
 asmlinkage long compat_sys_sched_getaffinity(compat_pid_t pid, unsigned int len,
                                             compat_ulong_t __user *user_mask_ptr)
 {
        int ret;
-       cpumask_t mask;
+       cpumask_var_t mask;
        unsigned long *k;
-       unsigned int min_length = sizeof(cpumask_t);
+       unsigned int min_length = cpumask_size();
 
-       if (NR_CPUS <= BITS_PER_COMPAT_LONG)
+       if (nr_cpu_ids <= BITS_PER_COMPAT_LONG)
                min_length = sizeof(compat_ulong_t);
 
        if (len < min_length)
                return -EINVAL;
 
-       ret = sched_getaffinity(pid, &mask);
+       if (!alloc_cpumask_var(&mask, GFP_KERNEL))
+               return -ENOMEM;
+
+       ret = sched_getaffinity(pid, mask);
        if (ret < 0)
-               return ret;
+               goto out;
 
-       k = cpus_addr(mask);
+       k = cpumask_bits(mask);
        ret = compat_put_bitmap(user_mask_ptr, k, min_length * 8);
-       if (ret)
-               return ret;
+       if (ret == 0)
+               ret = min_length;
 
-       return min_length;
+out:
+       free_cpumask_var(mask);
+       return ret;
 }
 
 int get_compat_itimerspec(struct itimerspec *dst,
index bae131a1211b55a9051bfe581dd74df8e72dc248..47fff3b63cbf5ac8f3cd92de1299a371a8e2d4dd 100644 (file)
 #include <linux/stop_machine.h>
 #include <linux/mutex.h>
 
-/*
- * Represents all cpu's present in the system
- * In systems capable of hotplug, this map could dynamically grow
- * as new cpu's are detected in the system via any platform specific
- * method, such as ACPI for e.g.
- */
-cpumask_t cpu_present_map __read_mostly;
-EXPORT_SYMBOL(cpu_present_map);
-
-/*
- * Represents all cpu's that are currently online.
- */
-cpumask_t cpu_online_map __read_mostly;
-EXPORT_SYMBOL(cpu_online_map);
-
-#ifdef CONFIG_INIT_ALL_POSSIBLE
-cpumask_t cpu_possible_map __read_mostly = CPU_MASK_ALL;
-#else
-cpumask_t cpu_possible_map __read_mostly;
-#endif
-EXPORT_SYMBOL(cpu_possible_map);
-
 #ifdef CONFIG_SMP
-/* Serializes the updates to cpu_online_map, cpu_present_map */
+/* Serializes the updates to cpu_online_mask, cpu_present_mask */
 static DEFINE_MUTEX(cpu_add_remove_lock);
 
 static __cpuinitdata RAW_NOTIFIER_HEAD(cpu_chain);
@@ -65,8 +43,6 @@ void __init cpu_hotplug_init(void)
        cpu_hotplug.refcount = 0;
 }
 
-cpumask_t cpu_active_map;
-
 #ifdef CONFIG_HOTPLUG_CPU
 
 void get_online_cpus(void)
@@ -97,7 +73,7 @@ EXPORT_SYMBOL_GPL(put_online_cpus);
 
 /*
  * The following two API's must be used when attempting
- * to serialize the updates to cpu_online_map, cpu_present_map.
+ * to serialize the updates to cpu_online_mask, cpu_present_mask.
  */
 void cpu_maps_update_begin(void)
 {
@@ -218,7 +194,7 @@ static int __ref take_cpu_down(void *_param)
 static int __ref _cpu_down(unsigned int cpu, int tasks_frozen)
 {
        int err, nr_calls = 0;
-       cpumask_t old_allowed, tmp;
+       cpumask_var_t old_allowed;
        void *hcpu = (void *)(long)cpu;
        unsigned long mod = tasks_frozen ? CPU_TASKS_FROZEN : 0;
        struct take_cpu_down_param tcd_param = {
@@ -232,6 +208,9 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen)
        if (!cpu_online(cpu))
                return -EINVAL;
 
+       if (!alloc_cpumask_var(&old_allowed, GFP_KERNEL))
+               return -ENOMEM;
+
        cpu_hotplug_begin();
        err = __raw_notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE | mod,
                                        hcpu, -1, &nr_calls);
@@ -246,13 +225,11 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen)
        }
 
        /* Ensure that we are not runnable on dying cpu */
-       old_allowed = current->cpus_allowed;
-       cpus_setall(tmp);
-       cpu_clear(cpu, tmp);
-       set_cpus_allowed_ptr(current, &tmp);
-       tmp = cpumask_of_cpu(cpu);
+       cpumask_copy(old_allowed, &current->cpus_allowed);
+       set_cpus_allowed_ptr(current,
+                            cpumask_of(cpumask_any_but(cpu_online_mask, cpu)));
 
-       err = __stop_machine(take_cpu_down, &tcd_param, &tmp);
+       err = __stop_machine(take_cpu_down, &tcd_param, cpumask_of(cpu));
        if (err) {
                /* CPU didn't die: tell everyone.  Can't complain. */
                if (raw_notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED | mod,
@@ -278,7 +255,7 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen)
        check_for_tasks(cpu);
 
 out_allowed:
-       set_cpus_allowed_ptr(current, &old_allowed);
+       set_cpus_allowed_ptr(current, old_allowed);
 out_release:
        cpu_hotplug_done();
        if (!err) {
@@ -286,6 +263,7 @@ out_release:
                                            hcpu) == NOTIFY_BAD)
                        BUG();
        }
+       free_cpumask_var(old_allowed);
        return err;
 }
 
@@ -304,7 +282,7 @@ int __ref cpu_down(unsigned int cpu)
 
        /*
         * Make sure the all cpus did the reschedule and are not
-        * using stale version of the cpu_active_map.
+        * using stale version of the cpu_active_mask.
         * This is not strictly necessary becuase stop_machine()
         * that we run down the line already provides the required
         * synchronization. But it's really a side effect and we do not
@@ -368,7 +346,7 @@ out_notify:
 int __cpuinit cpu_up(unsigned int cpu)
 {
        int err = 0;
-       if (!cpu_isset(cpu, cpu_possible_map)) {
+       if (!cpu_possible(cpu)) {
                printk(KERN_ERR "can't online cpu %d because it is not "
                        "configured as may-hotadd at boot time\n", cpu);
 #if defined(CONFIG_IA64) || defined(CONFIG_X86_64)
@@ -393,25 +371,25 @@ out:
 }
 
 #ifdef CONFIG_PM_SLEEP_SMP
-static cpumask_t frozen_cpus;
+static cpumask_var_t frozen_cpus;
 
 int disable_nonboot_cpus(void)
 {
        int cpu, first_cpu, error = 0;
 
        cpu_maps_update_begin();
-       first_cpu = first_cpu(cpu_online_map);
+       first_cpu = cpumask_first(cpu_online_mask);
        /* We take down all of the non-boot CPUs in one shot to avoid races
         * with the userspace trying to use the CPU hotplug at the same time
         */
-       cpus_clear(frozen_cpus);
+       cpumask_clear(frozen_cpus);
        printk("Disabling non-boot CPUs ...\n");
        for_each_online_cpu(cpu) {
                if (cpu == first_cpu)
                        continue;
                error = _cpu_down(cpu, 1);
                if (!error) {
-                       cpu_set(cpu, frozen_cpus);
+                       cpumask_set_cpu(cpu, frozen_cpus);
                        printk("CPU%d is down\n", cpu);
                } else {
                        printk(KERN_ERR "Error taking CPU%d down: %d\n",
@@ -437,11 +415,11 @@ void __ref enable_nonboot_cpus(void)
        /* Allow everyone to use the CPU hotplug again */
        cpu_maps_update_begin();
        cpu_hotplug_disabled = 0;
-       if (cpus_empty(frozen_cpus))
+       if (cpumask_empty(frozen_cpus))
                goto out;
 
        printk("Enabling non-boot CPUs ...\n");
-       for_each_cpu_mask_nr(cpu, frozen_cpus) {
+       for_each_cpu(cpu, frozen_cpus) {
                error = _cpu_up(cpu, 1);
                if (!error) {
                        printk("CPU%d is up\n", cpu);
@@ -449,10 +427,18 @@ void __ref enable_nonboot_cpus(void)
                }
                printk(KERN_WARNING "Error taking CPU%d up: %d\n", cpu, error);
        }
-       cpus_clear(frozen_cpus);
+       cpumask_clear(frozen_cpus);
 out:
        cpu_maps_update_done();
 }
+
+static int alloc_frozen_cpus(void)
+{
+       if (!alloc_cpumask_var(&frozen_cpus, GFP_KERNEL|__GFP_ZERO))
+               return -ENOMEM;
+       return 0;
+}
+core_initcall(alloc_frozen_cpus);
 #endif /* CONFIG_PM_SLEEP_SMP */
 
 /**
@@ -468,7 +454,7 @@ void __cpuinit notify_cpu_starting(unsigned int cpu)
        unsigned long val = CPU_STARTING;
 
 #ifdef CONFIG_PM_SLEEP_SMP
-       if (cpu_isset(cpu, frozen_cpus))
+       if (frozen_cpus != NULL && cpumask_test_cpu(cpu, frozen_cpus))
                val = CPU_STARTING_FROZEN;
 #endif /* CONFIG_PM_SLEEP_SMP */
        raw_notifier_call_chain(&cpu_chain, val, (void *)(long)cpu);
@@ -480,7 +466,7 @@ void __cpuinit notify_cpu_starting(unsigned int cpu)
  * cpu_bit_bitmap[] is a special, "compressed" data structure that
  * represents all NR_CPUS bits binary values of 1<<nr.
  *
- * It is used by cpumask_of_cpu() to get a constant address to a CPU
+ * It is used by cpumask_of() to get a constant address to a CPU
  * mask value that has a single bit set only.
  */
 
@@ -503,3 +489,71 @@ EXPORT_SYMBOL_GPL(cpu_bit_bitmap);
 
 const DECLARE_BITMAP(cpu_all_bits, NR_CPUS) = CPU_BITS_ALL;
 EXPORT_SYMBOL(cpu_all_bits);
+
+#ifdef CONFIG_INIT_ALL_POSSIBLE
+static DECLARE_BITMAP(cpu_possible_bits, CONFIG_NR_CPUS) __read_mostly
+       = CPU_BITS_ALL;
+#else
+static DECLARE_BITMAP(cpu_possible_bits, CONFIG_NR_CPUS) __read_mostly;
+#endif
+const struct cpumask *const cpu_possible_mask = to_cpumask(cpu_possible_bits);
+EXPORT_SYMBOL(cpu_possible_mask);
+
+static DECLARE_BITMAP(cpu_online_bits, CONFIG_NR_CPUS) __read_mostly;
+const struct cpumask *const cpu_online_mask = to_cpumask(cpu_online_bits);
+EXPORT_SYMBOL(cpu_online_mask);
+
+static DECLARE_BITMAP(cpu_present_bits, CONFIG_NR_CPUS) __read_mostly;
+const struct cpumask *const cpu_present_mask = to_cpumask(cpu_present_bits);
+EXPORT_SYMBOL(cpu_present_mask);
+
+static DECLARE_BITMAP(cpu_active_bits, CONFIG_NR_CPUS) __read_mostly;
+const struct cpumask *const cpu_active_mask = to_cpumask(cpu_active_bits);
+EXPORT_SYMBOL(cpu_active_mask);
+
+void set_cpu_possible(unsigned int cpu, bool possible)
+{
+       if (possible)
+               cpumask_set_cpu(cpu, to_cpumask(cpu_possible_bits));
+       else
+               cpumask_clear_cpu(cpu, to_cpumask(cpu_possible_bits));
+}
+
+void set_cpu_present(unsigned int cpu, bool present)
+{
+       if (present)
+               cpumask_set_cpu(cpu, to_cpumask(cpu_present_bits));
+       else
+               cpumask_clear_cpu(cpu, to_cpumask(cpu_present_bits));
+}
+
+void set_cpu_online(unsigned int cpu, bool online)
+{
+       if (online)
+               cpumask_set_cpu(cpu, to_cpumask(cpu_online_bits));
+       else
+               cpumask_clear_cpu(cpu, to_cpumask(cpu_online_bits));
+}
+
+void set_cpu_active(unsigned int cpu, bool active)
+{
+       if (active)
+               cpumask_set_cpu(cpu, to_cpumask(cpu_active_bits));
+       else
+               cpumask_clear_cpu(cpu, to_cpumask(cpu_active_bits));
+}
+
+void init_cpu_present(const struct cpumask *src)
+{
+       cpumask_copy(to_cpumask(cpu_present_bits), src);
+}
+
+void init_cpu_possible(const struct cpumask *src)
+{
+       cpumask_copy(to_cpumask(cpu_possible_bits), src);
+}
+
+void init_cpu_online(const struct cpumask *src)
+{
+       cpumask_copy(to_cpumask(cpu_online_bits), src);
+}
index 61c4a9b6216546aac546b4a6ab1427ed4ac2a00a..cd0cd8dcb3453aee98a20cd6652144cf10e42281 100644 (file)
 #include "internals.h"
 
 #ifdef CONFIG_SMP
+cpumask_var_t irq_default_affinity;
 
-cpumask_t irq_default_affinity = CPU_MASK_ALL;
+static int init_irq_default_affinity(void)
+{
+       alloc_cpumask_var(&irq_default_affinity, GFP_KERNEL);
+       cpumask_setall(irq_default_affinity);
+       return 0;
+}
+core_initcall(init_irq_default_affinity);
 
 /**
  *     synchronize_irq - wait for pending IRQ handlers (on other CPUs)
@@ -127,7 +134,7 @@ int do_irq_select_affinity(unsigned int irq, struct irq_desc *desc)
                        desc->status &= ~IRQ_AFFINITY_SET;
        }
 
-       cpumask_and(&desc->affinity, cpu_online_mask, &irq_default_affinity);
+       cpumask_and(&desc->affinity, cpu_online_mask, irq_default_affinity);
 set_affinity:
        desc->chip->set_affinity(irq, &desc->affinity);
 
index d2c0e5ee53c573019f45942e4d63bb362db42551..aae3f742bcec5cb7f5e348c2bec4a4945041966b 100644 (file)
@@ -20,7 +20,7 @@ static struct proc_dir_entry *root_irq_dir;
 static int irq_affinity_proc_show(struct seq_file *m, void *v)
 {
        struct irq_desc *desc = irq_to_desc((long)m->private);
-       cpumask_t *mask = &desc->affinity;
+       const struct cpumask *mask = &desc->affinity;
 
 #ifdef CONFIG_GENERIC_PENDING_IRQ
        if (desc->status & IRQ_MOVE_PENDING)
@@ -54,7 +54,7 @@ static ssize_t irq_affinity_proc_write(struct file *file,
        if (err)
                goto free_cpumask;
 
-       if (!is_affinity_mask_valid(*new_value)) {
+       if (!is_affinity_mask_valid(new_value)) {
                err = -EINVAL;
                goto free_cpumask;
        }
@@ -93,7 +93,7 @@ static const struct file_operations irq_affinity_proc_fops = {
 
 static int default_affinity_show(struct seq_file *m, void *v)
 {
-       seq_cpumask(m, &irq_default_affinity);
+       seq_cpumask(m, irq_default_affinity);
        seq_putc(m, '\n');
        return 0;
 }
@@ -101,27 +101,37 @@ static int default_affinity_show(struct seq_file *m, void *v)
 static ssize_t default_affinity_write(struct file *file,
                const char __user *buffer, size_t count, loff_t *ppos)
 {
-       cpumask_t new_value;
+       cpumask_var_t new_value;
        int err;
 
-       err = cpumask_parse_user(buffer, count, &new_value);
+       if (!alloc_cpumask_var(&new_value, GFP_KERNEL))
+               return -ENOMEM;
+
+       err = cpumask_parse_user(buffer, count, new_value);
        if (err)
-               return err;
+               goto out;
 
-       if (!is_affinity_mask_valid(new_value))
-               return -EINVAL;
+       if (!is_affinity_mask_valid(new_value)) {
+               err = -EINVAL;
+               goto out;
+       }
 
        /*
         * Do not allow disabling IRQs completely - it's a too easy
         * way to make the system unusable accidentally :-) At least
         * one online CPU still has to be targeted.
         */
-       if (!cpus_intersects(new_value, cpu_online_map))
-               return -EINVAL;
+       if (!cpumask_intersects(new_value, cpu_online_mask)) {
+               err = -EINVAL;
+               goto out;
+       }
 
-       irq_default_affinity = new_value;
+       cpumask_copy(irq_default_affinity, new_value);
+       err = count;
 
-       return count;
+out:
+       free_cpumask_var(new_value);
+       return err;
 }
 
 static int default_affinity_open(struct inode *inode, struct file *file)
index ac0fde7b54d082ee9ee327a0e57a7664f5cb72e7..3fb855ad6aa07fb5e03281aab28a1d163fb7686d 100644 (file)
@@ -1116,7 +1116,7 @@ void crash_save_cpu(struct pt_regs *regs, int cpu)
        struct elf_prstatus prstatus;
        u32 *buf;
 
-       if ((cpu < 0) || (cpu >= NR_CPUS))
+       if ((cpu < 0) || (cpu >= nr_cpu_ids))
                return;
 
        /* Using ELF notes here is opportunistic.
index 72016f051477c62941fb7e24697f9b6b87889b96..97890831e1b5b63f5e1e50d5d4c6014bf4b67257 100644 (file)
@@ -27,7 +27,7 @@ static DECLARE_WORK(poweroff_work, do_poweroff);
 static void handle_poweroff(int key, struct tty_struct *tty)
 {
        /* run sysrq poweroff on boot cpu */
-       schedule_work_on(first_cpu(cpu_online_map), &poweroff_work);
+       schedule_work_on(cpumask_first(cpu_online_mask), &poweroff_work);
 }
 
 static struct sysrq_key_op     sysrq_poweroff_op = {
index 4cb7d68fed82aabce7f74da9ecf30f3bb54b77e1..d18e2d2654f2b87ce45ecf7587440ce31f49d347 100644 (file)
@@ -45,7 +45,7 @@ static unsigned long prof_len, prof_shift;
 int prof_on __read_mostly;
 EXPORT_SYMBOL_GPL(prof_on);
 
-static cpumask_t prof_cpu_mask = CPU_MASK_ALL;
+static cpumask_var_t prof_cpu_mask;
 #ifdef CONFIG_SMP
 static DEFINE_PER_CPU(struct profile_hit *[2], cpu_profile_hits);
 static DEFINE_PER_CPU(int, cpu_profile_flip);
@@ -113,9 +113,13 @@ int __ref profile_init(void)
        buffer_bytes = prof_len*sizeof(atomic_t);
        if (!slab_is_available()) {
                prof_buffer = alloc_bootmem(buffer_bytes);
+               alloc_bootmem_cpumask_var(&prof_cpu_mask);
                return 0;
        }
 
+       if (!alloc_cpumask_var(&prof_cpu_mask, GFP_KERNEL))
+               return -ENOMEM;
+
        prof_buffer = kzalloc(buffer_bytes, GFP_KERNEL);
        if (prof_buffer)
                return 0;
@@ -128,6 +132,7 @@ int __ref profile_init(void)
        if (prof_buffer)
                return 0;
 
+       free_cpumask_var(prof_cpu_mask);
        return -ENOMEM;
 }
 
@@ -386,13 +391,15 @@ out_free:
                return NOTIFY_BAD;
        case CPU_ONLINE:
        case CPU_ONLINE_FROZEN:
-               cpu_set(cpu, prof_cpu_mask);
+               if (prof_cpu_mask != NULL)
+                       cpumask_set_cpu(cpu, prof_cpu_mask);
                break;
        case CPU_UP_CANCELED:
        case CPU_UP_CANCELED_FROZEN:
        case CPU_DEAD:
        case CPU_DEAD_FROZEN:
-               cpu_clear(cpu, prof_cpu_mask);
+               if (prof_cpu_mask != NULL)
+                       cpumask_clear_cpu(cpu, prof_cpu_mask);
                if (per_cpu(cpu_profile_hits, cpu)[0]) {
                        page = virt_to_page(per_cpu(cpu_profile_hits, cpu)[0]);
                        per_cpu(cpu_profile_hits, cpu)[0] = NULL;
@@ -430,7 +437,8 @@ void profile_tick(int type)
 
        if (type == CPU_PROFILING && timer_hook)
                timer_hook(regs);
-       if (!user_mode(regs) && cpu_isset(smp_processor_id(), prof_cpu_mask))
+       if (!user_mode(regs) && prof_cpu_mask != NULL &&
+           cpumask_test_cpu(smp_processor_id(), prof_cpu_mask))
                profile_hit(type, (void *)profile_pc(regs));
 }
 
@@ -442,7 +450,7 @@ void profile_tick(int type)
 static int prof_cpu_mask_read_proc(char *page, char **start, off_t off,
                        int count, int *eof, void *data)
 {
-       int len = cpumask_scnprintf(page, count, (cpumask_t *)data);
+       int len = cpumask_scnprintf(page, count, data);
        if (count - len < 2)
                return -EINVAL;
        len += sprintf(page + len, "\n");
@@ -452,16 +460,20 @@ static int prof_cpu_mask_read_proc(char *page, char **start, off_t off,
 static int prof_cpu_mask_write_proc(struct file *file,
        const char __user *buffer,  unsigned long count, void *data)
 {
-       cpumask_t *mask = (cpumask_t *)data;
+       struct cpumask *mask = data;
        unsigned long full_count = count, err;
-       cpumask_t new_value;
+       cpumask_var_t new_value;
 
-       err = cpumask_parse_user(buffer, count, &new_value);
-       if (err)
-               return err;
+       if (!alloc_cpumask_var(&new_value, GFP_KERNEL))
+               return -ENOMEM;
 
-       *mask = new_value;
-       return full_count;
+       err = cpumask_parse_user(buffer, count, new_value);
+       if (!err) {
+               cpumask_copy(mask, new_value);
+               err = full_count;
+       }
+       free_cpumask_var(new_value);
+       return err;
 }
 
 void create_prof_cpu_mask(struct proc_dir_entry *root_irq_dir)
@@ -472,7 +484,7 @@ void create_prof_cpu_mask(struct proc_dir_entry *root_irq_dir)
        entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
        if (!entry)
                return;
-       entry->data = (void *)&prof_cpu_mask;
+       entry->data = prof_cpu_mask;
        entry->read_proc = prof_cpu_mask_read_proc;
        entry->write_proc = prof_cpu_mask_write_proc;
 }
index c03ca3e619190c44292aed969c6c58f947e0b35a..490934fc7ac3a3b1fd9b094df0de8b0a5a794249 100644 (file)
@@ -63,14 +63,14 @@ static struct rcu_ctrlblk rcu_ctrlblk = {
        .completed = -300,
        .pending = -300,
        .lock = __SPIN_LOCK_UNLOCKED(&rcu_ctrlblk.lock),
-       .cpumask = CPU_MASK_NONE,
+       .cpumask = CPU_BITS_NONE,
 };
 static struct rcu_ctrlblk rcu_bh_ctrlblk = {
        .cur = -300,
        .completed = -300,
        .pending = -300,
        .lock = __SPIN_LOCK_UNLOCKED(&rcu_bh_ctrlblk.lock),
-       .cpumask = CPU_MASK_NONE,
+       .cpumask = CPU_BITS_NONE,
 };
 
 DEFINE_PER_CPU(struct rcu_data, rcu_data) = { 0L };
@@ -85,7 +85,6 @@ static void force_quiescent_state(struct rcu_data *rdp,
                        struct rcu_ctrlblk *rcp)
 {
        int cpu;
-       cpumask_t cpumask;
        unsigned long flags;
 
        set_need_resched();
@@ -96,10 +95,10 @@ static void force_quiescent_state(struct rcu_data *rdp,
                 * Don't send IPI to itself. With irqs disabled,
                 * rdp->cpu is the current cpu.
                 *
-                * cpu_online_map is updated by the _cpu_down()
+                * cpu_online_mask is updated by the _cpu_down()
                 * using __stop_machine(). Since we're in irqs disabled
                 * section, __stop_machine() is not exectuting, hence
-                * the cpu_online_map is stable.
+                * the cpu_online_mask is stable.
                 *
                 * However,  a cpu might have been offlined _just_ before
                 * we disabled irqs while entering here.
@@ -107,13 +106,14 @@ static void force_quiescent_state(struct rcu_data *rdp,
                 * notification, leading to the offlined cpu's bit
                 * being set in the rcp->cpumask.
                 *
-                * Hence cpumask = (rcp->cpumask & cpu_online_map) to prevent
+                * Hence cpumask = (rcp->cpumask & cpu_online_mask) to prevent
                 * sending smp_reschedule() to an offlined CPU.
                 */
-               cpus_and(cpumask, rcp->cpumask, cpu_online_map);
-               cpu_clear(rdp->cpu, cpumask);
-               for_each_cpu_mask_nr(cpu, cpumask)
-                       smp_send_reschedule(cpu);
+               for_each_cpu_and(cpu,
+                                 to_cpumask(rcp->cpumask), cpu_online_mask) {
+                       if (cpu != rdp->cpu)
+                               smp_send_reschedule(cpu);
+               }
        }
        spin_unlock_irqrestore(&rcp->lock, flags);
 }
@@ -193,7 +193,7 @@ static void print_other_cpu_stall(struct rcu_ctrlblk *rcp)
 
        printk(KERN_ERR "INFO: RCU detected CPU stalls:");
        for_each_possible_cpu(cpu) {
-               if (cpu_isset(cpu, rcp->cpumask))
+               if (cpumask_test_cpu(cpu, to_cpumask(rcp->cpumask)))
                        printk(" %d", cpu);
        }
        printk(" (detected by %d, t=%ld jiffies)\n",
@@ -221,7 +221,8 @@ static void check_cpu_stall(struct rcu_ctrlblk *rcp)
        long delta;
 
        delta = jiffies - rcp->jiffies_stall;
-       if (cpu_isset(smp_processor_id(), rcp->cpumask) && delta >= 0) {
+       if (cpumask_test_cpu(smp_processor_id(), to_cpumask(rcp->cpumask)) &&
+               delta >= 0) {
 
                /* We haven't checked in, so go dump stack. */
                print_cpu_stall(rcp);
@@ -393,7 +394,8 @@ static void rcu_start_batch(struct rcu_ctrlblk *rcp)
                 * unnecessarily.
                 */
                smp_mb();
-               cpumask_andnot(&rcp->cpumask, cpu_online_mask, nohz_cpu_mask);
+               cpumask_andnot(to_cpumask(rcp->cpumask),
+                              cpu_online_mask, nohz_cpu_mask);
 
                rcp->signaled = 0;
        }
@@ -406,8 +408,8 @@ static void rcu_start_batch(struct rcu_ctrlblk *rcp)
  */
 static void cpu_quiet(int cpu, struct rcu_ctrlblk *rcp)
 {
-       cpu_clear(cpu, rcp->cpumask);
-       if (cpus_empty(rcp->cpumask)) {
+       cpumask_clear_cpu(cpu, to_cpumask(rcp->cpumask));
+       if (cpumask_empty(to_cpumask(rcp->cpumask))) {
                /* batch completed ! */
                rcp->completed = rcp->cur;
                rcu_start_batch(rcp);
index 04982659875a0fe67b4483874674ad862e3a6640..f9dc8f3720f67ae977628f76f250d0ed8b05b4d5 100644 (file)
@@ -164,7 +164,8 @@ static char *rcu_try_flip_state_names[] =
        { "idle", "waitack", "waitzero", "waitmb" };
 #endif /* #ifdef CONFIG_RCU_TRACE */
 
-static cpumask_t rcu_cpu_online_map __read_mostly = CPU_MASK_NONE;
+static DECLARE_BITMAP(rcu_cpu_online_map, NR_CPUS) __read_mostly
+       = CPU_BITS_NONE;
 
 /*
  * Enum and per-CPU flag to determine when each CPU has seen
@@ -758,7 +759,7 @@ rcu_try_flip_idle(void)
 
        /* Now ask each CPU for acknowledgement of the flip. */
 
-       for_each_cpu_mask_nr(cpu, rcu_cpu_online_map) {
+       for_each_cpu(cpu, to_cpumask(rcu_cpu_online_map)) {
                per_cpu(rcu_flip_flag, cpu) = rcu_flipped;
                dyntick_save_progress_counter(cpu);
        }
@@ -776,7 +777,7 @@ rcu_try_flip_waitack(void)
        int cpu;
 
        RCU_TRACE_ME(rcupreempt_trace_try_flip_a1);
-       for_each_cpu_mask_nr(cpu, rcu_cpu_online_map)
+       for_each_cpu(cpu, to_cpumask(rcu_cpu_online_map))
                if (rcu_try_flip_waitack_needed(cpu) &&
                    per_cpu(rcu_flip_flag, cpu) != rcu_flip_seen) {
                        RCU_TRACE_ME(rcupreempt_trace_try_flip_ae1);
@@ -808,7 +809,7 @@ rcu_try_flip_waitzero(void)
        /* Check to see if the sum of the "last" counters is zero. */
 
        RCU_TRACE_ME(rcupreempt_trace_try_flip_z1);
-       for_each_cpu_mask_nr(cpu, rcu_cpu_online_map)
+       for_each_cpu(cpu, to_cpumask(rcu_cpu_online_map))
                sum += RCU_DATA_CPU(cpu)->rcu_flipctr[lastidx];
        if (sum != 0) {
                RCU_TRACE_ME(rcupreempt_trace_try_flip_ze1);
@@ -823,7 +824,7 @@ rcu_try_flip_waitzero(void)
        smp_mb();  /*  ^^^^^^^^^^^^ */
 
        /* Call for a memory barrier from each CPU. */
-       for_each_cpu_mask_nr(cpu, rcu_cpu_online_map) {
+       for_each_cpu(cpu, to_cpumask(rcu_cpu_online_map)) {
                per_cpu(rcu_mb_flag, cpu) = rcu_mb_needed;
                dyntick_save_progress_counter(cpu);
        }
@@ -843,7 +844,7 @@ rcu_try_flip_waitmb(void)
        int cpu;
 
        RCU_TRACE_ME(rcupreempt_trace_try_flip_m1);
-       for_each_cpu_mask_nr(cpu, rcu_cpu_online_map)
+       for_each_cpu(cpu, to_cpumask(rcu_cpu_online_map))
                if (rcu_try_flip_waitmb_needed(cpu) &&
                    per_cpu(rcu_mb_flag, cpu) != rcu_mb_done) {
                        RCU_TRACE_ME(rcupreempt_trace_try_flip_me1);
@@ -1032,7 +1033,7 @@ void rcu_offline_cpu(int cpu)
        RCU_DATA_CPU(cpu)->rcu_flipctr[0] = 0;
        RCU_DATA_CPU(cpu)->rcu_flipctr[1] = 0;
 
-       cpu_clear(cpu, rcu_cpu_online_map);
+       cpumask_clear_cpu(cpu, to_cpumask(rcu_cpu_online_map));
 
        spin_unlock_irqrestore(&rcu_ctrlblk.fliplock, flags);
 
@@ -1072,7 +1073,7 @@ void __cpuinit rcu_online_cpu(int cpu)
        struct rcu_data *rdp;
 
        spin_lock_irqsave(&rcu_ctrlblk.fliplock, flags);
-       cpu_set(cpu, rcu_cpu_online_map);
+       cpumask_set_cpu(cpu, to_cpumask(rcu_cpu_online_map));
        spin_unlock_irqrestore(&rcu_ctrlblk.fliplock, flags);
 
        /*
@@ -1430,7 +1431,7 @@ void __init __rcu_init(void)
         * We don't need protection against CPU-Hotplug here
         * since
         * a) If a CPU comes online while we are iterating over the
-        *    cpu_online_map below, we would only end up making a
+        *    cpu_online_mask below, we would only end up making a
         *    duplicate call to rcu_online_cpu() which sets the corresponding
         *    CPU's mask in the rcu_cpu_online_map.
         *
index b31065522104f1a324404ea721489909d9a845f7..3245b40952c61548d835d3f19c9d06cf4d1aa9d1 100644 (file)
@@ -868,49 +868,52 @@ static int rcu_idle_cpu;  /* Force all torture tasks off this CPU */
  */
 static void rcu_torture_shuffle_tasks(void)
 {
-       cpumask_t tmp_mask;
+       cpumask_var_t tmp_mask;
        int i;
 
-       cpus_setall(tmp_mask);
+       if (!alloc_cpumask_var(&tmp_mask, GFP_KERNEL))
+               BUG();
+
+       cpumask_setall(tmp_mask);
        get_online_cpus();
 
        /* No point in shuffling if there is only one online CPU (ex: UP) */
-       if (num_online_cpus() == 1) {
-               put_online_cpus();
-               return;
-       }
+       if (num_online_cpus() == 1)
+               goto out;
 
        if (rcu_idle_cpu != -1)
-               cpu_clear(rcu_idle_cpu, tmp_mask);
+               cpumask_clear_cpu(rcu_idle_cpu, tmp_mask);
 
-       set_cpus_allowed_ptr(current, &tmp_mask);
+       set_cpus_allowed_ptr(current, tmp_mask);
 
        if (reader_tasks) {
                for (i = 0; i < nrealreaders; i++)
                        if (reader_tasks[i])
                                set_cpus_allowed_ptr(reader_tasks[i],
-                                                    &tmp_mask);
+                                                    tmp_mask);
        }
 
        if (fakewriter_tasks) {
                for (i = 0; i < nfakewriters; i++)
                        if (fakewriter_tasks[i])
                                set_cpus_allowed_ptr(fakewriter_tasks[i],
-                                                    &tmp_mask);
+                                                    tmp_mask);
        }
 
        if (writer_task)
-               set_cpus_allowed_ptr(writer_task, &tmp_mask);
+               set_cpus_allowed_ptr(writer_task, tmp_mask);
 
        if (stats_task)
-               set_cpus_allowed_ptr(stats_task, &tmp_mask);
+               set_cpus_allowed_ptr(stats_task, tmp_mask);
 
        if (rcu_idle_cpu == -1)
                rcu_idle_cpu = num_online_cpus() - 1;
        else
                rcu_idle_cpu--;
 
+out:
        put_online_cpus();
+       free_cpumask_var(tmp_mask);
 }
 
 /* Shuffle tasks across CPUs, with the intent of allowing each CPU in the
index 27ba1d642f0f0c4c370e81a61b067874310532d0..545c6fccd1dc7ceba0e33e33250fc38369a41fab 100644 (file)
@@ -3715,7 +3715,7 @@ redo:
                 * don't kick the migration_thread, if the curr
                 * task on busiest cpu can't be moved to this_cpu
                 */
-               if (!cpu_isset(this_cpu, busiest->curr->cpus_allowed)) {
+               if (!cpumask_test_cpu(this_cpu, &busiest->curr->cpus_allowed)) {
                        double_unlock_balance(this_rq, busiest);
                        all_pinned = 1;
                        return ld_moved;
@@ -4150,13 +4150,17 @@ unsigned long long task_delta_exec(struct task_struct *p)
  * Account user cpu time to a process.
  * @p: the process that the cpu time gets accounted to
  * @cputime: the cpu time spent in user space since the last update
+ * @cputime_scaled: cputime scaled by cpu frequency
  */
-void account_user_time(struct task_struct *p, cputime_t cputime)
+void account_user_time(struct task_struct *p, cputime_t cputime,
+                      cputime_t cputime_scaled)
 {
        struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
        cputime64_t tmp;
 
+       /* Add user time to process. */
        p->utime = cputime_add(p->utime, cputime);
+       p->utimescaled = cputime_add(p->utimescaled, cputime_scaled);
        account_group_user_time(p, cputime);
 
        /* Add user time to cpustat. */
@@ -4173,51 +4177,48 @@ void account_user_time(struct task_struct *p, cputime_t cputime)
  * Account guest cpu time to a process.
  * @p: the process that the cpu time gets accounted to
  * @cputime: the cpu time spent in virtual machine since the last update
+ * @cputime_scaled: cputime scaled by cpu frequency
  */
-static void account_guest_time(struct task_struct *p, cputime_t cputime)
+static void account_guest_time(struct task_struct *p, cputime_t cputime,
+                              cputime_t cputime_scaled)
 {
        cputime64_t tmp;
        struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
 
        tmp = cputime_to_cputime64(cputime);
 
+       /* Add guest time to process. */
        p->utime = cputime_add(p->utime, cputime);
+       p->utimescaled = cputime_add(p->utimescaled, cputime_scaled);
        account_group_user_time(p, cputime);
        p->gtime = cputime_add(p->gtime, cputime);
 
+       /* Add guest time to cpustat. */
        cpustat->user = cputime64_add(cpustat->user, tmp);
        cpustat->guest = cputime64_add(cpustat->guest, tmp);
 }
 
-/*
- * Account scaled user cpu time to a process.
- * @p: the process that the cpu time gets accounted to
- * @cputime: the cpu time spent in user space since the last update
- */
-void account_user_time_scaled(struct task_struct *p, cputime_t cputime)
-{
-       p->utimescaled = cputime_add(p->utimescaled, cputime);
-}
-
 /*
  * Account system cpu time to a process.
  * @p: the process that the cpu time gets accounted to
  * @hardirq_offset: the offset to subtract from hardirq_count()
  * @cputime: the cpu time spent in kernel space since the last update
+ * @cputime_scaled: cputime scaled by cpu frequency
  */
 void account_system_time(struct task_struct *p, int hardirq_offset,
-                        cputime_t cputime)
+                        cputime_t cputime, cputime_t cputime_scaled)
 {
        struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
-       struct rq *rq = this_rq();
        cputime64_t tmp;
 
        if ((p->flags & PF_VCPU) && (irq_count() - hardirq_offset == 0)) {
-               account_guest_time(p, cputime);
+               account_guest_time(p, cputime, cputime_scaled);
                return;
        }
 
+       /* Add system time to process. */
        p->stime = cputime_add(p->stime, cputime);
+       p->stimescaled = cputime_add(p->stimescaled, cputime_scaled);
        account_group_system_time(p, cputime);
 
        /* Add system time to cpustat. */
@@ -4226,48 +4227,84 @@ void account_system_time(struct task_struct *p, int hardirq_offset,
                cpustat->irq = cputime64_add(cpustat->irq, tmp);
        else if (softirq_count())
                cpustat->softirq = cputime64_add(cpustat->softirq, tmp);
-       else if (p != rq->idle)
-               cpustat->system = cputime64_add(cpustat->system, tmp);
-       else if (atomic_read(&rq->nr_iowait) > 0)
-               cpustat->iowait = cputime64_add(cpustat->iowait, tmp);
        else
-               cpustat->idle = cputime64_add(cpustat->idle, tmp);
+               cpustat->system = cputime64_add(cpustat->system, tmp);
+
        /* Account for system time used */
        acct_update_integrals(p);
 }
 
 /*
- * Account scaled system cpu time to a process.
- * @p: the process that the cpu time gets accounted to
- * @hardirq_offset: the offset to subtract from hardirq_count()
- * @cputime: the cpu time spent in kernel space since the last update
+ * Account for involuntary wait time.
+ * @steal: the cpu time spent in involuntary wait
  */
-void account_system_time_scaled(struct task_struct *p, cputime_t cputime)
+void account_steal_time(cputime_t cputime)
 {
-       p->stimescaled = cputime_add(p->stimescaled, cputime);
+       struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
+       cputime64_t cputime64 = cputime_to_cputime64(cputime);
+
+       cpustat->steal = cputime64_add(cpustat->steal, cputime64);
 }
 
 /*
- * Account for involuntary wait time.
- * @p: the process from which the cpu time has been stolen
- * @steal: the cpu time spent in involuntary wait
+ * Account for idle time.
+ * @cputime: the cpu time spent in idle wait
  */
-void account_steal_time(struct task_struct *p, cputime_t steal)
+void account_idle_time(cputime_t cputime)
 {
        struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
-       cputime64_t tmp = cputime_to_cputime64(steal);
+       cputime64_t cputime64 = cputime_to_cputime64(cputime);
        struct rq *rq = this_rq();
 
-       if (p == rq->idle) {
-               p->stime = cputime_add(p->stime, steal);
-               if (atomic_read(&rq->nr_iowait) > 0)
-                       cpustat->iowait = cputime64_add(cpustat->iowait, tmp);
-               else
-                       cpustat->idle = cputime64_add(cpustat->idle, tmp);
-       } else
-               cpustat->steal = cputime64_add(cpustat->steal, tmp);
+       if (atomic_read(&rq->nr_iowait) > 0)
+               cpustat->iowait = cputime64_add(cpustat->iowait, cputime64);
+       else
+               cpustat->idle = cputime64_add(cpustat->idle, cputime64);
+}
+
+#ifndef CONFIG_VIRT_CPU_ACCOUNTING
+
+/*
+ * Account a single tick of cpu time.
+ * @p: the process that the cpu time gets accounted to
+ * @user_tick: indicates if the tick is a user or a system tick
+ */
+void account_process_tick(struct task_struct *p, int user_tick)
+{
+       cputime_t one_jiffy = jiffies_to_cputime(1);
+       cputime_t one_jiffy_scaled = cputime_to_scaled(one_jiffy);
+       struct rq *rq = this_rq();
+
+       if (user_tick)
+               account_user_time(p, one_jiffy, one_jiffy_scaled);
+       else if (p != rq->idle)
+               account_system_time(p, HARDIRQ_OFFSET, one_jiffy,
+                                   one_jiffy_scaled);
+       else
+               account_idle_time(one_jiffy);
+}
+
+/*
+ * Account multiple ticks of steal time.
+ * @p: the process from which the cpu time has been stolen
+ * @ticks: number of stolen ticks
+ */
+void account_steal_ticks(unsigned long ticks)
+{
+       account_steal_time(jiffies_to_cputime(ticks));
 }
 
+/*
+ * Account multiple ticks of idle time.
+ * @ticks: number of stolen ticks
+ */
+void account_idle_ticks(unsigned long ticks)
+{
+       account_idle_time(jiffies_to_cputime(ticks));
+}
+
+#endif
+
 /*
  * Use precise platform statistics if available:
  */
@@ -6220,9 +6257,7 @@ static int __migrate_task_irq(struct task_struct *p, int src_cpu, int dest_cpu)
 static void move_task_off_dead_cpu(int dead_cpu, struct task_struct *p)
 {
        int dest_cpu;
-       /* FIXME: Use cpumask_of_node here. */
-       cpumask_t _nodemask = node_to_cpumask(cpu_to_node(dead_cpu));
-       const struct cpumask *nodemask = &_nodemask;
+       const struct cpumask *nodemask = cpumask_of_node(cpu_to_node(dead_cpu));
 
 again:
        /* Look for allowed, online CPU in same node. */
@@ -7133,21 +7168,18 @@ static int find_next_best_node(int node, nodemask_t *used_nodes)
 static void sched_domain_node_span(int node, struct cpumask *span)
 {
        nodemask_t used_nodes;
-       /* FIXME: use cpumask_of_node() */
-       node_to_cpumask_ptr(nodemask, node);
        int i;
 
-       cpus_clear(*span);
+       cpumask_clear(span);
        nodes_clear(used_nodes);
 
-       cpus_or(*span, *span, *nodemask);
+       cpumask_or(span, span, cpumask_of_node(node));
        node_set(node, used_nodes);
 
        for (i = 1; i < SD_NODES_PER_DOMAIN; i++) {
                int next_node = find_next_best_node(node, &used_nodes);
 
-               node_to_cpumask_ptr_next(nodemask, next_node);
-               cpus_or(*span, *span, *nodemask);
+               cpumask_or(span, span, cpumask_of_node(next_node));
        }
 }
 #endif /* CONFIG_NUMA */
@@ -7227,9 +7259,7 @@ cpu_to_phys_group(int cpu, const struct cpumask *cpu_map,
 {
        int group;
 #ifdef CONFIG_SCHED_MC
-       /* FIXME: Use cpu_coregroup_mask. */
-       *mask = cpu_coregroup_map(cpu);
-       cpus_and(*mask, *mask, *cpu_map);
+       cpumask_and(mask, cpu_coregroup_mask(cpu), cpu_map);
        group = cpumask_first(mask);
 #elif defined(CONFIG_SCHED_SMT)
        cpumask_and(mask, &per_cpu(cpu_sibling_map, cpu), cpu_map);
@@ -7259,10 +7289,8 @@ static int cpu_to_allnodes_group(int cpu, const struct cpumask *cpu_map,
                                 struct cpumask *nodemask)
 {
        int group;
-       /* FIXME: use cpumask_of_node */
-       node_to_cpumask_ptr(pnodemask, cpu_to_node(cpu));
 
-       cpumask_and(nodemask, pnodemask, cpu_map);
+       cpumask_and(nodemask, cpumask_of_node(cpu_to_node(cpu)), cpu_map);
        group = cpumask_first(nodemask);
 
        if (sg)
@@ -7313,10 +7341,8 @@ static void free_sched_groups(const struct cpumask *cpu_map,
 
                for (i = 0; i < nr_node_ids; i++) {
                        struct sched_group *oldsg, *sg = sched_group_nodes[i];
-                       /* FIXME: Use cpumask_of_node */
-                       node_to_cpumask_ptr(pnodemask, i);
 
-                       cpus_and(*nodemask, *pnodemask, *cpu_map);
+                       cpumask_and(nodemask, cpumask_of_node(i), cpu_map);
                        if (cpumask_empty(nodemask))
                                continue;
 
@@ -7525,9 +7551,7 @@ static int __build_sched_domains(const struct cpumask *cpu_map,
        for_each_cpu(i, cpu_map) {
                struct sched_domain *sd = NULL, *p;
 
-               /* FIXME: use cpumask_of_node */
-               *nodemask = node_to_cpumask(cpu_to_node(i));
-               cpus_and(*nodemask, *nodemask, *cpu_map);
+               cpumask_and(nodemask, cpumask_of_node(cpu_to_node(i)), cpu_map);
 
 #ifdef CONFIG_NUMA
                if (cpumask_weight(cpu_map) >
@@ -7568,9 +7592,8 @@ static int __build_sched_domains(const struct cpumask *cpu_map,
                sd = &per_cpu(core_domains, i).sd;
                SD_INIT(sd, MC);
                set_domain_attribute(sd, attr);
-               *sched_domain_span(sd) = cpu_coregroup_map(i);
-               cpumask_and(sched_domain_span(sd),
-                           sched_domain_span(sd), cpu_map);
+               cpumask_and(sched_domain_span(sd), cpu_map,
+                                                  cpu_coregroup_mask(i));
                sd->parent = p;
                p->child = sd;
                cpu_to_core_group(i, cpu_map, &sd->groups, tmpmask);
@@ -7606,9 +7629,7 @@ static int __build_sched_domains(const struct cpumask *cpu_map,
 #ifdef CONFIG_SCHED_MC
        /* Set up multi-core groups */
        for_each_cpu(i, cpu_map) {
-               /* FIXME: Use cpu_coregroup_mask */
-               *this_core_map = cpu_coregroup_map(i);
-               cpus_and(*this_core_map, *this_core_map, *cpu_map);
+               cpumask_and(this_core_map, cpu_coregroup_mask(i), cpu_map);
                if (i != cpumask_first(this_core_map))
                        continue;
 
@@ -7620,9 +7641,7 @@ static int __build_sched_domains(const struct cpumask *cpu_map,
 
        /* Set up physical groups */
        for (i = 0; i < nr_node_ids; i++) {
-               /* FIXME: Use cpumask_of_node */
-               *nodemask = node_to_cpumask(i);
-               cpus_and(*nodemask, *nodemask, *cpu_map);
+               cpumask_and(nodemask, cpumask_of_node(i), cpu_map);
                if (cpumask_empty(nodemask))
                        continue;
 
@@ -7644,11 +7663,8 @@ static int __build_sched_domains(const struct cpumask *cpu_map,
                struct sched_group *sg, *prev;
                int j;
 
-               /* FIXME: Use cpumask_of_node */
-               *nodemask = node_to_cpumask(i);
                cpumask_clear(covered);
-
-               cpus_and(*nodemask, *nodemask, *cpu_map);
+               cpumask_and(nodemask, cpumask_of_node(i), cpu_map);
                if (cpumask_empty(nodemask)) {
                        sched_group_nodes[i] = NULL;
                        continue;
@@ -7679,8 +7695,6 @@ static int __build_sched_domains(const struct cpumask *cpu_map,
 
                for (j = 0; j < nr_node_ids; j++) {
                        int n = (i + j) % nr_node_ids;
-                       /* FIXME: Use cpumask_of_node */
-                       node_to_cpumask_ptr(pnodemask, n);
 
                        cpumask_complement(notcovered, covered);
                        cpumask_and(tmpmask, notcovered, cpu_map);
@@ -7688,7 +7702,7 @@ static int __build_sched_domains(const struct cpumask *cpu_map,
                        if (cpumask_empty(tmpmask))
                                break;
 
-                       cpumask_and(tmpmask, tmpmask, pnodemask);
+                       cpumask_and(tmpmask, tmpmask, cpumask_of_node(n));
                        if (cpumask_empty(tmpmask))
                                continue;
 
index 833b6d44483c57bb4473b9eddf448a2366302b6a..954e1a81b7967567b617b918b254deaa12a848a4 100644 (file)
@@ -1383,7 +1383,8 @@ static inline void init_sched_rt_class(void)
        unsigned int i;
 
        for_each_possible_cpu(i)
-               alloc_cpumask_var(&per_cpu(local_cpu_mask, i), GFP_KERNEL);
+               alloc_cpumask_var_node(&per_cpu(local_cpu_mask, i),
+                                       GFP_KERNEL, cpu_to_node(i));
 }
 #endif /* CONFIG_SMP */
 
index 75c8dde58c55fcdd2f0ae71f75ceb05213e0985e..5cfa0e5e3e88d0a4527205de6e438b0e17dbf8ec 100644 (file)
@@ -24,8 +24,8 @@ struct call_function_data {
        struct call_single_data csd;
        spinlock_t lock;
        unsigned int refs;
-       cpumask_t cpumask;
        struct rcu_head rcu_head;
+       unsigned long cpumask_bits[];
 };
 
 struct call_single_queue {
@@ -110,13 +110,13 @@ void generic_smp_call_function_interrupt(void)
        list_for_each_entry_rcu(data, &call_function_queue, csd.list) {
                int refs;
 
-               if (!cpu_isset(cpu, data->cpumask))
+               if (!cpumask_test_cpu(cpu, to_cpumask(data->cpumask_bits)))
                        continue;
 
                data->csd.func(data->csd.info);
 
                spin_lock(&data->lock);
-               cpu_clear(cpu, data->cpumask);
+               cpumask_clear_cpu(cpu, to_cpumask(data->cpumask_bits));
                WARN_ON(data->refs == 0);
                data->refs--;
                refs = data->refs;
@@ -223,7 +223,7 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
                local_irq_save(flags);
                func(info);
                local_irq_restore(flags);
-       } else if ((unsigned)cpu < NR_CPUS && cpu_online(cpu)) {
+       } else if ((unsigned)cpu < nr_cpu_ids && cpu_online(cpu)) {
                struct call_single_data *data = NULL;
 
                if (!wait) {
@@ -266,51 +266,19 @@ void __smp_call_function_single(int cpu, struct call_single_data *data)
        generic_exec_single(cpu, data);
 }
 
-/* Dummy function */
-static void quiesce_dummy(void *unused)
-{
-}
-
-/*
- * Ensure stack based data used in call function mask is safe to free.
- *
- * This is needed by smp_call_function_mask when using on-stack data, because
- * a single call function queue is shared by all CPUs, and any CPU may pick up
- * the data item on the queue at any time before it is deleted. So we need to
- * ensure that all CPUs have transitioned through a quiescent state after
- * this call.
- *
- * This is a very slow function, implemented by sending synchronous IPIs to
- * all possible CPUs. For this reason, we have to alloc data rather than use
- * stack based data even in the case of synchronous calls. The stack based
- * data is then just used for deadlock/oom fallback which will be very rare.
- *
- * If a faster scheme can be made, we could go back to preferring stack based
- * data -- the data allocation/free is non-zero cost.
- */
-static void smp_call_function_mask_quiesce_stack(cpumask_t mask)
-{
-       struct call_single_data data;
-       int cpu;
-
-       data.func = quiesce_dummy;
-       data.info = NULL;
-
-       for_each_cpu_mask(cpu, mask) {
-               data.flags = CSD_FLAG_WAIT;
-               generic_exec_single(cpu, &data);
-       }
-}
+/* FIXME: Shim for archs using old arch_send_call_function_ipi API. */
+#ifndef arch_send_call_function_ipi_mask
+#define arch_send_call_function_ipi_mask(maskp) \
+       arch_send_call_function_ipi(*(maskp))
+#endif
 
 /**
- * smp_call_function_mask(): Run a function on a set of other CPUs.
- * @mask: The set of cpus to run on.
+ * smp_call_function_many(): Run a function on a set of other CPUs.
+ * @mask: The set of cpus to run on (only runs on online subset).
  * @func: The function to run. This must be fast and non-blocking.
  * @info: An arbitrary pointer to pass to the function.
  * @wait: If true, wait (atomically) until function has completed on other CPUs.
  *
- * Returns 0 on success, else a negative status code.
- *
  * If @wait is true, then returns once @func has returned. Note that @wait
  * will be implicitly turned on in case of allocation failures, since
  * we fall back to on-stack allocation.
@@ -319,53 +287,57 @@ static void smp_call_function_mask_quiesce_stack(cpumask_t mask)
  * hardware interrupt handler or from a bottom half handler. Preemption
  * must be disabled when calling this function.
  */
-int smp_call_function_mask(cpumask_t mask, void (*func)(void *), void *info,
-                          int wait)
+void smp_call_function_many(const struct cpumask *mask,
+                           void (*func)(void *), void *info,
+                           bool wait)
 {
-       struct call_function_data d;
-       struct call_function_data *data = NULL;
-       cpumask_t allbutself;
+       struct call_function_data *data;
        unsigned long flags;
-       int cpu, num_cpus;
-       int slowpath = 0;
+       int cpu, next_cpu;
 
        /* Can deadlock when called with interrupts disabled */
        WARN_ON(irqs_disabled());
 
-       cpu = smp_processor_id();
-       allbutself = cpu_online_map;
-       cpu_clear(cpu, allbutself);
-       cpus_and(mask, mask, allbutself);
-       num_cpus = cpus_weight(mask);
-
-       /*
-        * If zero CPUs, return. If just a single CPU, turn this request
-        * into a targetted single call instead since it's faster.
-        */
-       if (!num_cpus)
-               return 0;
-       else if (num_cpus == 1) {
-               cpu = first_cpu(mask);
-               return smp_call_function_single(cpu, func, info, wait);
+       /* So, what's a CPU they want?  Ignoring this one. */
+       cpu = cpumask_first_and(mask, cpu_online_mask);
+       if (cpu == smp_processor_id())
+               cpu = cpumask_next_and(cpu, mask, cpu_online_mask);
+       /* No online cpus?  We're done. */
+       if (cpu >= nr_cpu_ids)
+               return;
+
+       /* Do we have another CPU which isn't us? */
+       next_cpu = cpumask_next_and(cpu, mask, cpu_online_mask);
+       if (next_cpu == smp_processor_id())
+               next_cpu = cpumask_next_and(next_cpu, mask, cpu_online_mask);
+
+       /* Fastpath: do that cpu by itself. */
+       if (next_cpu >= nr_cpu_ids) {
+               smp_call_function_single(cpu, func, info, wait);
+               return;
        }
 
-       data = kmalloc(sizeof(*data), GFP_ATOMIC);
-       if (data) {
-               data->csd.flags = CSD_FLAG_ALLOC;
-               if (wait)
-                       data->csd.flags |= CSD_FLAG_WAIT;
-       } else {
-               data = &d;
-               data->csd.flags = CSD_FLAG_WAIT;
-               wait = 1;
-               slowpath = 1;
+       data = kmalloc(sizeof(*data) + cpumask_size(), GFP_ATOMIC);
+       if (unlikely(!data)) {
+               /* Slow path. */
+               for_each_online_cpu(cpu) {
+                       if (cpu == smp_processor_id())
+                               continue;
+                       if (cpumask_test_cpu(cpu, mask))
+                               smp_call_function_single(cpu, func, info, wait);
+               }
+               return;
        }
 
        spin_lock_init(&data->lock);
+       data->csd.flags = CSD_FLAG_ALLOC;
+       if (wait)
+               data->csd.flags |= CSD_FLAG_WAIT;
        data->csd.func = func;
        data->csd.info = info;
-       data->refs = num_cpus;
-       data->cpumask = mask;
+       cpumask_and(to_cpumask(data->cpumask_bits), mask, cpu_online_mask);
+       cpumask_clear_cpu(smp_processor_id(), to_cpumask(data->cpumask_bits));
+       data->refs = cpumask_weight(to_cpumask(data->cpumask_bits));
 
        spin_lock_irqsave(&call_function_lock, flags);
        list_add_tail_rcu(&data->csd.list, &call_function_queue);
@@ -377,18 +349,13 @@ int smp_call_function_mask(cpumask_t mask, void (*func)(void *), void *info,
        smp_mb();
 
        /* Send a message to all CPUs in the map */
-       arch_send_call_function_ipi(mask);
+       arch_send_call_function_ipi_mask(to_cpumask(data->cpumask_bits));
 
        /* optionally wait for the CPUs to complete */
-       if (wait) {
+       if (wait)
                csd_flag_wait(&data->csd);
-               if (unlikely(slowpath))
-                       smp_call_function_mask_quiesce_stack(mask);
-       }
-
-       return 0;
 }
-EXPORT_SYMBOL(smp_call_function_mask);
+EXPORT_SYMBOL(smp_call_function_many);
 
 /**
  * smp_call_function(): Run a function on all other CPUs.
@@ -396,7 +363,7 @@ EXPORT_SYMBOL(smp_call_function_mask);
  * @info: An arbitrary pointer to pass to the function.
  * @wait: If true, wait (atomically) until function has completed on other CPUs.
  *
- * Returns 0 on success, else a negative status code.
+ * Returns 0.
  *
  * If @wait is true, then returns once @func has returned; otherwise
  * it returns just before the target cpu calls @func. In case of allocation
@@ -407,12 +374,10 @@ EXPORT_SYMBOL(smp_call_function_mask);
  */
 int smp_call_function(void (*func)(void *), void *info, int wait)
 {
-       int ret;
-
        preempt_disable();
-       ret = smp_call_function_mask(cpu_online_map, func, info, wait);
+       smp_call_function_many(cpu_online_mask, func, info, wait);
        preempt_enable();
-       return ret;
+       return 0;
 }
 EXPORT_SYMBOL(smp_call_function);
 
index 670c1eca47ec9964e2a8bef73dc3aa4840c427b4..bdbe9de9cd8d7091771201f232747bf30a83e467 100644 (file)
@@ -733,7 +733,7 @@ static int __cpuinit cpu_callback(struct notifier_block *nfb,
                        break;
                /* Unbind so it can run.  Fall thru. */
                kthread_bind(per_cpu(ksoftirqd, hotcpu),
-                            any_online_cpu(cpu_online_map));
+                            cpumask_any(cpu_online_mask));
        case CPU_DEAD:
        case CPU_DEAD_FROZEN: {
                struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
index 1ab790c67b174592401712b093bdc56a8aa3d537..d9188c66278ad5ad5dcaa2b95177bcdec3130655 100644 (file)
@@ -303,17 +303,15 @@ cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
                break;
        case CPU_ONLINE:
        case CPU_ONLINE_FROZEN:
-               check_cpu = any_online_cpu(cpu_online_map);
+               check_cpu = cpumask_any(cpu_online_mask);
                wake_up_process(per_cpu(watchdog_task, hotcpu));
                break;
 #ifdef CONFIG_HOTPLUG_CPU
        case CPU_DOWN_PREPARE:
        case CPU_DOWN_PREPARE_FROZEN:
                if (hotcpu == check_cpu) {
-                       cpumask_t temp_cpu_online_map = cpu_online_map;
-
-                       cpu_clear(hotcpu, temp_cpu_online_map);
-                       check_cpu = any_online_cpu(temp_cpu_online_map);
+                       /* Pick any other online cpu. */
+                       check_cpu = cpumask_any_but(cpu_online_mask, hotcpu);
                }
                break;
 
@@ -323,7 +321,7 @@ cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
                        break;
                /* Unbind so it can run.  Fall thru. */
                kthread_bind(per_cpu(watchdog_task, hotcpu),
-                            any_online_cpu(cpu_online_map));
+                            cpumask_any(cpu_online_mask));
        case CPU_DEAD:
        case CPU_DEAD_FROZEN:
                p = per_cpu(watchdog_task, hotcpu);
index 24e8ceacc388cd14e9ff4ae87fcc47d6f8d96b2b..286c41722e8cb68e76dc637d20298b67847771e0 100644 (file)
@@ -69,10 +69,10 @@ static void stop_cpu(struct work_struct *unused)
        int err;
 
        if (!active_cpus) {
-               if (cpu == first_cpu(cpu_online_map))
+               if (cpu == cpumask_first(cpu_online_mask))
                        smdata = &active;
        } else {
-               if (cpu_isset(cpu, *active_cpus))
+               if (cpumask_test_cpu(cpu, active_cpus))
                        smdata = &active;
        }
        /* Simple state machine */
@@ -109,7 +109,7 @@ static int chill(void *unused)
        return 0;
 }
 
-int __stop_machine(int (*fn)(void *), void *data, const cpumask_t *cpus)
+int __stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus)
 {
        struct work_struct *sm_work;
        int i, ret;
@@ -142,7 +142,7 @@ int __stop_machine(int (*fn)(void *), void *data, const cpumask_t *cpus)
        return ret;
 }
 
-int stop_machine(int (*fn)(void *), void *data, const cpumask_t *cpus)
+int stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus)
 {
        int ret;
 
index 6d7dc4ec4aa5735dbfd02ae68593c98ae5bf315d..888adbcca30c17c2db3922351a9ef8c9939a2d64 100644 (file)
@@ -290,18 +290,17 @@ ret:
        return;
 }
 
-static int add_del_listener(pid_t pid, cpumask_t *maskp, int isadd)
+static int add_del_listener(pid_t pid, const struct cpumask *mask, int isadd)
 {
        struct listener_list *listeners;
        struct listener *s, *tmp;
        unsigned int cpu;
-       cpumask_t mask = *maskp;
 
-       if (!cpus_subset(mask, cpu_possible_map))
+       if (!cpumask_subset(mask, cpu_possible_mask))
                return -EINVAL;
 
        if (isadd == REGISTER) {
-               for_each_cpu_mask_nr(cpu, mask) {
+               for_each_cpu(cpu, mask) {
                        s = kmalloc_node(sizeof(struct listener), GFP_KERNEL,
                                         cpu_to_node(cpu));
                        if (!s)
@@ -320,7 +319,7 @@ static int add_del_listener(pid_t pid, cpumask_t *maskp, int isadd)
 
        /* Deregister or cleanup */
 cleanup:
-       for_each_cpu_mask_nr(cpu, mask) {
+       for_each_cpu(cpu, mask) {
                listeners = &per_cpu(listener_array, cpu);
                down_write(&listeners->sem);
                list_for_each_entry_safe(s, tmp, &listeners->list, list) {
@@ -335,7 +334,7 @@ cleanup:
        return 0;
 }
 
-static int parse(struct nlattr *na, cpumask_t *mask)
+static int parse(struct nlattr *na, struct cpumask *mask)
 {
        char *data;
        int len;
@@ -428,23 +427,33 @@ err:
 
 static int taskstats_user_cmd(struct sk_buff *skb, struct genl_info *info)
 {
-       int rc = 0;
+       int rc;
        struct sk_buff *rep_skb;
        struct taskstats *stats;
        size_t size;
-       cpumask_t mask;
+       cpumask_var_t mask;
+
+       if (!alloc_cpumask_var(&mask, GFP_KERNEL))
+               return -ENOMEM;
 
-       rc = parse(info->attrs[TASKSTATS_CMD_ATTR_REGISTER_CPUMASK], &mask);
+       rc = parse(info->attrs[TASKSTATS_CMD_ATTR_REGISTER_CPUMASK], mask);
        if (rc < 0)
-               return rc;
-       if (rc == 0)
-               return add_del_listener(info->snd_pid, &mask, REGISTER);
+               goto free_return_rc;
+       if (rc == 0) {
+               rc = add_del_listener(info->snd_pid, mask, REGISTER);
+               goto free_return_rc;
+       }
 
-       rc = parse(info->attrs[TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK], &mask);
+       rc = parse(info->attrs[TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK], mask);
        if (rc < 0)
+               goto free_return_rc;
+       if (rc == 0) {
+               rc = add_del_listener(info->snd_pid, mask, DEREGISTER);
+free_return_rc:
+               free_cpumask_var(mask);
                return rc;
-       if (rc == 0)
-               return add_del_listener(info->snd_pid, &mask, DEREGISTER);
+       }
+       free_cpumask_var(mask);
 
        /*
         * Size includes space for nested attributes
index 9ed2eec97526546e26c4fb640702a8907b3530a9..ca89e1593f0833840fbbcaf58ba5bb5b075362e2 100644 (file)
@@ -145,10 +145,11 @@ static void clocksource_watchdog(unsigned long data)
                 * Cycle through CPUs to check if the CPUs stay
                 * synchronized to each other.
                 */
-               int next_cpu = next_cpu_nr(raw_smp_processor_id(), cpu_online_map);
+               int next_cpu = cpumask_next(raw_smp_processor_id(),
+                                           cpu_online_mask);
 
                if (next_cpu >= nr_cpu_ids)
-                       next_cpu = first_cpu(cpu_online_map);
+                       next_cpu = cpumask_first(cpu_online_mask);
                watchdog_timer.expires += WATCHDOG_INTERVAL;
                add_timer_on(&watchdog_timer, next_cpu);
        }
@@ -173,7 +174,7 @@ static void clocksource_check_watchdog(struct clocksource *cs)
                        watchdog_last = watchdog->read();
                        watchdog_timer.expires = jiffies + WATCHDOG_INTERVAL;
                        add_timer_on(&watchdog_timer,
-                                    first_cpu(cpu_online_map));
+                                    cpumask_first(cpu_online_mask));
                }
        } else {
                if (cs->flags & CLOCK_SOURCE_IS_CONTINUOUS)
@@ -195,7 +196,7 @@ static void clocksource_check_watchdog(struct clocksource *cs)
                                watchdog_timer.expires =
                                        jiffies + WATCHDOG_INTERVAL;
                                add_timer_on(&watchdog_timer,
-                                            first_cpu(cpu_online_map));
+                                            cpumask_first(cpu_online_mask));
                        }
                }
        }
index 9590af2327be382cc030ef79acdf6d1d26bd9599..118a3b3b3f9a3de4ffa48a2d30a73f6d8a56d3ef 100644 (file)
@@ -28,7 +28,9 @@
  */
 
 struct tick_device tick_broadcast_device;
-static cpumask_t tick_broadcast_mask;
+/* FIXME: Use cpumask_var_t. */
+static DECLARE_BITMAP(tick_broadcast_mask, NR_CPUS);
+static DECLARE_BITMAP(tmpmask, NR_CPUS);
 static DEFINE_SPINLOCK(tick_broadcast_lock);
 static int tick_broadcast_force;
 
@@ -46,9 +48,9 @@ struct tick_device *tick_get_broadcast_device(void)
        return &tick_broadcast_device;
 }
 
-cpumask_t *tick_get_broadcast_mask(void)
+struct cpumask *tick_get_broadcast_mask(void)
 {
-       return &tick_broadcast_mask;
+       return to_cpumask(tick_broadcast_mask);
 }
 
 /*
@@ -72,7 +74,7 @@ int tick_check_broadcast_device(struct clock_event_device *dev)
 
        clockevents_exchange_device(NULL, dev);
        tick_broadcast_device.evtdev = dev;
-       if (!cpus_empty(tick_broadcast_mask))
+       if (!cpumask_empty(tick_get_broadcast_mask()))
                tick_broadcast_start_periodic(dev);
        return 1;
 }
@@ -104,7 +106,7 @@ int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu)
         */
        if (!tick_device_is_functional(dev)) {
                dev->event_handler = tick_handle_periodic;
-               cpu_set(cpu, tick_broadcast_mask);
+               cpumask_set_cpu(cpu, tick_get_broadcast_mask());
                tick_broadcast_start_periodic(tick_broadcast_device.evtdev);
                ret = 1;
        } else {
@@ -116,7 +118,7 @@ int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu)
                if (!(dev->features & CLOCK_EVT_FEAT_C3STOP)) {
                        int cpu = smp_processor_id();
 
-                       cpu_clear(cpu, tick_broadcast_mask);
+                       cpumask_clear_cpu(cpu, tick_get_broadcast_mask());
                        tick_broadcast_clear_oneshot(cpu);
                }
        }
@@ -125,9 +127,9 @@ int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu)
 }
 
 /*
- * Broadcast the event to the cpus, which are set in the mask
+ * Broadcast the event to the cpus, which are set in the mask (mangled).
  */
-static void tick_do_broadcast(cpumask_t mask)
+static void tick_do_broadcast(struct cpumask *mask)
 {
        int cpu = smp_processor_id();
        struct tick_device *td;
@@ -135,22 +137,21 @@ static void tick_do_broadcast(cpumask_t mask)
        /*
         * Check, if the current cpu is in the mask
         */
-       if (cpu_isset(cpu, mask)) {
-               cpu_clear(cpu, mask);
+       if (cpumask_test_cpu(cpu, mask)) {
+               cpumask_clear_cpu(cpu, mask);
                td = &per_cpu(tick_cpu_device, cpu);
                td->evtdev->event_handler(td->evtdev);
        }
 
-       if (!cpus_empty(mask)) {
+       if (!cpumask_empty(mask)) {
                /*
                 * It might be necessary to actually check whether the devices
                 * have different broadcast functions. For now, just use the
                 * one of the first device. This works as long as we have this
                 * misfeature only on x86 (lapic)
                 */
-               cpu = first_cpu(mask);
-               td = &per_cpu(tick_cpu_device, cpu);
-               td->evtdev->broadcast(&mask);
+               td = &per_cpu(tick_cpu_device, cpumask_first(mask));
+               td->evtdev->broadcast(mask);
        }
 }
 
@@ -160,12 +161,11 @@ static void tick_do_broadcast(cpumask_t mask)
  */
 static void tick_do_periodic_broadcast(void)
 {
-       cpumask_t mask;
-
        spin_lock(&tick_broadcast_lock);
 
-       cpus_and(mask, cpu_online_map, tick_broadcast_mask);
-       tick_do_broadcast(mask);
+       cpumask_and(to_cpumask(tmpmask),
+                   cpu_online_mask, tick_get_broadcast_mask());
+       tick_do_broadcast(to_cpumask(tmpmask));
 
        spin_unlock(&tick_broadcast_lock);
 }
@@ -228,13 +228,13 @@ static void tick_do_broadcast_on_off(void *why)
        if (!tick_device_is_functional(dev))
                goto out;
 
-       bc_stopped = cpus_empty(tick_broadcast_mask);
+       bc_stopped = cpumask_empty(tick_get_broadcast_mask());
 
        switch (*reason) {
        case CLOCK_EVT_NOTIFY_BROADCAST_ON:
        case CLOCK_EVT_NOTIFY_BROADCAST_FORCE:
-               if (!cpu_isset(cpu, tick_broadcast_mask)) {
-                       cpu_set(cpu, tick_broadcast_mask);
+               if (!cpumask_test_cpu(cpu, tick_get_broadcast_mask())) {
+                       cpumask_set_cpu(cpu, tick_get_broadcast_mask());
                        if (tick_broadcast_device.mode ==
                            TICKDEV_MODE_PERIODIC)
                                clockevents_shutdown(dev);
@@ -244,8 +244,8 @@ static void tick_do_broadcast_on_off(void *why)
                break;
        case CLOCK_EVT_NOTIFY_BROADCAST_OFF:
                if (!tick_broadcast_force &&
-                   cpu_isset(cpu, tick_broadcast_mask)) {
-                       cpu_clear(cpu, tick_broadcast_mask);
+                   cpumask_test_cpu(cpu, tick_get_broadcast_mask())) {
+                       cpumask_clear_cpu(cpu, tick_get_broadcast_mask());
                        if (tick_broadcast_device.mode ==
                            TICKDEV_MODE_PERIODIC)
                                tick_setup_periodic(dev, 0);
@@ -253,7 +253,7 @@ static void tick_do_broadcast_on_off(void *why)
                break;
        }
 
-       if (cpus_empty(tick_broadcast_mask)) {
+       if (cpumask_empty(tick_get_broadcast_mask())) {
                if (!bc_stopped)
                        clockevents_shutdown(bc);
        } else if (bc_stopped) {
@@ -272,7 +272,7 @@ out:
  */
 void tick_broadcast_on_off(unsigned long reason, int *oncpu)
 {
-       if (!cpu_isset(*oncpu, cpu_online_map))
+       if (!cpumask_test_cpu(*oncpu, cpu_online_mask))
                printk(KERN_ERR "tick-broadcast: ignoring broadcast for "
                       "offline CPU #%d\n", *oncpu);
        else
@@ -303,10 +303,10 @@ void tick_shutdown_broadcast(unsigned int *cpup)
        spin_lock_irqsave(&tick_broadcast_lock, flags);
 
        bc = tick_broadcast_device.evtdev;
-       cpu_clear(cpu, tick_broadcast_mask);
+       cpumask_clear_cpu(cpu, tick_get_broadcast_mask());
 
        if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) {
-               if (bc && cpus_empty(tick_broadcast_mask))
+               if (bc && cpumask_empty(tick_get_broadcast_mask()))
                        clockevents_shutdown(bc);
        }
 
@@ -342,10 +342,10 @@ int tick_resume_broadcast(void)
 
                switch (tick_broadcast_device.mode) {
                case TICKDEV_MODE_PERIODIC:
-                       if(!cpus_empty(tick_broadcast_mask))
+                       if (!cpumask_empty(tick_get_broadcast_mask()))
                                tick_broadcast_start_periodic(bc);
-                       broadcast = cpu_isset(smp_processor_id(),
-                                             tick_broadcast_mask);
+                       broadcast = cpumask_test_cpu(smp_processor_id(),
+                                                    tick_get_broadcast_mask());
                        break;
                case TICKDEV_MODE_ONESHOT:
                        broadcast = tick_resume_broadcast_oneshot(bc);
@@ -360,14 +360,15 @@ int tick_resume_broadcast(void)
 
 #ifdef CONFIG_TICK_ONESHOT
 
-static cpumask_t tick_broadcast_oneshot_mask;
+/* FIXME: use cpumask_var_t. */
+static DECLARE_BITMAP(tick_broadcast_oneshot_mask, NR_CPUS);
 
 /*
- * Debugging: see timer_list.c
+ * Exposed for debugging: see timer_list.c
  */
-cpumask_t *tick_get_broadcast_oneshot_mask(void)
+struct cpumask *tick_get_broadcast_oneshot_mask(void)
 {
-       return &tick_broadcast_oneshot_mask;
+       return to_cpumask(tick_broadcast_oneshot_mask);
 }
 
 static int tick_broadcast_set_event(ktime_t expires, int force)
@@ -389,7 +390,7 @@ int tick_resume_broadcast_oneshot(struct clock_event_device *bc)
  */
 void tick_check_oneshot_broadcast(int cpu)
 {
-       if (cpu_isset(cpu, tick_broadcast_oneshot_mask)) {
+       if (cpumask_test_cpu(cpu, to_cpumask(tick_broadcast_oneshot_mask))) {
                struct tick_device *td = &per_cpu(tick_cpu_device, cpu);
 
                clockevents_set_mode(td->evtdev, CLOCK_EVT_MODE_ONESHOT);
@@ -402,7 +403,6 @@ void tick_check_oneshot_broadcast(int cpu)
 static void tick_handle_oneshot_broadcast(struct clock_event_device *dev)
 {
        struct tick_device *td;
-       cpumask_t mask;
        ktime_t now, next_event;
        int cpu;
 
@@ -410,13 +410,13 @@ static void tick_handle_oneshot_broadcast(struct clock_event_device *dev)
 again:
        dev->next_event.tv64 = KTIME_MAX;
        next_event.tv64 = KTIME_MAX;
-       mask = CPU_MASK_NONE;
+       cpumask_clear(to_cpumask(tmpmask));
        now = ktime_get();
        /* Find all expired events */
-       for_each_cpu_mask_nr(cpu, tick_broadcast_oneshot_mask) {
+       for_each_cpu(cpu, tick_get_broadcast_oneshot_mask()) {
                td = &per_cpu(tick_cpu_device, cpu);
                if (td->evtdev->next_event.tv64 <= now.tv64)
-                       cpu_set(cpu, mask);
+                       cpumask_set_cpu(cpu, to_cpumask(tmpmask));
                else if (td->evtdev->next_event.tv64 < next_event.tv64)
                        next_event.tv64 = td->evtdev->next_event.tv64;
        }
@@ -424,7 +424,7 @@ again:
        /*
         * Wakeup the cpus which have an expired event.
         */
-       tick_do_broadcast(mask);
+       tick_do_broadcast(to_cpumask(tmpmask));
 
        /*
         * Two reasons for reprogram:
@@ -476,15 +476,16 @@ void tick_broadcast_oneshot_control(unsigned long reason)
                goto out;
 
        if (reason == CLOCK_EVT_NOTIFY_BROADCAST_ENTER) {
-               if (!cpu_isset(cpu, tick_broadcast_oneshot_mask)) {
-                       cpu_set(cpu, tick_broadcast_oneshot_mask);
+               if (!cpumask_test_cpu(cpu, tick_get_broadcast_oneshot_mask())) {
+                       cpumask_set_cpu(cpu, tick_get_broadcast_oneshot_mask());
                        clockevents_set_mode(dev, CLOCK_EVT_MODE_SHUTDOWN);
                        if (dev->next_event.tv64 < bc->next_event.tv64)
                                tick_broadcast_set_event(dev->next_event, 1);
                }
        } else {
-               if (cpu_isset(cpu, tick_broadcast_oneshot_mask)) {
-                       cpu_clear(cpu, tick_broadcast_oneshot_mask);
+               if (cpumask_test_cpu(cpu, tick_get_broadcast_oneshot_mask())) {
+                       cpumask_clear_cpu(cpu,
+                                         tick_get_broadcast_oneshot_mask());
                        clockevents_set_mode(dev, CLOCK_EVT_MODE_ONESHOT);
                        if (dev->next_event.tv64 != KTIME_MAX)
                                tick_program_event(dev->next_event, 1);
@@ -502,15 +503,16 @@ out:
  */
 static void tick_broadcast_clear_oneshot(int cpu)
 {
-       cpu_clear(cpu, tick_broadcast_oneshot_mask);
+       cpumask_clear_cpu(cpu, tick_get_broadcast_oneshot_mask());
 }
 
-static void tick_broadcast_init_next_event(cpumask_t *mask, ktime_t expires)
+static void tick_broadcast_init_next_event(struct cpumask *mask,
+                                          ktime_t expires)
 {
        struct tick_device *td;
        int cpu;
 
-       for_each_cpu_mask_nr(cpu, *mask) {
+       for_each_cpu(cpu, mask) {
                td = &per_cpu(tick_cpu_device, cpu);
                if (td->evtdev)
                        td->evtdev->next_event = expires;
@@ -526,7 +528,6 @@ void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
        if (bc->event_handler != tick_handle_oneshot_broadcast) {
                int was_periodic = bc->mode == CLOCK_EVT_MODE_PERIODIC;
                int cpu = smp_processor_id();
-               cpumask_t mask;
 
                bc->event_handler = tick_handle_oneshot_broadcast;
                clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
@@ -540,13 +541,15 @@ void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
                 * oneshot_mask bits for those and program the
                 * broadcast device to fire.
                 */
-               mask = tick_broadcast_mask;
-               cpu_clear(cpu, mask);
-               cpus_or(tick_broadcast_oneshot_mask,
-                       tick_broadcast_oneshot_mask, mask);
-
-               if (was_periodic && !cpus_empty(mask)) {
-                       tick_broadcast_init_next_event(&mask, tick_next_period);
+               cpumask_copy(to_cpumask(tmpmask), tick_get_broadcast_mask());
+               cpumask_clear_cpu(cpu, to_cpumask(tmpmask));
+               cpumask_or(tick_get_broadcast_oneshot_mask(),
+                          tick_get_broadcast_oneshot_mask(),
+                          to_cpumask(tmpmask));
+
+               if (was_periodic && !cpumask_empty(to_cpumask(tmpmask))) {
+                       tick_broadcast_init_next_event(to_cpumask(tmpmask),
+                                                      tick_next_period);
                        tick_broadcast_set_event(tick_next_period, 1);
                } else
                        bc->next_event.tv64 = KTIME_MAX;
@@ -585,7 +588,7 @@ void tick_shutdown_broadcast_oneshot(unsigned int *cpup)
         * Clear the broadcast mask flag for the dead cpu, but do not
         * stop the broadcast device!
         */
-       cpu_clear(cpu, tick_broadcast_oneshot_mask);
+       cpumask_clear_cpu(cpu, tick_get_broadcast_oneshot_mask());
 
        spin_unlock_irqrestore(&tick_broadcast_lock, flags);
 }
index f8372be74122aa3f10b3dfc6642ffde2dc297920..63e05d423a09903907558d7d2aba661f5b426db6 100644 (file)
@@ -254,7 +254,7 @@ static int tick_check_new_device(struct clock_event_device *newdev)
                curdev = NULL;
        }
        clockevents_exchange_device(curdev, newdev);
-       tick_setup_device(td, newdev, cpu, &cpumask_of_cpu(cpu));
+       tick_setup_device(td, newdev, cpu, cpumask_of(cpu));
        if (newdev->features & CLOCK_EVT_FEAT_ONESHOT)
                tick_oneshot_notify();
 
@@ -299,9 +299,9 @@ static void tick_shutdown(unsigned int *cpup)
        }
        /* Transfer the do_timer job away from this cpu */
        if (*cpup == tick_do_timer_cpu) {
-               int cpu = first_cpu(cpu_online_map);
+               int cpu = cpumask_first(cpu_online_mask);
 
-               tick_do_timer_cpu = (cpu != NR_CPUS) ? cpu :
+               tick_do_timer_cpu = (cpu < nr_cpu_ids) ? cpu :
                        TICK_DO_TIMER_NONE;
        }
        spin_unlock_irqrestore(&tick_device_lock, flags);
index 76a574bbef97270672dee229b81b77872ba319e6..1b6c05bd0d0a99e4de3a7ade02c2186ca4fc4db7 100644 (file)
@@ -419,7 +419,9 @@ void tick_nohz_restart_sched_tick(void)
 {
        int cpu = smp_processor_id();
        struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
+#ifndef CONFIG_VIRT_CPU_ACCOUNTING
        unsigned long ticks;
+#endif
        ktime_t now;
 
        local_irq_disable();
@@ -441,6 +443,7 @@ void tick_nohz_restart_sched_tick(void)
        tick_do_update_jiffies64(now);
        cpumask_clear_cpu(cpu, nohz_cpu_mask);
 
+#ifndef CONFIG_VIRT_CPU_ACCOUNTING
        /*
         * We stopped the tick in idle. Update process times would miss the
         * time we slept as update_process_times does only a 1 tick
@@ -450,12 +453,9 @@ void tick_nohz_restart_sched_tick(void)
        /*
         * We might be one off. Do not randomly account a huge number of ticks!
         */
-       if (ticks && ticks < LONG_MAX) {
-               add_preempt_count(HARDIRQ_OFFSET);
-               account_system_time(current, HARDIRQ_OFFSET,
-                                   jiffies_to_cputime(ticks));
-               sub_preempt_count(HARDIRQ_OFFSET);
-       }
+       if (ticks && ticks < LONG_MAX)
+               account_idle_ticks(ticks);
+#endif
 
        touch_softlockup_watchdog();
        /*
index 566257d1dc10327818f787e5ca04559c05bd2566..dee3f641a7a72d5ec8f00c6ff07d64f0e1470385 100644 (file)
@@ -1018,21 +1018,6 @@ unsigned long get_next_timer_interrupt(unsigned long now)
 }
 #endif
 
-#ifndef CONFIG_VIRT_CPU_ACCOUNTING
-void account_process_tick(struct task_struct *p, int user_tick)
-{
-       cputime_t one_jiffy = jiffies_to_cputime(1);
-
-       if (user_tick) {
-               account_user_time(p, one_jiffy);
-               account_user_time_scaled(p, cputime_to_scaled(one_jiffy));
-       } else {
-               account_system_time(p, HARDIRQ_OFFSET, one_jiffy);
-               account_system_time_scaled(p, cputime_to_scaled(one_jiffy));
-       }
-}
-#endif
-
 /*
  * Called from the timer interrupt handler to charge one tick to the current
  * process.  user_tick is 1 if the tick is user time, 0 for system.
index 1d601a7c4587eb075b8fe0100705a6d00ffc9172..a9d9760dc7b62ae7d17894f815067ced748db2cd 100644 (file)
@@ -195,7 +195,7 @@ void *ring_buffer_event_data(struct ring_buffer_event *event)
 EXPORT_SYMBOL_GPL(ring_buffer_event_data);
 
 #define for_each_buffer_cpu(buffer, cpu)               \
-       for_each_cpu_mask(cpu, buffer->cpumask)
+       for_each_cpu(cpu, buffer->cpumask)
 
 #define TS_SHIFT       27
 #define TS_MASK                ((1ULL << TS_SHIFT) - 1)
@@ -267,7 +267,7 @@ struct ring_buffer {
        unsigned                        pages;
        unsigned                        flags;
        int                             cpus;
-       cpumask_t                       cpumask;
+       cpumask_var_t                   cpumask;
        atomic_t                        record_disabled;
 
        struct mutex                    mutex;
@@ -458,6 +458,9 @@ struct ring_buffer *ring_buffer_alloc(unsigned long size, unsigned flags)
        if (!buffer)
                return NULL;
 
+       if (!alloc_cpumask_var(&buffer->cpumask, GFP_KERNEL))
+               goto fail_free_buffer;
+
        buffer->pages = DIV_ROUND_UP(size, BUF_PAGE_SIZE);
        buffer->flags = flags;
 
@@ -465,14 +468,14 @@ struct ring_buffer *ring_buffer_alloc(unsigned long size, unsigned flags)
        if (buffer->pages == 1)
                buffer->pages++;
 
-       buffer->cpumask = cpu_possible_map;
+       cpumask_copy(buffer->cpumask, cpu_possible_mask);
        buffer->cpus = nr_cpu_ids;
 
        bsize = sizeof(void *) * nr_cpu_ids;
        buffer->buffers = kzalloc(ALIGN(bsize, cache_line_size()),
                                  GFP_KERNEL);
        if (!buffer->buffers)
-               goto fail_free_buffer;
+               goto fail_free_cpumask;
 
        for_each_buffer_cpu(buffer, cpu) {
                buffer->buffers[cpu] =
@@ -492,6 +495,9 @@ struct ring_buffer *ring_buffer_alloc(unsigned long size, unsigned flags)
        }
        kfree(buffer->buffers);
 
+ fail_free_cpumask:
+       free_cpumask_var(buffer->cpumask);
+
  fail_free_buffer:
        kfree(buffer);
        return NULL;
@@ -510,6 +516,8 @@ ring_buffer_free(struct ring_buffer *buffer)
        for_each_buffer_cpu(buffer, cpu)
                rb_free_cpu_buffer(buffer->buffers[cpu]);
 
+       free_cpumask_var(buffer->cpumask);
+
        kfree(buffer);
 }
 EXPORT_SYMBOL_GPL(ring_buffer_free);
@@ -1283,7 +1291,7 @@ ring_buffer_lock_reserve(struct ring_buffer *buffer,
 
        cpu = raw_smp_processor_id();
 
-       if (!cpu_isset(cpu, buffer->cpumask))
+       if (!cpumask_test_cpu(cpu, buffer->cpumask))
                goto out;
 
        cpu_buffer = buffer->buffers[cpu];
@@ -1396,7 +1404,7 @@ int ring_buffer_write(struct ring_buffer *buffer,
 
        cpu = raw_smp_processor_id();
 
-       if (!cpu_isset(cpu, buffer->cpumask))
+       if (!cpumask_test_cpu(cpu, buffer->cpumask))
                goto out;
 
        cpu_buffer = buffer->buffers[cpu];
@@ -1478,7 +1486,7 @@ void ring_buffer_record_disable_cpu(struct ring_buffer *buffer, int cpu)
 {
        struct ring_buffer_per_cpu *cpu_buffer;
 
-       if (!cpu_isset(cpu, buffer->cpumask))
+       if (!cpumask_test_cpu(cpu, buffer->cpumask))
                return;
 
        cpu_buffer = buffer->buffers[cpu];
@@ -1498,7 +1506,7 @@ void ring_buffer_record_enable_cpu(struct ring_buffer *buffer, int cpu)
 {
        struct ring_buffer_per_cpu *cpu_buffer;
 
-       if (!cpu_isset(cpu, buffer->cpumask))
+       if (!cpumask_test_cpu(cpu, buffer->cpumask))
                return;
 
        cpu_buffer = buffer->buffers[cpu];
@@ -1515,7 +1523,7 @@ unsigned long ring_buffer_entries_cpu(struct ring_buffer *buffer, int cpu)
 {
        struct ring_buffer_per_cpu *cpu_buffer;
 
-       if (!cpu_isset(cpu, buffer->cpumask))
+       if (!cpumask_test_cpu(cpu, buffer->cpumask))
                return 0;
 
        cpu_buffer = buffer->buffers[cpu];
@@ -1532,7 +1540,7 @@ unsigned long ring_buffer_overrun_cpu(struct ring_buffer *buffer, int cpu)
 {
        struct ring_buffer_per_cpu *cpu_buffer;
 
-       if (!cpu_isset(cpu, buffer->cpumask))
+       if (!cpumask_test_cpu(cpu, buffer->cpumask))
                return 0;
 
        cpu_buffer = buffer->buffers[cpu];
@@ -1850,7 +1858,7 @@ rb_buffer_peek(struct ring_buffer *buffer, int cpu, u64 *ts)
        struct buffer_page *reader;
        int nr_loops = 0;
 
-       if (!cpu_isset(cpu, buffer->cpumask))
+       if (!cpumask_test_cpu(cpu, buffer->cpumask))
                return NULL;
 
        cpu_buffer = buffer->buffers[cpu];
@@ -2025,7 +2033,7 @@ ring_buffer_consume(struct ring_buffer *buffer, int cpu, u64 *ts)
        struct ring_buffer_event *event;
        unsigned long flags;
 
-       if (!cpu_isset(cpu, buffer->cpumask))
+       if (!cpumask_test_cpu(cpu, buffer->cpumask))
                return NULL;
 
        spin_lock_irqsave(&cpu_buffer->reader_lock, flags);
@@ -2062,7 +2070,7 @@ ring_buffer_read_start(struct ring_buffer *buffer, int cpu)
        struct ring_buffer_iter *iter;
        unsigned long flags;
 
-       if (!cpu_isset(cpu, buffer->cpumask))
+       if (!cpumask_test_cpu(cpu, buffer->cpumask))
                return NULL;
 
        iter = kmalloc(sizeof(*iter), GFP_KERNEL);
@@ -2172,7 +2180,7 @@ void ring_buffer_reset_cpu(struct ring_buffer *buffer, int cpu)
        struct ring_buffer_per_cpu *cpu_buffer = buffer->buffers[cpu];
        unsigned long flags;
 
-       if (!cpu_isset(cpu, buffer->cpumask))
+       if (!cpumask_test_cpu(cpu, buffer->cpumask))
                return;
 
        spin_lock_irqsave(&cpu_buffer->reader_lock, flags);
@@ -2228,7 +2236,7 @@ int ring_buffer_empty_cpu(struct ring_buffer *buffer, int cpu)
 {
        struct ring_buffer_per_cpu *cpu_buffer;
 
-       if (!cpu_isset(cpu, buffer->cpumask))
+       if (!cpumask_test_cpu(cpu, buffer->cpumask))
                return 1;
 
        cpu_buffer = buffer->buffers[cpu];
@@ -2252,8 +2260,8 @@ int ring_buffer_swap_cpu(struct ring_buffer *buffer_a,
        struct ring_buffer_per_cpu *cpu_buffer_a;
        struct ring_buffer_per_cpu *cpu_buffer_b;
 
-       if (!cpu_isset(cpu, buffer_a->cpumask) ||
-           !cpu_isset(cpu, buffer_b->cpumask))
+       if (!cpumask_test_cpu(cpu, buffer_a->cpumask) ||
+           !cpumask_test_cpu(cpu, buffer_b->cpumask))
                return -EINVAL;
 
        /* At least make sure the two buffers are somewhat the same */
index 0e91f43b6baf53cac177af4ca02f0939997c1a0c..c580233add95a0915f4797b84ae05a728aa986c6 100644 (file)
@@ -89,10 +89,10 @@ static inline void ftrace_enable_cpu(void)
        preempt_enable();
 }
 
-static cpumask_t __read_mostly         tracing_buffer_mask;
+static cpumask_var_t __read_mostly     tracing_buffer_mask;
 
 #define for_each_tracing_cpu(cpu)      \
-       for_each_cpu_mask(cpu, tracing_buffer_mask)
+       for_each_cpu(cpu, tracing_buffer_mask)
 
 /*
  * ftrace_dump_on_oops - variable to dump ftrace buffer on oops
@@ -1811,10 +1811,10 @@ static void test_cpu_buff_start(struct trace_iterator *iter)
        if (!(iter->iter_flags & TRACE_FILE_ANNOTATE))
                return;
 
-       if (cpu_isset(iter->cpu, iter->started))
+       if (cpumask_test_cpu(iter->cpu, iter->started))
                return;
 
-       cpu_set(iter->cpu, iter->started);
+       cpumask_set_cpu(iter->cpu, iter->started);
        trace_seq_printf(s, "##### CPU %u buffer started ####\n", iter->cpu);
 }
 
@@ -2646,13 +2646,7 @@ static struct file_operations show_traces_fops = {
 /*
  * Only trace on a CPU if the bitmask is set:
  */
-static cpumask_t tracing_cpumask = CPU_MASK_ALL;
-
-/*
- * When tracing/tracing_cpu_mask is modified then this holds
- * the new bitmask we are about to install:
- */
-static cpumask_t tracing_cpumask_new;
+static cpumask_var_t tracing_cpumask;
 
 /*
  * The tracer itself will not take this lock, but still we want
@@ -2674,7 +2668,7 @@ tracing_cpumask_read(struct file *filp, char __user *ubuf,
 
        mutex_lock(&tracing_cpumask_update_lock);
 
-       len = cpumask_scnprintf(mask_str, count, &tracing_cpumask);
+       len = cpumask_scnprintf(mask_str, count, tracing_cpumask);
        if (count - len < 2) {
                count = -EINVAL;
                goto out_err;
@@ -2693,9 +2687,13 @@ tracing_cpumask_write(struct file *filp, const char __user *ubuf,
                      size_t count, loff_t *ppos)
 {
        int err, cpu;
+       cpumask_var_t tracing_cpumask_new;
+
+       if (!alloc_cpumask_var(&tracing_cpumask_new, GFP_KERNEL))
+               return -ENOMEM;
 
        mutex_lock(&tracing_cpumask_update_lock);
-       err = cpumask_parse_user(ubuf, count, &tracing_cpumask_new);
+       err = cpumask_parse_user(ubuf, count, tracing_cpumask_new);
        if (err)
                goto err_unlock;
 
@@ -2706,26 +2704,28 @@ tracing_cpumask_write(struct file *filp, const char __user *ubuf,
                 * Increase/decrease the disabled counter if we are
                 * about to flip a bit in the cpumask:
                 */
-               if (cpu_isset(cpu, tracing_cpumask) &&
-                               !cpu_isset(cpu, tracing_cpumask_new)) {
+               if (cpumask_test_cpu(cpu, tracing_cpumask) &&
+                               !cpumask_test_cpu(cpu, tracing_cpumask_new)) {
                        atomic_inc(&global_trace.data[cpu]->disabled);
                }
-               if (!cpu_isset(cpu, tracing_cpumask) &&
-                               cpu_isset(cpu, tracing_cpumask_new)) {
+               if (!cpumask_test_cpu(cpu, tracing_cpumask) &&
+                               cpumask_test_cpu(cpu, tracing_cpumask_new)) {
                        atomic_dec(&global_trace.data[cpu]->disabled);
                }
        }
        __raw_spin_unlock(&ftrace_max_lock);
        local_irq_enable();
 
-       tracing_cpumask = tracing_cpumask_new;
+       cpumask_copy(tracing_cpumask, tracing_cpumask_new);
 
        mutex_unlock(&tracing_cpumask_update_lock);
+       free_cpumask_var(tracing_cpumask_new);
 
        return count;
 
 err_unlock:
        mutex_unlock(&tracing_cpumask_update_lock);
+       free_cpumask_var(tracing_cpumask);
 
        return err;
 }
@@ -3114,10 +3114,15 @@ static int tracing_open_pipe(struct inode *inode, struct file *filp)
        if (!iter)
                return -ENOMEM;
 
+       if (!alloc_cpumask_var(&iter->started, GFP_KERNEL)) {
+               kfree(iter);
+               return -ENOMEM;
+       }
+
        mutex_lock(&trace_types_lock);
 
        /* trace pipe does not show start of buffer */
-       cpus_setall(iter->started);
+       cpumask_setall(iter->started);
 
        iter->tr = &global_trace;
        iter->trace = current_trace;
@@ -3134,6 +3139,7 @@ static int tracing_release_pipe(struct inode *inode, struct file *file)
 {
        struct trace_iterator *iter = file->private_data;
 
+       free_cpumask_var(iter->started);
        kfree(iter);
        atomic_dec(&tracing_reader);
 
@@ -3752,7 +3758,6 @@ void ftrace_dump(void)
        static DEFINE_SPINLOCK(ftrace_dump_lock);
        /* use static because iter can be a bit big for the stack */
        static struct trace_iterator iter;
-       static cpumask_t mask;
        static int dump_ran;
        unsigned long flags;
        int cnt = 0, cpu;
@@ -3786,8 +3791,6 @@ void ftrace_dump(void)
         * and then release the locks again.
         */
 
-       cpus_clear(mask);
-
        while (!trace_empty(&iter)) {
 
                if (!cnt)
@@ -3823,19 +3826,28 @@ __init static int tracer_alloc_buffers(void)
 {
        struct trace_array_cpu *data;
        int i;
+       int ret = -ENOMEM;
 
-       /* TODO: make the number of buffers hot pluggable with CPUS */
-       tracing_buffer_mask = cpu_possible_map;
+       if (!alloc_cpumask_var(&tracing_buffer_mask, GFP_KERNEL))
+               goto out;
+
+       if (!alloc_cpumask_var(&tracing_cpumask, GFP_KERNEL))
+               goto out_free_buffer_mask;
+
+       cpumask_copy(tracing_buffer_mask, cpu_possible_mask);
+       cpumask_copy(tracing_cpumask, cpu_all_mask);
 
+       /* TODO: make the number of buffers hot pluggable with CPUS */
        global_trace.buffer = ring_buffer_alloc(trace_buf_size,
                                                   TRACE_BUFFER_FLAGS);
        if (!global_trace.buffer) {
                printk(KERN_ERR "tracer: failed to allocate ring buffer!\n");
                WARN_ON(1);
-               return 0;
+               goto out_free_cpumask;
        }
        global_trace.entries = ring_buffer_size(global_trace.buffer);
 
+
 #ifdef CONFIG_TRACER_MAX_TRACE
        max_tr.buffer = ring_buffer_alloc(trace_buf_size,
                                             TRACE_BUFFER_FLAGS);
@@ -3843,7 +3855,7 @@ __init static int tracer_alloc_buffers(void)
                printk(KERN_ERR "tracer: failed to allocate max ring buffer!\n");
                WARN_ON(1);
                ring_buffer_free(global_trace.buffer);
-               return 0;
+               goto out_free_cpumask;
        }
        max_tr.entries = ring_buffer_size(max_tr.buffer);
        WARN_ON(max_tr.entries != global_trace.entries);
@@ -3873,8 +3885,14 @@ __init static int tracer_alloc_buffers(void)
                                       &trace_panic_notifier);
 
        register_die_notifier(&trace_die_notifier);
+       ret = 0;
 
-       return 0;
+out_free_cpumask:
+       free_cpumask_var(tracing_cpumask);
+out_free_buffer_mask:
+       free_cpumask_var(tracing_buffer_mask);
+out:
+       return ret;
 }
 early_initcall(tracer_alloc_buffers);
 fs_initcall(tracer_init_debugfs);
index cc7a4f86403695d6934f753cbc2cc7cdc6597f80..4d3d381bfd9537e3a43df767e30fb0d2991c66d0 100644 (file)
@@ -368,7 +368,7 @@ struct trace_iterator {
        loff_t                  pos;
        long                    idx;
 
-       cpumask_t               started;
+       cpumask_var_t           started;
 };
 
 int tracing_is_enabled(void);
index 3ccebde284820ee7bbb41c8ef8b4aad9d251b47a..366c8c333e136e77d79a4579b4e70f24242b1404 100644 (file)
@@ -42,7 +42,7 @@ static int boot_trace_init(struct trace_array *tr)
        int cpu;
        boot_trace = tr;
 
-       for_each_cpu_mask(cpu, cpu_possible_map)
+       for_each_cpu(cpu, cpu_possible_mask)
                tracing_reset(tr, cpu);
 
        tracing_sched_switch_assign_trace(tr);
index 4bf39fcae97afadc384b104e5d77be0120e375e3..930c08e5b38e0d35ab93b79896b0150907d31e50 100644 (file)
@@ -79,7 +79,7 @@ print_graph_cpu(struct trace_seq *s, int cpu)
        int i;
        int ret;
        int log10_this = log10_cpu(cpu);
-       int log10_all = log10_cpu(cpus_weight_nr(cpu_online_map));
+       int log10_all = log10_cpu(cpumask_weight(cpu_online_mask));
 
 
        /*
index b6a3e20a49a9f3ef3e4851de38017d961db548da..649df22d435fc3507d05aecbb244ccf5cbcfffa1 100644 (file)
@@ -46,7 +46,7 @@ static void bts_trace_start(struct trace_array *tr)
 
        tracing_reset_online_cpus(tr);
 
-       for_each_cpu_mask(cpu, cpu_possible_map)
+       for_each_cpu(cpu, cpu_possible_mask)
                smp_call_function_single(cpu, bts_trace_start_cpu, NULL, 1);
 }
 
@@ -62,7 +62,7 @@ static void bts_trace_stop(struct trace_array *tr)
 {
        int cpu;
 
-       for_each_cpu_mask(cpu, cpu_possible_map)
+       for_each_cpu(cpu, cpu_possible_mask)
                smp_call_function_single(cpu, bts_trace_stop_cpu, NULL, 1);
 }
 
@@ -172,7 +172,7 @@ static void trace_bts_prepare(struct trace_iterator *iter)
 {
        int cpu;
 
-       for_each_cpu_mask(cpu, cpu_possible_map)
+       for_each_cpu(cpu, cpu_possible_mask)
                smp_call_function_single(cpu, trace_bts_cpu, iter->tr, 1);
 }
 
index a7172a352f626b263e4a4226d39cb732224a979c..7bda248daf5557a04ff1f178764b80777a33dff5 100644 (file)
@@ -39,7 +39,7 @@ static int power_trace_init(struct trace_array *tr)
 
        trace_power_enabled = 1;
 
-       for_each_cpu_mask(cpu, cpu_possible_map)
+       for_each_cpu(cpu, cpu_possible_mask)
                tracing_reset(tr, cpu);
        return 0;
 }
index a5779bd975db0a386cd67d67629a2bf53e72764e..eaca5ad803fffe755767acd073a36564aa620d22 100644 (file)
@@ -196,9 +196,9 @@ static enum hrtimer_restart stack_trace_timer_fn(struct hrtimer *hrtimer)
        return HRTIMER_RESTART;
 }
 
-static void start_stack_timer(int cpu)
+static void start_stack_timer(void *unused)
 {
-       struct hrtimer *hrtimer = &per_cpu(stack_trace_hrtimer, cpu);
+       struct hrtimer *hrtimer = &__get_cpu_var(stack_trace_hrtimer);
 
        hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
        hrtimer->function = stack_trace_timer_fn;
@@ -208,14 +208,7 @@ static void start_stack_timer(int cpu)
 
 static void start_stack_timers(void)
 {
-       cpumask_t saved_mask = current->cpus_allowed;
-       int cpu;
-
-       for_each_online_cpu(cpu) {
-               set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
-               start_stack_timer(cpu);
-       }
-       set_cpus_allowed_ptr(current, &saved_mask);
+       on_each_cpu(start_stack_timer, NULL, 1);
 }
 
 static void stop_stack_timer(int cpu)
index 4952322cba45b05c90999f21b51016612c8144ca..2f445833ae371a58d35c56907e2eeb638e75a453 100644 (file)
@@ -73,7 +73,7 @@ static DEFINE_SPINLOCK(workqueue_lock);
 static LIST_HEAD(workqueues);
 
 static int singlethread_cpu __read_mostly;
-static cpumask_t cpu_singlethread_map __read_mostly;
+static const struct cpumask *cpu_singlethread_map __read_mostly;
 /*
  * _cpu_down() first removes CPU from cpu_online_map, then CPU_DEAD
  * flushes cwq->worklist. This means that flush_workqueue/wait_on_work
@@ -81,7 +81,7 @@ static cpumask_t cpu_singlethread_map __read_mostly;
  * use cpu_possible_map, the cpumask below is more a documentation
  * than optimization.
  */
-static cpumask_t cpu_populated_map __read_mostly;
+static cpumask_var_t cpu_populated_map __read_mostly;
 
 /* If it's single threaded, it isn't in the list of workqueues. */
 static inline int is_wq_single_threaded(struct workqueue_struct *wq)
@@ -89,10 +89,10 @@ static inline int is_wq_single_threaded(struct workqueue_struct *wq)
        return wq->singlethread;
 }
 
-static const cpumask_t *wq_cpu_map(struct workqueue_struct *wq)
+static const struct cpumask *wq_cpu_map(struct workqueue_struct *wq)
 {
        return is_wq_single_threaded(wq)
-               ? &cpu_singlethread_map : &cpu_populated_map;
+               ? cpu_singlethread_map : cpu_populated_map;
 }
 
 static
@@ -410,7 +410,7 @@ static int flush_cpu_workqueue(struct cpu_workqueue_struct *cwq)
  */
 void flush_workqueue(struct workqueue_struct *wq)
 {
-       const cpumask_t *cpu_map = wq_cpu_map(wq);
+       const struct cpumask *cpu_map = wq_cpu_map(wq);
        int cpu;
 
        might_sleep();
@@ -532,7 +532,7 @@ static void wait_on_work(struct work_struct *work)
 {
        struct cpu_workqueue_struct *cwq;
        struct workqueue_struct *wq;
-       const cpumask_t *cpu_map;
+       const struct cpumask *cpu_map;
        int cpu;
 
        might_sleep();
@@ -903,7 +903,7 @@ static void cleanup_workqueue_thread(struct cpu_workqueue_struct *cwq)
  */
 void destroy_workqueue(struct workqueue_struct *wq)
 {
-       const cpumask_t *cpu_map = wq_cpu_map(wq);
+       const struct cpumask *cpu_map = wq_cpu_map(wq);
        int cpu;
 
        cpu_maps_update_begin();
@@ -933,7 +933,7 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
 
        switch (action) {
        case CPU_UP_PREPARE:
-               cpu_set(cpu, cpu_populated_map);
+               cpumask_set_cpu(cpu, cpu_populated_map);
        }
 undo:
        list_for_each_entry(wq, &workqueues, list) {
@@ -964,7 +964,7 @@ undo:
        switch (action) {
        case CPU_UP_CANCELED:
        case CPU_POST_DEAD:
-               cpu_clear(cpu, cpu_populated_map);
+               cpumask_clear_cpu(cpu, cpu_populated_map);
        }
 
        return ret;
@@ -1017,9 +1017,11 @@ EXPORT_SYMBOL_GPL(work_on_cpu);
 
 void __init init_workqueues(void)
 {
-       cpu_populated_map = cpu_online_map;
-       singlethread_cpu = first_cpu(cpu_possible_map);
-       cpu_singlethread_map = cpumask_of_cpu(singlethread_cpu);
+       alloc_cpumask_var(&cpu_populated_map, GFP_KERNEL);
+
+       cpumask_copy(cpu_populated_map, cpu_online_mask);
+       singlethread_cpu = cpumask_first(cpu_possible_mask);
+       cpu_singlethread_map = cpumask_of(singlethread_cpu);
        hotcpu_notifier(workqueue_cpu_callback, 0);
        keventd_wq = create_workqueue("events");
        BUG_ON(!keventd_wq);
index 2ba43c4a5b075a28cb3dd05ae3f5db46fee23661..03c2c24b9083c17aff9372224ec2b22912691ffb 100644 (file)
@@ -13,6 +13,10 @@ config GENERIC_FIND_FIRST_BIT
 config GENERIC_FIND_NEXT_BIT
        bool
 
+config GENERIC_FIND_LAST_BIT
+       bool
+       default y
+
 config CRC_CCITT
        tristate "CRC-CCITT functions"
        help
@@ -166,4 +170,8 @@ config CPUMASK_OFFSTACK
          them on the stack.  This is a bit more expensive, but avoids
          stack overflow.
 
+config DISABLE_OBSOLETE_CPUMASK_FUNCTIONS
+       bool "Disable obsolete cpumask functions" if DEBUG_PER_CPU_MAPS
+       depends on EXPERIMENTAL && BROKEN
+
 endmenu
index 80fe8a3ec12a63a46ce2fe05841a3e9a6d9d54c2..32b0e64ded27d7c1f614fdc974d0857abfc19bbc 100644 (file)
@@ -37,6 +37,7 @@ lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
 lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
 lib-$(CONFIG_GENERIC_FIND_FIRST_BIT) += find_next_bit.o
 lib-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o
+lib-$(CONFIG_GENERIC_FIND_LAST_BIT) += find_last_bit.o
 obj-$(CONFIG_GENERIC_HWEIGHT) += hweight.o
 obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o
 obj-$(CONFIG_PLIST) += plist.o
index 8d03f22c6ced0176c3f2c368f58b3a167918a86e..3389e2440da0f30a76d49ab63f3419bce857849b 100644 (file)
@@ -76,15 +76,28 @@ int cpumask_any_but(const struct cpumask *mask, unsigned int cpu)
 
 /* These are not inline because of header tangles. */
 #ifdef CONFIG_CPUMASK_OFFSTACK
-bool alloc_cpumask_var(cpumask_var_t *mask, gfp_t flags)
+/**
+ * alloc_cpumask_var_node - allocate a struct cpumask on a given node
+ * @mask: pointer to cpumask_var_t where the cpumask is returned
+ * @flags: GFP_ flags
+ *
+ * Only defined when CONFIG_CPUMASK_OFFSTACK=y, otherwise is
+ * a nop returning a constant 1 (in <linux/cpumask.h>)
+ * Returns TRUE if memory allocation succeeded, FALSE otherwise.
+ *
+ * In addition, mask will be NULL if this fails.  Note that gcc is
+ * usually smart enough to know that mask can never be NULL if
+ * CONFIG_CPUMASK_OFFSTACK=n, so does code elimination in that case
+ * too.
+ */
+bool alloc_cpumask_var_node(cpumask_var_t *mask, gfp_t flags, int node)
 {
        if (likely(slab_is_available()))
-               *mask = kmalloc(cpumask_size(), flags);
+               *mask = kmalloc_node(cpumask_size(), flags, node);
        else {
 #ifdef CONFIG_DEBUG_PER_CPU_MAPS
                printk(KERN_ERR
                        "=> alloc_cpumask_var: kmalloc not available!\n");
-               dump_stack();
 #endif
                *mask = NULL;
        }
@@ -94,21 +107,64 @@ bool alloc_cpumask_var(cpumask_var_t *mask, gfp_t flags)
                dump_stack();
        }
 #endif
+       /* FIXME: Bandaid to save us from old primitives which go to NR_CPUS. */
+       if (*mask) {
+               unsigned int tail;
+               tail = BITS_TO_LONGS(NR_CPUS - nr_cpumask_bits) * sizeof(long);
+               memset(cpumask_bits(*mask) + cpumask_size() - tail,
+                      0, tail);
+       }
+
        return *mask != NULL;
 }
+EXPORT_SYMBOL(alloc_cpumask_var_node);
+
+/**
+ * alloc_cpumask_var - allocate a struct cpumask
+ * @mask: pointer to cpumask_var_t where the cpumask is returned
+ * @flags: GFP_ flags
+ *
+ * Only defined when CONFIG_CPUMASK_OFFSTACK=y, otherwise is
+ * a nop returning a constant 1 (in <linux/cpumask.h>).
+ *
+ * See alloc_cpumask_var_node.
+ */
+bool alloc_cpumask_var(cpumask_var_t *mask, gfp_t flags)
+{
+       return alloc_cpumask_var_node(mask, flags, numa_node_id());
+}
 EXPORT_SYMBOL(alloc_cpumask_var);
 
+/**
+ * alloc_bootmem_cpumask_var - allocate a struct cpumask from the bootmem arena.
+ * @mask: pointer to cpumask_var_t where the cpumask is returned
+ *
+ * Only defined when CONFIG_CPUMASK_OFFSTACK=y, otherwise is
+ * a nop (in <linux/cpumask.h>).
+ * Either returns an allocated (zero-filled) cpumask, or causes the
+ * system to panic.
+ */
 void __init alloc_bootmem_cpumask_var(cpumask_var_t *mask)
 {
        *mask = alloc_bootmem(cpumask_size());
 }
 
+/**
+ * free_cpumask_var - frees memory allocated for a struct cpumask.
+ * @mask: cpumask to free
+ *
+ * This is safe on a NULL mask.
+ */
 void free_cpumask_var(cpumask_var_t mask)
 {
        kfree(mask);
 }
 EXPORT_SYMBOL(free_cpumask_var);
 
+/**
+ * free_bootmem_cpumask_var - frees result of alloc_bootmem_cpumask_var
+ * @mask: cpumask to free
+ */
 void __init free_bootmem_cpumask_var(cpumask_var_t mask)
 {
        free_bootmem((unsigned long)mask, cpumask_size());
diff --git a/lib/find_last_bit.c b/lib/find_last_bit.c
new file mode 100644 (file)
index 0000000..5d202e3
--- /dev/null
@@ -0,0 +1,45 @@
+/* find_last_bit.c: fallback find next bit implementation
+ *
+ * Copyright (C) 2008 IBM Corporation
+ * Written by Rusty Russell <rusty@rustcorp.com.au>
+ * (Inspired by David Howell's find_next_bit implementation)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/bitops.h>
+#include <linux/module.h>
+#include <asm/types.h>
+#include <asm/byteorder.h>
+
+unsigned long find_last_bit(const unsigned long *addr, unsigned long size)
+{
+       unsigned long words;
+       unsigned long tmp;
+
+       /* Start at final word. */
+       words = size / BITS_PER_LONG;
+
+       /* Partial final word? */
+       if (size & (BITS_PER_LONG-1)) {
+               tmp = (addr[words] & (~0UL >> (BITS_PER_LONG
+                                        - (size & (BITS_PER_LONG-1)))));
+               if (tmp)
+                       goto found;
+       }
+
+       while (words) {
+               tmp = addr[--words];
+               if (tmp) {
+found:
+                       return words * BITS_PER_LONG + __fls(tmp);
+               }
+       }
+
+       /* Not found */
+       return size;
+}
+EXPORT_SYMBOL(find_last_bit);
index 3b777025d8769e4ae07838ad12aa7f2d1b82240e..98d632277ca8c932add9d0daf666dd1795c7f785 100644 (file)
@@ -661,6 +661,9 @@ static char *ip4_addr_string(char *buf, char *end, u8 *addr, int field_width,
  */
 static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int field_width, int precision, int flags)
 {
+       if (!ptr)
+               return string(buf, end, "(null)", field_width, precision, flags);
+
        switch (*fmt) {
        case 'F':
                ptr = dereference_function_descriptor(ptr);
index f3e5f8944d1763474b4c19e411af129ed03ab324..f5769b4dc075315a0ecc81c038068ebb2366cd8b 100644 (file)
@@ -1766,7 +1766,7 @@ int should_remove_suid(struct dentry *dentry)
        if (unlikely((mode & S_ISGID) && (mode & S_IXGRP)))
                kill |= ATTR_KILL_SGID;
 
-       if (unlikely(kill && !capable(CAP_FSETID)))
+       if (unlikely(kill && !capable(CAP_FSETID) && S_ISREG(mode)))
                return kill;
 
        return 0;
@@ -2140,19 +2140,24 @@ EXPORT_SYMBOL(generic_file_direct_write);
  * Find or create a page at the given pagecache position. Return the locked
  * page. This function is specifically for buffered writes.
  */
-struct page *__grab_cache_page(struct address_space *mapping, pgoff_t index)
+struct page *grab_cache_page_write_begin(struct address_space *mapping,
+                                       pgoff_t index, unsigned flags)
 {
        int status;
        struct page *page;
+       gfp_t gfp_notmask = 0;
+       if (flags & AOP_FLAG_NOFS)
+               gfp_notmask = __GFP_FS;
 repeat:
        page = find_lock_page(mapping, index);
        if (likely(page))
                return page;
 
-       page = page_cache_alloc(mapping);
+       page = __page_cache_alloc(mapping_gfp_mask(mapping) & ~gfp_notmask);
        if (!page)
                return NULL;
-       status = add_to_page_cache_lru(page, mapping, index, GFP_KERNEL);
+       status = add_to_page_cache_lru(page, mapping, index,
+                                               GFP_KERNEL & ~gfp_notmask);
        if (unlikely(status)) {
                page_cache_release(page);
                if (status == -EEXIST)
@@ -2161,7 +2166,7 @@ repeat:
        }
        return page;
 }
-EXPORT_SYMBOL(__grab_cache_page);
+EXPORT_SYMBOL(grab_cache_page_write_begin);
 
 static ssize_t generic_perform_write(struct file *file,
                                struct iov_iter *i, loff_t pos)
index 0a2010a9518c499efe694c9ed0d42f5bd18e459b..7b9db658aca22b7a10c6c596657237f294dce2fe 100644 (file)
@@ -2266,7 +2266,7 @@ int vmtruncate(struct inode * inode, loff_t offset)
                unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
        }
 
-       if (inode->i_op && inode->i_op->truncate)
+       if (inode->i_op->truncate)
                inode->i_op->truncate(inode);
        return 0;
 
@@ -2286,7 +2286,7 @@ int vmtruncate_range(struct inode *inode, loff_t offset, loff_t end)
         * a way to truncate a range of blocks (punch a hole) -
         * we should return failure right now.
         */
-       if (!inode->i_op || !inode->i_op->truncate_range)
+       if (!inode->i_op->truncate_range)
                return -ENOSYS;
 
        mutex_lock(&inode->i_mutex);
index d4855a682ab622863f85352a5353bd45fa1440e4..2c778fcfd9bd3d935b7fb74bf56ee100bfb93dd1 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -3,7 +3,7 @@
  *
  * Written by obz.
  *
- * Address space accounting code       <alan@redhat.com>
+ * Address space accounting code       <alan@lxorguk.ukuu.org.uk>
  */
 
 #include <linux/slab.h>
index fded06f923f4b939d75f745225b38b8e41e8ee08..cfb4c48520627bd83e6b39accc6d7dd0373c8c6e 100644 (file)
@@ -4,7 +4,7 @@
  *  (C) Copyright 1994 Linus Torvalds
  *  (C) Copyright 2002 Christoph Hellwig
  *
- *  Address space accounting code      <alan@redhat.com>
+ *  Address space accounting code      <alan@lxorguk.ukuu.org.uk>
  *  (C) Copyright 2002 Red Hat Inc, All Rights Reserved
  */
 
index 58a2908f42f500002e49adc218adbca0e8602c26..646de959aa5873b44b1a7f978a5e99524b7fa09c 100644 (file)
@@ -3,7 +3,7 @@
  *
  *     (C) Copyright 1996 Linus Torvalds
  *
- *     Address space accounting code   <alan@redhat.com>
+ *     Address space accounting code   <alan@lxorguk.ukuu.org.uk>
  *     (C) Copyright 2002 Red Hat Inc, All Rights Reserved
  */
 
index 144a7570535d2b57cad3e9abac4618aa9257e29a..07dae08cf31c70c25b8c5ea6300265489c4c7d97 100644 (file)
@@ -82,7 +82,7 @@ asmlinkage long sys_msync(unsigned long start, size_t len, int flags)
                                (vma->vm_flags & VM_SHARED)) {
                        get_file(file);
                        up_read(&mm->mmap_sem);
-                       error = do_fsync(file, 0);
+                       error = vfs_fsync(file, file->f_path.dentry, 0);
                        fput(file);
                        if (error || start >= end)
                                goto out;
index 7695dc850785e853f066e63992c242ffee14c30c..1c28ea3a4e9c9054975683a19237d2d823f98ead 100644 (file)
@@ -86,7 +86,7 @@ do_expand:
        i_size_write(inode, offset);
 
 out_truncate:
-       if (inode->i_op && inode->i_op->truncate)
+       if (inode->i_op->truncate)
                inode->i_op->truncate(inode);
        return 0;
 out_sig:
index a0a14c4d5072dbeef4f68c9ba37ea771e4f38577..15de509b68fd657c7b9ecb0356cdadf9bc43b1ef 100644 (file)
@@ -172,7 +172,16 @@ static int __pdflush(struct pdflush_work *my_work)
 static int pdflush(void *dummy)
 {
        struct pdflush_work my_work;
-       cpumask_t cpus_allowed;
+       cpumask_var_t cpus_allowed;
+
+       /*
+        * Since the caller doesn't even check kthread_run() worked, let's not
+        * freak out too much if this fails.
+        */
+       if (!alloc_cpumask_var(&cpus_allowed, GFP_KERNEL)) {
+               printk(KERN_WARNING "pdflush failed to allocate cpumask\n");
+               return 0;
+       }
 
        /*
         * pdflush can spend a lot of time doing encryption via dm-crypt.  We
@@ -187,8 +196,9 @@ static int pdflush(void *dummy)
         * This is needed as pdflush's are dynamically created and destroyed.
         * The boottime pdflush's are easily placed w/o these 2 lines.
         */
-       cpuset_cpus_allowed(current, &cpus_allowed);
-       set_cpus_allowed_ptr(current, &cpus_allowed);
+       cpuset_cpus_allowed(current, cpus_allowed);
+       set_cpus_allowed_ptr(current, cpus_allowed);
+       free_cpumask_var(cpus_allowed);
 
        return __pdflush(&my_work);
 }
index f97e564bdf118f140e66fb8ad1978d20abf2c939..ddc41f337d587750122f54a44806a8a29a0a67c2 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -2157,7 +2157,7 @@ kmem_cache_create (const char *name, size_t size, size_t align,
 
        /*
         * We use cache_chain_mutex to ensure a consistent view of
-        * cpu_online_map as well.  Please see cpuup_callback
+        * cpu_online_mask as well.  Please see cpuup_callback
         */
        get_online_cpus();
        mutex_lock(&cache_chain_mutex);
index 0d861c3154b6eeed56981c33b3505ecca87d5712..f0e2892fe403e57c8b29dfde41d7abf6f3a6b1f6 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1970,7 +1970,7 @@ static DEFINE_PER_CPU(struct kmem_cache_cpu,
                                kmem_cache_cpu)[NR_KMEM_CACHE_CPU];
 
 static DEFINE_PER_CPU(struct kmem_cache_cpu *, kmem_cache_cpu_free);
-static cpumask_t kmem_cach_cpu_free_init_once = CPU_MASK_NONE;
+static DECLARE_BITMAP(kmem_cach_cpu_free_init_once, CONFIG_NR_CPUS);
 
 static struct kmem_cache_cpu *alloc_kmem_cache_cpu(struct kmem_cache *s,
                                                        int cpu, gfp_t flags)
@@ -2045,13 +2045,13 @@ static void init_alloc_cpu_cpu(int cpu)
 {
        int i;
 
-       if (cpu_isset(cpu, kmem_cach_cpu_free_init_once))
+       if (cpumask_test_cpu(cpu, to_cpumask(kmem_cach_cpu_free_init_once)))
                return;
 
        for (i = NR_KMEM_CACHE_CPU - 1; i >= 0; i--)
                free_kmem_cache_cpu(&per_cpu(kmem_cache_cpu, cpu)[i], cpu);
 
-       cpu_set(cpu, kmem_cach_cpu_free_init_once);
+       cpumask_set_cpu(cpu, to_cpumask(kmem_cach_cpu_free_init_once));
 }
 
 static void __init init_alloc_cpu(void)
@@ -3451,7 +3451,7 @@ struct location {
        long max_time;
        long min_pid;
        long max_pid;
-       cpumask_t cpus;
+       DECLARE_BITMAP(cpus, NR_CPUS);
        nodemask_t nodes;
 };
 
@@ -3526,7 +3526,8 @@ static int add_location(struct loc_track *t, struct kmem_cache *s,
                                if (track->pid > l->max_pid)
                                        l->max_pid = track->pid;
 
-                               cpu_set(track->cpu, l->cpus);
+                               cpumask_set_cpu(track->cpu,
+                                               to_cpumask(l->cpus));
                        }
                        node_set(page_to_nid(virt_to_page(track)), l->nodes);
                        return 1;
@@ -3556,8 +3557,8 @@ static int add_location(struct loc_track *t, struct kmem_cache *s,
        l->max_time = age;
        l->min_pid = track->pid;
        l->max_pid = track->pid;
-       cpus_clear(l->cpus);
-       cpu_set(track->cpu, l->cpus);
+       cpumask_clear(to_cpumask(l->cpus));
+       cpumask_set_cpu(track->cpu, to_cpumask(l->cpus));
        nodes_clear(l->nodes);
        node_set(page_to_nid(virt_to_page(track)), l->nodes);
        return 1;
@@ -3638,11 +3639,12 @@ static int list_locations(struct kmem_cache *s, char *buf,
                        len += sprintf(buf + len, " pid=%ld",
                                l->min_pid);
 
-               if (num_online_cpus() > 1 && !cpus_empty(l->cpus) &&
+               if (num_online_cpus() > 1 &&
+                               !cpumask_empty(to_cpumask(l->cpus)) &&
                                len < PAGE_SIZE - 60) {
                        len += sprintf(buf + len, " cpus=");
                        len += cpulist_scnprintf(buf + len, PAGE_SIZE - len - 50,
-                                       &l->cpus);
+                                                to_cpumask(l->cpus));
                }
 
                if (num_online_nodes() > 1 && !nodes_empty(l->nodes) &&
index 1ddb77ba3995c2d8f486baf32c1409b3daf8093f..7465f22fec0cb800187ce0a98e8a80d616ce9fc8 100644 (file)
@@ -151,11 +151,12 @@ static int vmap_pud_range(pgd_t *pgd, unsigned long addr,
  *
  * Ie. pte at addr+N*PAGE_SIZE shall point to pfn corresponding to pages[N]
  */
-static int vmap_page_range(unsigned long addr, unsigned long end,
+static int vmap_page_range(unsigned long start, unsigned long end,
                                pgprot_t prot, struct page **pages)
 {
        pgd_t *pgd;
        unsigned long next;
+       unsigned long addr = start;
        int err = 0;
        int nr = 0;
 
@@ -167,7 +168,7 @@ static int vmap_page_range(unsigned long addr, unsigned long end,
                if (err)
                        break;
        } while (pgd++, addr = next, addr != end);
-       flush_cache_vmap(addr, end);
+       flush_cache_vmap(start, end);
 
        if (unlikely(err))
                return err;
index 62e7f62fb559c7a09b5b15b4d7a0b3a7b5b4c5e5..d196f46c8808ea56734f12501d0e53968cc3f4eb 100644 (file)
@@ -1902,7 +1902,7 @@ static int kswapd(void *p)
        };
        node_to_cpumask_ptr(cpumask, pgdat->node_id);
 
-       if (!cpus_empty(*cpumask))
+       if (!cpumask_empty(cpumask))
                set_cpus_allowed_ptr(tsk, cpumask);
        current->reclaim_state = &reclaim_state;
 
@@ -2141,7 +2141,7 @@ static int __devinit cpu_callback(struct notifier_block *nfb,
                        pg_data_t *pgdat = NODE_DATA(nid);
                        node_to_cpumask_ptr(mask, pgdat->node_id);
 
-                       if (any_online_cpu(*mask) < nr_cpu_ids)
+                       if (cpumask_any_and(cpu_online_mask, mask) < nr_cpu_ids)
                                /* One of our CPUs online: restore mask */
                                set_cpus_allowed_ptr(pgdat->kswapd, mask);
                }
index c3ccfda23adc56abafb58abbcc31b33c5588ce4d..91149746bb8d6c94ac036879bbe557551630a1e1 100644 (file)
@@ -20,7 +20,7 @@
 DEFINE_PER_CPU(struct vm_event_state, vm_event_states) = {{0}};
 EXPORT_PER_CPU_SYMBOL(vm_event_states);
 
-static void sum_vm_events(unsigned long *ret, cpumask_t *cpumask)
+static void sum_vm_events(unsigned long *ret, const struct cpumask *cpumask)
 {
        int cpu;
        int i;
@@ -43,7 +43,7 @@ static void sum_vm_events(unsigned long *ret, cpumask_t *cpumask)
 void all_vm_events(unsigned long *ret)
 {
        get_online_cpus();
-       sum_vm_events(ret, &cpu_online_map);
+       sum_vm_events(ret, cpu_online_mask);
        put_online_cpus();
 }
 EXPORT_SYMBOL_GPL(all_vm_events);
index da0d426c0ce473f53450c65690a7bfe4a3e79f42..6248ae2502c765d1bf263059d2f58baffab930a6 100644 (file)
@@ -70,7 +70,7 @@
 
 #define CAN_BCM_VERSION CAN_VERSION
 static __initdata const char banner[] = KERN_INFO
-       "can: broadcast manager protocol (rev " CAN_BCM_VERSION ")\n";
+       "can: broadcast manager protocol (rev " CAN_BCM_VERSION " t)\n";
 
 MODULE_DESCRIPTION("PF_CAN broadcast manager protocol");
 MODULE_LICENSE("Dual BSD/GPL");
@@ -90,6 +90,7 @@ struct bcm_op {
        unsigned long frames_abs, frames_filtered;
        struct timeval ival1, ival2;
        struct hrtimer timer, thrtimer;
+       struct tasklet_struct tsklet, thrtsklet;
        ktime_t rx_stamp, kt_ival1, kt_ival2, kt_lastmsg;
        int rx_ifindex;
        int count;
@@ -341,6 +342,23 @@ static void bcm_send_to_user(struct bcm_op *op, struct bcm_msg_head *head,
        }
 }
 
+static void bcm_tx_timeout_tsklet(unsigned long data)
+{
+       struct bcm_op *op = (struct bcm_op *)data;
+       struct bcm_msg_head msg_head;
+
+       /* create notification to user */
+       msg_head.opcode  = TX_EXPIRED;
+       msg_head.flags   = op->flags;
+       msg_head.count   = op->count;
+       msg_head.ival1   = op->ival1;
+       msg_head.ival2   = op->ival2;
+       msg_head.can_id  = op->can_id;
+       msg_head.nframes = 0;
+
+       bcm_send_to_user(op, &msg_head, NULL, 0);
+}
+
 /*
  * bcm_tx_timeout_handler - performes cyclic CAN frame transmissions
  */
@@ -352,20 +370,8 @@ static enum hrtimer_restart bcm_tx_timeout_handler(struct hrtimer *hrtimer)
        if (op->kt_ival1.tv64 && (op->count > 0)) {
 
                op->count--;
-               if (!op->count && (op->flags & TX_COUNTEVT)) {
-                       struct bcm_msg_head msg_head;
-
-                       /* create notification to user */
-                       msg_head.opcode  = TX_EXPIRED;
-                       msg_head.flags   = op->flags;
-                       msg_head.count   = op->count;
-                       msg_head.ival1   = op->ival1;
-                       msg_head.ival2   = op->ival2;
-                       msg_head.can_id  = op->can_id;
-                       msg_head.nframes = 0;
-
-                       bcm_send_to_user(op, &msg_head, NULL, 0);
-               }
+               if (!op->count && (op->flags & TX_COUNTEVT))
+                       tasklet_schedule(&op->tsklet);
        }
 
        if (op->kt_ival1.tv64 && (op->count > 0)) {
@@ -402,6 +408,9 @@ static void bcm_rx_changed(struct bcm_op *op, struct can_frame *data)
        if (op->frames_filtered > ULONG_MAX/100)
                op->frames_filtered = op->frames_abs = 0;
 
+       /* this element is not throttled anymore */
+       data->can_dlc &= (BCM_CAN_DLC_MASK|RX_RECV);
+
        head.opcode  = RX_CHANGED;
        head.flags   = op->flags;
        head.count   = op->count;
@@ -420,37 +429,32 @@ static void bcm_rx_changed(struct bcm_op *op, struct can_frame *data)
  */
 static void bcm_rx_update_and_send(struct bcm_op *op,
                                   struct can_frame *lastdata,
-                                  struct can_frame *rxdata)
+                                  const struct can_frame *rxdata)
 {
        memcpy(lastdata, rxdata, CFSIZ);
 
-       /* mark as used */
-       lastdata->can_dlc |= RX_RECV;
+       /* mark as used and throttled by default */
+       lastdata->can_dlc |= (RX_RECV|RX_THR);
 
-       /* throtteling mode inactive OR data update already on the run ? */
-       if (!op->kt_ival2.tv64 || hrtimer_callback_running(&op->thrtimer)) {
+       /* throtteling mode inactive ? */
+       if (!op->kt_ival2.tv64) {
                /* send RX_CHANGED to the user immediately */
-               bcm_rx_changed(op, rxdata);
+               bcm_rx_changed(op, lastdata);
                return;
        }
 
-       if (hrtimer_active(&op->thrtimer)) {
-               /* mark as 'throttled' */
-               lastdata->can_dlc |= RX_THR;
+       /* with active throttling timer we are just done here */
+       if (hrtimer_active(&op->thrtimer))
                return;
-       }
 
-       if (!op->kt_lastmsg.tv64) {
-               /* send first RX_CHANGED to the user immediately */
-               bcm_rx_changed(op, rxdata);
-               op->kt_lastmsg = ktime_get();
-               return;
-       }
+       /* first receiption with enabled throttling mode */
+       if (!op->kt_lastmsg.tv64)
+               goto rx_changed_settime;
 
+       /* got a second frame inside a potential throttle period? */
        if (ktime_us_delta(ktime_get(), op->kt_lastmsg) <
            ktime_to_us(op->kt_ival2)) {
-               /* mark as 'throttled' and start timer */
-               lastdata->can_dlc |= RX_THR;
+               /* do not send the saved data - only start throttle timer */
                hrtimer_start(&op->thrtimer,
                              ktime_add(op->kt_lastmsg, op->kt_ival2),
                              HRTIMER_MODE_ABS);
@@ -458,7 +462,8 @@ static void bcm_rx_update_and_send(struct bcm_op *op,
        }
 
        /* the gap was that big, that throttling was not needed here */
-       bcm_rx_changed(op, rxdata);
+rx_changed_settime:
+       bcm_rx_changed(op, lastdata);
        op->kt_lastmsg = ktime_get();
 }
 
@@ -467,7 +472,7 @@ static void bcm_rx_update_and_send(struct bcm_op *op,
  *                       received data stored in op->last_frames[]
  */
 static void bcm_rx_cmp_to_index(struct bcm_op *op, int index,
-                               struct can_frame *rxdata)
+                               const struct can_frame *rxdata)
 {
        /*
         * no one uses the MSBs of can_dlc for comparation,
@@ -511,14 +516,12 @@ static void bcm_rx_starttimer(struct bcm_op *op)
                hrtimer_start(&op->timer, op->kt_ival1, HRTIMER_MODE_REL);
 }
 
-/*
- * bcm_rx_timeout_handler - when the (cyclic) CAN frame receiption timed out
- */
-static enum hrtimer_restart bcm_rx_timeout_handler(struct hrtimer *hrtimer)
+static void bcm_rx_timeout_tsklet(unsigned long data)
 {
-       struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer);
+       struct bcm_op *op = (struct bcm_op *)data;
        struct bcm_msg_head msg_head;
 
+       /* create notification to user */
        msg_head.opcode  = RX_TIMEOUT;
        msg_head.flags   = op->flags;
        msg_head.count   = op->count;
@@ -528,6 +531,17 @@ static enum hrtimer_restart bcm_rx_timeout_handler(struct hrtimer *hrtimer)
        msg_head.nframes = 0;
 
        bcm_send_to_user(op, &msg_head, NULL, 0);
+}
+
+/*
+ * bcm_rx_timeout_handler - when the (cyclic) CAN frame receiption timed out
+ */
+static enum hrtimer_restart bcm_rx_timeout_handler(struct hrtimer *hrtimer)
+{
+       struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer);
+
+       /* schedule before NET_RX_SOFTIRQ */
+       tasklet_hi_schedule(&op->tsklet);
 
        /* no restart of the timer is done here! */
 
@@ -540,10 +554,26 @@ static enum hrtimer_restart bcm_rx_timeout_handler(struct hrtimer *hrtimer)
        return HRTIMER_NORESTART;
 }
 
+/*
+ * bcm_rx_do_flush - helper for bcm_rx_thr_flush
+ */
+static inline int bcm_rx_do_flush(struct bcm_op *op, int update, int index)
+{
+       if ((op->last_frames) && (op->last_frames[index].can_dlc & RX_THR)) {
+               if (update)
+                       bcm_rx_changed(op, &op->last_frames[index]);
+               return 1;
+       }
+       return 0;
+}
+
 /*
  * bcm_rx_thr_flush - Check for throttled data and send it to the userspace
+ *
+ * update == 0 : just check if throttled data is available  (any irq context)
+ * update == 1 : check and send throttled data to userspace (soft_irq context)
  */
-static int bcm_rx_thr_flush(struct bcm_op *op)
+static int bcm_rx_thr_flush(struct bcm_op *op, int update)
 {
        int updated = 0;
 
@@ -551,27 +581,25 @@ static int bcm_rx_thr_flush(struct bcm_op *op)
                int i;
 
                /* for MUX filter we start at index 1 */
-               for (i = 1; i < op->nframes; i++) {
-                       if ((op->last_frames) &&
-                           (op->last_frames[i].can_dlc & RX_THR)) {
-                               op->last_frames[i].can_dlc &= ~RX_THR;
-                               bcm_rx_changed(op, &op->last_frames[i]);
-                               updated++;
-                       }
-               }
+               for (i = 1; i < op->nframes; i++)
+                       updated += bcm_rx_do_flush(op, update, i);
 
        } else {
                /* for RX_FILTER_ID and simple filter */
-               if (op->last_frames && (op->last_frames[0].can_dlc & RX_THR)) {
-                       op->last_frames[0].can_dlc &= ~RX_THR;
-                       bcm_rx_changed(op, &op->last_frames[0]);
-                       updated++;
-               }
+               updated += bcm_rx_do_flush(op, update, 0);
        }
 
        return updated;
 }
 
+static void bcm_rx_thr_tsklet(unsigned long data)
+{
+       struct bcm_op *op = (struct bcm_op *)data;
+
+       /* push the changed data to the userspace */
+       bcm_rx_thr_flush(op, 1);
+}
+
 /*
  * bcm_rx_thr_handler - the time for blocked content updates is over now:
  *                      Check for throttled data and send it to the userspace
@@ -580,7 +608,9 @@ static enum hrtimer_restart bcm_rx_thr_handler(struct hrtimer *hrtimer)
 {
        struct bcm_op *op = container_of(hrtimer, struct bcm_op, thrtimer);
 
-       if (bcm_rx_thr_flush(op)) {
+       tasklet_schedule(&op->thrtsklet);
+
+       if (bcm_rx_thr_flush(op, 0)) {
                hrtimer_forward(hrtimer, ktime_get(), op->kt_ival2);
                return HRTIMER_RESTART;
        } else {
@@ -596,48 +626,38 @@ static enum hrtimer_restart bcm_rx_thr_handler(struct hrtimer *hrtimer)
 static void bcm_rx_handler(struct sk_buff *skb, void *data)
 {
        struct bcm_op *op = (struct bcm_op *)data;
-       struct can_frame rxframe;
+       const struct can_frame *rxframe = (struct can_frame *)skb->data;
        int i;
 
        /* disable timeout */
        hrtimer_cancel(&op->timer);
 
-       if (skb->len == sizeof(rxframe)) {
-               memcpy(&rxframe, skb->data, sizeof(rxframe));
-               /* save rx timestamp */
-               op->rx_stamp = skb->tstamp;
-               /* save originator for recvfrom() */
-               op->rx_ifindex = skb->dev->ifindex;
-               /* update statistics */
-               op->frames_abs++;
-               kfree_skb(skb);
+       if (op->can_id != rxframe->can_id)
+               goto rx_freeskb;
 
-       } else {
-               kfree_skb(skb);
-               return;
-       }
-
-       if (op->can_id != rxframe.can_id)
-               return;
+       /* save rx timestamp */
+       op->rx_stamp = skb->tstamp;
+       /* save originator for recvfrom() */
+       op->rx_ifindex = skb->dev->ifindex;
+       /* update statistics */
+       op->frames_abs++;
 
        if (op->flags & RX_RTR_FRAME) {
                /* send reply for RTR-request (placed in op->frames[0]) */
                bcm_can_tx(op);
-               return;
+               goto rx_freeskb;
        }
 
        if (op->flags & RX_FILTER_ID) {
                /* the easiest case */
-               bcm_rx_update_and_send(op, &op->last_frames[0], &rxframe);
-               bcm_rx_starttimer(op);
-               return;
+               bcm_rx_update_and_send(op, &op->last_frames[0], rxframe);
+               goto rx_freeskb_starttimer;
        }
 
        if (op->nframes == 1) {
                /* simple compare with index 0 */
-               bcm_rx_cmp_to_index(op, 0, &rxframe);
-               bcm_rx_starttimer(op);
-               return;
+               bcm_rx_cmp_to_index(op, 0, rxframe);
+               goto rx_freeskb_starttimer;
        }
 
        if (op->nframes > 1) {
@@ -649,15 +669,19 @@ static void bcm_rx_handler(struct sk_buff *skb, void *data)
                 */
 
                for (i = 1; i < op->nframes; i++) {
-                       if ((GET_U64(&op->frames[0]) & GET_U64(&rxframe)) ==
+                       if ((GET_U64(&op->frames[0]) & GET_U64(rxframe)) ==
                            (GET_U64(&op->frames[0]) &
                             GET_U64(&op->frames[i]))) {
-                               bcm_rx_cmp_to_index(op, i, &rxframe);
+                               bcm_rx_cmp_to_index(op, i, rxframe);
                                break;
                        }
                }
-               bcm_rx_starttimer(op);
        }
+
+rx_freeskb_starttimer:
+       bcm_rx_starttimer(op);
+rx_freeskb:
+       kfree_skb(skb);
 }
 
 /*
@@ -681,6 +705,12 @@ static void bcm_remove_op(struct bcm_op *op)
        hrtimer_cancel(&op->timer);
        hrtimer_cancel(&op->thrtimer);
 
+       if (op->tsklet.func)
+               tasklet_kill(&op->tsklet);
+
+       if (op->thrtsklet.func)
+               tasklet_kill(&op->thrtsklet);
+
        if ((op->frames) && (op->frames != &op->sframe))
                kfree(op->frames);
 
@@ -891,6 +921,10 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
                hrtimer_init(&op->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
                op->timer.function = bcm_tx_timeout_handler;
 
+               /* initialize tasklet for tx countevent notification */
+               tasklet_init(&op->tsklet, bcm_tx_timeout_tsklet,
+                            (unsigned long) op);
+
                /* currently unused in tx_ops */
                hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 
@@ -1054,9 +1088,17 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
                hrtimer_init(&op->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
                op->timer.function = bcm_rx_timeout_handler;
 
+               /* initialize tasklet for rx timeout notification */
+               tasklet_init(&op->tsklet, bcm_rx_timeout_tsklet,
+                            (unsigned long) op);
+
                hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
                op->thrtimer.function = bcm_rx_thr_handler;
 
+               /* initialize tasklet for rx throttle handling */
+               tasklet_init(&op->thrtsklet, bcm_rx_thr_tsklet,
+                            (unsigned long) op);
+
                /* add this bcm_op to the list of the rx_ops */
                list_add(&op->list, &bo->rx_ops);
 
@@ -1102,7 +1144,7 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
                         */
                        op->kt_lastmsg = ktime_set(0, 0);
                        hrtimer_cancel(&op->thrtimer);
-                       bcm_rx_thr_flush(op);
+                       bcm_rx_thr_flush(op, 1);
                }
 
                if ((op->flags & STARTTIMER) && op->kt_ival1.tv64)
index 09c66a449da6c7c72c1bca4bfb8e392281d84bbb..382df6c09eecece6771b09a9e3fa93315798728b 100644 (file)
 /* Instead of increasing this, you should create a hash table. */
 #define MAX_GRO_SKBS 8
 
+/* This should be increased if a protocol with a bigger head is added. */
+#define GRO_MAX_HEAD (MAX_HEADER + 128)
+
 /*
  *     The list of packet types we will receive (as opposed to discard)
  *     and the routines to invoke.
@@ -2345,7 +2348,7 @@ static int napi_gro_complete(struct sk_buff *skb)
        struct list_head *head = &ptype_base[ntohs(type) & PTYPE_HASH_MASK];
        int err = -ENOENT;
 
-       if (!skb_shinfo(skb)->frag_list)
+       if (NAPI_GRO_CB(skb)->count == 1)
                goto out;
 
        rcu_read_lock();
@@ -2365,6 +2368,7 @@ static int napi_gro_complete(struct sk_buff *skb)
        }
 
 out:
+       skb_shinfo(skb)->gso_size = 0;
        __skb_push(skb, -skb_network_offset(skb));
        return netif_receive_skb(skb);
 }
@@ -2383,7 +2387,7 @@ void napi_gro_flush(struct napi_struct *napi)
 }
 EXPORT_SYMBOL(napi_gro_flush);
 
-int napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
+static int __napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
 {
        struct sk_buff **pp = NULL;
        struct packet_type *ptype;
@@ -2392,6 +2396,7 @@ int napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
        int count = 0;
        int same_flow;
        int mac_len;
+       int free;
 
        if (!(skb->dev->features & NETIF_F_GRO))
                goto normal;
@@ -2408,6 +2413,7 @@ int napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
                skb->mac_len = mac_len;
                NAPI_GRO_CB(skb)->same_flow = 0;
                NAPI_GRO_CB(skb)->flush = 0;
+               NAPI_GRO_CB(skb)->free = 0;
 
                for (p = napi->gro_list; p; p = p->next) {
                        count++;
@@ -2427,6 +2433,7 @@ int napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
                goto normal;
 
        same_flow = NAPI_GRO_CB(skb)->same_flow;
+       free = NAPI_GRO_CB(skb)->free;
 
        if (pp) {
                struct sk_buff *nskb = *pp;
@@ -2446,17 +2453,91 @@ int napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
        }
 
        NAPI_GRO_CB(skb)->count = 1;
+       skb_shinfo(skb)->gso_size = skb->len;
        skb->next = napi->gro_list;
        napi->gro_list = skb;
 
 ok:
-       return NET_RX_SUCCESS;
+       return free;
 
 normal:
-       return netif_receive_skb(skb);
+       return -1;
+}
+
+int napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
+{
+       switch (__napi_gro_receive(napi, skb)) {
+       case -1:
+               return netif_receive_skb(skb);
+
+       case 1:
+               kfree_skb(skb);
+               break;
+       }
+
+       return NET_RX_SUCCESS;
 }
 EXPORT_SYMBOL(napi_gro_receive);
 
+int napi_gro_frags(struct napi_struct *napi, struct napi_gro_fraginfo *info)
+{
+       struct net_device *dev = napi->dev;
+       struct sk_buff *skb = napi->skb;
+       int err = NET_RX_DROP;
+
+       napi->skb = NULL;
+
+       if (!skb) {
+               skb = netdev_alloc_skb(dev, GRO_MAX_HEAD + NET_IP_ALIGN);
+               if (!skb)
+                       goto out;
+
+               skb_reserve(skb, NET_IP_ALIGN);
+       }
+
+       BUG_ON(info->nr_frags > MAX_SKB_FRAGS);
+       skb_shinfo(skb)->nr_frags = info->nr_frags;
+       memcpy(skb_shinfo(skb)->frags, info->frags, sizeof(info->frags));
+
+       skb->data_len = info->len;
+       skb->len += info->len;
+       skb->truesize += info->len;
+
+       if (!pskb_may_pull(skb, ETH_HLEN))
+               goto reuse;
+
+       err = NET_RX_SUCCESS;
+
+       skb->protocol = eth_type_trans(skb, dev);
+
+       skb->ip_summed = info->ip_summed;
+       skb->csum = info->csum;
+
+       switch (__napi_gro_receive(napi, skb)) {
+       case -1:
+               return netif_receive_skb(skb);
+
+       case 0:
+               goto out;
+       }
+
+reuse:
+       skb_shinfo(skb)->nr_frags = 0;
+
+       skb->len -= skb->data_len;
+       skb->truesize -= skb->data_len;
+       skb->data_len = 0;
+
+       __skb_pull(skb, skb_headlen(skb));
+       skb_reserve(skb, NET_IP_ALIGN - skb_headroom(skb));
+
+       napi->skb = skb;
+
+out:
+       return err;
+}
+EXPORT_SYMBOL(napi_gro_frags);
+
 static int process_backlog(struct napi_struct *napi, int quota)
 {
        int work = 0;
@@ -2535,11 +2616,12 @@ void netif_napi_add(struct net_device *dev, struct napi_struct *napi,
 {
        INIT_LIST_HEAD(&napi->poll_list);
        napi->gro_list = NULL;
+       napi->skb = NULL;
        napi->poll = poll;
        napi->weight = weight;
        list_add(&napi->dev_list, &dev->napi_list);
-#ifdef CONFIG_NETPOLL
        napi->dev = dev;
+#ifdef CONFIG_NETPOLL
        spin_lock_init(&napi->poll_lock);
        napi->poll_owner = -1;
 #endif
@@ -2552,6 +2634,7 @@ void netif_napi_del(struct napi_struct *napi)
        struct sk_buff *skb, *next;
 
        list_del_init(&napi->dev_list);
+       kfree(napi->skb);
 
        for (skb = napi->gro_list; skb; skb = next) {
                next = skb->next;
index b8d0abb264334d6d5589d107c8cf4007e393ffd4..5110b359c758c2e8abe7d13e5f63f90269fbbd5e 100644 (file)
@@ -2594,6 +2594,17 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
 
        if (skb_shinfo(p)->frag_list)
                goto merge;
+       else if (!skb_headlen(p) && !skb_headlen(skb) &&
+                skb_shinfo(p)->nr_frags + skb_shinfo(skb)->nr_frags <
+                MAX_SKB_FRAGS) {
+               memcpy(skb_shinfo(p)->frags + skb_shinfo(p)->nr_frags,
+                      skb_shinfo(skb)->frags,
+                      skb_shinfo(skb)->nr_frags * sizeof(skb_frag_t));
+
+               skb_shinfo(p)->nr_frags += skb_shinfo(skb)->nr_frags;
+               NAPI_GRO_CB(skb)->free = 1;
+               goto done;
+       }
 
        headroom = skb_headroom(p);
        nskb = netdev_alloc_skb(p->dev, headroom);
@@ -2613,6 +2624,7 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
 
        *NAPI_GRO_CB(nskb) = *NAPI_GRO_CB(p);
        skb_shinfo(nskb)->frag_list = p;
+       skb_shinfo(nskb)->gso_size = skb_shinfo(p)->gso_size;
        skb_header_release(p);
        nskb->prev = p;
 
@@ -2627,11 +2639,12 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
        p = nskb;
 
 merge:
-       NAPI_GRO_CB(p)->count++;
        p->prev->next = skb;
        p->prev = skb;
        skb_header_release(skb);
 
+done:
+       NAPI_GRO_CB(p)->count++;
        p->data_len += skb->len;
        p->truesize += skb->len;
        p->len += skb->len;
index 5dbfe5fdc0d63970071945a1059d5032281071ed..8379496de82b92fe298d808981bf55edb9a50a05 100644 (file)
@@ -191,7 +191,7 @@ static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid,
        return 0;
 nlmsg_failure:
 err:
-       kfree(dcbnl_skb);
+       kfree_skb(dcbnl_skb);
        return ret;
 }
 
@@ -272,7 +272,7 @@ static int dcbnl_getpfccfg(struct net_device *netdev, struct nlattr **tb,
        return 0;
 nlmsg_failure:
 err:
-       kfree(dcbnl_skb);
+       kfree_skb(dcbnl_skb);
 err_out:
        return -EINVAL;
 }
@@ -314,7 +314,7 @@ static int dcbnl_getperm_hwaddr(struct net_device *netdev, struct nlattr **tb,
 
 nlmsg_failure:
 err:
-       kfree(dcbnl_skb);
+       kfree_skb(dcbnl_skb);
 err_out:
        return -EINVAL;
 }
@@ -380,7 +380,7 @@ static int dcbnl_getcap(struct net_device *netdev, struct nlattr **tb,
        return 0;
 nlmsg_failure:
 err:
-       kfree(dcbnl_skb);
+       kfree_skb(dcbnl_skb);
 err_out:
        return -EINVAL;
 }
@@ -458,7 +458,7 @@ static int dcbnl_getnumtcs(struct net_device *netdev, struct nlattr **tb,
        return 0;
 nlmsg_failure:
 err:
-       kfree(dcbnl_skb);
+       kfree_skb(dcbnl_skb);
 err_out:
        return ret;
 }
@@ -687,7 +687,7 @@ err_pg:
        nla_nest_cancel(dcbnl_skb, pg_nest);
 nlmsg_failure:
 err:
-       kfree(dcbnl_skb);
+       kfree_skb(dcbnl_skb);
 err_out:
        ret  = -EINVAL;
        return ret;
@@ -949,7 +949,7 @@ err_bcn:
        nla_nest_cancel(dcbnl_skb, bcn_nest);
 nlmsg_failure:
 err:
-       kfree(dcbnl_skb);
+       kfree_skb(dcbnl_skb);
 err_out:
        ret  = -EINVAL;
        return ret;
index 7aa2a7acc7ec815ab34f7d35df05425bd8765e2a..ad6dffd9070e3ce818f2e85261b2bac2fca55e36 100644 (file)
@@ -1,7 +1,6 @@
 menuconfig IP_DCCP
        tristate "The DCCP Protocol (EXPERIMENTAL)"
        depends on INET && EXPERIMENTAL
-       select IP_DCCP_CCID2
        ---help---
          Datagram Congestion Control Protocol (RFC 4340)
 
@@ -25,9 +24,6 @@ config INET_DCCP_DIAG
        def_tristate y if (IP_DCCP = y && INET_DIAG = y)
        def_tristate m
 
-config IP_DCCP_ACKVEC
-       bool
-
 source "net/dccp/ccids/Kconfig"
 
 menu "DCCP Kernel Hacking"
index f4f8793aafffe3bf03d7c28d340445b8e4082bb0..2991efcc8deab0137acd4454ea09780a52d79a1a 100644 (file)
@@ -2,14 +2,23 @@ obj-$(CONFIG_IP_DCCP) += dccp.o dccp_ipv4.o
 
 dccp-y := ccid.o feat.o input.o minisocks.o options.o output.o proto.o timer.o
 
+#
+# CCID algorithms to be used by dccp.ko
+#
+# CCID-2 is default (RFC 4340, p. 77) and has Ack Vectors as dependency
+dccp-y += ccids/ccid2.o ackvec.o
+dccp-$(CONFIG_IP_DCCP_CCID3)   += ccids/ccid3.o
+dccp-$(CONFIG_IP_DCCP_TFRC_LIB) += ccids/lib/tfrc.o            \
+                                  ccids/lib/tfrc_equation.o    \
+                                  ccids/lib/packet_history.o   \
+                                  ccids/lib/loss_interval.o
+
 dccp_ipv4-y := ipv4.o
 
 # build dccp_ipv6 as module whenever either IPv6 or DCCP is a module
 obj-$(subst y,$(CONFIG_IP_DCCP),$(CONFIG_IPV6)) += dccp_ipv6.o
 dccp_ipv6-y := ipv6.o
 
-dccp-$(CONFIG_IP_DCCP_ACKVEC) += ackvec.o
-
 obj-$(CONFIG_INET_DCCP_DIAG) += dccp_diag.o
 obj-$(CONFIG_NET_DCCPPROBE) += dccp_probe.o
 
@@ -17,5 +26,3 @@ dccp-$(CONFIG_SYSCTL) += sysctl.o
 
 dccp_diag-y := diag.o
 dccp_probe-y := probe.o
-
-obj-y += ccids/
index 4ccee030524e403abac5cec98e340307937021b1..45f95e55f873f47674601a617b7d8284e8f0763f 100644 (file)
@@ -84,7 +84,6 @@ struct dccp_ackvec_record {
 struct sock;
 struct sk_buff;
 
-#ifdef CONFIG_IP_DCCP_ACKVEC
 extern int dccp_ackvec_init(void);
 extern void dccp_ackvec_exit(void);
 
@@ -106,52 +105,4 @@ static inline int dccp_ackvec_pending(const struct dccp_ackvec *av)
 {
        return av->av_vec_len;
 }
-#else /* CONFIG_IP_DCCP_ACKVEC */
-static inline int dccp_ackvec_init(void)
-{
-       return 0;
-}
-
-static inline void dccp_ackvec_exit(void)
-{
-}
-
-static inline struct dccp_ackvec *dccp_ackvec_alloc(const gfp_t priority)
-{
-       return NULL;
-}
-
-static inline void dccp_ackvec_free(struct dccp_ackvec *av)
-{
-}
-
-static inline int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk,
-                                 const u64 ackno, const u8 state)
-{
-       return -1;
-}
-
-static inline void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av,
-                                              struct sock *sk, const u64 ackno)
-{
-}
-
-static inline int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb,
-                                   const u64 *ackno, const u8 opt,
-                                   const u8 *value, const u8 len)
-{
-       return -1;
-}
-
-static inline int dccp_insert_option_ackvec(const struct sock *sk,
-                                           const struct sk_buff *skb)
-{
-       return -1;
-}
-
-static inline int dccp_ackvec_pending(const struct dccp_ackvec *av)
-{
-       return 0;
-}
-#endif /* CONFIG_IP_DCCP_ACKVEC */
 #endif /* _ACKVEC_H */
index bcc643f992aeb6c70ed218ebb7248e9a072ea758..f3e9ba1cfd01479b222720359a142547786c0cca 100644 (file)
  */
 
 #include "ccid.h"
+#include "ccids/lib/tfrc.h"
 
-static u8 builtin_ccids[] = {
-       DCCPC_CCID2,            /* CCID2 is supported by default */
-#if defined(CONFIG_IP_DCCP_CCID3) || defined(CONFIG_IP_DCCP_CCID3_MODULE)
-       DCCPC_CCID3,
+static struct ccid_operations *ccids[] = {
+       &ccid2_ops,
+#ifdef CONFIG_IP_DCCP_CCID3
+       &ccid3_ops,
 #endif
 };
 
-static struct ccid_operations *ccids[CCID_MAX];
-#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
-static atomic_t ccids_lockct = ATOMIC_INIT(0);
-static DEFINE_SPINLOCK(ccids_lock);
-
-/*
- * The strategy is: modifications ccids vector are short, do not sleep and
- * veeery rare, but read access should be free of any exclusive locks.
- */
-static void ccids_write_lock(void)
+static struct ccid_operations *ccid_by_number(const u8 id)
 {
-       spin_lock(&ccids_lock);
-       while (atomic_read(&ccids_lockct) != 0) {
-               spin_unlock(&ccids_lock);
-               yield();
-               spin_lock(&ccids_lock);
-       }
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(ccids); i++)
+               if (ccids[i]->ccid_id == id)
+                       return ccids[i];
+       return NULL;
 }
 
-static inline void ccids_write_unlock(void)
+/* check that up to @array_len members in @ccid_array are supported */
+bool ccid_support_check(u8 const *ccid_array, u8 array_len)
 {
-       spin_unlock(&ccids_lock);
+       while (array_len > 0)
+               if (ccid_by_number(ccid_array[--array_len]) == NULL)
+                       return false;
+       return true;
 }
 
-static inline void ccids_read_lock(void)
+/**
+ * ccid_get_builtin_ccids  -  Populate a list of built-in CCIDs
+ * @ccid_array: pointer to copy into
+ * @array_len: value to return length into
+ * This function allocates memory - caller must see that it is freed after use.
+ */
+int ccid_get_builtin_ccids(u8 **ccid_array, u8 *array_len)
 {
-       atomic_inc(&ccids_lockct);
-       smp_mb__after_atomic_inc();
-       spin_unlock_wait(&ccids_lock);
+       *ccid_array = kmalloc(ARRAY_SIZE(ccids), gfp_any());
+       if (*ccid_array == NULL)
+               return -ENOBUFS;
+
+       for (*array_len = 0; *array_len < ARRAY_SIZE(ccids); *array_len += 1)
+               (*ccid_array)[*array_len] = ccids[*array_len]->ccid_id;
+       return 0;
 }
 
-static inline void ccids_read_unlock(void)
+int ccid_getsockopt_builtin_ccids(struct sock *sk, int len,
+                                 char __user *optval, int __user *optlen)
 {
-       atomic_dec(&ccids_lockct);
-}
+       u8 *ccid_array, array_len;
+       int err = 0;
 
-#else
-#define ccids_write_lock() do { } while(0)
-#define ccids_write_unlock() do { } while(0)
-#define ccids_read_lock() do { } while(0)
-#define ccids_read_unlock() do { } while(0)
-#endif
+       if (len < ARRAY_SIZE(ccids))
+               return -EINVAL;
+
+       if (ccid_get_builtin_ccids(&ccid_array, &array_len))
+               return -ENOBUFS;
+
+       if (put_user(array_len, optlen) ||
+           copy_to_user(optval, ccid_array, array_len))
+               err = -EFAULT;
+
+       kfree(ccid_array);
+       return err;
+}
 
 static struct kmem_cache *ccid_kmem_cache_create(int obj_size, const char *fmt,...)
 {
@@ -93,48 +107,7 @@ static void ccid_kmem_cache_destroy(struct kmem_cache *slab)
        }
 }
 
-/* check that up to @array_len members in @ccid_array are supported */
-bool ccid_support_check(u8 const *ccid_array, u8 array_len)
-{
-       u8 i, j, found;
-
-       for (i = 0, found = 0; i < array_len; i++, found = 0) {
-               for (j = 0; !found && j < ARRAY_SIZE(builtin_ccids); j++)
-                       found = (ccid_array[i] == builtin_ccids[j]);
-               if (!found)
-                       return false;
-       }
-       return true;
-}
-
-/**
- * ccid_get_builtin_ccids  -  Provide copy of `builtin' CCID array
- * @ccid_array: pointer to copy into
- * @array_len: value to return length into
- * This function allocates memory - caller must see that it is freed after use.
- */
-int ccid_get_builtin_ccids(u8 **ccid_array, u8 *array_len)
-{
-       *ccid_array = kmemdup(builtin_ccids, sizeof(builtin_ccids), gfp_any());
-       if (*ccid_array == NULL)
-               return -ENOBUFS;
-       *array_len = ARRAY_SIZE(builtin_ccids);
-       return 0;
-}
-
-int ccid_getsockopt_builtin_ccids(struct sock *sk, int len,
-                                   char __user *optval, int __user *optlen)
-{
-       if (len < sizeof(builtin_ccids))
-               return -EINVAL;
-
-       if (put_user(sizeof(builtin_ccids), optlen) ||
-           copy_to_user(optval, builtin_ccids, sizeof(builtin_ccids)))
-               return -EFAULT;
-       return 0;
-}
-
-int ccid_register(struct ccid_operations *ccid_ops)
+static int ccid_activate(struct ccid_operations *ccid_ops)
 {
        int err = -ENOBUFS;
 
@@ -152,79 +125,40 @@ int ccid_register(struct ccid_operations *ccid_ops)
        if (ccid_ops->ccid_hc_tx_slab == NULL)
                goto out_free_rx_slab;
 
-       ccids_write_lock();
-       err = -EEXIST;
-       if (ccids[ccid_ops->ccid_id] == NULL) {
-               ccids[ccid_ops->ccid_id] = ccid_ops;
-               err = 0;
-       }
-       ccids_write_unlock();
-       if (err != 0)
-               goto out_free_tx_slab;
-
-       pr_info("CCID: Registered CCID %d (%s)\n",
+       pr_info("CCID: Activated CCID %d (%s)\n",
                ccid_ops->ccid_id, ccid_ops->ccid_name);
+       err = 0;
 out:
        return err;
-out_free_tx_slab:
-       ccid_kmem_cache_destroy(ccid_ops->ccid_hc_tx_slab);
-       ccid_ops->ccid_hc_tx_slab = NULL;
-       goto out;
 out_free_rx_slab:
        ccid_kmem_cache_destroy(ccid_ops->ccid_hc_rx_slab);
        ccid_ops->ccid_hc_rx_slab = NULL;
        goto out;
 }
 
-EXPORT_SYMBOL_GPL(ccid_register);
-
-int ccid_unregister(struct ccid_operations *ccid_ops)
+static void ccid_deactivate(struct ccid_operations *ccid_ops)
 {
-       ccids_write_lock();
-       ccids[ccid_ops->ccid_id] = NULL;
-       ccids_write_unlock();
-
        ccid_kmem_cache_destroy(ccid_ops->ccid_hc_tx_slab);
        ccid_ops->ccid_hc_tx_slab = NULL;
        ccid_kmem_cache_destroy(ccid_ops->ccid_hc_rx_slab);
        ccid_ops->ccid_hc_rx_slab = NULL;
 
-       pr_info("CCID: Unregistered CCID %d (%s)\n",
+       pr_info("CCID: Deactivated CCID %d (%s)\n",
                ccid_ops->ccid_id, ccid_ops->ccid_name);
-       return 0;
 }
 
-EXPORT_SYMBOL_GPL(ccid_unregister);
-
-struct ccid *ccid_new(unsigned char id, struct sock *sk, int rx, gfp_t gfp)
+struct ccid *ccid_new(const u8 id, struct sock *sk, bool rx)
 {
-       struct ccid_operations *ccid_ops;
+       struct ccid_operations *ccid_ops = ccid_by_number(id);
        struct ccid *ccid = NULL;
 
-       ccids_read_lock();
-#ifdef CONFIG_MODULES
-       if (ccids[id] == NULL) {
-               /* We only try to load if in process context */
-               ccids_read_unlock();
-               if (gfp & GFP_ATOMIC)
-                       goto out;
-               request_module("net-dccp-ccid-%d", id);
-               ccids_read_lock();
-       }
-#endif
-       ccid_ops = ccids[id];
        if (ccid_ops == NULL)
-               goto out_unlock;
-
-       if (!try_module_get(ccid_ops->ccid_owner))
-               goto out_unlock;
-
-       ccids_read_unlock();
+               goto out;
 
        ccid = kmem_cache_alloc(rx ? ccid_ops->ccid_hc_rx_slab :
-                                    ccid_ops->ccid_hc_tx_slab, gfp);
+                                    ccid_ops->ccid_hc_tx_slab, gfp_any());
        if (ccid == NULL)
-               goto out_module_put;
+               goto out;
        ccid->ccid_ops = ccid_ops;
        if (rx) {
                memset(ccid + 1, 0, ccid_ops->ccid_hc_rx_obj_size);
@@ -239,53 +173,57 @@ struct ccid *ccid_new(unsigned char id, struct sock *sk, int rx, gfp_t gfp)
        }
 out:
        return ccid;
-out_unlock:
-       ccids_read_unlock();
-       goto out;
 out_free_ccid:
        kmem_cache_free(rx ? ccid_ops->ccid_hc_rx_slab :
                        ccid_ops->ccid_hc_tx_slab, ccid);
        ccid = NULL;
-out_module_put:
-       module_put(ccid_ops->ccid_owner);
        goto out;
 }
 
-EXPORT_SYMBOL_GPL(ccid_new);
-
-static void ccid_delete(struct ccid *ccid, struct sock *sk, int rx)
+void ccid_hc_rx_delete(struct ccid *ccid, struct sock *sk)
 {
-       struct ccid_operations *ccid_ops;
-
-       if (ccid == NULL)
-               return;
-
-       ccid_ops = ccid->ccid_ops;
-       if (rx) {
-               if (ccid_ops->ccid_hc_rx_exit != NULL)
-                       ccid_ops->ccid_hc_rx_exit(sk);
-               kmem_cache_free(ccid_ops->ccid_hc_rx_slab,  ccid);
-       } else {
-               if (ccid_ops->ccid_hc_tx_exit != NULL)
-                       ccid_ops->ccid_hc_tx_exit(sk);
-               kmem_cache_free(ccid_ops->ccid_hc_tx_slab,  ccid);
+       if (ccid != NULL) {
+               if (ccid->ccid_ops->ccid_hc_rx_exit != NULL)
+                       ccid->ccid_ops->ccid_hc_rx_exit(sk);
+               kmem_cache_free(ccid->ccid_ops->ccid_hc_rx_slab, ccid);
        }
-       ccids_read_lock();
-       if (ccids[ccid_ops->ccid_id] != NULL)
-               module_put(ccid_ops->ccid_owner);
-       ccids_read_unlock();
 }
 
-void ccid_hc_rx_delete(struct ccid *ccid, struct sock *sk)
+void ccid_hc_tx_delete(struct ccid *ccid, struct sock *sk)
 {
-       ccid_delete(ccid, sk, 1);
+       if (ccid != NULL) {
+               if (ccid->ccid_ops->ccid_hc_tx_exit != NULL)
+                       ccid->ccid_ops->ccid_hc_tx_exit(sk);
+               kmem_cache_free(ccid->ccid_ops->ccid_hc_tx_slab, ccid);
+       }
 }
 
-EXPORT_SYMBOL_GPL(ccid_hc_rx_delete);
-
-void ccid_hc_tx_delete(struct ccid *ccid, struct sock *sk)
+int __init ccid_initialize_builtins(void)
 {
-       ccid_delete(ccid, sk, 0);
+       int i, err = tfrc_lib_init();
+
+       if (err)
+               return err;
+
+       for (i = 0; i < ARRAY_SIZE(ccids); i++) {
+               err = ccid_activate(ccids[i]);
+               if (err)
+                       goto unwind_registrations;
+       }
+       return 0;
+
+unwind_registrations:
+       while(--i >= 0)
+               ccid_deactivate(ccids[i]);
+       tfrc_lib_exit();
+       return err;
 }
 
-EXPORT_SYMBOL_GPL(ccid_hc_tx_delete);
+void ccid_cleanup_builtins(void)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(ccids); i++)
+               ccid_deactivate(ccids[i]);
+       tfrc_lib_exit();
+}
index 18f69423a7084fc929c359a5168d4250c5beb208..facedd20b531a0ce42fb03f5afccef290f11f7bc 100644 (file)
@@ -29,7 +29,6 @@ struct tcp_info;
  *  @ccid_id: numerical CCID ID (up to %CCID_MAX, cf. table 5 in RFC 4340, 10.)
  *  @ccid_ccmps: the CCMPS including network/transport headers (0 when disabled)
  *  @ccid_name: alphabetical identifier string for @ccid_id
- *  @ccid_owner: module which implements/owns this CCID
  *  @ccid_hc_{r,t}x_slab: memory pool for the receiver/sender half-connection
  *  @ccid_hc_{r,t}x_obj_size: size of the receiver/sender half-connection socket
  *
@@ -48,7 +47,6 @@ struct ccid_operations {
        unsigned char           ccid_id;
        __u32                   ccid_ccmps;
        const char              *ccid_name;
-       struct module           *ccid_owner;
        struct kmem_cache       *ccid_hc_rx_slab,
                                *ccid_hc_tx_slab;
        __u32                   ccid_hc_rx_obj_size,
@@ -90,8 +88,13 @@ struct ccid_operations {
                                                 int __user *optlen);
 };
 
-extern int ccid_register(struct ccid_operations *ccid_ops);
-extern int ccid_unregister(struct ccid_operations *ccid_ops);
+extern struct ccid_operations ccid2_ops;
+#ifdef CONFIG_IP_DCCP_CCID3
+extern struct ccid_operations ccid3_ops;
+#endif
+
+extern int  ccid_initialize_builtins(void);
+extern void ccid_cleanup_builtins(void);
 
 struct ccid {
        struct ccid_operations *ccid_ops;
@@ -108,8 +111,7 @@ extern int  ccid_get_builtin_ccids(u8 **ccid_array, u8 *array_len);
 extern int  ccid_getsockopt_builtin_ccids(struct sock *sk, int len,
                                          char __user *, int __user *);
 
-extern struct ccid *ccid_new(unsigned char id, struct sock *sk, int rx,
-                            gfp_t gfp);
+extern struct ccid *ccid_new(const u8 id, struct sock *sk, bool rx);
 
 static inline int ccid_get_current_rx_ccid(struct dccp_sock *dp)
 {
index 12275943eab8fae852664b3adba29ecb54415f24..b28bf962edc3799182f4ef1e0b3e5433c14ad115 100644 (file)
@@ -1,80 +1,51 @@
 menu "DCCP CCIDs Configuration (EXPERIMENTAL)"
        depends on EXPERIMENTAL
 
-config IP_DCCP_CCID2
-       tristate "CCID2 (TCP-Like) (EXPERIMENTAL)"
-       def_tristate IP_DCCP
-       select IP_DCCP_ACKVEC
-       ---help---
-         CCID 2, TCP-like Congestion Control, denotes Additive Increase,
-         Multiplicative Decrease (AIMD) congestion control with behavior
-         modelled directly on TCP, including congestion window, slow start,
-         timeouts, and so forth [RFC 2581].  CCID 2 achieves maximum
-         bandwidth over the long term, consistent with the use of end-to-end
-         congestion control, but halves its congestion window in response to
-         each congestion event.  This leads to the abrupt rate changes
-         typical of TCP.  Applications should use CCID 2 if they prefer
-         maximum bandwidth utilization to steadiness of rate.  This is often
-         the case for applications that are not playing their data directly
-         to the user.  For example, a hypothetical application that
-         transferred files over DCCP, using application-level retransmissions
-         for lost packets, would prefer CCID 2 to CCID 3.  On-line games may
-         also prefer CCID 2.  See RFC 4341 for further details.
-
-         CCID2 is the default CCID used by DCCP.
-
 config IP_DCCP_CCID2_DEBUG
-         bool "CCID2 debugging messages"
-         depends on IP_DCCP_CCID2
-         ---help---
-           Enable CCID2-specific debugging messages.
+       bool "CCID-2 debugging messages"
+       ---help---
+         Enable CCID-2 specific debugging messages.
 
-           When compiling CCID2 as a module, this debugging output can
-           additionally be toggled by setting the ccid2_debug module
-           parameter to 0 or 1.
+         The debugging output can additionally be toggled by setting the
+         ccid2_debug parameter to 0 or 1.
 
-           If in doubt, say N.
+         If in doubt, say N.
 
 config IP_DCCP_CCID3
-       tristate "CCID3 (TCP-Friendly) (EXPERIMENTAL)"
-       def_tristate IP_DCCP
-       select IP_DCCP_TFRC_LIB
+       bool "CCID-3 (TCP-Friendly) (EXPERIMENTAL)"
+       def_bool y if (IP_DCCP = y || IP_DCCP = m)
        ---help---
-         CCID 3 denotes TCP-Friendly Rate Control (TFRC), an equation-based
+         CCID-3 denotes TCP-Friendly Rate Control (TFRC), an equation-based
          rate-controlled congestion control mechanism.  TFRC is designed to
          be reasonably fair when competing for bandwidth with TCP-like flows,
          where a flow is "reasonably fair" if its sending rate is generally
          within a factor of two of the sending rate of a TCP flow under the
          same conditions.  However, TFRC has a much lower variation of
-         throughput over time compared with TCP, which makes CCID 3 more
-         suitable than CCID 2 for applications such streaming media where a
+         throughput over time compared with TCP, which makes CCID-3 more
+         suitable than CCID-2 for applications such streaming media where a
          relatively smooth sending rate is of importance.
 
-         CCID 3 is further described in RFC 4342,
+         CCID-3 is further described in RFC 4342,
          http://www.ietf.org/rfc/rfc4342.txt
 
          The TFRC congestion control algorithms were initially described in
-         RFC 3448.
+         RFC 5448.
 
          This text was extracted from RFC 4340 (sec. 10.2),
          http://www.ietf.org/rfc/rfc4340.txt
-         
-         To compile this CCID as a module, choose M here: the module will be
-         called dccp_ccid3.
 
-         If in doubt, say M.
+         If in doubt, say N.
 
 config IP_DCCP_CCID3_DEBUG
-         bool "CCID3 debugging messages"
-         depends on IP_DCCP_CCID3
-         ---help---
-           Enable CCID3-specific debugging messages.
+       bool "CCID-3 debugging messages"
+       depends on IP_DCCP_CCID3
+       ---help---
+         Enable CCID-3 specific debugging messages.
 
-           When compiling CCID3 as a module, this debugging output can
-           additionally be toggled by setting the ccid3_debug module
-           parameter to 0 or 1.
+         The debugging output can additionally be toggled by setting the
+         ccid3_debug parameter to 0 or 1.
 
-           If in doubt, say N.
+         If in doubt, say N.
 
 config IP_DCCP_CCID3_RTO
          int "Use higher bound for nofeedback timer"
@@ -108,12 +79,8 @@ config IP_DCCP_CCID3_RTO
            therefore not be performed on WANs.
 
 config IP_DCCP_TFRC_LIB
-       tristate
-       default n
+       def_bool y if IP_DCCP_CCID3
 
 config IP_DCCP_TFRC_DEBUG
-       bool
-       depends on IP_DCCP_TFRC_LIB
-       default y if IP_DCCP_CCID3_DEBUG
-
+       def_bool y if IP_DCCP_CCID3_DEBUG
 endmenu
diff --git a/net/dccp/ccids/Makefile b/net/dccp/ccids/Makefile
deleted file mode 100644 (file)
index 438f20b..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-obj-$(CONFIG_IP_DCCP_CCID3) += dccp_ccid3.o
-
-dccp_ccid3-y := ccid3.o
-
-obj-$(CONFIG_IP_DCCP_CCID2) += dccp_ccid2.o
-
-dccp_ccid2-y := ccid2.o
-
-obj-y += lib/
index c9ea19a4d85e10b0ba8c5a2a4d8c27b2496bc79b..d235294ace23b640960999a8dd2be995d82f1193 100644 (file)
@@ -768,10 +768,9 @@ static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
        }
 }
 
-static struct ccid_operations ccid2 = {
+struct ccid_operations ccid2_ops = {
        .ccid_id                = DCCPC_CCID2,
        .ccid_name              = "TCP-like",
-       .ccid_owner             = THIS_MODULE,
        .ccid_hc_tx_obj_size    = sizeof(struct ccid2_hc_tx_sock),
        .ccid_hc_tx_init        = ccid2_hc_tx_init,
        .ccid_hc_tx_exit        = ccid2_hc_tx_exit,
@@ -784,22 +783,5 @@ static struct ccid_operations ccid2 = {
 
 #ifdef CONFIG_IP_DCCP_CCID2_DEBUG
 module_param(ccid2_debug, bool, 0644);
-MODULE_PARM_DESC(ccid2_debug, "Enable debug messages");
+MODULE_PARM_DESC(ccid2_debug, "Enable CCID-2 debug messages");
 #endif
-
-static __init int ccid2_module_init(void)
-{
-       return ccid_register(&ccid2);
-}
-module_init(ccid2_module_init);
-
-static __exit void ccid2_module_exit(void)
-{
-       ccid_unregister(&ccid2);
-}
-module_exit(ccid2_module_exit);
-
-MODULE_AUTHOR("Andrea Bittau <a.bittau@cs.ucl.ac.uk>");
-MODULE_DESCRIPTION("DCCP TCP-Like (CCID2) CCID");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("net-dccp-ccid-2");
index 3b8bd7ca6761f2bded8aaae9bf21efa4cc8b2fac..a27b7f4c19c509ba5aaefd01b37935cc78600c20 100644 (file)
@@ -940,10 +940,9 @@ static int ccid3_hc_rx_getsockopt(struct sock *sk, const int optname, int len,
        return 0;
 }
 
-static struct ccid_operations ccid3 = {
+struct ccid_operations ccid3_ops = {
        .ccid_id                   = DCCPC_CCID3,
        .ccid_name                 = "TCP-Friendly Rate Control",
-       .ccid_owner                = THIS_MODULE,
        .ccid_hc_tx_obj_size       = sizeof(struct ccid3_hc_tx_sock),
        .ccid_hc_tx_init           = ccid3_hc_tx_init,
        .ccid_hc_tx_exit           = ccid3_hc_tx_exit,
@@ -964,23 +963,5 @@ static struct ccid_operations ccid3 = {
 
 #ifdef CONFIG_IP_DCCP_CCID3_DEBUG
 module_param(ccid3_debug, bool, 0644);
-MODULE_PARM_DESC(ccid3_debug, "Enable debug messages");
+MODULE_PARM_DESC(ccid3_debug, "Enable CCID-3 debug messages");
 #endif
-
-static __init int ccid3_module_init(void)
-{
-       return ccid_register(&ccid3);
-}
-module_init(ccid3_module_init);
-
-static __exit void ccid3_module_exit(void)
-{
-       ccid_unregister(&ccid3);
-}
-module_exit(ccid3_module_exit);
-
-MODULE_AUTHOR("Ian McDonald <ian.mcdonald@jandi.co.nz>, "
-             "Arnaldo Carvalho de Melo <acme@ghostprotocols.net>");
-MODULE_DESCRIPTION("DCCP TFRC CCID3 CCID");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("net-dccp-ccid-3");
diff --git a/net/dccp/ccids/lib/Makefile b/net/dccp/ccids/lib/Makefile
deleted file mode 100644 (file)
index 68c93e3..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_IP_DCCP_TFRC_LIB) += dccp_tfrc_lib.o
-
-dccp_tfrc_lib-y := tfrc.o tfrc_equation.o packet_history.o loss_interval.o
index 5b3ce0688c5c121a407cd8cc6680e0818313d90f..4d1e401272646c88789c9c0beb537718b3260708 100644 (file)
@@ -60,7 +60,6 @@ void tfrc_lh_cleanup(struct tfrc_loss_hist *lh)
                        lh->ring[LIH_INDEX(lh->counter)] = NULL;
                }
 }
-EXPORT_SYMBOL_GPL(tfrc_lh_cleanup);
 
 static void tfrc_lh_calc_i_mean(struct tfrc_loss_hist *lh)
 {
@@ -121,7 +120,6 @@ u8 tfrc_lh_update_i_mean(struct tfrc_loss_hist *lh, struct sk_buff *skb)
 
        return (lh->i_mean < old_i_mean);
 }
-EXPORT_SYMBOL_GPL(tfrc_lh_update_i_mean);
 
 /* Determine if `new_loss' does begin a new loss interval [RFC 4342, 10.2] */
 static inline u8 tfrc_lh_is_new_loss(struct tfrc_loss_interval *cur,
@@ -169,7 +167,6 @@ int tfrc_lh_interval_add(struct tfrc_loss_hist *lh, struct tfrc_rx_hist *rh,
        }
        return 1;
 }
-EXPORT_SYMBOL_GPL(tfrc_lh_interval_add);
 
 int __init tfrc_li_init(void)
 {
index 6cc108afdc3be594ddb6231b9fc4664de4a8c8da..b7785b3581ec2ee5a747ec3975d00496f6a42183 100644 (file)
@@ -94,7 +94,6 @@ int tfrc_tx_hist_add(struct tfrc_tx_hist_entry **headp, u64 seqno)
        *headp       = entry;
        return 0;
 }
-EXPORT_SYMBOL_GPL(tfrc_tx_hist_add);
 
 void tfrc_tx_hist_purge(struct tfrc_tx_hist_entry **headp)
 {
@@ -109,7 +108,6 @@ void tfrc_tx_hist_purge(struct tfrc_tx_hist_entry **headp)
 
        *headp = NULL;
 }
-EXPORT_SYMBOL_GPL(tfrc_tx_hist_purge);
 
 u32 tfrc_tx_hist_rtt(struct tfrc_tx_hist_entry *head, const u64 seqno,
                     const ktime_t now)
@@ -127,7 +125,6 @@ u32 tfrc_tx_hist_rtt(struct tfrc_tx_hist_entry *head, const u64 seqno,
 
        return rtt;
 }
-EXPORT_SYMBOL_GPL(tfrc_tx_hist_rtt);
 
 
 /*
@@ -172,7 +169,6 @@ void tfrc_rx_hist_add_packet(struct tfrc_rx_hist *h,
 
        tfrc_rx_hist_entry_from_skb(entry, skb, ndp);
 }
-EXPORT_SYMBOL_GPL(tfrc_rx_hist_add_packet);
 
 /* has the packet contained in skb been seen before? */
 int tfrc_rx_hist_duplicate(struct tfrc_rx_hist *h, struct sk_buff *skb)
@@ -189,7 +185,6 @@ int tfrc_rx_hist_duplicate(struct tfrc_rx_hist *h, struct sk_buff *skb)
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(tfrc_rx_hist_duplicate);
 
 static void tfrc_rx_hist_swap(struct tfrc_rx_hist *h, const u8 a, const u8 b)
 {
@@ -390,7 +385,6 @@ int tfrc_rx_handle_loss(struct tfrc_rx_hist *h,
        }
        return is_new_loss;
 }
-EXPORT_SYMBOL_GPL(tfrc_rx_handle_loss);
 
 int tfrc_rx_hist_alloc(struct tfrc_rx_hist *h)
 {
@@ -412,7 +406,6 @@ out_free:
        }
        return -ENOBUFS;
 }
-EXPORT_SYMBOL_GPL(tfrc_rx_hist_alloc);
 
 void tfrc_rx_hist_purge(struct tfrc_rx_hist *h)
 {
@@ -424,7 +417,6 @@ void tfrc_rx_hist_purge(struct tfrc_rx_hist *h)
                        h->ring[i] = NULL;
                }
 }
-EXPORT_SYMBOL_GPL(tfrc_rx_hist_purge);
 
 /**
  * tfrc_rx_hist_rtt_last_s - reference entry to compute RTT samples against
@@ -495,4 +487,3 @@ keep_ref_for_next_time:
 
        return sample;
 }
-EXPORT_SYMBOL_GPL(tfrc_rx_hist_sample_rtt);
index 185916218e07161ecec75fbd6095dfbfd32c23e0..60c412ccfeef4e6e527abc2f271b27f76abe7f01 100644 (file)
@@ -1,20 +1,18 @@
 /*
- * TFRC: main module holding the pieces of the TFRC library together
+ * TFRC library initialisation
  *
  * Copyright (c) 2007 The University of Aberdeen, Scotland, UK
  * Copyright (c) 2007 Arnaldo Carvalho de Melo <acme@redhat.com>
  */
-#include <linux/module.h>
-#include <linux/moduleparam.h>
 #include "tfrc.h"
 
 #ifdef CONFIG_IP_DCCP_TFRC_DEBUG
 int tfrc_debug;
 module_param(tfrc_debug, bool, 0644);
-MODULE_PARM_DESC(tfrc_debug, "Enable debug messages");
+MODULE_PARM_DESC(tfrc_debug, "Enable TFRC debug messages");
 #endif
 
-static int __init tfrc_module_init(void)
+int __init tfrc_lib_init(void)
 {
        int rc = tfrc_li_init();
 
@@ -38,18 +36,9 @@ out:
        return rc;
 }
 
-static void __exit tfrc_module_exit(void)
+void __exit tfrc_lib_exit(void)
 {
        tfrc_rx_packet_history_exit();
        tfrc_tx_packet_history_exit();
        tfrc_li_exit();
 }
-
-module_init(tfrc_module_init);
-module_exit(tfrc_module_exit);
-
-MODULE_AUTHOR("Gerrit Renker <gerrit@erg.abdn.ac.uk>, "
-             "Ian McDonald <ian.mcdonald@jandi.co.nz>, "
-             "Arnaldo Carvalho de Melo <acme@redhat.com>");
-MODULE_DESCRIPTION("DCCP TFRC library");
-MODULE_LICENSE("GPL");
index ed9857527acf4e43f69f3bfdb4e6388f0f8bd490..e9720b14327536192b72fa282d97fa439eeb0a99 100644 (file)
@@ -17,7 +17,8 @@
 #include <linux/types.h>
 #include <linux/math64.h>
 #include "../../dccp.h"
-/* internal includes that this module exports: */
+
+/* internal includes that this library exports: */
 #include "loss_interval.h"
 #include "packet_history.h"
 
@@ -66,4 +67,12 @@ extern void tfrc_rx_packet_history_exit(void);
 
 extern int  tfrc_li_init(void);
 extern void tfrc_li_exit(void);
+
+#ifdef CONFIG_IP_DCCP_TFRC_LIB
+extern int  tfrc_lib_init(void);
+extern void tfrc_lib_exit(void);
+#else
+#define tfrc_lib_init() (0)
+#define tfrc_lib_exit()
+#endif
 #endif /* _TFRC_H_ */
index 2f20a29cffe417a9ca7de9f1153763722ee087ba..c5d3a9e5a5a46ee59e5665087df31fcaeb0986ff 100644 (file)
@@ -659,8 +659,6 @@ u32 tfrc_calc_x(u16 s, u32 R, u32 p)
        return scaled_div32(result, f);
 }
 
-EXPORT_SYMBOL_GPL(tfrc_calc_x);
-
 /**
  *  tfrc_calc_x_reverse_lookup  -  try to find p given f(p)
  *
@@ -693,5 +691,3 @@ u32 tfrc_calc_x_reverse_lookup(u32 fvalue)
        index = tfrc_binsearch(fvalue, 0);
        return (index + 1) * 1000000 / TFRC_CALC_X_ARRSIZE;
 }
-
-EXPORT_SYMBOL_GPL(tfrc_calc_x_reverse_lookup);
index 0bc4c9a02e1964d3f6e0c5431b0a4d968115739a..f2230fc168e14b257028378c49d5227397ae52b7 100644 (file)
@@ -432,10 +432,8 @@ static inline int dccp_ack_pending(const struct sock *sk)
 {
        const struct dccp_sock *dp = dccp_sk(sk);
        return dp->dccps_timestamp_echo != 0 ||
-#ifdef CONFIG_IP_DCCP_ACKVEC
               (dp->dccps_hc_rx_ackvec != NULL &&
                dccp_ackvec_pending(dp->dccps_hc_rx_ackvec)) ||
-#endif
               inet_csk_ack_scheduled(sk);
 }
 
index 30f9fb76b921f3ffe19690d9732239b869c6f6fe..4152308958ab0b3a10a70b729e32e8d988816e3b 100644 (file)
@@ -34,7 +34,7 @@
 static int dccp_hdlr_ccid(struct sock *sk, u64 ccid, bool rx)
 {
        struct dccp_sock *dp = dccp_sk(sk);
-       struct ccid *new_ccid = ccid_new(ccid, sk, rx, gfp_any());
+       struct ccid *new_ccid = ccid_new(ccid, sk, rx);
 
        if (new_ccid == NULL)
                return -ENOMEM;
@@ -1214,8 +1214,6 @@ const char *dccp_feat_typename(const u8 type)
        return NULL;
 }
 
-EXPORT_SYMBOL_GPL(dccp_feat_typename);
-
 const char *dccp_feat_name(const u8 feat)
 {
        static const char *feature_names[] = {
@@ -1240,6 +1238,4 @@ const char *dccp_feat_name(const u8 feat)
 
        return feature_names[feat];
 }
-
-EXPORT_SYMBOL_GPL(dccp_feat_name);
 #endif /* CONFIG_IP_DCCP_DEBUG */
index 5eb443f656c19ea115114379703c72bc31e79fb0..7648f316310fbe668342915d82995d833eb71a91 100644 (file)
@@ -741,5 +741,3 @@ u32 dccp_sample_rtt(struct sock *sk, long delta)
 
        return delta;
 }
-
-EXPORT_SYMBOL_GPL(dccp_sample_rtt);
index 1747ccae8e8d098f50232253e7be60a40867848f..945b4d5d23b3153fce6efd1fb0b3e04dee04b501 100644 (file)
@@ -1118,9 +1118,15 @@ static int __init dccp_init(void)
        if (rc)
                goto out_ackvec_exit;
 
+       rc = ccid_initialize_builtins();
+       if (rc)
+               goto out_sysctl_exit;
+
        dccp_timestamping_init();
 out:
        return rc;
+out_sysctl_exit:
+       dccp_sysctl_exit();
 out_ackvec_exit:
        dccp_ackvec_exit();
 out_free_dccp_mib:
@@ -1143,6 +1149,7 @@ out_free_percpu:
 
 static void __exit dccp_fini(void)
 {
+       ccid_cleanup_builtins();
        dccp_mib_exit();
        free_pages((unsigned long)dccp_hashinfo.bhash,
                   get_order(dccp_hashinfo.bhash_size *
index f28acf11fc67d419bc0ccab57510c8bcedee1c3e..35bcddf8a932ea7a3b377b0b2b2592d3f33a17c0 100644 (file)
@@ -580,10 +580,6 @@ ssize_t tcp_splice_read(struct socket *sock, loff_t *ppos,
                else if (!ret) {
                        if (spliced)
                                break;
-                       if (flags & SPLICE_F_NONBLOCK) {
-                               ret = -EAGAIN;
-                               break;
-                       }
                        if (sock_flag(sk, SOCK_DONE))
                                break;
                        if (sk->sk_err) {
@@ -2519,9 +2515,7 @@ found:
        flush |= memcmp(th + 1, th2 + 1, thlen - sizeof(*th));
 
        total = p->len;
-       mss = total;
-       if (skb_shinfo(p)->frag_list)
-               mss = skb_shinfo(p)->frag_list->len;
+       mss = skb_shinfo(p)->gso_size;
 
        flush |= skb->len > mss || skb->len <= 0;
        flush |= ntohl(th2->seq) + total != ntohl(th->seq);
@@ -2557,7 +2551,6 @@ int tcp_gro_complete(struct sk_buff *skb)
        skb->csum_offset = offsetof(struct tcphdr, check);
        skb->ip_summed = CHECKSUM_PARTIAL;
 
-       skb_shinfo(skb)->gso_size = skb_shinfo(skb)->frag_list->len;
        skb_shinfo(skb)->gso_segs = NAPI_GRO_CB(skb)->count;
 
        if (th->cwr)
index eeeaad2e8b5ca7f64d69f31cdf3a7b9852a2a113..40f324655e2439cf6ba62dddecda75c9208a6c5c 100644 (file)
@@ -404,7 +404,7 @@ sticky_done:
                else if (optlen < sizeof(struct in6_pktinfo) || optval == NULL)
                        goto e_inval;
 
-               if (copy_from_user(&pkt, optval, optlen)) {
+               if (copy_from_user(&pkt, optval, sizeof(struct in6_pktinfo))) {
                                retv = -EFAULT;
                                break;
                }
index 18c486cf498756b5a4536d17798854ba137ba37f..76f06b94ab9f61a6e7ed6c844feeba21cae47e9a 100644 (file)
@@ -627,6 +627,9 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, struct in6_addr *dad
        rt = ip6_rt_copy(ort);
 
        if (rt) {
+               struct neighbour *neigh;
+               int attempts = !in_softirq();
+
                if (!(rt->rt6i_flags&RTF_GATEWAY)) {
                        if (rt->rt6i_dst.plen != 128 &&
                            ipv6_addr_equal(&rt->rt6i_dst.addr, daddr))
@@ -646,7 +649,35 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, struct in6_addr *dad
                }
 #endif
 
-               rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway);
+       retry:
+               neigh = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway);
+               if (IS_ERR(neigh)) {
+                       struct net *net = dev_net(rt->rt6i_dev);
+                       int saved_rt_min_interval =
+                               net->ipv6.sysctl.ip6_rt_gc_min_interval;
+                       int saved_rt_elasticity =
+                               net->ipv6.sysctl.ip6_rt_gc_elasticity;
+
+                       if (attempts-- > 0) {
+                               net->ipv6.sysctl.ip6_rt_gc_elasticity = 1;
+                               net->ipv6.sysctl.ip6_rt_gc_min_interval = 0;
+
+                               ip6_dst_gc(net->ipv6.ip6_dst_ops);
+
+                               net->ipv6.sysctl.ip6_rt_gc_elasticity =
+                                       saved_rt_elasticity;
+                               net->ipv6.sysctl.ip6_rt_gc_min_interval =
+                                       saved_rt_min_interval;
+                               goto retry;
+                       }
+
+                       if (net_ratelimit())
+                               printk(KERN_WARNING
+                                      "Neighbour table overflow.\n");
+                       dst_free(&rt->u.dst);
+                       return NULL;
+               }
+               rt->rt6i_nexthop = neigh;
 
        }
 
@@ -945,8 +976,11 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
        dev_hold(dev);
        if (neigh)
                neigh_hold(neigh);
-       else
+       else {
                neigh = ndisc_get_neigh(dev, addr);
+               if (IS_ERR(neigh))
+                       neigh = NULL;
+       }
 
        rt->rt6i_dev      = dev;
        rt->rt6i_idev     = idev;
@@ -1887,6 +1921,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
 {
        struct net *net = dev_net(idev->dev);
        struct rt6_info *rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops);
+       struct neighbour *neigh;
 
        if (rt == NULL)
                return ERR_PTR(-ENOMEM);
@@ -1909,11 +1944,18 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
                rt->rt6i_flags |= RTF_ANYCAST;
        else
                rt->rt6i_flags |= RTF_LOCAL;
-       rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway);
-       if (rt->rt6i_nexthop == NULL) {
+       neigh = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway);
+       if (IS_ERR(neigh)) {
                dst_free(&rt->u.dst);
-               return ERR_PTR(-ENOMEM);
+
+               /* We are casting this because that is the return
+                * value type.  But an errno encoded pointer is the
+                * same regardless of the underlying pointer type,
+                * and that's what we are returning.  So this is OK.
+                */
+               return (struct rt6_info *) neigh;
        }
+       rt->rt6i_nexthop = neigh;
 
        ipv6_addr_copy(&rt->rt6i_dst.addr, addr);
        rt->rt6i_dst.plen = 128;
index af3192d2a5a3401f5ebb1aff58e58fa0b6457de9..eb8a2a0b6eb71fc10671097563e71c3b7ae97ed9 100644 (file)
@@ -494,7 +494,21 @@ static int iucv_sock_connect(struct socket *sock, struct sockaddr *addr,
        if (err) {
                iucv_path_free(iucv->path);
                iucv->path = NULL;
-               err = -ECONNREFUSED;
+               switch (err) {
+               case 0x0b:      /* Target communicator is not logged on */
+                       err = -ENETUNREACH;
+                       break;
+               case 0x0d:      /* Max connections for this guest exceeded */
+               case 0x0e:      /* Max connections for target guest exceeded */
+                       err = -EAGAIN;
+                       break;
+               case 0x0f:      /* Missing IUCV authorization */
+                       err = -EACCES;
+                       break;
+               default:
+                       err = -ECONNREFUSED;
+                       break;
+               }
                goto done;
        }
 
@@ -507,6 +521,13 @@ static int iucv_sock_connect(struct socket *sock, struct sockaddr *addr,
                release_sock(sk);
                return -ECONNREFUSED;
        }
+
+       if (err) {
+               iucv_path_sever(iucv->path, NULL);
+               iucv_path_free(iucv->path);
+               iucv->path = NULL;
+       }
+
 done:
        release_sock(sk);
        return err;
@@ -1021,12 +1042,14 @@ static int iucv_callback_connreq(struct iucv_path *path,
        ASCEBC(user_data, sizeof(user_data));
        if (sk->sk_state != IUCV_LISTEN) {
                err = iucv_path_sever(path, user_data);
+               iucv_path_free(path);
                goto fail;
        }
 
        /* Check for backlog size */
        if (sk_acceptq_is_full(sk)) {
                err = iucv_path_sever(path, user_data);
+               iucv_path_free(path);
                goto fail;
        }
 
@@ -1034,6 +1057,7 @@ static int iucv_callback_connreq(struct iucv_path *path,
        nsk = iucv_sock_alloc(NULL, SOCK_STREAM, GFP_ATOMIC);
        if (!nsk) {
                err = iucv_path_sever(path, user_data);
+               iucv_path_free(path);
                goto fail;
        }
 
@@ -1057,6 +1081,8 @@ static int iucv_callback_connreq(struct iucv_path *path,
        err = iucv_path_accept(path, &af_iucv_handler, nuser_data, nsk);
        if (err) {
                err = iucv_path_sever(path, user_data);
+               iucv_path_free(path);
+               iucv_sock_kill(nsk);
                goto fail;
        }
 
index 8f57d4f4328a88265792a881f99dfd92ca077f15..032f61e985951bc85e1825a1e42529e660406713 100644 (file)
@@ -517,6 +517,7 @@ static int iucv_enable(void)
        size_t alloc_size;
        int cpu, rc;
 
+       get_online_cpus();
        rc = -ENOMEM;
        alloc_size = iucv_max_pathid * sizeof(struct iucv_path);
        iucv_path_table = kzalloc(alloc_size, GFP_KERNEL);
@@ -524,19 +525,17 @@ static int iucv_enable(void)
                goto out;
        /* Declare per cpu buffers. */
        rc = -EIO;
-       get_online_cpus();
        for_each_online_cpu(cpu)
                smp_call_function_single(cpu, iucv_declare_cpu, NULL, 1);
        if (cpus_empty(iucv_buffer_cpumask))
                /* No cpu could declare an iucv buffer. */
-               goto out_path;
+               goto out;
        put_online_cpus();
        return 0;
-
-out_path:
-       put_online_cpus();
-       kfree(iucv_path_table);
 out:
+       kfree(iucv_path_table);
+       iucv_path_table = NULL;
+       put_online_cpus();
        return rc;
 }
 
@@ -551,8 +550,9 @@ static void iucv_disable(void)
 {
        get_online_cpus();
        on_each_cpu(iucv_retrieve_cpu, NULL, 1);
-       put_online_cpus();
        kfree(iucv_path_table);
+       iucv_path_table = NULL;
+       put_online_cpus();
 }
 
 static int __cpuinit iucv_cpu_notify(struct notifier_block *self,
@@ -589,10 +589,14 @@ static int __cpuinit iucv_cpu_notify(struct notifier_block *self,
        case CPU_ONLINE_FROZEN:
        case CPU_DOWN_FAILED:
        case CPU_DOWN_FAILED_FROZEN:
+               if (!iucv_path_table)
+                       break;
                smp_call_function_single(cpu, iucv_declare_cpu, NULL, 1);
                break;
        case CPU_DOWN_PREPARE:
        case CPU_DOWN_PREPARE_FROZEN:
+               if (!iucv_path_table)
+                       break;
                cpumask = iucv_buffer_cpumask;
                cpu_clear(cpu, cpumask);
                if (cpus_empty(cpumask))
index 3c94f76d5525565f7cbb95372099ca9768d72a75..3eaa39403c13e447d4b4603c8c9f7f75d77ca252 100644 (file)
@@ -54,10 +54,10 @@ static unsigned long rfkill_states_lockdflt[BITS_TO_LONGS(RFKILL_TYPE_MAX)];
 static bool rfkill_epo_lock_active;
 
 
+#ifdef CONFIG_RFKILL_LEDS
 static void rfkill_led_trigger(struct rfkill *rfkill,
                               enum rfkill_state state)
 {
-#ifdef CONFIG_RFKILL_LEDS
        struct led_trigger *led = &rfkill->led_trigger;
 
        if (!led->name)
@@ -66,10 +66,8 @@ static void rfkill_led_trigger(struct rfkill *rfkill,
                led_trigger_event(led, LED_OFF);
        else
                led_trigger_event(led, LED_FULL);
-#endif /* CONFIG_RFKILL_LEDS */
 }
 
-#ifdef CONFIG_RFKILL_LEDS
 static void rfkill_led_trigger_activate(struct led_classdev *led)
 {
        struct rfkill *rfkill = container_of(led->trigger,
index 05d178008cbc9046d682f2bc2dbc01ce1e85737b..07372f60bee3364588cb94fcfcad1cc7bee514e5 100644 (file)
@@ -638,8 +638,9 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle,
                                break;
 
                n->next = *ins;
-               wmb();
+               tcf_tree_lock(tp);
                *ins = n;
+               tcf_tree_unlock(tp);
 
                *arg = (unsigned long)n;
                return 0;
index 2c730fc718ab4f28f2135893ccd9683def86be78..06603d73c411839fa78c58b84d5851805b0111d0 100644 (file)
@@ -1313,13 +1313,7 @@ asmlinkage long sys_socketpair(int family, int type, int protocol,
                goto out_fd1;
        }
 
-       err = audit_fd_pair(fd1, fd2);
-       if (err < 0) {
-               fput(newfile1);
-               fput(newfile2);
-               goto out_fd;
-       }
-
+       audit_fd_pair(fd1, fd2);
        fd_install(fd1, newfile1);
        fd_install(fd2, newfile2);
        /* fd1 and fd2 may be already another descriptors.
@@ -1349,7 +1343,6 @@ out_fd2:
 out_fd1:
        put_filp(newfile2);
        sock_release(sock2);
-out_fd:
        put_unused_fd(fd1);
        put_unused_fd(fd2);
        goto out;
@@ -2065,9 +2058,7 @@ asmlinkage long sys_socketcall(int call, unsigned long __user *args)
        if (copy_from_user(a, args, nargs[call]))
                return -EFAULT;
 
-       err = audit_socketcall(nargs[call] / sizeof(unsigned long), a);
-       if (err)
-               return err;
+       audit_socketcall(nargs[call] / sizeof(unsigned long), a);
 
        a0 = a[0];
        a1 = a[1];
index 19245324887011f358adab5baa5a28d38811549f..577385a4a5dc51219f1b2d6c8e6dec8568b3c2af 100644 (file)
@@ -522,8 +522,6 @@ rpc_get_inode(struct super_block *sb, int mode)
        if (!inode)
                return NULL;
        inode->i_mode = mode;
-       inode->i_uid = inode->i_gid = 0;
-       inode->i_blocks = 0;
        inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
        switch(mode & S_IFMT) {
                case S_IFDIR:
index 488a3b1f760f77009d8a2a0f65b17aca9e7f3b9d..db30fac3083efd488596577743422adae9b0c6cc 100644 (file)
@@ -14,7 +14,9 @@
 #    Only include files located in asm* and linux* are checked.
 #    The rest are assumed to be system include files.
 #
-# 2) TODO: check for leaked CONFIG_ symbols
+# 2) It is checked that prototypes does not use "extern"
+#
+# 3) Check for leaked CONFIG_ symbols
 
 use strict;
 
@@ -32,7 +34,11 @@ foreach my $file (@files) {
        $lineno = 0;
        while ($line = <FH>) {
                $lineno++;
-               check_include();
+               &check_include();
+               &check_asm_types();
+               &check_sizetypes();
+               &check_prototypes();
+               &check_config();
        }
        close FH;
 }
@@ -54,3 +60,63 @@ sub check_include
                }
        }
 }
+
+sub check_prototypes
+{
+       if ($line =~ m/^\s*extern\b/) {
+               printf STDERR "$filename:$lineno: extern's make no sense in userspace\n";
+       }
+}
+
+sub check_config
+{
+       if ($line =~ m/[^a-zA-Z0-9_]+CONFIG_([a-zA-Z0-9]+)[^a-zA-Z0-9]/) {
+               printf STDERR "$filename:$lineno: leaks CONFIG_$1 to userspace where it is not valid\n";
+       }
+}
+
+my $linux_asm_types;
+sub check_asm_types()
+{
+       if ($filename =~ /types.h|int-l64.h|int-ll64.h/o) {
+               return;
+       }
+       if ($lineno == 1) {
+               $linux_asm_types = 0;
+       } elsif ($linux_asm_types >= 1) {
+               return;
+       }
+       if ($line =~ m/^\s*#\s*include\s+<asm\/types.h>/) {
+               $linux_asm_types = 1;
+               printf STDERR "$filename:$lineno: " .
+               "include of <linux/types.h> is preferred over <asm/types.h>\n"
+               # Warn until headers are all fixed
+               #$ret = 1;
+       }
+}
+
+my $linux_types;
+sub check_sizetypes
+{
+       if ($filename =~ /types.h|int-l64.h|int-ll64.h/o) {
+               return;
+       }
+       if ($lineno == 1) {
+               $linux_types = 0;
+       } elsif ($linux_types >= 1) {
+               return;
+       }
+       if ($line =~ m/^\s*#\s*include\s+<linux\/types.h>/) {
+               $linux_types = 1;
+               return;
+       }
+       if ($line =~ m/__[us](8|16|32|64)\b/) {
+               printf STDERR "$filename:$lineno: " .
+                             "found __[us]{8,16,32,64} type " .
+                             "without #include <linux/types.h>\n";
+               $linux_types = 2;
+               # Warn until headers are all fixed
+               #$ret = 1;
+       }
+}
+
index 7d2b4146e02ff1a58c3c1e53f996902a0620901f..c6ae4052ab43bb5b8a884c23923d59ebf49de8ec 100644 (file)
@@ -36,6 +36,9 @@ foreach my $file (@files) {
                $line =~ s/\s__attribute_const__\s/ /g;
                $line =~ s/\s__attribute_const__$//g;
                $line =~ s/^#include <linux\/compiler.h>//;
+               $line =~ s/(^|\s)(inline)\b/$1__$2__/g;
+               $line =~ s/(^|\s)(asm)\b(\s|[(]|$)/$1__$2__$3/g;
+               $line =~ s/(^|\s|[(])(volatile)\b(\s|[(]|$)/$1__$2__$3/g;
                printf OUTFILE "%s", $line;
        }
        close OUTFILE;
index 9d4cba1c001d9ec5f48a365a2d864e1b2f3f467a..6408fefae083703e2fa3d8e8a3d4f8a814f44f0b 100644 (file)
@@ -65,9 +65,13 @@ enum symbol_type {
        S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING, S_OTHER
 };
 
+/* enum values are used as index to symbol.def[] */
 enum {
        S_DEF_USER,             /* main user value */
-       S_DEF_AUTO,
+       S_DEF_AUTO,             /* values read from auto.conf */
+       S_DEF_DEF3,             /* Reserved for UI usage */
+       S_DEF_DEF4,             /* Reserved for UI usage */
+       S_DEF_COUNT
 };
 
 struct symbol {
@@ -75,7 +79,7 @@ struct symbol {
        char *name;
        enum symbol_type type;
        struct symbol_value curr;
-       struct symbol_value def[4];
+       struct symbol_value def[S_DEF_COUNT];
        tristate visible;
        int flags;
        struct property *prop;
@@ -84,42 +88,64 @@ struct symbol {
 
 #define for_all_symbols(i, sym) for (i = 0; i < 257; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER)
 
-#define SYMBOL_CONST           0x0001
-#define SYMBOL_CHECK           0x0008
-#define SYMBOL_CHOICE          0x0010
-#define SYMBOL_CHOICEVAL       0x0020
-#define SYMBOL_VALID           0x0080
-#define SYMBOL_OPTIONAL                0x0100
-#define SYMBOL_WRITE           0x0200
-#define SYMBOL_CHANGED         0x0400
-#define SYMBOL_AUTO            0x1000
-#define SYMBOL_CHECKED         0x2000
-#define SYMBOL_WARNED          0x8000
-#define SYMBOL_DEF             0x10000
-#define SYMBOL_DEF_USER                0x10000
-#define SYMBOL_DEF_AUTO                0x20000
-#define SYMBOL_DEF3            0x40000
-#define SYMBOL_DEF4            0x80000
+#define SYMBOL_CONST      0x0001  /* symbol is const */
+#define SYMBOL_CHECK      0x0008  /* used during dependency checking */
+#define SYMBOL_CHOICE     0x0010  /* start of a choice block (null name) */
+#define SYMBOL_CHOICEVAL  0x0020  /* used as a value in a choice block */
+#define SYMBOL_VALID      0x0080  /* set when symbol.curr is calculated */
+#define SYMBOL_OPTIONAL   0x0100  /* choice is optional - values can be 'n' */
+#define SYMBOL_WRITE      0x0200  /* ? */
+#define SYMBOL_CHANGED    0x0400  /* ? */
+#define SYMBOL_AUTO       0x1000  /* value from environment variable */
+#define SYMBOL_CHECKED    0x2000  /* used during dependency checking */
+#define SYMBOL_WARNED     0x8000  /* warning has been issued */
+
+/* Set when symbol.def[] is used */
+#define SYMBOL_DEF        0x10000  /* First bit of SYMBOL_DEF */
+#define SYMBOL_DEF_USER   0x10000  /* symbol.def[S_DEF_USER] is valid */
+#define SYMBOL_DEF_AUTO   0x20000  /* symbol.def[S_DEF_AUTO] is valid */
+#define SYMBOL_DEF3       0x40000  /* symbol.def[S_DEF_3] is valid */
+#define SYMBOL_DEF4       0x80000  /* symbol.def[S_DEF_4] is valid */
 
 #define SYMBOL_MAXLENGTH       256
 #define SYMBOL_HASHSIZE                257
 #define SYMBOL_HASHMASK                0xff
 
+/* A property represent the config options that can be associated
+ * with a config "symbol".
+ * Sample:
+ * config FOO
+ *         default y
+ *         prompt "foo prompt"
+ *         select BAR
+ * config BAZ
+ *         int "BAZ Value"
+ *         range 1..255
+ */
 enum prop_type {
-       P_UNKNOWN, P_PROMPT, P_COMMENT, P_MENU, P_DEFAULT, P_CHOICE,
-       P_SELECT, P_RANGE, P_ENV
+       P_UNKNOWN,
+       P_PROMPT,   /* prompt "foo prompt" or "BAZ Value" */
+       P_COMMENT,  /* text associated with a comment */
+       P_MENU,     /* prompt associated with a menuconfig option */
+       P_DEFAULT,  /* default y */
+       P_CHOICE,   /* choice value */
+       P_SELECT,   /* select BAR */
+       P_RANGE,    /* range 7..100 (for a symbol) */
+       P_ENV,      /* value from environment variable */
 };
 
 struct property {
-       struct property *next;
-       struct symbol *sym;
-       enum prop_type type;
-       const char *text;
+       struct property *next;     /* next property - null if last */
+       struct symbol *sym;        /* the symbol for which the property is associated */
+       enum prop_type type;       /* type of property */
+       const char *text;          /* the prompt value - P_PROMPT, P_MENU, P_COMMENT */
        struct expr_value visible;
-       struct expr *expr;
-       struct menu *menu;
-       struct file *file;
-       int lineno;
+       struct expr *expr;         /* the optional conditional part of the property */
+       struct menu *menu;         /* the menu the property are associated with
+                                   * valid for: P_SELECT, P_RANGE, P_CHOICE,
+                                   * P_PROMPT, P_DEFAULT, P_MENU, P_COMMENT */
+       struct file *file;         /* what file was this property defined */
+       int lineno;                /* what lineno was this property defined */
 };
 
 #define for_all_properties(sym, st, tok) \
index 7342ce0a77801ff031e81e88f6ff1de3d48e7f4e..dc3e81807d13a41c18df6d20ce8c466e566e9853 100644 (file)
@@ -2370,11 +2370,14 @@ void zconf_nextfile(const char *name)
        current_buf = buf;
 
        if (file->flags & FILE_BUSY) {
-               printf("recursive scan (%s)?\n", name);
+               printf("%s:%d: do not source '%s' from itself\n",
+                      zconf_curname(), zconf_lineno(), name);
                exit(1);
        }
        if (file->flags & FILE_SCANNED) {
-               printf("file %s already scanned?\n", name);
+               printf("%s:%d: file '%s' is already sourced from '%s'\n",
+                      zconf_curname(), zconf_lineno(), name,
+                      file->parent->name);
                exit(1);
        }
        file->flags |= FILE_BUSY;
index 5164ef7ce499db39f1dc40b1ff5be6165083ed2e..21ff69c9ad4e846b3c409216a86434e587b22989 100644 (file)
@@ -314,11 +314,14 @@ void zconf_nextfile(const char *name)
        current_buf = buf;
 
        if (file->flags & FILE_BUSY) {
-               printf("recursive scan (%s)?\n", name);
+               printf("%s:%d: do not source '%s' from itself\n",
+                      zconf_curname(), zconf_lineno(), name);
                exit(1);
        }
        if (file->flags & FILE_SCANNED) {
-               printf("file %s already scanned?\n", name);
+               printf("%s:%d: file '%s' is already sourced from '%s'\n",
+                      zconf_curname(), zconf_lineno(), name,
+                      file->parent->name);
                exit(1);
        }
        file->flags |= FILE_BUSY;
index 4e7547209852b13fa1844cae687af17bad217564..9e3451d2c3a1d608b401c01685b841df02ae0550 100755 (executable)
@@ -84,7 +84,6 @@ docscope()
 
 exuberant()
 {
-       all_sources > all
        all_sources | xargs $1 -a                               \
        -I __initdata,__exitdata,__acquires,__releases          \
        -I __read_mostly,____cacheline_aligned                  \
index 79713545cd631158fc4acd69dbfdcdd3c098e384..69fc9952650f83fbbe718a6088fe461c64fda238 100644 (file)
@@ -238,7 +238,7 @@ int cap_inode_need_killpriv(struct dentry *dentry)
        struct inode *inode = dentry->d_inode;
        int error;
 
-       if (!inode->i_op || !inode->i_op->getxattr)
+       if (!inode->i_op->getxattr)
               return 0;
 
        error = inode->i_op->getxattr(dentry, XATTR_NAME_CAPS, NULL, 0);
@@ -259,7 +259,7 @@ int cap_inode_killpriv(struct dentry *dentry)
 {
        struct inode *inode = dentry->d_inode;
 
-       if (!inode->i_op || !inode->i_op->removexattr)
+       if (!inode->i_op->removexattr)
               return 0;
 
        return inode->i_op->removexattr(dentry, XATTR_NAME_CAPS);
@@ -317,7 +317,7 @@ int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data
 
        memset(cpu_caps, 0, sizeof(struct cpu_vfs_cap_data));
 
-       if (!inode || !inode->i_op || !inode->i_op->getxattr)
+       if (!inode || !inode->i_op->getxattr)
                return -ENODATA;
 
        size = inode->i_op->getxattr((struct dentry *)dentry, XATTR_NAME_CAPS, &caps,
index efea5a6054663f2d2aba78930bd3185986e14cdd..007ef252dde7b966661f2d1f9d8df4f47cb72927 100644 (file)
@@ -61,9 +61,6 @@ static struct inode *get_inode(struct super_block *sb, int mode, dev_t dev)
 
        if (inode) {
                inode->i_mode = mode;
-               inode->i_uid = 0;
-               inode->i_gid = 0;
-               inode->i_blocks = 0;
                inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
                switch (mode & S_IFMT) {
                default:
index c86303638235f2633eaff9c5426eed950517f785..8f612c8becb5de8637644df36c75ffaff632ad9a 100644 (file)
@@ -847,8 +847,6 @@ static struct inode *sel_make_inode(struct super_block *sb, int mode)
 
        if (ret) {
                ret->i_mode = mode;
-               ret->i_uid = ret->i_gid = 0;
-               ret->i_blocks = 0;
                ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
        }
        return ret;
@@ -1211,7 +1209,7 @@ static struct avc_cache_stats *sel_avc_get_stat_idx(loff_t *idx)
 {
        int cpu;
 
-       for (cpu = *idx; cpu < NR_CPUS; ++cpu) {
+       for (cpu = *idx; cpu < nr_cpu_ids; ++cpu) {
                if (!cpu_possible(cpu))
                        continue;
                *idx = cpu + 1;
index 343c8ab14af0a71881336ac3c2461d3360839895..c65e4fe4a0f176fc561717e6c28f0053332250e4 100644 (file)
@@ -2602,7 +2602,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
        case AUDIT_OBJ_ROLE:
        case AUDIT_OBJ_TYPE:
                /* only 'equals' and 'not equals' fit user, role, and type */
-               if (op != AUDIT_EQUAL && op != AUDIT_NOT_EQUAL)
+               if (op != Audit_equal && op != Audit_not_equal)
                        return -EINVAL;
                break;
        case AUDIT_SUBJ_SEN:
@@ -2736,10 +2736,10 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule,
        case AUDIT_SUBJ_USER:
        case AUDIT_OBJ_USER:
                switch (op) {
-               case AUDIT_EQUAL:
+               case Audit_equal:
                        match = (ctxt->user == rule->au_ctxt.user);
                        break;
-               case AUDIT_NOT_EQUAL:
+               case Audit_not_equal:
                        match = (ctxt->user != rule->au_ctxt.user);
                        break;
                }
@@ -2747,10 +2747,10 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule,
        case AUDIT_SUBJ_ROLE:
        case AUDIT_OBJ_ROLE:
                switch (op) {
-               case AUDIT_EQUAL:
+               case Audit_equal:
                        match = (ctxt->role == rule->au_ctxt.role);
                        break;
-               case AUDIT_NOT_EQUAL:
+               case Audit_not_equal:
                        match = (ctxt->role != rule->au_ctxt.role);
                        break;
                }
@@ -2758,10 +2758,10 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule,
        case AUDIT_SUBJ_TYPE:
        case AUDIT_OBJ_TYPE:
                switch (op) {
-               case AUDIT_EQUAL:
+               case Audit_equal:
                        match = (ctxt->type == rule->au_ctxt.type);
                        break;
-               case AUDIT_NOT_EQUAL:
+               case Audit_not_equal:
                        match = (ctxt->type != rule->au_ctxt.type);
                        break;
                }
@@ -2774,31 +2774,31 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule,
                          field == AUDIT_OBJ_LEV_LOW) ?
                         &ctxt->range.level[0] : &ctxt->range.level[1]);
                switch (op) {
-               case AUDIT_EQUAL:
+               case Audit_equal:
                        match = mls_level_eq(&rule->au_ctxt.range.level[0],
                                             level);
                        break;
-               case AUDIT_NOT_EQUAL:
+               case Audit_not_equal:
                        match = !mls_level_eq(&rule->au_ctxt.range.level[0],
                                              level);
                        break;
-               case AUDIT_LESS_THAN:
+               case Audit_lt:
                        match = (mls_level_dom(&rule->au_ctxt.range.level[0],
                                               level) &&
                                 !mls_level_eq(&rule->au_ctxt.range.level[0],
                                               level));
                        break;
-               case AUDIT_LESS_THAN_OR_EQUAL:
+               case Audit_le:
                        match = mls_level_dom(&rule->au_ctxt.range.level[0],
                                              level);
                        break;
-               case AUDIT_GREATER_THAN:
+               case Audit_gt:
                        match = (mls_level_dom(level,
                                              &rule->au_ctxt.range.level[0]) &&
                                 !mls_level_eq(level,
                                               &rule->au_ctxt.range.level[0]));
                        break;
-               case AUDIT_GREATER_THAN_OR_EQUAL:
+               case Audit_ge:
                        match = mls_level_dom(level,
                                              &rule->au_ctxt.range.level[0]);
                        break;
index 1b5551dfc1f74ab2119db364ef4dab08e3bcc373..848212fd48458d8bfc1207167c4920ba3123a1be 100644 (file)
@@ -2492,7 +2492,7 @@ static int smack_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
        if (field != AUDIT_SUBJ_USER && field != AUDIT_OBJ_USER)
                return -EINVAL;
 
-       if (op != AUDIT_EQUAL && op != AUDIT_NOT_EQUAL)
+       if (op != Audit_equal && op != Audit_not_equal)
                return -EINVAL;
 
        *rule = smk_import(rulestr, 0);
@@ -2556,9 +2556,9 @@ static int smack_audit_rule_match(u32 secid, u32 field, u32 op, void *vrule,
         * both pointers will point to the same smack_known
         * label.
         */
-       if (op == AUDIT_EQUAL)
+       if (op == Audit_equal)
                return (rule == smack);
-       if (op == AUDIT_NOT_EQUAL)
+       if (op == Audit_not_equal)
                return (rule != smack);
 
        return 0;
index 549b4eba14963d3b624acac71fad8fc8ce491957..9d98a6658ac9d757c004f7c130a7c143109dfe51 100644 (file)
@@ -84,7 +84,7 @@ static void snd_tea575x_set_freq(struct snd_tea575x *tea)
  * Linux Video interface
  */
 
-static int snd_tea575x_ioctl(struct inode *inode, struct file *file,
+static long snd_tea575x_ioctl(struct file *file,
                             unsigned int cmd, unsigned long data)
 {
        struct snd_tea575x *tea = video_drvdata(file);
@@ -174,14 +174,14 @@ static void snd_tea575x_release(struct video_device *vfd)
 {
 }
 
-static int snd_tea575x_exclusive_open(struct inode *inode, struct file *file)
+static int snd_tea575x_exclusive_open(struct file *file)
 {
        struct snd_tea575x *tea = video_drvdata(file);
 
        return test_and_set_bit(0, &tea->in_use) ? -EBUSY : 0;
 }
 
-static int snd_tea575x_exclusive_release(struct inode *inode, struct file *file)
+static int snd_tea575x_exclusive_release(struct file *file)
 {
        struct snd_tea575x *tea = video_drvdata(file);
 
index b20e1cede00b2c767200ca3f095351ef653bd9b8..75de40aaab0af5d5c558788468132bad574523f4 100644 (file)
@@ -25,6 +25,8 @@
 #include <linux/slab.h>
 #include <linux/pci.h>
 #include <sound/core.h>
+#include <sound/jack.h>
+
 #include "hda_codec.h"
 #include "hda_local.h"
 
 #define CONEXANT_HP_EVENT      0x37
 #define CONEXANT_MIC_EVENT     0x38
 
+/* Conexant 5051 specific */
+
+#define CXT5051_SPDIF_OUT      0x1C
+#define CXT5051_PORTB_EVENT    0x38
+#define CXT5051_PORTC_EVENT    0x39
 
 
+struct conexant_jack {
+
+       hda_nid_t nid;
+       int type;
+       struct snd_jack *jack;
+
+};
+
 struct conexant_spec {
 
        struct snd_kcontrol_new *mixers[5];
@@ -83,6 +98,9 @@ struct conexant_spec {
 
        unsigned int spdif_route;
 
+       /* jack detection */
+       struct snd_array jacks;
+
        /* dynamic controls, init_verbs and input_mux */
        struct auto_pin_cfg autocfg;
        struct hda_input_mux private_imux;
@@ -329,6 +347,86 @@ static int conexant_mux_enum_put(struct snd_kcontrol *kcontrol,
                                     &spec->cur_mux[adc_idx]);
 }
 
+static int conexant_add_jack(struct hda_codec *codec,
+               hda_nid_t nid, int type)
+{
+       struct conexant_spec *spec;
+       struct conexant_jack *jack;
+       const char *name;
+
+       spec = codec->spec;
+       snd_array_init(&spec->jacks, sizeof(*jack), 32);
+       jack = snd_array_new(&spec->jacks);
+       name = (type == SND_JACK_HEADPHONE) ? "Headphone" : "Mic" ;
+
+       if (!jack)
+               return -ENOMEM;
+
+       jack->nid = nid;
+       jack->type = type;
+
+       return snd_jack_new(codec->bus->card, name, type, &jack->jack);
+}
+
+static void conexant_report_jack(struct hda_codec *codec, hda_nid_t nid)
+{
+       struct conexant_spec *spec = codec->spec;
+       struct conexant_jack *jacks = spec->jacks.list;
+
+       if (jacks) {
+               int i;
+               for (i = 0; i < spec->jacks.used; i++) {
+                       if (jacks->nid == nid) {
+                               unsigned int present;
+                               present = snd_hda_codec_read(codec, nid, 0,
+                                               AC_VERB_GET_PIN_SENSE, 0) &
+                                       AC_PINSENSE_PRESENCE;
+
+                               present = (present) ? jacks->type : 0 ;
+
+                               snd_jack_report(jacks->jack,
+                                               present);
+                       }
+                       jacks++;
+               }
+       }
+}
+
+static int conexant_init_jacks(struct hda_codec *codec)
+{
+#ifdef CONFIG_SND_JACK
+       struct conexant_spec *spec = codec->spec;
+       int i;
+
+       for (i = 0; i < spec->num_init_verbs; i++) {
+               const struct hda_verb *hv;
+
+               hv = spec->init_verbs[i];
+               while (hv->nid) {
+                       int err = 0;
+                       switch (hv->param ^ AC_USRSP_EN) {
+                       case CONEXANT_HP_EVENT:
+                               err = conexant_add_jack(codec, hv->nid,
+                                               SND_JACK_HEADPHONE);
+                               conexant_report_jack(codec, hv->nid);
+                               break;
+                       case CXT5051_PORTC_EVENT:
+                       case CONEXANT_MIC_EVENT:
+                               err = conexant_add_jack(codec, hv->nid,
+                                               SND_JACK_MICROPHONE);
+                               conexant_report_jack(codec, hv->nid);
+                               break;
+                       }
+                       if (err < 0)
+                               return err;
+                       ++hv;
+               }
+       }
+#endif
+       return 0;
+
+}
+
 static int conexant_init(struct hda_codec *codec)
 {
        struct conexant_spec *spec = codec->spec;
@@ -341,6 +439,16 @@ static int conexant_init(struct hda_codec *codec)
 
 static void conexant_free(struct hda_codec *codec)
 {
+#ifdef CONFIG_SND_JACK
+       struct conexant_spec *spec = codec->spec;
+       if (spec->jacks.list) {
+               struct conexant_jack *jacks = spec->jacks.list;
+               int i;
+               for (i = 0; i < spec->jacks.used; i++)
+                       snd_device_free(codec->bus->card, &jacks[i].jack);
+               snd_array_free(&spec->jacks);
+       }
+#endif
        kfree(codec->spec);
 }
 
@@ -1526,9 +1634,6 @@ static int patch_cxt5047(struct hda_codec *codec)
 /* Conexant 5051 specific */
 static hda_nid_t cxt5051_dac_nids[1] = { 0x10 };
 static hda_nid_t cxt5051_adc_nids[2] = { 0x14, 0x15 };
-#define CXT5051_SPDIF_OUT      0x1C
-#define CXT5051_PORTB_EVENT    0x38
-#define CXT5051_PORTC_EVENT    0x39
 
 static struct hda_channel_mode cxt5051_modes[1] = {
        { 2, NULL },
@@ -1608,6 +1713,7 @@ static void cxt5051_hp_automute(struct hda_codec *codec)
 static void cxt5051_hp_unsol_event(struct hda_codec *codec,
                                   unsigned int res)
 {
+       int nid = (res & AC_UNSOL_RES_SUBTAG) >> 20;
        switch (res >> 26) {
        case CONEXANT_HP_EVENT:
                cxt5051_hp_automute(codec);
@@ -1619,6 +1725,7 @@ static void cxt5051_hp_unsol_event(struct hda_codec *codec,
                cxt5051_portc_automic(codec);
                break;
        }
+       conexant_report_jack(codec, nid);
 }
 
 static struct snd_kcontrol_new cxt5051_mixers[] = {
@@ -1693,6 +1800,7 @@ static struct hda_verb cxt5051_init_verbs[] = {
 static int cxt5051_init(struct hda_codec *codec)
 {
        conexant_init(codec);
+       conexant_init_jacks(codec);
        if (codec->patch_ops.unsol_event) {
                cxt5051_hp_automute(codec);
                cxt5051_portb_automic(codec);
index 0bd4e6bf354d42b7f74284b855d16ba41b78d3ef..9065ebf9c065a52d761d27d74a72728513f2af5b 100644 (file)
@@ -8467,6 +8467,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP),
        SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP),
        SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC883_6ST_DIG),
+       SND_PCI_QUIRK(0x103c, 0x2a66, "HP Acacia", ALC888_3ST_HP),
        SND_PCI_QUIRK(0x1043, 0x1873, "Asus M90V", ALC888_ASUS_M90V),
        SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG),
        SND_PCI_QUIRK(0x1043, 0x82fe, "Asus P5Q-EM HDMI", ALC1200_ASUS_P5Q),
@@ -16638,9 +16639,9 @@ static struct hda_codec_preset snd_hda_preset_realtek[] = {
          .patch = patch_alc882 }, /* should be patch_alc883() in future */
        { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
        { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc883 },
-       { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc883 },
        { .id = 0x10ec0888, .rev = 0x100101, .name = "ALC1200",
          .patch = patch_alc883 },
+       { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc883 },
        { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc883 },
        {} /* terminator */
 };
index 0dfa0540ce2cb917991d058d8c6aa9d88e6329ba..bb8d8c766b9d1f5ee5e08f85a8a36694ac1b8058 100644 (file)
@@ -1239,7 +1239,7 @@ static int __devinit snd_vt1724_pcm_spdif(struct snd_ice1712 *ice, int device)
        if (ice->force_pdma4 || ice->force_rdma1)
                name = "ICE1724 Secondary";
        else
-               name = "IEC1724 IEC958";
+               name = "ICE1724 IEC958";
        err = snd_pcm_new(ice->card, name, device, play, capt, &pcm);
        if (err < 0)
                return err;
index 51848880504a38e6051072873422b94396fbd364..31e44e346dc83c63744566c5721df440dc493bf2 100644 (file)
@@ -298,30 +298,107 @@ static const struct soc_enum twl4030_handsfreer_enum =
 static const struct snd_kcontrol_new twl4030_dapm_handsfreer_control =
 SOC_DAPM_ENUM("Route", twl4030_handsfreer_enum);
 
-static int outmixer_event(struct snd_soc_dapm_widget *w,
+/* Left analog microphone selection */
+static const char *twl4030_analoglmic_texts[] =
+               {"Off", "Main mic", "Headset mic", "Invalid", "AUXL",
+                "Invalid", "Invalid", "Invalid", "Carkit mic"};
+
+static const struct soc_enum twl4030_analoglmic_enum =
+       SOC_ENUM_SINGLE(TWL4030_REG_ANAMICL, 0,
+                       ARRAY_SIZE(twl4030_analoglmic_texts),
+                       twl4030_analoglmic_texts);
+
+static const struct snd_kcontrol_new twl4030_dapm_analoglmic_control =
+SOC_DAPM_ENUM("Route", twl4030_analoglmic_enum);
+
+/* Right analog microphone selection */
+static const char *twl4030_analogrmic_texts[] =
+               {"Off", "Sub mic", "Invalid", "Invalid", "AUXR"};
+
+static const struct soc_enum twl4030_analogrmic_enum =
+       SOC_ENUM_SINGLE(TWL4030_REG_ANAMICR, 0,
+                       ARRAY_SIZE(twl4030_analogrmic_texts),
+                       twl4030_analogrmic_texts);
+
+static const struct snd_kcontrol_new twl4030_dapm_analogrmic_control =
+SOC_DAPM_ENUM("Route", twl4030_analogrmic_enum);
+
+/* TX1 L/R Analog/Digital microphone selection */
+static const char *twl4030_micpathtx1_texts[] =
+               {"Analog", "Digimic0"};
+
+static const struct soc_enum twl4030_micpathtx1_enum =
+       SOC_ENUM_SINGLE(TWL4030_REG_ADCMICSEL, 0,
+                       ARRAY_SIZE(twl4030_micpathtx1_texts),
+                       twl4030_micpathtx1_texts);
+
+static const struct snd_kcontrol_new twl4030_dapm_micpathtx1_control =
+SOC_DAPM_ENUM("Route", twl4030_micpathtx1_enum);
+
+/* TX2 L/R Analog/Digital microphone selection */
+static const char *twl4030_micpathtx2_texts[] =
+               {"Analog", "Digimic1"};
+
+static const struct soc_enum twl4030_micpathtx2_enum =
+       SOC_ENUM_SINGLE(TWL4030_REG_ADCMICSEL, 2,
+                       ARRAY_SIZE(twl4030_micpathtx2_texts),
+                       twl4030_micpathtx2_texts);
+
+static const struct snd_kcontrol_new twl4030_dapm_micpathtx2_control =
+SOC_DAPM_ENUM("Route", twl4030_micpathtx2_enum);
+
+/*
+ * This function filters out the non valid mux settings, named as "Invalid"
+ * in the enum texts.
+ * Just refuse to set an invalid mux mode.
+ */
+static int twl4030_enum_event(struct snd_soc_dapm_widget *w,
        struct snd_kcontrol *kcontrol, int event)
 {
        struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
        int ret = 0;
        int val;
 
-       switch (e->reg) {
-       case TWL4030_REG_PREDL_CTL:
-       case TWL4030_REG_PREDR_CTL:
-       case TWL4030_REG_EAR_CTL:
-               val = w->value >> e->shift_l;
-               if (val == 3) {
-                       printk(KERN_WARNING
-                       "Invalid MUX setting for register 0x%02x (%d)\n",
-                             e->reg, val);
-                       ret = -1;
-               }
-               break;
+       val = w->value >> e->shift_l;
+       if (!strcmp("Invalid", e->texts[val])) {
+               printk(KERN_WARNING "Invalid MUX setting on 0x%02x (%d)\n",
+                       e->reg, val);
+               ret = -1;
        }
 
        return ret;
 }
 
+static int micpath_event(struct snd_soc_dapm_widget *w,
+       struct snd_kcontrol *kcontrol, int event)
+{
+       struct soc_enum *e = (struct soc_enum *)w->kcontrols->private_value;
+       unsigned char adcmicsel, micbias_ctl;
+
+       adcmicsel = twl4030_read_reg_cache(w->codec, TWL4030_REG_ADCMICSEL);
+       micbias_ctl = twl4030_read_reg_cache(w->codec, TWL4030_REG_MICBIAS_CTL);
+       /* Prepare the bits for the given TX path:
+        * shift_l == 0: TX1 microphone path
+        * shift_l == 2: TX2 microphone path */
+       if (e->shift_l) {
+               /* TX2 microphone path */
+               if (adcmicsel & TWL4030_TX2IN_SEL)
+                       micbias_ctl |= TWL4030_MICBIAS2_CTL; /* digimic */
+               else
+                       micbias_ctl &= ~TWL4030_MICBIAS2_CTL;
+       } else {
+               /* TX1 microphone path */
+               if (adcmicsel & TWL4030_TX1IN_SEL)
+                       micbias_ctl |= TWL4030_MICBIAS1_CTL; /* digimic */
+               else
+                       micbias_ctl &= ~TWL4030_MICBIAS1_CTL;
+       }
+
+       twl4030_write(w->codec, TWL4030_REG_MICBIAS_CTL, micbias_ctl);
+
+       return 0;
+}
+
 static int handsfree_event(struct snd_soc_dapm_widget *w,
                struct snd_kcontrol *kcontrol, int event)
 {
@@ -503,162 +580,6 @@ static int snd_soc_put_volsw_r2_twl4030(struct snd_kcontrol *kcontrol,
        return err;
 }
 
-static int twl4030_get_left_input(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_soc_codec *codec = kcontrol->private_data;
-       u8 reg = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL);
-       int result = 0;
-
-       /* one bit must be set a time */
-       reg &= TWL4030_CKMIC_EN | TWL4030_AUXL_EN | TWL4030_HSMIC_EN
-                       | TWL4030_MAINMIC_EN;
-       if (reg != 0) {
-               result++;
-               while ((reg & 1) == 0) {
-                       result++;
-                       reg >>= 1;
-               }
-       }
-
-       ucontrol->value.integer.value[0] = result;
-       return 0;
-}
-
-static int twl4030_put_left_input(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_soc_codec *codec = kcontrol->private_data;
-       int value = ucontrol->value.integer.value[0];
-       u8 anamicl, micbias, avadc_ctl;
-
-       anamicl = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL);
-       anamicl &= ~(TWL4030_CKMIC_EN | TWL4030_AUXL_EN | TWL4030_HSMIC_EN
-                       | TWL4030_MAINMIC_EN);
-       micbias = twl4030_read_reg_cache(codec, TWL4030_REG_MICBIAS_CTL);
-       micbias &= ~(TWL4030_HSMICBIAS_EN | TWL4030_MICBIAS1_EN);
-       avadc_ctl = twl4030_read_reg_cache(codec, TWL4030_REG_AVADC_CTL);
-
-       switch (value) {
-       case 1:
-               anamicl |= TWL4030_MAINMIC_EN;
-               micbias |= TWL4030_MICBIAS1_EN;
-               break;
-       case 2:
-               anamicl |= TWL4030_HSMIC_EN;
-               micbias |= TWL4030_HSMICBIAS_EN;
-               break;
-       case 3:
-               anamicl |= TWL4030_AUXL_EN;
-               break;
-       case 4:
-               anamicl |= TWL4030_CKMIC_EN;
-               break;
-       default:
-               break;
-       }
-
-       /* If some input is selected, enable amp and ADC */
-       if (value != 0) {
-               anamicl |= TWL4030_MICAMPL_EN;
-               avadc_ctl |= TWL4030_ADCL_EN;
-       } else {
-               anamicl &= ~TWL4030_MICAMPL_EN;
-               avadc_ctl &= ~TWL4030_ADCL_EN;
-       }
-
-       twl4030_write(codec, TWL4030_REG_ANAMICL, anamicl);
-       twl4030_write(codec, TWL4030_REG_MICBIAS_CTL, micbias);
-       twl4030_write(codec, TWL4030_REG_AVADC_CTL, avadc_ctl);
-
-       return 1;
-}
-
-static int twl4030_get_right_input(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_soc_codec *codec = kcontrol->private_data;
-       u8 reg = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICR);
-       int value = 0;
-
-       reg &= TWL4030_SUBMIC_EN|TWL4030_AUXR_EN;
-       switch (reg) {
-       case TWL4030_SUBMIC_EN:
-               value = 1;
-               break;
-       case TWL4030_AUXR_EN:
-               value = 2;
-               break;
-       default:
-               break;
-       }
-
-       ucontrol->value.integer.value[0] = value;
-       return 0;
-}
-
-static int twl4030_put_right_input(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_soc_codec *codec = kcontrol->private_data;
-       int value = ucontrol->value.integer.value[0];
-       u8 anamicr, micbias, avadc_ctl;
-
-       anamicr = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICR);
-       anamicr &= ~(TWL4030_SUBMIC_EN|TWL4030_AUXR_EN);
-       micbias = twl4030_read_reg_cache(codec, TWL4030_REG_MICBIAS_CTL);
-       micbias &= ~TWL4030_MICBIAS2_EN;
-       avadc_ctl = twl4030_read_reg_cache(codec, TWL4030_REG_AVADC_CTL);
-
-       switch (value) {
-       case 1:
-               anamicr |= TWL4030_SUBMIC_EN;
-               micbias |= TWL4030_MICBIAS2_EN;
-               break;
-       case 2:
-               anamicr |= TWL4030_AUXR_EN;
-               break;
-       default:
-               break;
-       }
-
-       if (value != 0) {
-               anamicr |= TWL4030_MICAMPR_EN;
-               avadc_ctl |= TWL4030_ADCR_EN;
-       } else {
-               anamicr &= ~TWL4030_MICAMPR_EN;
-               avadc_ctl &= ~TWL4030_ADCR_EN;
-       }
-
-       twl4030_write(codec, TWL4030_REG_ANAMICR, anamicr);
-       twl4030_write(codec, TWL4030_REG_MICBIAS_CTL, micbias);
-       twl4030_write(codec, TWL4030_REG_AVADC_CTL, avadc_ctl);
-
-       return 1;
-}
-
-static const char *twl4030_left_in_sel[] = {
-       "None",
-       "Main Mic",
-       "Headset Mic",
-       "Line In",
-       "Carkit Mic",
-};
-
-static const char *twl4030_right_in_sel[] = {
-       "None",
-       "Sub Mic",
-       "Line In",
-};
-
-static const struct soc_enum twl4030_left_input_mux =
-       SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(twl4030_left_in_sel),
-               twl4030_left_in_sel);
-
-static const struct soc_enum twl4030_right_input_mux =
-       SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(twl4030_right_in_sel),
-               twl4030_right_in_sel);
-
 /*
  * FGAIN volume control:
  * from -62 to 0 dB in 1 dB steps (mute instead of -63 dB)
@@ -741,18 +662,15 @@ static const struct snd_kcontrol_new twl4030_snd_controls[] = {
                TWL4030_REG_EAR_CTL, 4, 3, 0, output_tvl),
 
        /* Common capture gain controls */
-       SOC_DOUBLE_R_TLV("Capture Volume",
+       SOC_DOUBLE_R_TLV("TX1 Digital Capture Volume",
                TWL4030_REG_ATXL1PGA, TWL4030_REG_ATXR1PGA,
                0, 0x1f, 0, digital_capture_tlv),
+       SOC_DOUBLE_R_TLV("TX2 Digital Capture Volume",
+               TWL4030_REG_AVTXL2PGA, TWL4030_REG_AVTXR2PGA,
+               0, 0x1f, 0, digital_capture_tlv),
 
-       SOC_DOUBLE_TLV("Input Boost Volume", TWL4030_REG_ANAMIC_GAIN,
+       SOC_DOUBLE_TLV("Analog Capture Volume", TWL4030_REG_ANAMIC_GAIN,
                0, 3, 5, 0, input_gain_tlv),
-
-       /* Input source controls */
-       SOC_ENUM_EXT("Left Input Source", twl4030_left_input_mux,
-               twl4030_get_left_input, twl4030_put_left_input),
-       SOC_ENUM_EXT("Right Input Source", twl4030_right_input_mux,
-               twl4030_get_right_input, twl4030_put_right_input),
 };
 
 /* add non dapm controls */
@@ -772,9 +690,19 @@ static int twl4030_add_controls(struct snd_soc_codec *codec)
 }
 
 static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
-       SND_SOC_DAPM_INPUT("INL"),
-       SND_SOC_DAPM_INPUT("INR"),
-
+       /* Left channel inputs */
+       SND_SOC_DAPM_INPUT("MAINMIC"),
+       SND_SOC_DAPM_INPUT("HSMIC"),
+       SND_SOC_DAPM_INPUT("AUXL"),
+       SND_SOC_DAPM_INPUT("CARKITMIC"),
+       /* Right channel inputs */
+       SND_SOC_DAPM_INPUT("SUBMIC"),
+       SND_SOC_DAPM_INPUT("AUXR"),
+       /* Digital microphones (Stereo) */
+       SND_SOC_DAPM_INPUT("DIGIMIC0"),
+       SND_SOC_DAPM_INPUT("DIGIMIC1"),
+
+       /* Outputs */
        SND_SOC_DAPM_OUTPUT("OUTL"),
        SND_SOC_DAPM_OUTPUT("OUTR"),
        SND_SOC_DAPM_OUTPUT("EARPIECE"),
@@ -810,14 +738,14 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
        /* Output MUX controls */
        /* Earpiece */
        SND_SOC_DAPM_MUX_E("Earpiece Mux", SND_SOC_NOPM, 0, 0,
-               &twl4030_dapm_earpiece_control, outmixer_event,
+               &twl4030_dapm_earpiece_control, twl4030_enum_event,
                SND_SOC_DAPM_PRE_REG),
        /* PreDrivL/R */
        SND_SOC_DAPM_MUX_E("PredriveL Mux", SND_SOC_NOPM, 0, 0,
-               &twl4030_dapm_predrivel_control, outmixer_event,
+               &twl4030_dapm_predrivel_control, twl4030_enum_event,
                SND_SOC_DAPM_PRE_REG),
        SND_SOC_DAPM_MUX_E("PredriveR Mux", SND_SOC_NOPM, 0, 0,
-               &twl4030_dapm_predriver_control, outmixer_event,
+               &twl4030_dapm_predriver_control, twl4030_enum_event,
                SND_SOC_DAPM_PRE_REG),
        /* HeadsetL/R */
        SND_SOC_DAPM_MUX("HeadsetL Mux", SND_SOC_NOPM, 0, 0,
@@ -837,8 +765,50 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
                &twl4030_dapm_handsfreer_control, handsfree_event,
                SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
 
-       SND_SOC_DAPM_ADC("ADCL", "Left Capture", SND_SOC_NOPM, 0, 0),
-       SND_SOC_DAPM_ADC("ADCR", "Right Capture", SND_SOC_NOPM, 0, 0),
+       /* Introducing four virtual ADC, since TWL4030 have four channel for
+          capture */
+       SND_SOC_DAPM_ADC("ADC Virtual Left1", "Left Front Capture",
+               SND_SOC_NOPM, 0, 0),
+       SND_SOC_DAPM_ADC("ADC Virtual Right1", "Right Front Capture",
+               SND_SOC_NOPM, 0, 0),
+       SND_SOC_DAPM_ADC("ADC Virtual Left2", "Left Rear Capture",
+               SND_SOC_NOPM, 0, 0),
+       SND_SOC_DAPM_ADC("ADC Virtual Right2", "Right Rear Capture",
+               SND_SOC_NOPM, 0, 0),
+
+       /* Analog/Digital mic path selection.
+          TX1 Left/Right: either analog Left/Right or Digimic0
+          TX2 Left/Right: either analog Left/Right or Digimic1 */
+       SND_SOC_DAPM_MUX_E("TX1 Capture Route", SND_SOC_NOPM, 0, 0,
+               &twl4030_dapm_micpathtx1_control, micpath_event,
+               SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD|
+               SND_SOC_DAPM_POST_REG),
+       SND_SOC_DAPM_MUX_E("TX2 Capture Route", SND_SOC_NOPM, 0, 0,
+               &twl4030_dapm_micpathtx2_control, micpath_event,
+               SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD|
+               SND_SOC_DAPM_POST_REG),
+
+       /* Analog input muxes with power switch for the physical ADCL/R */
+       SND_SOC_DAPM_MUX_E("Analog Left Capture Route",
+               TWL4030_REG_AVADC_CTL, 3, 0, &twl4030_dapm_analoglmic_control,
+               twl4030_enum_event, SND_SOC_DAPM_PRE_REG),
+       SND_SOC_DAPM_MUX_E("Analog Right Capture Route",
+               TWL4030_REG_AVADC_CTL, 1, 0, &twl4030_dapm_analogrmic_control,
+               twl4030_enum_event, SND_SOC_DAPM_PRE_REG),
+
+       SND_SOC_DAPM_PGA("Analog Left Amplifier",
+               TWL4030_REG_ANAMICL, 4, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("Analog Right Amplifier",
+               TWL4030_REG_ANAMICR, 4, 0, NULL, 0),
+
+       SND_SOC_DAPM_PGA("Digimic0 Enable",
+               TWL4030_REG_ADCMICSEL, 1, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("Digimic1 Enable",
+               TWL4030_REG_ADCMICSEL, 3, 0, NULL, 0),
+
+       SND_SOC_DAPM_MICBIAS("Mic Bias 1", TWL4030_REG_MICBIAS_CTL, 0, 0),
+       SND_SOC_DAPM_MICBIAS("Mic Bias 2", TWL4030_REG_MICBIAS_CTL, 1, 0),
+       SND_SOC_DAPM_MICBIAS("Headset Mic Bias", TWL4030_REG_MICBIAS_CTL, 2, 0),
 };
 
 static const struct snd_soc_dapm_route intercon[] = {
@@ -894,9 +864,39 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"HFL", NULL, "HandsfreeL Mux"},
        {"HFR", NULL, "HandsfreeR Mux"},
 
-       /* inputs */
-       {"ADCL", NULL, "INL"},
-       {"ADCR", NULL, "INR"},
+       /* Capture path */
+       {"Analog Left Capture Route", "Main mic", "MAINMIC"},
+       {"Analog Left Capture Route", "Headset mic", "HSMIC"},
+       {"Analog Left Capture Route", "AUXL", "AUXL"},
+       {"Analog Left Capture Route", "Carkit mic", "CARKITMIC"},
+
+       {"Analog Right Capture Route", "Sub mic", "SUBMIC"},
+       {"Analog Right Capture Route", "AUXR", "AUXR"},
+
+       {"Analog Left Amplifier", NULL, "Analog Left Capture Route"},
+       {"Analog Right Amplifier", NULL, "Analog Right Capture Route"},
+
+       {"Digimic0 Enable", NULL, "DIGIMIC0"},
+       {"Digimic1 Enable", NULL, "DIGIMIC1"},
+
+       /* TX1 Left capture path */
+       {"TX1 Capture Route", "Analog", "Analog Left Amplifier"},
+       {"TX1 Capture Route", "Digimic0", "Digimic0 Enable"},
+       /* TX1 Right capture path */
+       {"TX1 Capture Route", "Analog", "Analog Right Amplifier"},
+       {"TX1 Capture Route", "Digimic0", "Digimic0 Enable"},
+       /* TX2 Left capture path */
+       {"TX2 Capture Route", "Analog", "Analog Left Amplifier"},
+       {"TX2 Capture Route", "Digimic1", "Digimic1 Enable"},
+       /* TX2 Right capture path */
+       {"TX2 Capture Route", "Analog", "Analog Right Amplifier"},
+       {"TX2 Capture Route", "Digimic1", "Digimic1 Enable"},
+
+       {"ADC Virtual Left1", NULL, "TX1 Capture Route"},
+       {"ADC Virtual Right1", NULL, "TX1 Capture Route"},
+       {"ADC Virtual Left2", NULL, "TX2 Capture Route"},
+       {"ADC Virtual Right2", NULL, "TX2 Capture Route"},
+
 };
 
 static int twl4030_add_widgets(struct snd_soc_codec *codec)
@@ -923,6 +923,7 @@ static void twl4030_power_up(struct snd_soc_codec *codec)
        twl4030_write(codec, TWL4030_REG_ANAMICL,
                anamicl | TWL4030_CNCL_OFFSET_START);
 
+
        /* wait for offset cancellation to complete */
        do {
                /* this takes a little while, so don't slam i2c */
index 54615c76802bd633918ea01513c93a34619ca777..442e5a82861736d71ac801ffcbcc57ca7560ef15 100644 (file)
 #define TWL4030_AVADC_CLK_PRIORITY     0x04
 #define TWL4030_ADCR_EN                        0x02
 
+/* TWL4030_REG_ADCMICSEL (0x08) Fields */
+
+#define TWL4030_DIGMIC1_EN             0x08
+#define TWL4030_TX2IN_SEL              0x04
+#define TWL4030_DIGMIC0_EN             0x02
+#define TWL4030_TX1IN_SEL              0x01
+
 /* AUDIO_IF (0x0E) Fields */
 
 #define TWL4030_AIF_SLAVE_EN           0x80
index f67579d527655ad3fd84eb9a4e8f0c1bd23b5527..4935d1bcbd8d4733408866475425bc5332fbebb5 100644 (file)
@@ -24,6 +24,7 @@
 #include <sound/soc-dapm.h>
 
 #include <asm/dma.h>
+#include <asm/mach-types.h>
 #include <asm/plat-sffsdr/sffsdr-fpga.h>
 
 #include <mach/mcbsp.h>
@@ -115,6 +116,9 @@ static int __init sffsdr_init(void)
 {
        int ret;
 
+       if (!machine_is_sffsdr())
+               return -EINVAL;
+
        sffsdr_snd_device = platform_device_alloc("soc-audio", 0);
        if (!sffsdr_snd_device) {
                printk(KERN_ERR "platform device allocation failed\n");
index c670d08e7c9ede6223b24b4ef78e8c2465859b89..53b9fb127a6d7f1b05121b7fe3979022d5c9acf2 100644 (file)
@@ -61,9 +61,9 @@ static int pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream)
 
        __pxa2xx_pcm_hw_free(substream);
 
-       if (prtd->dma_ch) {
+       if (prtd->dma_ch >= 0) {
                pxa_free_dma(prtd->dma_ch);
-               prtd->dma_ch = 0;
+               prtd->dma_ch = -1;
        }
 
        return 0;
index b098c0b4c584ea8b5a441c3f626ecf02290caeee..f73c1341437cf2aaf1e0e8442b466a05b67cc183 100644 (file)
@@ -1300,6 +1300,8 @@ EXPORT_SYMBOL_GPL(snd_soc_test_bits);
 /**
  * snd_soc_new_pcms - create new sound card and pcms
  * @socdev: the SoC audio device
+ * @idx: ALSA card index
+ * @xid: card identification
  *
  * Create a new sound card based upon the codec and interface pcms.
  *
@@ -1472,7 +1474,7 @@ EXPORT_SYMBOL_GPL(snd_soc_set_runtime_hwparams);
  * snd_soc_cnew - create new control
  * @_template: control template
  * @data: control private data
- * @lnng_name: control long name
+ * @long_name: control long name
  *
  * Create a new mixer control from a template control.
  *
@@ -1522,7 +1524,7 @@ EXPORT_SYMBOL_GPL(snd_soc_info_enum_double);
 /**
  * snd_soc_get_enum_double - enumerated double mixer get callback
  * @kcontrol: mixer control
- * @uinfo: control element information
+ * @ucontrol: control element information
  *
  * Callback to get the value of a double enumerated mixer.
  *
@@ -1551,7 +1553,7 @@ EXPORT_SYMBOL_GPL(snd_soc_get_enum_double);
 /**
  * snd_soc_put_enum_double - enumerated double mixer put callback
  * @kcontrol: mixer control
- * @uinfo: control element information
+ * @ucontrol: control element information
  *
  * Callback to set the value of a double enumerated mixer.
  *
@@ -1668,7 +1670,7 @@ EXPORT_SYMBOL_GPL(snd_soc_info_volsw);
 /**
  * snd_soc_get_volsw - single mixer get callback
  * @kcontrol: mixer control
- * @uinfo: control element information
+ * @ucontrol: control element information
  *
  * Callback to get the value of a single mixer control.
  *
@@ -1707,7 +1709,7 @@ EXPORT_SYMBOL_GPL(snd_soc_get_volsw);
 /**
  * snd_soc_put_volsw - single mixer put callback
  * @kcontrol: mixer control
- * @uinfo: control element information
+ * @ucontrol: control element information
  *
  * Callback to set the value of a single mixer control.
  *
@@ -1775,7 +1777,7 @@ EXPORT_SYMBOL_GPL(snd_soc_info_volsw_2r);
 /**
  * snd_soc_get_volsw_2r - double mixer get callback
  * @kcontrol: mixer control
- * @uinfo: control element information
+ * @ucontrol: control element information
  *
  * Callback to get the value of a double mixer control that spans 2 registers.
  *
@@ -1812,7 +1814,7 @@ EXPORT_SYMBOL_GPL(snd_soc_get_volsw_2r);
 /**
  * snd_soc_put_volsw_2r - double mixer set callback
  * @kcontrol: mixer control
- * @uinfo: control element information
+ * @ucontrol: control element information
  *
  * Callback to set the value of a double mixer control that spans 2 registers.
  *
@@ -1882,7 +1884,7 @@ EXPORT_SYMBOL_GPL(snd_soc_info_volsw_s8);
 /**
  * snd_soc_get_volsw_s8 - signed mixer get callback
  * @kcontrol: mixer control
- * @uinfo: control element information
+ * @ucontrol: control element information
  *
  * Callback to get the value of a signed mixer control.
  *
@@ -1909,7 +1911,7 @@ EXPORT_SYMBOL_GPL(snd_soc_get_volsw_s8);
 /**
  * snd_soc_put_volsw_sgn - signed mixer put callback
  * @kcontrol: mixer control
- * @uinfo: control element information
+ * @ucontrol: control element information
  *
  * Callback to set the value of a signed mixer control.
  *
@@ -1954,7 +1956,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk);
 /**
  * snd_soc_dai_set_clkdiv - configure DAI clock dividers.
  * @dai: DAI
- * @clk_id: DAI specific clock divider ID
+ * @div_id: DAI specific clock divider ID
  * @div: new clock divisor.
  *
  * Configures the clock dividers. This is used to derive the best DAI bit and
@@ -2060,7 +2062,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute);
 /**
  * snd_soc_register_card - Register a card with the ASoC core
  *
- * @param card Card to register
+ * @card: Card to register
  *
  * Note that currently this is an internal only function: it will be
  * exposed to machine drivers after further backporting of ASoC v2
@@ -2087,7 +2089,7 @@ static int snd_soc_register_card(struct snd_soc_card *card)
 /**
  * snd_soc_unregister_card - Unregister a card with the ASoC core
  *
- * @param card Card to unregister
+ * @card: Card to unregister
  *
  * Note that currently this is an internal only function: it will be
  * exposed to machine drivers after further backporting of ASoC v2
@@ -2107,7 +2109,7 @@ static int snd_soc_unregister_card(struct snd_soc_card *card)
 /**
  * snd_soc_register_dai - Register a DAI with the ASoC core
  *
- * @param dai DAI to register
+ * @dai: DAI to register
  */
 int snd_soc_register_dai(struct snd_soc_dai *dai)
 {
@@ -2134,7 +2136,7 @@ EXPORT_SYMBOL_GPL(snd_soc_register_dai);
 /**
  * snd_soc_unregister_dai - Unregister a DAI from the ASoC core
  *
- * @param dai DAI to unregister
+ * @dai: DAI to unregister
  */
 void snd_soc_unregister_dai(struct snd_soc_dai *dai)
 {
@@ -2149,8 +2151,8 @@ EXPORT_SYMBOL_GPL(snd_soc_unregister_dai);
 /**
  * snd_soc_register_dais - Register multiple DAIs with the ASoC core
  *
- * @param dai Array of DAIs to register
- * @param count Number of DAIs
+ * @dai: Array of DAIs to register
+ * @count: Number of DAIs
  */
 int snd_soc_register_dais(struct snd_soc_dai *dai, size_t count)
 {
@@ -2175,8 +2177,8 @@ EXPORT_SYMBOL_GPL(snd_soc_register_dais);
 /**
  * snd_soc_unregister_dais - Unregister multiple DAIs from the ASoC core
  *
- * @param dai Array of DAIs to unregister
- * @param count Number of DAIs
+ * @dai: Array of DAIs to unregister
+ * @count: Number of DAIs
  */
 void snd_soc_unregister_dais(struct snd_soc_dai *dai, size_t count)
 {
@@ -2190,7 +2192,7 @@ EXPORT_SYMBOL_GPL(snd_soc_unregister_dais);
 /**
  * snd_soc_register_platform - Register a platform with the ASoC core
  *
- * @param platform platform to register
+ * @platform: platform to register
  */
 int snd_soc_register_platform(struct snd_soc_platform *platform)
 {
@@ -2213,7 +2215,7 @@ EXPORT_SYMBOL_GPL(snd_soc_register_platform);
 /**
  * snd_soc_unregister_platform - Unregister a platform from the ASoC core
  *
- * @param platform platform to unregister
+ * @platform: platform to unregister
  */
 void snd_soc_unregister_platform(struct snd_soc_platform *platform)
 {
@@ -2228,7 +2230,7 @@ EXPORT_SYMBOL_GPL(snd_soc_unregister_platform);
 /**
  * snd_soc_register_codec - Register a codec with the ASoC core
  *
- * @param codec codec to register
+ * @codec: codec to register
  */
 int snd_soc_register_codec(struct snd_soc_codec *codec)
 {
@@ -2255,7 +2257,7 @@ EXPORT_SYMBOL_GPL(snd_soc_register_codec);
 /**
  * snd_soc_unregister_codec - Unregister a codec from the ASoC core
  *
- * @param codec codec to unregister
+ * @codec: codec to unregister
  */
 void snd_soc_unregister_codec(struct snd_soc_codec *codec)
 {
index 8863eddbac029975f9f7b4fefeac73b73bbcb6cf..6c79ca6df0bf284ba59e8075152e911518c7c2dc 100644 (file)
@@ -1077,7 +1077,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets);
 /**
  * snd_soc_dapm_get_volsw - dapm mixer get callback
  * @kcontrol: mixer control
- * @uinfo: control element information
+ * @ucontrol: control element information
  *
  * Callback to get the value of a dapm mixer control.
  *
@@ -1122,7 +1122,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw);
 /**
  * snd_soc_dapm_put_volsw - dapm mixer set callback
  * @kcontrol: mixer control
- * @uinfo: control element information
+ * @ucontrol: control element information
  *
  * Callback to set the value of a dapm mixer control.
  *
@@ -1193,7 +1193,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw);
 /**
  * snd_soc_dapm_get_enum_double - dapm enumerated double mixer get callback
  * @kcontrol: mixer control
- * @uinfo: control element information
+ * @ucontrol: control element information
  *
  * Callback to get the value of a dapm enumerated double mixer control.
  *
@@ -1221,7 +1221,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double);
 /**
  * snd_soc_dapm_put_enum_double - dapm enumerated double mixer set callback
  * @kcontrol: mixer control
- * @uinfo: control element information
+ * @ucontrol: control element information
  *
  * Callback to set the value of a dapm enumerated double mixer control.
  *
@@ -1419,7 +1419,7 @@ int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev,
 
 /**
  * snd_soc_dapm_enable_pin - enable pin.
- * @snd_soc_codec: SoC codec
+ * @codec: SoC codec
  * @pin: pin name
  *
  * Enables input/output pin and it's parents or children widgets iff there is
index b143ef7152f7b7b734ff08c58ffdb014b518b6e0..a62500e387a654b904a2cdfda9c6b16f319bfa1b 100644 (file)
@@ -446,7 +446,7 @@ static int __devinit snd_probe(struct usb_interface *intf,
        if (!card)
                return -ENOMEM;
                        
-       dev_set_drvdata(&intf->dev, card);
+       usb_set_intfdata(intf, card);
        ret = init_card(caiaqdev(card));
        if (ret < 0) {
                log("unable to init card! (ret=%d)\n", ret);
@@ -460,7 +460,7 @@ static int __devinit snd_probe(struct usb_interface *intf,
 static void snd_disconnect(struct usb_interface *intf)
 {
        struct snd_usb_caiaqdev *dev;
-       struct snd_card *card = dev_get_drvdata(&intf->dev);
+       struct snd_card *card = usb_get_intfdata(intf);
 
        debug("%s(%p)\n", __func__, intf);
 
index bbd70d5814a083fff3d130cf5b2be652abd7f2f9..c709b9563226c0b343f98588f4bc91345c5bf185 100644 (file)
@@ -3709,7 +3709,7 @@ static int usb_audio_probe(struct usb_interface *intf,
        void *chip;
        chip = snd_usb_audio_probe(interface_to_usbdev(intf), intf, id);
        if (chip) {
-               dev_set_drvdata(&intf->dev, chip);
+               usb_set_intfdata(intf, chip);
                return 0;
        } else
                return -EIO;
@@ -3718,13 +3718,13 @@ static int usb_audio_probe(struct usb_interface *intf,
 static void usb_audio_disconnect(struct usb_interface *intf)
 {
        snd_usb_audio_disconnect(interface_to_usbdev(intf),
-                                dev_get_drvdata(&intf->dev));
+                                usb_get_intfdata(intf));
 }
 
 #ifdef CONFIG_PM
 static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
 {
-       struct snd_usb_audio *chip = dev_get_drvdata(&intf->dev);
+       struct snd_usb_audio *chip = usb_get_intfdata(intf);
        struct list_head *p;
        struct snd_usb_stream *as;
 
@@ -3744,7 +3744,7 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
 
 static int usb_audio_resume(struct usb_interface *intf)
 {
-       struct snd_usb_audio *chip = dev_get_drvdata(&intf->dev);
+       struct snd_usb_audio *chip = usb_get_intfdata(intf);
 
        if (chip == (void *)-1L)
                return 0;
index 6d9f9b135c62258bf0727166f32cfccbab31e744..320641ab5be7bf972a78603d1c988ef8fae8f08a 100644 (file)
@@ -1392,8 +1392,7 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi* umidi,
        for (i = 0; i < intfd->bNumEndpoints; ++i) {
                hostep = &hostif->endpoint[i];
                ep = get_ep_desc(hostep);
-               if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK &&
-                   (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
+               if (!usb_endpoint_xfer_bulk(ep) && !usb_endpoint_xfer_int(ep))
                        continue;
                ms_ep = (struct usb_ms_endpoint_descriptor*)hostep->extra;
                if (hostep->extralen < 4 ||
@@ -1401,15 +1400,15 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi* umidi,
                    ms_ep->bDescriptorType != USB_DT_CS_ENDPOINT ||
                    ms_ep->bDescriptorSubtype != MS_GENERAL)
                        continue;
-               if ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) {
+               if (usb_endpoint_dir_out(ep)) {
                        if (endpoints[epidx].out_ep) {
                                if (++epidx >= MIDI_MAX_ENDPOINTS) {
                                        snd_printk(KERN_WARNING "too many endpoints\n");
                                        break;
                                }
                        }
-                       endpoints[epidx].out_ep = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
-                       if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
+                       endpoints[epidx].out_ep = usb_endpoint_num(ep);
+                       if (usb_endpoint_xfer_int(ep))
                                endpoints[epidx].out_interval = ep->bInterval;
                        else if (snd_usb_get_speed(umidi->chip->dev) == USB_SPEED_LOW)
                                /*
@@ -1428,8 +1427,8 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi* umidi,
                                        break;
                                }
                        }
-                       endpoints[epidx].in_ep = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
-                       if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
+                       endpoints[epidx].in_ep = usb_endpoint_num(ep);
+                       if (usb_endpoint_xfer_int(ep))
                                endpoints[epidx].in_interval = ep->bInterval;
                        else if (snd_usb_get_speed(umidi->chip->dev) == USB_SPEED_LOW)
                                endpoints[epidx].in_interval = 1;
@@ -1495,20 +1494,20 @@ static int snd_usbmidi_detect_endpoints(struct snd_usb_midi* umidi,
 
        for (i = 0; i < intfd->bNumEndpoints; ++i) {
                epd = get_endpoint(hostif, i);
-               if ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK &&
-                   (epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
+               if (!usb_endpoint_xfer_bulk(epd) &&
+                   !usb_endpoint_xfer_int(epd))
                        continue;
                if (out_eps < max_endpoints &&
-                   (epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) {
-                       endpoint[out_eps].out_ep = epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
-                       if ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
+                   usb_endpoint_dir_out(epd)) {
+                       endpoint[out_eps].out_ep = usb_endpoint_num(epd);
+                       if (usb_endpoint_xfer_int(epd))
                                endpoint[out_eps].out_interval = epd->bInterval;
                        ++out_eps;
                }
                if (in_eps < max_endpoints &&
-                   (epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) {
-                       endpoint[in_eps].in_ep = epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
-                       if ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
+                   usb_endpoint_dir_in(epd)) {
+                       endpoint[in_eps].in_ep = usb_endpoint_num(epd);
+                       if (usb_endpoint_xfer_int(epd))
                                endpoint[in_eps].in_interval = epd->bInterval;
                        ++in_eps;
                }
@@ -1607,21 +1606,19 @@ static int snd_usbmidi_create_endpoints_midiman(struct snd_usb_midi* umidi,
        }
 
        epd = get_endpoint(hostif, 0);
-       if ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) != USB_DIR_IN ||
-           (epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) {
+       if (!usb_endpoint_dir_in(epd) || !usb_endpoint_xfer_int(epd)) {
                snd_printdd(KERN_ERR "endpoint[0] isn't interrupt\n");
                return -ENXIO;
        }
        epd = get_endpoint(hostif, 2);
-       if ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) != USB_DIR_OUT ||
-           (epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK) {
+       if (!usb_endpoint_dir_out(epd) || !usb_endpoint_xfer_bulk(epd)) {
                snd_printdd(KERN_ERR "endpoint[2] isn't bulk output\n");
                return -ENXIO;
        }
        if (endpoint->out_cables > 0x0001) {
                epd = get_endpoint(hostif, 4);
-               if ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) != USB_DIR_OUT ||
-                   (epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK) {
+               if (!usb_endpoint_dir_out(epd) ||
+                   !usb_endpoint_xfer_bulk(epd)) {
                        snd_printdd(KERN_ERR "endpoint[4] isn't bulk output\n");
                        return -ENXIO;
                }
index a49246113e7563c60f08c47d6104c7774d1073ac..00397c8a765ba62b6f004e5a36d818aa8f25f923 100644 (file)
@@ -1755,11 +1755,10 @@ static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer)
        if (get_iface_desc(hostif)->bNumEndpoints < 1)
                return 0;
        ep = get_endpoint(hostif, 0);
-       if ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) != USB_DIR_IN ||
-           (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
+       if (!usb_endpoint_dir_in(ep) || !usb_endpoint_xfer_int(ep))
                return 0;
 
-       epnum = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+       epnum = usb_endpoint_num(ep);
        buffer_length = le16_to_cpu(ep->wMaxPacketSize);
        transfer_buffer = kmalloc(buffer_length, GFP_KERNEL);
        if (!transfer_buffer)
index c2515b680f9fd8d5245fad46c79c378cd418ba82..73e59f4403a483b16a041a9bba9f767e6b021c60 100644 (file)
@@ -589,7 +589,7 @@ static int snd_us122l_suspend(struct usb_interface *intf, pm_message_t message)
        struct us122l *us122l;
        struct list_head *p;
 
-       card = dev_get_drvdata(&intf->dev);
+       card = usb_get_intfdata(intf);
        if (!card)
                return 0;
        snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
@@ -615,7 +615,7 @@ static int snd_us122l_resume(struct usb_interface *intf)
        struct list_head *p;
        int err;
 
-       card = dev_get_drvdata(&intf->dev);
+       card = usb_get_intfdata(intf);
        if (!card)
                return 0;
 
index e5981a630314a328253c4a92f3c7641f5b191938..ca26c532e77e36e71b4966030592628c87874141 100644 (file)
@@ -392,7 +392,7 @@ static int snd_usX2Y_probe(struct usb_interface *intf, const struct usb_device_i
        void *chip;
        chip = usX2Y_usb_probe(interface_to_usbdev(intf), intf, id);
        if (chip) {
-               dev_set_drvdata(&intf->dev, chip);
+               usb_set_intfdata(intf, chip);
                return 0;
        } else
                return -EIO;
@@ -401,7 +401,7 @@ static int snd_usX2Y_probe(struct usb_interface *intf, const struct usb_device_i
 static void snd_usX2Y_disconnect(struct usb_interface *intf)
 {
        usX2Y_usb_disconnect(interface_to_usbdev(intf),
-                                dev_get_drvdata(&intf->dev));
+                                usb_get_intfdata(intf));
 }
 
 MODULE_DEVICE_TABLE(usb, snd_usX2Y_usb_id_table);
similarity index 58%
rename from virt/kvm/vtd.c
rename to virt/kvm/iommu.c
index a770874f3a3aa98774d08f3ce213ef1726197e56..e9693a29d00e2fe5b159632e301ca4cd0d08bb4d 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/kvm_host.h>
 #include <linux/pci.h>
 #include <linux/dmar.h>
+#include <linux/iommu.h>
 #include <linux/intel-iommu.h>
 
 static int kvm_iommu_unmap_memslots(struct kvm *kvm);
@@ -37,7 +38,7 @@ int kvm_iommu_map_pages(struct kvm *kvm,
        gfn_t gfn = base_gfn;
        pfn_t pfn;
        int i, r = 0;
-       struct dmar_domain *domain = kvm->arch.intel_iommu_domain;
+       struct iommu_domain *domain = kvm->arch.iommu_domain;
 
        /* check if iommu exists and in use */
        if (!domain)
@@ -45,20 +46,17 @@ int kvm_iommu_map_pages(struct kvm *kvm,
 
        for (i = 0; i < npages; i++) {
                /* check if already mapped */
-               pfn = (pfn_t)intel_iommu_iova_to_pfn(domain,
-                                                    gfn_to_gpa(gfn));
-               if (pfn)
+               if (iommu_iova_to_phys(domain, gfn_to_gpa(gfn)))
                        continue;
 
                pfn = gfn_to_pfn(kvm, gfn);
-               r = intel_iommu_page_mapping(domain,
-                                            gfn_to_gpa(gfn),
-                                            pfn_to_hpa(pfn),
-                                            PAGE_SIZE,
-                                            DMA_PTE_READ |
-                                            DMA_PTE_WRITE);
+               r = iommu_map_range(domain,
+                                   gfn_to_gpa(gfn),
+                                   pfn_to_hpa(pfn),
+                                   PAGE_SIZE,
+                                   IOMMU_READ | IOMMU_WRITE);
                if (r) {
-                       printk(KERN_ERR "kvm_iommu_map_pages:"
+                       printk(KERN_ERR "kvm_iommu_map_address:"
                               "iommu failed to map pfn=%lx\n", pfn);
                        goto unmap_pages;
                }
@@ -73,7 +71,7 @@ unmap_pages:
 
 static int kvm_iommu_map_memslots(struct kvm *kvm)
 {
-       int i, r;
+       int i, r = 0;
 
        down_read(&kvm->slots_lock);
        for (i = 0; i < kvm->nmemslots; i++) {
@@ -86,50 +84,79 @@ static int kvm_iommu_map_memslots(struct kvm *kvm)
        return r;
 }
 
-int kvm_iommu_map_guest(struct kvm *kvm,
-                       struct kvm_assigned_dev_kernel *assigned_dev)
+int kvm_assign_device(struct kvm *kvm,
+                     struct kvm_assigned_dev_kernel *assigned_dev)
 {
        struct pci_dev *pdev = NULL;
+       struct iommu_domain *domain = kvm->arch.iommu_domain;
        int r;
 
-       if (!intel_iommu_found()) {
-               printk(KERN_ERR "%s: intel iommu not found\n", __func__);
+       /* check if iommu exists and in use */
+       if (!domain)
+               return 0;
+
+       pdev = assigned_dev->dev;
+       if (pdev == NULL)
                return -ENODEV;
+
+       r = iommu_attach_device(domain, &pdev->dev);
+       if (r) {
+               printk(KERN_ERR "assign device %x:%x.%x failed",
+                       pdev->bus->number,
+                       PCI_SLOT(pdev->devfn),
+                       PCI_FUNC(pdev->devfn));
+               return r;
        }
 
-       printk(KERN_DEBUG "VT-d direct map: host bdf = %x:%x:%x\n",
-              assigned_dev->host_busnr,
-              PCI_SLOT(assigned_dev->host_devfn),
-              PCI_FUNC(assigned_dev->host_devfn));
+       printk(KERN_DEBUG "assign device: host bdf = %x:%x:%x\n",
+               assigned_dev->host_busnr,
+               PCI_SLOT(assigned_dev->host_devfn),
+               PCI_FUNC(assigned_dev->host_devfn));
+
+       return 0;
+}
+
+int kvm_deassign_device(struct kvm *kvm,
+                       struct kvm_assigned_dev_kernel *assigned_dev)
+{
+       struct iommu_domain *domain = kvm->arch.iommu_domain;
+       struct pci_dev *pdev = NULL;
+
+       /* check if iommu exists and in use */
+       if (!domain)
+               return 0;
 
        pdev = assigned_dev->dev;
+       if (pdev == NULL)
+               return -ENODEV;
 
-       if (pdev == NULL) {
-               if (kvm->arch.intel_iommu_domain) {
-                       intel_iommu_domain_exit(kvm->arch.intel_iommu_domain);
-                       kvm->arch.intel_iommu_domain = NULL;
-               }
+       iommu_detach_device(domain, &pdev->dev);
+
+       printk(KERN_DEBUG "deassign device: host bdf = %x:%x:%x\n",
+               assigned_dev->host_busnr,
+               PCI_SLOT(assigned_dev->host_devfn),
+               PCI_FUNC(assigned_dev->host_devfn));
+
+       return 0;
+}
+
+int kvm_iommu_map_guest(struct kvm *kvm)
+{
+       int r;
+
+       if (!iommu_found()) {
+               printk(KERN_ERR "%s: iommu not found\n", __func__);
                return -ENODEV;
        }
 
-       kvm->arch.intel_iommu_domain = intel_iommu_domain_alloc(pdev);
-       if (!kvm->arch.intel_iommu_domain)
-               return -ENODEV;
+       kvm->arch.iommu_domain = iommu_domain_alloc();
+       if (!kvm->arch.iommu_domain)
+               return -ENOMEM;
 
        r = kvm_iommu_map_memslots(kvm);
        if (r)
                goto out_unmap;
 
-       intel_iommu_detach_dev(kvm->arch.intel_iommu_domain,
-                              pdev->bus->number, pdev->devfn);
-
-       r = intel_iommu_context_mapping(kvm->arch.intel_iommu_domain,
-                                       pdev);
-       if (r) {
-               printk(KERN_ERR "Domain context map for %s failed",
-                      pci_name(pdev));
-               goto out_unmap;
-       }
        return 0;
 
 out_unmap:
@@ -138,19 +165,26 @@ out_unmap:
 }
 
 static void kvm_iommu_put_pages(struct kvm *kvm,
-                              gfn_t base_gfn, unsigned long npages)
+                               gfn_t base_gfn, unsigned long npages)
 {
        gfn_t gfn = base_gfn;
        pfn_t pfn;
-       struct dmar_domain *domain = kvm->arch.intel_iommu_domain;
-       int i;
+       struct iommu_domain *domain = kvm->arch.iommu_domain;
+       unsigned long i;
+       u64 phys;
+
+       /* check if iommu exists and in use */
+       if (!domain)
+               return;
 
        for (i = 0; i < npages; i++) {
-               pfn = (pfn_t)intel_iommu_iova_to_pfn(domain,
-                                                    gfn_to_gpa(gfn));
+               phys = iommu_iova_to_phys(domain, gfn_to_gpa(gfn));
+               pfn = phys >> PAGE_SHIFT;
                kvm_release_pfn_clean(pfn);
                gfn++;
        }
+
+       iommu_unmap_range(domain, gfn_to_gpa(base_gfn), PAGE_SIZE * npages);
 }
 
 static int kvm_iommu_unmap_memslots(struct kvm *kvm)
@@ -168,24 +202,13 @@ static int kvm_iommu_unmap_memslots(struct kvm *kvm)
 
 int kvm_iommu_unmap_guest(struct kvm *kvm)
 {
-       struct kvm_assigned_dev_kernel *entry;
-       struct dmar_domain *domain = kvm->arch.intel_iommu_domain;
+       struct iommu_domain *domain = kvm->arch.iommu_domain;
 
        /* check if iommu exists and in use */
        if (!domain)
                return 0;
 
-       list_for_each_entry(entry, &kvm->arch.assigned_dev_head, list) {
-               printk(KERN_DEBUG "VT-d unmap: host bdf = %x:%x:%x\n",
-                      entry->host_busnr,
-                      PCI_SLOT(entry->host_devfn),
-                      PCI_FUNC(entry->host_devfn));
-
-               /* detach kvm dmar domain */
-               intel_iommu_detach_dev(domain, entry->host_busnr,
-                                      entry->host_devfn);
-       }
        kvm_iommu_unmap_memslots(kvm);
-       intel_iommu_domain_exit(domain);
+       iommu_domain_free(domain);
        return 0;
 }
index fc6127cbea1f09e98c7d5e05bcec17e733a5b165..3a5a08298aabd1a06c770c2cf4c2b657fae0af14 100644 (file)
@@ -496,6 +496,7 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm,
        match->assigned_dev_id = assigned_dev->assigned_dev_id;
        match->host_busnr = assigned_dev->busnr;
        match->host_devfn = assigned_dev->devfn;
+       match->flags = assigned_dev->flags;
        match->dev = dev;
        match->irq_source_id = -1;
        match->kvm = kvm;
@@ -503,7 +504,12 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm,
        list_add(&match->list, &kvm->arch.assigned_dev_head);
 
        if (assigned_dev->flags & KVM_DEV_ASSIGN_ENABLE_IOMMU) {
-               r = kvm_iommu_map_guest(kvm, match);
+               if (!kvm->arch.iommu_domain) {
+                       r = kvm_iommu_map_guest(kvm);
+                       if (r)
+                               goto out_list_del;
+               }
+               r = kvm_assign_device(kvm, match);
                if (r)
                        goto out_list_del;
        }
@@ -525,6 +531,35 @@ out_free:
 }
 #endif
 
+#ifdef KVM_CAP_DEVICE_DEASSIGNMENT
+static int kvm_vm_ioctl_deassign_device(struct kvm *kvm,
+               struct kvm_assigned_pci_dev *assigned_dev)
+{
+       int r = 0;
+       struct kvm_assigned_dev_kernel *match;
+
+       mutex_lock(&kvm->lock);
+
+       match = kvm_find_assigned_dev(&kvm->arch.assigned_dev_head,
+                                     assigned_dev->assigned_dev_id);
+       if (!match) {
+               printk(KERN_INFO "%s: device hasn't been assigned before, "
+                 "so cannot be deassigned\n", __func__);
+               r = -EINVAL;
+               goto out;
+       }
+
+       if (assigned_dev->flags & KVM_DEV_ASSIGN_ENABLE_IOMMU)
+               kvm_deassign_device(kvm, match);
+
+       kvm_free_assigned_device(kvm, match);
+
+out:
+       mutex_unlock(&kvm->lock);
+       return r;
+}
+#endif
+
 static inline int valid_vcpu(int n)
 {
        return likely(n >= 0 && n < KVM_MAX_VCPUS);
@@ -1857,6 +1892,19 @@ static long kvm_vm_ioctl(struct file *filp,
                        goto out;
                break;
        }
+#endif
+#ifdef KVM_CAP_DEVICE_DEASSIGNMENT
+       case KVM_DEASSIGN_PCI_DEVICE: {
+               struct kvm_assigned_pci_dev assigned_dev;
+
+               r = -EFAULT;
+               if (copy_from_user(&assigned_dev, argp, sizeof assigned_dev))
+                       goto out;
+               r = kvm_vm_ioctl_deassign_device(kvm, &assigned_dev);
+               if (r)
+                       goto out;
+               break;
+       }
 #endif
        default:
                r = kvm_arch_vm_ioctl(filp, ioctl, arg);